diff options
-rw-r--r-- | src/lib.rs | 237 |
1 files changed, 207 insertions, 30 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, KbLedFlags, KbLedState, KbLeds, Palette}; use libc::ioctl; use std::{io::Result, os::unix::io::AsRawFd}; @@ -58,8 +58,11 @@ pub mod ioctl pub const KB_101: libc::c_char = 0x0002; pub const KDGETLED: libc::c_ulong = 0x4b31; pub const KDSETLED: libc::c_ulong = 0x4b32; + pub const KDGKBLED: libc::c_ulong = 0x4B64; pub const KDSKBLED: libc::c_ulong = 0x4B65; + pub const KD_KBLED_STATE_MASK: libc::c_ulong = 0x07; + pub const KD_KBLED_DEFAULT_MASK: libc::c_ulong = 0x70; pub fn pio_cmap<F: AsRawFd>(fd: &F, pal: &Palette) -> Result<()> { @@ -113,7 +116,7 @@ pub mod ioctl }) .map(|_| ())?; - Ok(KbLedState::from(leds)) + Ok(KbLedState(KbLeds::from(leds))) } /** If ``state`` is ``None`` it is taken to mean “revert to normal” as per @@ -167,12 +170,13 @@ pub mod ioctl }) .map(|_| ())?; - Ok(KbLedFlags::from(flags)) + KbLedFlags::try_from(flags as u8) } pub fn kdskbled<F: AsRawFd>(fd: &F, flags: KbLedFlags) -> Result<()> { - let flags = libc::c_ulong::from(flags); + let default = libc::c_ulong::from(flags.default); + let flags = libc::c_ulong::from(flags.flags) | (default << 4); cvt_r(&mut || { unsafe { @@ -200,16 +204,12 @@ pub mod ioctl } } -/** Base type which the LED state and flags are aliases of. */ #[derive(Clone, Copy, Debug)] -pub struct KbLeds(u8); - -pub type KbLedFlags = KbLeds; -pub type KbLedState = KbLeds; +struct KbLeds(u8); impl KbLeds { - pub fn new(cap: bool, num: bool, scr: bool) -> Self + fn new(cap: bool, num: bool, scr: bool) -> Self { let mut state = 0u8; @@ -220,46 +220,33 @@ impl KbLeds Self(state) } - #[inline] - pub fn get(con: &Console) -> io::Result<Self> { ioctl::kdgetled(con) } - - #[inline] - pub fn set(&self, con: &Console) -> io::Result<()> - { - ioctl::kdsetled(con, Some(*self)) - } - - #[inline] - pub fn revert(con: &Console) -> io::Result<()> - { - ioctl::kdsetled(con, None) - } + fn off() -> Self { Self(0) } #[inline] - pub fn cap(&self) -> bool { (self.0 & 0x4) != 0 } + fn cap(&self) -> bool { (self.0 & 0x4) != 0 } #[inline] - pub fn num(&self) -> bool { (self.0 & 0x2) != 0 } + fn num(&self) -> bool { (self.0 & 0x2) != 0 } #[inline] - pub fn scr(&self) -> bool { (self.0 & 0x1) != 0 } + fn scr(&self) -> bool { (self.0 & 0x1) != 0 } #[inline] - pub fn set_cap(&mut self, set: bool) + fn set_cap(&mut self, set: bool) { let bit = (set as u8) << 2; self.0 = (self.0 & !bit) | bit; } #[inline] - pub fn set_num(&mut self, set: bool) + fn set_num(&mut self, set: bool) { let bit = (set as u8) << 1; self.0 = (self.0 & !bit) | bit; } #[inline] - pub fn set_scr(&mut self, set: bool) + fn set_scr(&mut self, set: bool) { let bit = set as u8; self.0 = (self.0 & !bit) | bit; @@ -340,6 +327,196 @@ mod kb_led_state } } +#[derive(Copy, Clone, Debug)] +pub struct KbLedState(KbLeds); + +impl KbLedState +{ + pub fn new(cap: bool, num: bool, scr: bool) -> Self + { + Self(KbLeds::new(cap, num, scr)) + } + + #[inline] + pub fn get(con: &Console) -> io::Result<Self> { ioctl::kdgetled(con) } + + #[inline] + pub fn set(&self, con: &Console) -> io::Result<()> + { + ioctl::kdsetled(con, Some(*self)) + } + + #[inline] + pub fn revert(con: &Console) -> io::Result<()> + { + ioctl::kdsetled(con, None) + } + + #[inline] + pub fn cap(&self) -> bool { self.0.cap() } + + #[inline] + pub fn num(&self) -> bool { self.0.num() } + + #[inline] + pub fn scr(&self) -> bool { self.0.scr() } + + #[inline] + pub fn set_cap(&mut self, set: bool) { self.0.set_cap(set) } + + #[inline] + pub fn set_num(&mut self, set: bool) { self.0.set_num(set) } + + #[inline] + pub fn set_scr(&mut self, set: bool) { self.0.set_scr(set) } +} + +impl fmt::Display for KbLedState +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result + { + write!(f, "{}", self.0) + } +} + +impl From<libc::c_char> for KbLedState +{ + fn from(leds: libc::c_char) -> Self { Self(KbLeds(leds as u8)) } +} + +impl From<KbLedState> for libc::c_ulong +{ + fn from(state: KbLedState) -> Self { state.0 .0 as libc::c_ulong } +} + +impl From<KbLedState> for u8 +{ + fn from(state: KbLedState) -> Self { state.0 .0 } +} + +impl TryFrom<u8> for KbLedState +{ + type Error = io::Error; + + fn try_from(val: u8) -> io::Result<Self> + { + Ok(Self(KbLeds::try_from(val)?)) + } +} + +#[derive(Copy, Clone, Debug)] +pub struct KbLedFlags +{ + flags: KbLeds, + default: KbLeds, +} + +impl KbLedFlags +{ + pub fn new_flags(cap: bool, num: bool, scr: bool) -> Self + { + let flags = KbLeds::new(cap, num, scr); + let default = KbLeds::off(); + Self { flags, default } + } + + pub fn new( + fcap: bool, + fnum: bool, + fscr: bool, + dcap: bool, + dnum: bool, + dscr: bool, + ) -> Self + { + let flags = KbLeds::new(fcap, fnum, fscr); + let default = KbLeds::new(dcap, dnum, dscr); + Self { flags, default } + } + + #[inline] + pub fn get(con: &Console) -> io::Result<Self> { ioctl::kdgkbled(con) } + + #[inline] + pub fn set(&self, con: &Console) -> io::Result<()> + { + ioctl::kdskbled(con, *self) + } + + #[inline] + pub fn cap(&self) -> bool { self.flags.cap() } + + #[inline] + pub fn num(&self) -> bool { self.flags.num() } + + #[inline] + pub fn scr(&self) -> bool { self.flags.scr() } + + #[inline] + pub fn default_cap(&self) -> bool { self.default.cap() } + + #[inline] + pub fn default_num(&self) -> bool { self.default.num() } + + #[inline] + pub fn default_scr(&self) -> bool { self.default.scr() } + + #[inline] + pub fn set_cap(&mut self, set: bool) { self.flags.set_cap(set) } + + #[inline] + pub fn set_num(&mut self, set: bool) { self.flags.set_num(set) } + + #[inline] + pub fn set_scr(&mut self, set: bool) { self.flags.set_scr(set) } + + #[inline] + pub fn set_default_cap(&mut self, set: bool) { self.default.set_cap(set) } + + #[inline] + pub fn set_default_num(&mut self, set: bool) { self.default.set_num(set) } + + #[inline] + pub fn set_default_scr(&mut self, set: bool) { self.default.set_scr(set) } +} + +impl From<KbLedFlags> for u8 +{ + fn from(state: KbLedFlags) -> Self + { + state.flags.0 | (state.default.0 << 0x4) + } +} + +impl TryFrom<u8> for KbLedFlags +{ + type Error = io::Error; + + /** From the manpage: + + The low order three bits (mask 0x7) get the current flag state, + and the low order bits of the next nibble (mask 0x70) get the + default flag state. + */ + fn try_from(val: u8) -> io::Result<Self> + { + let flags = val & (ioctl::KD_KBLED_STATE_MASK as u8); + let default = val & (ioctl::KD_KBLED_DEFAULT_MASK as u8) >> 4; + let flags = KbLeds::try_from(flags)?; + let default = KbLeds::try_from(default)?; + + Ok(Self { flags, default }) + } +} + +impl fmt::Display for KbLedFlags +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result + { + write!(f, "[flags: {}; default: {}]", self.flags, self.default) + } +} + #[derive(Debug)] pub struct Fd(libc::c_int); |