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/vtcol.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/vtcol.rs')
-rw-r--r-- | src/vtcol.rs | 260 |
1 files changed, 242 insertions, 18 deletions
diff --git a/src/vtcol.rs b/src/vtcol.rs index b24937b..a3ff57b 100644 --- a/src/vtcol.rs +++ b/src/vtcol.rs @@ -1,6 +1,6 @@ pub mod lib; -use vtcol::{Console, Fade, KbLedState, Palette, Scheme}; +use vtcol::{Console, Fade, KbLedFlags, KbLedState, Palette, Scheme}; use anyhow::{anyhow, Result}; use std::{io::{self, BufWriter}, @@ -127,6 +127,105 @@ impl LedJob } /* [impl LedJob] */ #[derive(Debug)] +enum FlagJob +{ + /** Get keyboard flags. */ + Get(bool), + /** Set all keyboard flags at once. */ + Set(KbLedFlags), + /** Set keyboard LED state of individual LEDs. */ + SetIndividual(Option<bool>, Option<bool>, Option<bool>), +} + +impl FlagJob +{ + /** Get the keyboard flags (modifier locks). */ + fn get(con: Option<String>, raw: bool) -> Result<()> + { + let fd = open_console(con.as_deref())?; + vrb!("console fd: {}", fd); + + let leds = KbLedFlags::get(&fd)?; + + if raw { + println!("{}", u8::from(leds)); + } else { + println!("{}", leds); + } + + Ok(()) + } + + /** Set the keyboard flags. */ + fn set(con: Option<String>, st: KbLedFlags) -> Result<()> + { + let fd = open_console(con.as_deref())?; + vrb!("console fd: {}", fd); + + st.set(&fd)?; + vrb!("applied"); + + Ok(()) + } + + /** Set / unset keyboard flags using the current as base. */ + fn set_individual( + con: Option<String>, + cap: Option<bool>, + num: Option<bool>, + scr: Option<bool>, + ) -> Result<()> + { + let fd = open_console(con.as_deref())?; + vrb!("console fd: {}", fd); + + let mut st = KbLedFlags::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(()) + } +} /*[impl FlagJob] */ + +impl Run for FlagJob +{ + fn run(self, console: Option<String>) -> Result<()> + { + match self { + Self::Get(raw) => Self::get(console, raw), + Self::Set(flags) => Self::set(console, flags), + Self::SetIndividual(c, n, s) => + Self::set_individual(console, c, n, s), + } + } +} /* [impl Run for FlagJob] */ + +#[derive(Debug)] +enum KbJob +{ + /** LED state ops. */ + Leds(LedJob), + /** Flags. */ + Flags(FlagJob), +} + +impl Run for KbJob +{ + fn run(self, console: Option<String>) -> Result<()> + { + match self { + Self::Leds(leds) => leds.run(console), + Self::Flags(flags) => flags.run(console), + } + } +} /* [impl Run for KbJob] */ + +#[derive(Debug)] enum ColorJob { /** List available schemes. */ @@ -286,7 +385,7 @@ enum Subcmd /** Console palette ops. */ Colors(ColorJob), /** Keyboard LED ops. */ - Leds(LedJob), + Kb(KbJob), } #[derive(Debug)] @@ -545,6 +644,85 @@ impl<'a> Job ]), ), ), + ) + .subcommand( + SubCommand::with_name("flags") + .about( + "operations regarding keyboard flags \ + (modifier locks)", + ) + .subcommand( + SubCommand::with_name("get") + .about("get flags") + .arg( + Arg::with_name("u8") + .short("8") + .long("u8") + .help("output raw flags as integer") + .takes_value(false), + ), + ) + .subcommand( + SubCommand::with_name("set") + .about("set flags") + .arg( + Arg::with_name("u8") + .short("8") + .long("u8") + .help( + "provide desired flags as + integer", + ) + .takes_value(true) + .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 flag") + .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 flag") + .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 flag", + ) + .takes_value(true) + .possible_values(&["on", "off"]) + .conflicts_with_all(&[ + "revert", "u8", + ]) + .value_name("STATE"), + ), + ), ), ); @@ -681,13 +859,16 @@ impl<'a> Job match subm.subcommand() { ("get", Some(subm)) => { let raw = subm.is_present("u8"); - Ok(Self(con, Subcmd::Leds(LedJob::Get(raw)))) + Ok(Self( + con, + Subcmd::Kb(KbJob::Leds(LedJob::Get(raw))), + )) }, ("set", Some(subm)) => { if subm.is_present("revert") { return Ok(Self( con, - Subcmd::Leds(LedJob::Revert), + Subcmd::Kb(KbJob::Leds(LedJob::Revert)), )); } if let Some(st) = subm.value_of("u8") { @@ -695,7 +876,50 @@ impl<'a> Job let st = KbLedState::try_from(st)?; return Ok(Self( con, - Subcmd::Leds(LedJob::Set(st)), + Subcmd::Kb(KbJob::Leds(LedJob::Set( + 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( + con, + Subcmd::Kb(KbJob::Leds( + LedJob::SetIndividual(cap, num, scr), + )), + )) + }, + (leds_junk, _) => + Err(anyhow!( + "invalid sub-sub-subcommand to kb leds: \ + [{}]; try ``{} kb leds --help``", + leds_junk, + clap::crate_name!() + )), + }, + ("flags", Some(subm)) => + match subm.subcommand() { + ("get", Some(subm)) => { + let raw = subm.is_present("u8"); + Ok(Self( + con, + Subcmd::Kb(KbJob::Flags(FlagJob::Get(raw))), + )) + }, + ("set", Some(subm)) => { + if let Some(st) = subm.value_of("u8") { + let st: u8 = st.parse()?; + let st = KbLedFlags::try_from(st)?; + return Ok(Self( + con, + Subcmd::Kb(KbJob::Flags(FlagJob::Set( + st, + ))), )); } let cap = @@ -706,32 +930,32 @@ impl<'a> Job subm.value_of("scroll").map(|a| a == "on"); Ok(Self( con, - Subcmd::Leds(LedJob::SetIndividual( - cap, num, scr, + Subcmd::Kb(KbJob::Flags( + FlagJob::SetIndividual(cap, num, scr), )), )) }, - (junk, _) => + (flags_junk, _) => Err(anyhow!( - "invalid sub-subcommand to leds: [{}]; \ - try ``{} leds --help``", - junk, + "invalid sub-sub-subcommand to kb flags: \ + [{}]; try ``{} kb flags --help``", + flags_junk, clap::crate_name!() )), }, - (leds_junk, _) => + (kb_junk, _) => Err(anyhow!( - "invalid subcommand to kb leds [{}]; try ``{} \ + "invalid sub-subcommand to kb [{}]; try ``{} kb \ --help``", - leds_junk, + kb_junk, clap::crate_name!() )), }, - (kb_junk, _) => + (junk, _) => Err(anyhow!( - "invalid subcommand to kb [{}]; try ``{} --help``", - kb_junk, + "invalid subcommand [{}]; try ``{} --help``", + junk, clap::crate_name!() )), } @@ -749,7 +973,7 @@ impl<'a> Job let Job(con, cmd) = self; match cmd { Subcmd::Colors(cols) => cols.run(con)?, - Subcmd::Leds(leds) => leds.run(con)?, + Subcmd::Kb(kb) => kb.run(con)?, } Ok(()) |