From f31af68e8cd3e50f18b4e3e901e78d186617dedc Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Thu, 20 Feb 2025 16:18:47 +0800 Subject: [PATCH 1/6] chromium_ec: Make commands it all uint16 Only code formatting difference. Signed-off-by: Daniel Schaefer --- framework_lib/src/chromium_ec/command.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/framework_lib/src/chromium_ec/command.rs b/framework_lib/src/chromium_ec/command.rs index cad2be87..e7cffeed 100644 --- a/framework_lib/src/chromium_ec/command.rs +++ b/framework_lib/src/chromium_ec/command.rs @@ -34,18 +34,18 @@ pub enum EcCommands { PwmSetDuty = 0x0025, PwmGetDuty = 0x0026, SetTabletMode = 0x0031, - GpioGet = 0x93, - I2cPassthrough = 0x9e, - ConsoleSnapshot = 0x97, - ConsoleRead = 0x98, + GpioGet = 0x0093, + I2cPassthrough = 0x009e, + ConsoleSnapshot = 0x0097, + ConsoleRead = 0x0098, /// List the features supported by the firmware - GetFeatures = 0x0D, + GetFeatures = 0x000D, /// Force reboot, causes host reboot as well - Reboot = 0xD1, + Reboot = 0x00D1, /// Control EC boot - RebootEc = 0xD2, + RebootEc = 0x00D2, /// Get information about PD controller power - UsbPdPowerInfo = 0x103, + UsbPdPowerInfo = 0x0103, // Framework specific commands /// Configure the behavior of the flash notify From a718e635b8c793ab807aae12f1a83f3811eabd17 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Thu, 20 Feb 2025 16:19:49 +0800 Subject: [PATCH 2/6] framework_lib: Add support for RgbKbdSetColor HC Signed-off-by: Daniel Schaefer --- framework_lib/src/chromium_ec/command.rs | 2 ++ framework_lib/src/chromium_ec/commands.rs | 31 +++++++++++++++++++++++ framework_lib/src/chromium_ec/mod.rs | 15 +++++++++++ 3 files changed, 48 insertions(+) diff --git a/framework_lib/src/chromium_ec/command.rs b/framework_lib/src/chromium_ec/command.rs index e7cffeed..247ff5ee 100644 --- a/framework_lib/src/chromium_ec/command.rs +++ b/framework_lib/src/chromium_ec/command.rs @@ -46,6 +46,8 @@ pub enum EcCommands { RebootEc = 0x00D2, /// Get information about PD controller power UsbPdPowerInfo = 0x0103, + RgbKbdSetColor = 0x013A, + RgbKbd = 0x013B, // Framework specific commands /// Configure the behavior of the flash notify diff --git a/framework_lib/src/chromium_ec/commands.rs b/framework_lib/src/chromium_ec/commands.rs index 01b7f71b..c4944db8 100644 --- a/framework_lib/src/chromium_ec/commands.rs +++ b/framework_lib/src/chromium_ec/commands.rs @@ -518,6 +518,37 @@ impl EcRequest for EcRequestUsbPdPowerInfo { } } +// TODO: Actually 128, but if we go above ~80 EC returns REQUEST_TRUNCATED +// At least when I use the portio driver +pub const EC_RGBKBD_MAX_KEY_COUNT: usize = 64; + +#[repr(C, packed)] +#[derive(Default, Clone, Copy, Debug)] +pub struct RgbS { + pub r: u8, + pub g: u8, + pub b: u8, +} + +#[repr(C, packed)] +pub struct EcRequestRgbKbdSetColor { + /// Specifies the starting key ID whose color is being changed + pub start_key: u8, + /// Specifies # of elements in color + pub length: u8, + /// RGB color data array of length up to MAX_KEY_COUNT + pub color: [RgbS; EC_RGBKBD_MAX_KEY_COUNT], +} + +#[repr(C, packed)] +pub struct EcResponseRgbKbdSetColor {} + +impl EcRequest for EcRequestRgbKbdSetColor { + fn command_id() -> EcCommands { + EcCommands::RgbKbdSetColor + } +} + // --- Framework Specific commands --- #[repr(C, packed)] diff --git a/framework_lib/src/chromium_ec/mod.rs b/framework_lib/src/chromium_ec/mod.rs index 2dc53206..c7734e06 100644 --- a/framework_lib/src/chromium_ec/mod.rs +++ b/framework_lib/src/chromium_ec/mod.rs @@ -921,6 +921,21 @@ impl CrosEc { let res = request.send_command(self)?; Ok(res.val == 1) } + + pub fn rgbkbd_set_color(&self, start_key: u8, colors: Vec) -> EcResult<()> { + let mut request = EcRequestRgbKbdSetColor { + start_key, + length: colors.len() as u8, + color: [(); EC_RGBKBD_MAX_KEY_COUNT].map(|()| Default::default()), + }; + + for (i, color) in colors.iter().enumerate() { + request.color[i] = *color; + } + + let _res = request.send_command(self)?; + Ok(()) + } } #[cfg_attr(not(feature = "uefi"), derive(clap::ValueEnum))] From b69985ae1f3ce667be3473da00c67ac4ac7f8f41 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Thu, 20 Feb 2025 16:20:21 +0800 Subject: [PATCH 3/6] Add --rgbkbd commandline Works like this: ``` > cargo build && sudo ./target/debug/framework_tool --rgbkbd 0 16711680 65280 255 ``` Signed-off-by: Daniel Schaefer --- framework_lib/src/commandline/clap_std.rs | 9 +++++++++ framework_lib/src/commandline/mod.rs | 17 +++++++++++++++++ framework_lib/src/commandline/uefi.rs | 13 +++++++++++++ 3 files changed, 39 insertions(+) diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs index 96b4cd6c..51837517 100644 --- a/framework_lib/src/commandline/clap_std.rs +++ b/framework_lib/src/commandline/clap_std.rs @@ -3,6 +3,7 @@ //! as well as on the UEFI shell tool. use clap::Parser; +use crate::chromium_ec::commands::EC_RGBKBD_MAX_KEY_COUNT; use crate::chromium_ec::CrosEcDriverType; use crate::commandline::{ Cli, ConsoleArg, FpBrightnessArg, HardwareDeviceType, InputDeckModeArg, RebootEcArg, @@ -149,6 +150,13 @@ struct ClapCli { #[arg(long)] kblight: Option>, + /// Set the color of to . Multiple colors for adjacent keys can be set at once. + /// [ ...] + /// Example: 0 0xFF000 0x00FF00 0x0000FF + #[clap(num_args = 2..EC_RGBKBD_MAX_KEY_COUNT)] + #[arg(long)] + rgbkbd: Vec, + /// Set tablet mode override #[clap(value_enum)] #[arg(long)] @@ -274,6 +282,7 @@ pub fn parse(args: &[String]) -> Cli { fp_led_level: args.fp_led_level, fp_brightness: args.fp_brightness, kblight: args.kblight, + rgbkbd: args.rgbkbd, tablet_mode: args.tablet_mode, console: args.console, reboot_ec: args.reboot_ec, diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index 567e9e84..01a40fe5 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -35,6 +35,7 @@ use crate::chromium_ec; use crate::chromium_ec::commands::DeckStateMode; use crate::chromium_ec::commands::FpLedBrightnessLevel; use crate::chromium_ec::commands::RebootEcCmd; +use crate::chromium_ec::commands::RgbS; use crate::chromium_ec::commands::TabletModeOverride; use crate::chromium_ec::EcResponseStatus; use crate::chromium_ec::{print_err, EcFlashType}; @@ -166,6 +167,7 @@ pub struct Cli { pub fp_led_level: Option>, pub fp_brightness: Option>, pub kblight: Option>, + pub rgbkbd: Vec, pub tablet_mode: Option, pub console: Option, pub reboot_ec: Option, @@ -753,6 +755,21 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { } else if let Some(Some(kblight)) = args.kblight { assert!(kblight <= 100); ec.set_keyboard_backlight(kblight); + } else if !args.rgbkbd.is_empty() { + if args.rgbkbd.len() < 2 { + println!( + "Must provide at least 2 arguments. Provided only: {}", + args.rgbkbd.len() + ); + } else { + let start_key = args.rgbkbd[0] as u8; + let colors = args.rgbkbd[1..].iter().map(|color| RgbS { + r: ((color & 0x00FF0000) >> 16) as u8, + g: ((color & 0x0000FF00) >> 8) as u8, + b: (color & 0x000000FF) as u8, + }); + ec.rgbkbd_set_color(start_key, colors.collect()).unwrap(); + } } else if let Some(None) = args.kblight { print!("Keyboard backlight: "); if let Some(percentage) = print_err(ec.get_keyboard_backlight()) { diff --git a/framework_lib/src/commandline/uefi.rs b/framework_lib/src/commandline/uefi.rs index e826cb25..ce350868 100644 --- a/framework_lib/src/commandline/uefi.rs +++ b/framework_lib/src/commandline/uefi.rs @@ -87,6 +87,7 @@ pub fn parse(args: &[String]) -> Cli { fp_led_level: None, fp_brightness: None, kblight: None, + rgbkbd: vec![], tablet_mode: None, console: None, reboot_ec: None, @@ -216,6 +217,18 @@ pub fn parse(args: &[String]) -> Cli { Some(None) }; found_an_option = true; + } else if arg == "--rgbkbd" { + cli.rgbkbd = if args.len() > i + 2 { + let mut colors = Vec::::new(); + for color_i in i + 1..args.len() { + // TODO: Fail parsing instead of unwrap() + colors.push(args[color_i].parse::().unwrap()); + } + colors + } else { + println!("--rgbkbd requires at least 2 arguments, the start key and an RGB value"); + vec![] + } } else if arg == "--tablet-mode" { cli.tablet_mode = if args.len() > i + 1 { let tablet_mode_arg = &args[i + 1]; From 054f1b8e74f2ceee91bf08dec3002bfdb615fc7e Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Sun, 23 Feb 2025 20:21:44 +0800 Subject: [PATCH 4/6] rgbkbd: Add sample script for --rgbkbd command Signed-off-by: Daniel Schaefer --- rgbkbd.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100755 rgbkbd.py diff --git a/rgbkbd.py b/rgbkbd.py new file mode 100755 index 00000000..9088b85e --- /dev/null +++ b/rgbkbd.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# Example invocation in fish shell +# cargo build && sudo ./target/debug/framework_tool \ +# --driver portio --has-mec false --pd-ports 1 1 --pd-addrs 64 64 \ +# (./rgbkbd.py | string split ' ') + +BRIGHTNESS = 1 +RED = int(0xFF * BRIGHTNESS) << 16 +GREEN = int(0xFF * BRIGHTNESS) << 8 +BLUE = int(0xFF * BRIGHTNESS) +CYAN = GREEN + BLUE +YELLOW = RED + GREEN +PURPLE = BLUE + RED +WHITE = RED + GREEN + BLUE + +grid_4x4 = [ + [ YELLOW, RED, RED, RED, YELLOW ], + [ RED, WHITE, GREEN, WHITE, RED ], + [ RED, GREEN, BLUE, GREEN, RED ], + [ RED, WHITE, GREEN, WHITE, RED ], + [ YELLOW, RED, RED, RED, YELLOW ], +] + +fan_8leds = [[ + # WHITE, CYAN, BLUE, GREEN, PURPLE, RED, YELLOW, WHITE + RED, RED, RED, RED, + GREEN, GREEN, GREEN, GREEN +]] + +# colors = grid_4x4 +colors = fan_8leds + +print('--rgbkbd 0', end='') +for row in colors: + for col in row: + print(' ', end='') + print(col, end='') From 9324ad44dbd1f0f26df1541d589acaffc8986b74 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Tue, 4 Mar 2025 10:11:50 +0800 Subject: [PATCH 5/6] rgbkbd: Accept hex values ``` sudo framework_tool --rgbkbd 0 0xFF0000 0x00FF00 0x0000FF ``` Signed-off-by: Daniel Schaefer --- Cargo.lock | 10 ++++++++++ framework_lib/Cargo.toml | 3 ++- framework_lib/src/commandline/clap_std.rs | 3 ++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 30842e31..10110b18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,6 +175,15 @@ dependencies = [ "clap_derive", ] +[[package]] +name = "clap-num" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "822c4000301ac390e65995c62207501e3ef800a1fc441df913a5e8e4dc374816" +dependencies = [ + "num-traits", +] + [[package]] name = "clap-verbosity-flag" version = "2.2.1" @@ -383,6 +392,7 @@ version = "0.2.1" dependencies = [ "built", "clap", + "clap-num", "clap-verbosity-flag", "env_logger", "guid_macros", diff --git a/framework_lib/Cargo.toml b/framework_lib/Cargo.toml index 81db759a..fb5096ca 100644 --- a/framework_lib/Cargo.toml +++ b/framework_lib/Cargo.toml @@ -18,7 +18,7 @@ cross_freebsd = ["unix", "freebsd_pio"] # Windows does not have the cros_ec driver nor raw port I/O access to userspace windows = ["std", "smbios", "dep:windows", "win_driver", "raw_pio", "hidapi", "rusb", "dep:wmi"] smbios = ["dep:smbios-lib"] -std = ["dep:clap", "dep:clap-verbosity-flag", "dep:env_logger", "smbios-lib?/std"] +std = ["dep:clap", "dep:clap-num", "dep:clap-verbosity-flag", "dep:env_logger", "smbios-lib?/std"] rusb = ["dep:rusb"] hidapi = ["dep:hidapi"] uefi = [ @@ -51,6 +51,7 @@ regex = { version = "1.11.1", default-features = false } redox_hwio = { git = "https://github.com/FrameworkComputer/rust-hwio", branch = "freebsd", default-features = false } libc = { version = "0.2.155", optional = true } clap = { version = "4.5", features = ["derive"], optional = true } +clap-num = { version = "1.2.0", optional = true } clap-verbosity-flag = { version = "2.2.1", optional = true } nix = { version = "0.29.0", features = ["ioctl", "user"], optional = true } num = { version = "0.4", default-features = false } diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs index 51837517..6fafdc67 100644 --- a/framework_lib/src/commandline/clap_std.rs +++ b/framework_lib/src/commandline/clap_std.rs @@ -2,6 +2,7 @@ //! This way we can use it in the regular OS commandline tool on Linux and Windows, //! as well as on the UEFI shell tool. use clap::Parser; +use clap_num::maybe_hex; use crate::chromium_ec::commands::EC_RGBKBD_MAX_KEY_COUNT; use crate::chromium_ec::CrosEcDriverType; @@ -154,7 +155,7 @@ struct ClapCli { /// [ ...] /// Example: 0 0xFF000 0x00FF00 0x0000FF #[clap(num_args = 2..EC_RGBKBD_MAX_KEY_COUNT)] - #[arg(long)] + #[arg(long, value_parser=maybe_hex::)] rgbkbd: Vec, /// Set tablet mode override From 0424c811e2dccf49e801b33df75b5954ea01b38b Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 17 Mar 2025 10:58:18 +0800 Subject: [PATCH 6/6] rgbkbd: Send unlimited number of LEDs with multiple HCs Signed-off-by: Daniel Schaefer --- framework_lib/src/chromium_ec/mod.rs | 20 +++++++++++--------- framework_lib/src/commandline/clap_std.rs | 3 +-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/framework_lib/src/chromium_ec/mod.rs b/framework_lib/src/chromium_ec/mod.rs index c7734e06..05713c34 100644 --- a/framework_lib/src/chromium_ec/mod.rs +++ b/framework_lib/src/chromium_ec/mod.rs @@ -923,17 +923,19 @@ impl CrosEc { } pub fn rgbkbd_set_color(&self, start_key: u8, colors: Vec) -> EcResult<()> { - let mut request = EcRequestRgbKbdSetColor { - start_key, - length: colors.len() as u8, - color: [(); EC_RGBKBD_MAX_KEY_COUNT].map(|()| Default::default()), - }; + for (chunk, colors) in colors.chunks(EC_RGBKBD_MAX_KEY_COUNT).enumerate() { + let mut request = EcRequestRgbKbdSetColor { + start_key: start_key + ((chunk * EC_RGBKBD_MAX_KEY_COUNT) as u8), + length: colors.len() as u8, + color: [(); EC_RGBKBD_MAX_KEY_COUNT].map(|()| Default::default()), + }; - for (i, color) in colors.iter().enumerate() { - request.color[i] = *color; - } + for (i, color) in colors.iter().enumerate() { + request.color[i] = *color; + } - let _res = request.send_command(self)?; + let _res = request.send_command(self)?; + } Ok(()) } } diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs index 6fafdc67..96249b8e 100644 --- a/framework_lib/src/commandline/clap_std.rs +++ b/framework_lib/src/commandline/clap_std.rs @@ -4,7 +4,6 @@ use clap::Parser; use clap_num::maybe_hex; -use crate::chromium_ec::commands::EC_RGBKBD_MAX_KEY_COUNT; use crate::chromium_ec::CrosEcDriverType; use crate::commandline::{ Cli, ConsoleArg, FpBrightnessArg, HardwareDeviceType, InputDeckModeArg, RebootEcArg, @@ -154,7 +153,7 @@ struct ClapCli { /// Set the color of to . Multiple colors for adjacent keys can be set at once. /// [ ...] /// Example: 0 0xFF000 0x00FF00 0x0000FF - #[clap(num_args = 2..EC_RGBKBD_MAX_KEY_COUNT)] + #[clap(num_args = 2..)] #[arg(long, value_parser=maybe_hex::)] rgbkbd: Vec,