Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,3 +382,39 @@ sudo framework_tool --rgbkbd 2 0xFF0000
> sudo framework_tool --stylus-battery
Stylus Battery Strength: 77%
```

## Remap keyboard

Note that the keyboard matrix on Framework 12 and Framework 13 are
different.
The scancodes are the same.

- Left-Ctrl 0x0014
- Left-Alt 0x0014
- Tab 0x0058

### Framework 12

```
# Remap capslock key as left-ctrl
> framework_tool --remap-key 6 15 0x0014

# Swap left-ctrl and alt
> framework_tool --remap-key 1 14 0x0011
> framework_tool --remap-key 6 13 0x0014
```

### Framework 13

```
# Remap capslock key as left-ctrl
> framework_tool --remap-key 4 4 0x0014

# Swap left-ctrl and alt
> framework_tool --remap-key 1 12 0x0011
> framework_tool --remap-key 1 3 0x0014
```

### Framework 16

It's not controlled by the EC, use https://keyboard.frame.work.
1 change: 1 addition & 0 deletions framework_lib/src/chromium_ec/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pub enum EcCommands {
/// Change charge limit
ChargeLimitControl = 0x3E03,
DisablePs2Emulation = 0x3E08,
UpdateKeyboardMatrix = 0x3E0C,
/// Get/Set Fingerprint LED brightness
FpLedLevelControl = 0x3E0E,
/// Get information about the current chassis open/close status
Expand Down
25 changes: 25 additions & 0 deletions framework_lib/src/chromium_ec/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,31 @@ impl EcRequest<EcResponseFlashNotify> for EcRequestFlashNotify {
}
}

#[repr(C, packed)]
pub struct KeyboardMatrixMap {
pub row: u8,
pub col: u8,
pub scanset: u16,
}
#[repr(C, packed)]
pub struct EcRequestUpdateKeyboardMatrix {
pub num_items: u32,
pub write: u32,
pub scan_update: [KeyboardMatrixMap; 1],
}
#[repr(C, packed)]
pub struct EcResponseUpdateKeyboardMatrix {
pub num_items: u32,
pub write: u32,
pub scan_update: [KeyboardMatrixMap; 32],
}

impl EcRequest<EcResponseUpdateKeyboardMatrix> for EcRequestUpdateKeyboardMatrix {
fn command_id() -> EcCommands {
EcCommands::UpdateKeyboardMatrix
}
}

#[repr(C, packed)]
pub struct EcRequestChassisOpenCheck {}

Expand Down
14 changes: 14 additions & 0 deletions framework_lib/src/chromium_ec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,20 @@ impl CrosEc {
.map(|res| res.sensor_count)
}

pub fn remap_caps_to_ctrl(&self) -> EcResult<()> {
self.remap_key(6, 15, 0x0014)
}

pub fn remap_key(&self, row: u8, col: u8, scanset: u16) -> EcResult<()> {
let _current_matrix = EcRequestUpdateKeyboardMatrix {
num_items: 1,
write: 1,
scan_update: [KeyboardMatrixMap { row, col, scanset }],
}
.send_command(self)?;
Ok(())
}

/// Get current status of Framework Laptop's microphone and camera privacy switches
/// [true = device enabled/connected, false = device disabled]
pub fn get_privacy_info(&self) -> EcResult<(bool, bool)> {
Expand Down
14 changes: 14 additions & 0 deletions framework_lib/src/commandline/clap_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ struct ClapCli {
#[arg(long)]
kblight: Option<Option<u8>>,

/// Set keyboard backlight percentage or get, if no value provided
#[arg(long, value_parser=maybe_hex::<u16>)]
#[clap(num_args = 3)]
remap_key: Vec<u16>,

/// Set the color of <key> to <RGB>. Multiple colors for adjacent keys can be set at once.
/// <key> <RGB> [<RGB> ...]
/// Example: 0 0xFF000 0x00FF00 0x0000FF
Expand Down Expand Up @@ -338,6 +343,14 @@ pub fn parse(args: &[String]) -> Cli {
1 => Some((args.charge_rate_limit[0], None)),
_ => None,
};
let remap_key = match args.remap_key.len() {
3 => Some((
args.remap_key[0] as u8,
args.remap_key[1] as u8,
args.remap_key[2],
)),
_ => None,
};

Cli {
verbosity: args.verbosity.log_level_filter(),
Expand Down Expand Up @@ -397,6 +410,7 @@ pub fn parse(args: &[String]) -> Cli {
fp_led_level: args.fp_led_level,
fp_brightness: args.fp_brightness,
kblight: args.kblight,
remap_key,
rgbkbd: args.rgbkbd,
ps2_enable: args.ps2_enable,
tablet_mode: args.tablet_mode,
Expand Down
17 changes: 10 additions & 7 deletions framework_lib/src/commandline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ pub struct Cli {
pub fp_led_level: Option<Option<FpBrightnessArg>>,
pub fp_brightness: Option<Option<u8>>,
pub kblight: Option<Option<u8>>,
pub remap_key: Option<(u8, u8, u16)>,
pub rgbkbd: Vec<u64>,
pub ps2_enable: Option<bool>,
pub tablet_mode: Option<TabletModeArg>,
Expand Down Expand Up @@ -809,6 +810,15 @@ 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 let Some(None) = args.kblight {
print!("Keyboard backlight: ");
if let Some(percentage) = print_err(ec.get_keyboard_backlight()) {
println!("{}%", percentage);
} else {
println!("Unable to tell");
}
} else if let Some((row, col, scanset)) = args.remap_key {
print_err(ec.remap_key(row, col, scanset));
} else if !args.rgbkbd.is_empty() {
if args.rgbkbd.len() < 2 {
println!(
Expand All @@ -826,13 +836,6 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
}
} else if let Some(enable) = args.ps2_enable {
print_err(ec.ps2_emulation_enable(enable));
} else if let Some(None) = args.kblight {
print!("Keyboard backlight: ");
if let Some(percentage) = print_err(ec.get_keyboard_backlight()) {
println!("{}%", percentage);
} else {
println!("Unable to tell");
}
} else if let Some(tablet_arg) = &args.tablet_mode {
let mode = match tablet_arg {
TabletModeArg::Auto => TabletModeOverride::Default,
Expand Down
1 change: 1 addition & 0 deletions framework_lib/src/commandline/uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pub fn parse(args: &[String]) -> Cli {
fp_led_level: None,
fp_brightness: None,
kblight: None,
remap_key: None,
rgbkbd: vec![],
ps2_enable: None,
tablet_mode: None,
Expand Down
Loading