From 2bb98ae1f837f4d09f282886b5d6d184e8726207 Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Wed, 8 Dec 2021 19:55:20 +0100 Subject: add KDGETLED subcommand to vtcol-bin Actually we add both subcommand and sub-subcommand. Example: [*] 15:52:40 phg@acheron vtcol $ vtcol leds get Caps: false, Num: true, Scroll: false --- src/lib.rs | 28 +++++++++++++++++++++++++++- src/vtcol.rs | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 681177c..2ef43e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -165,7 +165,7 @@ pub struct KbLedState(u8); impl KbLedState { - fn new(cap: bool, num: bool, scr: bool) -> Self + pub fn new(cap: bool, num: bool, scr: bool) -> Self { let mut state = 0u8; @@ -175,6 +175,32 @@ impl KbLedState Self(state) } + + #[inline] + pub fn get(con: &Console) -> io::Result { ioctl::kdgetled(con) } + + #[inline] + pub fn cap(&self) -> bool { (self.0 & 0x4) != 0 } + + #[inline] + pub fn num(&self) -> bool { (self.0 & 0x2) != 0 } + + #[inline] + pub fn scr(&self) -> bool { (self.0 & 0x1) != 0 } +} + +impl fmt::Display for KbLedState +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result + { + write!( + f, + "caps: {}, num: {}, scroll: {}", + self.cap(), + self.num(), + self.scr() + ) + } } impl From for KbLedState diff --git a/src/vtcol.rs b/src/vtcol.rs index c879641..99846be 100644 --- a/src/vtcol.rs +++ b/src/vtcol.rs @@ -1,6 +1,6 @@ pub mod lib; -use vtcol::{Console, Fade, Palette, Scheme}; +use vtcol::{Console, Fade, KbLedState, Palette, Scheme}; use anyhow::{anyhow, Result}; use std::{io::{self, BufWriter}, @@ -20,6 +20,13 @@ macro_rules! vrb { /* struct Job -- Runtime parameters. */ +#[derive(Debug)] +enum LedJob +{ + Get(bool), + Set, +} + #[derive(Debug)] enum Job { @@ -35,6 +42,8 @@ enum Job Toggle(Scheme, Scheme), /** Fade from current scheme to another. */ Fade(Option, Scheme, Duration, u8, bool), + /** Keyboard LED ops. */ + Leds(LedJob), } impl<'a> Job @@ -170,6 +179,22 @@ impl<'a> Job .takes_value(true), ), ) + .subcommand( + SubCommand::with_name("leds") + .about("operations regarding keyboard LEDs") + .subcommand( + SubCommand::with_name("get") + .about("get keyboard LED state") + .arg( + Arg::with_name("u8") + .value_name("NAME") + .short("8") + .long("u8") + .help("output raw state as integer") + .takes_value(false), + ), + ), + ) .arg( Arg::with_name("verbose") .short("v") @@ -262,6 +287,20 @@ impl<'a> Job )), } }, + ("leds", Some(subm)) => + match subm.subcommand() { + ("get", Some(subm)) => { + let raw = subm.is_present("u8"); + Ok(Self::Leds(LedJob::Get(raw))) + }, + (junk, _) => + Err(anyhow!( + "invalid sub-subcommand to leds: [{}]; try ``{} \ + leds --help``", + junk, + clap::crate_name!() + )), + }, (junk, _) => Err(anyhow!( "invalid subcommand [{}]; try ``{} --help``", @@ -328,6 +367,8 @@ impl<'a> Job Self::Toggle(one, two) => Self::toggle_scheme(one, two)?, Self::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::Set) => unimplemented!(), } Ok(()) @@ -403,6 +444,23 @@ impl<'a> Job fade.commence(&fd)?; Ok(()) } + + /** Get the keyboard led state. */ + fn get_leds(raw: bool) -> Result<()> + { + let fd = Console::current()?; + vrb!("console fd: {}", fd); + + let leds = KbLedState::get(&fd)?; + + if raw { + println!("{}", u8::from(leds)); + } else { + println!("{}", leds); + } + + Ok(()) + } } /* [impl Job] */ fn main() -> Result<()> -- cgit v1.2.3