diff --git a/README.md b/README.md index 7c41c4ca..2841b579 100644 --- a/README.md +++ b/README.md @@ -171,8 +171,8 @@ Options: --expansion-bay Show status of the expansion bay (Framework 16 only) --charge-limit [] Get or set max charge limit - --get-gpio - Get GPIO value by name + --get-gpio [] + Get GPIO value by name or all, if no name provided --fp-led-level [] Get or set fingerprint LED brightness level [possible values: high, medium, low, ultra-low, auto] --fp-brightness [] diff --git a/framework_lib/src/chromium_ec/commands.rs b/framework_lib/src/chromium_ec/commands.rs index 38cafeb6..0c8a6ef2 100644 --- a/framework_lib/src/chromium_ec/commands.rs +++ b/framework_lib/src/chromium_ec/commands.rs @@ -343,6 +343,61 @@ impl EcRequest for EcRequestGpioGetV0 { } } +pub enum GpioGetSubCommand { + ByName = 0, + Count = 1, + Info = 2, +} + +#[repr(C, packed)] +pub struct EcRequestGpioGetV1Count { + pub subcmd: u8, +} + +#[repr(C, packed)] +pub struct EcRequestGpioGetV1ByName { + pub subcmd: u8, + pub name: [u8; 32], +} + +#[repr(C, packed)] +pub struct EcRequestGpioGetV1Info { + pub subcmd: u8, + pub index: u8, +} + +#[repr(C)] +pub struct EcResponseGpioGetV1Info { + pub val: u8, + pub name: [u8; 32], + pub flags: u32, +} + +impl EcRequest for EcRequestGpioGetV1Count { + fn command_id() -> EcCommands { + EcCommands::GpioGet + } + fn command_version() -> u8 { + 1 + } +} +impl EcRequest for EcRequestGpioGetV1ByName { + fn command_id() -> EcCommands { + EcCommands::GpioGet + } + fn command_version() -> u8 { + 1 + } +} +impl EcRequest for EcRequestGpioGetV1Info { + fn command_id() -> EcCommands { + EcCommands::GpioGet + } + fn command_version() -> u8 { + 1 + } +} + #[repr(C, packed)] pub struct EcRequestReboot {} diff --git a/framework_lib/src/chromium_ec/mod.rs b/framework_lib/src/chromium_ec/mod.rs index afdaef0c..460e7985 100644 --- a/framework_lib/src/chromium_ec/mod.rs +++ b/framework_lib/src/chromium_ec/mod.rs @@ -1228,6 +1228,41 @@ impl CrosEc { Ok(res.val == 1) } + pub fn get_all_gpios(&self) -> EcResult { + let res = EcRequestGpioGetV1Count { + subcmd: GpioGetSubCommand::Count as u8, + } + .send_command(self)?; + let gpio_count = res.val; + + debug!("Found {} GPIOs", gpio_count); + + for index in 0..res.val { + let res = EcRequestGpioGetV1Info { + subcmd: GpioGetSubCommand::Info as u8, + index, + } + .send_command(self)?; + + let name = std::str::from_utf8(&res.name) + .map_err(|utf8_err| { + EcError::DeviceError(format!("Failed to decode GPIO name: {:?}", utf8_err)) + })? + .trim_end_matches(char::from(0)) + .to_string(); + + if log_enabled!(Level::Info) { + // Same output as ectool + println!("{:>32}: {:>2} 0x{:04X}", res.val, name, { res.flags }); + } else { + // Simple output, just name and level high/low + println!("{:<32} {}", name, res.val); + } + } + + Ok(gpio_count) + } + pub fn adc_read(&self, adc_channel: u8) -> EcResult { let res = EcRequestAdcRead { adc_channel }.send_command(self)?; Ok(res.adc_value) diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs index 76784a5f..14147f82 100644 --- a/framework_lib/src/commandline/clap_std.rs +++ b/framework_lib/src/commandline/clap_std.rs @@ -165,9 +165,9 @@ struct ClapCli { #[clap(num_args = ..=2)] charge_rate_limit: Vec, - /// Get GPIO value by name + /// Get GPIO value by name or all, if no name provided #[arg(long)] - get_gpio: Option, + get_gpio: Option>, /// Get or set fingerprint LED brightness level #[arg(long)] diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index b2a324f1..6676ca07 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -177,7 +177,7 @@ pub struct Cli { pub charge_limit: Option>, pub charge_current_limit: Option<(u32, Option)>, pub charge_rate_limit: Option<(f32, Option)>, - pub get_gpio: Option, + pub get_gpio: Option>, pub fp_led_level: Option>, pub fp_brightness: Option>, pub kblight: Option>, @@ -791,11 +791,15 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { } else if let Some((limit, soc)) = args.charge_rate_limit { print_err(ec.set_charge_rate_limit(limit, soc)); } else if let Some(gpio_name) = &args.get_gpio { - print!("Getting GPIO value {}: ", gpio_name); - if let Ok(value) = ec.get_gpio(gpio_name) { - println!("{:?}", value); + if let Some(gpio_name) = gpio_name { + print!("GPIO {}: ", gpio_name); + if let Ok(value) = ec.get_gpio(gpio_name) { + println!("{:?}", value); + } else { + println!("Not found"); + } } else { - println!("Not found"); + print_err(ec.get_all_gpios()); } } else if let Some(maybe_led_level) = &args.fp_led_level { print_err(handle_fp_led_level(&ec, *maybe_led_level)); @@ -1120,7 +1124,7 @@ Options: --expansion-bay Show status of the expansion bay (Framework 16 only) --charge-limit [] Get or set battery charge limit (Percentage number as arg, e.g. '100') --charge-current-limit [] Get or set battery current charge limit (Percentage number as arg, e.g. '100') - --get-gpio Get GPIO value by name + --get-gpio Get GPIO value by name or all, if no name provided --fp-led-level [] Get or set fingerprint LED brightness level [possible values: high, medium, low] --fp-brightness []Get or set fingerprint LED brightness percentage --kblight [] Set keyboard backlight percentage or get, if no value provided diff --git a/framework_lib/src/commandline/uefi.rs b/framework_lib/src/commandline/uefi.rs index 1fd9e5d8..1675c5be 100644 --- a/framework_lib/src/commandline/uefi.rs +++ b/framework_lib/src/commandline/uefi.rs @@ -329,9 +329,9 @@ pub fn parse(args: &[String]) -> Cli { found_an_option = true; } else if arg == "--get-gpio" { cli.get_gpio = if args.len() > i + 1 { - Some(args[i + 1].clone()) + Some(Some(args[i + 1].clone())) } else { - None + Some(None) }; found_an_option = true; } else if arg == "--kblight" {