ectool: Use clap derive syntax

Co-authored-by: Tim Crawford <tcrawford@system76.com>
This commit is contained in:
Ian Douglas Scott
2023-10-06 10:27:05 -06:00
committed by Jeremy Soller
parent cbad8e09be
commit 47b070418a
3 changed files with 198 additions and 142 deletions

92
tool/Cargo.lock generated
View File

@ -42,13 +42,28 @@ checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"indexmap",
"once_cell",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_derive"
version = "3.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
@ -70,6 +85,12 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
version = "0.1.19"
@ -107,6 +128,12 @@ version = "0.2.148"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
[[package]]
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "os_str_bytes"
version = "6.5.1"
@ -119,6 +146,48 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b1106fec09662ec6dd98ccac0f81cef56984d0b49f75c92d8cbad76e20c005c"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_hwio"
version = "0.1.6"
@ -131,6 +200,17 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "system76_ectool"
version = "0.3.8"
@ -157,6 +237,18 @@ version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "winapi"
version = "0.3.9"

View File

@ -16,7 +16,7 @@ name = "system76_ectool"
required-features = ["std", "hidapi", "clap"]
[dependencies]
clap = { version = "3.2", optional = true }
clap = { version = "3.2", features = ["derive"], optional = true }
libc = { version = "0.2", optional = true }
# NOTE: Upgrading to 2.x blocked on Ubuntu shipping newer hidapi
hidapi = { version = "1.5", default-features = false, features = ["linux-shared-hidraw"], optional = true }

View File

@ -2,7 +2,7 @@
#![allow(clippy::uninlined_format_args)]
use clap::{Arg, App, AppSettings, SubCommand};
use clap::{AppSettings, Parser};
use ectool::{
Access,
AccessHid,
@ -303,115 +303,96 @@ fn parse_color(s: &str) -> Result<(u8, u8, u8), String> {
}
}
#[derive(Parser)]
#[clap(rename_all = "snake_case")]
enum SubCommand {
Console,
Fan {
index: u8,
duty: Option<u8>,
},
Flash {
path: String,
},
FlashBackup {
path: String,
},
Info,
Keymap {
layer: u8,
output: u8,
input: u8,
value: Option<String>,
},
LedColor {
index: u8,
#[clap(validator = |x| parse_color(x).and(Ok(())))]
value: Option<String>,
},
LedValue {
index: u8,
value: Option<u8>,
},
LedMode {
layer: u8,
#[clap(requires = "speed")]
mode: Option<u8>,
speed: Option<u8>,
},
LedSave,
Reset,
Matrix,
Print {
#[clap(required = true)]
message: Vec<String>,
},
SetNoInput {
#[clap(parse(try_from_str))]
value: bool,
},
Security {
state: Option<String>,
},
}
#[derive(clap::ArgEnum, Clone)]
enum AccessMode {
LpcLinux,
LpcSim,
Hid,
}
#[derive(Parser)]
#[clap(name = "system76_ectool", setting = AppSettings::SubcommandRequired)]
struct Args {
#[clap(
long = "access",
arg_enum,
default_value = "lpc-linux",
)]
access: AccessMode,
#[clap(subcommand)]
subcommand: SubCommand,
}
fn main() {
let matches = App::new("system76_ectool")
.setting(AppSettings::SubcommandRequired)
.arg(Arg::with_name("access")
.long("access")
.possible_values(["lpc-linux", "lpc-sim", "hid"])
.default_value("lpc-linux")
)
.subcommand(SubCommand::with_name("console"))
.subcommand(SubCommand::with_name("fan")
.arg(Arg::with_name("index")
.value_parser(clap::value_parser!(u8))
.required(true)
)
.arg(Arg::with_name("duty")
.value_parser(clap::value_parser!(u8))
)
)
.subcommand(SubCommand::with_name("flash")
.arg(Arg::with_name("path")
.required(true)
)
)
.subcommand(SubCommand::with_name("flash_backup")
.arg(Arg::with_name("path")
.required(true)
)
)
.subcommand(SubCommand::with_name("info"))
.subcommand(SubCommand::with_name("keymap")
.arg(Arg::with_name("layer")
.value_parser(clap::value_parser!(u8))
.required(true)
)
.arg(Arg::with_name("output")
.value_parser(clap::value_parser!(u8))
.required(true)
)
.arg(Arg::with_name("input")
.value_parser(clap::value_parser!(u8))
.required(true)
)
.arg(Arg::with_name("value"))
)
.subcommand(SubCommand::with_name("led_color")
.arg(Arg::with_name("index")
.value_parser(clap::value_parser!(u8))
.required(true)
)
.arg(Arg::with_name("value")
.value_parser(parse_color)
)
)
.subcommand(SubCommand::with_name("led_value")
.arg(Arg::with_name("index")
.value_parser(clap::value_parser!(u8))
.required(true)
)
.arg(Arg::with_name("value")
.value_parser(clap::value_parser!(u8))
)
)
.subcommand(SubCommand::with_name("led_mode")
.arg(Arg::with_name("layer")
.value_parser(clap::value_parser!(u8))
.required(true)
)
.arg(Arg::with_name("mode")
.value_parser(clap::value_parser!(u8))
.requires("speed")
)
.arg(Arg::with_name("speed")
.value_parser(clap::value_parser!(u8))
)
)
.subcommand(SubCommand::with_name("led_save"))
.subcommand(SubCommand::with_name("reset"))
.subcommand(SubCommand::with_name("matrix"))
.subcommand(SubCommand::with_name("print")
.arg(Arg::with_name("message")
.required(true)
.multiple(true)
)
)
.subcommand(SubCommand::with_name("set_no_input")
.arg(Arg::with_name("value")
.possible_values(["true", "false"])
.required(true)
)
)
.subcommand(SubCommand::with_name("security")
.arg(Arg::with_name("state")
.possible_values(["lock", "unlock"])
)
)
.get_matches();
//.subcommand(Command::new("security").arg(Arg::new("state").value_parser(["lock", "unlock"])))
let args = Args::parse();
let get_ec = || -> Result<_, Error> {
unsafe {
match matches.value_of("access").unwrap() {
"lpc-linux" => {
match args.access {
AccessMode::LpcLinux => {
let access = AccessLpcLinux::new(Duration::new(1, 0))?;
Ok(Ec::new(access)?.into_dyn())
},
"lpc-sim" => {
AccessMode::LpcSim => {
let access = AccessLpcSim::new(Duration::new(1, 0))?;
Ok(Ec::new(access)?.into_dyn())
},
"hid" => {
AccessMode::Hid => {
let api = HidApi::new()?;
for info in api.device_list() {
#[allow(clippy::single_match)]
@ -433,7 +414,6 @@ fn main() {
}
Err(hidapi::HidError::HidApiErrorEmpty.into())
}
_ => unreachable!(),
}
}
};
@ -445,18 +425,16 @@ fn main() {
}
};
match matches.subcommand() {
Some(("console", _sub_m)) => match unsafe { console(&mut ec) } {
match args.subcommand {
SubCommand::Console => match unsafe { console(&mut ec) } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to read console: {:X?}", err);
process::exit(1);
},
},
Some(("fan", sub_m)) => {
let index = sub_m.value_of("index").unwrap().parse::<u8>().unwrap();
let duty_opt = sub_m.value_of("duty").map(|x| x.parse::<u8>().unwrap());
match duty_opt {
SubCommand::Fan { index, duty } => {
match duty {
Some(duty) => match unsafe { fan_set(&mut ec, index, duty) } {
Ok(()) => (),
Err(err) => {
@ -473,9 +451,8 @@ fn main() {
},
}
},
Some(("flash", sub_m)) => {
let path = sub_m.value_of("path").unwrap();
match unsafe { flash(&mut ec, path, SpiTarget::Main) } {
SubCommand::Flash { path } => {
match unsafe { flash(&mut ec, &path, SpiTarget::Main) } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to flash '{}': {:X?}", path, err);
@ -483,9 +460,8 @@ fn main() {
},
}
},
Some(("flash_backup", sub_m)) => {
let path = sub_m.value_of("path").unwrap();
match unsafe { flash(&mut ec, path, SpiTarget::Backup) } {
SubCommand::FlashBackup { path } => {
match unsafe { flash(&mut ec, &path, SpiTarget::Backup) } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to flash '{}': {:X?}", path, err);
@ -493,18 +469,15 @@ fn main() {
},
}
},
Some(("info", _sub_m)) => match unsafe { info(&mut ec) } {
SubCommand::Info => match unsafe { info(&mut ec) } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to read info: {:X?}", err);
process::exit(1);
},
},
Some(("keymap", sub_m)) => {
let layer = sub_m.value_of("layer").unwrap().parse::<u8>().unwrap();
let output = sub_m.value_of("output").unwrap().parse::<u8>().unwrap();
let input = sub_m.value_of("input").unwrap().parse::<u8>().unwrap();
match sub_m.value_of("value") {
SubCommand::Keymap { layer, output, input, value } => {
match value {
Some(value_str) => match u16::from_str_radix(value_str.trim_start_matches("0x"), 16) {
Ok(value) => match unsafe { keymap_set(&mut ec, layer, output, input, value) } {
Ok(()) => (),
@ -527,11 +500,9 @@ fn main() {
},
}
},
Some(("led_color", sub_m)) => {
let index = sub_m.value_of("index").unwrap().parse::<u8>().unwrap();
let value = sub_m.value_of("value");
SubCommand::LedColor { index, value } => {
if let Some(value) = value {
let (r, g, b) = parse_color(value).unwrap();
let (r, g, b) = parse_color(&value).unwrap();
match unsafe { ec.led_set_color(index, r, g, b) } {
Ok(()) => (),
Err(err) => {
@ -549,9 +520,7 @@ fn main() {
}
}
},
Some(("led_value", sub_m)) => {
let index = sub_m.value_of("index").unwrap().parse::<u8>().unwrap();
let value = sub_m.value_of("value").map(|x| x.parse::<u8>().unwrap());
SubCommand::LedValue { index, value } => {
if let Some(value) = value {
match unsafe { ec.led_set_value(index, value) } {
Ok(()) => (),
@ -573,10 +542,7 @@ fn main() {
}
}
},
Some(("led_mode", sub_m)) => {
let layer = sub_m.value_of("layer").unwrap().parse::<u8>().unwrap();
let mode = sub_m.value_of("mode").map(|x| x.parse::<u8>().unwrap());
let speed = sub_m.value_of("speed").map(|x| x.parse::<u8>().unwrap());
SubCommand::LedMode { layer, mode, speed } => {
if let (Some(mode), Some(speed)) = (mode, speed) {
match unsafe { ec.led_set_mode(layer, mode, speed) } {
Ok(()) => (),
@ -598,28 +564,28 @@ fn main() {
}
}
},
Some(("led_save", _sub_m)) => match unsafe { ec.led_save() } {
SubCommand::LedSave => match unsafe { ec.led_save() } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to save LED settings: {:X?}", err);
process::exit(1);
},
},
Some(("reset", _sub_m)) => match unsafe { ec.reset() } {
SubCommand::Reset => match unsafe { ec.reset() } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to reset device: {:X?}", err);
process::exit(1);
},
},
Some(("matrix", _sub_m)) => match unsafe { matrix(&mut ec) } {
SubCommand::Matrix => match unsafe { matrix(&mut ec) } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to read matrix: {:X?}", err);
process::exit(1);
},
},
Some(("print", sub_m)) => for arg in sub_m.values_of("message").unwrap() {
SubCommand::Print { message } => for arg in message {
let mut arg = arg.to_owned();
arg.push('\n');
match unsafe { print(&mut ec, arg.as_bytes()) } {
@ -630,9 +596,8 @@ fn main() {
},
}
},
Some(("set_no_input", sub_m)) => {
let no_input = sub_m.value_of("value").unwrap().parse::<bool>().unwrap();
match unsafe { ec.set_no_input(no_input) } {
SubCommand::SetNoInput { value } => {
match unsafe { ec.set_no_input(value) } {
Ok(()) => (),
Err(err) => {
eprintln!("failed to set no_input mode: {:X?}", err);
@ -640,10 +605,10 @@ fn main() {
}
}
},
Some(("security", sub_m)) => {
match sub_m.value_of("state") {
SubCommand::Security { state } => {
match state {
Some(value) => {
let state = match value {
let state = match value.as_str() {
"lock" => SecurityState::PrepareLock,
"unlock" => SecurityState::PrepareUnlock,
_ => {
@ -668,6 +633,5 @@ fn main() {
},
}
},
_ => unreachable!()
}
}