summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2021-12-12 23:17:29 +0100
committerPhilipp Gesang <phg@phi-gamma.net>2021-12-12 23:19:45 +0100
commit92f35f8e90199e4d9dfbcc545be456f4c2d7a1ce (patch)
tree99decf47747cc32983dd0a149600e7e7256866ff /src/lib.rs
parent468341393863e35bec170528ab5a99ee26acb85a (diff)
downloadvtcol-92f35f8e90199e4d9dfbcc545be456f4c2d7a1ce.tar.gz
lib: implement “kb flags”
A const-genericized version of the “kb leds” implementation. Does seem to consistently run into EINVAL no matter what flags we provide. Also incomplete as KDGKBLED / KDSKBLED pack more info into higher bits of their argument.
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs156
1 files changed, 61 insertions, 95 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 75595cd..5d777de 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -46,7 +46,7 @@ fn cvt_r<T: IsMinusOne>(f: &mut dyn FnMut() -> T) -> io::Result<T>
/** Wrappers for ``ioctl_console(2)`` functionality. */
pub mod ioctl
{
- use super::{cvt_r, KbLedFlags, KbLedState, Palette};
+ use super::{cvt_r, KbLeds, Palette};
use libc::ioctl;
use std::{io::Result, os::unix::io::AsRawFd};
@@ -96,7 +96,14 @@ pub mod ioctl
Ok(pal)
}
- pub fn kdgetled<F: AsRawFd>(fd: &F) -> Result<KbLedState>
+ #[allow(non_snake_case)]
+ pub fn kdg__led<
+ F: AsRawFd,
+ const GET: libc::c_ulong,
+ const SET: libc::c_ulong,
+ >(
+ fd: &F,
+ ) -> Result<KbLeds<GET, SET>>
{
let mut leds: libc::c_char = 0;
@@ -104,7 +111,7 @@ pub mod ioctl
unsafe {
ioctl(
fd.as_raw_fd(),
- KDGETLED,
+ GET,
std::mem::transmute::<&mut libc::c_char, *mut libc::c_void>(
&mut leds,
),
@@ -113,7 +120,7 @@ pub mod ioctl
})
.map(|_| ())?;
- Ok(KbLedState::from(leds))
+ Ok(KbLeds::from(leds))
}
/** If ``state`` is ``None`` it is taken to mean “revert to normal” as per
@@ -125,8 +132,15 @@ pub mod ioctl
order bit is set, the LEDs revert to normal: displaying the state
of the keyboard functions of caps lock, num lock, and scroll lock.
*/
- pub fn kdsetled<F: AsRawFd>(fd: &F, state: Option<KbLedState>)
- -> Result<()>
+ #[allow(non_snake_case)]
+ pub fn kds__led<
+ F: AsRawFd,
+ const GET: libc::c_ulong,
+ const SET: libc::c_ulong,
+ >(
+ fd: &F,
+ state: Option<KbLeds<GET, SET>>,
+ ) -> Result<()>
{
let leds: libc::c_ulong = if let Some(state) = state {
state.into()
@@ -138,7 +152,7 @@ pub mod ioctl
unsafe {
ioctl(
fd.as_raw_fd(),
- KDSETLED,
+ SET,
std::mem::transmute::<&libc::c_ulong, *const libc::c_void>(
&leds,
),
@@ -150,44 +164,6 @@ pub mod ioctl
Ok(())
}
- pub fn kdgkbled<F: AsRawFd>(fd: &F) -> Result<KbLedFlags>
- {
- let mut flags: libc::c_char = 0;
-
- cvt_r(&mut || {
- unsafe {
- ioctl(
- fd.as_raw_fd(),
- KDGKBLED,
- std::mem::transmute::<&mut libc::c_char, *mut libc::c_void>(
- &mut flags,
- ),
- )
- }
- })
- .map(|_| ())?;
-
- Ok(KbLedFlags::from(flags))
- }
-
- pub fn kdskbled<F: AsRawFd>(fd: &F, flags: KbLedFlags) -> Result<()>
- {
- let flags = libc::c_ulong::from(flags);
-
- cvt_r(&mut || {
- unsafe {
- ioctl(
- fd.as_raw_fd(),
- KDSKBLED,
- std::mem::transmute::<&libc::c_ulong, *const libc::c_void>(
- &flags,
- ),
- )
- }
- })
- .map(|_| ())
- }
-
pub fn kdgkbtype<F: AsRawFd>(fd: &F) -> Result<libc::c_char>
{
let mut kb: libc::c_char = 0;
@@ -202,12 +178,18 @@ pub mod ioctl
/** Base type which the LED state and flags are aliases of. */
#[derive(Clone, Copy, Debug)]
-pub struct KbLeds(u8);
+pub struct KbLeds<const GET: libc::c_ulong, const SET: libc::c_ulong>(u8);
-pub type KbLedFlags = KbLeds;
-pub type KbLedState = KbLeds;
+/* XXX why do we need this? the constants from ioctl:: don’t work */
+const KDGETLED: libc::c_ulong = 0x4b31;
+const KDSETLED: libc::c_ulong = 0x4b32;
+const KDGKBLED: libc::c_ulong = 0x4B64;
+const KDSKBLED: libc::c_ulong = 0x4B65;
-impl KbLeds
+pub type KbLedState = KbLeds<KDGETLED, KDSETLED>;
+pub type KbLedFlags = KbLeds<KDGKBLED, KDSKBLED>;
+
+impl<const GET: libc::c_ulong, const SET: libc::c_ulong> KbLeds<GET, SET>
{
pub fn new(cap: bool, num: bool, scr: bool) -> Self
{
@@ -221,18 +203,21 @@ impl KbLeds
}
#[inline]
- pub fn get(con: &Console) -> io::Result<Self> { ioctl::kdgetled(con) }
+ pub fn get(con: &Console) -> io::Result<Self>
+ {
+ ioctl::kdg__led::<Console, GET, SET>(con)
+ }
#[inline]
pub fn set(&self, con: &Console) -> io::Result<()>
{
- ioctl::kdsetled(con, Some(*self))
+ ioctl::kds__led::<Console, GET, SET>(con, Some(*self))
}
#[inline]
pub fn revert(con: &Console) -> io::Result<()>
{
- ioctl::kdsetled(con, None)
+ ioctl::kds__led::<Console, GET, SET>(con, None)
}
#[inline]
@@ -266,7 +251,8 @@ impl KbLeds
}
}
-impl fmt::Display for KbLeds
+impl<const GET: libc::c_ulong, const SET: libc::c_ulong> fmt::Display
+ for KbLeds<GET, SET>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{
@@ -280,7 +266,8 @@ impl fmt::Display for KbLeds
}
}
-impl From<libc::c_char> for KbLeds
+impl<const GET: libc::c_ulong, const SET: libc::c_ulong> From<libc::c_char>
+ for KbLeds<GET, SET>
{
fn from(leds: libc::c_char) -> Self
{
@@ -288,17 +275,20 @@ impl From<libc::c_char> for KbLeds
}
}
-impl From<KbLeds> for libc::c_ulong
+impl<const GET: libc::c_ulong, const SET: libc::c_ulong> From<KbLeds<GET, SET>>
+ for libc::c_ulong
{
- fn from(state: KbLeds) -> Self { state.0 as libc::c_ulong }
+ fn from(state: KbLeds<GET, SET>) -> Self { state.0 as libc::c_ulong }
}
-impl From<KbLeds> for u8
+impl<const GET: libc::c_ulong, const SET: libc::c_ulong> From<KbLeds<GET, SET>>
+ for u8
{
- fn from(state: KbLeds) -> Self { state.0 }
+ fn from(state: KbLeds<GET, SET>) -> Self { state.0 }
}
-impl TryFrom<u8> for KbLeds
+impl<const GET: libc::c_ulong, const SET: libc::c_ulong> TryFrom<u8>
+ for KbLeds<GET, SET>
{
type Error = io::Error;
@@ -321,49 +311,25 @@ impl TryFrom<u8> for KbLeds
#[cfg(test)]
mod kb_led_state
{
- use super::KbLeds;
+ use super::KbLedState;
#[test]
fn create()
{
- assert_eq!(0u8, KbLeds::new(false, false, false).into());
- assert_eq!(1u8, KbLeds::new(false, false, true).into());
- assert_eq!(2u8, KbLeds::new(false, true, false).into());
- assert_eq!(4u8, KbLeds::new(true, false, false).into());
- assert_eq!(6u8, KbLeds::new(true, true, false).into());
-
- assert_eq!(0u8, KbLeds::from(0u8 as libc::c_char).into());
- assert_eq!(1u8, KbLeds::from(1u8 as libc::c_char).into());
- assert_eq!(2u8, KbLeds::from(2u8 as libc::c_char).into());
- assert_eq!(4u8, KbLeds::from(4u8 as libc::c_char).into());
- assert_eq!(6u8, KbLeds::from(6u8 as libc::c_char).into());
+ assert_eq!(0u8, KbLedState::new(false, false, false).into());
+ assert_eq!(1u8, KbLedState::new(false, false, true).into());
+ assert_eq!(2u8, KbLedState::new(false, true, false).into());
+ assert_eq!(4u8, KbLedState::new(true, false, false).into());
+ assert_eq!(6u8, KbLedState::new(true, true, false).into());
+
+ assert_eq!(0u8, KbLedState::from(0u8 as libc::c_char).into());
+ assert_eq!(1u8, KbLedState::from(1u8 as libc::c_char).into());
+ assert_eq!(2u8, KbLedState::from(2u8 as libc::c_char).into());
+ assert_eq!(4u8, KbLedState::from(4u8 as libc::c_char).into());
+ assert_eq!(6u8, KbLedState::from(6u8 as libc::c_char).into());
}
}
-//#[derive(Clone, Copy, Debug)]
-//pub struct KbLedFlags(u8);
-
-//impl KbLedFlags {
-//pub fn new(cap: bool, num: bool, scr: bool) -> Self
-//{
-//let mut flags = 0u8;
-
-//flags |= (cap as u8) << 2;
-//flags |= (num as u8) << 1;
-//flags |= scr as u8;
-
-//Self(flags)
-//}
-//}
-
-//impl From<libc::c_char> for KbLedFlags
-//{
-//fn from(flags: libc::c_char) -> Self
-//{
-//Self::new(flags & 0x4 != 0, flags & 0x2 != 0, flags & 0x1 != 0)
-//}
-//}
-
#[derive(Debug)]
pub struct Fd(libc::c_int);