diff options
author | Philipp Gesang <phg@phi-gamma.net> | 2021-12-12 23:17:29 +0100 |
---|---|---|
committer | Philipp Gesang <phg@phi-gamma.net> | 2021-12-12 23:19:45 +0100 |
commit | 92f35f8e90199e4d9dfbcc545be456f4c2d7a1ce (patch) | |
tree | 99decf47747cc32983dd0a149600e7e7256866ff /src/lib.rs | |
parent | 468341393863e35bec170528ab5a99ee26acb85a (diff) | |
download | vtcol-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.rs | 156 |
1 files changed, 61 insertions, 95 deletions
@@ -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); |