From f86892c2639f0256a99d66bd34f40a572acc070c Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Sun, 12 Dec 2021 01:30:31 +0100 Subject: bin: lib: implement setting state of individual LEDs --- src/lib.rs | 26 +++++++++++++- src/vtcol.rs | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 120 insertions(+), 17 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0669b87..64cf6f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -186,7 +186,10 @@ impl KbLedState } #[inline] - pub fn revert(con: &Console) -> io::Result<()> { ioctl::kdsetled(con, None) } + pub fn revert(con: &Console) -> io::Result<()> + { + ioctl::kdsetled(con, None) + } #[inline] pub fn cap(&self) -> bool { (self.0 & 0x4) != 0 } @@ -196,6 +199,27 @@ impl KbLedState #[inline] pub fn scr(&self) -> bool { (self.0 & 0x1) != 0 } + + #[inline] + pub 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) + { + let bit = (set as u8) << 1; + self.0 = (self.0 & !bit) | bit; + } + + #[inline] + pub fn set_scr(&mut self, set: bool) + { + let bit = set as u8; + self.0 = (self.0 & !bit) | bit; + } } impl fmt::Display for KbLedState diff --git a/src/vtcol.rs b/src/vtcol.rs index 738a622..0daccb0 100644 --- a/src/vtcol.rs +++ b/src/vtcol.rs @@ -23,8 +23,12 @@ enum LedJob { /** Get keyboard LED state. */ Get(bool), - /** Set keyboard LED state; ``None`` indicates revert. */ - Set(Option), + /** Revert to normal. */ + Revert, + /** Set keyboard LED state of all leds at once. */ + Set(KbLedState), + /** Set keyboard LED state of individual LEDs. */ + SetIndividual(Option, Option, Option), } #[derive(Debug)] @@ -230,7 +234,42 @@ impl<'a> Job .long("u8") .help("provide desired state as integer") .takes_value(true) - .required_unless_one(&["revert"]) + .required_unless_one(&[ + "revert", "caps", "num", "scroll", + ]) + .conflicts_with_all(&[ + "revert", "caps", "num", "scroll", + ]) + .value_name("STATE"), + ) + .arg( + Arg::with_name("caps") + .short("c") + .long("caps") + .help("[de]activate Caps Lock LED") + .takes_value(true) + .possible_values(&["on", "off"]) + .conflicts_with_all(&["revert", "u8"]) + .value_name("STATE"), + ) + .arg( + Arg::with_name("num") + .short("n") + .long("num") + .help("[de]activate Num Lock LED") + .takes_value(true) + .possible_values(&["on", "off"]) + .conflicts_with_all(&["revert", "u8"]) + .value_name("STATE"), + ) + .arg( + Arg::with_name("scroll") + .short("s") + .long("scroll") + .help("[de]activate Scroll Lock LED") + .takes_value(true) + .possible_values(&["on", "off"]) + .conflicts_with_all(&["revert", "u8"]) .value_name("STATE"), ) .arg( @@ -239,7 +278,9 @@ impl<'a> Job .long("revert") .help("revert LED state to normal") .takes_value(false) - .conflicts_with("u8"), + .conflicts_with_all(&[ + "u8", "caps", "num", "scroll", + ]), ), ), ); @@ -358,11 +399,17 @@ impl<'a> Job }, ("set", Some(subm)) => { if subm.is_present("revert") { - return Ok(Self::Leds(LedJob::Set(None))); + return Ok(Self::Leds(LedJob::Revert)); + } + if let Some(st) = subm.value_of("u8") { + let st: u8 = st.parse()?; + let st = KbLedState::try_from(st)?; + return Ok(Self::Leds(LedJob::Set(st))); } - let st: u8 = subm.value_of("u8").unwrap().parse()?; - let st = KbLedState::try_from(st)?; - Ok(Self::Leds(LedJob::Set(Some(st)))) + let cap = subm.value_of("caps").map(|a| a == "on"); + let num = subm.value_of("num").map(|a| a == "on"); + let scr = subm.value_of("scroll").map(|a| a == "on"); + Ok(Self::Leds(LedJob::SetIndividual(cap, num, scr))) }, (junk, _) => Err(anyhow!( @@ -441,7 +488,10 @@ impl<'a> Job Self::Colors(ColorJob::Fade(from, to, ms, hz, clear)) => Self::fade(from, to, ms, hz, clear)?, Self::Leds(LedJob::Get(raw)) => Self::get_leds(raw)?, + Self::Leds(LedJob::Revert) => Self::revert_leds()?, Self::Leds(LedJob::Set(st)) => Self::set_leds(st)?, + Self::Leds(LedJob::SetIndividual(c, n, s)) => + Self::set_leds_individual(c, n, s)?, } Ok(()) @@ -536,18 +586,47 @@ impl<'a> Job } /** Set the keyboard LED state. */ - fn set_leds(st: Option) -> Result<()> + fn set_leds(st: KbLedState) -> Result<()> { let fd = Console::current()?; vrb!("console fd: {}", fd); - if let Some(st) = st { - st.set(&fd)?; - vrb!("applied"); - } else { - KbLedState::revert(&fd)?; - vrb!("reverted"); - } + st.set(&fd)?; + vrb!("applied"); + + Ok(()) + } + + /** Set the state of the given LEDs using the current state as base. */ + fn set_leds_individual( + cap: Option, + num: Option, + scr: Option, + ) -> Result<()> + { + let fd = Console::current()?; + vrb!("console fd: {}", fd); + + let mut st = KbLedState::get(&fd)?; + + cap.map(|b| st.set_cap(b)); + num.map(|b| st.set_num(b)); + scr.map(|b| st.set_scr(b)); + + st.set(&fd)?; + vrb!("applied"); + + Ok(()) + } + + /** Revert the keyboard LED state. */ + fn revert_leds() -> Result<()> + { + let fd = Console::current()?; + vrb!("console fd: {}", fd); + + KbLedState::revert(&fd)?; + vrb!("reverted"); Ok(()) } -- cgit v1.2.3