summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2021-12-22 15:25:36 +0100
committerPhilipp Gesang <phg@phi-gamma.net>2021-12-22 15:31:58 +0100
commitc7ebd8c35cfbf2de62a6ac058d98c26becb83390 (patch)
tree8e192604b98db29429df3e6af02c8281989a3c68
parent52c4bc83135f8749a33d360e2e360a3d93552826 (diff)
downloadvtcol-c7ebd8c35cfbf2de62a6ac058d98c26becb83390.tar.gz
lib: rework led flags as composite type
Split the underlying led bits handling into KbLeds and employ this to construct both KbLedState and KbLedFlags, preserving their distinctness. This also finally implements the handling of the default states from the higher order bits of KD*KBLED.
-rw-r--r--src/lib.rs237
1 files changed, 207 insertions, 30 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 01f0187..aee486d 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, 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);