From d11f7677f579f6b1bd0cf7b8a342c8d22063a707 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 30 Dec 2025 18:51:47 +0800 Subject: [PATCH 1/9] refactor(types): rewrite internal `KeyCode` Signed-off-by: Haobo Gu --- .../keymap_configuration/keyboard_macros.md | 86 +- docs/docs/main/docs/configuration/layout.md | 4 +- docs/docs/main/docs/features/use_rust_api.md | 2 +- rmk-types/src/action.rs | 71 +- rmk-types/src/keycode.rs | 1048 +++++++------ rmk-types/src/keycode_backup.rs | 1380 +++++++++++++++++ rmk/src/host/via/keycode_convert.rs | 209 ++- rmk/src/keyboard.rs | 635 ++++---- rmk/src/keyboard_macros.rs | 16 +- rmk/src/layout_macro.rs | 404 ++++- 10 files changed, 2899 insertions(+), 956 deletions(-) create mode 100644 rmk-types/src/keycode_backup.rs diff --git a/docs/docs/main/docs/configuration/keymap_configuration/keyboard_macros.md b/docs/docs/main/docs/configuration/keymap_configuration/keyboard_macros.md index c996ef960..e89691efd 100644 --- a/docs/docs/main/docs/configuration/keymap_configuration/keyboard_macros.md +++ b/docs/docs/main/docs/configuration/keymap_configuration/keyboard_macros.md @@ -8,21 +8,21 @@ This can be configured via Vial or rust. A configuration via the toml configurat The following operations, coming from Vial, can be used to form a macro sequence. They are in `rmk::config::keyboard_macros::keyboard_macro`: -### Text(KeyCode, bool) +### Text(HidKeyCode, bool) -Execute a key press from any available KeyCode. The boolean flags if the key should be pressed with the shift modifier. +Execute a key press from any available HID keycode. The boolean flags if the key should be pressed with the shift modifier. Note that other modifiers pressed outside of a sequence with `Text` are disabled. -### Tap(KeyCode) +### Tap(HidKeyCode) -Presses and releases a key. Modifiers pressed outside of a macro sequence are considered as well. If you don't need this prefer `Text(KeyCode, bool)` above, as the resulting macro is 3 times smaller in size. +Presses and releases a key. Modifiers pressed outside of a macro sequence are considered as well. If you don't need this prefer `Text(HidKeyCode, bool)` above, as the resulting macro is 3 times smaller in size. -### Press(KeyCode) +### Press(HidKeyCode) Press (and hold) a keycode. Useful for modifier keys. -### Release(KeyCode) +### Release(HidKeyCode) Release (a formerly pressed) keycode. Useful for modifier keys. @@ -56,21 +56,21 @@ There are two helper functions to define macro sequences: pub(crate) fn get_macro_sequences() -> [u8; MACRO_SPACE_SIZE] { define_macro_sequences(&[ Vec::from_slice(&[ - MacroOperation::Text(KeyCode::H, true), - MacroOperation::Text(KeyCode::E, false), - MacroOperation::Text(KeyCode::L, false), - MacroOperation::Text(KeyCode::L, false), - MacroOperation::Text(KeyCode::O, false), + MacroOperation::Text(HidKeyCode::H, true), + MacroOperation::Text(HidKeyCode::E, false), + MacroOperation::Text(HidKeyCode::L, false), + MacroOperation::Text(HidKeyCode::L, false), + MacroOperation::Text(HidKeyCode::O, false), ]) .expect("too many elements"), Vec::from_slice(&[ - MacroOperation::Press(KeyCode::LShift), - MacroOperation::Tap(KeyCode::W), - MacroOperation::Release(KeyCode::LShift), - MacroOperation::Tap(KeyCode::O), - MacroOperation::Tap(KeyCode::R), - MacroOperation::Tap(KeyCode::L), - MacroOperation::Tap(KeyCode::D), + MacroOperation::Press(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::W), + MacroOperation::Release(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::O), + MacroOperation::Tap(HidKeyCode::R), + MacroOperation::Tap(HidKeyCode::L), + MacroOperation::Tap(HidKeyCode::D), ]) .expect("too many elements"), ]) @@ -94,7 +94,7 @@ pub(crate) fn get_macro_sequences() -> [u8; MACRO_SPACE_SIZE] { (With the improvement that the `Text` macro operation is used in both cases.) -Note that you are still limited to the ascii characters defined as `KeyCode`s. For example, you can't enter a German Umlaut (`ü`) or unicode directly with a `KeyCode` binding. If you enter an illegal character it will be converted to `X`. +Note that you are still limited to the ascii characters defined as `HidKeyCode`s. For example, you can't enter a German Umlaut (`ü`) or unicode directly with a `HidKeyCode` binding. If you enter an illegal character it will be converted to `X`. Entering these special characters usually require a key combination which depends on your operating system and chosen keyboard layout (setting in the OS). For example, in MacOS with a en-US layout you can define the following sequence to enter an `ö`: @@ -102,10 +102,10 @@ Entering these special characters usually require a key combination which depend pub(crate) fn get_macro_sequences() -> [u8; MACRO_SPACE_SIZE] { define_macro_sequences(&[ Vec::from_slice(&[ - MacroOperation::Press(KeyCode::LAlt), - MacroOperation::Tap(KeyCode::U), - MacroOperation::Release(KeyCode::LAlt), - MacroOperation::Tap(KeyCode::O), + MacroOperation::Press(HidKeyCode::LAlt), + MacroOperation::Tap(HidKeyCode::U), + MacroOperation::Release(HidKeyCode::LAlt), + MacroOperation::Tap(HidKeyCode::O), ]) .expect("too many elements"), ]) @@ -118,11 +118,11 @@ pub(crate) fn get_macro_sequences() -> [u8; MACRO_SPACE_SIZE] { A macro can be triggered in two ways: -1. Using the `KeyCode::Macro0` - `KeyCode::Macro31`. -2. Using the `Action::MacroTrigger(index)`, where index can be any number. If the total number of macro sequences is less than the index passed, nothing is executed (and an error "Macro not found" is logged). Remember that the index starts at `0`. -3. Defined macro sequences are automatically bound to a sequence: The first macro sequence defined is executed when triggering `KeyCode::Macro0` and `Action::MacroTrigger(0)`. +1. Using the macro shortcuts in keymap configuration (e.g., `Macro(0)` - `Macro(31)` in toml config, or `macros!(0)` - `macros!(31)` in Rust). +2. Using the `Action::TriggerMacro(index)`, where index can be any number between 0~31. If the total number of macro sequences is less than the index passed, nothing is executed (and an error "Macro not found" is logged). Remember that the index starts at `0`. +3. Defined macro sequences are automatically bound to a sequence: The first macro sequence defined is executed when triggering `Macro(0)` and `Action::TriggerMacro(0)`. -There is no difference using either, other than that there is no `KeyCode::Macro32`. To trigger the 33th macro and above you need to use `Action::TriggerMacro(index)`. +There is no difference using either, other than that there are only 32 shortcuts available (0-31). To trigger the 33rd macro and above you need to use `Action::TriggerMacro(index)`. ### Combining @@ -139,14 +139,12 @@ For example: ```rust // Trigger macro(1) when tapping and switch to layer 1 when holding KeyAction::TapHold(Action::TriggerMacro(1), Action::LayerOn(1)) -// Or -KeyAction::TapHold(Action::Key(KeyCode::Macro0), Action::LayerOn(1)) ``` Probably you most likely will need ```rust -k!(Macro0) +macros!(0) ``` or @@ -171,14 +169,14 @@ This is the configuration for the above example, assuming `1` is the chording la CombosConfig { combos: [ - Some(Combo::new([k!(T), k!(Y)], k!(Macro0), Some(1))), + Some(Combo::new([k!(T), k!(Y)], macros!(0), Some(1))), Some(Combo::new([k!(T), k!(Y), k!(G)], KeyAction::Single(Action::TriggerMacro(1)), Some(1))), ], timeout: Duration::from_millis(50), } ``` -(`Action::TriggerMacro(1)` was used for demonstration only. Using `k!(Macro1)` is recommended to keep it brief.) +(`Action::TriggerMacro(1)` was used for demonstration only. Using `macros!(1)` is recommended to keep it brief.) Note that instead of having a second macro for all verbs (normal and `ing` form) you can define a macro which converts a word to the `ing` form: @@ -186,17 +184,17 @@ Note that instead of having a second macro for all verbs (normal and `ing` form) define_macro_sequences(&[ to_macro_sequence("type"), Vec::from_slice(&[ - MacroOperation::Press(KeyCode::Backspace), - MacroOperation::Text(KeyCode::I, false), - MacroOperation::Text(KeyCode::N, false), - MacroOperation::Text(KeyCode::G, false), + MacroOperation::Press(HidKeyCode::Backspace), + MacroOperation::Text(HidKeyCode::I, false), + MacroOperation::Text(HidKeyCode::N, false), + MacroOperation::Text(HidKeyCode::G, false), ]) .expect("too many elements"), ]) CombosConfig { combos: [ - Some(Combo::new([k!(T), k!(Y)], k!(Macro0), Some(1))), + Some(Combo::new([k!(T), k!(Y)], macros!(0), Some(1))), Some(Combo::new([k!(G)], KeyAction::Single(Action::TriggerMacro(1)), Some(1))), ], timeout: Duration::from_millis(50), @@ -222,9 +220,9 @@ pub(crate) fn get_forks() -> ForksConfig { ForksConfig { forks: Vec::from_slice(&[ Fork::new( - k!(Macro0), - k!(Macro0), - k!(Macro1), + macros!(0), + macros!(0), + macros!(1), StateBits::new_from( ModifierCombination::LSHIFT, LedIndicator::default(), @@ -254,8 +252,8 @@ Thus, implement the macro: pub(crate) fn get_macro_sequences() -> [u8; MACRO_SPACE_SIZE] { define_macro_sequences(&[ Vec::from_slice(&[ - MacroOperation::Text(KeyCode::Q, false), - MacroOperation::Text(KeyCode::U, false), + MacroOperation::Text(HidKeyCode::Q, false), + MacroOperation::Text(HidKeyCode::U, false), ]) .expect("too many elements"), ]) @@ -268,8 +266,8 @@ When you press `shift` and use `MacroOperation::Text`, like in the code above, n pub(crate) fn get_macro_sequences() -> [u8; MACRO_SPACE_SIZE] { define_macro_sequences(&[ Vec::from_slice(&[ - MacroOperation::Text(KeyCode::Q, false), - MacroOperation::Tap(KeyCode::U), + MacroOperation::Text(HidKeyCode::Q, false), + MacroOperation::Tap(HidKeyCode::U), ]) .expect("too many elements"), ]) diff --git a/docs/docs/main/docs/configuration/layout.md b/docs/docs/main/docs/configuration/layout.md index affb53677..d0c8e5d09 100644 --- a/docs/docs/main/docs/configuration/layout.md +++ b/docs/docs/main/docs/configuration/layout.md @@ -98,9 +98,9 @@ In each `layer.keys`, the keys are bound to various key actions. Due to the limi The `layer.keys` string should follow several rules: -1. For a simple keycode (i.e., keys in RMK's [`KeyCode`](https://docs.rs/rmk/latest/rmk/keycode/enum.KeyCode.html) enum), just fill in its name. +1. For a simple keycode (i.e., keys in RMK's [`HidKeyCode`](https://docs.rs/rmk/latest/rmk/keycode/enum.HidKeyCode.html) enum), just fill in its name. - For example, if you set a keycode `Backspace`, it will be turned to `KeyCode::Backspace`. So you have to ensure that the keycode string is valid, or RMK wouldn't compile! However, to make things easier a number of alternative key names (see alias column in [KeyCode table](./keymap_configuration/keycodes)) were added and also case-insensitive search is used to find the valid [KeyCode](https://docs.rs/rmk/latest/rmk/keycode/enum.KeyCode.html). + For example, if you set a keycode `Backspace`, it will be turned to the corresponding HID keycode. So you have to ensure that the keycode string is valid, or RMK wouldn't compile! However, to make things easier a number of alternative key names (see alias column in [KeyCode table](./keymap_configuration/keycodes)) were added and also case-insensitive search is used to find the valid keycode. For simple keycodes with modifiers active, you can use `WM(key, modifier)` to create a keypress with modifier action. Modifiers can be chained together like `LShift | RGui` to have multiple modifiers active. diff --git a/docs/docs/main/docs/features/use_rust_api.md b/docs/docs/main/docs/features/use_rust_api.md index 29867dedb..e54b226ac 100644 --- a/docs/docs/main/docs/features/use_rust_api.md +++ b/docs/docs/main/docs/features/use_rust_api.md @@ -38,7 +38,7 @@ After adding the layout of your keyboard, the default keymap should also be upda RMK provides a bunch of useful [macros](https://docs.rs/rmk/latest/rmk/#macros) to help you define your keymap. Check out the [keymap configuration](../configuration/keymap_configuration) chapter for more details. You can also check the `src/keymap.rs` files in the examples for reference. -Some `KeyAction`s are not supported by the macros; plain `KeyAction`s also work, for example: `KeyAction::TapHold(Action::Key(KeyCode::Kc1), Action::Key(KeyCode::Kc2))` +Some `KeyAction`s are not supported by the macros; plain `KeyAction`s also work, for example: `KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::Kc1)), Action::Key(KeyCode::Hid(HidKeyCode::Kc2)))` ### Define your matrix diff --git a/rmk-types/src/action.rs b/rmk-types/src/action.rs index ae10abfde..ff96f1e12 100644 --- a/rmk-types/src/action.rs +++ b/rmk-types/src/action.rs @@ -9,7 +9,7 @@ //! - [`KeyAction`] - Complex behaviors that keyboards should behave //! - [`EncoderAction`] - Rotary encoder actions -use crate::keycode::KeyCode; +use crate::keycode::{KeyCode, SpecialKey}; use crate::modifier::ModifierCombination; /// EncoderAction is the action at a encoder position, stored in encoder_map. @@ -313,11 +313,6 @@ pub enum Action { /// Activate a layer and deactivate all other layers(except default layer) LayerToggleOnly(u8), /// Triggers the Macro at the 'index'. - /// this is an alternative trigger to - /// Macro keycodes (0x500 ~ 0x5FF; KeyCode::Macro0 ~ KeyCode::Macro31 - /// e.g. `Action::TriggerMacro(6)`` will trigger the same Macro as `Action::Key(KeyCode::Macro6)` - /// the main purpose for this enum variant is to easily extend to more than 32 macros (to 256) - /// without introducing new Keycodes. TriggerMacro(u8), /// Oneshot layer, keep the layer active until the next key is triggered. OneShotLayer(u8), @@ -325,6 +320,70 @@ pub enum Action { OneShotModifier(ModifierCombination), /// Oneshot key, keep the key active until the next key is triggered. OneShotKey(KeyCode), + /// Actions for controlling lights + Light(LightAction), + /// Actions for controlling the keyboard + Keyboard(KeyboardAction), + /// Special Keys + Special(SpecialKey), + /// User Keys + User(u8), +} + +/// Actions for controlling the keyboard, for example, enable/disable a particular function +#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(postcard::experimental::max_size::MaxSize)] +pub enum KeyboardAction { + Bootloader, + Reboot, + DebugToggle, + ClearEeprom, + OutputAuto, + OutputUsb, + OutputBluetooth, + ComboOn, + ComboOff, + ComboToggle, + CapsWordToggle, + TriLayerLower, + TriLayerUpper, +} + +/// Actions for controlling lights +#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(postcard::experimental::max_size::MaxSize)] +pub enum LightAction { + BacklightOn, + BacklightOff, + BacklightToggle, + BacklightDown, + BacklightUp, + BacklightStep, + BacklightToggleBreathing, + RgbTog, + RgbModeForward, + RgbModeReverse, + RgbHui, + RgbHud, + RgbSai, + RgbSad, + RgbVai, + RgbVad, + RgbSpi, + RgbSpd, + RgbModePlain, + RgbModeBreathe, + RgbModeRainbow, + RgbModeSwirl, + RgbModeSnake, + RgbModeKnight, + RgbModeXmas, + RgbModeGradient, + // Not in vial + RgbModeRgbtest, + RgbModeTwinkle, } #[cfg(test)] diff --git a/rmk-types/src/keycode.rs b/rmk-types/src/keycode.rs index b50dbb6b9..c92ce72d1 100644 --- a/rmk-types/src/keycode.rs +++ b/rmk-types/src/keycode.rs @@ -1,18 +1,13 @@ -//! Complete keycode definitions. -//! -//! This module provides keycode definitions following the USB HID -//! specification, extended with additional codes use serde::{Deserialize, Serialize}; -use strum::FromRepr; use crate::modifier::ModifierCombination; -/// KeyCode is the internal representation of all keycodes, keyboard operations, etc. -/// Use flat representation of keycodes. -#[repr(u16)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, FromRepr)] +// All key codes defined in HID spec +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum KeyCode { + +pub enum HidKeyCode { /// Reserved, no-key. No = 0x0000, /// Keyboard roll over error, too many keys are pressed simultaneously, not a physical key. @@ -377,230 +372,49 @@ pub enum KeyCode { RAlt = 0x00E6, /// Right GUI RGui = 0x00E7, - // Macro keycodes, use 0x500 ~ 0x5FF - Macro0 = 0x500, - Macro1 = 0x501, - Macro2 = 0x502, - Macro3 = 0x503, - Macro4 = 0x504, - Macro5 = 0x505, - Macro6 = 0x506, - Macro7 = 0x507, - Macro8 = 0x508, - Macro9 = 0x509, - Macro10 = 0x50A, - Macro11 = 0x50B, - Macro12 = 0x50C, - Macro13 = 0x50D, - Macro14 = 0x50E, - Macro15 = 0x50F, - Macro16 = 0x510, - Macro17 = 0x511, - Macro18 = 0x512, - Macro19 = 0x513, - Macro20 = 0x514, - Macro21 = 0x515, - Macro22 = 0x516, - Macro23 = 0x517, - Macro24 = 0x518, - Macro25 = 0x519, - Macro26 = 0x51A, - Macro27 = 0x51B, - Macro28 = 0x51C, - Macro29 = 0x51D, - Macro30 = 0x51E, - Macro31 = 0x51F, - // Backlight and RGB keycodes, uses 0x600 ~ 0x6FF - BacklightOn = 0x600, - BacklightOff = 0x601, - BacklightToggle = 0x602, - BacklightDown = 0x603, - BacklightUp = 0x604, - BacklightStep = 0x605, - BacklightToggleBreathing = 0x606, - RgbTog = 0x620, - RgbModeForward = 0x621, - RgbModeReverse = 0x622, - RgbHui = 0x623, - RgbHud = 0x624, - RgbSai = 0x625, - RgbSad = 0x626, - RgbVai = 0x627, - RgbVad = 0x628, - RgbSpi = 0x629, - RgbSpd = 0x62A, - RgbModePlain = 0x62B, - RgbModeBreathe = 0x62C, - RgbModeRainbow = 0x62D, - RgbModeSwirl = 0x62E, - RgbModeSnake = 0x62F, - RgbModeKnight = 0x630, - RgbModeXmas = 0x631, - RgbModeGradient = 0x632, - // Not in vial - RgbModeRgbtest = 0x633, - RgbModeTwinkle = 0x634, - // Internal functional keycodes, use 0x700 ~ 0x7FF - Bootloader = 0x700, - Reboot = 0x701, - DebugToggle = 0x702, - ClearEeprom = 0x703, - GraveEscape = 0x716, - OutputAuto = 0x720, - OutputUsb = 0x721, - OutputBluetooth = 0x722, - ComboOn = 0x750, - ComboOff = 0x751, - ComboToggle = 0x752, - CapsWordToggle = 0x773, - TriLayerLower = 0x777, - TriLayerUpper = 0x778, - RepeatKey = 0x779, - AltRepeatKey = 0x77A, - // User keycodes, use 0x840 ~ 0x85F - User0 = 0x840, - User1 = 0x841, - User2 = 0x842, - User3 = 0x843, - User4 = 0x844, - User5 = 0x845, - User6 = 0x846, - User7 = 0x847, - User8 = 0x848, - User9 = 0x849, - User10 = 0x84A, - User11 = 0x84B, - User12 = 0x84C, - User13 = 0x84D, - User14 = 0x84E, - User15 = 0x84F, - User16 = 0x850, - User17 = 0x851, - User18 = 0x852, - User19 = 0x853, - User20 = 0x854, - User21 = 0x855, - User22 = 0x856, - User23 = 0x857, - User24 = 0x858, - User25 = 0x859, - User26 = 0x85A, - User27 = 0x85B, - User28 = 0x85C, - User29 = 0x85D, - User30 = 0x85E, - User31 = 0x85F, -} - -impl ::postcard::experimental::max_size::MaxSize for KeyCode { - const POSTCARD_MAX_SIZE: usize = 3usize; } -impl KeyCode { +impl HidKeyCode { /// Returns `true` if the keycode is a simple keycode defined in HID spec pub fn is_simple_key(self) -> bool { - KeyCode::No <= self && self <= KeyCode::MouseAccel2 + HidKeyCode::No <= self && self <= HidKeyCode::MouseAccel2 } /// Returns `true` if the keycode is a modifier keycode pub fn is_modifier(self) -> bool { - KeyCode::LCtrl <= self && self <= KeyCode::RGui - } - - /// Returns `true` if the keycode is basic keycode - /// The basic keycode = simple key + modifier - pub fn is_basic(self) -> bool { - KeyCode::No <= self && self <= KeyCode::RGui + HidKeyCode::LCtrl <= self && self <= HidKeyCode::RGui } - /// Returns `true` if the keycode is a letter - pub fn is_letter(self) -> bool { - KeyCode::A <= self && self <= KeyCode::Z + /// Returns `true` if the keycode is a mouse keycode + pub fn is_mouse_key(self) -> bool { + HidKeyCode::MouseUp <= self && self <= HidKeyCode::MouseAccel2 } /// Returns the byte with the bit corresponding to the USB HID /// modifier bitfield set. pub fn to_hid_modifiers(self) -> ModifierCombination { match self { - KeyCode::LCtrl => ModifierCombination::new().with_left_ctrl(true), - KeyCode::LShift => ModifierCombination::new().with_left_shift(true), - KeyCode::LAlt => ModifierCombination::new().with_left_alt(true), - KeyCode::LGui => ModifierCombination::new().with_left_gui(true), - KeyCode::RCtrl => ModifierCombination::new().with_right_ctrl(true), - KeyCode::RShift => ModifierCombination::new().with_right_shift(true), - KeyCode::RAlt => ModifierCombination::new().with_right_alt(true), - KeyCode::RGui => ModifierCombination::new().with_right_gui(true), + HidKeyCode::LCtrl => ModifierCombination::LCTRL, + HidKeyCode::LShift => ModifierCombination::LSHIFT, + HidKeyCode::LAlt => ModifierCombination::LALT, + HidKeyCode::LGui => ModifierCombination::LGUI, + HidKeyCode::RCtrl => ModifierCombination::RCTRL, + HidKeyCode::RShift => ModifierCombination::RSHIFT, + HidKeyCode::RAlt => ModifierCombination::RALT, + HidKeyCode::RGui => ModifierCombination::RGUI, _ => ModifierCombination::new(), } } - /// Returns `true` if the keycode is a system keycode - pub fn is_system(self) -> bool { - KeyCode::SystemPower <= self && self <= KeyCode::SystemWake - } - - /// Returns `true` if the keycode is a keycode in consumer page - pub fn is_consumer(self) -> bool { - KeyCode::AudioMute <= self && self <= KeyCode::Launchpad - } - - /// Returns `true` if the keycode is a mouse keycode - pub fn is_mouse_key(self) -> bool { - KeyCode::MouseUp <= self && self <= KeyCode::MouseAccel2 - } - - /// Returns `true` if the keycode is a combo keycode - pub fn is_combo(self) -> bool { - KeyCode::ComboOn <= self && self <= KeyCode::ComboToggle - } - - /// Returns `true` if the keycode is a macro keycode - pub fn is_macro(self) -> bool { - KeyCode::Macro0 <= self && self <= KeyCode::Macro31 - } - - /// Returns `true` if the keycode is a backlight keycode - pub fn is_backlight(self) -> bool { - KeyCode::BacklightOn <= self && self <= KeyCode::BacklightToggleBreathing - } - - /// Returns `true` if the keycode is a rgb keycode - pub fn is_rgb(self) -> bool { - KeyCode::RgbTog <= self && self <= KeyCode::RgbModeTwinkle - } - - /// Returns `true` if the keycode is defined by rmk to achieve special functionalities, such as reboot keyboard, goto bootloader, etc. - pub fn is_rmk(self) -> bool { - KeyCode::Bootloader <= self && self <= KeyCode::AltRepeatKey - } - - /// Returns `true` if the keycode is a boot keycode - pub fn is_boot(self) -> bool { - KeyCode::Bootloader <= self && self <= KeyCode::Reboot - } - /// Returns `true` if the keycode is a user keycode - pub fn is_user(self) -> bool { - KeyCode::User0 <= self && self <= KeyCode::User31 - } - - /// Convert a keycode to macro number - pub fn as_macro_index(self) -> Option { - if self.is_macro() { - Some((self as u16 & 0x1F) as u8) - } else { - None - } - } - /// Does current keycode continues Caps Word? pub fn is_caps_word_continue_key(self) -> bool { - if self >= KeyCode::A && self <= KeyCode::Z { + if self >= HidKeyCode::A && self <= HidKeyCode::Z { return true; } - if self >= KeyCode::Kc1 && self <= KeyCode::Kc0 { + if self >= HidKeyCode::Kc1 && self <= HidKeyCode::Kc0 { return true; } - if self == KeyCode::Minus || self == KeyCode::Backspace || self == KeyCode::Delete { + if self == HidKeyCode::Minus || self == HidKeyCode::Backspace || self == HidKeyCode::Delete { return true; } false @@ -608,289 +422,319 @@ impl KeyCode { /// Does current keycode is to be shifted by Caps Word? pub fn is_caps_word_shifted_key(self) -> bool { - if self >= KeyCode::A && self <= KeyCode::Z { + if self >= HidKeyCode::A && self <= HidKeyCode::Z { return true; } - if self == KeyCode::Minus { + if self == HidKeyCode::Minus { return true; } false } - /// Convert a keycode to usb hid media key - pub fn as_consumer_control_usage_id(self) -> ConsumerKey { + /// Some hid keycodes are processed as consumer keys, for compatibility + pub fn process_as_consumer(&self) -> Option { match self { - KeyCode::AudioMute => ConsumerKey::Mute, - KeyCode::AudioVolUp => ConsumerKey::VolumeIncrement, - KeyCode::AudioVolDown => ConsumerKey::VolumeDecrement, - KeyCode::MediaNextTrack => ConsumerKey::NextTrack, - KeyCode::MediaPrevTrack => ConsumerKey::PrevTrack, - KeyCode::MediaStop => ConsumerKey::StopPlay, - KeyCode::MediaPlayPause => ConsumerKey::PlayPause, - KeyCode::MediaSelect => ConsumerKey::Record, - KeyCode::MediaEject => ConsumerKey::Eject, - KeyCode::Mail => ConsumerKey::Email, - KeyCode::Calculator => ConsumerKey::Calculator, - KeyCode::MyComputer => ConsumerKey::LocalBrowser, - KeyCode::WwwSearch => ConsumerKey::Search, - KeyCode::WwwHome => ConsumerKey::Home, - KeyCode::WwwBack => ConsumerKey::Back, - KeyCode::WwwForward => ConsumerKey::Forward, - KeyCode::WwwStop => ConsumerKey::Stop, - KeyCode::WwwRefresh => ConsumerKey::Refresh, - KeyCode::WwwFavorites => ConsumerKey::Bookmarks, - KeyCode::MediaFastForward => ConsumerKey::FastForward, - KeyCode::MediaRewind => ConsumerKey::Rewind, - KeyCode::BrightnessUp => ConsumerKey::BrightnessUp, - KeyCode::BrightnessDown => ConsumerKey::BrightnessDown, - KeyCode::ControlPanel => ConsumerKey::ControlPanel, - KeyCode::Assistant => ConsumerKey::Assistant, - KeyCode::MissionControl => ConsumerKey::DesktopShowAllWindows, - KeyCode::Launchpad => ConsumerKey::AcSoftKeyLeft, - _ => ConsumerKey::No, + HidKeyCode::AudioMute => Some(ConsumerKey::Mute), + HidKeyCode::AudioVolUp => Some(ConsumerKey::VolumeIncrement), + HidKeyCode::AudioVolDown => Some(ConsumerKey::VolumeDecrement), + HidKeyCode::MediaNextTrack => Some(ConsumerKey::NextTrack), + HidKeyCode::MediaPrevTrack => Some(ConsumerKey::PrevTrack), + HidKeyCode::MediaStop => Some(ConsumerKey::StopPlay), + HidKeyCode::MediaPlayPause => Some(ConsumerKey::PlayPause), + HidKeyCode::MediaSelect => Some(ConsumerKey::Record), + HidKeyCode::MediaEject => Some(ConsumerKey::Eject), + HidKeyCode::Mail => Some(ConsumerKey::Email), + HidKeyCode::Calculator => Some(ConsumerKey::Calculator), + HidKeyCode::MyComputer => Some(ConsumerKey::LocalBrowser), + HidKeyCode::WwwSearch => Some(ConsumerKey::Search), + HidKeyCode::WwwHome => Some(ConsumerKey::Home), + HidKeyCode::WwwBack => Some(ConsumerKey::Back), + HidKeyCode::WwwForward => Some(ConsumerKey::Forward), + HidKeyCode::WwwStop => Some(ConsumerKey::Stop), + HidKeyCode::WwwRefresh => Some(ConsumerKey::Refresh), + HidKeyCode::WwwFavorites => Some(ConsumerKey::Bookmarks), + HidKeyCode::MediaFastForward => Some(ConsumerKey::FastForward), + HidKeyCode::MediaRewind => Some(ConsumerKey::Rewind), + HidKeyCode::BrightnessUp => Some(ConsumerKey::BrightnessUp), + HidKeyCode::BrightnessDown => Some(ConsumerKey::BrightnessDown), + HidKeyCode::ControlPanel => Some(ConsumerKey::ControlPanel), + HidKeyCode::Assistant => Some(ConsumerKey::Assistant), + HidKeyCode::MissionControl => Some(ConsumerKey::DesktopShowAllWindows), + HidKeyCode::Launchpad => Some(ConsumerKey::AcSoftKeyLeft), + _ => None, } } - /// Convert a keycode to usb hid media key - pub fn as_system_control_usage_id(self) -> Option { + /// Some hid keycodes are processed as system control keys, for compatibility + pub fn process_as_system_control(&self) -> Option { match self { - KeyCode::SystemPower => Some(SystemControlKey::PowerDown), - KeyCode::SystemSleep => Some(SystemControlKey::Sleep), - KeyCode::SystemWake => Some(SystemControlKey::WakeUp), + HidKeyCode::SystemPower => Some(SystemControlKey::PowerDown), + HidKeyCode::SystemSleep => Some(SystemControlKey::Sleep), + HidKeyCode::SystemWake => Some(SystemControlKey::WakeUp), _ => None, } } } -/// Convert a ascii chat to keycode -/// bool, if the keycode should be shifted -/// assumes en-us keyboard mapping -pub fn from_ascii(ascii: u8) -> (KeyCode, bool) { - match ascii { - b'0' => (KeyCode::Kc0, false), - b'1' => (KeyCode::Kc1, false), - b'2' => (KeyCode::Kc2, false), - b'3' => (KeyCode::Kc3, false), - b'4' => (KeyCode::Kc4, false), - b'5' => (KeyCode::Kc5, false), - b'6' => (KeyCode::Kc6, false), - b'7' => (KeyCode::Kc7, false), - b'8' => (KeyCode::Kc8, false), - b'9' => (KeyCode::Kc9, false), - b'a' => (KeyCode::A, false), - b'b' => (KeyCode::B, false), - b'c' => (KeyCode::C, false), - b'd' => (KeyCode::D, false), - b'e' => (KeyCode::E, false), - b'f' => (KeyCode::F, false), - b'g' => (KeyCode::G, false), - b'h' => (KeyCode::H, false), - b'i' => (KeyCode::I, false), - b'j' => (KeyCode::J, false), - b'k' => (KeyCode::K, false), - b'l' => (KeyCode::L, false), - b'm' => (KeyCode::M, false), - b'n' => (KeyCode::N, false), - b'o' => (KeyCode::O, false), - b'p' => (KeyCode::P, false), - b'q' => (KeyCode::Q, false), - b'r' => (KeyCode::R, false), - b's' => (KeyCode::S, false), - b't' => (KeyCode::T, false), - b'u' => (KeyCode::U, false), - b'v' => (KeyCode::V, false), - b'w' => (KeyCode::W, false), - b'x' => (KeyCode::X, false), - b'y' => (KeyCode::Y, false), - b'z' => (KeyCode::Z, false), - b'A' => (KeyCode::A, true), - b'B' => (KeyCode::B, true), - b'C' => (KeyCode::C, true), - b'D' => (KeyCode::D, true), - b'E' => (KeyCode::E, true), - b'F' => (KeyCode::F, true), - b'G' => (KeyCode::G, true), - b'H' => (KeyCode::H, true), - b'I' => (KeyCode::I, true), - b'J' => (KeyCode::J, true), - b'K' => (KeyCode::K, true), - b'L' => (KeyCode::L, true), - b'M' => (KeyCode::M, true), - b'N' => (KeyCode::N, true), - b'O' => (KeyCode::O, true), - b'P' => (KeyCode::P, true), - b'Q' => (KeyCode::Q, true), - b'R' => (KeyCode::R, true), - b'S' => (KeyCode::S, true), - b'T' => (KeyCode::T, true), - b'U' => (KeyCode::U, true), - b'V' => (KeyCode::V, true), - b'W' => (KeyCode::W, true), - b'X' => (KeyCode::X, true), - b'Y' => (KeyCode::Y, true), - b'Z' => (KeyCode::Z, true), - b'!' => (KeyCode::Kc1, true), - b'@' => (KeyCode::Kc2, true), - b'#' => (KeyCode::Kc3, true), - b'$' => (KeyCode::Kc4, true), - b'%' => (KeyCode::Kc5, true), - b'^' => (KeyCode::Kc6, true), - b'&' => (KeyCode::Kc7, true), - b'*' => (KeyCode::Kc8, true), - b'(' => (KeyCode::Kc9, true), - b')' => (KeyCode::Kc0, true), - b'-' => (KeyCode::Minus, false), - b'_' => (KeyCode::Minus, true), - b'=' => (KeyCode::Equal, false), - b'+' => (KeyCode::Equal, true), - b'[' => (KeyCode::LeftBracket, false), - b']' => (KeyCode::RightBracket, false), - b'{' => (KeyCode::LeftBracket, true), - b'}' => (KeyCode::RightBracket, true), - b';' => (KeyCode::Semicolon, false), - b':' => (KeyCode::Semicolon, true), - b'\'' => (KeyCode::Quote, false), - b'"' => (KeyCode::Quote, true), - b'`' => (KeyCode::Grave, false), - b'~' => (KeyCode::Grave, true), - b'\\' => (KeyCode::Backslash, false), - b'|' => (KeyCode::Backslash, true), - b',' => (KeyCode::Comma, false), - b'<' => (KeyCode::Comma, true), - b'.' => (KeyCode::Dot, false), - b'>' => (KeyCode::Dot, true), - b'/' => (KeyCode::Slash, false), - b'?' => (KeyCode::Slash, true), - b' ' => (KeyCode::Space, false), - b'\n' => (KeyCode::Enter, false), - b'\t' => (KeyCode::Tab, false), - b'\x08' => (KeyCode::Backspace, false), - b'\x1B' => (KeyCode::Escape, false), - b'\x7F' => (KeyCode::Delete, false), - _ => (KeyCode::No, false), - } +impl ::postcard::experimental::max_size::MaxSize for HidKeyCode { + const POSTCARD_MAX_SIZE: usize = 1usize; } -/// Convert a ascii chat to keycode -/// assumes en-us keyboard mapping -pub fn to_ascii(keycode: KeyCode, shifted: bool) -> u8 { - match (keycode, shifted) { - (KeyCode::Kc0, false) => b'0', - (KeyCode::Kc1, false) => b'1', - (KeyCode::Kc2, false) => b'2', - (KeyCode::Kc3, false) => b'3', - (KeyCode::Kc4, false) => b'4', - (KeyCode::Kc5, false) => b'5', - (KeyCode::Kc6, false) => b'6', - (KeyCode::Kc7, false) => b'7', - (KeyCode::Kc8, false) => b'8', - (KeyCode::Kc9, false) => b'9', - (KeyCode::A, false) => b'a', - (KeyCode::B, false) => b'b', - (KeyCode::C, false) => b'c', - (KeyCode::D, false) => b'd', - (KeyCode::E, false) => b'e', - (KeyCode::F, false) => b'f', - (KeyCode::G, false) => b'g', - (KeyCode::H, false) => b'h', - (KeyCode::I, false) => b'i', - (KeyCode::J, false) => b'j', - (KeyCode::K, false) => b'k', - (KeyCode::L, false) => b'l', - (KeyCode::M, false) => b'm', - (KeyCode::N, false) => b'n', - (KeyCode::O, false) => b'o', - (KeyCode::P, false) => b'p', - (KeyCode::Q, false) => b'q', - (KeyCode::R, false) => b'r', - (KeyCode::S, false) => b's', - (KeyCode::T, false) => b't', - (KeyCode::U, false) => b'u', - (KeyCode::V, false) => b'v', - (KeyCode::W, false) => b'w', - (KeyCode::X, false) => b'x', - (KeyCode::Y, false) => b'y', - (KeyCode::Z, false) => b'z', - (KeyCode::A, true) => b'A', - (KeyCode::B, true) => b'B', - (KeyCode::C, true) => b'C', - (KeyCode::D, true) => b'D', - (KeyCode::E, true) => b'E', - (KeyCode::F, true) => b'F', - (KeyCode::G, true) => b'G', - (KeyCode::H, true) => b'H', - (KeyCode::I, true) => b'I', - (KeyCode::J, true) => b'J', - (KeyCode::K, true) => b'K', - (KeyCode::L, true) => b'L', - (KeyCode::M, true) => b'M', - (KeyCode::N, true) => b'N', - (KeyCode::O, true) => b'O', - (KeyCode::P, true) => b'P', - (KeyCode::Q, true) => b'Q', - (KeyCode::R, true) => b'R', - (KeyCode::S, true) => b'S', - (KeyCode::T, true) => b'T', - (KeyCode::U, true) => b'U', - (KeyCode::V, true) => b'V', - (KeyCode::W, true) => b'W', - (KeyCode::X, true) => b'X', - (KeyCode::Y, true) => b'Y', - (KeyCode::Z, true) => b'Z', - (KeyCode::Kc1, true) => b'!', - (KeyCode::Kc2, true) => b'@', - (KeyCode::Kc3, true) => b'#', - (KeyCode::Kc4, true) => b'$', - (KeyCode::Kc5, true) => b'%', - (KeyCode::Kc6, true) => b'^', - (KeyCode::Kc7, true) => b'&', - (KeyCode::Kc8, true) => b'*', - (KeyCode::Kc9, true) => b'(', - (KeyCode::Kc0, true) => b')', - (KeyCode::Minus, false) => b'-', - (KeyCode::Minus, true) => b'_', - (KeyCode::Equal, false) => b'=', - (KeyCode::Equal, true) => b'+', - (KeyCode::LeftBracket, false) => b'[', - (KeyCode::RightBracket, false) => b']', - (KeyCode::LeftBracket, true) => b'{', - (KeyCode::RightBracket, true) => b'}', - (KeyCode::Semicolon, false) => b';', - (KeyCode::Semicolon, true) => b':', - (KeyCode::Quote, false) => b'\'', - (KeyCode::Quote, true) => b'"', - (KeyCode::Grave, false) => b'`', - (KeyCode::Grave, true) => b'~', - (KeyCode::Backslash, true) => b'\\', - (KeyCode::Backslash, false) => b'|', - (KeyCode::Comma, false) => b',', - (KeyCode::Comma, true) => b'<', - (KeyCode::Dot, false) => b'.', - (KeyCode::Dot, true) => b'>', - (KeyCode::Slash, false) => b'/', - (KeyCode::Slash, true) => b'?', - (KeyCode::Space, false) => b' ', - (KeyCode::Enter, false) => b'\n', - (KeyCode::Tab, false) => b'\t', - (KeyCode::Backspace, false) => b'\x08', - (KeyCode::Escape, false) => b'\x1B', - (KeyCode::Delete, false) => b'\x7F', - // not supported keycodes - (_, _) => b'X', +impl From for HidKeyCode { + fn from(value: u8) -> Self { + match value { + 0x00 => HidKeyCode::No, + 0x01 => HidKeyCode::ErrorRollover, + 0x02 => HidKeyCode::PostFail, + 0x03 => HidKeyCode::ErrorUndefined, + 0x04 => HidKeyCode::A, + 0x05 => HidKeyCode::B, + 0x06 => HidKeyCode::C, + 0x07 => HidKeyCode::D, + 0x08 => HidKeyCode::E, + 0x09 => HidKeyCode::F, + 0x0A => HidKeyCode::G, + 0x0B => HidKeyCode::H, + 0x0C => HidKeyCode::I, + 0x0D => HidKeyCode::J, + 0x0E => HidKeyCode::K, + 0x0F => HidKeyCode::L, + 0x10 => HidKeyCode::M, + 0x11 => HidKeyCode::N, + 0x12 => HidKeyCode::O, + 0x13 => HidKeyCode::P, + 0x14 => HidKeyCode::Q, + 0x15 => HidKeyCode::R, + 0x16 => HidKeyCode::S, + 0x17 => HidKeyCode::T, + 0x18 => HidKeyCode::U, + 0x19 => HidKeyCode::V, + 0x1A => HidKeyCode::W, + 0x1B => HidKeyCode::X, + 0x1C => HidKeyCode::Y, + 0x1D => HidKeyCode::Z, + 0x1E => HidKeyCode::Kc1, + 0x1F => HidKeyCode::Kc2, + 0x20 => HidKeyCode::Kc3, + 0x21 => HidKeyCode::Kc4, + 0x22 => HidKeyCode::Kc5, + 0x23 => HidKeyCode::Kc6, + 0x24 => HidKeyCode::Kc7, + 0x25 => HidKeyCode::Kc8, + 0x26 => HidKeyCode::Kc9, + 0x27 => HidKeyCode::Kc0, + 0x28 => HidKeyCode::Enter, + 0x29 => HidKeyCode::Escape, + 0x2A => HidKeyCode::Backspace, + 0x2B => HidKeyCode::Tab, + 0x2C => HidKeyCode::Space, + 0x2D => HidKeyCode::Minus, + 0x2E => HidKeyCode::Equal, + 0x2F => HidKeyCode::LeftBracket, + 0x30 => HidKeyCode::RightBracket, + 0x31 => HidKeyCode::Backslash, + 0x32 => HidKeyCode::NonusHash, + 0x33 => HidKeyCode::Semicolon, + 0x34 => HidKeyCode::Quote, + 0x35 => HidKeyCode::Grave, + 0x36 => HidKeyCode::Comma, + 0x37 => HidKeyCode::Dot, + 0x38 => HidKeyCode::Slash, + 0x39 => HidKeyCode::CapsLock, + 0x3A => HidKeyCode::F1, + 0x3B => HidKeyCode::F2, + 0x3C => HidKeyCode::F3, + 0x3D => HidKeyCode::F4, + 0x3E => HidKeyCode::F5, + 0x3F => HidKeyCode::F6, + 0x40 => HidKeyCode::F7, + 0x41 => HidKeyCode::F8, + 0x42 => HidKeyCode::F9, + 0x43 => HidKeyCode::F10, + 0x44 => HidKeyCode::F11, + 0x45 => HidKeyCode::F12, + 0x46 => HidKeyCode::PrintScreen, + 0x47 => HidKeyCode::ScrollLock, + 0x48 => HidKeyCode::Pause, + 0x49 => HidKeyCode::Insert, + 0x4A => HidKeyCode::Home, + 0x4B => HidKeyCode::PageUp, + 0x4C => HidKeyCode::Delete, + 0x4D => HidKeyCode::End, + 0x4E => HidKeyCode::PageDown, + 0x4F => HidKeyCode::Right, + 0x50 => HidKeyCode::Left, + 0x51 => HidKeyCode::Down, + 0x52 => HidKeyCode::Up, + 0x53 => HidKeyCode::NumLock, + 0x54 => HidKeyCode::KpSlash, + 0x55 => HidKeyCode::KpAsterisk, + 0x56 => HidKeyCode::KpMinus, + 0x57 => HidKeyCode::KpPlus, + 0x58 => HidKeyCode::KpEnter, + 0x59 => HidKeyCode::Kp1, + 0x5A => HidKeyCode::Kp2, + 0x5B => HidKeyCode::Kp3, + 0x5C => HidKeyCode::Kp4, + 0x5D => HidKeyCode::Kp5, + 0x5E => HidKeyCode::Kp6, + 0x5F => HidKeyCode::Kp7, + 0x60 => HidKeyCode::Kp8, + 0x61 => HidKeyCode::Kp9, + 0x62 => HidKeyCode::Kp0, + 0x63 => HidKeyCode::KpDot, + 0x64 => HidKeyCode::NonusBackslash, + 0x65 => HidKeyCode::Application, + 0x66 => HidKeyCode::KbPower, + 0x67 => HidKeyCode::KpEqual, + 0x68 => HidKeyCode::F13, + 0x69 => HidKeyCode::F14, + 0x6A => HidKeyCode::F15, + 0x6B => HidKeyCode::F16, + 0x6C => HidKeyCode::F17, + 0x6D => HidKeyCode::F18, + 0x6E => HidKeyCode::F19, + 0x6F => HidKeyCode::F20, + 0x70 => HidKeyCode::F21, + 0x71 => HidKeyCode::F22, + 0x72 => HidKeyCode::F23, + 0x73 => HidKeyCode::F24, + 0x74 => HidKeyCode::Execute, + 0x75 => HidKeyCode::Help, + 0x76 => HidKeyCode::Menu, + 0x77 => HidKeyCode::Select, + 0x78 => HidKeyCode::Stop, + 0x79 => HidKeyCode::Again, + 0x7A => HidKeyCode::Undo, + 0x7B => HidKeyCode::Cut, + 0x7C => HidKeyCode::Copy, + 0x7D => HidKeyCode::Paste, + 0x7E => HidKeyCode::Find, + 0x7F => HidKeyCode::KbMute, + 0x80 => HidKeyCode::KbVolumeUp, + 0x81 => HidKeyCode::KbVolumeDown, + 0x82 => HidKeyCode::LockingCapsLock, + 0x83 => HidKeyCode::LockingNumLock, + 0x84 => HidKeyCode::LockingScrollLock, + 0x85 => HidKeyCode::KpComma, + 0x86 => HidKeyCode::KpEqualAs400, + 0x87 => HidKeyCode::International1, + 0x88 => HidKeyCode::International2, + 0x89 => HidKeyCode::International3, + 0x8A => HidKeyCode::International4, + 0x8B => HidKeyCode::International5, + 0x8C => HidKeyCode::International6, + 0x8D => HidKeyCode::International7, + 0x8E => HidKeyCode::International8, + 0x8F => HidKeyCode::International9, + 0x90 => HidKeyCode::Language1, + 0x91 => HidKeyCode::Language2, + 0x92 => HidKeyCode::Language3, + 0x93 => HidKeyCode::Language4, + 0x94 => HidKeyCode::Language5, + 0x95 => HidKeyCode::Language6, + 0x96 => HidKeyCode::Language7, + 0x97 => HidKeyCode::Language8, + 0x98 => HidKeyCode::Language9, + 0x99 => HidKeyCode::AlternateErase, + 0x9A => HidKeyCode::SystemRequest, + 0x9B => HidKeyCode::Cancel, + 0x9C => HidKeyCode::Clear, + 0x9D => HidKeyCode::Prior, + 0x9E => HidKeyCode::Return, + 0x9F => HidKeyCode::Separator, + 0xA0 => HidKeyCode::Out, + 0xA1 => HidKeyCode::Oper, + 0xA2 => HidKeyCode::ClearAgain, + 0xA3 => HidKeyCode::Crsel, + 0xA4 => HidKeyCode::Exsel, + 0xA5 => HidKeyCode::SystemPower, + 0xA6 => HidKeyCode::SystemSleep, + 0xA7 => HidKeyCode::SystemWake, + 0xA8 => HidKeyCode::AudioMute, + 0xA9 => HidKeyCode::AudioVolUp, + 0xAA => HidKeyCode::AudioVolDown, + 0xAB => HidKeyCode::MediaNextTrack, + 0xAC => HidKeyCode::MediaPrevTrack, + 0xAD => HidKeyCode::MediaStop, + 0xAE => HidKeyCode::MediaPlayPause, + 0xAF => HidKeyCode::MediaSelect, + 0xB0 => HidKeyCode::MediaEject, + 0xB1 => HidKeyCode::Mail, + 0xB2 => HidKeyCode::Calculator, + 0xB3 => HidKeyCode::MyComputer, + 0xB4 => HidKeyCode::WwwSearch, + 0xB5 => HidKeyCode::WwwHome, + 0xB6 => HidKeyCode::WwwBack, + 0xB7 => HidKeyCode::WwwForward, + 0xB8 => HidKeyCode::WwwStop, + 0xB9 => HidKeyCode::WwwRefresh, + 0xBA => HidKeyCode::WwwFavorites, + 0xBB => HidKeyCode::MediaFastForward, + 0xBC => HidKeyCode::MediaRewind, + 0xBD => HidKeyCode::BrightnessUp, + 0xBE => HidKeyCode::BrightnessDown, + 0xBF => HidKeyCode::ControlPanel, + 0xC0 => HidKeyCode::Assistant, + 0xC1 => HidKeyCode::MissionControl, + 0xC2 => HidKeyCode::Launchpad, + 0xCD => HidKeyCode::MouseUp, + 0xCE => HidKeyCode::MouseDown, + 0xCF => HidKeyCode::MouseLeft, + 0xD0 => HidKeyCode::MouseRight, + 0xD1 => HidKeyCode::MouseBtn1, + 0xD2 => HidKeyCode::MouseBtn2, + 0xD3 => HidKeyCode::MouseBtn3, + 0xD4 => HidKeyCode::MouseBtn4, + 0xD5 => HidKeyCode::MouseBtn5, + 0xD6 => HidKeyCode::MouseBtn6, + 0xD7 => HidKeyCode::MouseBtn7, + 0xD8 => HidKeyCode::MouseBtn8, + 0xD9 => HidKeyCode::MouseWheelUp, + 0xDA => HidKeyCode::MouseWheelDown, + 0xDB => HidKeyCode::MouseWheelLeft, + 0xDC => HidKeyCode::MouseWheelRight, + 0xDD => HidKeyCode::MouseAccel0, + 0xDE => HidKeyCode::MouseAccel1, + 0xDF => HidKeyCode::MouseAccel2, + 0xE0 => HidKeyCode::LCtrl, + 0xE1 => HidKeyCode::LShift, + 0xE2 => HidKeyCode::LAlt, + 0xE3 => HidKeyCode::LGui, + 0xE4 => HidKeyCode::RCtrl, + 0xE5 => HidKeyCode::RShift, + 0xE6 => HidKeyCode::RAlt, + 0xE7 => HidKeyCode::RGui, + _ => HidKeyCode::No, + } } } -impl From for KeyCode { - fn from(value: u16) -> Self { - Self::from_repr(value).unwrap_or(Self::No) - } +/// Key codes which are not in the HID spec, but still commonly used +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(postcard::experimental::max_size::MaxSize)] +pub enum SpecialKey { + // GraveEscape + GraveEscape, + // Repeat + Repeat, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(postcard::experimental::max_size::MaxSize)] +pub enum KeyCode { + Hid(HidKeyCode), + Consumer(ConsumerKey), + SystemControl(SystemControlKey), } /// Keys in consumer page /// Ref: #[non_exhaustive] #[repr(u16)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromRepr)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ConsumerKey { No = 0x00, @@ -953,17 +797,51 @@ pub enum ConsumerKey { AcSoftKeyLeft = 0x2A0, } -impl From for ConsumerKey { - fn from(value: u16) -> Self { - Self::from_repr(value).unwrap_or(Self::No) +impl ::postcard::experimental::max_size::MaxSize for ConsumerKey { + const POSTCARD_MAX_SIZE: usize = 3usize; +} + +impl ConsumerKey { + /// Convert ConsumerKey to the corresponding HidKeyCode + pub fn to_hid_keycode(&self) -> Option { + match self { + ConsumerKey::Mute => Some(HidKeyCode::AudioMute), + ConsumerKey::VolumeIncrement => Some(HidKeyCode::AudioVolUp), + ConsumerKey::VolumeDecrement => Some(HidKeyCode::AudioVolDown), + ConsumerKey::NextTrack => Some(HidKeyCode::MediaNextTrack), + ConsumerKey::PrevTrack => Some(HidKeyCode::MediaPrevTrack), + ConsumerKey::StopPlay => Some(HidKeyCode::MediaStop), + ConsumerKey::PlayPause => Some(HidKeyCode::MediaPlayPause), + ConsumerKey::Record => Some(HidKeyCode::MediaSelect), + ConsumerKey::Eject => Some(HidKeyCode::MediaEject), + ConsumerKey::Email => Some(HidKeyCode::Mail), + ConsumerKey::Calculator => Some(HidKeyCode::Calculator), + ConsumerKey::LocalBrowser => Some(HidKeyCode::MyComputer), + ConsumerKey::Search => Some(HidKeyCode::WwwSearch), + ConsumerKey::Home => Some(HidKeyCode::WwwHome), + ConsumerKey::Back => Some(HidKeyCode::WwwBack), + ConsumerKey::Forward => Some(HidKeyCode::WwwForward), + ConsumerKey::Stop => Some(HidKeyCode::WwwStop), + ConsumerKey::Refresh => Some(HidKeyCode::WwwRefresh), + ConsumerKey::Bookmarks => Some(HidKeyCode::WwwFavorites), + ConsumerKey::FastForward => Some(HidKeyCode::MediaFastForward), + ConsumerKey::Rewind => Some(HidKeyCode::MediaRewind), + ConsumerKey::BrightnessUp => Some(HidKeyCode::BrightnessUp), + ConsumerKey::BrightnessDown => Some(HidKeyCode::BrightnessDown), + ConsumerKey::ControlPanel => Some(HidKeyCode::ControlPanel), + ConsumerKey::Assistant => Some(HidKeyCode::Assistant), + ConsumerKey::DesktopShowAllWindows => Some(HidKeyCode::MissionControl), + ConsumerKey::AcSoftKeyLeft => Some(HidKeyCode::Launchpad), + _ => None, + } } } /// Keys in `Generic Desktop Page`, generally used for system control /// Ref: #[non_exhaustive] -#[repr(u16)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromRepr)] +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SystemControlKey { No = 0x00, @@ -973,8 +851,236 @@ pub enum SystemControlKey { Restart = 0x8F, } -impl From for SystemControlKey { - fn from(value: u16) -> Self { - Self::from_repr(value).unwrap_or(Self::No) +impl ::postcard::experimental::max_size::MaxSize for SystemControlKey { + const POSTCARD_MAX_SIZE: usize = 1usize; +} + +impl SystemControlKey { + /// Convert SystemControlKey to the corresponding HidKeyCode + pub fn to_hid_keycode(&self) -> Option { + match self { + SystemControlKey::PowerDown => Some(HidKeyCode::SystemPower), + SystemControlKey::Sleep => Some(HidKeyCode::SystemSleep), + SystemControlKey::WakeUp => Some(HidKeyCode::SystemWake), + _ => None, + } + } +} + +/// Convert a ascii chat to keycode +/// bool, if the keycode should be shifted +/// assumes en-us keyboard mapping +pub fn from_ascii(ascii: u8) -> (HidKeyCode, bool) { + match ascii { + b'0' => (HidKeyCode::Kc0, false), + b'1' => (HidKeyCode::Kc1, false), + b'2' => (HidKeyCode::Kc2, false), + b'3' => (HidKeyCode::Kc3, false), + b'4' => (HidKeyCode::Kc4, false), + b'5' => (HidKeyCode::Kc5, false), + b'6' => (HidKeyCode::Kc6, false), + b'7' => (HidKeyCode::Kc7, false), + b'8' => (HidKeyCode::Kc8, false), + b'9' => (HidKeyCode::Kc9, false), + b'a' => (HidKeyCode::A, false), + b'b' => (HidKeyCode::B, false), + b'c' => (HidKeyCode::C, false), + b'd' => (HidKeyCode::D, false), + b'e' => (HidKeyCode::E, false), + b'f' => (HidKeyCode::F, false), + b'g' => (HidKeyCode::G, false), + b'h' => (HidKeyCode::H, false), + b'i' => (HidKeyCode::I, false), + b'j' => (HidKeyCode::J, false), + b'k' => (HidKeyCode::K, false), + b'l' => (HidKeyCode::L, false), + b'm' => (HidKeyCode::M, false), + b'n' => (HidKeyCode::N, false), + b'o' => (HidKeyCode::O, false), + b'p' => (HidKeyCode::P, false), + b'q' => (HidKeyCode::Q, false), + b'r' => (HidKeyCode::R, false), + b's' => (HidKeyCode::S, false), + b't' => (HidKeyCode::T, false), + b'u' => (HidKeyCode::U, false), + b'v' => (HidKeyCode::V, false), + b'w' => (HidKeyCode::W, false), + b'x' => (HidKeyCode::X, false), + b'y' => (HidKeyCode::Y, false), + b'z' => (HidKeyCode::Z, false), + b'A' => (HidKeyCode::A, true), + b'B' => (HidKeyCode::B, true), + b'C' => (HidKeyCode::C, true), + b'D' => (HidKeyCode::D, true), + b'E' => (HidKeyCode::E, true), + b'F' => (HidKeyCode::F, true), + b'G' => (HidKeyCode::G, true), + b'H' => (HidKeyCode::H, true), + b'I' => (HidKeyCode::I, true), + b'J' => (HidKeyCode::J, true), + b'K' => (HidKeyCode::K, true), + b'L' => (HidKeyCode::L, true), + b'M' => (HidKeyCode::M, true), + b'N' => (HidKeyCode::N, true), + b'O' => (HidKeyCode::O, true), + b'P' => (HidKeyCode::P, true), + b'Q' => (HidKeyCode::Q, true), + b'R' => (HidKeyCode::R, true), + b'S' => (HidKeyCode::S, true), + b'T' => (HidKeyCode::T, true), + b'U' => (HidKeyCode::U, true), + b'V' => (HidKeyCode::V, true), + b'W' => (HidKeyCode::W, true), + b'X' => (HidKeyCode::X, true), + b'Y' => (HidKeyCode::Y, true), + b'Z' => (HidKeyCode::Z, true), + b'!' => (HidKeyCode::Kc1, true), + b'@' => (HidKeyCode::Kc2, true), + b'#' => (HidKeyCode::Kc3, true), + b'$' => (HidKeyCode::Kc4, true), + b'%' => (HidKeyCode::Kc5, true), + b'^' => (HidKeyCode::Kc6, true), + b'&' => (HidKeyCode::Kc7, true), + b'*' => (HidKeyCode::Kc8, true), + b'(' => (HidKeyCode::Kc9, true), + b')' => (HidKeyCode::Kc0, true), + b'-' => (HidKeyCode::Minus, false), + b'_' => (HidKeyCode::Minus, true), + b'=' => (HidKeyCode::Equal, false), + b'+' => (HidKeyCode::Equal, true), + b'[' => (HidKeyCode::LeftBracket, false), + b']' => (HidKeyCode::RightBracket, false), + b'{' => (HidKeyCode::LeftBracket, true), + b'}' => (HidKeyCode::RightBracket, true), + b';' => (HidKeyCode::Semicolon, false), + b':' => (HidKeyCode::Semicolon, true), + b'\'' => (HidKeyCode::Quote, false), + b'"' => (HidKeyCode::Quote, true), + b'`' => (HidKeyCode::Grave, false), + b'~' => (HidKeyCode::Grave, true), + b'\\' => (HidKeyCode::Backslash, false), + b'|' => (HidKeyCode::Backslash, true), + b',' => (HidKeyCode::Comma, false), + b'<' => (HidKeyCode::Comma, true), + b'.' => (HidKeyCode::Dot, false), + b'>' => (HidKeyCode::Dot, true), + b'/' => (HidKeyCode::Slash, false), + b'?' => (HidKeyCode::Slash, true), + b' ' => (HidKeyCode::Space, false), + b'\n' => (HidKeyCode::Enter, false), + b'\t' => (HidKeyCode::Tab, false), + b'\x08' => (HidKeyCode::Backspace, false), + b'\x1B' => (HidKeyCode::Escape, false), + b'\x7F' => (HidKeyCode::Delete, false), + _ => (HidKeyCode::No, false), + } +} + +/// Convert a ascii chat to keycode +/// assumes en-us keyboard mapping +pub fn to_ascii(keycode: HidKeyCode, shifted: bool) -> u8 { + match (keycode, shifted) { + (HidKeyCode::Kc0, false) => b'0', + (HidKeyCode::Kc1, false) => b'1', + (HidKeyCode::Kc2, false) => b'2', + (HidKeyCode::Kc3, false) => b'3', + (HidKeyCode::Kc4, false) => b'4', + (HidKeyCode::Kc5, false) => b'5', + (HidKeyCode::Kc6, false) => b'6', + (HidKeyCode::Kc7, false) => b'7', + (HidKeyCode::Kc8, false) => b'8', + (HidKeyCode::Kc9, false) => b'9', + (HidKeyCode::A, false) => b'a', + (HidKeyCode::B, false) => b'b', + (HidKeyCode::C, false) => b'c', + (HidKeyCode::D, false) => b'd', + (HidKeyCode::E, false) => b'e', + (HidKeyCode::F, false) => b'f', + (HidKeyCode::G, false) => b'g', + (HidKeyCode::H, false) => b'h', + (HidKeyCode::I, false) => b'i', + (HidKeyCode::J, false) => b'j', + (HidKeyCode::K, false) => b'k', + (HidKeyCode::L, false) => b'l', + (HidKeyCode::M, false) => b'm', + (HidKeyCode::N, false) => b'n', + (HidKeyCode::O, false) => b'o', + (HidKeyCode::P, false) => b'p', + (HidKeyCode::Q, false) => b'q', + (HidKeyCode::R, false) => b'r', + (HidKeyCode::S, false) => b's', + (HidKeyCode::T, false) => b't', + (HidKeyCode::U, false) => b'u', + (HidKeyCode::V, false) => b'v', + (HidKeyCode::W, false) => b'w', + (HidKeyCode::X, false) => b'x', + (HidKeyCode::Y, false) => b'y', + (HidKeyCode::Z, false) => b'z', + (HidKeyCode::A, true) => b'A', + (HidKeyCode::B, true) => b'B', + (HidKeyCode::C, true) => b'C', + (HidKeyCode::D, true) => b'D', + (HidKeyCode::E, true) => b'E', + (HidKeyCode::F, true) => b'F', + (HidKeyCode::G, true) => b'G', + (HidKeyCode::H, true) => b'H', + (HidKeyCode::I, true) => b'I', + (HidKeyCode::J, true) => b'J', + (HidKeyCode::K, true) => b'K', + (HidKeyCode::L, true) => b'L', + (HidKeyCode::M, true) => b'M', + (HidKeyCode::N, true) => b'N', + (HidKeyCode::O, true) => b'O', + (HidKeyCode::P, true) => b'P', + (HidKeyCode::Q, true) => b'Q', + (HidKeyCode::R, true) => b'R', + (HidKeyCode::S, true) => b'S', + (HidKeyCode::T, true) => b'T', + (HidKeyCode::U, true) => b'U', + (HidKeyCode::V, true) => b'V', + (HidKeyCode::W, true) => b'W', + (HidKeyCode::X, true) => b'X', + (HidKeyCode::Y, true) => b'Y', + (HidKeyCode::Z, true) => b'Z', + (HidKeyCode::Kc1, true) => b'!', + (HidKeyCode::Kc2, true) => b'@', + (HidKeyCode::Kc3, true) => b'#', + (HidKeyCode::Kc4, true) => b'$', + (HidKeyCode::Kc5, true) => b'%', + (HidKeyCode::Kc6, true) => b'^', + (HidKeyCode::Kc7, true) => b'&', + (HidKeyCode::Kc8, true) => b'*', + (HidKeyCode::Kc9, true) => b'(', + (HidKeyCode::Kc0, true) => b')', + (HidKeyCode::Minus, false) => b'-', + (HidKeyCode::Minus, true) => b'_', + (HidKeyCode::Equal, false) => b'=', + (HidKeyCode::Equal, true) => b'+', + (HidKeyCode::LeftBracket, false) => b'[', + (HidKeyCode::RightBracket, false) => b']', + (HidKeyCode::LeftBracket, true) => b'{', + (HidKeyCode::RightBracket, true) => b'}', + (HidKeyCode::Semicolon, false) => b';', + (HidKeyCode::Semicolon, true) => b':', + (HidKeyCode::Quote, false) => b'\'', + (HidKeyCode::Quote, true) => b'"', + (HidKeyCode::Grave, false) => b'`', + (HidKeyCode::Grave, true) => b'~', + (HidKeyCode::Backslash, true) => b'\\', + (HidKeyCode::Backslash, false) => b'|', + (HidKeyCode::Comma, false) => b',', + (HidKeyCode::Comma, true) => b'<', + (HidKeyCode::Dot, false) => b'.', + (HidKeyCode::Dot, true) => b'>', + (HidKeyCode::Slash, false) => b'/', + (HidKeyCode::Slash, true) => b'?', + (HidKeyCode::Space, false) => b' ', + (HidKeyCode::Enter, false) => b'\n', + (HidKeyCode::Tab, false) => b'\t', + (HidKeyCode::Backspace, false) => b'\x08', + (HidKeyCode::Escape, false) => b'\x1B', + (HidKeyCode::Delete, false) => b'\x7F', + // not supported keycodes + (_, _) => b'X', } } diff --git a/rmk-types/src/keycode_backup.rs b/rmk-types/src/keycode_backup.rs new file mode 100644 index 000000000..0a24db6ce --- /dev/null +++ b/rmk-types/src/keycode_backup.rs @@ -0,0 +1,1380 @@ +//! Complete keycode definitions. +//! +//! This module provides keycode definitions following the USB HID +//! specification, extended with additional codes +use serde::{Deserialize, Serialize}; +use strum::FromRepr; + +use crate::modifier::ModifierCombination; + +/// KeyCode is the internal representation of all keycodes, keyboard operations, etc. +/// Use flat representation of keycodes. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum KeyCode { + /// Reserved, no-key. + No = 0x0000, + /// Keyboard roll over error, too many keys are pressed simultaneously, not a physical key. + /// NKRO: n-key rollover. + ErrorRollover = 0x0001, + /// Keyboard post fail error, not a physical key. + PostFail = 0x0002, + /// An undefined error, not a physical key. + ErrorUndefined = 0x0003, + /// `a` and `A` + A = 0x0004, + /// `b` and `B` + B = 0x0005, + /// `c` and `C` + C = 0x0006, + /// `d` and `D` + D = 0x0007, + /// `e` and `E` + E = 0x0008, + /// `f` and `F` + F = 0x0009, + /// `g` and `G` + G = 0x000A, + /// `h` and `H` + H = 0x000B, + /// `i` and `I` + I = 0x000C, + /// `j` and `J` + J = 0x000D, + /// `k` and `K` + K = 0x000E, + /// `l` and `L` + L = 0x000F, + /// `m` and `M` + M = 0x0010, + /// `n` and `N` + N = 0x0011, + /// `o` and `O` + O = 0x0012, + /// `p` and `P` + P = 0x0013, + /// `q` and `Q` + Q = 0x0014, + /// `r` and `R` + R = 0x0015, + /// `s` and `S` + S = 0x0016, + /// `t` and `T` + T = 0x0017, + /// `u` and `U` + U = 0x0018, + /// `v` and `V` + V = 0x0019, + /// `w` and `W` + W = 0x001A, + /// `x` and `X` + X = 0x001B, + /// `y` and `Y` + Y = 0x001C, + /// `z` and `Z` + Z = 0x001D, + /// `1` and `!` + Kc1 = 0x001E, + /// `2` and `@` + Kc2 = 0x001F, + /// `3` and `#` + Kc3 = 0x0020, + /// `4` and `$` + Kc4 = 0x0021, + /// `5` and `%` + Kc5 = 0x0022, + /// `6` and `^` + Kc6 = 0x0023, + /// `7` and `&` + Kc7 = 0x0024, + /// `8` and `*` + Kc8 = 0x0025, + /// `9` and `(` + Kc9 = 0x0026, + /// `0` and `)` + Kc0 = 0x0027, + /// `Enter` + Enter = 0x0028, + /// `Esc` + Escape = 0x0029, + /// `Backspace` + Backspace = 0x002A, + /// `Tab` + Tab = 0x002B, + /// `Space` + Space = 0x002C, + /// `-` and `_` + Minus = 0x002D, + /// `=` and `+` + Equal = 0x002E, + /// `[` and `{` + LeftBracket = 0x002F, + /// `]` and `}` + RightBracket = 0x0030, + /// `\` and `|` + Backslash = 0x0031, + /// Non-US `#` and `~` + NonusHash = 0x0032, + /// `;` and `:` + Semicolon = 0x0033, + /// `'` and `"` + Quote = 0x0034, + /// `~` and `\`` + Grave = 0x0035, + /// `,` and `<` + Comma = 0x0036, + /// `.` and `>` + Dot = 0x0037, + /// `/` and `?` + Slash = 0x0038, + /// `CapsLock` + CapsLock = 0x0039, + /// `F1` + F1 = 0x003A, + /// `F2` + F2 = 0x003B, + /// `F3` + F3 = 0x003C, + /// `F4` + F4 = 0x003D, + /// `F5` + F5 = 0x003E, + /// `F6` + F6 = 0x003F, + /// `F7` + F7 = 0x0040, + /// `F8` + F8 = 0x0041, + /// `F9` + F9 = 0x0042, + /// `F10` + F10 = 0x0043, + /// `F11` + F11 = 0x0044, + /// `F12` + F12 = 0x0045, + /// Print Screen + PrintScreen = 0x0046, + /// Scroll Lock + ScrollLock = 0x0047, + /// Pause + Pause = 0x0048, + /// Insert + Insert = 0x0049, + /// Home + Home = 0x004A, + /// Page Up + PageUp = 0x004B, + /// Delete + Delete = 0x004C, + /// End + End = 0x004D, + /// Page Down + PageDown = 0x004E, + /// Right arrow + Right = 0x004F, + /// Left arrow + Left = 0x0050, + /// Down arrow + Down = 0x0051, + /// Up arrow + Up = 0x0052, + /// Nums Lock + NumLock = 0x0053, + /// `/` on keypad + KpSlash = 0x0054, + /// `*` on keypad + KpAsterisk = 0x0055, + /// `-` on keypad + KpMinus = 0x0056, + /// `+` on keypad + KpPlus = 0x0057, + /// `Enter` on keypad + KpEnter = 0x0058, + /// `1` on keypad + Kp1 = 0x0059, + /// `2` on keypad + Kp2 = 0x005A, + /// `3` on keypad + Kp3 = 0x005B, + /// `4` on keypad + Kp4 = 0x005C, + /// `5` on keypad + Kp5 = 0x005D, + /// `6` on keypad + Kp6 = 0x005E, + /// `7` on keypad + Kp7 = 0x005F, + /// `8` on keypad + Kp8 = 0x0060, + /// `9` on keypad + Kp9 = 0x0061, + /// `0` on keypad + Kp0 = 0x0062, + /// `.` on keypad + KpDot = 0x0063, + /// Non-US `\` or `|` + NonusBackslash = 0x0064, + /// `Application` + Application = 0x0065, + /// `Power` + KbPower = 0x0066, + /// `=` on keypad + KpEqual = 0x0067, + /// `F13` + F13 = 0x0068, + /// `F14` + F14 = 0x0069, + /// `F15` + F15 = 0x006A, + /// `F16` + F16 = 0x006B, + /// `F17` + F17 = 0x006C, + /// `F18` + F18 = 0x006D, + /// `F19` + F19 = 0x006E, + /// `F20` + F20 = 0x006F, + /// `F21` + F21 = 0x0070, + /// `F22` + F22 = 0x0071, + /// `F23` + F23 = 0x0072, + /// `F24` + F24 = 0x0073, + Execute = 0x0074, + Help = 0x0075, + Menu = 0x0076, + Select = 0x0077, + Stop = 0x0078, + Again = 0x0079, + Undo = 0x007A, + Cut = 0x007B, + Copy = 0x007C, + Paste = 0x007D, + Find = 0x007E, + /// Mute + KbMute = 0x007F, + /// Volume Up + KbVolumeUp = 0x0080, + /// Volume Down + KbVolumeDown = 0x0081, + /// Locking Caps Lock + LockingCapsLock = 0x0082, + /// Locking Num Lock + LockingNumLock = 0x0083, + /// Locking scroll lock + LockingScrollLock = 0x0084, + KpComma = 0x0085, + KpEqualAs400 = 0x0086, + International1 = 0x0087, + International2 = 0x0088, + International3 = 0x0089, + International4 = 0x008A, + International5 = 0x008B, + International6 = 0x008C, + International7 = 0x008D, + International8 = 0x008E, + International9 = 0x008F, + Language1 = 0x0090, + Language2 = 0x0091, + Language3 = 0x0092, + Language4 = 0x0093, + Language5 = 0x0094, + Language6 = 0x0095, + Language7 = 0x0096, + Language8 = 0x0097, + Language9 = 0x0098, + AlternateErase = 0x0099, + SystemRequest = 0x009A, + Cancel = 0x009B, + Clear = 0x009C, + Prior = 0x009D, + Return = 0x009E, + Separator = 0x009F, + Out = 0x00A0, + Oper = 0x00A1, + ClearAgain = 0x00A2, + Crsel = 0x00A3, + Exsel = 0x00A4, + SystemPower = 0x00A5, + SystemSleep = 0x00A6, + SystemWake = 0x00A7, + AudioMute = 0x00A8, + AudioVolUp = 0x00A9, + AudioVolDown = 0x00AA, + MediaNextTrack = 0x00AB, + MediaPrevTrack = 0x00AC, + MediaStop = 0x00AD, + MediaPlayPause = 0x00AE, + MediaSelect = 0x00AF, + MediaEject = 0x00B0, + Mail = 0x00B1, + Calculator = 0x00B2, + MyComputer = 0x00B3, + WwwSearch = 0x00B4, + WwwHome = 0x00B5, + WwwBack = 0x00B6, + WwwForward = 0x00B7, + WwwStop = 0x00B8, + WwwRefresh = 0x00B9, + WwwFavorites = 0x00BA, + MediaFastForward = 0x00BB, + MediaRewind = 0x00BC, + /// Brightness Up + BrightnessUp = 0x00BD, + /// Brightness Down + BrightnessDown = 0x00BE, + ControlPanel = 0x00BF, + Assistant = 0x00C0, + MissionControl = 0x00C1, + Launchpad = 0x00C2, + /// Mouse Up + MouseUp = 0x00CD, + /// Mouse Down + MouseDown = 0x00CE, + /// Mouse Left + MouseLeft = 0x00CF, + /// Mouse Right + MouseRight = 0x00D0, + /// Mouse Button 1(Left) + MouseBtn1 = 0x00D1, + /// Mouse Button 2(Right) + MouseBtn2 = 0x00D2, + /// Mouse Button 3(Middle) + MouseBtn3 = 0x00D3, + /// Mouse Button 4(Back) + MouseBtn4 = 0x00D4, + /// Mouse Button 5(Forward) + MouseBtn5 = 0x00D5, + MouseBtn6 = 0x00D6, + MouseBtn7 = 0x00D7, + MouseBtn8 = 0x00D8, + MouseWheelUp = 0x00D9, + MouseWheelDown = 0x00DA, + MouseWheelLeft = 0x00DB, + MouseWheelRight = 0x00DC, + MouseAccel0 = 0x00DD, + MouseAccel1 = 0x00DE, + MouseAccel2 = 0x00DF, + /// Left Control + LCtrl = 0x00E0, + /// Left Shift + LShift = 0x00E1, + /// Left Alt + LAlt = 0x00E2, + /// Left GUI + LGui = 0x00E3, + /// Right Control + RCtrl = 0x00E4, + /// Right Shift + RShift = 0x00E5, + /// Right Alt + RAlt = 0x00E6, + /// Right GUI + RGui = 0x00E7, + // Macro keycodes, use 0x500 ~ 0x5FF + Macro0 = 0x500, + Macro1 = 0x501, + Macro2 = 0x502, + Macro3 = 0x503, + Macro4 = 0x504, + Macro5 = 0x505, + Macro6 = 0x506, + Macro7 = 0x507, + Macro8 = 0x508, + Macro9 = 0x509, + Macro10 = 0x50A, + Macro11 = 0x50B, + Macro12 = 0x50C, + Macro13 = 0x50D, + Macro14 = 0x50E, + Macro15 = 0x50F, + Macro16 = 0x510, + Macro17 = 0x511, + Macro18 = 0x512, + Macro19 = 0x513, + Macro20 = 0x514, + Macro21 = 0x515, + Macro22 = 0x516, + Macro23 = 0x517, + Macro24 = 0x518, + Macro25 = 0x519, + Macro26 = 0x51A, + Macro27 = 0x51B, + Macro28 = 0x51C, + Macro29 = 0x51D, + Macro30 = 0x51E, + Macro31 = 0x51F, + // Backlight and RGB keycodes, uses 0x600 ~ 0x6FF + BacklightOn = 0x600, + BacklightOff = 0x601, + BacklightToggle = 0x602, + BacklightDown = 0x603, + BacklightUp = 0x604, + BacklightStep = 0x605, + BacklightToggleBreathing = 0x606, + RgbTog = 0x620, + RgbModeForward = 0x621, + RgbModeReverse = 0x622, + RgbHui = 0x623, + RgbHud = 0x624, + RgbSai = 0x625, + RgbSad = 0x626, + RgbVai = 0x627, + RgbVad = 0x628, + RgbSpi = 0x629, + RgbSpd = 0x62A, + RgbModePlain = 0x62B, + RgbModeBreathe = 0x62C, + RgbModeRainbow = 0x62D, + RgbModeSwirl = 0x62E, + RgbModeSnake = 0x62F, + RgbModeKnight = 0x630, + RgbModeXmas = 0x631, + RgbModeGradient = 0x632, + // Not in vial + RgbModeRgbtest = 0x633, + RgbModeTwinkle = 0x634, + // Internal functional keycodes, use 0x700 ~ 0x7FF + Bootloader = 0x700, + Reboot = 0x701, + DebugToggle = 0x702, + ClearEeprom = 0x703, + GraveEscape = 0x716, + OutputAuto = 0x720, + OutputUsb = 0x721, + OutputBluetooth = 0x722, + ComboOn = 0x750, + ComboOff = 0x751, + ComboToggle = 0x752, + CapsWordToggle = 0x773, + TriLayerLower = 0x777, + TriLayerUpper = 0x778, + RepeatKey = 0x779, + AltRepeatKey = 0x77A, + // User keycodes, use 0x840 ~ 0x85F + User0 = 0x840, + User1 = 0x841, + User2 = 0x842, + User3 = 0x843, + User4 = 0x844, + User5 = 0x845, + User6 = 0x846, + User7 = 0x847, + User8 = 0x848, + User9 = 0x849, + User10 = 0x84A, + User11 = 0x84B, + User12 = 0x84C, + User13 = 0x84D, + User14 = 0x84E, + User15 = 0x84F, + User16 = 0x850, + User17 = 0x851, + User18 = 0x852, + User19 = 0x853, + User20 = 0x854, + User21 = 0x855, + User22 = 0x856, + User23 = 0x857, + User24 = 0x858, + User25 = 0x859, + User26 = 0x85A, + User27 = 0x85B, + User28 = 0x85C, + User29 = 0x85D, + User30 = 0x85E, + User31 = 0x85F, +} + +impl ::postcard::experimental::max_size::MaxSize for KeyCode { + const POSTCARD_MAX_SIZE: usize = 3usize; +} + +impl KeyCode { + /// Returns `true` if the keycode is a simple keycode defined in HID spec + pub fn is_simple_key(self) -> bool { + KeyCode::No <= self && self <= KeyCode::MouseAccel2 + } + + /// Returns `true` if the keycode is a modifier keycode + pub fn is_modifier(self) -> bool { + KeyCode::LCtrl <= self && self <= KeyCode::RGui + } + + /// Returns `true` if the keycode is basic keycode + /// The basic keycode = simple key + modifier + pub fn is_basic(self) -> bool { + KeyCode::No <= self && self <= KeyCode::RGui + } + + /// Returns `true` if the keycode is a letter + pub fn is_letter(self) -> bool { + KeyCode::A <= self && self <= KeyCode::Z + } + + /// Returns the byte with the bit corresponding to the USB HID + /// modifier bitfield set. + pub fn to_hid_modifiers(self) -> ModifierCombination { + match self { + KeyCode::LCtrl => ModifierCombination::new().with_left_ctrl(true), + KeyCode::LShift => ModifierCombination::new().with_left_shift(true), + KeyCode::LAlt => ModifierCombination::new().with_left_alt(true), + KeyCode::LGui => ModifierCombination::new().with_left_gui(true), + KeyCode::RCtrl => ModifierCombination::new().with_right_ctrl(true), + KeyCode::RShift => ModifierCombination::new().with_right_shift(true), + KeyCode::RAlt => ModifierCombination::new().with_right_alt(true), + KeyCode::RGui => ModifierCombination::new().with_right_gui(true), + _ => ModifierCombination::new(), + } + } + + /// Returns `true` if the keycode is a system keycode + pub fn is_system(self) -> bool { + KeyCode::SystemPower <= self && self <= KeyCode::SystemWake + } + + /// Returns `true` if the keycode is a keycode in consumer page + pub fn is_consumer(self) -> bool { + KeyCode::AudioMute <= self && self <= KeyCode::Launchpad + } + + /// Returns `true` if the keycode is a mouse keycode + pub fn is_mouse_key(self) -> bool { + KeyCode::MouseUp <= self && self <= KeyCode::MouseAccel2 + } + + /// Returns `true` if the keycode is a combo keycode + pub fn is_combo(self) -> bool { + KeyCode::ComboOn <= self && self <= KeyCode::ComboToggle + } + + /// Returns `true` if the keycode is a macro keycode + pub fn is_macro(self) -> bool { + KeyCode::Macro0 <= self && self <= KeyCode::Macro31 + } + + /// Returns `true` if the keycode is a backlight keycode + pub fn is_backlight(self) -> bool { + KeyCode::BacklightOn <= self && self <= KeyCode::BacklightToggleBreathing + } + + /// Returns `true` if the keycode is a rgb keycode + pub fn is_rgb(self) -> bool { + KeyCode::RgbTog <= self && self <= KeyCode::RgbModeTwinkle + } + + /// Returns `true` if the keycode is defined by rmk to achieve special functionalities, such as reboot keyboard, goto bootloader, etc. + pub fn is_rmk(self) -> bool { + KeyCode::Bootloader <= self && self <= KeyCode::AltRepeatKey + } + + /// Returns `true` if the keycode is a boot keycode + pub fn is_boot(self) -> bool { + KeyCode::Bootloader <= self && self <= KeyCode::Reboot + } + /// Returns `true` if the keycode is a user keycode + pub fn is_user(self) -> bool { + KeyCode::User0 <= self && self <= KeyCode::User31 + } + + /// Convert a keycode to macro number + pub fn as_macro_index(self) -> Option { + if self.is_macro() { + Some((self as u16 & 0x1F) as u8) + } else { + None + } + } + + /// Does current keycode continues Caps Word? + pub fn is_caps_word_continue_key(self) -> bool { + if self >= KeyCode::A && self <= KeyCode::Z { + return true; + } + if self >= KeyCode::Kc1 && self <= KeyCode::Kc0 { + return true; + } + if self == KeyCode::Minus || self == KeyCode::Backspace || self == KeyCode::Delete { + return true; + } + false + } + + /// Does current keycode is to be shifted by Caps Word? + pub fn is_caps_word_shifted_key(self) -> bool { + if self >= KeyCode::A && self <= KeyCode::Z { + return true; + } + if self == KeyCode::Minus { + return true; + } + false + } + + /// Convert a keycode to usb hid media key + pub fn as_consumer_control_usage_id(self) -> ConsumerKey { + match self { + KeyCode::AudioMute => ConsumerKey::Mute, + KeyCode::AudioVolUp => ConsumerKey::VolumeIncrement, + KeyCode::AudioVolDown => ConsumerKey::VolumeDecrement, + KeyCode::MediaNextTrack => ConsumerKey::NextTrack, + KeyCode::MediaPrevTrack => ConsumerKey::PrevTrack, + KeyCode::MediaStop => ConsumerKey::StopPlay, + KeyCode::MediaPlayPause => ConsumerKey::PlayPause, + KeyCode::MediaSelect => ConsumerKey::Record, + KeyCode::MediaEject => ConsumerKey::Eject, + KeyCode::Mail => ConsumerKey::Email, + KeyCode::Calculator => ConsumerKey::Calculator, + KeyCode::MyComputer => ConsumerKey::LocalBrowser, + KeyCode::WwwSearch => ConsumerKey::Search, + KeyCode::WwwHome => ConsumerKey::Home, + KeyCode::WwwBack => ConsumerKey::Back, + KeyCode::WwwForward => ConsumerKey::Forward, + KeyCode::WwwStop => ConsumerKey::Stop, + KeyCode::WwwRefresh => ConsumerKey::Refresh, + KeyCode::WwwFavorites => ConsumerKey::Bookmarks, + KeyCode::MediaFastForward => ConsumerKey::FastForward, + KeyCode::MediaRewind => ConsumerKey::Rewind, + KeyCode::BrightnessUp => ConsumerKey::BrightnessUp, + KeyCode::BrightnessDown => ConsumerKey::BrightnessDown, + KeyCode::ControlPanel => ConsumerKey::ControlPanel, + KeyCode::Assistant => ConsumerKey::Assistant, + KeyCode::MissionControl => ConsumerKey::DesktopShowAllWindows, + KeyCode::Launchpad => ConsumerKey::AcSoftKeyLeft, + _ => ConsumerKey::No, + } + } + + /// Convert a keycode to usb hid media key + pub fn as_system_control_usage_id(self) -> Option { + match self { + KeyCode::SystemPower => Some(SystemControlKey::PowerDown), + KeyCode::SystemSleep => Some(SystemControlKey::Sleep), + KeyCode::SystemWake => Some(SystemControlKey::WakeUp), + _ => None, + } + } +} + +/// Convert a ascii chat to keycode +/// bool, if the keycode should be shifted +/// assumes en-us keyboard mapping +pub fn from_ascii(ascii: u8) -> (KeyCode, bool) { + match ascii { + b'0' => (KeyCode::Kc0, false), + b'1' => (KeyCode::Kc1, false), + b'2' => (KeyCode::Kc2, false), + b'3' => (KeyCode::Kc3, false), + b'4' => (KeyCode::Kc4, false), + b'5' => (KeyCode::Kc5, false), + b'6' => (KeyCode::Kc6, false), + b'7' => (KeyCode::Kc7, false), + b'8' => (KeyCode::Kc8, false), + b'9' => (KeyCode::Kc9, false), + b'a' => (KeyCode::A, false), + b'b' => (KeyCode::B, false), + b'c' => (KeyCode::C, false), + b'd' => (KeyCode::D, false), + b'e' => (KeyCode::E, false), + b'f' => (KeyCode::F, false), + b'g' => (KeyCode::G, false), + b'h' => (KeyCode::H, false), + b'i' => (KeyCode::I, false), + b'j' => (KeyCode::J, false), + b'k' => (KeyCode::K, false), + b'l' => (KeyCode::L, false), + b'm' => (KeyCode::M, false), + b'n' => (KeyCode::N, false), + b'o' => (KeyCode::O, false), + b'p' => (KeyCode::P, false), + b'q' => (KeyCode::Q, false), + b'r' => (KeyCode::R, false), + b's' => (KeyCode::S, false), + b't' => (KeyCode::T, false), + b'u' => (KeyCode::U, false), + b'v' => (KeyCode::V, false), + b'w' => (KeyCode::W, false), + b'x' => (KeyCode::X, false), + b'y' => (KeyCode::Y, false), + b'z' => (KeyCode::Z, false), + b'A' => (KeyCode::A, true), + b'B' => (KeyCode::B, true), + b'C' => (KeyCode::C, true), + b'D' => (KeyCode::D, true), + b'E' => (KeyCode::E, true), + b'F' => (KeyCode::F, true), + b'G' => (KeyCode::G, true), + b'H' => (KeyCode::H, true), + b'I' => (KeyCode::I, true), + b'J' => (KeyCode::J, true), + b'K' => (KeyCode::K, true), + b'L' => (KeyCode::L, true), + b'M' => (KeyCode::M, true), + b'N' => (KeyCode::N, true), + b'O' => (KeyCode::O, true), + b'P' => (KeyCode::P, true), + b'Q' => (KeyCode::Q, true), + b'R' => (KeyCode::R, true), + b'S' => (KeyCode::S, true), + b'T' => (KeyCode::T, true), + b'U' => (KeyCode::U, true), + b'V' => (KeyCode::V, true), + b'W' => (KeyCode::W, true), + b'X' => (KeyCode::X, true), + b'Y' => (KeyCode::Y, true), + b'Z' => (KeyCode::Z, true), + b'!' => (KeyCode::Kc1, true), + b'@' => (KeyCode::Kc2, true), + b'#' => (KeyCode::Kc3, true), + b'$' => (KeyCode::Kc4, true), + b'%' => (KeyCode::Kc5, true), + b'^' => (KeyCode::Kc6, true), + b'&' => (KeyCode::Kc7, true), + b'*' => (KeyCode::Kc8, true), + b'(' => (KeyCode::Kc9, true), + b')' => (KeyCode::Kc0, true), + b'-' => (KeyCode::Minus, false), + b'_' => (KeyCode::Minus, true), + b'=' => (KeyCode::Equal, false), + b'+' => (KeyCode::Equal, true), + b'[' => (KeyCode::LeftBracket, false), + b']' => (KeyCode::RightBracket, false), + b'{' => (KeyCode::LeftBracket, true), + b'}' => (KeyCode::RightBracket, true), + b';' => (KeyCode::Semicolon, false), + b':' => (KeyCode::Semicolon, true), + b'\'' => (KeyCode::Quote, false), + b'"' => (KeyCode::Quote, true), + b'`' => (KeyCode::Grave, false), + b'~' => (KeyCode::Grave, true), + b'\\' => (KeyCode::Backslash, false), + b'|' => (KeyCode::Backslash, true), + b',' => (KeyCode::Comma, false), + b'<' => (KeyCode::Comma, true), + b'.' => (KeyCode::Dot, false), + b'>' => (KeyCode::Dot, true), + b'/' => (KeyCode::Slash, false), + b'?' => (KeyCode::Slash, true), + b' ' => (KeyCode::Space, false), + b'\n' => (KeyCode::Enter, false), + b'\t' => (KeyCode::Tab, false), + b'\x08' => (KeyCode::Backspace, false), + b'\x1B' => (KeyCode::Escape, false), + b'\x7F' => (KeyCode::Delete, false), + _ => (KeyCode::No, false), + } +} + +/// Convert a ascii chat to keycode +/// assumes en-us keyboard mapping +pub fn to_ascii(keycode: KeyCode, shifted: bool) -> u8 { + match (keycode, shifted) { + (KeyCode::Kc0, false) => b'0', + (KeyCode::Kc1, false) => b'1', + (KeyCode::Kc2, false) => b'2', + (KeyCode::Kc3, false) => b'3', + (KeyCode::Kc4, false) => b'4', + (KeyCode::Kc5, false) => b'5', + (KeyCode::Kc6, false) => b'6', + (KeyCode::Kc7, false) => b'7', + (KeyCode::Kc8, false) => b'8', + (KeyCode::Kc9, false) => b'9', + (KeyCode::A, false) => b'a', + (KeyCode::B, false) => b'b', + (KeyCode::C, false) => b'c', + (KeyCode::D, false) => b'd', + (KeyCode::E, false) => b'e', + (KeyCode::F, false) => b'f', + (KeyCode::G, false) => b'g', + (KeyCode::H, false) => b'h', + (KeyCode::I, false) => b'i', + (KeyCode::J, false) => b'j', + (KeyCode::K, false) => b'k', + (KeyCode::L, false) => b'l', + (KeyCode::M, false) => b'm', + (KeyCode::N, false) => b'n', + (KeyCode::O, false) => b'o', + (KeyCode::P, false) => b'p', + (KeyCode::Q, false) => b'q', + (KeyCode::R, false) => b'r', + (KeyCode::S, false) => b's', + (KeyCode::T, false) => b't', + (KeyCode::U, false) => b'u', + (KeyCode::V, false) => b'v', + (KeyCode::W, false) => b'w', + (KeyCode::X, false) => b'x', + (KeyCode::Y, false) => b'y', + (KeyCode::Z, false) => b'z', + (KeyCode::A, true) => b'A', + (KeyCode::B, true) => b'B', + (KeyCode::C, true) => b'C', + (KeyCode::D, true) => b'D', + (KeyCode::E, true) => b'E', + (KeyCode::F, true) => b'F', + (KeyCode::G, true) => b'G', + (KeyCode::H, true) => b'H', + (KeyCode::I, true) => b'I', + (KeyCode::J, true) => b'J', + (KeyCode::K, true) => b'K', + (KeyCode::L, true) => b'L', + (KeyCode::M, true) => b'M', + (KeyCode::N, true) => b'N', + (KeyCode::O, true) => b'O', + (KeyCode::P, true) => b'P', + (KeyCode::Q, true) => b'Q', + (KeyCode::R, true) => b'R', + (KeyCode::S, true) => b'S', + (KeyCode::T, true) => b'T', + (KeyCode::U, true) => b'U', + (KeyCode::V, true) => b'V', + (KeyCode::W, true) => b'W', + (KeyCode::X, true) => b'X', + (KeyCode::Y, true) => b'Y', + (KeyCode::Z, true) => b'Z', + (KeyCode::Kc1, true) => b'!', + (KeyCode::Kc2, true) => b'@', + (KeyCode::Kc3, true) => b'#', + (KeyCode::Kc4, true) => b'$', + (KeyCode::Kc5, true) => b'%', + (KeyCode::Kc6, true) => b'^', + (KeyCode::Kc7, true) => b'&', + (KeyCode::Kc8, true) => b'*', + (KeyCode::Kc9, true) => b'(', + (KeyCode::Kc0, true) => b')', + (KeyCode::Minus, false) => b'-', + (KeyCode::Minus, true) => b'_', + (KeyCode::Equal, false) => b'=', + (KeyCode::Equal, true) => b'+', + (KeyCode::LeftBracket, false) => b'[', + (KeyCode::RightBracket, false) => b']', + (KeyCode::LeftBracket, true) => b'{', + (KeyCode::RightBracket, true) => b'}', + (KeyCode::Semicolon, false) => b';', + (KeyCode::Semicolon, true) => b':', + (KeyCode::Quote, false) => b'\'', + (KeyCode::Quote, true) => b'"', + (KeyCode::Grave, false) => b'`', + (KeyCode::Grave, true) => b'~', + (KeyCode::Backslash, true) => b'\\', + (KeyCode::Backslash, false) => b'|', + (KeyCode::Comma, false) => b',', + (KeyCode::Comma, true) => b'<', + (KeyCode::Dot, false) => b'.', + (KeyCode::Dot, true) => b'>', + (KeyCode::Slash, false) => b'/', + (KeyCode::Slash, true) => b'?', + (KeyCode::Space, false) => b' ', + (KeyCode::Enter, false) => b'\n', + (KeyCode::Tab, false) => b'\t', + (KeyCode::Backspace, false) => b'\x08', + (KeyCode::Escape, false) => b'\x1B', + (KeyCode::Delete, false) => b'\x7F', + // not supported keycodes + (_, _) => b'X', + } +} + +impl From for KeyCode { + fn from(value: u16) -> Self { + match value { + 0x0000 => Self::No, + 0x0001 => Self::ErrorRollover, + 0x0002 => Self::PostFail, + 0x0003 => Self::ErrorUndefined, + 0x0004 => Self::A, + 0x0005 => Self::B, + 0x0006 => Self::C, + 0x0007 => Self::D, + 0x0008 => Self::E, + 0x0009 => Self::F, + 0x000A => Self::G, + 0x000B => Self::H, + 0x000C => Self::I, + 0x000D => Self::J, + 0x000E => Self::K, + 0x000F => Self::L, + 0x0010 => Self::M, + 0x0011 => Self::N, + 0x0012 => Self::O, + 0x0013 => Self::P, + 0x0014 => Self::Q, + 0x0015 => Self::R, + 0x0016 => Self::S, + 0x0017 => Self::T, + 0x0018 => Self::U, + 0x0019 => Self::V, + 0x001A => Self::W, + 0x001B => Self::X, + 0x001C => Self::Y, + 0x001D => Self::Z, + 0x001E => Self::Kc1, + 0x001F => Self::Kc2, + 0x0020 => Self::Kc3, + 0x0021 => Self::Kc4, + 0x0022 => Self::Kc5, + 0x0023 => Self::Kc6, + 0x0024 => Self::Kc7, + 0x0025 => Self::Kc8, + 0x0026 => Self::Kc9, + 0x0027 => Self::Kc0, + 0x0028 => Self::Enter, + 0x0029 => Self::Escape, + 0x002A => Self::Backspace, + 0x002B => Self::Tab, + 0x002C => Self::Space, + 0x002D => Self::Minus, + 0x002E => Self::Equal, + 0x002F => Self::LeftBracket, + 0x0030 => Self::RightBracket, + 0x0031 => Self::Backslash, + 0x0032 => Self::NonusHash, + 0x0033 => Self::Semicolon, + 0x0034 => Self::Quote, + 0x0035 => Self::Grave, + 0x0036 => Self::Comma, + 0x0037 => Self::Dot, + 0x0038 => Self::Slash, + 0x0039 => Self::CapsLock, + 0x003A => Self::F1, + 0x003B => Self::F2, + 0x003C => Self::F3, + 0x003D => Self::F4, + 0x003E => Self::F5, + 0x003F => Self::F6, + 0x0040 => Self::F7, + 0x0041 => Self::F8, + 0x0042 => Self::F9, + 0x0043 => Self::F10, + 0x0044 => Self::F11, + 0x0045 => Self::F12, + 0x0046 => Self::PrintScreen, + 0x0047 => Self::ScrollLock, + 0x0048 => Self::Pause, + 0x0049 => Self::Insert, + 0x004A => Self::Home, + 0x004B => Self::PageUp, + 0x004C => Self::Delete, + 0x004D => Self::End, + 0x004E => Self::PageDown, + 0x004F => Self::Right, + 0x0050 => Self::Left, + 0x0051 => Self::Down, + 0x0052 => Self::Up, + 0x0053 => Self::NumLock, + 0x0054 => Self::KpSlash, + 0x0055 => Self::KpAsterisk, + 0x0056 => Self::KpMinus, + 0x0057 => Self::KpPlus, + 0x0058 => Self::KpEnter, + 0x0059 => Self::Kp1, + 0x005A => Self::Kp2, + 0x005B => Self::Kp3, + 0x005C => Self::Kp4, + 0x005D => Self::Kp5, + 0x005E => Self::Kp6, + 0x005F => Self::Kp7, + 0x0060 => Self::Kp8, + 0x0061 => Self::Kp9, + 0x0062 => Self::Kp0, + 0x0063 => Self::KpDot, + 0x0064 => Self::NonusBackslash, + 0x0065 => Self::Application, + 0x0066 => Self::KbPower, + 0x0067 => Self::KpEqual, + 0x0068 => Self::F13, + 0x0069 => Self::F14, + 0x006A => Self::F15, + 0x006B => Self::F16, + 0x006C => Self::F17, + 0x006D => Self::F18, + 0x006E => Self::F19, + 0x006F => Self::F20, + 0x0070 => Self::F21, + 0x0071 => Self::F22, + 0x0072 => Self::F23, + 0x0073 => Self::F24, + 0x0074 => Self::Execute, + 0x0075 => Self::Help, + 0x0076 => Self::Menu, + 0x0077 => Self::Select, + 0x0078 => Self::Stop, + 0x0079 => Self::Again, + 0x007A => Self::Undo, + 0x007B => Self::Cut, + 0x007C => Self::Copy, + 0x007D => Self::Paste, + 0x007E => Self::Find, + 0x007F => Self::KbMute, + 0x0080 => Self::KbVolumeUp, + 0x0081 => Self::KbVolumeDown, + 0x0082 => Self::LockingCapsLock, + 0x0083 => Self::LockingNumLock, + 0x0084 => Self::LockingScrollLock, + 0x0085 => Self::KpComma, + 0x0086 => Self::KpEqualAs400, + 0x0087 => Self::International1, + 0x0088 => Self::International2, + 0x0089 => Self::International3, + 0x008A => Self::International4, + 0x008B => Self::International5, + 0x008C => Self::International6, + 0x008D => Self::International7, + 0x008E => Self::International8, + 0x008F => Self::International9, + 0x0090 => Self::Language1, + 0x0091 => Self::Language2, + 0x0092 => Self::Language3, + 0x0093 => Self::Language4, + 0x0094 => Self::Language5, + 0x0095 => Self::Language6, + 0x0096 => Self::Language7, + 0x0097 => Self::Language8, + 0x0098 => Self::Language9, + 0x0099 => Self::AlternateErase, + 0x009A => Self::SystemRequest, + 0x009B => Self::Cancel, + 0x009C => Self::Clear, + 0x009D => Self::Prior, + 0x009E => Self::Return, + 0x009F => Self::Separator, + 0x00A0 => Self::Out, + 0x00A1 => Self::Oper, + 0x00A2 => Self::ClearAgain, + 0x00A3 => Self::Crsel, + 0x00A4 => Self::Exsel, + 0x00A5 => Self::SystemPower, + 0x00A6 => Self::SystemSleep, + 0x00A7 => Self::SystemWake, + 0x00A8 => Self::AudioMute, + 0x00A9 => Self::AudioVolUp, + 0x00AA => Self::AudioVolDown, + 0x00AB => Self::MediaNextTrack, + 0x00AC => Self::MediaPrevTrack, + 0x00AD => Self::MediaStop, + 0x00AE => Self::MediaPlayPause, + 0x00AF => Self::MediaSelect, + 0x00B0 => Self::MediaEject, + 0x00B1 => Self::Mail, + 0x00B2 => Self::Calculator, + 0x00B3 => Self::MyComputer, + 0x00B4 => Self::WwwSearch, + 0x00B5 => Self::WwwHome, + 0x00B6 => Self::WwwBack, + 0x00B7 => Self::WwwForward, + 0x00B8 => Self::WwwStop, + 0x00B9 => Self::WwwRefresh, + 0x00BA => Self::WwwFavorites, + 0x00BB => Self::MediaFastForward, + 0x00BC => Self::MediaRewind, + 0x00BD => Self::BrightnessUp, + 0x00BE => Self::BrightnessDown, + 0x00BF => Self::ControlPanel, + 0x00C0 => Self::Assistant, + 0x00C1 => Self::MissionControl, + 0x00C2 => Self::Launchpad, + 0x00CD => Self::MouseUp, + 0x00CE => Self::MouseDown, + 0x00CF => Self::MouseLeft, + 0x00D0 => Self::MouseRight, + 0x00D1 => Self::MouseBtn1, + 0x00D2 => Self::MouseBtn2, + 0x00D3 => Self::MouseBtn3, + 0x00D4 => Self::MouseBtn4, + 0x00D5 => Self::MouseBtn5, + 0x00D6 => Self::MouseBtn6, + 0x00D7 => Self::MouseBtn7, + 0x00D8 => Self::MouseBtn8, + 0x00D9 => Self::MouseWheelUp, + 0x00DA => Self::MouseWheelDown, + 0x00DB => Self::MouseWheelLeft, + 0x00DC => Self::MouseWheelRight, + 0x00DD => Self::MouseAccel0, + 0x00DE => Self::MouseAccel1, + 0x00DF => Self::MouseAccel2, + 0x00E0 => Self::LCtrl, + 0x00E1 => Self::LShift, + 0x00E2 => Self::LAlt, + 0x00E3 => Self::LGui, + 0x00E4 => Self::RCtrl, + 0x00E5 => Self::RShift, + 0x00E6 => Self::RAlt, + 0x00E7 => Self::RGui, + 0x500 => Self::Macro0, + 0x501 => Self::Macro1, + 0x502 => Self::Macro2, + 0x503 => Self::Macro3, + 0x504 => Self::Macro4, + 0x505 => Self::Macro5, + 0x506 => Self::Macro6, + 0x507 => Self::Macro7, + 0x508 => Self::Macro8, + 0x509 => Self::Macro9, + 0x50A => Self::Macro10, + 0x50B => Self::Macro11, + 0x50C => Self::Macro12, + 0x50D => Self::Macro13, + 0x50E => Self::Macro14, + 0x50F => Self::Macro15, + 0x510 => Self::Macro16, + 0x511 => Self::Macro17, + 0x512 => Self::Macro18, + 0x513 => Self::Macro19, + 0x514 => Self::Macro20, + 0x515 => Self::Macro21, + 0x516 => Self::Macro22, + 0x517 => Self::Macro23, + 0x518 => Self::Macro24, + 0x519 => Self::Macro25, + 0x51A => Self::Macro26, + 0x51B => Self::Macro27, + 0x51C => Self::Macro28, + 0x51D => Self::Macro29, + 0x51E => Self::Macro30, + 0x51F => Self::Macro31, + 0x600 => Self::BacklightOn, + 0x601 => Self::BacklightOff, + 0x602 => Self::BacklightToggle, + 0x603 => Self::BacklightDown, + 0x604 => Self::BacklightUp, + 0x605 => Self::BacklightStep, + 0x606 => Self::BacklightToggleBreathing, + 0x620 => Self::RgbTog, + 0x621 => Self::RgbModeForward, + 0x622 => Self::RgbModeReverse, + 0x623 => Self::RgbHui, + 0x624 => Self::RgbHud, + 0x625 => Self::RgbSai, + 0x626 => Self::RgbSad, + 0x627 => Self::RgbVai, + 0x628 => Self::RgbVad, + 0x629 => Self::RgbSpi, + 0x62A => Self::RgbSpd, + 0x62B => Self::RgbModePlain, + 0x62C => Self::RgbModeBreathe, + 0x62D => Self::RgbModeRainbow, + 0x62E => Self::RgbModeSwirl, + 0x62F => Self::RgbModeSnake, + 0x630 => Self::RgbModeKnight, + 0x631 => Self::RgbModeXmas, + 0x632 => Self::RgbModeGradient, + 0x633 => Self::RgbModeRgbtest, + 0x634 => Self::RgbModeTwinkle, + 0x700 => Self::Bootloader, + 0x701 => Self::Reboot, + 0x702 => Self::DebugToggle, + 0x703 => Self::ClearEeprom, + 0x716 => Self::GraveEscape, + 0x720 => Self::OutputAuto, + 0x721 => Self::OutputUsb, + 0x722 => Self::OutputBluetooth, + 0x750 => Self::ComboOn, + 0x751 => Self::ComboOff, + 0x752 => Self::ComboToggle, + 0x773 => Self::CapsWordToggle, + 0x777 => Self::TriLayerLower, + 0x778 => Self::TriLayerUpper, + 0x779 => Self::RepeatKey, + 0x77A => Self::AltRepeatKey, + 0x840 => Self::User0, + 0x841 => Self::User1, + 0x842 => Self::User2, + 0x843 => Self::User3, + 0x844 => Self::User4, + 0x845 => Self::User5, + 0x846 => Self::User6, + 0x847 => Self::User7, + 0x848 => Self::User8, + 0x849 => Self::User9, + 0x84A => Self::User10, + 0x84B => Self::User11, + 0x84C => Self::User12, + 0x84D => Self::User13, + 0x84E => Self::User14, + 0x84F => Self::User15, + 0x850 => Self::User16, + 0x851 => Self::User17, + 0x852 => Self::User18, + 0x853 => Self::User19, + 0x854 => Self::User20, + 0x855 => Self::User21, + 0x856 => Self::User22, + 0x857 => Self::User23, + 0x858 => Self::User24, + 0x859 => Self::User25, + 0x85A => Self::User26, + 0x85B => Self::User27, + 0x85C => Self::User28, + 0x85D => Self::User29, + 0x85E => Self::User30, + 0x85F => Self::User31, + _ => Self::No, + } + } +} + +/// Keys in consumer page +/// Ref: +#[non_exhaustive] +#[repr(u16)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, FromRepr)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ConsumerKey { + No = 0x00, + // 15.5 Display Controls + SnapShot = 0x65, + /// + BrightnessUp = 0x6F, + BrightnessDown = 0x70, + // 15.7 Transport Controls + Play = 0xB0, + Pause = 0xB1, + Record = 0xB2, + FastForward = 0xB3, + Rewind = 0xB4, + NextTrack = 0xB5, + PrevTrack = 0xB6, + StopPlay = 0xB7, + Eject = 0xB8, + RandomPlay = 0xB9, + Repeat = 0xBC, + StopEject = 0xCC, + PlayPause = 0xCD, + // 15.9.1 Audio Controls - Volume + Mute = 0xE2, + VolumeIncrement = 0xE9, + VolumeDecrement = 0xEA, + Reserved = 0xEB, + // 15.15 Application Launch Buttons + Email = 0x18A, + Calculator = 0x192, + LocalBrowser = 0x194, + Lock = 0x19E, + ControlPanel = 0x19F, + Assistant = 0x1CB, + // 15.16 Generic GUI Application Controls + New = 0x201, + Open = 0x202, + Close = 0x203, + Exit = 0x204, + Maximize = 0x205, + Minimize = 0x206, + Save = 0x207, + Print = 0x208, + Properties = 0x209, + Undo = 0x21A, + Copy = 0x21B, + Cut = 0x21C, + Paste = 0x21D, + SelectAll = 0x21E, + Find = 0x21F, + Search = 0x221, + Home = 0x223, + Back = 0x224, + Forward = 0x225, + Stop = 0x226, + Refresh = 0x227, + Bookmarks = 0x22A, + NextKeyboardLayoutSelect = 0x29D, + DesktopShowAllWindows = 0x29F, + AcSoftKeyLeft = 0x2A0, +} + +impl ::postcard::experimental::max_size::MaxSize for ConsumerKey { + const POSTCARD_MAX_SIZE: usize = 3usize; +} + +impl From for ConsumerKey { + fn from(value: u16) -> Self { + match value { + 0x00 => Self::No, + 0x65 => Self::SnapShot, + 0x6F => Self::BrightnessUp, + 0x70 => Self::BrightnessDown, + 0xB0 => Self::Play, + 0xB1 => Self::Pause, + 0xB2 => Self::Record, + 0xB3 => Self::FastForward, + 0xB4 => Self::Rewind, + 0xB5 => Self::NextTrack, + 0xB6 => Self::PrevTrack, + 0xB7 => Self::StopPlay, + 0xB8 => Self::Eject, + 0xB9 => Self::RandomPlay, + 0xBC => Self::Repeat, + 0xCC => Self::StopEject, + 0xCD => Self::PlayPause, + 0xE2 => Self::Mute, + 0xE9 => Self::VolumeIncrement, + 0xEA => Self::VolumeDecrement, + 0xEB => Self::Reserved, + 0x18A => Self::Email, + 0x192 => Self::Calculator, + 0x194 => Self::LocalBrowser, + 0x19E => Self::Lock, + 0x19F => Self::ControlPanel, + 0x1CB => Self::Assistant, + 0x201 => Self::New, + 0x202 => Self::Open, + 0x203 => Self::Close, + 0x204 => Self::Exit, + 0x205 => Self::Maximize, + 0x206 => Self::Minimize, + 0x207 => Self::Save, + 0x208 => Self::Print, + 0x209 => Self::Properties, + 0x21A => Self::Undo, + 0x21B => Self::Copy, + 0x21C => Self::Cut, + 0x21D => Self::Paste, + 0x21E => Self::SelectAll, + 0x21F => Self::Find, + 0x221 => Self::Search, + 0x223 => Self::Home, + 0x224 => Self::Back, + 0x225 => Self::Forward, + 0x226 => Self::Stop, + 0x227 => Self::Refresh, + 0x22A => Self::Bookmarks, + 0x29D => Self::NextKeyboardLayoutSelect, + 0x29F => Self::DesktopShowAllWindows, + 0x2A0 => Self::AcSoftKeyLeft, + _ => Self::No, + } + } +} + +/// Keys in `Generic Desktop Page`, generally used for system control +/// Ref: +#[non_exhaustive] +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, FromRepr)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum SystemControlKey { + No = 0x00, + PowerDown = 0x81, + Sleep = 0x82, + WakeUp = 0x83, + Restart = 0x8F, +} + +impl ::postcard::experimental::max_size::MaxSize for SystemControlKey { + const POSTCARD_MAX_SIZE: usize = 1usize; +} + +impl From for SystemControlKey { + fn from(value: u16) -> Self { + match value { + 0x00 => Self::No, + 0x81 => Self::PowerDown, + 0x82 => Self::Sleep, + 0x83 => Self::WakeUp, + 0x8F => Self::Restart, + _ => Self::No, + } + } +} diff --git a/rmk/src/host/via/keycode_convert.rs b/rmk/src/host/via/keycode_convert.rs index c3ee073dd..3dac04ffe 100644 --- a/rmk/src/host/via/keycode_convert.rs +++ b/rmk/src/host/via/keycode_convert.rs @@ -1,5 +1,5 @@ -use rmk_types::action::{Action, KeyAction}; -use rmk_types::keycode::KeyCode; +use rmk_types::action::{Action, KeyAction, KeyboardAction}; +use rmk_types::keycode::{KeyCode, SpecialKey}; use rmk_types::modifier::ModifierCombination; pub(crate) fn to_via_keycode(key_action: KeyAction) -> u16 { @@ -7,29 +7,38 @@ pub(crate) fn to_via_keycode(key_action: KeyAction) -> u16 { KeyAction::No => 0x0000, KeyAction::Transparent => 0x0001, KeyAction::Single(a) => match a { - Action::Key(KeyCode::GraveEscape) => 0x7c16, - Action::Key(KeyCode::RepeatKey) => 0x7c79, - Action::Key(KeyCode::CapsWordToggle) => 0x7c73, - Action::Key(KeyCode::TriLayerLower) => 0x7c77, - Action::Key(KeyCode::TriLayerUpper) => 0x7c78, - Action::Key(k) => { - if k.is_macro() { - k as u16 & 0xFF | 0x7700 - } else if k.is_user() { - k as u16 & 0xF | 0x7E00 - } else if k.is_combo() || k.is_boot() { - // is_rmk() 's subset - k as u16 & 0xFF | 0x7C00 + Action::Key(k) => match k { + KeyCode::Hid(hid_keycode) => hid_keycode as u16, + // Consumer and SystemControl keys are automatically converted to HID keycodes + // which are natively supported in VIA protocol + KeyCode::Consumer(consumer_key) => { + if let Some(hid_keycode) = consumer_key.to_hid_keycode() { + hid_keycode as u16 + } else { + warn!("Consumer key {:?} has no corresponding HID keycode for VIA", consumer_key); + 0 + } + } + KeyCode::SystemControl(system_key) => { + if let Some(hid_keycode) = system_key.to_hid_keycode() { + hid_keycode as u16 + } else { + warn!("SystemControl key {:?} has no corresponding HID keycode for VIA", system_key); + 0 + } + } + }, + Action::KeyWithModifier(k, m) => { + if let KeyCode::Hid(hid_keycode) = k { + ((m.into_packed_bits() as u16) << 8) | hid_keycode as u16 } else { - k as u16 + 0 } } - Action::KeyWithModifier(k, m) => ((m.into_packed_bits() as u16) << 8) | k as u16, Action::LayerToggleOnly(l) => 0x5200 | l as u16, Action::LayerOn(l) => 0x5220 | l as u16, Action::DefaultLayer(l) => 0x5240 | l as u16, Action::LayerToggle(l) => 0x5260 | l as u16, - // convert to KeyCode::Macro0 - Macro31, 0x0 for above (as 0x600 is already reserved) Action::TriggerMacro(idx) => { // if idx < 32 { 0x7700 + (idx as u16) @@ -53,7 +62,29 @@ pub(crate) fn to_via_keycode(key_action: KeyAction) -> u16 { 0 } } - _ => 0x0000, + Action::Keyboard(keyboard_action) => match keyboard_action { + KeyboardAction::Bootloader => 0x7c00, + KeyboardAction::Reboot => 0x7c01, + KeyboardAction::ComboOn => 0x7c50, + KeyboardAction::ComboOff => 0x7c51, + KeyboardAction::ComboToggle => 0x7c52, + KeyboardAction::CapsWordToggle => 0x7c73, + KeyboardAction::TriLayerLower => 0x7c77, + KeyboardAction::TriLayerUpper => 0x7c78, + _ => { + warn!("KeyboardAction: {:?} vial is not supported yet", keyboard_action); + 0 + } + }, + Action::Special(special_key) => match special_key { + SpecialKey::GraveEscape => 0x7c16, + SpecialKey::Repeat => 0x7c79, + }, + Action::User(id) => (id as u16 & 0xF) | 0x7E00, + _ => { + warn!("Action: {:?} in vial is not supported yet", a); + 0 + } }, KeyAction::Tap(_) => { warn!("Tap action is not supported by via"); @@ -65,7 +96,7 @@ pub(crate) fn to_via_keycode(key_action: KeyAction) -> u16 { 0 } else { let keycode = match tap { - Action::Key(k) => k as u16, + Action::Key(KeyCode::Hid(k)) => k as u16, _ => 0, }; 0x4000 | ((l as u16) << 8) | keycode @@ -73,7 +104,7 @@ pub(crate) fn to_via_keycode(key_action: KeyAction) -> u16 { } Action::Modifier(m) => { let keycode = match tap { - Action::Key(k) => k as u16, + Action::Key(KeyCode::Hid(k)) => k as u16, _ => 0, }; 0x2000 | ((m.into_packed_bits() as u16) << 8) | keycode @@ -92,23 +123,23 @@ pub(crate) fn from_via_keycode(via_keycode: u16) -> KeyAction { match via_keycode { 0x0000 => KeyAction::No, 0x0001 => KeyAction::Transparent, - 0x0002..=0x00FF => KeyAction::Single(Action::Key(via_keycode.into())), + 0x0002..=0x00FF => KeyAction::Single(Action::Key(KeyCode::Hid((via_keycode as u8).into()))), 0x0100..=0x1FFF => { // WithModifier - let keycode = (via_keycode & 0x00FF).into(); + let keycode = KeyCode::Hid((via_keycode as u8).into()); let modifier = ModifierCombination::from_packed_bits((via_keycode >> 8) as u8); KeyAction::Single(Action::KeyWithModifier(keycode, modifier)) } 0x2000..=0x3FFF => { // Modifier tap-hold. - let keycode = (via_keycode & 0x00FF).into(); + let keycode = KeyCode::Hid((via_keycode as u8).into()); let modifier = ModifierCombination::from_packed_bits(((via_keycode >> 8) & 0b11111) as u8); KeyAction::TapHold(Action::Key(keycode), Action::Modifier(modifier), Default::default()) } 0x4000..=0x4FFF => { // Layer tap-hold. let layer = (via_keycode >> 8) & 0xF; - let keycode = (via_keycode & 0x00FF).into(); + let keycode = KeyCode::Hid((via_keycode as u8).into()); KeyAction::TapHold(Action::Key(keycode), Action::LayerOn(layer as u8), Default::default()) } 0x5000..=0x51FF => { @@ -163,26 +194,24 @@ pub(crate) fn from_via_keycode(via_keycode: u16) -> KeyAction { } 0x7700..=0x771F => { // Macro - let keycode = via_keycode & 0xFF | 0x500; - KeyAction::Single(Action::Key(keycode.into())) + let id = via_keycode as u8 & 0x1F; + KeyAction::Single(Action::TriggerMacro(id)) } 0x7800..=0x783F => { // TODO: backlight and rgb configuration warn!("Backlight and RGB configuration key not supported"); KeyAction::No } - // boot related | combo related - 0x7C00..=0x7C01 | 0x7C50..=0x7C52 => { - // is_rmk() 's related - let keycode = via_keycode & 0xFF | 0x700; - KeyAction::Single(Action::Key(keycode.into())) - } - // GraveEscape - 0x7C16 => KeyAction::Single(Action::Key(KeyCode::GraveEscape)), - // RepeatKey - 0x7C79 => KeyAction::Single(Action::Key(KeyCode::RepeatKey)), - // Caps Word - 0x7C73 => KeyAction::Single(Action::Key(KeyCode::CapsWordToggle)), + 0x7C00 => KeyAction::Single(Action::Keyboard(KeyboardAction::Bootloader)), + 0x7C01 => KeyAction::Single(Action::Keyboard(KeyboardAction::Reboot)), + 0x7C50 => KeyAction::Single(Action::Keyboard(KeyboardAction::ComboOn)), + 0x7C51 => KeyAction::Single(Action::Keyboard(KeyboardAction::ComboOff)), + 0x7C52 => KeyAction::Single(Action::Keyboard(KeyboardAction::ComboToggle)), + 0x7C16 => KeyAction::Single(Action::Special(SpecialKey::GraveEscape)), + 0x7C73 => KeyAction::Single(Action::Keyboard(KeyboardAction::CapsWordToggle)), + 0x7C77 => KeyAction::Single(Action::Keyboard(KeyboardAction::TriLayerLower)), + 0x7C78 => KeyAction::Single(Action::Keyboard(KeyboardAction::TriLayerUpper)), + 0x7C79 => KeyAction::Single(Action::Special(SpecialKey::Repeat)), 0x7C00..=0x7C5F => { // TODO: Reset/Space Cadet/Haptic/Auto shift(AS)/Dynamic macro // - [Space Cadet](https://docs.qmk.fm/#/feature_space_cadet) @@ -192,14 +221,9 @@ pub(crate) fn from_via_keycode(via_keycode: u16) -> KeyAction { ); KeyAction::No } - // TriLayer Lower - 0x7C77 => KeyAction::Single(Action::Key(KeyCode::TriLayerLower)), - // TriLayer Upper - 0x7C78 => KeyAction::Single(Action::Key(KeyCode::TriLayerUpper)), 0x7E00..=0x7E0F => { // QK_KB_N, aka UserN - let keycode = via_keycode & 0xFF | 0x840; - KeyAction::Single(Action::Key(keycode.into())) + KeyAction::Single(Action::User(via_keycode as u8 & 0xF)) } _ => { warn!("Via keycode {:#X} is not processed", via_keycode); @@ -211,21 +235,21 @@ pub(crate) fn from_via_keycode(via_keycode: u16) -> KeyAction { #[cfg(test)] mod test { use super::*; - use crate::types::keycode::{from_ascii, to_ascii}; + use rmk_types::keycode::HidKeyCode; #[test] fn test_convert_via_keycode_to_key_action() { // A let via_keycode = 0x04; assert_eq!( - KeyAction::Single(Action::Key(KeyCode::A)), + KeyAction::Single(Action::Key(KeyCode::Hid(HidKeyCode::A))), from_via_keycode(via_keycode) ); // Right shift let via_keycode = 0xE5; assert_eq!( - KeyAction::Single(Action::Key(KeyCode::RShift)), + KeyAction::Single(Action::Key(KeyCode::Hid(HidKeyCode::RShift))), from_via_keycode(via_keycode) ); @@ -292,14 +316,14 @@ mod test { // LT0(A) -> LayerTapHold(A, 0) let via_keycode = 0x4004; assert_eq!( - KeyAction::TapHold(Action::Key(KeyCode::A), Action::LayerOn(0), Default::default()), + KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::LayerOn(0), Default::default()), from_via_keycode(via_keycode) ); // LT3(A) -> LayerTapHold(A, 3) let via_keycode = 0x4304; assert_eq!( - KeyAction::TapHold(Action::Key(KeyCode::A), Action::LayerOn(3), Default::default()), + KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::LayerOn(3), Default::default()), from_via_keycode(via_keycode) ); @@ -307,7 +331,7 @@ mod test { let via_keycode = 0x2604; assert_eq!( KeyAction::TapHold( - Action::Key(KeyCode::A), + Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::Modifier(ModifierCombination::new_from(false, false, true, true, false)), Default::default(), ), //hrm @@ -318,7 +342,7 @@ mod test { let via_keycode = 0x3D05; assert_eq!( KeyAction::TapHold( - Action::Key(KeyCode::B), + Action::Key(KeyCode::Hid(HidKeyCode::B)), Action::Modifier(ModifierCombination::new_from(true, true, true, false, true)), Default::default(), ), @@ -329,7 +353,7 @@ mod test { let via_keycode: u16 = 0x2F04; assert_eq!( KeyAction::TapHold( - Action::Key(KeyCode::A), + Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::Modifier(ModifierCombination::new_from(false, true, true, true, true)), Default::default(), ), //hrm @@ -340,7 +364,7 @@ mod test { let via_keycode = 0x2705; assert_eq!( KeyAction::TapHold( - Action::Key(KeyCode::B), + Action::Key(KeyCode::Hid(HidKeyCode::B)), Action::Modifier(ModifierCombination::new_from(false, false, true, true, true)), Default::default(), ), @@ -367,21 +391,21 @@ mod test { // ComboOff let via_keycode = 0x7C51; assert_eq!( - KeyAction::Single(Action::Key(KeyCode::ComboOff)), + KeyAction::Single(Action::Keyboard(KeyboardAction::ComboOff)), from_via_keycode(via_keycode) ); // GraveEscape let via_keycode = 0x7C16; assert_eq!( - KeyAction::Single(Action::Key(KeyCode::GraveEscape)), + KeyAction::Single(Action::Special(SpecialKey::GraveEscape)), from_via_keycode(via_keycode) ); // RepeatKey let via_keycode = 0x7C79; assert_eq!( - KeyAction::Single(Action::Key(KeyCode::RepeatKey)), + KeyAction::Single(Action::Special(SpecialKey::Repeat)), from_via_keycode(via_keycode) ); @@ -400,12 +424,14 @@ mod test { #[test] fn test_convert_key_action_to_via_keycode() { + use rmk_types::keycode::HidKeyCode; + // A - let a = KeyAction::Single(Action::Key(KeyCode::A)); + let a = KeyAction::Single(Action::Key(KeyCode::Hid(HidKeyCode::A))); assert_eq!(0x04, to_via_keycode(a)); // Right shift - let a = KeyAction::Single(Action::Key(KeyCode::RShift)); + let a = KeyAction::Single(Action::Key(KeyCode::Hid(HidKeyCode::RShift))); assert_eq!(0xE5, to_via_keycode(a)); // Mo(3) @@ -424,43 +450,43 @@ mod test { // LCtrl(A) -> WithModifier(A) let a = KeyAction::Single(Action::KeyWithModifier( - KeyCode::A, + KeyCode::Hid(HidKeyCode::A), ModifierCombination::new_from(false, false, false, false, true), )); assert_eq!(0x104, to_via_keycode(a)); // RCtrl(A) -> WithModifier(A) let a = KeyAction::Single(Action::KeyWithModifier( - KeyCode::A, + KeyCode::Hid(HidKeyCode::A), ModifierCombination::new_from(true, false, false, false, true), )); assert_eq!(0x1104, to_via_keycode(a)); // Meh(A) -> WithModifier(A) let a = KeyAction::Single(Action::KeyWithModifier( - KeyCode::A, + KeyCode::Hid(HidKeyCode::A), ModifierCombination::new_from(false, false, true, true, true), )); assert_eq!(0x704, to_via_keycode(a)); // Hypr(A) -> WithModifier(A) let a = KeyAction::Single(Action::KeyWithModifier( - KeyCode::A, + KeyCode::Hid(HidKeyCode::A), ModifierCombination::new_from(false, true, true, true, true), )); assert_eq!(0xF04, to_via_keycode(a)); // LT0(A) -> LayerTapHold(A, 0) - let a = KeyAction::TapHold(Action::Key(KeyCode::A), Action::LayerOn(0), Default::default()); + let a = KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::LayerOn(0), Default::default()); assert_eq!(0x4004, to_via_keycode(a)); // LT3(A) -> LayerTapHold(A, 3) - let a = KeyAction::TapHold(Action::Key(KeyCode::A), Action::LayerOn(3), Default::default()); + let a = KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::LayerOn(3), Default::default()); assert_eq!(0x4304, to_via_keycode(a)); // LSA_T(A) -> let a = KeyAction::TapHold( - Action::Key(KeyCode::A), + Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::Modifier(ModifierCombination::new_from(false, false, true, true, false)), Default::default(), ); @@ -468,7 +494,7 @@ mod test { // RCAG_T(A) -> let a = KeyAction::TapHold( - Action::Key(KeyCode::A), + Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::Modifier(ModifierCombination::new_from(true, true, true, false, true)), Default::default(), ); @@ -476,7 +502,7 @@ mod test { // ALL_T(A) -> let a = KeyAction::TapHold( - Action::Key(KeyCode::A), + Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::Modifier(ModifierCombination::new_from(false, true, true, true, true)), Default::default(), ); @@ -484,7 +510,7 @@ mod test { // Meh_T(A) -> let a = KeyAction::TapHold( - Action::Key(KeyCode::A), + Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::Modifier(ModifierCombination::new_from(false, false, true, true, true)), Default::default(), ); @@ -502,15 +528,15 @@ mod test { assert_eq!(0x5039, to_via_keycode(a)); // ComboOff - let a = KeyAction::Single(Action::Key(KeyCode::ComboOff)); + let a = KeyAction::Single(Action::Keyboard(KeyboardAction::ComboOff)); assert_eq!(0x7C51, to_via_keycode(a)); // GraveEscape - let a = KeyAction::Single(Action::Key(KeyCode::GraveEscape)); + let a = KeyAction::Single(Action::Special(SpecialKey::GraveEscape)); assert_eq!(0x7C16, to_via_keycode(a)); // RepeatKey - let a = KeyAction::Single(Action::Key(KeyCode::RepeatKey)); + let a = KeyAction::Single(Action::Special(SpecialKey::Repeat)); assert_eq!(0x7C79, to_via_keycode(a)); // Morse @@ -524,9 +550,42 @@ mod test { assert_eq!(0x57FF, to_via_keycode(a)); } + #[test] + fn test_convert_consumer_system_keys_to_via() { + use rmk_types::keycode::{ConsumerKey, SystemControlKey}; + + // Test Consumer keys conversion + // AudioMute (ConsumerKey::Mute) -> HidKeyCode::AudioMute (0xA8) + let a = KeyAction::Single(Action::Key(KeyCode::Consumer(ConsumerKey::Mute))); + assert_eq!(0xA8, to_via_keycode(a)); + + // PlayPause (ConsumerKey::PlayPause) -> HidKeyCode::MediaPlayPause (0xAE) + let a = KeyAction::Single(Action::Key(KeyCode::Consumer(ConsumerKey::PlayPause))); + assert_eq!(0xAE, to_via_keycode(a)); + + // VolumeIncrement (ConsumerKey::VolumeIncrement) -> HidKeyCode::AudioVolUp (0xA9) + let a = KeyAction::Single(Action::Key(KeyCode::Consumer(ConsumerKey::VolumeIncrement))); + assert_eq!(0xA9, to_via_keycode(a)); + + // Test SystemControl keys conversion + // PowerDown (SystemControlKey::PowerDown) -> HidKeyCode::SystemPower (0xA5) + let a = KeyAction::Single(Action::Key(KeyCode::SystemControl(SystemControlKey::PowerDown))); + assert_eq!(0xA5, to_via_keycode(a)); + + // Sleep (SystemControlKey::Sleep) -> HidKeyCode::SystemSleep (0xA6) + let a = KeyAction::Single(Action::Key(KeyCode::SystemControl(SystemControlKey::Sleep))); + assert_eq!(0xA6, to_via_keycode(a)); + + // WakeUp (SystemControlKey::WakeUp) -> HidKeyCode::SystemWake (0xA7) + let a = KeyAction::Single(Action::Key(KeyCode::SystemControl(SystemControlKey::WakeUp))); + assert_eq!(0xA7, to_via_keycode(a)); + } + #[test] fn test_convert_from_to_ascii_a() { - let keycode = KeyCode::A; + use rmk_types::keycode::{from_ascii, to_ascii, HidKeyCode}; + + let keycode = HidKeyCode::A; let shifted = false; let ascii = b'a'; @@ -535,7 +594,9 @@ mod test { } #[test] fn test_convert_from_to_ascii_K() { - let keycode = KeyCode::K; + use rmk_types::keycode::{from_ascii, to_ascii, HidKeyCode}; + + let keycode = HidKeyCode::K; let shifted = true; let ascii = b'K'; diff --git a/rmk/src/keyboard.rs b/rmk/src/keyboard.rs index f27be97f6..9a164162f 100644 --- a/rmk/src/keyboard.rs +++ b/rmk/src/keyboard.rs @@ -7,8 +7,8 @@ use embassy_futures::yield_now; use embassy_sync::signal::Signal; use embassy_time::{Duration, Instant, Timer, with_deadline}; use heapless::Vec; -use rmk_types::action::{Action, KeyAction, MorseMode}; -use rmk_types::keycode::KeyCode; +use rmk_types::action::{Action, KeyAction, KeyboardAction, MorseMode}; +use rmk_types::keycode::{ConsumerKey, HidKeyCode, KeyCode, SpecialKey, SystemControlKey}; use rmk_types::led_indicator::LedIndicator; use rmk_types::modifier::ModifierCombination; use rmk_types::mouse_button::MouseButtons; @@ -137,7 +137,7 @@ impl CapsWordState { /// Check whether to shift the given key, and update the state accordingly /// /// Note that this function does not check the CapsWord key itself. - fn check(&mut self, key: KeyCode) { + fn check(&mut self, key: HidKeyCode) { if let CapsWordState::Activated { timer, shift_current } = self { if key.is_caps_word_continue_key() && timer.elapsed() < Self::TIMEOUT { *timer = Instant::now(); @@ -224,7 +224,7 @@ pub struct Keyboard<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usi held_modifiers: ModifierCombination, /// The held keys for the keyboard hid report, except the modifiers - held_keycodes: [KeyCode; 6], + held_keycodes: [HidKeyCode; 6], /// Registered key position. /// This is still needed besides `held_keycodes` because multiple keys with same keycode can be registered. @@ -273,7 +273,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E held_buffer: HeldBuffer::new(), registered_keys: [None; 6], held_modifiers: ModifierCombination::default(), - held_keycodes: [KeyCode::No; 6], + held_keycodes: [HidKeyCode::No; 6], mouse_report: MouseReport { buttons: 0, x: 0, @@ -283,7 +283,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E }, media_report: MediaKeyboardReport { usage_id: 0 }, system_control_report: SystemControlReport { usage_id: 0 }, - last_key_code: KeyCode::No, + last_key_code: KeyCode::Hid(HidKeyCode::No), mouse_accel: 0, mouse_repeat: 0, mouse_wheel_repeat: 0, @@ -1207,6 +1207,10 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E self.update_osl(event); } Action::OneShotKey(_k) => warn!("One-shot key is not supported: {:?}", action), + Action::Light(_light_action) => warn!("Light controll is not supported"), + Action::Keyboard(keyboard_action) => self.process_action_keyboard_control(keyboard_action, event).await, + Action::Special(special_key) => self.process_action_special(special_key, event).await, + Action::User(id) => self.process_user(id, event).await, } } @@ -1396,7 +1400,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E } // Process a basic keypress/release and also take care of applying one shot modifiers - async fn process_basic(&mut self, key: KeyCode, event: KeyboardEvent) { + async fn process_hid_keycode(&mut self, key: HidKeyCode, event: KeyboardEvent) { if event.pressed { self.register_key(key, event); } else { @@ -1406,76 +1410,113 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E self.send_keyboard_report_with_resolved_modifiers(event.pressed).await; } - // Process action key - async fn process_action_key(&mut self, key: KeyCode, event: KeyboardEvent) { - if matches!(key, KeyCode::TriLayerLower | KeyCode::TriLayerUpper) { - // Check tri-layer first - let layer = if key == KeyCode::TriLayerLower { 1 } else { 2 }; - self.process_action_layer_switch(layer, event); - self.keymap.borrow_mut().update_fn_layer_state(); - return; - } - let key = match key { - KeyCode::GraveEscape => { - if self.held_modifiers.into_bits() == 0 { - KeyCode::Escape + // Process action special keys + async fn process_action_special(&mut self, key: SpecialKey, event: KeyboardEvent) { + match key { + SpecialKey::GraveEscape => { + let hid_keycode = if self.held_modifiers.into_bits() == 0 { + HidKeyCode::Escape } else { - KeyCode::Grave - } + HidKeyCode::Grave + }; + self.process_hid_keycode(hid_keycode, event).await; } - KeyCode::CapsWordToggle => { - // Handle Caps Word keycode + SpecialKey::Repeat => { + debug!("Repeat last key code: {:?} , {:?}", self.last_key_code, event); + let key = self.last_key_code; + self.process_action_key(key, event).await; + } + }; + } + + async fn process_action_keyboard_control(&mut self, keyboard_control: KeyboardAction, event: KeyboardEvent) { + match keyboard_control { + KeyboardAction::TriLayerLower => { + // Tri-layer lower, turn layer 1 on and update layer state + self.process_action_layer_switch(1, event); + self.keymap.borrow_mut().update_fn_layer_state(); + } + KeyboardAction::TriLayerUpper => { + // Tri-layer upper, turn layer 2 on and update layer state + self.process_action_layer_switch(2, event); + self.keymap.borrow_mut().update_fn_layer_state(); + } + KeyboardAction::CapsWordToggle => { + // Handle Caps Word if event.pressed { self.caps_word.toggle(); }; - return; } - KeyCode::Again => { - debug!("Repeat last key code: {:?} , {:?}", self.last_key_code, event); - self.last_key_code + KeyboardAction::ComboOn => self.combo_on = true, + KeyboardAction::ComboOff => self.combo_on = false, + KeyboardAction::ComboToggle => self.combo_on = !self.combo_on, + KeyboardAction::Bootloader => { + // When releasing the key, process the boot action + if !event.pressed { + boot::jump_to_bootloader(); + } + } + KeyboardAction::Reboot => { + // When releasing the key, process the boot action + if !event.pressed { + boot::reboot_keyboard(); + } } - _ => key, - }; + _ => warn!("KeyboardAction: {:?} is not supported yet", keyboard_control), + } + } + + // Process action key + async fn process_action_key(&mut self, mut key: KeyCode, event: KeyboardEvent) { + // Process `Again` key first. + // Not all platform support `Again` key, so we manually repeat it for users. + if key == KeyCode::Hid(HidKeyCode::Again) { + debug!("Repeat(Again) last key code: {:?} , {:?}", self.last_key_code, event); + key = self.last_key_code; + } + + // Pre-check if event.pressed { - // Record last press time - if key.is_simple_key() { - // Records only the simple key - self.last_press_time = Instant::now(); + if let KeyCode::Hid(hid_keycode) = key { + // Check hid keycodes + // Record last press time + if hid_keycode.is_simple_key() { + // Records only the simple key + self.last_press_time = Instant::now(); + } + + // Update last key code + if hid_keycode != HidKeyCode::Again { + debug!( + "Last key code changed from {:?} to {:?}(pressed: {:?})", + self.last_key_code, key, event.pressed + ); + self.last_key_code = key; + } + + // Check Caps Word + self.caps_word.check(hid_keycode); } - // Check repeat key - if key != KeyCode::Again { - debug!( - "Last key code changed from {:?} to {:?}(pressed: {:?})", - self.last_key_code, key, event.pressed - ); - self.last_key_code = key; + } + + match key { + KeyCode::Hid(hid_keycode) => { + if let Some(consumer) = hid_keycode.process_as_consumer() { + self.process_action_consumer_control(consumer, event).await + } else if let Some(system_control) = hid_keycode.process_as_system_control() { + self.process_action_system_control(system_control, event).await + } else if hid_keycode.is_mouse_key() { + self.process_action_mouse(hid_keycode, event).await; + } else { + // Basic keycodes + self.process_hid_keycode(hid_keycode, event).await + } } - // Check Caps Word - self.caps_word.check(key); - } - - // Consumer, system and mouse keys should be processed before basic keycodes, since basic keycodes contain them all - if key.is_consumer() { - self.process_action_consumer_control(key, event).await; - } else if key.is_system() { - self.process_action_system_control(key, event).await; - } else if key.is_mouse_key() { - self.process_action_mouse(key, event).await; - } else if key.is_basic() { - self.process_basic(key, event).await; - } else if key.is_user() { - self.process_user(key, event).await; - } else if key.is_macro() { - // Process macro - self.process_action_macro(key, event).await; - } else if key.is_combo() { - self.process_action_combo(key, event).await; - } else if key.is_boot() { - self.process_boot(key, event); - } else { - warn!("Unsupported key: {:?}", key); + KeyCode::Consumer(consumer) => self.process_action_consumer_control(consumer, event).await, + KeyCode::SystemControl(system_control) => self.process_action_system_control(system_control, event).await, } + self.update_osm(event); self.update_osl(event); } @@ -1494,279 +1535,265 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E async fn process_action_combo(&mut self, key: KeyCode, event: KeyboardEvent) { if event.pressed { match key { - KeyCode::ComboOn => self.combo_on = true, - KeyCode::ComboOff => self.combo_on = false, - KeyCode::ComboToggle => self.combo_on = !self.combo_on, _ => (), } } } /// Process consumer control action. Consumer control keys are keys in hid consumer page, such as media keys. - async fn process_action_consumer_control(&mut self, key: KeyCode, event: KeyboardEvent) { - if key.is_consumer() { - self.media_report.usage_id = if event.pressed { - key.as_consumer_control_usage_id() as u16 - } else { - 0 - }; + async fn process_action_consumer_control(&mut self, key: ConsumerKey, event: KeyboardEvent) { + self.media_report.usage_id = if event.pressed { key as u16 } else { 0 }; - self.send_media_report().await; - } + self.send_media_report().await; } /// Process system control action. System control keys are keys in system page, such as power key. - async fn process_action_system_control(&mut self, key: KeyCode, event: KeyboardEvent) { - if key.is_system() { - if event.pressed { - if let Some(system_key) = key.as_system_control_usage_id() { - self.system_control_report.usage_id = system_key as u8; - self.send_system_control_report().await; - } - } else { - self.system_control_report.usage_id = 0; - self.send_system_control_report().await; - } + async fn process_action_system_control(&mut self, key: SystemControlKey, event: KeyboardEvent) { + if event.pressed { + self.system_control_report.usage_id = key as u8; + self.send_system_control_report().await; + } else { + self.system_control_report.usage_id = 0; + self.send_system_control_report().await; } } /// Process mouse key action with acceleration support. - async fn process_action_mouse(&mut self, key: KeyCode, event: KeyboardEvent) { - if key.is_mouse_key() { - if event.pressed { - match key { - KeyCode::MouseUp => { - // Reset repeat counter for direction change - if self.mouse_report.y > 0 { - self.mouse_repeat = 0; - } - let unit = self.calculate_mouse_move_unit(); - self.mouse_report.y = -unit; - } - KeyCode::MouseDown => { - if self.mouse_report.y < 0 { - self.mouse_repeat = 0; - } - let unit = self.calculate_mouse_move_unit(); - self.mouse_report.y = unit; - } - KeyCode::MouseLeft => { - if self.mouse_report.x > 0 { - self.mouse_repeat = 0; - } - let unit = self.calculate_mouse_move_unit(); - self.mouse_report.x = -unit; - } - KeyCode::MouseRight => { - if self.mouse_report.x < 0 { - self.mouse_repeat = 0; - } - let unit = self.calculate_mouse_move_unit(); - self.mouse_report.x = unit; - } - KeyCode::MouseWheelUp => { - if self.mouse_report.wheel < 0 { - self.mouse_wheel_repeat = 0; - } - let unit = self.calculate_mouse_wheel_unit(); - self.mouse_report.wheel = unit; - } - KeyCode::MouseWheelDown => { - if self.mouse_report.wheel > 0 { - self.mouse_wheel_repeat = 0; - } - let unit = self.calculate_mouse_wheel_unit(); - self.mouse_report.wheel = -unit; - } - KeyCode::MouseWheelLeft => { - if self.mouse_report.pan > 0 { - self.mouse_wheel_repeat = 0; - } - let unit = self.calculate_mouse_wheel_unit(); - self.mouse_report.pan = -unit; + async fn process_action_mouse(&mut self, key: HidKeyCode, event: KeyboardEvent) { + if event.pressed { + match key { + HidKeyCode::MouseUp => { + // Reset repeat counter for direction change + if self.mouse_report.y > 0 { + self.mouse_repeat = 0; } - KeyCode::MouseWheelRight => { - if self.mouse_report.pan < 0 { - self.mouse_wheel_repeat = 0; - } - let unit = self.calculate_mouse_wheel_unit(); - self.mouse_report.pan = unit; + let unit = self.calculate_mouse_move_unit(); + self.mouse_report.y = -unit; + } + HidKeyCode::MouseDown => { + if self.mouse_report.y < 0 { + self.mouse_repeat = 0; } - KeyCode::MouseBtn1 => self.mouse_report.buttons |= 1 << 0, - KeyCode::MouseBtn2 => self.mouse_report.buttons |= 1 << 1, - KeyCode::MouseBtn3 => self.mouse_report.buttons |= 1 << 2, - KeyCode::MouseBtn4 => self.mouse_report.buttons |= 1 << 3, - KeyCode::MouseBtn5 => self.mouse_report.buttons |= 1 << 4, - KeyCode::MouseBtn6 => self.mouse_report.buttons |= 1 << 5, - KeyCode::MouseBtn7 => self.mouse_report.buttons |= 1 << 6, - KeyCode::MouseBtn8 => self.mouse_report.buttons |= 1 << 7, - KeyCode::MouseAccel0 => { - self.mouse_accel |= 1 << 0; + let unit = self.calculate_mouse_move_unit(); + self.mouse_report.y = unit; + } + HidKeyCode::MouseLeft => { + if self.mouse_report.x > 0 { + self.mouse_repeat = 0; } - KeyCode::MouseAccel1 => { - self.mouse_accel |= 1 << 1; + let unit = self.calculate_mouse_move_unit(); + self.mouse_report.x = -unit; + } + HidKeyCode::MouseRight => { + if self.mouse_report.x < 0 { + self.mouse_repeat = 0; } - KeyCode::MouseAccel2 => { - self.mouse_accel |= 1 << 2; + let unit = self.calculate_mouse_move_unit(); + self.mouse_report.x = unit; + } + HidKeyCode::MouseWheelUp => { + if self.mouse_report.wheel < 0 { + self.mouse_wheel_repeat = 0; } - _ => {} + let unit = self.calculate_mouse_wheel_unit(); + self.mouse_report.wheel = unit; } - } else { - match key { - KeyCode::MouseUp => { - if self.mouse_report.y < 0 { - self.mouse_report.y = 0; - } + HidKeyCode::MouseWheelDown => { + if self.mouse_report.wheel > 0 { + self.mouse_wheel_repeat = 0; } - KeyCode::MouseDown => { - if self.mouse_report.y > 0 { - self.mouse_report.y = 0; - } + let unit = self.calculate_mouse_wheel_unit(); + self.mouse_report.wheel = -unit; + } + HidKeyCode::MouseWheelLeft => { + if self.mouse_report.pan > 0 { + self.mouse_wheel_repeat = 0; } - KeyCode::MouseLeft => { - if self.mouse_report.x < 0 { - self.mouse_report.x = 0; - } + let unit = self.calculate_mouse_wheel_unit(); + self.mouse_report.pan = -unit; + } + HidKeyCode::MouseWheelRight => { + if self.mouse_report.pan < 0 { + self.mouse_wheel_repeat = 0; } - KeyCode::MouseRight => { - if self.mouse_report.x > 0 { - self.mouse_report.x = 0; - } + let unit = self.calculate_mouse_wheel_unit(); + self.mouse_report.pan = unit; + } + HidKeyCode::MouseBtn1 => self.mouse_report.buttons |= 1 << 0, + HidKeyCode::MouseBtn2 => self.mouse_report.buttons |= 1 << 1, + HidKeyCode::MouseBtn3 => self.mouse_report.buttons |= 1 << 2, + HidKeyCode::MouseBtn4 => self.mouse_report.buttons |= 1 << 3, + HidKeyCode::MouseBtn5 => self.mouse_report.buttons |= 1 << 4, + HidKeyCode::MouseBtn6 => self.mouse_report.buttons |= 1 << 5, + HidKeyCode::MouseBtn7 => self.mouse_report.buttons |= 1 << 6, + HidKeyCode::MouseBtn8 => self.mouse_report.buttons |= 1 << 7, + HidKeyCode::MouseAccel0 => { + self.mouse_accel |= 1 << 0; + } + HidKeyCode::MouseAccel1 => { + self.mouse_accel |= 1 << 1; + } + HidKeyCode::MouseAccel2 => { + self.mouse_accel |= 1 << 2; + } + _ => {} + } + } else { + match key { + HidKeyCode::MouseUp => { + if self.mouse_report.y < 0 { + self.mouse_report.y = 0; } - KeyCode::MouseWheelUp => { - if self.mouse_report.wheel > 0 { - self.mouse_report.wheel = 0; - } + } + HidKeyCode::MouseDown => { + if self.mouse_report.y > 0 { + self.mouse_report.y = 0; } - KeyCode::MouseWheelDown => { - if self.mouse_report.wheel < 0 { - self.mouse_report.wheel = 0; - } + } + HidKeyCode::MouseLeft => { + if self.mouse_report.x < 0 { + self.mouse_report.x = 0; } - KeyCode::MouseWheelLeft => { - if self.mouse_report.pan < 0 { - self.mouse_report.pan = 0; - } + } + HidKeyCode::MouseRight => { + if self.mouse_report.x > 0 { + self.mouse_report.x = 0; } - KeyCode::MouseWheelRight => { - if self.mouse_report.pan > 0 { - self.mouse_report.pan = 0; - } + } + HidKeyCode::MouseWheelUp => { + if self.mouse_report.wheel > 0 { + self.mouse_report.wheel = 0; } - KeyCode::MouseBtn1 => self.mouse_report.buttons &= !(1 << 0), - KeyCode::MouseBtn2 => self.mouse_report.buttons &= !(1 << 1), - KeyCode::MouseBtn3 => self.mouse_report.buttons &= !(1 << 2), - KeyCode::MouseBtn4 => self.mouse_report.buttons &= !(1 << 3), - KeyCode::MouseBtn5 => self.mouse_report.buttons &= !(1 << 4), - KeyCode::MouseBtn6 => self.mouse_report.buttons &= !(1 << 5), - KeyCode::MouseBtn7 => self.mouse_report.buttons &= !(1 << 6), - KeyCode::MouseBtn8 => self.mouse_report.buttons &= !(1 << 7), - KeyCode::MouseAccel0 => { - self.mouse_accel &= !(1 << 0); + } + HidKeyCode::MouseWheelDown => { + if self.mouse_report.wheel < 0 { + self.mouse_report.wheel = 0; } - KeyCode::MouseAccel1 => { - self.mouse_accel &= !(1 << 1); + } + HidKeyCode::MouseWheelLeft => { + if self.mouse_report.pan < 0 { + self.mouse_report.pan = 0; } - KeyCode::MouseAccel2 => { - self.mouse_accel &= !(1 << 2); + } + HidKeyCode::MouseWheelRight => { + if self.mouse_report.pan > 0 { + self.mouse_report.pan = 0; } - _ => {} } - - // Reset repeat counters when movement stops - if self.mouse_report.x == 0 && self.mouse_report.y == 0 { - self.mouse_repeat = 0; + HidKeyCode::MouseBtn1 => self.mouse_report.buttons &= !(1 << 0), + HidKeyCode::MouseBtn2 => self.mouse_report.buttons &= !(1 << 1), + HidKeyCode::MouseBtn3 => self.mouse_report.buttons &= !(1 << 2), + HidKeyCode::MouseBtn4 => self.mouse_report.buttons &= !(1 << 3), + HidKeyCode::MouseBtn5 => self.mouse_report.buttons &= !(1 << 4), + HidKeyCode::MouseBtn6 => self.mouse_report.buttons &= !(1 << 5), + HidKeyCode::MouseBtn7 => self.mouse_report.buttons &= !(1 << 6), + HidKeyCode::MouseBtn8 => self.mouse_report.buttons &= !(1 << 7), + HidKeyCode::MouseAccel0 => { + self.mouse_accel &= !(1 << 0); + } + HidKeyCode::MouseAccel1 => { + self.mouse_accel &= !(1 << 1); } - if self.mouse_report.wheel == 0 && self.mouse_report.pan == 0 { - self.mouse_wheel_repeat = 0; + HidKeyCode::MouseAccel2 => { + self.mouse_accel &= !(1 << 2); } + _ => {} } - // Apply diagonal compensation for movement - if self.mouse_report.x != 0 && self.mouse_report.y != 0 { - let (x, y) = self.apply_diagonal_compensation(self.mouse_report.x, self.mouse_report.y); - self.mouse_report.x = x; - self.mouse_report.y = y; + // Reset repeat counters when movement stops + if self.mouse_report.x == 0 && self.mouse_report.y == 0 { + self.mouse_repeat = 0; } - - // Apply diagonal compensation for wheel - if self.mouse_report.wheel != 0 && self.mouse_report.pan != 0 { - let (wheel, pan) = self.apply_diagonal_compensation(self.mouse_report.wheel, self.mouse_report.pan); - self.mouse_report.wheel = wheel; - self.mouse_report.pan = pan; + if self.mouse_report.wheel == 0 && self.mouse_report.pan == 0 { + self.mouse_wheel_repeat = 0; } + } - if !matches!(key, KeyCode::MouseAccel0 | KeyCode::MouseAccel1 | KeyCode::MouseAccel2) { - // Send mouse report only for movement and wheel keys - self.send_mouse_report().await; - } + // Apply diagonal compensation for movement + if self.mouse_report.x != 0 && self.mouse_report.y != 0 { + let (x, y) = self.apply_diagonal_compensation(self.mouse_report.x, self.mouse_report.y); + self.mouse_report.x = x; + self.mouse_report.y = y; + } - // Continue processing ONLY for movement and wheel keys - if event.pressed { - let is_movement_key = matches!( - key, - KeyCode::MouseUp | KeyCode::MouseDown | KeyCode::MouseLeft | KeyCode::MouseRight - ); - let is_wheel_key = matches!( - key, - KeyCode::MouseWheelUp - | KeyCode::MouseWheelDown - | KeyCode::MouseWheelLeft - | KeyCode::MouseWheelRight - ); + // Apply diagonal compensation for wheel + if self.mouse_report.wheel != 0 && self.mouse_report.pan != 0 { + let (wheel, pan) = self.apply_diagonal_compensation(self.mouse_report.wheel, self.mouse_report.pan); + self.mouse_report.wheel = wheel; + self.mouse_report.pan = pan; + } - // Only continue processing for movement and wheel keys - if is_movement_key || is_wheel_key { - // Determine the delay for the next repeat using convenience methods - let delay = { - let config = &self.keymap.borrow().behavior.mouse_key; - if is_movement_key { - config.get_movement_delay(self.mouse_repeat) - } else { - config.get_wheel_delay(self.mouse_wheel_repeat) - } - }; + if !matches!( + key, + HidKeyCode::MouseAccel0 | HidKeyCode::MouseAccel1 | HidKeyCode::MouseAccel2 + ) { + // Send mouse report only for movement and wheel keys + self.send_mouse_report().await; + } - // Increment the appropriate repeat counter - if is_movement_key && self.mouse_repeat < u8::MAX { - self.mouse_repeat += 1; - } - if is_wheel_key && self.mouse_wheel_repeat < u8::MAX { - self.mouse_wheel_repeat += 1; + // Continue processing ONLY for movement and wheel keys + if event.pressed { + let is_movement_key = matches!( + key, + HidKeyCode::MouseUp | HidKeyCode::MouseDown | HidKeyCode::MouseLeft | HidKeyCode::MouseRight + ); + let is_wheel_key = matches!( + key, + HidKeyCode::MouseWheelUp + | HidKeyCode::MouseWheelDown + | HidKeyCode::MouseWheelLeft + | HidKeyCode::MouseWheelRight + ); + + // Only continue processing for movement and wheel keys + if is_movement_key || is_wheel_key { + // Determine the delay for the next repeat using convenience methods + let delay = { + let config = &self.keymap.borrow().behavior.mouse_key; + if is_movement_key { + config.get_movement_delay(self.mouse_repeat) + } else { + config.get_wheel_delay(self.mouse_wheel_repeat) } + }; - // Schedule next movement after the delay - embassy_time::Timer::after_millis(delay as u64).await; - // Check if there's a release event in the channel, if there's no release event, re-send the event - let len = KEY_EVENT_CHANNEL.len(); - let mut released = false; - for _ in 0..len { - let queued_event = KEY_EVENT_CHANNEL.receive().await; - if queued_event.pos != event.pos || !queued_event.pressed { - KEY_EVENT_CHANNEL.send(queued_event).await; - } - // If there's a release event in the channel - if queued_event.pos == event.pos && !queued_event.pressed { - released = true; - } + // Increment the appropriate repeat counter + if is_movement_key && self.mouse_repeat < u8::MAX { + self.mouse_repeat += 1; + } + if is_wheel_key && self.mouse_wheel_repeat < u8::MAX { + self.mouse_wheel_repeat += 1; + } + + // Schedule next movement after the delay + embassy_time::Timer::after_millis(delay as u64).await; + // Check if there's a release event in the channel, if there's no release event, re-send the event + let len = KEY_EVENT_CHANNEL.len(); + let mut released = false; + for _ in 0..len { + let queued_event = KEY_EVENT_CHANNEL.receive().await; + if queued_event.pos != event.pos || !queued_event.pressed { + KEY_EVENT_CHANNEL.send(queued_event).await; } - if !released { - KEY_EVENT_CHANNEL.send(event).await; + // If there's a release event in the channel + if queued_event.pos == event.pos && !queued_event.pressed { + released = true; } } + if !released { + KEY_EVENT_CHANNEL.send(event).await; + } } } } - async fn process_user(&mut self, key: KeyCode, event: KeyboardEvent) { - debug!("Processing user key: {:?}, event: {:?}", key, event); + async fn process_user(&mut self, id: u8, event: KeyboardEvent) { + debug!("Processing user key id: {:?}, event: {:?}", id, event); #[cfg(feature = "_ble")] { use crate::NUM_BLE_PROFILE; use crate::ble::profile::BleProfileAction; use crate::channel::BLE_PROFILE_CHANNEL; - // Get user key id - let id = (key as u16 - KeyCode::User0 as u16) as u8; if event.pressed { // Clear Peer is processed when pressed if id == NUM_BLE_PROFILE as u8 + 4 { @@ -1813,28 +1840,6 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E } } - fn process_boot(&mut self, key: KeyCode, event: KeyboardEvent) { - // When releasing the key, process the boot action - if !event.pressed { - match key { - KeyCode::Bootloader => { - boot::jump_to_bootloader(); - } - KeyCode::Reboot => { - boot::reboot_keyboard(); - } - _ => (), // unreachable, do nothing - }; - } - } - - async fn process_action_macro(&mut self, key: KeyCode, event: KeyboardEvent) { - // Get macro index - if let Some(macro_idx) = key.as_macro_index() { - self.execute_macro(macro_idx, event).await; - } - } - async fn execute_macro(&mut self, macro_idx: u8, event: KeyboardEvent) { // Execute the macro only when releasing the key if event.pressed { @@ -1974,19 +1979,19 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E } /// Register a key, the key can be a basic keycode or a modifier. - fn register_key(&mut self, key: KeyCode, event: KeyboardEvent) { + fn register_key(&mut self, key: HidKeyCode, event: KeyboardEvent) { if key.is_modifier() { self.register_modifier_key(key); - } else if key.is_basic() { + } else { self.register_keycode(key, event); } } /// Unregister a key, the key can be a basic keycode or a modifier. - fn unregister_key(&mut self, key: KeyCode, event: KeyboardEvent) { + fn unregister_key(&mut self, key: HidKeyCode, event: KeyboardEvent) { if key.is_modifier() { self.unregister_modifier_key(key); - } else if key.is_basic() { + } else { self.unregister_keycode(key, event); } } @@ -2025,7 +2030,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E } /// Register a key to be sent in hid report. - fn register_keycode(&mut self, key: KeyCode, event: KeyboardEvent) { + fn register_keycode(&mut self, key: HidKeyCode, event: KeyboardEvent) { // First, find the key event slot according to the position let slot = self.registered_keys.iter().enumerate().find_map(|(i, k)| { if let Some(e) = k @@ -2042,7 +2047,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E self.registered_keys[index] = Some(event); } else { // Otherwise, find the first free slot - if let Some(index) = self.held_keycodes.iter().position(|&k| k == KeyCode::No) { + if let Some(index) = self.held_keycodes.iter().position(|&k| k == HidKeyCode::No) { self.held_keycodes[index] = key; self.registered_keys[index] = Some(event); } @@ -2050,7 +2055,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E } /// Unregister a key from hid report. - fn unregister_keycode(&mut self, key: KeyCode, event: KeyboardEvent) { + fn unregister_keycode(&mut self, key: HidKeyCode, event: KeyboardEvent) { // First, find the key event slot according to the position let slot = self.registered_keys.iter().enumerate().find_map(|(i, k)| { if let Some(e) = k @@ -2063,19 +2068,19 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E // If the slot is found, update the key in the slot if let Some(index) = slot { - self.held_keycodes[index] = KeyCode::No; + self.held_keycodes[index] = HidKeyCode::No; self.registered_keys[index] = None; } else { // Otherwise, release the first same key if let Some(index) = self.held_keycodes.iter().position(|&k| k == key) { - self.held_keycodes[index] = KeyCode::No; + self.held_keycodes[index] = HidKeyCode::No; self.registered_keys[index] = None; } } } /// Register a modifier to be sent in hid report. - fn register_modifier_key(&mut self, key: KeyCode) { + fn register_modifier_key(&mut self, key: HidKeyCode) { self.held_modifiers |= key.to_hid_modifiers(); #[cfg(feature = "controller")] @@ -2086,7 +2091,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E } /// Unregister a modifier from hid report. - fn unregister_modifier_key(&mut self, key: KeyCode) { + fn unregister_modifier_key(&mut self, key: HidKeyCode) { self.held_modifiers &= !key.to_hid_modifiers(); #[cfg(feature = "controller")] diff --git a/rmk/src/keyboard_macros.rs b/rmk/src/keyboard_macros.rs index 1b35e96f2..20a62d8ff 100644 --- a/rmk/src/keyboard_macros.rs +++ b/rmk/src/keyboard_macros.rs @@ -1,4 +1,4 @@ -use rmk_types::keycode::{KeyCode, from_ascii, to_ascii}; +use rmk_types::keycode::{HidKeyCode, from_ascii, to_ascii}; use crate::MACRO_SPACE_SIZE; use crate::keymap::fill_vec; @@ -16,16 +16,16 @@ pub enum MacroOperation { /// by MacroOperations::define_macro_sequences() End, /// 0x01 01 + 1 byte keycode - Tap(KeyCode), + Tap(HidKeyCode), /// 0x01 02 + 1 byte keycode - Press(KeyCode), + Press(HidKeyCode), /// 0x01 03 + 1 byte keycode - Release(KeyCode), + Release(HidKeyCode), /// 0x01 04 + 2 byte for the delay in ms Delay(u16), /// Anything not covered above (and starting at /// 0x30 (= b'0'), is the 1 byte ascii character. - Text(KeyCode, bool), // bool = shifted + Text(HidKeyCode, bool), // bool = shifted } impl MacroOperation { @@ -44,7 +44,7 @@ impl MacroOperation { (0, _) => (MacroOperation::End, offset), (1, 1) => { if idx + 2 < macro_sequences.len() { - let keycode = (macro_sequences[idx + 2] as u16).into(); + let keycode = (macro_sequences[idx + 2] as u8).into(); (MacroOperation::Tap(keycode), offset + 3) } else { (MacroOperation::End, offset + 3) @@ -52,7 +52,7 @@ impl MacroOperation { } (1, 2) => { if idx + 2 < macro_sequences.len() { - let keycode = (macro_sequences[idx + 2] as u16).into(); + let keycode = (macro_sequences[idx + 2] as u8).into(); (MacroOperation::Press(keycode), offset + 3) } else { (MacroOperation::End, offset + 3) @@ -60,7 +60,7 @@ impl MacroOperation { } (1, 3) => { if idx + 2 < macro_sequences.len() { - let keycode = (macro_sequences[idx + 2] as u16).into(); + let keycode = (macro_sequences[idx + 2] as u8).into(); (MacroOperation::Release(keycode), offset + 3) } else { (MacroOperation::End, offset + 3) diff --git a/rmk/src/layout_macro.rs b/rmk/src/layout_macro.rs index 67803fe08..f79b507c4 100644 --- a/rmk/src/layout_macro.rs +++ b/rmk/src/layout_macro.rs @@ -1,4 +1,15 @@ -/// Create a layer in keymap +/// Create a layer in keymap. +/// +/// This macro simplifies the syntax for defining keyboard layers by allowing +/// a more natural 2D array notation. +/// +/// # Example +/// ```ignore +/// let layer = layer!([ +/// [k!(Esc), k!(Kc1), k!(Kc2)], +/// [k!(Tab), k!(Q), k!(W)] +/// ]); +/// ``` #[macro_export] macro_rules! layer { ([$([$($x: expr), +]), +]) => { @@ -6,28 +17,75 @@ macro_rules! layer { }; } -/// Create a normal key. For example, `k!(A)` represents `KeyAction::Single(Action::Key(KeyCode::A))` +/// Create a normal key action. +/// +/// This macro creates a simple key press action for any HID keyboard key. +/// When the key is pressed, it sends the corresponding HID keycode. +/// +/// # Parameters +/// - `$k`: The HID keycode identifier (e.g., `A`, `Space`, `Enter`, `F1`) +/// +/// # Example +/// ```ignore +/// k!(A) // Creates action for key 'A' +/// k!(Space) // Creates action for Space key +/// k!(Enter) // Creates action for Enter key +/// k!(F1) // Creates action for F1 key +/// ``` +/// +/// # Expands to +/// `KeyAction::Single(Action::Key(KeyCode::Hid(HidKeyCode::A)))` #[macro_export] macro_rules! k { ($k: ident) => { $crate::types::action::KeyAction::Single($crate::types::action::Action::Key( - $crate::types::keycode::KeyCode::$k, + $crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$k), )) }; } -/// Create a normal key with modifier action +/// Create a key action with modifier combination. +/// +/// This macro creates a key action that sends a key along with modifier keys +/// (Ctrl, Shift, Alt, GUI) pressed simultaneously. +/// +/// # Parameters +/// - `$x`: The HID keycode identifier +/// - `$m`: A `ModifierCombination` expression specifying which modifiers to apply +/// +/// # Example +/// ```ignore +/// // Ctrl+C +/// wm!(C, ModifierCombination::new_from(false, false, false, false, true)) +/// +/// // Shift+A (can also use the `shifted!` macro for this) +/// wm!(A, ModifierCombination::LSHIFT) +/// +/// // Ctrl+Shift+Esc +/// wm!(Escape, ModifierCombination::LCTRL.with_left_shift(true)) +/// ``` #[macro_export] macro_rules! wm { ($x: ident, $m: expr) => { $crate::types::action::KeyAction::Single($crate::types::action::Action::KeyWithModifier( - $crate::types::keycode::KeyCode::$x, + $crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$x), $m, )) }; } -/// Create a normal action: `KeyAction` +/// Create a KeyAction variant directly. +/// +/// This macro provides shorthand access to KeyAction enum variants. +/// +/// # Parameters +/// - `$a`: The KeyAction variant name (e.g., `No`, `Transparent`) +/// +/// # Example +/// ```ignore +/// a!(No) // KeyAction::No - empty action +/// a!(Transparent) // KeyAction::Transparent - pass through to next layer +/// ``` #[macro_export] macro_rules! a { ($a: ident) => { @@ -35,7 +93,19 @@ macro_rules! a { }; } -/// Create a layer activate action. For example, `mo!(1)` activates layer 1. +/// Create a momentary layer activation action. +/// +/// This macro creates an action that activates a layer while the key is held down. +/// The layer is deactivated when the key is released. Similar to QMK's `MO()`. +/// +/// # Parameters +/// - `$x`: Layer number (0-255) +/// +/// # Example +/// ```ignore +/// mo!(1) // Activates layer 1 while held +/// mo!(2) // Activates layer 2 while held +/// ``` #[macro_export] macro_rules! mo { ($x: literal) => { @@ -43,7 +113,20 @@ macro_rules! mo { }; } -/// Create a layer activate with modifier action +/// Create a layer activation with modifier action. +/// +/// This macro activates a layer while also applying modifier keys. +/// Both the layer and modifiers are active while the key is held. +/// +/// # Parameters +/// - `$x`: Layer number (0-15) +/// - `$m`: A `ModifierCombination` expression +/// +/// # Example +/// ```ignore +/// lm!(1, ModifierCombination::LSHIFT) // Activates layer 1 with Left Shift +/// lm!(2, ModifierCombination::LCTRL) // Activates layer 2 with Left Ctrl +/// ``` #[macro_export] macro_rules! lm { ($x: literal, $m: expr) => { @@ -51,76 +134,180 @@ macro_rules! lm { }; } -/// Create a layer activate action or tap key(tap/hold) +/// Create a layer-tap action (tap/hold behavior). +/// +/// This macro creates a dual-function key: +/// - **Tap**: Sends the specified key +/// - **Hold**: Activates the specified layer +/// +/// Uses default timing configuration for tap/hold detection. +/// +/// # Parameters +/// - `$x`: Layer number to activate when held +/// - `$k`: HID keycode to send when tapped +/// +/// # Example +/// ```ignore +/// lt!(1, Space) // Tap for Space, hold for layer 1 +/// lt!(2, Enter) // Tap for Enter, hold for layer 2 +/// ``` #[macro_export] macro_rules! lt { ($x: literal, $k: ident) => { $crate::types::action::KeyAction::TapHold( - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::$k), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$k)), $crate::types::action::Action::LayerOn($x), $crate::types::action::MorseProfile::const_default(), ) }; } -/// Create a layer activate action or tap key(tap/hold) with profile + +/// Create a layer-tap action with custom timing profile. +/// +/// Same as `lt!` but allows specifying custom tap/hold timing configuration +/// through a `MorseProfile`. +/// +/// # Parameters +/// - `$x`: Layer number to activate when held +/// - `$k`: HID keycode to send when tapped +/// - `$p`: Custom `MorseProfile` for timing configuration +/// +/// # Example +/// ```ignore +/// let profile = MorseProfile::new(Some(true), None, Some(200), Some(300)); +/// ltp!(1, Space, profile) // Layer-tap with custom timing +/// ``` #[macro_export] macro_rules! ltp { ($x: literal, $k: ident, $p: expr) => { $crate::types::action::KeyAction::TapHold( - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::$k), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$k)), $crate::types::action::Action::LayerOn($x), $p, ) }; } -/// Create a modifier-tap-hold action +/// Create a modifier-tap action (tap/hold behavior). +/// +/// This macro creates a dual-function key: +/// - **Tap**: Sends the specified key +/// - **Hold**: Applies the specified modifier(s) +/// +/// Commonly used for home row mods. Uses default timing configuration. +/// +/// # Parameters +/// - `$k`: HID keycode to send when tapped +/// - `$m`: `ModifierCombination` to apply when held +/// +/// # Example +/// ```ignore +/// mt!(A, ModifierCombination::LCTRL) // Tap for A, hold for Ctrl +/// mt!(S, ModifierCombination::LSHIFT) // Tap for S, hold for Shift +/// mt!(D, ModifierCombination::LALT) // Tap for D, hold for Alt +/// ``` #[macro_export] macro_rules! mt { ($k: ident, $m: expr) => { $crate::types::action::KeyAction::TapHold( - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::$k), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$k)), $crate::types::action::Action::Modifier($m), $crate::types::action::MorseProfile::const_default(), ) }; } -/// Create a modifier-tap-hold action with profile + +/// Create a modifier-tap action with custom timing profile. +/// +/// Same as `mt!` but allows specifying custom tap/hold timing configuration. +/// +/// # Parameters +/// - `$k`: HID keycode to send when tapped +/// - `$m`: `ModifierCombination` to apply when held +/// - `$p`: Custom `MorseProfile` for timing configuration +/// +/// # Example +/// ```ignore +/// let profile = MorseProfile::new(Some(false), None, Some(180), None); +/// mtp!(A, ModifierCombination::LCTRL, profile) +/// ``` #[macro_export] macro_rules! mtp { ($k: ident, $m: expr, $p: expr) => { $crate::types::action::KeyAction::TapHold( - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::$k), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$k)), $crate::types::action::Action::Modifier($m), $p, ) }; } -/// Create a tap-hold action +/// Create a dual-key tap-hold action. +/// +/// This macro creates a key with two different key behaviors: +/// - **Tap**: Sends the first key +/// - **Hold**: Sends the second key +/// +/// Uses default timing configuration. +/// +/// # Parameters +/// - `$t`: HID keycode to send when tapped +/// - `$h`: HID keycode to send when held +/// +/// # Example +/// ```ignore +/// th!(Space, Backspace) // Tap for Space, hold for Backspace +/// th!(Escape, Grave) // Tap for Escape, hold for Grave +/// ``` #[macro_export] macro_rules! th { ($t: ident, $h: ident) => { $crate::types::action::KeyAction::TapHold( - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::$t), - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::$h), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$t)), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$h)), $crate::types::action::MorseProfile::const_default(), ) }; } -/// Create a tap-hold action with profile + +/// Create a dual-key tap-hold action with custom timing profile. +/// +/// Same as `th!` but allows specifying custom tap/hold timing configuration. +/// +/// # Parameters +/// - `$t`: HID keycode to send when tapped +/// - `$h`: HID keycode to send when held +/// - `$p`: Custom `MorseProfile` for timing configuration +/// +/// # Example +/// ```ignore +/// let profile = MorseProfile::new(None, Some(MorseMode::PermissiveHold), Some(200), None); +/// thp!(Space, Backspace, profile) +/// ``` #[macro_export] macro_rules! thp { ($t: ident, $h: ident, $p: expr) => { $crate::types::action::KeyAction::TapHold( - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::$t), - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::$h), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$t)), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$h)), $p, ) }; } -/// Create an oneshot layer key in keymap +/// Create a one-shot layer action. +/// +/// This macro creates a key that activates a layer for the next keypress only. +/// After the next key is pressed, the layer automatically deactivates. +/// +/// # Parameters +/// - `$x`: Layer number (0-255) +/// +/// # Example +/// ```ignore +/// osl!(1) // Next key will be from layer 1, then return to current layer +/// osl!(2) // Next key will be from layer 2, then return to current layer +/// ``` #[macro_export] macro_rules! osl { ($x: literal) => { @@ -128,7 +315,19 @@ macro_rules! osl { }; } -/// Create an oneshot modifier key in keymap +/// Create a one-shot modifier action. +/// +/// This macro creates a key that applies modifiers for the next keypress only. +/// After the next key is pressed, the modifiers automatically deactivate. +/// +/// # Parameters +/// - `$m`: `ModifierCombination` to apply for the next keypress +/// +/// # Example +/// ```ignore +/// osm!(ModifierCombination::LSHIFT) // Next key will be shifted +/// osm!(ModifierCombination::LCTRL) // Next key will have Ctrl applied +/// ``` #[macro_export] macro_rules! osm { ($m: expr) => { @@ -136,7 +335,19 @@ macro_rules! osm { }; } -/// Create a layer toggle action +/// Create a layer toggle action. +/// +/// This macro creates a key that toggles a layer on/off with each press. +/// First press activates the layer, second press deactivates it. +/// +/// # Parameters +/// - `$x`: Layer number (0-255) +/// +/// # Example +/// ```ignore +/// tg!(1) // Toggle layer 1 on/off +/// tg!(2) // Toggle layer 2 on/off +/// ``` #[macro_export] macro_rules! tg { ($x: literal) => { @@ -144,7 +355,20 @@ macro_rules! tg { }; } -/// Create a layer activate or tap toggle action +/// Create a layer tap-toggle action. +/// +/// This macro creates a dual-function key: +/// - **Tap**: Toggles the layer on/off +/// - **Hold**: Momentarily activates the layer (like `mo!`) +/// +/// # Parameters +/// - `$x`: Layer number (0-255) +/// +/// # Example +/// ```ignore +/// tt!(1) // Tap to toggle layer 1, hold to activate momentarily +/// tt!(2) // Tap to toggle layer 2, hold to activate momentarily +/// ``` #[macro_export] macro_rules! tt { ($x: literal) => { @@ -155,7 +379,14 @@ macro_rules! tt { ) }; } -/// Create a layer activate or tap toggle action with profile + +/// Create a layer tap-toggle action with custom timing profile. +/// +/// Same as `tt!` but allows specifying custom tap/hold timing configuration. +/// +/// # Parameters +/// - `$x`: Layer number (0-255) +/// - `$p`: Custom `MorseProfile` for timing configuration #[macro_export] macro_rules! ttp { ($x: literal, $p: expr) => { @@ -167,7 +398,19 @@ macro_rules! ttp { }; } -/// Create a layer toggle only action (activate layer `n` and deactivate all other layers), `n` is the layer number +/// Create a "to layer" action (exclusive layer activation). +/// +/// This macro activates the specified layer and deactivates all other layers +/// (except the default layer). This creates an exclusive layer switch. +/// +/// # Parameters +/// - `$x`: Layer number (0-255) +/// +/// # Example +/// ```ignore +/// to!(1) // Switch exclusively to layer 1 +/// to!(0) // Return to base layer +/// ``` #[macro_export] macro_rules! to { ($x: literal) => { @@ -175,7 +418,19 @@ macro_rules! to { }; } -/// create a switch default layer action, `n` is the layer number +/// Create a default layer switch action. +/// +/// This macro sets the default/base layer. The default layer is always active +/// and serves as the fallback when no other layers are active. +/// +/// # Parameters +/// - `$x`: Layer number (0-255) +/// +/// # Example +/// ```ignore +/// df!(0) // Set layer 0 as the default layer +/// df!(1) // Set layer 1 as the default layer (e.g., for Dvorak layout) +/// ``` #[macro_export] macro_rules! df { ($x: literal) => { @@ -183,7 +438,20 @@ macro_rules! df { }; } -/// Create a shifted key +/// Create a shifted key action. +/// +/// This is a convenience macro that creates a key with left shift applied. +/// Equivalent to `wm!($x, ModifierCombination::LSHIFT)`. +/// +/// # Parameters +/// - `$x`: HID keycode identifier +/// +/// # Example +/// ```ignore +/// shifted!(A) // Sends Shift+A (uppercase 'A') +/// shifted!(Kc1) // Sends Shift+1 (exclamation mark '!') +/// shifted!(Slash) // Sends Shift+/ (question mark '?') +/// ``` #[macro_export] macro_rules! shifted { ($x: ident) => { @@ -194,7 +462,29 @@ macro_rules! shifted { }; } -/// Create an encoder action, the first argument is the clockwise action, the second is the counter-clockwise action +/// Create a rotary encoder action. +/// +/// This macro defines the behavior of a rotary encoder, specifying different +/// actions for clockwise and counter-clockwise rotation. +/// +/// # Parameters +/// - `$clockwise`: `KeyAction` to execute on clockwise rotation +/// - `$counter_clockwise`: `KeyAction` to execute on counter-clockwise rotation +/// +/// # Example +/// ```ignore +/// // Volume control encoder +/// encoder!( +/// k!(KbVolumeUp), // Clockwise increases volume +/// k!(KbVolumeDown) // Counter-clockwise decreases volume +/// ) +/// +/// // Scroll encoder +/// encoder!( +/// k!(MouseWheelUp), +/// k!(MouseWheelDown) +/// ) +/// ``` #[macro_export] macro_rules! encoder { ($clockwise: expr, $counter_clockwise: expr) => { @@ -202,7 +492,24 @@ macro_rules! encoder { }; } -/// Create a Morse(index) action (in Vial its simplest form is known as "Tap Dance", so `td` name is used) +/// Create a tap dance action (Morse action). +/// +/// This macro creates a reference to a tap dance configuration by index. +/// Tap dance allows multiple actions based on the number of taps. +/// In Vial, this appears as "Tap Dance". +/// +/// # Parameters +/// - `$index`: Index of the tap dance configuration (0-255) +/// +/// # Example +/// ```ignore +/// td!(0) // References tap dance configuration at index 0 +/// td!(1) // References tap dance configuration at index 1 +/// ``` +/// +/// # Note +/// The actual tap dance behavior must be configured separately in the +/// keyboard's tap dance configuration array. #[macro_export] macro_rules! td { ($index: literal) => { @@ -210,7 +517,18 @@ macro_rules! td { }; } -/// Create a Morse(index) action (in Vial it will appear as "Tap Dance") +/// Create a Morse action (alias for tap dance). +/// +/// This is an alias for `td!` macro. "Morse" is the internal name for +/// the superset of tap dance and tap-hold functionality. +/// +/// # Parameters +/// - `$index`: Index of the Morse configuration (0-255) +/// +/// # Example +/// ```ignore +/// morse!(0) // Same as td!(0) +/// ``` #[macro_export] macro_rules! morse { ($index: literal) => { @@ -218,8 +536,24 @@ macro_rules! morse { }; } -// Create a macro trigger action -// Use `macros` because `macro` is a key word in Rust +/// Create a macro trigger action. +/// +/// This macro creates a key that triggers a predefined macro sequence by index. +/// Macros can send multiple keypresses or perform complex sequences. +/// +/// # Parameters +/// - `$index`: Index of the macro configuration (0-255) +/// +/// # Example +/// ```ignore +/// macros!(0) // Triggers macro at index 0 +/// macros!(1) // Triggers macro at index 1 +/// ``` +/// +/// # Note +/// - Named `macros` because `macro` is a Rust keyword +/// - The actual macro sequence must be configured separately in the +/// keyboard's macro configuration array #[macro_export] macro_rules! macros { ($index: literal) => { From 92dd4629eb84e1bfe9656230ba53cdc2661ff0f8 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 30 Dec 2025 19:22:32 +0800 Subject: [PATCH 2/9] test: fix all tests for new `KeyCode` Signed-off-by: Haobo Gu --- rmk/src/host/storage.rs | 26 ++-- rmk/src/host/via/keycode_convert.rs | 8 +- rmk/src/host/via/vial.rs | 6 +- rmk/src/keyboard.rs | 128 +++++++++--------- rmk/src/keyboard_macros.rs | 110 +++++++-------- rmk/src/morse.rs | 44 +++--- rmk/tests/common/morse.rs | 34 ++--- rmk/tests/common/test_macro.rs | 4 +- rmk/tests/keyboard_combo_test.rs | 26 ++-- rmk/tests/keyboard_layer_test.rs | 8 +- rmk/tests/keyboard_macro_test.rs | 24 ++-- ...keyboard_morse_hold_on_other_press_test.rs | 8 +- rmk/tests/keyboard_morse_hrm_test.rs | 8 +- .../keyboard_morse_permissive_hold_test.rs | 8 +- rmk/tests/keyboard_morse_tap_dance_test.rs | 22 +-- rmk/tests/keyboard_morse_test.rs | 10 +- 16 files changed, 237 insertions(+), 237 deletions(-) diff --git a/rmk/src/host/storage.rs b/rmk/src/host/storage.rs index 4d1126b2b..6ddcb1f7c 100644 --- a/rmk/src/host/storage.rs +++ b/rmk/src/host/storage.rs @@ -289,7 +289,7 @@ impl releases 'D' keyboard.process_inner(KeyboardEvent::key(2, 1, false)).await; - assert_eq!(keyboard.held_keycodes[0], KeyCode::No); + assert_eq!(keyboard.held_keycodes[0], HidKeyCode::No); }; block_on(main); diff --git a/rmk/src/keyboard_macros.rs b/rmk/src/keyboard_macros.rs index 20a62d8ff..6c44a9f79 100644 --- a/rmk/src/keyboard_macros.rs +++ b/rmk/src/keyboard_macros.rs @@ -226,11 +226,11 @@ mod test { #[test] fn test_define_one_macro_sequence_manual() { let macro_sequences = &[heapless::Vec::from_slice(&[ - MacroOperation::Press(KeyCode::LShift), - MacroOperation::Tap(KeyCode::P), - MacroOperation::Release(KeyCode::LShift), - MacroOperation::Tap(KeyCode::A), - MacroOperation::Tap(KeyCode::T), + MacroOperation::Press(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::P), + MacroOperation::Release(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::A), + MacroOperation::Tap(HidKeyCode::T), ]) .expect("too many elements")]; let macro_sequences_binary = define_macro_sequences(macro_sequences); @@ -248,16 +248,16 @@ mod test { fn test_define_two_macro_sequence_manual() { let macro_sequences_terminated_uneccessarily = [ heapless::Vec::from_slice(&[ - MacroOperation::Text(KeyCode::H, true), - MacroOperation::Text(KeyCode::I, false), + MacroOperation::Text(HidKeyCode::H, true), + MacroOperation::Text(HidKeyCode::I, false), ]) .expect("too many elements"), heapless::Vec::from_slice(&[ - MacroOperation::Press(KeyCode::LShift), - MacroOperation::Tap(KeyCode::P), - MacroOperation::Release(KeyCode::LShift), - MacroOperation::Tap(KeyCode::A), - MacroOperation::Tap(KeyCode::T), + MacroOperation::Press(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::P), + MacroOperation::Release(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::A), + MacroOperation::Tap(HidKeyCode::T), ]) .expect("too many elements"), ]; @@ -277,27 +277,27 @@ mod test { fn test_define_macro_sequences_clean() { let macro_sequences_clean = [ heapless::Vec::from_slice(&[ - MacroOperation::Press(KeyCode::LShift), - MacroOperation::Tap(KeyCode::H), - MacroOperation::Release(KeyCode::LShift), - MacroOperation::Tap(KeyCode::E), - MacroOperation::Tap(KeyCode::L), - MacroOperation::Tap(KeyCode::L), - MacroOperation::Tap(KeyCode::O), + MacroOperation::Press(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::H), + MacroOperation::Release(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::E), + MacroOperation::Tap(HidKeyCode::L), + MacroOperation::Tap(HidKeyCode::L), + MacroOperation::Tap(HidKeyCode::O), ]) .expect("too many elements"), heapless::Vec::from_slice(&[ - MacroOperation::Tap(KeyCode::W), - MacroOperation::Tap(KeyCode::O), - MacroOperation::Tap(KeyCode::R), - MacroOperation::Tap(KeyCode::L), - MacroOperation::Tap(KeyCode::D), + MacroOperation::Tap(HidKeyCode::W), + MacroOperation::Tap(HidKeyCode::O), + MacroOperation::Tap(HidKeyCode::R), + MacroOperation::Tap(HidKeyCode::L), + MacroOperation::Tap(HidKeyCode::D), ]) .expect("too many elements"), heapless::Vec::from_slice(&[ - MacroOperation::Press(KeyCode::LShift), - MacroOperation::Tap(KeyCode::Kc2), - MacroOperation::Release(KeyCode::LShift), + MacroOperation::Press(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::Kc2), + MacroOperation::Release(HidKeyCode::LShift), ]) .expect("too many elements"), ]; @@ -317,28 +317,28 @@ mod test { fn test_define_macro_sequences_uneccessarily_terminated() { let macro_sequences_terminated_uneccessarily = [ heapless::Vec::from_slice(&[ - MacroOperation::Press(KeyCode::LShift), - MacroOperation::Tap(KeyCode::H), - MacroOperation::Release(KeyCode::LShift), - MacroOperation::Tap(KeyCode::E), - MacroOperation::Tap(KeyCode::L), - MacroOperation::Tap(KeyCode::L), - MacroOperation::Tap(KeyCode::O), + MacroOperation::Press(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::H), + MacroOperation::Release(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::E), + MacroOperation::Tap(HidKeyCode::L), + MacroOperation::Tap(HidKeyCode::L), + MacroOperation::Tap(HidKeyCode::O), MacroOperation::End, ]) .expect("too many elements"), heapless::Vec::from_slice(&[ - MacroOperation::Tap(KeyCode::W), - MacroOperation::Tap(KeyCode::O), - MacroOperation::Tap(KeyCode::R), - MacroOperation::Tap(KeyCode::L), + MacroOperation::Tap(HidKeyCode::W), + MacroOperation::Tap(HidKeyCode::O), + MacroOperation::Tap(HidKeyCode::R), + MacroOperation::Tap(HidKeyCode::L), MacroOperation::End, ]) .expect("too many elements"), heapless::Vec::from_slice(&[ - MacroOperation::Press(KeyCode::LShift), - MacroOperation::Tap(KeyCode::Kc2), - MacroOperation::Release(KeyCode::LShift), + MacroOperation::Press(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::Kc2), + MacroOperation::Release(HidKeyCode::LShift), MacroOperation::End, ]) .expect("too many elements"), @@ -359,35 +359,35 @@ mod test { fn test_define_macro_sequences_random_end_markers() { let macro_sequences_random_end_markers = [ heapless::Vec::from_slice(&[ - MacroOperation::Press(KeyCode::LShift), - MacroOperation::Tap(KeyCode::H), + MacroOperation::Press(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::H), MacroOperation::End, - MacroOperation::Release(KeyCode::LShift), - MacroOperation::Tap(KeyCode::E), + MacroOperation::Release(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::E), MacroOperation::End, MacroOperation::End, - MacroOperation::Tap(KeyCode::L), + MacroOperation::Tap(HidKeyCode::L), MacroOperation::End, - MacroOperation::Tap(KeyCode::L), - MacroOperation::Tap(KeyCode::O), + MacroOperation::Tap(HidKeyCode::L), + MacroOperation::Tap(HidKeyCode::O), MacroOperation::End, ]) .expect("too many elements"), heapless::Vec::from_slice(&[ - MacroOperation::Tap(KeyCode::W), - MacroOperation::Tap(KeyCode::O), + MacroOperation::Tap(HidKeyCode::W), + MacroOperation::Tap(HidKeyCode::O), MacroOperation::End, MacroOperation::End, MacroOperation::End, MacroOperation::End, - MacroOperation::Tap(KeyCode::R), - MacroOperation::Tap(KeyCode::L), + MacroOperation::Tap(HidKeyCode::R), + MacroOperation::Tap(HidKeyCode::L), ]) .expect("too many elements"), heapless::Vec::from_slice(&[ - MacroOperation::Press(KeyCode::LShift), - MacroOperation::Tap(KeyCode::Kc2), - MacroOperation::Release(KeyCode::LShift), + MacroOperation::Press(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::Kc2), + MacroOperation::Release(HidKeyCode::LShift), MacroOperation::End, MacroOperation::End, MacroOperation::End, diff --git a/rmk/src/morse.rs b/rmk/src/morse.rs index 8dfd61a06..586571eb6 100644 --- a/rmk/src/morse.rs +++ b/rmk/src/morse.rs @@ -275,7 +275,7 @@ impl Morse { #[cfg(test)] mod tests { - use rmk_types::keycode::KeyCode; + use rmk_types::keycode::{HidKeyCode, KeyCode}; use super::*; @@ -302,14 +302,14 @@ mod tests { profile: MorseProfile::const_default(), actions: heapless::LinearMap::default(), }; - morse.actions.insert(TAP, Action::Key(KeyCode::A)).ok(); + morse.actions.insert(TAP, Action::Key(KeyCode::Hid(HidKeyCode::A))).ok(); let mut buffer = [0u8; 128]; let serialized = postcard::to_slice(&morse, &mut buffer).unwrap(); let deserialized: Morse<4> = postcard::from_bytes(serialized).unwrap(); assert_eq!(morse.actions.len(), deserialized.actions.len()); - assert_eq!(deserialized.actions.get(&TAP), Some(&Action::Key(KeyCode::A))); + assert_eq!(deserialized.actions.get(&TAP), Some(&Action::Key(KeyCode::Hid(HidKeyCode::A)))); } #[test] @@ -319,10 +319,10 @@ mod tests { profile: MorseProfile::const_default(), actions: heapless::LinearMap::default(), }; - morse.actions.insert(TAP, Action::Key(KeyCode::A)).ok(); - morse.actions.insert(HOLD, Action::Key(KeyCode::B)).ok(); - morse.actions.insert(DOUBLE_TAP, Action::Key(KeyCode::C)).ok(); - morse.actions.insert(HOLD_AFTER_TAP, Action::Key(KeyCode::D)).ok(); + morse.actions.insert(TAP, Action::Key(KeyCode::Hid(HidKeyCode::A))).ok(); + morse.actions.insert(HOLD, Action::Key(KeyCode::Hid(HidKeyCode::B))).ok(); + morse.actions.insert(DOUBLE_TAP, Action::Key(KeyCode::Hid(HidKeyCode::C))).ok(); + morse.actions.insert(HOLD_AFTER_TAP, Action::Key(KeyCode::Hid(HidKeyCode::D))).ok(); let mut buffer = [0u8; 128]; let serialized = postcard::to_slice(&morse, &mut buffer).unwrap(); @@ -332,12 +332,12 @@ mod tests { assert_eq!(morse.actions.len(), 4); // Verify each entry - assert_eq!(deserialized.actions.get(&TAP), Some(&Action::Key(KeyCode::A))); - assert_eq!(deserialized.actions.get(&HOLD), Some(&Action::Key(KeyCode::B))); - assert_eq!(deserialized.actions.get(&DOUBLE_TAP), Some(&Action::Key(KeyCode::C))); + assert_eq!(deserialized.actions.get(&TAP), Some(&Action::Key(KeyCode::Hid(HidKeyCode::A)))); + assert_eq!(deserialized.actions.get(&HOLD), Some(&Action::Key(KeyCode::Hid(HidKeyCode::B)))); + assert_eq!(deserialized.actions.get(&DOUBLE_TAP), Some(&Action::Key(KeyCode::Hid(HidKeyCode::C)))); assert_eq!( deserialized.actions.get(&HOLD_AFTER_TAP), - Some(&Action::Key(KeyCode::D)) + Some(&Action::Key(KeyCode::Hid(HidKeyCode::D))) ); } @@ -350,15 +350,15 @@ mod tests { }; morse .actions - .insert(MorsePattern::from_u16(0b1_01), Action::Key(KeyCode::E)) + .insert(MorsePattern::from_u16(0b1_01), Action::Key(KeyCode::Hid(HidKeyCode::E))) .ok(); morse .actions - .insert(MorsePattern::from_u16(0b1_1000), Action::Key(KeyCode::F)) + .insert(MorsePattern::from_u16(0b1_1000), Action::Key(KeyCode::Hid(HidKeyCode::F))) .ok(); morse .actions - .insert(MorsePattern::from_u16(0b1_1010), Action::Key(KeyCode::G)) + .insert(MorsePattern::from_u16(0b1_1010), Action::Key(KeyCode::Hid(HidKeyCode::G))) .ok(); let mut buffer = [0u8; 128]; @@ -386,8 +386,8 @@ mod tests { ), actions: heapless::LinearMap::default(), }; - morse.actions.insert(TAP, Action::Key(KeyCode::H)).ok(); - morse.actions.insert(HOLD, Action::Key(KeyCode::I)).ok(); + morse.actions.insert(TAP, Action::Key(KeyCode::Hid(HidKeyCode::H))).ok(); + morse.actions.insert(HOLD, Action::Key(KeyCode::Hid(HidKeyCode::I))).ok(); let mut buffer = [0u8; 128]; let serialized = postcard::to_slice(&morse, &mut buffer).unwrap(); @@ -395,8 +395,8 @@ mod tests { assert_eq!(morse.profile, deserialized.profile); assert_eq!(morse.actions.len(), deserialized.actions.len()); - assert_eq!(deserialized.actions.get(&TAP), Some(&Action::Key(KeyCode::H))); - assert_eq!(deserialized.actions.get(&HOLD), Some(&Action::Key(KeyCode::I))); + assert_eq!(deserialized.actions.get(&TAP), Some(&Action::Key(KeyCode::Hid(HidKeyCode::H)))); + assert_eq!(deserialized.actions.get(&HOLD), Some(&Action::Key(KeyCode::Hid(HidKeyCode::I)))); } #[test] @@ -406,15 +406,15 @@ mod tests { profile: MorseProfile::const_default(), actions: heapless::LinearMap::default(), }; - morse1.actions.insert(TAP, Action::Key(KeyCode::A)).ok(); - morse1.actions.insert(HOLD, Action::Key(KeyCode::B)).ok(); + morse1.actions.insert(TAP, Action::Key(KeyCode::Hid(HidKeyCode::A))).ok(); + morse1.actions.insert(HOLD, Action::Key(KeyCode::Hid(HidKeyCode::B))).ok(); let mut morse2 = Morse::<4> { profile: MorseProfile::const_default(), actions: heapless::LinearMap::default(), }; - morse2.actions.insert(HOLD, Action::Key(KeyCode::B)).ok(); - morse2.actions.insert(TAP, Action::Key(KeyCode::A)).ok(); + morse2.actions.insert(HOLD, Action::Key(KeyCode::Hid(HidKeyCode::B))).ok(); + morse2.actions.insert(TAP, Action::Key(KeyCode::Hid(HidKeyCode::A))).ok(); let mut buffer1 = [0u8; 128]; let mut buffer2 = [0u8; 128]; diff --git a/rmk/tests/common/morse.rs b/rmk/tests/common/morse.rs index f33708ed0..0445978e5 100644 --- a/rmk/tests/common/morse.rs +++ b/rmk/tests/common/morse.rs @@ -3,7 +3,7 @@ use rmk::config::{BehaviorConfig, Hand, MorsesConfig, PositionalConfig}; use rmk::keyboard::Keyboard; use rmk::morse::{Morse, MorsePattern}; use rmk::types::action::Action; -use rmk::types::keycode::KeyCode; +use rmk::types::keycode::{HidKeyCode, KeyCode}; use rmk::types::modifier::ModifierCombination; use rmk::{k, lt, mt, td}; @@ -24,14 +24,14 @@ pub fn create_simple_morse_keyboard(behavior_config: BehaviorConfig) -> Keyboard let morse0 = Morse { actions: LinearMap::from_iter( [ - (MorsePattern::from_u16(0b1_01), Action::Key(KeyCode::A)), - (MorsePattern::from_u16(0b1_1000), Action::Key(KeyCode::B)), - (MorsePattern::from_u16(0b1_1010), Action::Key(KeyCode::C)), - (MorsePattern::from_u16(0b1_101), Action::Key(KeyCode::K)), - (MorsePattern::from_u16(0b1_11), Action::Key(KeyCode::M)), - (MorsePattern::from_u16(0b1_111), Action::Key(KeyCode::O)), - (MorsePattern::from_u16(0b1_010), Action::Key(KeyCode::R)), - (MorsePattern::from_u16(0b1_000), Action::Key(KeyCode::S)), + (MorsePattern::from_u16(0b1_01), Action::Key(KeyCode::Hid(HidKeyCode::A))), + (MorsePattern::from_u16(0b1_1000), Action::Key(KeyCode::Hid(HidKeyCode::B))), + (MorsePattern::from_u16(0b1_1010), Action::Key(KeyCode::Hid(HidKeyCode::C))), + (MorsePattern::from_u16(0b1_101), Action::Key(KeyCode::Hid(HidKeyCode::K))), + (MorsePattern::from_u16(0b1_11), Action::Key(KeyCode::Hid(HidKeyCode::M))), + (MorsePattern::from_u16(0b1_111), Action::Key(KeyCode::Hid(HidKeyCode::O))), + (MorsePattern::from_u16(0b1_010), Action::Key(KeyCode::Hid(HidKeyCode::R))), + (MorsePattern::from_u16(0b1_000), Action::Key(KeyCode::Hid(HidKeyCode::S))), ] .into_iter(), ), @@ -68,14 +68,14 @@ pub fn create_morse_keyboard(behavior_config: BehaviorConfig, hand: [[Hand; 5]; let morse0 = Morse { actions: LinearMap::from_iter( [ - (MorsePattern::from_u16(0b1_01), Action::Key(KeyCode::A)), - (MorsePattern::from_u16(0b1_1000), Action::Key(KeyCode::B)), - (MorsePattern::from_u16(0b1_1010), Action::Key(KeyCode::C)), - (MorsePattern::from_u16(0b1_101), Action::Key(KeyCode::K)), - (MorsePattern::from_u16(0b1_11), Action::Key(KeyCode::M)), - (MorsePattern::from_u16(0b1_111), Action::Key(KeyCode::O)), - (MorsePattern::from_u16(0b1_010), Action::Key(KeyCode::R)), - (MorsePattern::from_u16(0b1_000), Action::Key(KeyCode::S)), + (MorsePattern::from_u16(0b1_01), Action::Key(KeyCode::Hid(HidKeyCode::A))), + (MorsePattern::from_u16(0b1_1000), Action::Key(KeyCode::Hid(HidKeyCode::B))), + (MorsePattern::from_u16(0b1_1010), Action::Key(KeyCode::Hid(HidKeyCode::C))), + (MorsePattern::from_u16(0b1_101), Action::Key(KeyCode::Hid(HidKeyCode::K))), + (MorsePattern::from_u16(0b1_11), Action::Key(KeyCode::Hid(HidKeyCode::M))), + (MorsePattern::from_u16(0b1_111), Action::Key(KeyCode::Hid(HidKeyCode::O))), + (MorsePattern::from_u16(0b1_010), Action::Key(KeyCode::Hid(HidKeyCode::R))), + (MorsePattern::from_u16(0b1_000), Action::Key(KeyCode::Hid(HidKeyCode::S))), ] .into_iter(), ), diff --git a/rmk/tests/common/test_macro.rs b/rmk/tests/common/test_macro.rs index b3a39ea7e..d004646f5 100644 --- a/rmk/tests/common/test_macro.rs +++ b/rmk/tests/common/test_macro.rs @@ -38,10 +38,10 @@ macro_rules! key_sequence_test { } /// Convert a key `k!(key)` to the u8 representation in hid report. -/// For example, `KeyCode::A` will be converted to `0x04`. +/// For example, `HidKeyCode::A` will be converted to `0x04`. #[macro_export] macro_rules! kc_to_u8 { ($key: ident) => { - rmk::types::keycode::KeyCode::$key as u8 + rmk::types::keycode::HidKeyCode::$key as u8 }; } diff --git a/rmk/tests/keyboard_combo_test.rs b/rmk/tests/keyboard_combo_test.rs index ea634e844..000ab9aec 100644 --- a/rmk/tests/keyboard_combo_test.rs +++ b/rmk/tests/keyboard_combo_test.rs @@ -3,7 +3,7 @@ pub mod common; use embassy_time::Duration; use rmk::combo::{Combo, ComboConfig}; use rmk::config::{BehaviorConfig, CombosConfig, MorsesConfig, OneShotConfig}; -use rmk::types::keycode::KeyCode; +use rmk::types::keycode::HidKeyCode; use rmk::types::modifier::ModifierCombination; use rmk::{k, osm, th}; use rmk_types::action::{MorseMode, MorseProfile}; @@ -87,11 +87,11 @@ rusty_fork_test! { [1, 5, false, 10], ], expected_reports: [ - [0, [KeyCode::E as u8, 0, 0, 0, 0, 0]], + [0, [HidKeyCode::E as u8, 0, 0, 0, 0, 0]], [0, [0; 6]], - [0, [KeyCode::R as u8, 0, 0, 0, 0, 0]], + [0, [HidKeyCode::R as u8, 0, 0, 0, 0, 0]], [0, [0; 6]], - [0, [KeyCode::T as u8, 0, 0, 0, 0, 0]], + [0, [HidKeyCode::T as u8, 0, 0, 0, 0, 0]], [0, [0; 6]], ] } @@ -130,7 +130,7 @@ rusty_fork_test! { ], expected_reports: [ [KC_LSHIFT, [0; 6]], // V + B = LShift - [KC_LSHIFT, [KeyCode::R as u8, 0, 0, 0, 0, 0]], // Press R + [KC_LSHIFT, [HidKeyCode::R as u8, 0, 0, 0, 0, 0]], // Press R [KC_LSHIFT, [0; 6]], // Release R [0, [0; 6]], // Release V + B ] @@ -155,7 +155,7 @@ rusty_fork_test! { [1, 3, false, 110], ], expected_reports: [ - [KC_LSHIFT, [KeyCode::E as u8, 0, 0, 0, 0, 0]], + [KC_LSHIFT, [HidKeyCode::E as u8, 0, 0, 0, 0, 0]], [0, [0; 6]], ] } @@ -178,7 +178,7 @@ rusty_fork_test! { ], expected_reports: [ [KC_LSHIFT, [0; 6]], - [KC_LSHIFT, [KeyCode::N as u8, 0, 0, 0, 0, 0]], + [KC_LSHIFT, [HidKeyCode::N as u8, 0, 0, 0, 0, 0]], [KC_LSHIFT, [0; 6]], [0, [0; 6]], ] @@ -199,7 +199,7 @@ rusty_fork_test! { [1, 4, false, 10], ], expected_reports: [ - [0, [KeyCode::A as u8, 0, 0, 0, 0, 0]], + [0, [HidKeyCode::A as u8, 0, 0, 0, 0, 0]], [0, [0; 6]], ] } @@ -219,7 +219,7 @@ rusty_fork_test! { [1, 4, false, 10], ], expected_reports: [ - [0, [KeyCode::A as u8, 0, 0, 0, 0, 0]], + [0, [HidKeyCode::A as u8, 0, 0, 0, 0, 0]], [0, [0; 6]], ] } @@ -256,11 +256,11 @@ rusty_fork_test! { ], expected_reports: [ - [0, [KeyCode::Space as u8, 0, 0, 0, 0, 0]], + [0, [HidKeyCode::Space as u8, 0, 0, 0, 0, 0]], [0, [0; 6]], - [KC_LSHIFT, [KeyCode::A as u8, 0, 0, 0, 0, 0]], + [KC_LSHIFT, [HidKeyCode::A as u8, 0, 0, 0, 0, 0]], [0, [0; 6]], - [0, [KeyCode::Space as u8, 0, 0, 0, 0, 0]], + [0, [HidKeyCode::Space as u8, 0, 0, 0, 0, 0]], [0, [0; 6]], ] } @@ -284,7 +284,7 @@ rusty_fork_test! { [1, 3, false, 10], ], expected_reports: [ - [KC_LSHIFT, [KeyCode::A as u8, 0, 0, 0, 0, 0]], + [KC_LSHIFT, [HidKeyCode::A as u8, 0, 0, 0, 0, 0]], [0, [0; 6]], ] } diff --git a/rmk/tests/keyboard_layer_test.rs b/rmk/tests/keyboard_layer_test.rs index b898842dc..bbca6587d 100644 --- a/rmk/tests/keyboard_layer_test.rs +++ b/rmk/tests/keyboard_layer_test.rs @@ -3,7 +3,7 @@ pub mod common; use rmk::config::{BehaviorConfig, PositionalConfig}; use rmk::keyboard::Keyboard; use rmk::types::action::{Action, KeyAction}; -use rmk::types::keycode::KeyCode; +use rmk::types::keycode::{HidKeyCode, KeyCode}; use rmk_types::modifier::ModifierCombination; use rusty_fork::rusty_fork_test; @@ -12,12 +12,12 @@ use crate::common::{KC_LSHIFT, wrap_keymap}; fn create_simple_keyboard(behavior_config: BehaviorConfig) -> Keyboard<'static, 1, 2, 2> { let keymap = [ [[ - KeyAction::Single(Action::Key(KeyCode::A)), + KeyAction::Single(Action::Key(KeyCode::Hid(HidKeyCode::A))), KeyAction::Single(Action::LayerOnWithModifier(1, ModifierCombination::LSHIFT)), ]], [[ - KeyAction::Single(Action::Key(KeyCode::B)), - KeyAction::Single(Action::Key(KeyCode::C)), + KeyAction::Single(Action::Key(KeyCode::Hid(HidKeyCode::B))), + KeyAction::Single(Action::Key(KeyCode::Hid(HidKeyCode::C))), ]], ]; static BEHAVIOR_CONFIG: static_cell::StaticCell = static_cell::StaticCell::new(); diff --git a/rmk/tests/keyboard_macro_test.rs b/rmk/tests/keyboard_macro_test.rs index 7a20e855c..82fcb6ce5 100644 --- a/rmk/tests/keyboard_macro_test.rs +++ b/rmk/tests/keyboard_macro_test.rs @@ -6,7 +6,7 @@ mod macro_test { use rmk::keyboard::Keyboard; use rmk::keyboard_macros::{MacroOperation, define_macro_sequences, to_macro_sequence}; use rmk::types::action::{Action, KeyAction}; - use rmk::types::keycode::KeyCode; + use rmk_types::keycode::HidKeyCode; use rusty_fork::rusty_fork_test; use crate::common::{KC_LSHIFT, wrap_keymap}; @@ -14,8 +14,8 @@ mod macro_test { fn create_simple_macro_keyboard(behavior_config: BehaviorConfig) -> Keyboard<'static, 1, 2, 1> { let keymap = [[[ - KeyAction::Single(Action::Key(KeyCode::Macro0)), - KeyAction::Single(Action::Key(KeyCode::Macro1)), + KeyAction::Single(Action::TriggerMacro(0)), + KeyAction::Single(Action::TriggerMacro(1)), ]]]; static BEHAVIOR_CONFIG: static_cell::StaticCell = static_cell::StaticCell::new(); let behavior_config: &'static mut BehaviorConfig = BEHAVIOR_CONFIG.init(behavior_config); @@ -29,8 +29,8 @@ mod macro_test { #[test] fn test_macro_key_a_press_release() { let macro_sequences = &[Vec::from_slice(&[ - MacroOperation::Press(KeyCode::A), - MacroOperation::Release(KeyCode::A), + MacroOperation::Press(HidKeyCode::A), + MacroOperation::Release(HidKeyCode::A), ]) .expect("too many elements")]; @@ -100,7 +100,7 @@ mod macro_test { #[test] fn test_macro_tap_key_a() { - let macro_sequences = &[Vec::from_slice(&[MacroOperation::Tap(KeyCode::A)]).expect("too many elements")]; + let macro_sequences = &[Vec::from_slice(&[MacroOperation::Tap(HidKeyCode::A)]).expect("too many elements")]; let macro_data = define_macro_sequences(macro_sequences); let mut config = BehaviorConfig::default(); @@ -124,10 +124,10 @@ mod macro_test { #[test] fn test_macro_multiple_operations() { let macro_sequences = &[Vec::from_slice(&[ - MacroOperation::Press(KeyCode::LShift), - MacroOperation::Tap(KeyCode::A), - MacroOperation::Release(KeyCode::LShift), - MacroOperation::Tap(KeyCode::B), + MacroOperation::Press(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::A), + MacroOperation::Release(HidKeyCode::LShift), + MacroOperation::Tap(HidKeyCode::B), ]) .expect("too many elements")]; @@ -157,9 +157,9 @@ mod macro_test { #[test] fn test_macro_with_delay() { let macro_sequences = &[Vec::from_slice(&[ - MacroOperation::Tap(KeyCode::A), + MacroOperation::Tap(HidKeyCode::A), MacroOperation::Delay(50 << 8), // 50 ms - MacroOperation::Tap(KeyCode::B), + MacroOperation::Tap(HidKeyCode::B), ]) .expect("too many elements")]; diff --git a/rmk/tests/keyboard_morse_hold_on_other_press_test.rs b/rmk/tests/keyboard_morse_hold_on_other_press_test.rs index 063febcaa..c42f2b8a0 100644 --- a/rmk/tests/keyboard_morse_hold_on_other_press_test.rs +++ b/rmk/tests/keyboard_morse_hold_on_other_press_test.rs @@ -6,7 +6,7 @@ use rmk::config::{BehaviorConfig, CombosConfig, MorsesConfig}; use rmk::k; use rmk::keyboard::Keyboard; use rmk::types::action::{Action, KeyAction}; -use rmk::types::keycode::KeyCode; +use rmk::types::keycode::{HidKeyCode, KeyCode}; use rmk::types::modifier::ModifierCombination; use rmk_types::action::{MorseMode, MorseProfile}; use rusty_fork::rusty_fork_test; @@ -32,7 +32,7 @@ fn create_hold_on_other_key_press_keyboard() -> Keyboard<'static, 1, 5, 2> { fn create_hold_on_other_key_press_keyboard_with_combo() -> Keyboard<'static, 1, 5, 2> { let combo_key = KeyAction::TapHold( - Action::Key(KeyCode::B), + Action::Key(KeyCode::Hid(HidKeyCode::B)), Action::Modifier(ModifierCombination::LSHIFT), MorseProfile::new( //just to test if combo ignores the profile as expected @@ -43,11 +43,11 @@ fn create_hold_on_other_key_press_keyboard_with_combo() -> Keyboard<'static, 1, ), ); let combo_key_2 = KeyAction::TapHold( - Action::Key(KeyCode::C), + Action::Key(KeyCode::Hid(HidKeyCode::C)), Action::Modifier(ModifierCombination::LGUI), MorseProfile::new(Some(false), Some(MorseMode::Normal), Some(250u16), Some(250u16)), //just to test if combo ignores the profile as expected ); - let combo_key_3 = KeyAction::TapHold(Action::Key(KeyCode::D), Action::LayerOn(1), Default::default()); + let combo_key_3 = KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::D)), Action::LayerOn(1), Default::default()); create_simple_morse_keyboard(BehaviorConfig { morse: MorsesConfig { enable_flow_tap: false, diff --git a/rmk/tests/keyboard_morse_hrm_test.rs b/rmk/tests/keyboard_morse_hrm_test.rs index 84f16b622..3bc589b06 100644 --- a/rmk/tests/keyboard_morse_hrm_test.rs +++ b/rmk/tests/keyboard_morse_hrm_test.rs @@ -9,7 +9,7 @@ use rmk::config::{BehaviorConfig, CombosConfig, Hand, MorsesConfig}; use rmk::k; use rmk::keyboard::Keyboard; use rmk::types::action::{Action, KeyAction}; -use rmk::types::keycode::KeyCode; +use rmk::types::keycode::{HidKeyCode, KeyCode}; use rmk::types::modifier::ModifierCombination; use rmk_types::action::{MorseMode, MorseProfile}; use rusty_fork::rusty_fork_test; @@ -41,16 +41,16 @@ fn create_hrm_keyboard() -> Keyboard<'static, 1, 5, 2> { fn create_hrm_keyboard_with_combo() -> Keyboard<'static, 1, 5, 2> { let combo_key = KeyAction::TapHold( - Action::Key(KeyCode::B), + Action::Key(KeyCode::Hid(HidKeyCode::B)), Action::Modifier(ModifierCombination::LSHIFT), Default::default(), ); let combo_key_2 = KeyAction::TapHold( - Action::Key(KeyCode::C), + Action::Key(KeyCode::Hid(HidKeyCode::C)), Action::Modifier(ModifierCombination::LGUI), Default::default(), ); - let combo_key_3 = KeyAction::TapHold(Action::Key(KeyCode::D), Action::LayerOn(1), Default::default()); + let combo_key_3 = KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::D)), Action::LayerOn(1), Default::default()); let hand = [[Hand::Left, Hand::Left, Hand::Right, Hand::Right, Hand::Right]]; diff --git a/rmk/tests/keyboard_morse_permissive_hold_test.rs b/rmk/tests/keyboard_morse_permissive_hold_test.rs index 493b91843..715744ba8 100644 --- a/rmk/tests/keyboard_morse_permissive_hold_test.rs +++ b/rmk/tests/keyboard_morse_permissive_hold_test.rs @@ -6,7 +6,7 @@ use rmk::config::{BehaviorConfig, CombosConfig, MorsesConfig}; use rmk::k; use rmk::keyboard::Keyboard; use rmk::types::action::{Action, KeyAction}; -use rmk::types::keycode::KeyCode; +use rmk::types::keycode::{HidKeyCode, KeyCode}; use rmk::types::modifier::ModifierCombination; use rmk_types::action::{MorseMode, MorseProfile}; use rusty_fork::rusty_fork_test; @@ -32,16 +32,16 @@ fn create_permissive_hold_keyboard() -> Keyboard<'static, 1, 5, 2> { fn create_permissive_hold_keyboard_with_combo() -> Keyboard<'static, 1, 5, 2> { let combo_key = KeyAction::TapHold( - Action::Key(KeyCode::B), + Action::Key(KeyCode::Hid(HidKeyCode::B)), Action::Modifier(ModifierCombination::LSHIFT), Default::default(), ); let combo_key_2 = KeyAction::TapHold( - Action::Key(KeyCode::C), + Action::Key(KeyCode::Hid(HidKeyCode::C)), Action::Modifier(ModifierCombination::LGUI), Default::default(), ); - let combo_key_3 = KeyAction::TapHold(Action::Key(KeyCode::D), Action::LayerOn(1), Default::default()); + let combo_key_3 = KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::D)), Action::LayerOn(1), Default::default()); create_simple_morse_keyboard(BehaviorConfig { morse: MorsesConfig { enable_flow_tap: false, diff --git a/rmk/tests/keyboard_morse_tap_dance_test.rs b/rmk/tests/keyboard_morse_tap_dance_test.rs index ef1df1a1e..2d123b870 100644 --- a/rmk/tests/keyboard_morse_tap_dance_test.rs +++ b/rmk/tests/keyboard_morse_tap_dance_test.rs @@ -6,7 +6,7 @@ use rmk::config::{BehaviorConfig, MorsesConfig, PositionalConfig}; use rmk::keyboard::Keyboard; use rmk::morse::Morse; use rmk::types::action::{Action, MorseMode, MorseProfile}; -use rmk::types::keycode::KeyCode; +use rmk::types::keycode::{HidKeyCode, KeyCode}; use rmk::types::modifier::ModifierCombination; use rmk::{k, td}; use rusty_fork::rusty_fork_test; @@ -30,23 +30,23 @@ pub fn create_tap_dance_test_keyboard() -> Keyboard<'static, 1, 4, 2> { ), morses: Vec::from_slice(&[ Morse::new_from_vial( - Action::Key(KeyCode::A), - Action::Key(KeyCode::B), - Action::Key(KeyCode::C), - Action::Key(KeyCode::D), + Action::Key(KeyCode::Hid(HidKeyCode::A)), + Action::Key(KeyCode::Hid(HidKeyCode::B)), + Action::Key(KeyCode::Hid(HidKeyCode::C)), + Action::Key(KeyCode::Hid(HidKeyCode::D)), MorseProfile::const_default(), ), Morse::new_from_vial( - Action::Key(KeyCode::X), - Action::Key(KeyCode::Y), - Action::Key(KeyCode::Z), - Action::Key(KeyCode::Space), + Action::Key(KeyCode::Hid(HidKeyCode::X)), + Action::Key(KeyCode::Hid(HidKeyCode::Y)), + Action::Key(KeyCode::Hid(HidKeyCode::Z)), + Action::Key(KeyCode::Hid(HidKeyCode::Space)), MorseProfile::const_default(), ), Morse::new_from_vial( - Action::Key(KeyCode::Kp1), + Action::Key(KeyCode::Hid(HidKeyCode::Kp1)), Action::Modifier(ModifierCombination::LSHIFT), - Action::Key(KeyCode::Kp2), + Action::Key(KeyCode::Hid(HidKeyCode::Kp2)), Action::Modifier(ModifierCombination::LGUI), MorseProfile::const_default(), ), diff --git a/rmk/tests/keyboard_morse_test.rs b/rmk/tests/keyboard_morse_test.rs index 8da3b7b9e..0e08b90c8 100644 --- a/rmk/tests/keyboard_morse_test.rs +++ b/rmk/tests/keyboard_morse_test.rs @@ -5,7 +5,7 @@ use rmk::combo::{Combo, ComboConfig}; use rmk::config::{BehaviorConfig, CombosConfig}; use rmk::k; use rmk::types::action::{Action, KeyAction}; -use rmk::types::keycode::KeyCode; +use rmk::types::keycode::{HidKeyCode, KeyCode}; use rmk::types::modifier::ModifierCombination; use rusty_fork::rusty_fork_test; @@ -728,8 +728,8 @@ rusty_fork_test! { combo: CombosConfig { combos: [ Some(Combo::new(ComboConfig::new( - [KeyAction::TapHold(Action::Key(KeyCode::B), Action::Modifier(ModifierCombination::LSHIFT), Default::default()), - KeyAction::TapHold(Action::Key(KeyCode::C), Action::Modifier(ModifierCombination::LGUI), Default::default())], + [KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::B)), Action::Modifier(ModifierCombination::LSHIFT), Default::default()), + KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::C)), Action::Modifier(ModifierCombination::LGUI), Default::default())], k!(X), None, ))), None, None, None, None, None, None, None @@ -760,8 +760,8 @@ rusty_fork_test! { combo: CombosConfig { combos: [ Some(Combo::new(ComboConfig::new( - [KeyAction::TapHold(Action::Key(KeyCode::B), Action::Modifier(ModifierCombination::LSHIFT), Default::default()), - KeyAction::TapHold(Action::Key(KeyCode::C), Action::Modifier(ModifierCombination::LGUI), Default::default())], + [KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::B)), Action::Modifier(ModifierCombination::LSHIFT), Default::default()), + KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::C)), Action::Modifier(ModifierCombination::LGUI), Default::default())], k!(X), None, ))), None, None, None, None, None, None, None From 6f94a673a100442ab50b4d87e68e3b8b4b5fb8bc Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 30 Dec 2025 19:31:38 +0800 Subject: [PATCH 3/9] fix: fix legacy macro representation in keyboard.toml Signed-off-by: Haobo Gu --- rmk-macro/src/layout.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rmk-macro/src/layout.rs b/rmk-macro/src/layout.rs index 298917053..18c15419b 100644 --- a/rmk-macro/src/layout.rs +++ b/rmk-macro/src/layout.rs @@ -437,6 +437,14 @@ pub(crate) fn parse_key(key: String, profiles: &Option { + // Support Macro0, Macro1, Macro2, etc. + let index_str = &s[5..]; + let index = index_str.parse::().unwrap(); + quote! { + ::rmk::macros!(#index) + } + } _ => { let ident = get_key_with_alias(key); quote! { ::rmk::k!(#ident) } From 1cae61faea4406d4271261af405afc5d67dfb219 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 30 Dec 2025 19:33:05 +0800 Subject: [PATCH 4/9] refactor: remove unused file Signed-off-by: Haobo Gu --- rmk-types/src/keycode_backup.rs | 1380 ------------------------------- 1 file changed, 1380 deletions(-) delete mode 100644 rmk-types/src/keycode_backup.rs diff --git a/rmk-types/src/keycode_backup.rs b/rmk-types/src/keycode_backup.rs deleted file mode 100644 index 0a24db6ce..000000000 --- a/rmk-types/src/keycode_backup.rs +++ /dev/null @@ -1,1380 +0,0 @@ -//! Complete keycode definitions. -//! -//! This module provides keycode definitions following the USB HID -//! specification, extended with additional codes -use serde::{Deserialize, Serialize}; -use strum::FromRepr; - -use crate::modifier::ModifierCombination; - -/// KeyCode is the internal representation of all keycodes, keyboard operations, etc. -/// Use flat representation of keycodes. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum KeyCode { - /// Reserved, no-key. - No = 0x0000, - /// Keyboard roll over error, too many keys are pressed simultaneously, not a physical key. - /// NKRO: n-key rollover. - ErrorRollover = 0x0001, - /// Keyboard post fail error, not a physical key. - PostFail = 0x0002, - /// An undefined error, not a physical key. - ErrorUndefined = 0x0003, - /// `a` and `A` - A = 0x0004, - /// `b` and `B` - B = 0x0005, - /// `c` and `C` - C = 0x0006, - /// `d` and `D` - D = 0x0007, - /// `e` and `E` - E = 0x0008, - /// `f` and `F` - F = 0x0009, - /// `g` and `G` - G = 0x000A, - /// `h` and `H` - H = 0x000B, - /// `i` and `I` - I = 0x000C, - /// `j` and `J` - J = 0x000D, - /// `k` and `K` - K = 0x000E, - /// `l` and `L` - L = 0x000F, - /// `m` and `M` - M = 0x0010, - /// `n` and `N` - N = 0x0011, - /// `o` and `O` - O = 0x0012, - /// `p` and `P` - P = 0x0013, - /// `q` and `Q` - Q = 0x0014, - /// `r` and `R` - R = 0x0015, - /// `s` and `S` - S = 0x0016, - /// `t` and `T` - T = 0x0017, - /// `u` and `U` - U = 0x0018, - /// `v` and `V` - V = 0x0019, - /// `w` and `W` - W = 0x001A, - /// `x` and `X` - X = 0x001B, - /// `y` and `Y` - Y = 0x001C, - /// `z` and `Z` - Z = 0x001D, - /// `1` and `!` - Kc1 = 0x001E, - /// `2` and `@` - Kc2 = 0x001F, - /// `3` and `#` - Kc3 = 0x0020, - /// `4` and `$` - Kc4 = 0x0021, - /// `5` and `%` - Kc5 = 0x0022, - /// `6` and `^` - Kc6 = 0x0023, - /// `7` and `&` - Kc7 = 0x0024, - /// `8` and `*` - Kc8 = 0x0025, - /// `9` and `(` - Kc9 = 0x0026, - /// `0` and `)` - Kc0 = 0x0027, - /// `Enter` - Enter = 0x0028, - /// `Esc` - Escape = 0x0029, - /// `Backspace` - Backspace = 0x002A, - /// `Tab` - Tab = 0x002B, - /// `Space` - Space = 0x002C, - /// `-` and `_` - Minus = 0x002D, - /// `=` and `+` - Equal = 0x002E, - /// `[` and `{` - LeftBracket = 0x002F, - /// `]` and `}` - RightBracket = 0x0030, - /// `\` and `|` - Backslash = 0x0031, - /// Non-US `#` and `~` - NonusHash = 0x0032, - /// `;` and `:` - Semicolon = 0x0033, - /// `'` and `"` - Quote = 0x0034, - /// `~` and `\`` - Grave = 0x0035, - /// `,` and `<` - Comma = 0x0036, - /// `.` and `>` - Dot = 0x0037, - /// `/` and `?` - Slash = 0x0038, - /// `CapsLock` - CapsLock = 0x0039, - /// `F1` - F1 = 0x003A, - /// `F2` - F2 = 0x003B, - /// `F3` - F3 = 0x003C, - /// `F4` - F4 = 0x003D, - /// `F5` - F5 = 0x003E, - /// `F6` - F6 = 0x003F, - /// `F7` - F7 = 0x0040, - /// `F8` - F8 = 0x0041, - /// `F9` - F9 = 0x0042, - /// `F10` - F10 = 0x0043, - /// `F11` - F11 = 0x0044, - /// `F12` - F12 = 0x0045, - /// Print Screen - PrintScreen = 0x0046, - /// Scroll Lock - ScrollLock = 0x0047, - /// Pause - Pause = 0x0048, - /// Insert - Insert = 0x0049, - /// Home - Home = 0x004A, - /// Page Up - PageUp = 0x004B, - /// Delete - Delete = 0x004C, - /// End - End = 0x004D, - /// Page Down - PageDown = 0x004E, - /// Right arrow - Right = 0x004F, - /// Left arrow - Left = 0x0050, - /// Down arrow - Down = 0x0051, - /// Up arrow - Up = 0x0052, - /// Nums Lock - NumLock = 0x0053, - /// `/` on keypad - KpSlash = 0x0054, - /// `*` on keypad - KpAsterisk = 0x0055, - /// `-` on keypad - KpMinus = 0x0056, - /// `+` on keypad - KpPlus = 0x0057, - /// `Enter` on keypad - KpEnter = 0x0058, - /// `1` on keypad - Kp1 = 0x0059, - /// `2` on keypad - Kp2 = 0x005A, - /// `3` on keypad - Kp3 = 0x005B, - /// `4` on keypad - Kp4 = 0x005C, - /// `5` on keypad - Kp5 = 0x005D, - /// `6` on keypad - Kp6 = 0x005E, - /// `7` on keypad - Kp7 = 0x005F, - /// `8` on keypad - Kp8 = 0x0060, - /// `9` on keypad - Kp9 = 0x0061, - /// `0` on keypad - Kp0 = 0x0062, - /// `.` on keypad - KpDot = 0x0063, - /// Non-US `\` or `|` - NonusBackslash = 0x0064, - /// `Application` - Application = 0x0065, - /// `Power` - KbPower = 0x0066, - /// `=` on keypad - KpEqual = 0x0067, - /// `F13` - F13 = 0x0068, - /// `F14` - F14 = 0x0069, - /// `F15` - F15 = 0x006A, - /// `F16` - F16 = 0x006B, - /// `F17` - F17 = 0x006C, - /// `F18` - F18 = 0x006D, - /// `F19` - F19 = 0x006E, - /// `F20` - F20 = 0x006F, - /// `F21` - F21 = 0x0070, - /// `F22` - F22 = 0x0071, - /// `F23` - F23 = 0x0072, - /// `F24` - F24 = 0x0073, - Execute = 0x0074, - Help = 0x0075, - Menu = 0x0076, - Select = 0x0077, - Stop = 0x0078, - Again = 0x0079, - Undo = 0x007A, - Cut = 0x007B, - Copy = 0x007C, - Paste = 0x007D, - Find = 0x007E, - /// Mute - KbMute = 0x007F, - /// Volume Up - KbVolumeUp = 0x0080, - /// Volume Down - KbVolumeDown = 0x0081, - /// Locking Caps Lock - LockingCapsLock = 0x0082, - /// Locking Num Lock - LockingNumLock = 0x0083, - /// Locking scroll lock - LockingScrollLock = 0x0084, - KpComma = 0x0085, - KpEqualAs400 = 0x0086, - International1 = 0x0087, - International2 = 0x0088, - International3 = 0x0089, - International4 = 0x008A, - International5 = 0x008B, - International6 = 0x008C, - International7 = 0x008D, - International8 = 0x008E, - International9 = 0x008F, - Language1 = 0x0090, - Language2 = 0x0091, - Language3 = 0x0092, - Language4 = 0x0093, - Language5 = 0x0094, - Language6 = 0x0095, - Language7 = 0x0096, - Language8 = 0x0097, - Language9 = 0x0098, - AlternateErase = 0x0099, - SystemRequest = 0x009A, - Cancel = 0x009B, - Clear = 0x009C, - Prior = 0x009D, - Return = 0x009E, - Separator = 0x009F, - Out = 0x00A0, - Oper = 0x00A1, - ClearAgain = 0x00A2, - Crsel = 0x00A3, - Exsel = 0x00A4, - SystemPower = 0x00A5, - SystemSleep = 0x00A6, - SystemWake = 0x00A7, - AudioMute = 0x00A8, - AudioVolUp = 0x00A9, - AudioVolDown = 0x00AA, - MediaNextTrack = 0x00AB, - MediaPrevTrack = 0x00AC, - MediaStop = 0x00AD, - MediaPlayPause = 0x00AE, - MediaSelect = 0x00AF, - MediaEject = 0x00B0, - Mail = 0x00B1, - Calculator = 0x00B2, - MyComputer = 0x00B3, - WwwSearch = 0x00B4, - WwwHome = 0x00B5, - WwwBack = 0x00B6, - WwwForward = 0x00B7, - WwwStop = 0x00B8, - WwwRefresh = 0x00B9, - WwwFavorites = 0x00BA, - MediaFastForward = 0x00BB, - MediaRewind = 0x00BC, - /// Brightness Up - BrightnessUp = 0x00BD, - /// Brightness Down - BrightnessDown = 0x00BE, - ControlPanel = 0x00BF, - Assistant = 0x00C0, - MissionControl = 0x00C1, - Launchpad = 0x00C2, - /// Mouse Up - MouseUp = 0x00CD, - /// Mouse Down - MouseDown = 0x00CE, - /// Mouse Left - MouseLeft = 0x00CF, - /// Mouse Right - MouseRight = 0x00D0, - /// Mouse Button 1(Left) - MouseBtn1 = 0x00D1, - /// Mouse Button 2(Right) - MouseBtn2 = 0x00D2, - /// Mouse Button 3(Middle) - MouseBtn3 = 0x00D3, - /// Mouse Button 4(Back) - MouseBtn4 = 0x00D4, - /// Mouse Button 5(Forward) - MouseBtn5 = 0x00D5, - MouseBtn6 = 0x00D6, - MouseBtn7 = 0x00D7, - MouseBtn8 = 0x00D8, - MouseWheelUp = 0x00D9, - MouseWheelDown = 0x00DA, - MouseWheelLeft = 0x00DB, - MouseWheelRight = 0x00DC, - MouseAccel0 = 0x00DD, - MouseAccel1 = 0x00DE, - MouseAccel2 = 0x00DF, - /// Left Control - LCtrl = 0x00E0, - /// Left Shift - LShift = 0x00E1, - /// Left Alt - LAlt = 0x00E2, - /// Left GUI - LGui = 0x00E3, - /// Right Control - RCtrl = 0x00E4, - /// Right Shift - RShift = 0x00E5, - /// Right Alt - RAlt = 0x00E6, - /// Right GUI - RGui = 0x00E7, - // Macro keycodes, use 0x500 ~ 0x5FF - Macro0 = 0x500, - Macro1 = 0x501, - Macro2 = 0x502, - Macro3 = 0x503, - Macro4 = 0x504, - Macro5 = 0x505, - Macro6 = 0x506, - Macro7 = 0x507, - Macro8 = 0x508, - Macro9 = 0x509, - Macro10 = 0x50A, - Macro11 = 0x50B, - Macro12 = 0x50C, - Macro13 = 0x50D, - Macro14 = 0x50E, - Macro15 = 0x50F, - Macro16 = 0x510, - Macro17 = 0x511, - Macro18 = 0x512, - Macro19 = 0x513, - Macro20 = 0x514, - Macro21 = 0x515, - Macro22 = 0x516, - Macro23 = 0x517, - Macro24 = 0x518, - Macro25 = 0x519, - Macro26 = 0x51A, - Macro27 = 0x51B, - Macro28 = 0x51C, - Macro29 = 0x51D, - Macro30 = 0x51E, - Macro31 = 0x51F, - // Backlight and RGB keycodes, uses 0x600 ~ 0x6FF - BacklightOn = 0x600, - BacklightOff = 0x601, - BacklightToggle = 0x602, - BacklightDown = 0x603, - BacklightUp = 0x604, - BacklightStep = 0x605, - BacklightToggleBreathing = 0x606, - RgbTog = 0x620, - RgbModeForward = 0x621, - RgbModeReverse = 0x622, - RgbHui = 0x623, - RgbHud = 0x624, - RgbSai = 0x625, - RgbSad = 0x626, - RgbVai = 0x627, - RgbVad = 0x628, - RgbSpi = 0x629, - RgbSpd = 0x62A, - RgbModePlain = 0x62B, - RgbModeBreathe = 0x62C, - RgbModeRainbow = 0x62D, - RgbModeSwirl = 0x62E, - RgbModeSnake = 0x62F, - RgbModeKnight = 0x630, - RgbModeXmas = 0x631, - RgbModeGradient = 0x632, - // Not in vial - RgbModeRgbtest = 0x633, - RgbModeTwinkle = 0x634, - // Internal functional keycodes, use 0x700 ~ 0x7FF - Bootloader = 0x700, - Reboot = 0x701, - DebugToggle = 0x702, - ClearEeprom = 0x703, - GraveEscape = 0x716, - OutputAuto = 0x720, - OutputUsb = 0x721, - OutputBluetooth = 0x722, - ComboOn = 0x750, - ComboOff = 0x751, - ComboToggle = 0x752, - CapsWordToggle = 0x773, - TriLayerLower = 0x777, - TriLayerUpper = 0x778, - RepeatKey = 0x779, - AltRepeatKey = 0x77A, - // User keycodes, use 0x840 ~ 0x85F - User0 = 0x840, - User1 = 0x841, - User2 = 0x842, - User3 = 0x843, - User4 = 0x844, - User5 = 0x845, - User6 = 0x846, - User7 = 0x847, - User8 = 0x848, - User9 = 0x849, - User10 = 0x84A, - User11 = 0x84B, - User12 = 0x84C, - User13 = 0x84D, - User14 = 0x84E, - User15 = 0x84F, - User16 = 0x850, - User17 = 0x851, - User18 = 0x852, - User19 = 0x853, - User20 = 0x854, - User21 = 0x855, - User22 = 0x856, - User23 = 0x857, - User24 = 0x858, - User25 = 0x859, - User26 = 0x85A, - User27 = 0x85B, - User28 = 0x85C, - User29 = 0x85D, - User30 = 0x85E, - User31 = 0x85F, -} - -impl ::postcard::experimental::max_size::MaxSize for KeyCode { - const POSTCARD_MAX_SIZE: usize = 3usize; -} - -impl KeyCode { - /// Returns `true` if the keycode is a simple keycode defined in HID spec - pub fn is_simple_key(self) -> bool { - KeyCode::No <= self && self <= KeyCode::MouseAccel2 - } - - /// Returns `true` if the keycode is a modifier keycode - pub fn is_modifier(self) -> bool { - KeyCode::LCtrl <= self && self <= KeyCode::RGui - } - - /// Returns `true` if the keycode is basic keycode - /// The basic keycode = simple key + modifier - pub fn is_basic(self) -> bool { - KeyCode::No <= self && self <= KeyCode::RGui - } - - /// Returns `true` if the keycode is a letter - pub fn is_letter(self) -> bool { - KeyCode::A <= self && self <= KeyCode::Z - } - - /// Returns the byte with the bit corresponding to the USB HID - /// modifier bitfield set. - pub fn to_hid_modifiers(self) -> ModifierCombination { - match self { - KeyCode::LCtrl => ModifierCombination::new().with_left_ctrl(true), - KeyCode::LShift => ModifierCombination::new().with_left_shift(true), - KeyCode::LAlt => ModifierCombination::new().with_left_alt(true), - KeyCode::LGui => ModifierCombination::new().with_left_gui(true), - KeyCode::RCtrl => ModifierCombination::new().with_right_ctrl(true), - KeyCode::RShift => ModifierCombination::new().with_right_shift(true), - KeyCode::RAlt => ModifierCombination::new().with_right_alt(true), - KeyCode::RGui => ModifierCombination::new().with_right_gui(true), - _ => ModifierCombination::new(), - } - } - - /// Returns `true` if the keycode is a system keycode - pub fn is_system(self) -> bool { - KeyCode::SystemPower <= self && self <= KeyCode::SystemWake - } - - /// Returns `true` if the keycode is a keycode in consumer page - pub fn is_consumer(self) -> bool { - KeyCode::AudioMute <= self && self <= KeyCode::Launchpad - } - - /// Returns `true` if the keycode is a mouse keycode - pub fn is_mouse_key(self) -> bool { - KeyCode::MouseUp <= self && self <= KeyCode::MouseAccel2 - } - - /// Returns `true` if the keycode is a combo keycode - pub fn is_combo(self) -> bool { - KeyCode::ComboOn <= self && self <= KeyCode::ComboToggle - } - - /// Returns `true` if the keycode is a macro keycode - pub fn is_macro(self) -> bool { - KeyCode::Macro0 <= self && self <= KeyCode::Macro31 - } - - /// Returns `true` if the keycode is a backlight keycode - pub fn is_backlight(self) -> bool { - KeyCode::BacklightOn <= self && self <= KeyCode::BacklightToggleBreathing - } - - /// Returns `true` if the keycode is a rgb keycode - pub fn is_rgb(self) -> bool { - KeyCode::RgbTog <= self && self <= KeyCode::RgbModeTwinkle - } - - /// Returns `true` if the keycode is defined by rmk to achieve special functionalities, such as reboot keyboard, goto bootloader, etc. - pub fn is_rmk(self) -> bool { - KeyCode::Bootloader <= self && self <= KeyCode::AltRepeatKey - } - - /// Returns `true` if the keycode is a boot keycode - pub fn is_boot(self) -> bool { - KeyCode::Bootloader <= self && self <= KeyCode::Reboot - } - /// Returns `true` if the keycode is a user keycode - pub fn is_user(self) -> bool { - KeyCode::User0 <= self && self <= KeyCode::User31 - } - - /// Convert a keycode to macro number - pub fn as_macro_index(self) -> Option { - if self.is_macro() { - Some((self as u16 & 0x1F) as u8) - } else { - None - } - } - - /// Does current keycode continues Caps Word? - pub fn is_caps_word_continue_key(self) -> bool { - if self >= KeyCode::A && self <= KeyCode::Z { - return true; - } - if self >= KeyCode::Kc1 && self <= KeyCode::Kc0 { - return true; - } - if self == KeyCode::Minus || self == KeyCode::Backspace || self == KeyCode::Delete { - return true; - } - false - } - - /// Does current keycode is to be shifted by Caps Word? - pub fn is_caps_word_shifted_key(self) -> bool { - if self >= KeyCode::A && self <= KeyCode::Z { - return true; - } - if self == KeyCode::Minus { - return true; - } - false - } - - /// Convert a keycode to usb hid media key - pub fn as_consumer_control_usage_id(self) -> ConsumerKey { - match self { - KeyCode::AudioMute => ConsumerKey::Mute, - KeyCode::AudioVolUp => ConsumerKey::VolumeIncrement, - KeyCode::AudioVolDown => ConsumerKey::VolumeDecrement, - KeyCode::MediaNextTrack => ConsumerKey::NextTrack, - KeyCode::MediaPrevTrack => ConsumerKey::PrevTrack, - KeyCode::MediaStop => ConsumerKey::StopPlay, - KeyCode::MediaPlayPause => ConsumerKey::PlayPause, - KeyCode::MediaSelect => ConsumerKey::Record, - KeyCode::MediaEject => ConsumerKey::Eject, - KeyCode::Mail => ConsumerKey::Email, - KeyCode::Calculator => ConsumerKey::Calculator, - KeyCode::MyComputer => ConsumerKey::LocalBrowser, - KeyCode::WwwSearch => ConsumerKey::Search, - KeyCode::WwwHome => ConsumerKey::Home, - KeyCode::WwwBack => ConsumerKey::Back, - KeyCode::WwwForward => ConsumerKey::Forward, - KeyCode::WwwStop => ConsumerKey::Stop, - KeyCode::WwwRefresh => ConsumerKey::Refresh, - KeyCode::WwwFavorites => ConsumerKey::Bookmarks, - KeyCode::MediaFastForward => ConsumerKey::FastForward, - KeyCode::MediaRewind => ConsumerKey::Rewind, - KeyCode::BrightnessUp => ConsumerKey::BrightnessUp, - KeyCode::BrightnessDown => ConsumerKey::BrightnessDown, - KeyCode::ControlPanel => ConsumerKey::ControlPanel, - KeyCode::Assistant => ConsumerKey::Assistant, - KeyCode::MissionControl => ConsumerKey::DesktopShowAllWindows, - KeyCode::Launchpad => ConsumerKey::AcSoftKeyLeft, - _ => ConsumerKey::No, - } - } - - /// Convert a keycode to usb hid media key - pub fn as_system_control_usage_id(self) -> Option { - match self { - KeyCode::SystemPower => Some(SystemControlKey::PowerDown), - KeyCode::SystemSleep => Some(SystemControlKey::Sleep), - KeyCode::SystemWake => Some(SystemControlKey::WakeUp), - _ => None, - } - } -} - -/// Convert a ascii chat to keycode -/// bool, if the keycode should be shifted -/// assumes en-us keyboard mapping -pub fn from_ascii(ascii: u8) -> (KeyCode, bool) { - match ascii { - b'0' => (KeyCode::Kc0, false), - b'1' => (KeyCode::Kc1, false), - b'2' => (KeyCode::Kc2, false), - b'3' => (KeyCode::Kc3, false), - b'4' => (KeyCode::Kc4, false), - b'5' => (KeyCode::Kc5, false), - b'6' => (KeyCode::Kc6, false), - b'7' => (KeyCode::Kc7, false), - b'8' => (KeyCode::Kc8, false), - b'9' => (KeyCode::Kc9, false), - b'a' => (KeyCode::A, false), - b'b' => (KeyCode::B, false), - b'c' => (KeyCode::C, false), - b'd' => (KeyCode::D, false), - b'e' => (KeyCode::E, false), - b'f' => (KeyCode::F, false), - b'g' => (KeyCode::G, false), - b'h' => (KeyCode::H, false), - b'i' => (KeyCode::I, false), - b'j' => (KeyCode::J, false), - b'k' => (KeyCode::K, false), - b'l' => (KeyCode::L, false), - b'm' => (KeyCode::M, false), - b'n' => (KeyCode::N, false), - b'o' => (KeyCode::O, false), - b'p' => (KeyCode::P, false), - b'q' => (KeyCode::Q, false), - b'r' => (KeyCode::R, false), - b's' => (KeyCode::S, false), - b't' => (KeyCode::T, false), - b'u' => (KeyCode::U, false), - b'v' => (KeyCode::V, false), - b'w' => (KeyCode::W, false), - b'x' => (KeyCode::X, false), - b'y' => (KeyCode::Y, false), - b'z' => (KeyCode::Z, false), - b'A' => (KeyCode::A, true), - b'B' => (KeyCode::B, true), - b'C' => (KeyCode::C, true), - b'D' => (KeyCode::D, true), - b'E' => (KeyCode::E, true), - b'F' => (KeyCode::F, true), - b'G' => (KeyCode::G, true), - b'H' => (KeyCode::H, true), - b'I' => (KeyCode::I, true), - b'J' => (KeyCode::J, true), - b'K' => (KeyCode::K, true), - b'L' => (KeyCode::L, true), - b'M' => (KeyCode::M, true), - b'N' => (KeyCode::N, true), - b'O' => (KeyCode::O, true), - b'P' => (KeyCode::P, true), - b'Q' => (KeyCode::Q, true), - b'R' => (KeyCode::R, true), - b'S' => (KeyCode::S, true), - b'T' => (KeyCode::T, true), - b'U' => (KeyCode::U, true), - b'V' => (KeyCode::V, true), - b'W' => (KeyCode::W, true), - b'X' => (KeyCode::X, true), - b'Y' => (KeyCode::Y, true), - b'Z' => (KeyCode::Z, true), - b'!' => (KeyCode::Kc1, true), - b'@' => (KeyCode::Kc2, true), - b'#' => (KeyCode::Kc3, true), - b'$' => (KeyCode::Kc4, true), - b'%' => (KeyCode::Kc5, true), - b'^' => (KeyCode::Kc6, true), - b'&' => (KeyCode::Kc7, true), - b'*' => (KeyCode::Kc8, true), - b'(' => (KeyCode::Kc9, true), - b')' => (KeyCode::Kc0, true), - b'-' => (KeyCode::Minus, false), - b'_' => (KeyCode::Minus, true), - b'=' => (KeyCode::Equal, false), - b'+' => (KeyCode::Equal, true), - b'[' => (KeyCode::LeftBracket, false), - b']' => (KeyCode::RightBracket, false), - b'{' => (KeyCode::LeftBracket, true), - b'}' => (KeyCode::RightBracket, true), - b';' => (KeyCode::Semicolon, false), - b':' => (KeyCode::Semicolon, true), - b'\'' => (KeyCode::Quote, false), - b'"' => (KeyCode::Quote, true), - b'`' => (KeyCode::Grave, false), - b'~' => (KeyCode::Grave, true), - b'\\' => (KeyCode::Backslash, false), - b'|' => (KeyCode::Backslash, true), - b',' => (KeyCode::Comma, false), - b'<' => (KeyCode::Comma, true), - b'.' => (KeyCode::Dot, false), - b'>' => (KeyCode::Dot, true), - b'/' => (KeyCode::Slash, false), - b'?' => (KeyCode::Slash, true), - b' ' => (KeyCode::Space, false), - b'\n' => (KeyCode::Enter, false), - b'\t' => (KeyCode::Tab, false), - b'\x08' => (KeyCode::Backspace, false), - b'\x1B' => (KeyCode::Escape, false), - b'\x7F' => (KeyCode::Delete, false), - _ => (KeyCode::No, false), - } -} - -/// Convert a ascii chat to keycode -/// assumes en-us keyboard mapping -pub fn to_ascii(keycode: KeyCode, shifted: bool) -> u8 { - match (keycode, shifted) { - (KeyCode::Kc0, false) => b'0', - (KeyCode::Kc1, false) => b'1', - (KeyCode::Kc2, false) => b'2', - (KeyCode::Kc3, false) => b'3', - (KeyCode::Kc4, false) => b'4', - (KeyCode::Kc5, false) => b'5', - (KeyCode::Kc6, false) => b'6', - (KeyCode::Kc7, false) => b'7', - (KeyCode::Kc8, false) => b'8', - (KeyCode::Kc9, false) => b'9', - (KeyCode::A, false) => b'a', - (KeyCode::B, false) => b'b', - (KeyCode::C, false) => b'c', - (KeyCode::D, false) => b'd', - (KeyCode::E, false) => b'e', - (KeyCode::F, false) => b'f', - (KeyCode::G, false) => b'g', - (KeyCode::H, false) => b'h', - (KeyCode::I, false) => b'i', - (KeyCode::J, false) => b'j', - (KeyCode::K, false) => b'k', - (KeyCode::L, false) => b'l', - (KeyCode::M, false) => b'm', - (KeyCode::N, false) => b'n', - (KeyCode::O, false) => b'o', - (KeyCode::P, false) => b'p', - (KeyCode::Q, false) => b'q', - (KeyCode::R, false) => b'r', - (KeyCode::S, false) => b's', - (KeyCode::T, false) => b't', - (KeyCode::U, false) => b'u', - (KeyCode::V, false) => b'v', - (KeyCode::W, false) => b'w', - (KeyCode::X, false) => b'x', - (KeyCode::Y, false) => b'y', - (KeyCode::Z, false) => b'z', - (KeyCode::A, true) => b'A', - (KeyCode::B, true) => b'B', - (KeyCode::C, true) => b'C', - (KeyCode::D, true) => b'D', - (KeyCode::E, true) => b'E', - (KeyCode::F, true) => b'F', - (KeyCode::G, true) => b'G', - (KeyCode::H, true) => b'H', - (KeyCode::I, true) => b'I', - (KeyCode::J, true) => b'J', - (KeyCode::K, true) => b'K', - (KeyCode::L, true) => b'L', - (KeyCode::M, true) => b'M', - (KeyCode::N, true) => b'N', - (KeyCode::O, true) => b'O', - (KeyCode::P, true) => b'P', - (KeyCode::Q, true) => b'Q', - (KeyCode::R, true) => b'R', - (KeyCode::S, true) => b'S', - (KeyCode::T, true) => b'T', - (KeyCode::U, true) => b'U', - (KeyCode::V, true) => b'V', - (KeyCode::W, true) => b'W', - (KeyCode::X, true) => b'X', - (KeyCode::Y, true) => b'Y', - (KeyCode::Z, true) => b'Z', - (KeyCode::Kc1, true) => b'!', - (KeyCode::Kc2, true) => b'@', - (KeyCode::Kc3, true) => b'#', - (KeyCode::Kc4, true) => b'$', - (KeyCode::Kc5, true) => b'%', - (KeyCode::Kc6, true) => b'^', - (KeyCode::Kc7, true) => b'&', - (KeyCode::Kc8, true) => b'*', - (KeyCode::Kc9, true) => b'(', - (KeyCode::Kc0, true) => b')', - (KeyCode::Minus, false) => b'-', - (KeyCode::Minus, true) => b'_', - (KeyCode::Equal, false) => b'=', - (KeyCode::Equal, true) => b'+', - (KeyCode::LeftBracket, false) => b'[', - (KeyCode::RightBracket, false) => b']', - (KeyCode::LeftBracket, true) => b'{', - (KeyCode::RightBracket, true) => b'}', - (KeyCode::Semicolon, false) => b';', - (KeyCode::Semicolon, true) => b':', - (KeyCode::Quote, false) => b'\'', - (KeyCode::Quote, true) => b'"', - (KeyCode::Grave, false) => b'`', - (KeyCode::Grave, true) => b'~', - (KeyCode::Backslash, true) => b'\\', - (KeyCode::Backslash, false) => b'|', - (KeyCode::Comma, false) => b',', - (KeyCode::Comma, true) => b'<', - (KeyCode::Dot, false) => b'.', - (KeyCode::Dot, true) => b'>', - (KeyCode::Slash, false) => b'/', - (KeyCode::Slash, true) => b'?', - (KeyCode::Space, false) => b' ', - (KeyCode::Enter, false) => b'\n', - (KeyCode::Tab, false) => b'\t', - (KeyCode::Backspace, false) => b'\x08', - (KeyCode::Escape, false) => b'\x1B', - (KeyCode::Delete, false) => b'\x7F', - // not supported keycodes - (_, _) => b'X', - } -} - -impl From for KeyCode { - fn from(value: u16) -> Self { - match value { - 0x0000 => Self::No, - 0x0001 => Self::ErrorRollover, - 0x0002 => Self::PostFail, - 0x0003 => Self::ErrorUndefined, - 0x0004 => Self::A, - 0x0005 => Self::B, - 0x0006 => Self::C, - 0x0007 => Self::D, - 0x0008 => Self::E, - 0x0009 => Self::F, - 0x000A => Self::G, - 0x000B => Self::H, - 0x000C => Self::I, - 0x000D => Self::J, - 0x000E => Self::K, - 0x000F => Self::L, - 0x0010 => Self::M, - 0x0011 => Self::N, - 0x0012 => Self::O, - 0x0013 => Self::P, - 0x0014 => Self::Q, - 0x0015 => Self::R, - 0x0016 => Self::S, - 0x0017 => Self::T, - 0x0018 => Self::U, - 0x0019 => Self::V, - 0x001A => Self::W, - 0x001B => Self::X, - 0x001C => Self::Y, - 0x001D => Self::Z, - 0x001E => Self::Kc1, - 0x001F => Self::Kc2, - 0x0020 => Self::Kc3, - 0x0021 => Self::Kc4, - 0x0022 => Self::Kc5, - 0x0023 => Self::Kc6, - 0x0024 => Self::Kc7, - 0x0025 => Self::Kc8, - 0x0026 => Self::Kc9, - 0x0027 => Self::Kc0, - 0x0028 => Self::Enter, - 0x0029 => Self::Escape, - 0x002A => Self::Backspace, - 0x002B => Self::Tab, - 0x002C => Self::Space, - 0x002D => Self::Minus, - 0x002E => Self::Equal, - 0x002F => Self::LeftBracket, - 0x0030 => Self::RightBracket, - 0x0031 => Self::Backslash, - 0x0032 => Self::NonusHash, - 0x0033 => Self::Semicolon, - 0x0034 => Self::Quote, - 0x0035 => Self::Grave, - 0x0036 => Self::Comma, - 0x0037 => Self::Dot, - 0x0038 => Self::Slash, - 0x0039 => Self::CapsLock, - 0x003A => Self::F1, - 0x003B => Self::F2, - 0x003C => Self::F3, - 0x003D => Self::F4, - 0x003E => Self::F5, - 0x003F => Self::F6, - 0x0040 => Self::F7, - 0x0041 => Self::F8, - 0x0042 => Self::F9, - 0x0043 => Self::F10, - 0x0044 => Self::F11, - 0x0045 => Self::F12, - 0x0046 => Self::PrintScreen, - 0x0047 => Self::ScrollLock, - 0x0048 => Self::Pause, - 0x0049 => Self::Insert, - 0x004A => Self::Home, - 0x004B => Self::PageUp, - 0x004C => Self::Delete, - 0x004D => Self::End, - 0x004E => Self::PageDown, - 0x004F => Self::Right, - 0x0050 => Self::Left, - 0x0051 => Self::Down, - 0x0052 => Self::Up, - 0x0053 => Self::NumLock, - 0x0054 => Self::KpSlash, - 0x0055 => Self::KpAsterisk, - 0x0056 => Self::KpMinus, - 0x0057 => Self::KpPlus, - 0x0058 => Self::KpEnter, - 0x0059 => Self::Kp1, - 0x005A => Self::Kp2, - 0x005B => Self::Kp3, - 0x005C => Self::Kp4, - 0x005D => Self::Kp5, - 0x005E => Self::Kp6, - 0x005F => Self::Kp7, - 0x0060 => Self::Kp8, - 0x0061 => Self::Kp9, - 0x0062 => Self::Kp0, - 0x0063 => Self::KpDot, - 0x0064 => Self::NonusBackslash, - 0x0065 => Self::Application, - 0x0066 => Self::KbPower, - 0x0067 => Self::KpEqual, - 0x0068 => Self::F13, - 0x0069 => Self::F14, - 0x006A => Self::F15, - 0x006B => Self::F16, - 0x006C => Self::F17, - 0x006D => Self::F18, - 0x006E => Self::F19, - 0x006F => Self::F20, - 0x0070 => Self::F21, - 0x0071 => Self::F22, - 0x0072 => Self::F23, - 0x0073 => Self::F24, - 0x0074 => Self::Execute, - 0x0075 => Self::Help, - 0x0076 => Self::Menu, - 0x0077 => Self::Select, - 0x0078 => Self::Stop, - 0x0079 => Self::Again, - 0x007A => Self::Undo, - 0x007B => Self::Cut, - 0x007C => Self::Copy, - 0x007D => Self::Paste, - 0x007E => Self::Find, - 0x007F => Self::KbMute, - 0x0080 => Self::KbVolumeUp, - 0x0081 => Self::KbVolumeDown, - 0x0082 => Self::LockingCapsLock, - 0x0083 => Self::LockingNumLock, - 0x0084 => Self::LockingScrollLock, - 0x0085 => Self::KpComma, - 0x0086 => Self::KpEqualAs400, - 0x0087 => Self::International1, - 0x0088 => Self::International2, - 0x0089 => Self::International3, - 0x008A => Self::International4, - 0x008B => Self::International5, - 0x008C => Self::International6, - 0x008D => Self::International7, - 0x008E => Self::International8, - 0x008F => Self::International9, - 0x0090 => Self::Language1, - 0x0091 => Self::Language2, - 0x0092 => Self::Language3, - 0x0093 => Self::Language4, - 0x0094 => Self::Language5, - 0x0095 => Self::Language6, - 0x0096 => Self::Language7, - 0x0097 => Self::Language8, - 0x0098 => Self::Language9, - 0x0099 => Self::AlternateErase, - 0x009A => Self::SystemRequest, - 0x009B => Self::Cancel, - 0x009C => Self::Clear, - 0x009D => Self::Prior, - 0x009E => Self::Return, - 0x009F => Self::Separator, - 0x00A0 => Self::Out, - 0x00A1 => Self::Oper, - 0x00A2 => Self::ClearAgain, - 0x00A3 => Self::Crsel, - 0x00A4 => Self::Exsel, - 0x00A5 => Self::SystemPower, - 0x00A6 => Self::SystemSleep, - 0x00A7 => Self::SystemWake, - 0x00A8 => Self::AudioMute, - 0x00A9 => Self::AudioVolUp, - 0x00AA => Self::AudioVolDown, - 0x00AB => Self::MediaNextTrack, - 0x00AC => Self::MediaPrevTrack, - 0x00AD => Self::MediaStop, - 0x00AE => Self::MediaPlayPause, - 0x00AF => Self::MediaSelect, - 0x00B0 => Self::MediaEject, - 0x00B1 => Self::Mail, - 0x00B2 => Self::Calculator, - 0x00B3 => Self::MyComputer, - 0x00B4 => Self::WwwSearch, - 0x00B5 => Self::WwwHome, - 0x00B6 => Self::WwwBack, - 0x00B7 => Self::WwwForward, - 0x00B8 => Self::WwwStop, - 0x00B9 => Self::WwwRefresh, - 0x00BA => Self::WwwFavorites, - 0x00BB => Self::MediaFastForward, - 0x00BC => Self::MediaRewind, - 0x00BD => Self::BrightnessUp, - 0x00BE => Self::BrightnessDown, - 0x00BF => Self::ControlPanel, - 0x00C0 => Self::Assistant, - 0x00C1 => Self::MissionControl, - 0x00C2 => Self::Launchpad, - 0x00CD => Self::MouseUp, - 0x00CE => Self::MouseDown, - 0x00CF => Self::MouseLeft, - 0x00D0 => Self::MouseRight, - 0x00D1 => Self::MouseBtn1, - 0x00D2 => Self::MouseBtn2, - 0x00D3 => Self::MouseBtn3, - 0x00D4 => Self::MouseBtn4, - 0x00D5 => Self::MouseBtn5, - 0x00D6 => Self::MouseBtn6, - 0x00D7 => Self::MouseBtn7, - 0x00D8 => Self::MouseBtn8, - 0x00D9 => Self::MouseWheelUp, - 0x00DA => Self::MouseWheelDown, - 0x00DB => Self::MouseWheelLeft, - 0x00DC => Self::MouseWheelRight, - 0x00DD => Self::MouseAccel0, - 0x00DE => Self::MouseAccel1, - 0x00DF => Self::MouseAccel2, - 0x00E0 => Self::LCtrl, - 0x00E1 => Self::LShift, - 0x00E2 => Self::LAlt, - 0x00E3 => Self::LGui, - 0x00E4 => Self::RCtrl, - 0x00E5 => Self::RShift, - 0x00E6 => Self::RAlt, - 0x00E7 => Self::RGui, - 0x500 => Self::Macro0, - 0x501 => Self::Macro1, - 0x502 => Self::Macro2, - 0x503 => Self::Macro3, - 0x504 => Self::Macro4, - 0x505 => Self::Macro5, - 0x506 => Self::Macro6, - 0x507 => Self::Macro7, - 0x508 => Self::Macro8, - 0x509 => Self::Macro9, - 0x50A => Self::Macro10, - 0x50B => Self::Macro11, - 0x50C => Self::Macro12, - 0x50D => Self::Macro13, - 0x50E => Self::Macro14, - 0x50F => Self::Macro15, - 0x510 => Self::Macro16, - 0x511 => Self::Macro17, - 0x512 => Self::Macro18, - 0x513 => Self::Macro19, - 0x514 => Self::Macro20, - 0x515 => Self::Macro21, - 0x516 => Self::Macro22, - 0x517 => Self::Macro23, - 0x518 => Self::Macro24, - 0x519 => Self::Macro25, - 0x51A => Self::Macro26, - 0x51B => Self::Macro27, - 0x51C => Self::Macro28, - 0x51D => Self::Macro29, - 0x51E => Self::Macro30, - 0x51F => Self::Macro31, - 0x600 => Self::BacklightOn, - 0x601 => Self::BacklightOff, - 0x602 => Self::BacklightToggle, - 0x603 => Self::BacklightDown, - 0x604 => Self::BacklightUp, - 0x605 => Self::BacklightStep, - 0x606 => Self::BacklightToggleBreathing, - 0x620 => Self::RgbTog, - 0x621 => Self::RgbModeForward, - 0x622 => Self::RgbModeReverse, - 0x623 => Self::RgbHui, - 0x624 => Self::RgbHud, - 0x625 => Self::RgbSai, - 0x626 => Self::RgbSad, - 0x627 => Self::RgbVai, - 0x628 => Self::RgbVad, - 0x629 => Self::RgbSpi, - 0x62A => Self::RgbSpd, - 0x62B => Self::RgbModePlain, - 0x62C => Self::RgbModeBreathe, - 0x62D => Self::RgbModeRainbow, - 0x62E => Self::RgbModeSwirl, - 0x62F => Self::RgbModeSnake, - 0x630 => Self::RgbModeKnight, - 0x631 => Self::RgbModeXmas, - 0x632 => Self::RgbModeGradient, - 0x633 => Self::RgbModeRgbtest, - 0x634 => Self::RgbModeTwinkle, - 0x700 => Self::Bootloader, - 0x701 => Self::Reboot, - 0x702 => Self::DebugToggle, - 0x703 => Self::ClearEeprom, - 0x716 => Self::GraveEscape, - 0x720 => Self::OutputAuto, - 0x721 => Self::OutputUsb, - 0x722 => Self::OutputBluetooth, - 0x750 => Self::ComboOn, - 0x751 => Self::ComboOff, - 0x752 => Self::ComboToggle, - 0x773 => Self::CapsWordToggle, - 0x777 => Self::TriLayerLower, - 0x778 => Self::TriLayerUpper, - 0x779 => Self::RepeatKey, - 0x77A => Self::AltRepeatKey, - 0x840 => Self::User0, - 0x841 => Self::User1, - 0x842 => Self::User2, - 0x843 => Self::User3, - 0x844 => Self::User4, - 0x845 => Self::User5, - 0x846 => Self::User6, - 0x847 => Self::User7, - 0x848 => Self::User8, - 0x849 => Self::User9, - 0x84A => Self::User10, - 0x84B => Self::User11, - 0x84C => Self::User12, - 0x84D => Self::User13, - 0x84E => Self::User14, - 0x84F => Self::User15, - 0x850 => Self::User16, - 0x851 => Self::User17, - 0x852 => Self::User18, - 0x853 => Self::User19, - 0x854 => Self::User20, - 0x855 => Self::User21, - 0x856 => Self::User22, - 0x857 => Self::User23, - 0x858 => Self::User24, - 0x859 => Self::User25, - 0x85A => Self::User26, - 0x85B => Self::User27, - 0x85C => Self::User28, - 0x85D => Self::User29, - 0x85E => Self::User30, - 0x85F => Self::User31, - _ => Self::No, - } - } -} - -/// Keys in consumer page -/// Ref: -#[non_exhaustive] -#[repr(u16)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, FromRepr)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum ConsumerKey { - No = 0x00, - // 15.5 Display Controls - SnapShot = 0x65, - /// - BrightnessUp = 0x6F, - BrightnessDown = 0x70, - // 15.7 Transport Controls - Play = 0xB0, - Pause = 0xB1, - Record = 0xB2, - FastForward = 0xB3, - Rewind = 0xB4, - NextTrack = 0xB5, - PrevTrack = 0xB6, - StopPlay = 0xB7, - Eject = 0xB8, - RandomPlay = 0xB9, - Repeat = 0xBC, - StopEject = 0xCC, - PlayPause = 0xCD, - // 15.9.1 Audio Controls - Volume - Mute = 0xE2, - VolumeIncrement = 0xE9, - VolumeDecrement = 0xEA, - Reserved = 0xEB, - // 15.15 Application Launch Buttons - Email = 0x18A, - Calculator = 0x192, - LocalBrowser = 0x194, - Lock = 0x19E, - ControlPanel = 0x19F, - Assistant = 0x1CB, - // 15.16 Generic GUI Application Controls - New = 0x201, - Open = 0x202, - Close = 0x203, - Exit = 0x204, - Maximize = 0x205, - Minimize = 0x206, - Save = 0x207, - Print = 0x208, - Properties = 0x209, - Undo = 0x21A, - Copy = 0x21B, - Cut = 0x21C, - Paste = 0x21D, - SelectAll = 0x21E, - Find = 0x21F, - Search = 0x221, - Home = 0x223, - Back = 0x224, - Forward = 0x225, - Stop = 0x226, - Refresh = 0x227, - Bookmarks = 0x22A, - NextKeyboardLayoutSelect = 0x29D, - DesktopShowAllWindows = 0x29F, - AcSoftKeyLeft = 0x2A0, -} - -impl ::postcard::experimental::max_size::MaxSize for ConsumerKey { - const POSTCARD_MAX_SIZE: usize = 3usize; -} - -impl From for ConsumerKey { - fn from(value: u16) -> Self { - match value { - 0x00 => Self::No, - 0x65 => Self::SnapShot, - 0x6F => Self::BrightnessUp, - 0x70 => Self::BrightnessDown, - 0xB0 => Self::Play, - 0xB1 => Self::Pause, - 0xB2 => Self::Record, - 0xB3 => Self::FastForward, - 0xB4 => Self::Rewind, - 0xB5 => Self::NextTrack, - 0xB6 => Self::PrevTrack, - 0xB7 => Self::StopPlay, - 0xB8 => Self::Eject, - 0xB9 => Self::RandomPlay, - 0xBC => Self::Repeat, - 0xCC => Self::StopEject, - 0xCD => Self::PlayPause, - 0xE2 => Self::Mute, - 0xE9 => Self::VolumeIncrement, - 0xEA => Self::VolumeDecrement, - 0xEB => Self::Reserved, - 0x18A => Self::Email, - 0x192 => Self::Calculator, - 0x194 => Self::LocalBrowser, - 0x19E => Self::Lock, - 0x19F => Self::ControlPanel, - 0x1CB => Self::Assistant, - 0x201 => Self::New, - 0x202 => Self::Open, - 0x203 => Self::Close, - 0x204 => Self::Exit, - 0x205 => Self::Maximize, - 0x206 => Self::Minimize, - 0x207 => Self::Save, - 0x208 => Self::Print, - 0x209 => Self::Properties, - 0x21A => Self::Undo, - 0x21B => Self::Copy, - 0x21C => Self::Cut, - 0x21D => Self::Paste, - 0x21E => Self::SelectAll, - 0x21F => Self::Find, - 0x221 => Self::Search, - 0x223 => Self::Home, - 0x224 => Self::Back, - 0x225 => Self::Forward, - 0x226 => Self::Stop, - 0x227 => Self::Refresh, - 0x22A => Self::Bookmarks, - 0x29D => Self::NextKeyboardLayoutSelect, - 0x29F => Self::DesktopShowAllWindows, - 0x2A0 => Self::AcSoftKeyLeft, - _ => Self::No, - } - } -} - -/// Keys in `Generic Desktop Page`, generally used for system control -/// Ref: -#[non_exhaustive] -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, FromRepr)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum SystemControlKey { - No = 0x00, - PowerDown = 0x81, - Sleep = 0x82, - WakeUp = 0x83, - Restart = 0x8F, -} - -impl ::postcard::experimental::max_size::MaxSize for SystemControlKey { - const POSTCARD_MAX_SIZE: usize = 1usize; -} - -impl From for SystemControlKey { - fn from(value: u16) -> Self { - match value { - 0x00 => Self::No, - 0x81 => Self::PowerDown, - 0x82 => Self::Sleep, - 0x83 => Self::WakeUp, - 0x8F => Self::Restart, - _ => Self::No, - } - } -} From cae2cf9952ec5d865a491160d211bf897dafee36 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 30 Dec 2025 22:29:38 +0800 Subject: [PATCH 5/9] fix: fix example build error Signed-off-by: Haobo Gu --- examples/use_config/stm32f4/src/main.rs | 16 +- examples/use_config/stm32h7/Cargo.lock | 407 +--------------------- examples/use_config/stm32h7/Cargo.toml | 2 +- examples/use_config/stm32h7/keyboard.toml | 2 +- examples/use_config/stm32h7/src/main.rs | 3 +- rmk/src/host/via/vial.rs | 98 +++--- 6 files changed, 64 insertions(+), 464 deletions(-) diff --git a/examples/use_config/stm32f4/src/main.rs b/examples/use_config/stm32f4/src/main.rs index fb414e7fe..2e04377ff 100644 --- a/examples/use_config/stm32f4/src/main.rs +++ b/examples/use_config/stm32f4/src/main.rs @@ -18,24 +18,24 @@ mod keyboard { { use embassy_stm32::rcc::*; config.rcc.hse = Some(Hse { - // freq: Hertz(25_000_000), - freq: Hertz(8_000_000), + freq: Hertz(25_000_000), + // freq: Hertz(8_000_000), mode: HseMode::Oscillator, }); config.rcc.pll_src = PllSource::HSE; config.rcc.pll = Some(Pll { - // prediv: PllPreDiv::DIV25, - prediv: PllPreDiv::DIV8, + prediv: PllPreDiv::DIV25, + // prediv: PllPreDiv::DIV8, mul: PllMul::MUL192, divp: Some(PllPDiv::DIV2), // 25mhz / 25 * 192 / 2 = 96Mhz. divq: Some(PllQDiv::DIV4), // 25mhz / 25 * 192 / 4 = 48Mhz. divr: None, }); config.rcc.ahb_pre = AHBPrescaler::DIV1; - // config.rcc.apb1_pre = APBPrescaler::DIV2; - // config.rcc.apb2_pre = APBPrescaler::DIV1; - config.rcc.apb1_pre = APBPrescaler::DIV4; - config.rcc.apb2_pre = APBPrescaler::DIV2; + config.rcc.apb1_pre = APBPrescaler::DIV2; + config.rcc.apb2_pre = APBPrescaler::DIV1; + // config.rcc.apb1_pre = APBPrescaler::DIV4; + // config.rcc.apb2_pre = APBPrescaler::DIV2; config.rcc.sys = Sysclk::PLL1_P; } config diff --git a/examples/use_config/stm32h7/Cargo.lock b/examples/use_config/stm32h7/Cargo.lock index 6b2e60670..bee6f2cbe 100644 --- a/examples/use_config/stm32h7/Cargo.lock +++ b/examples/use_config/stm32h7/Cargo.lock @@ -2,17 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - [[package]] name = "ahash" version = "0.8.12" @@ -84,12 +73,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "az" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" - [[package]] name = "bare-metal" version = "0.2.5" @@ -99,12 +82,6 @@ dependencies = [ "rustc_version 0.2.3", ] -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - [[package]] name = "bit_field" version = "0.10.3" @@ -167,43 +144,12 @@ dependencies = [ "aligned", ] -[[package]] -name = "bt-hci" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb938a3b4c5cc6c2409275bad789c0346a0495fa071a0acc5d72b9bd3175a2f7" -dependencies = [ - "btuuid", - "defmt 1.0.1", - "embassy-sync", - "embedded-io", - "embedded-io-async", - "futures-intrusive", - "heapless 0.9.2", -] - -[[package]] -name = "btuuid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0acfef8a77a02866e04f7e2ad3f4c7b32d575696c49c4bbad742b4aecb8e4a3" -dependencies = [ - "defmt 0.3.100", - "uuid", -] - [[package]] name = "bumpalo" version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" -[[package]] -name = "bytemuck" -version = "1.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" - [[package]] name = "byteorder" version = "1.5.0" @@ -249,27 +195,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - -[[package]] -name = "cmac" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8543454e3c3f5126effff9cd44d562af4e31fb8ce1cc0d3dcd8f084515dbc1aa" -dependencies = [ - "cipher", - "dbl", - "digest", -] - [[package]] name = "cobs" version = "0.3.0" @@ -286,7 +211,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b30fa8254caad766fc03cb0ccae691e14bf3bd72bfff27f72802ce729551b3d6" dependencies = [ "async-trait", - "convert_case 0.6.0", + "convert_case", "json5", "pathdiff", "ron", @@ -319,12 +244,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - [[package]] name = "const-random" version = "0.1.18" @@ -354,15 +273,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "convert_case" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -432,18 +342,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - [[package]] name = "crypto-common" version = "0.1.7" @@ -489,15 +387,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "dbl" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd2735a791158376708f9347fe8faba9667589d82427ef3aed6794a8981de3d9" -dependencies = [ - "generic-array", -] - [[package]] name = "defmt" version = "0.3.100" @@ -549,16 +438,6 @@ dependencies = [ "defmt 1.0.1", ] -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid", - "zeroize", -] - [[package]] name = "digest" version = "0.10.7" @@ -567,7 +446,6 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", - "subtle", ] [[package]] @@ -588,25 +466,6 @@ dependencies = [ "litrs", ] -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest", - "ff", - "generic-array", - "group", - "hkdf", - "rand_core 0.6.4", - "sec1", - "subtle", - "zeroize", -] - [[package]] name = "embassy-embedded-hal" version = "0.5.0" @@ -663,9 +522,6 @@ name = "embassy-futures" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01" -dependencies = [ - "defmt 1.0.1", -] [[package]] name = "embassy-hal-internal" @@ -699,37 +555,6 @@ dependencies = [ "embassy-sync", ] -[[package]] -name = "embassy-nrf" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d63429d74ab5786cde7c9dc9a0338ea162a4da95e204ac5345c5ae36831fdb" -dependencies = [ - "bitflags 2.10.0", - "cfg-if", - "cortex-m", - "cortex-m-rt", - "critical-section", - "defmt 1.0.1", - "document-features", - "embassy-embedded-hal", - "embassy-hal-internal", - "embassy-sync", - "embassy-time", - "embassy-usb-driver", - "embedded-hal 0.2.7", - "embedded-hal 1.0.0", - "embedded-hal-async", - "embedded-io", - "embedded-io-async", - "embedded-storage", - "embedded-storage-async", - "fixed", - "nrf-pac", - "rand_core 0.6.4", - "rand_core 0.9.3", -] - [[package]] name = "embassy-stm32" version = "0.4.0" @@ -836,7 +661,6 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc4462e48b19a4f401a11901bdd981aab80c6a826608016a0bdc73cbbab31954" dependencies = [ - "defmt 1.0.1", "embassy-futures", "embassy-net-driver-channel", "embassy-sync", @@ -893,9 +717,6 @@ name = "embedded-hal" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" -dependencies = [ - "defmt 0.3.100", -] [[package]] name = "embedded-hal-async" @@ -903,7 +724,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" dependencies = [ - "defmt 0.3.100", "embedded-hal 1.0.0", ] @@ -983,34 +803,12 @@ dependencies = [ "typeid", ] -[[package]] -name = "ff" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "find-msvc-tools" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" -[[package]] -name = "fixed" -version = "1.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707070ccf8c4173548210893a0186e29c266901b71ed20cd9e2ca0193dfe95c3" -dependencies = [ - "az", - "bytemuck", - "half", - "typenum", -] - [[package]] name = "fnv" version = "1.0.7" @@ -1053,16 +851,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" -[[package]] -name = "futures-intrusive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" -dependencies = [ - "futures-core", - "lock_api", -] - [[package]] name = "futures-io" version = "0.3.31" @@ -1114,7 +902,6 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", - "zeroize", ] [[package]] @@ -1128,28 +915,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "half" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" -dependencies = [ - "cfg-if", - "crunchy", - "zerocopy", -] - [[package]] name = "hash32" version = "0.2.1" @@ -1237,7 +1002,6 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af2455f757db2b292a9b1768c4b70186d443bcb3b316252d6b540aec1cd89ed" dependencies = [ - "defmt 1.0.1", "hash32 0.3.1", "stable_deref_trait", ] @@ -1248,24 +1012,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - [[package]] name = "iana-time-zone" version = "0.1.64" @@ -1306,15 +1052,6 @@ dependencies = [ "hashbrown 0.16.1", ] -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "generic-array", -] - [[package]] name = "itoa" version = "1.0.15" @@ -1407,16 +1144,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" -[[package]] -name = "nrf-pac" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d334027d6703534f2a80de0794ae435c0e029358d28278533d3935e69b221b01" -dependencies = [ - "cortex-m", - "cortex-m-rt", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -1442,16 +1169,6 @@ dependencies = [ "hashbrown 0.14.5", ] -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "elliptic-curve", - "primeorder", -] - [[package]] name = "panic-probe" version = "1.0.0" @@ -1548,7 +1265,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" dependencies = [ "cobs", - "defmt 1.0.1", "heapless 0.7.17", "postcard-derive", "serde", @@ -1565,15 +1281,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "prettyplease" version = "0.2.37" @@ -1584,15 +1291,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - [[package]] name = "proc-macro-error-attr2" version = "2.0.0" @@ -1633,25 +1331,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - [[package]] name = "rand_core" version = "0.6.4" @@ -1669,26 +1348,21 @@ name = "rmk" version = "0.8.2" dependencies = [ "bitfield-struct", - "bt-hci", "byteorder", "chrono", "const-gen", "cortex-m", "crc32fast", - "defmt 1.0.1", "document-features", "embassy-embedded-hal", "embassy-executor", "embassy-futures", - "embassy-nrf", "embassy-sync", "embassy-time", "embassy-usb", "embedded-hal 1.0.0", "embedded-hal-async", "embedded-io-async", - "embedded-storage", - "embedded-storage-async", "futures", "heapless 0.9.2", "paste", @@ -1703,7 +1377,6 @@ dependencies = [ "static_cell", "strum", "toml", - "trouble-host", "usbd-hid 0.9.0", ] @@ -1766,7 +1439,6 @@ name = "rmk-types" version = "0.2.2" dependencies = [ "bitfield-struct", - "defmt 1.0.1", "postcard", "serde", "strum", @@ -1838,19 +1510,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b328e2cb950eeccd55b7f55c3a963691455dcd044cfb5354f0c5e68d2c2d6ee2" -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "subtle", - "zeroize", -] - [[package]] name = "semver" version = "0.9.0" @@ -1878,7 +1537,6 @@ version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f93d860af08a0079f1c596b65176d5ea2bca1f977ba6210d4547aa16865477" dependencies = [ - "defmt 1.0.1", "embedded-storage-async", ] @@ -2061,12 +1719,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - [[package]] name = "syn" version = "1.0.109" @@ -2157,45 +1809,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" -[[package]] -name = "trouble-host" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2881b4859001fe1f48445145cda5149deac9110b1d707ec0a251b7ff6d8bdfa4" -dependencies = [ - "aes", - "bt-hci", - "cmac", - "defmt 1.0.1", - "embassy-futures", - "embassy-sync", - "embassy-time", - "embedded-io", - "futures", - "heapless 0.9.2", - "p256", - "rand", - "rand_chacha", - "rand_core 0.6.4", - "static_cell", - "trouble-host-macros", - "zerocopy", -] - -[[package]] -name = "trouble-host-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcb85bec3a8393c22ca1a7c25c82c2d33689ab412f3487c492fd01a033ede7c2" -dependencies = [ - "convert_case 0.8.0", - "darling", - "proc-macro2", - "quote", - "syn 2.0.111", - "uuid", -] - [[package]] name = "typeid" version = "1.0.3" @@ -2232,7 +1845,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6" dependencies = [ - "defmt 0.3.100", "heapless 0.8.0", "portable-atomic", ] @@ -2255,7 +1867,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a7cd3bfb2bb57779f2aeab3f679e5ec6c80265adfe77894539792be7c22aaf0" dependencies = [ - "defmt 0.3.100", "serde", "ssmarshal", "usb-device", @@ -2312,16 +1923,6 @@ dependencies = [ "usbd-hid-descriptors 0.9.0", ] -[[package]] -name = "uuid" -version = "1.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "vcell" version = "0.1.3" @@ -2507,9 +2108,3 @@ dependencies = [ "quote", "syn 2.0.111", ] - -[[package]] -name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" diff --git a/examples/use_config/stm32h7/Cargo.toml b/examples/use_config/stm32h7/Cargo.toml index ba855848e..6ddfe3ecf 100644 --- a/examples/use_config/stm32h7/Cargo.toml +++ b/examples/use_config/stm32h7/Cargo.toml @@ -10,7 +10,7 @@ edition = "2024" license = "MIT OR Apache-2.0" [dependencies] -rmk = { path = "../../../rmk", features = ["async_matrix", "controller"] } +rmk = { path = "../../../rmk", default-features = false, features = ["async_matrix", "controller", "vial"] } cortex-m = { version = "0.7.7", features = ['critical-section-single-core'] } cortex-m-rt = "0.7.5" embassy-time = { version = "0.5", features = ["tick-hz-32_768", "defmt"] } diff --git a/examples/use_config/stm32h7/keyboard.toml b/examples/use_config/stm32h7/keyboard.toml index 1ad2860d0..53678a101 100644 --- a/examples/use_config/stm32h7/keyboard.toml +++ b/examples/use_config/stm32h7/keyboard.toml @@ -44,7 +44,7 @@ scrolllock.low_active = false [storage] # Storage feature is enabled by default -# enabled = false +enabled = false [dependency] defmt_log = false \ No newline at end of file diff --git a/examples/use_config/stm32h7/src/main.rs b/examples/use_config/stm32h7/src/main.rs index 140eaf71d..36528d2f2 100644 --- a/examples/use_config/stm32h7/src/main.rs +++ b/examples/use_config/stm32h7/src/main.rs @@ -83,7 +83,8 @@ mod my_keyboard { join3( run_devices!((matrix) => EVENT_CHANNEL), keyboard.run(), - run_rmk(&keymap, driver, &mut storage, rmk_config), + // run_rmk(&keymap, driver, &mut storage, rmk_config), + run_rmk(&keymap, driver, rmk_config), ) .await; } diff --git a/rmk/src/host/via/vial.rs b/rmk/src/host/via/vial.rs index d0bc44bb3..0471b7793 100644 --- a/rmk/src/host/via/vial.rs +++ b/rmk/src/host/via/vial.rs @@ -7,13 +7,12 @@ use rmk_types::protocol::vial::{ SettingKey, VIAL_COMBO_MAX_LENGTH, VIAL_EP_SIZE, VIAL_PROTOCOL_VERSION, VialCommand, VialDynamic, }; -use crate::combo::{Combo, ComboConfig}; use crate::config::VialConfig; use crate::descriptor::ViaReport; use crate::host::via::keycode_convert::{from_via_keycode, to_via_keycode}; use crate::keymap::KeyMap; use crate::morse::{DOUBLE_TAP, HOLD, HOLD_AFTER_TAP, TAP}; -use crate::{COMBO_MAX_LENGTH, COMBO_MAX_NUM, MORSE_MAX_NUM}; +use crate::{COMBO_MAX_NUM, MORSE_MAX_NUM}; #[cfg(feature = "storage")] use crate::{channel::FLASH_CHANNEL, host::storage::KeymapData, storage::FlashOperationMessage}; @@ -416,56 +415,61 @@ pub(crate) async fn process_vial< debug!("DynamicEntryOp - DynamicVialComboSet"); report.input_data[0] = 0; // Index 0 is the return code, 0 means success - // Drop combos to release the borrowed keymap, avoid potential run-time panics - let combo_idx = report.output_data[3] as usize; - let (actions, output) = { - let km = &mut keymap.borrow_mut(); - let combos = &mut km.behavior.combo.combos; - if combo_idx >= combos.len() { - return; - } + #[cfg(feature = "storage")] + { + use crate::COMBO_MAX_LENGTH; + use crate::combo::{Combo, ComboConfig}; + // Drop combos to release the borrowed keymap, avoid potential run-time panics + let combo_idx = report.output_data[3] as usize; + let (actions, output) = { + let km = &mut keymap.borrow_mut(); + let combos = &mut km.behavior.combo.combos; + if combo_idx >= combos.len() { + return; + } - let mut actions = [KeyAction::No; COMBO_MAX_LENGTH]; - let mut n: usize = 0; - for i in 0..VIAL_COMBO_MAX_LENGTH { - let action = - from_via_keycode(LittleEndian::read_u16(&report.output_data[4 + i * 2..6 + i * 2])); - if !action.is_empty() { - if n >= COMBO_MAX_LENGTH { - // Fail if the combo action buffer is too small - return; + let mut actions = [KeyAction::No; COMBO_MAX_LENGTH]; + let mut n: usize = 0; + for i in 0..VIAL_COMBO_MAX_LENGTH { + let action = + from_via_keycode(LittleEndian::read_u16(&report.output_data[4 + i * 2..6 + i * 2])); + if !action.is_empty() { + if n >= COMBO_MAX_LENGTH { + // Fail if the combo action buffer is too small + return; + } + actions[n] = action; + n += 1; } - actions[n] = action; - n += 1; } - } - let output = from_via_keycode(LittleEndian::read_u16( - &report.output_data[4 + VIAL_COMBO_MAX_LENGTH * 2..6 + VIAL_COMBO_MAX_LENGTH * 2], - )); - combos[combo_idx] = if !actions.iter().any(|&x| x != KeyAction::No) && output == KeyAction::No { - debug!("combo is empty"); - None - } else { - Some(Combo::new(ComboConfig { - actions, - output, - layer: None, - })) + let output = from_via_keycode(LittleEndian::read_u16( + &report.output_data[4 + VIAL_COMBO_MAX_LENGTH * 2..6 + VIAL_COMBO_MAX_LENGTH * 2], + )); + combos[combo_idx] = + if !actions.iter().any(|&x| x != KeyAction::No) && output == KeyAction::No { + debug!("combo is empty"); + None + } else { + Some(Combo::new(ComboConfig { + actions, + output, + layer: None, + })) + }; + (actions, output) }; - (actions, output) - }; - #[cfg(feature = "storage")] - FLASH_CHANNEL - .send(FlashOperationMessage::VialMessage(KeymapData::Combo( - combo_idx as u8, - ComboConfig { - actions, - output, - layer: None, - }, - ))) - .await; + FLASH_CHANNEL + .send(FlashOperationMessage::VialMessage(KeymapData::Combo( + combo_idx as u8, + ComboConfig { + actions, + output, + layer: None, + }, + ))) + .await; + } } VialDynamic::DynamicVialKeyOverrideGet => { warn!("DynamicEntryOp - DynamicVialKeyOverrideGet -- to be implemented"); From 47a3bfc5d3a9f4739e987e3729ae564b42312ca1 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 30 Dec 2025 22:42:10 +0800 Subject: [PATCH 6/9] test: fix test imports Signed-off-by: Haobo Gu --- rmk/src/host/via/vial.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rmk/src/host/via/vial.rs b/rmk/src/host/via/vial.rs index 0471b7793..6bf95b66e 100644 --- a/rmk/src/host/via/vial.rs +++ b/rmk/src/host/via/vial.rs @@ -565,6 +565,8 @@ mod tests { use sequential_storage::map::Value; use super::*; + use crate::COMBO_MAX_LENGTH; + use crate::combo::ComboConfig; use crate::storage::StorageData; #[test] fn test_combo_serialization_deserialization() { From f5610d7aa81f245bc4e8a187998cb31cf718f409 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Wed, 31 Dec 2025 00:04:10 +0800 Subject: [PATCH 7/9] refactor(types): use `FromRepr` for `HidKeyCode` Signed-off-by: Haobo Gu --- rmk-types/src/keycode.rs | 229 +-------------------------------------- 1 file changed, 3 insertions(+), 226 deletions(-) diff --git a/rmk-types/src/keycode.rs b/rmk-types/src/keycode.rs index c92ce72d1..f6a107267 100644 --- a/rmk-types/src/keycode.rs +++ b/rmk-types/src/keycode.rs @@ -1,10 +1,11 @@ use serde::{Deserialize, Serialize}; +use strum::FromRepr; use crate::modifier::ModifierCombination; // All key codes defined in HID spec #[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, FromRepr)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum HidKeyCode { @@ -482,231 +483,7 @@ impl ::postcard::experimental::max_size::MaxSize for HidKeyCode { impl From for HidKeyCode { fn from(value: u8) -> Self { - match value { - 0x00 => HidKeyCode::No, - 0x01 => HidKeyCode::ErrorRollover, - 0x02 => HidKeyCode::PostFail, - 0x03 => HidKeyCode::ErrorUndefined, - 0x04 => HidKeyCode::A, - 0x05 => HidKeyCode::B, - 0x06 => HidKeyCode::C, - 0x07 => HidKeyCode::D, - 0x08 => HidKeyCode::E, - 0x09 => HidKeyCode::F, - 0x0A => HidKeyCode::G, - 0x0B => HidKeyCode::H, - 0x0C => HidKeyCode::I, - 0x0D => HidKeyCode::J, - 0x0E => HidKeyCode::K, - 0x0F => HidKeyCode::L, - 0x10 => HidKeyCode::M, - 0x11 => HidKeyCode::N, - 0x12 => HidKeyCode::O, - 0x13 => HidKeyCode::P, - 0x14 => HidKeyCode::Q, - 0x15 => HidKeyCode::R, - 0x16 => HidKeyCode::S, - 0x17 => HidKeyCode::T, - 0x18 => HidKeyCode::U, - 0x19 => HidKeyCode::V, - 0x1A => HidKeyCode::W, - 0x1B => HidKeyCode::X, - 0x1C => HidKeyCode::Y, - 0x1D => HidKeyCode::Z, - 0x1E => HidKeyCode::Kc1, - 0x1F => HidKeyCode::Kc2, - 0x20 => HidKeyCode::Kc3, - 0x21 => HidKeyCode::Kc4, - 0x22 => HidKeyCode::Kc5, - 0x23 => HidKeyCode::Kc6, - 0x24 => HidKeyCode::Kc7, - 0x25 => HidKeyCode::Kc8, - 0x26 => HidKeyCode::Kc9, - 0x27 => HidKeyCode::Kc0, - 0x28 => HidKeyCode::Enter, - 0x29 => HidKeyCode::Escape, - 0x2A => HidKeyCode::Backspace, - 0x2B => HidKeyCode::Tab, - 0x2C => HidKeyCode::Space, - 0x2D => HidKeyCode::Minus, - 0x2E => HidKeyCode::Equal, - 0x2F => HidKeyCode::LeftBracket, - 0x30 => HidKeyCode::RightBracket, - 0x31 => HidKeyCode::Backslash, - 0x32 => HidKeyCode::NonusHash, - 0x33 => HidKeyCode::Semicolon, - 0x34 => HidKeyCode::Quote, - 0x35 => HidKeyCode::Grave, - 0x36 => HidKeyCode::Comma, - 0x37 => HidKeyCode::Dot, - 0x38 => HidKeyCode::Slash, - 0x39 => HidKeyCode::CapsLock, - 0x3A => HidKeyCode::F1, - 0x3B => HidKeyCode::F2, - 0x3C => HidKeyCode::F3, - 0x3D => HidKeyCode::F4, - 0x3E => HidKeyCode::F5, - 0x3F => HidKeyCode::F6, - 0x40 => HidKeyCode::F7, - 0x41 => HidKeyCode::F8, - 0x42 => HidKeyCode::F9, - 0x43 => HidKeyCode::F10, - 0x44 => HidKeyCode::F11, - 0x45 => HidKeyCode::F12, - 0x46 => HidKeyCode::PrintScreen, - 0x47 => HidKeyCode::ScrollLock, - 0x48 => HidKeyCode::Pause, - 0x49 => HidKeyCode::Insert, - 0x4A => HidKeyCode::Home, - 0x4B => HidKeyCode::PageUp, - 0x4C => HidKeyCode::Delete, - 0x4D => HidKeyCode::End, - 0x4E => HidKeyCode::PageDown, - 0x4F => HidKeyCode::Right, - 0x50 => HidKeyCode::Left, - 0x51 => HidKeyCode::Down, - 0x52 => HidKeyCode::Up, - 0x53 => HidKeyCode::NumLock, - 0x54 => HidKeyCode::KpSlash, - 0x55 => HidKeyCode::KpAsterisk, - 0x56 => HidKeyCode::KpMinus, - 0x57 => HidKeyCode::KpPlus, - 0x58 => HidKeyCode::KpEnter, - 0x59 => HidKeyCode::Kp1, - 0x5A => HidKeyCode::Kp2, - 0x5B => HidKeyCode::Kp3, - 0x5C => HidKeyCode::Kp4, - 0x5D => HidKeyCode::Kp5, - 0x5E => HidKeyCode::Kp6, - 0x5F => HidKeyCode::Kp7, - 0x60 => HidKeyCode::Kp8, - 0x61 => HidKeyCode::Kp9, - 0x62 => HidKeyCode::Kp0, - 0x63 => HidKeyCode::KpDot, - 0x64 => HidKeyCode::NonusBackslash, - 0x65 => HidKeyCode::Application, - 0x66 => HidKeyCode::KbPower, - 0x67 => HidKeyCode::KpEqual, - 0x68 => HidKeyCode::F13, - 0x69 => HidKeyCode::F14, - 0x6A => HidKeyCode::F15, - 0x6B => HidKeyCode::F16, - 0x6C => HidKeyCode::F17, - 0x6D => HidKeyCode::F18, - 0x6E => HidKeyCode::F19, - 0x6F => HidKeyCode::F20, - 0x70 => HidKeyCode::F21, - 0x71 => HidKeyCode::F22, - 0x72 => HidKeyCode::F23, - 0x73 => HidKeyCode::F24, - 0x74 => HidKeyCode::Execute, - 0x75 => HidKeyCode::Help, - 0x76 => HidKeyCode::Menu, - 0x77 => HidKeyCode::Select, - 0x78 => HidKeyCode::Stop, - 0x79 => HidKeyCode::Again, - 0x7A => HidKeyCode::Undo, - 0x7B => HidKeyCode::Cut, - 0x7C => HidKeyCode::Copy, - 0x7D => HidKeyCode::Paste, - 0x7E => HidKeyCode::Find, - 0x7F => HidKeyCode::KbMute, - 0x80 => HidKeyCode::KbVolumeUp, - 0x81 => HidKeyCode::KbVolumeDown, - 0x82 => HidKeyCode::LockingCapsLock, - 0x83 => HidKeyCode::LockingNumLock, - 0x84 => HidKeyCode::LockingScrollLock, - 0x85 => HidKeyCode::KpComma, - 0x86 => HidKeyCode::KpEqualAs400, - 0x87 => HidKeyCode::International1, - 0x88 => HidKeyCode::International2, - 0x89 => HidKeyCode::International3, - 0x8A => HidKeyCode::International4, - 0x8B => HidKeyCode::International5, - 0x8C => HidKeyCode::International6, - 0x8D => HidKeyCode::International7, - 0x8E => HidKeyCode::International8, - 0x8F => HidKeyCode::International9, - 0x90 => HidKeyCode::Language1, - 0x91 => HidKeyCode::Language2, - 0x92 => HidKeyCode::Language3, - 0x93 => HidKeyCode::Language4, - 0x94 => HidKeyCode::Language5, - 0x95 => HidKeyCode::Language6, - 0x96 => HidKeyCode::Language7, - 0x97 => HidKeyCode::Language8, - 0x98 => HidKeyCode::Language9, - 0x99 => HidKeyCode::AlternateErase, - 0x9A => HidKeyCode::SystemRequest, - 0x9B => HidKeyCode::Cancel, - 0x9C => HidKeyCode::Clear, - 0x9D => HidKeyCode::Prior, - 0x9E => HidKeyCode::Return, - 0x9F => HidKeyCode::Separator, - 0xA0 => HidKeyCode::Out, - 0xA1 => HidKeyCode::Oper, - 0xA2 => HidKeyCode::ClearAgain, - 0xA3 => HidKeyCode::Crsel, - 0xA4 => HidKeyCode::Exsel, - 0xA5 => HidKeyCode::SystemPower, - 0xA6 => HidKeyCode::SystemSleep, - 0xA7 => HidKeyCode::SystemWake, - 0xA8 => HidKeyCode::AudioMute, - 0xA9 => HidKeyCode::AudioVolUp, - 0xAA => HidKeyCode::AudioVolDown, - 0xAB => HidKeyCode::MediaNextTrack, - 0xAC => HidKeyCode::MediaPrevTrack, - 0xAD => HidKeyCode::MediaStop, - 0xAE => HidKeyCode::MediaPlayPause, - 0xAF => HidKeyCode::MediaSelect, - 0xB0 => HidKeyCode::MediaEject, - 0xB1 => HidKeyCode::Mail, - 0xB2 => HidKeyCode::Calculator, - 0xB3 => HidKeyCode::MyComputer, - 0xB4 => HidKeyCode::WwwSearch, - 0xB5 => HidKeyCode::WwwHome, - 0xB6 => HidKeyCode::WwwBack, - 0xB7 => HidKeyCode::WwwForward, - 0xB8 => HidKeyCode::WwwStop, - 0xB9 => HidKeyCode::WwwRefresh, - 0xBA => HidKeyCode::WwwFavorites, - 0xBB => HidKeyCode::MediaFastForward, - 0xBC => HidKeyCode::MediaRewind, - 0xBD => HidKeyCode::BrightnessUp, - 0xBE => HidKeyCode::BrightnessDown, - 0xBF => HidKeyCode::ControlPanel, - 0xC0 => HidKeyCode::Assistant, - 0xC1 => HidKeyCode::MissionControl, - 0xC2 => HidKeyCode::Launchpad, - 0xCD => HidKeyCode::MouseUp, - 0xCE => HidKeyCode::MouseDown, - 0xCF => HidKeyCode::MouseLeft, - 0xD0 => HidKeyCode::MouseRight, - 0xD1 => HidKeyCode::MouseBtn1, - 0xD2 => HidKeyCode::MouseBtn2, - 0xD3 => HidKeyCode::MouseBtn3, - 0xD4 => HidKeyCode::MouseBtn4, - 0xD5 => HidKeyCode::MouseBtn5, - 0xD6 => HidKeyCode::MouseBtn6, - 0xD7 => HidKeyCode::MouseBtn7, - 0xD8 => HidKeyCode::MouseBtn8, - 0xD9 => HidKeyCode::MouseWheelUp, - 0xDA => HidKeyCode::MouseWheelDown, - 0xDB => HidKeyCode::MouseWheelLeft, - 0xDC => HidKeyCode::MouseWheelRight, - 0xDD => HidKeyCode::MouseAccel0, - 0xDE => HidKeyCode::MouseAccel1, - 0xDF => HidKeyCode::MouseAccel2, - 0xE0 => HidKeyCode::LCtrl, - 0xE1 => HidKeyCode::LShift, - 0xE2 => HidKeyCode::LAlt, - 0xE3 => HidKeyCode::LGui, - 0xE4 => HidKeyCode::RCtrl, - 0xE5 => HidKeyCode::RShift, - 0xE6 => HidKeyCode::RAlt, - 0xE7 => HidKeyCode::RGui, - _ => HidKeyCode::No, - } + Self::from_repr(value).unwrap_or(HidKeyCode::No) } } From 78e57683c68cd93365146f9f45df5d3456519a00 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Wed, 31 Dec 2025 00:14:56 +0800 Subject: [PATCH 8/9] refactor: fix fmt and clippy Signed-off-by: Haobo Gu --- rmk-macro/src/layout.rs | 4 +- rmk-types/src/keycode.rs | 1 - rmk/src/host/storage.rs | 10 ++- rmk/src/host/via/keycode_convert.rs | 43 +++++++--- rmk/src/keyboard.rs | 47 +++++------ rmk/src/keyboard_macros.rs | 6 +- rmk/src/layout_macro.rs | 32 ++++++-- rmk/src/morse.rs | 80 +++++++++++++++---- rmk/tests/common/morse.rs | 60 +++++++++++--- ...keyboard_morse_hold_on_other_press_test.rs | 6 +- rmk/tests/keyboard_morse_hrm_test.rs | 6 +- .../keyboard_morse_permissive_hold_test.rs | 6 +- 12 files changed, 217 insertions(+), 84 deletions(-) diff --git a/rmk-macro/src/layout.rs b/rmk-macro/src/layout.rs index 18c15419b..7a3bf4b14 100644 --- a/rmk-macro/src/layout.rs +++ b/rmk-macro/src/layout.rs @@ -437,7 +437,9 @@ pub(crate) fn parse_key(key: String, profiles: &Option { + s if s.to_lowercase().starts_with("macro") + && s[5..].chars().next().map(|c| c.is_ascii_digit()).unwrap_or(false) => + { // Support Macro0, Macro1, Macro2, etc. let index_str = &s[5..]; let index = index_str.parse::().unwrap(); diff --git a/rmk-types/src/keycode.rs b/rmk-types/src/keycode.rs index f6a107267..9662f6070 100644 --- a/rmk-types/src/keycode.rs +++ b/rmk-types/src/keycode.rs @@ -7,7 +7,6 @@ use crate::modifier::ModifierCombination; #[repr(u8)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, FromRepr)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] - pub enum HidKeyCode { /// Reserved, no-key. No = 0x0000, diff --git a/rmk/src/host/storage.rs b/rmk/src/host/storage.rs index 6ddcb1f7c..85be17f50 100644 --- a/rmk/src/host/storage.rs +++ b/rmk/src/host/storage.rs @@ -375,11 +375,17 @@ mod tests { .ok(); morse .actions - .insert(MorsePattern::from_u16(0b1_1000), Action::Key(KeyCode::Hid(HidKeyCode::B))) + .insert( + MorsePattern::from_u16(0b1_1000), + Action::Key(KeyCode::Hid(HidKeyCode::B)), + ) .ok(); morse .actions - .insert(MorsePattern::from_u16(0b1_1010), Action::Key(KeyCode::Hid(HidKeyCode::C))) + .insert( + MorsePattern::from_u16(0b1_1010), + Action::Key(KeyCode::Hid(HidKeyCode::C)), + ) .ok(); // Serialization diff --git a/rmk/src/host/via/keycode_convert.rs b/rmk/src/host/via/keycode_convert.rs index 7d1e6f768..cc33263fd 100644 --- a/rmk/src/host/via/keycode_convert.rs +++ b/rmk/src/host/via/keycode_convert.rs @@ -15,7 +15,10 @@ pub(crate) fn to_via_keycode(key_action: KeyAction) -> u16 { if let Some(hid_keycode) = consumer_key.to_hid_keycode() { hid_keycode as u16 } else { - warn!("Consumer key {:?} has no corresponding HID keycode for VIA", consumer_key); + warn!( + "Consumer key {:?} has no corresponding HID keycode for VIA", + consumer_key + ); 0 } } @@ -23,7 +26,10 @@ pub(crate) fn to_via_keycode(key_action: KeyAction) -> u16 { if let Some(hid_keycode) = system_key.to_hid_keycode() { hid_keycode as u16 } else { - warn!("SystemControl key {:?} has no corresponding HID keycode for VIA", system_key); + warn!( + "SystemControl key {:?} has no corresponding HID keycode for VIA", + system_key + ); 0 } } @@ -212,7 +218,7 @@ pub(crate) fn from_via_keycode(via_keycode: u16) -> KeyAction { 0x7C77 => KeyAction::Single(Action::Keyboard(KeyboardAction::TriLayerLower)), 0x7C78 => KeyAction::Single(Action::Keyboard(KeyboardAction::TriLayerUpper)), 0x7C79 => KeyAction::Single(Action::Special(SpecialKey::Repeat)), - 0x7C00..=0x7C5F => { + 0x7C02..=0x7C5F => { // TODO: Reset/Space Cadet/Haptic/Auto shift(AS)/Dynamic macro // - [Space Cadet](https://docs.qmk.fm/#/feature_space_cadet) warn!( @@ -234,9 +240,10 @@ pub(crate) fn from_via_keycode(via_keycode: u16) -> KeyAction { #[cfg(test)] mod test { - use super::*; use rmk_types::keycode::HidKeyCode; + use super::*; + #[test] fn test_convert_via_keycode_to_key_action() { // A @@ -316,14 +323,22 @@ mod test { // LT0(A) -> LayerTapHold(A, 0) let via_keycode = 0x4004; assert_eq!( - KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::LayerOn(0), Default::default()), + KeyAction::TapHold( + Action::Key(KeyCode::Hid(HidKeyCode::A)), + Action::LayerOn(0), + Default::default() + ), from_via_keycode(via_keycode) ); // LT3(A) -> LayerTapHold(A, 3) let via_keycode = 0x4304; assert_eq!( - KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::LayerOn(3), Default::default()), + KeyAction::TapHold( + Action::Key(KeyCode::Hid(HidKeyCode::A)), + Action::LayerOn(3), + Default::default() + ), from_via_keycode(via_keycode) ); @@ -477,11 +492,19 @@ mod test { assert_eq!(0xF04, to_via_keycode(a)); // LT0(A) -> LayerTapHold(A, 0) - let a = KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::LayerOn(0), Default::default()); + let a = KeyAction::TapHold( + Action::Key(KeyCode::Hid(HidKeyCode::A)), + Action::LayerOn(0), + Default::default(), + ); assert_eq!(0x4004, to_via_keycode(a)); // LT3(A) -> LayerTapHold(A, 3) - let a = KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::A)), Action::LayerOn(3), Default::default()); + let a = KeyAction::TapHold( + Action::Key(KeyCode::Hid(HidKeyCode::A)), + Action::LayerOn(3), + Default::default(), + ); assert_eq!(0x4304, to_via_keycode(a)); // LSA_T(A) -> @@ -583,7 +606,7 @@ mod test { #[test] fn test_convert_from_to_ascii_a() { - use rmk_types::keycode::{from_ascii, to_ascii, HidKeyCode}; + use rmk_types::keycode::{HidKeyCode, from_ascii, to_ascii}; let keycode = HidKeyCode::A; let shifted = false; @@ -594,7 +617,7 @@ mod test { } #[test] fn test_convert_from_to_ascii_K() { - use rmk_types::keycode::{from_ascii, to_ascii, HidKeyCode}; + use rmk_types::keycode::{HidKeyCode, from_ascii, to_ascii}; let keycode = HidKeyCode::K; let shifted = true; diff --git a/rmk/src/keyboard.rs b/rmk/src/keyboard.rs index 7774b3fb5..a4281adc3 100644 --- a/rmk/src/keyboard.rs +++ b/rmk/src/keyboard.rs @@ -1477,27 +1477,27 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E } // Pre-check - if event.pressed { - if let KeyCode::Hid(hid_keycode) = key { - // Check hid keycodes - // Record last press time - if hid_keycode.is_simple_key() { - // Records only the simple key - self.last_press_time = Instant::now(); - } - - // Update last key code - if hid_keycode != HidKeyCode::Again { - debug!( - "Last key code changed from {:?} to {:?}(pressed: {:?})", - self.last_key_code, key, event.pressed - ); - self.last_key_code = key; - } + if event.pressed + && let KeyCode::Hid(hid_keycode) = key + { + // Check hid keycodes + // Record last press time + if hid_keycode.is_simple_key() { + // Records only the simple key + self.last_press_time = Instant::now(); + } - // Check Caps Word - self.caps_word.check(hid_keycode); + // Update last key code + if hid_keycode != HidKeyCode::Again { + debug!( + "Last key code changed from {:?} to {:?}(pressed: {:?})", + self.last_key_code, key, event.pressed + ); + self.last_key_code = key; } + + // Check Caps Word + self.caps_word.check(hid_keycode); } match key { @@ -1531,15 +1531,6 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E } } - /// Process combo action. - async fn process_action_combo(&mut self, key: KeyCode, event: KeyboardEvent) { - if event.pressed { - match key { - _ => (), - } - } - } - /// Process consumer control action. Consumer control keys are keys in hid consumer page, such as media keys. async fn process_action_consumer_control(&mut self, key: ConsumerKey, event: KeyboardEvent) { self.media_report.usage_id = if event.pressed { key as u16 } else { 0 }; diff --git a/rmk/src/keyboard_macros.rs b/rmk/src/keyboard_macros.rs index 6c44a9f79..532190a75 100644 --- a/rmk/src/keyboard_macros.rs +++ b/rmk/src/keyboard_macros.rs @@ -44,7 +44,7 @@ impl MacroOperation { (0, _) => (MacroOperation::End, offset), (1, 1) => { if idx + 2 < macro_sequences.len() { - let keycode = (macro_sequences[idx + 2] as u8).into(); + let keycode = macro_sequences[idx + 2].into(); (MacroOperation::Tap(keycode), offset + 3) } else { (MacroOperation::End, offset + 3) @@ -52,7 +52,7 @@ impl MacroOperation { } (1, 2) => { if idx + 2 < macro_sequences.len() { - let keycode = (macro_sequences[idx + 2] as u8).into(); + let keycode = macro_sequences[idx + 2].into(); (MacroOperation::Press(keycode), offset + 3) } else { (MacroOperation::End, offset + 3) @@ -60,7 +60,7 @@ impl MacroOperation { } (1, 3) => { if idx + 2 < macro_sequences.len() { - let keycode = (macro_sequences[idx + 2] as u8).into(); + let keycode = macro_sequences[idx + 2].into(); (MacroOperation::Release(keycode), offset + 3) } else { (MacroOperation::End, offset + 3) diff --git a/rmk/src/layout_macro.rs b/rmk/src/layout_macro.rs index f79b507c4..2a6e4453a 100644 --- a/rmk/src/layout_macro.rs +++ b/rmk/src/layout_macro.rs @@ -155,7 +155,9 @@ macro_rules! lm { macro_rules! lt { ($x: literal, $k: ident) => { $crate::types::action::KeyAction::TapHold( - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$k)), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid( + $crate::types::keycode::HidKeyCode::$k, + )), $crate::types::action::Action::LayerOn($x), $crate::types::action::MorseProfile::const_default(), ) @@ -181,7 +183,9 @@ macro_rules! lt { macro_rules! ltp { ($x: literal, $k: ident, $p: expr) => { $crate::types::action::KeyAction::TapHold( - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$k)), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid( + $crate::types::keycode::HidKeyCode::$k, + )), $crate::types::action::Action::LayerOn($x), $p, ) @@ -210,7 +214,9 @@ macro_rules! ltp { macro_rules! mt { ($k: ident, $m: expr) => { $crate::types::action::KeyAction::TapHold( - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$k)), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid( + $crate::types::keycode::HidKeyCode::$k, + )), $crate::types::action::Action::Modifier($m), $crate::types::action::MorseProfile::const_default(), ) @@ -235,7 +241,9 @@ macro_rules! mt { macro_rules! mtp { ($k: ident, $m: expr, $p: expr) => { $crate::types::action::KeyAction::TapHold( - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$k)), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid( + $crate::types::keycode::HidKeyCode::$k, + )), $crate::types::action::Action::Modifier($m), $p, ) @@ -263,8 +271,12 @@ macro_rules! mtp { macro_rules! th { ($t: ident, $h: ident) => { $crate::types::action::KeyAction::TapHold( - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$t)), - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$h)), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid( + $crate::types::keycode::HidKeyCode::$t, + )), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid( + $crate::types::keycode::HidKeyCode::$h, + )), $crate::types::action::MorseProfile::const_default(), ) }; @@ -288,8 +300,12 @@ macro_rules! th { macro_rules! thp { ($t: ident, $h: ident, $p: expr) => { $crate::types::action::KeyAction::TapHold( - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$t)), - $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid($crate::types::keycode::HidKeyCode::$h)), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid( + $crate::types::keycode::HidKeyCode::$t, + )), + $crate::types::action::Action::Key($crate::types::keycode::KeyCode::Hid( + $crate::types::keycode::HidKeyCode::$h, + )), $p, ) }; diff --git a/rmk/src/morse.rs b/rmk/src/morse.rs index 586571eb6..73d5780d7 100644 --- a/rmk/src/morse.rs +++ b/rmk/src/morse.rs @@ -309,7 +309,10 @@ mod tests { let deserialized: Morse<4> = postcard::from_bytes(serialized).unwrap(); assert_eq!(morse.actions.len(), deserialized.actions.len()); - assert_eq!(deserialized.actions.get(&TAP), Some(&Action::Key(KeyCode::Hid(HidKeyCode::A)))); + assert_eq!( + deserialized.actions.get(&TAP), + Some(&Action::Key(KeyCode::Hid(HidKeyCode::A))) + ); } #[test] @@ -320,9 +323,18 @@ mod tests { actions: heapless::LinearMap::default(), }; morse.actions.insert(TAP, Action::Key(KeyCode::Hid(HidKeyCode::A))).ok(); - morse.actions.insert(HOLD, Action::Key(KeyCode::Hid(HidKeyCode::B))).ok(); - morse.actions.insert(DOUBLE_TAP, Action::Key(KeyCode::Hid(HidKeyCode::C))).ok(); - morse.actions.insert(HOLD_AFTER_TAP, Action::Key(KeyCode::Hid(HidKeyCode::D))).ok(); + morse + .actions + .insert(HOLD, Action::Key(KeyCode::Hid(HidKeyCode::B))) + .ok(); + morse + .actions + .insert(DOUBLE_TAP, Action::Key(KeyCode::Hid(HidKeyCode::C))) + .ok(); + morse + .actions + .insert(HOLD_AFTER_TAP, Action::Key(KeyCode::Hid(HidKeyCode::D))) + .ok(); let mut buffer = [0u8; 128]; let serialized = postcard::to_slice(&morse, &mut buffer).unwrap(); @@ -332,9 +344,18 @@ mod tests { assert_eq!(morse.actions.len(), 4); // Verify each entry - assert_eq!(deserialized.actions.get(&TAP), Some(&Action::Key(KeyCode::Hid(HidKeyCode::A)))); - assert_eq!(deserialized.actions.get(&HOLD), Some(&Action::Key(KeyCode::Hid(HidKeyCode::B)))); - assert_eq!(deserialized.actions.get(&DOUBLE_TAP), Some(&Action::Key(KeyCode::Hid(HidKeyCode::C)))); + assert_eq!( + deserialized.actions.get(&TAP), + Some(&Action::Key(KeyCode::Hid(HidKeyCode::A))) + ); + assert_eq!( + deserialized.actions.get(&HOLD), + Some(&Action::Key(KeyCode::Hid(HidKeyCode::B))) + ); + assert_eq!( + deserialized.actions.get(&DOUBLE_TAP), + Some(&Action::Key(KeyCode::Hid(HidKeyCode::C))) + ); assert_eq!( deserialized.actions.get(&HOLD_AFTER_TAP), Some(&Action::Key(KeyCode::Hid(HidKeyCode::D))) @@ -354,11 +375,17 @@ mod tests { .ok(); morse .actions - .insert(MorsePattern::from_u16(0b1_1000), Action::Key(KeyCode::Hid(HidKeyCode::F))) + .insert( + MorsePattern::from_u16(0b1_1000), + Action::Key(KeyCode::Hid(HidKeyCode::F)), + ) .ok(); morse .actions - .insert(MorsePattern::from_u16(0b1_1010), Action::Key(KeyCode::Hid(HidKeyCode::G))) + .insert( + MorsePattern::from_u16(0b1_1010), + Action::Key(KeyCode::Hid(HidKeyCode::G)), + ) .ok(); let mut buffer = [0u8; 128]; @@ -387,7 +414,10 @@ mod tests { actions: heapless::LinearMap::default(), }; morse.actions.insert(TAP, Action::Key(KeyCode::Hid(HidKeyCode::H))).ok(); - morse.actions.insert(HOLD, Action::Key(KeyCode::Hid(HidKeyCode::I))).ok(); + morse + .actions + .insert(HOLD, Action::Key(KeyCode::Hid(HidKeyCode::I))) + .ok(); let mut buffer = [0u8; 128]; let serialized = postcard::to_slice(&morse, &mut buffer).unwrap(); @@ -395,8 +425,14 @@ mod tests { assert_eq!(morse.profile, deserialized.profile); assert_eq!(morse.actions.len(), deserialized.actions.len()); - assert_eq!(deserialized.actions.get(&TAP), Some(&Action::Key(KeyCode::Hid(HidKeyCode::H)))); - assert_eq!(deserialized.actions.get(&HOLD), Some(&Action::Key(KeyCode::Hid(HidKeyCode::I)))); + assert_eq!( + deserialized.actions.get(&TAP), + Some(&Action::Key(KeyCode::Hid(HidKeyCode::H))) + ); + assert_eq!( + deserialized.actions.get(&HOLD), + Some(&Action::Key(KeyCode::Hid(HidKeyCode::I))) + ); } #[test] @@ -406,15 +442,27 @@ mod tests { profile: MorseProfile::const_default(), actions: heapless::LinearMap::default(), }; - morse1.actions.insert(TAP, Action::Key(KeyCode::Hid(HidKeyCode::A))).ok(); - morse1.actions.insert(HOLD, Action::Key(KeyCode::Hid(HidKeyCode::B))).ok(); + morse1 + .actions + .insert(TAP, Action::Key(KeyCode::Hid(HidKeyCode::A))) + .ok(); + morse1 + .actions + .insert(HOLD, Action::Key(KeyCode::Hid(HidKeyCode::B))) + .ok(); let mut morse2 = Morse::<4> { profile: MorseProfile::const_default(), actions: heapless::LinearMap::default(), }; - morse2.actions.insert(HOLD, Action::Key(KeyCode::Hid(HidKeyCode::B))).ok(); - morse2.actions.insert(TAP, Action::Key(KeyCode::Hid(HidKeyCode::A))).ok(); + morse2 + .actions + .insert(HOLD, Action::Key(KeyCode::Hid(HidKeyCode::B))) + .ok(); + morse2 + .actions + .insert(TAP, Action::Key(KeyCode::Hid(HidKeyCode::A))) + .ok(); let mut buffer1 = [0u8; 128]; let mut buffer2 = [0u8; 128]; diff --git a/rmk/tests/common/morse.rs b/rmk/tests/common/morse.rs index 0445978e5..d68114215 100644 --- a/rmk/tests/common/morse.rs +++ b/rmk/tests/common/morse.rs @@ -25,13 +25,31 @@ pub fn create_simple_morse_keyboard(behavior_config: BehaviorConfig) -> Keyboard actions: LinearMap::from_iter( [ (MorsePattern::from_u16(0b1_01), Action::Key(KeyCode::Hid(HidKeyCode::A))), - (MorsePattern::from_u16(0b1_1000), Action::Key(KeyCode::Hid(HidKeyCode::B))), - (MorsePattern::from_u16(0b1_1010), Action::Key(KeyCode::Hid(HidKeyCode::C))), - (MorsePattern::from_u16(0b1_101), Action::Key(KeyCode::Hid(HidKeyCode::K))), + ( + MorsePattern::from_u16(0b1_1000), + Action::Key(KeyCode::Hid(HidKeyCode::B)), + ), + ( + MorsePattern::from_u16(0b1_1010), + Action::Key(KeyCode::Hid(HidKeyCode::C)), + ), + ( + MorsePattern::from_u16(0b1_101), + Action::Key(KeyCode::Hid(HidKeyCode::K)), + ), (MorsePattern::from_u16(0b1_11), Action::Key(KeyCode::Hid(HidKeyCode::M))), - (MorsePattern::from_u16(0b1_111), Action::Key(KeyCode::Hid(HidKeyCode::O))), - (MorsePattern::from_u16(0b1_010), Action::Key(KeyCode::Hid(HidKeyCode::R))), - (MorsePattern::from_u16(0b1_000), Action::Key(KeyCode::Hid(HidKeyCode::S))), + ( + MorsePattern::from_u16(0b1_111), + Action::Key(KeyCode::Hid(HidKeyCode::O)), + ), + ( + MorsePattern::from_u16(0b1_010), + Action::Key(KeyCode::Hid(HidKeyCode::R)), + ), + ( + MorsePattern::from_u16(0b1_000), + Action::Key(KeyCode::Hid(HidKeyCode::S)), + ), ] .into_iter(), ), @@ -69,13 +87,31 @@ pub fn create_morse_keyboard(behavior_config: BehaviorConfig, hand: [[Hand; 5]; actions: LinearMap::from_iter( [ (MorsePattern::from_u16(0b1_01), Action::Key(KeyCode::Hid(HidKeyCode::A))), - (MorsePattern::from_u16(0b1_1000), Action::Key(KeyCode::Hid(HidKeyCode::B))), - (MorsePattern::from_u16(0b1_1010), Action::Key(KeyCode::Hid(HidKeyCode::C))), - (MorsePattern::from_u16(0b1_101), Action::Key(KeyCode::Hid(HidKeyCode::K))), + ( + MorsePattern::from_u16(0b1_1000), + Action::Key(KeyCode::Hid(HidKeyCode::B)), + ), + ( + MorsePattern::from_u16(0b1_1010), + Action::Key(KeyCode::Hid(HidKeyCode::C)), + ), + ( + MorsePattern::from_u16(0b1_101), + Action::Key(KeyCode::Hid(HidKeyCode::K)), + ), (MorsePattern::from_u16(0b1_11), Action::Key(KeyCode::Hid(HidKeyCode::M))), - (MorsePattern::from_u16(0b1_111), Action::Key(KeyCode::Hid(HidKeyCode::O))), - (MorsePattern::from_u16(0b1_010), Action::Key(KeyCode::Hid(HidKeyCode::R))), - (MorsePattern::from_u16(0b1_000), Action::Key(KeyCode::Hid(HidKeyCode::S))), + ( + MorsePattern::from_u16(0b1_111), + Action::Key(KeyCode::Hid(HidKeyCode::O)), + ), + ( + MorsePattern::from_u16(0b1_010), + Action::Key(KeyCode::Hid(HidKeyCode::R)), + ), + ( + MorsePattern::from_u16(0b1_000), + Action::Key(KeyCode::Hid(HidKeyCode::S)), + ), ] .into_iter(), ), diff --git a/rmk/tests/keyboard_morse_hold_on_other_press_test.rs b/rmk/tests/keyboard_morse_hold_on_other_press_test.rs index c42f2b8a0..df45c2982 100644 --- a/rmk/tests/keyboard_morse_hold_on_other_press_test.rs +++ b/rmk/tests/keyboard_morse_hold_on_other_press_test.rs @@ -47,7 +47,11 @@ fn create_hold_on_other_key_press_keyboard_with_combo() -> Keyboard<'static, 1, Action::Modifier(ModifierCombination::LGUI), MorseProfile::new(Some(false), Some(MorseMode::Normal), Some(250u16), Some(250u16)), //just to test if combo ignores the profile as expected ); - let combo_key_3 = KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::D)), Action::LayerOn(1), Default::default()); + let combo_key_3 = KeyAction::TapHold( + Action::Key(KeyCode::Hid(HidKeyCode::D)), + Action::LayerOn(1), + Default::default(), + ); create_simple_morse_keyboard(BehaviorConfig { morse: MorsesConfig { enable_flow_tap: false, diff --git a/rmk/tests/keyboard_morse_hrm_test.rs b/rmk/tests/keyboard_morse_hrm_test.rs index 3bc589b06..74cfc74bf 100644 --- a/rmk/tests/keyboard_morse_hrm_test.rs +++ b/rmk/tests/keyboard_morse_hrm_test.rs @@ -50,7 +50,11 @@ fn create_hrm_keyboard_with_combo() -> Keyboard<'static, 1, 5, 2> { Action::Modifier(ModifierCombination::LGUI), Default::default(), ); - let combo_key_3 = KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::D)), Action::LayerOn(1), Default::default()); + let combo_key_3 = KeyAction::TapHold( + Action::Key(KeyCode::Hid(HidKeyCode::D)), + Action::LayerOn(1), + Default::default(), + ); let hand = [[Hand::Left, Hand::Left, Hand::Right, Hand::Right, Hand::Right]]; diff --git a/rmk/tests/keyboard_morse_permissive_hold_test.rs b/rmk/tests/keyboard_morse_permissive_hold_test.rs index 715744ba8..30a9de6b0 100644 --- a/rmk/tests/keyboard_morse_permissive_hold_test.rs +++ b/rmk/tests/keyboard_morse_permissive_hold_test.rs @@ -41,7 +41,11 @@ fn create_permissive_hold_keyboard_with_combo() -> Keyboard<'static, 1, 5, 2> { Action::Modifier(ModifierCombination::LGUI), Default::default(), ); - let combo_key_3 = KeyAction::TapHold(Action::Key(KeyCode::Hid(HidKeyCode::D)), Action::LayerOn(1), Default::default()); + let combo_key_3 = KeyAction::TapHold( + Action::Key(KeyCode::Hid(HidKeyCode::D)), + Action::LayerOn(1), + Default::default(), + ); create_simple_morse_keyboard(BehaviorConfig { morse: MorsesConfig { enable_flow_tap: false, From feb9d6fa5277c88ba7d4e228851c965f499b8bb0 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Wed, 31 Dec 2025 17:55:56 +0800 Subject: [PATCH 9/9] refactor: adjust `Action` names and structure Signed-off-by: Haobo Gu --- rmk-types/src/action.rs | 16 +++++++--------- rmk/src/host/via/keycode_convert.rs | 28 ++++++++++++++-------------- rmk/src/keyboard.rs | 24 ++++++++++++------------ 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/rmk-types/src/action.rs b/rmk-types/src/action.rs index ff96f1e12..4f7f4ff95 100644 --- a/rmk-types/src/action.rs +++ b/rmk-types/src/action.rs @@ -233,9 +233,9 @@ impl From for u32 { #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(postcard::experimental::max_size::MaxSize)] pub enum KeyAction { - /// No action. Serialized as 0x0000. + /// No action No, - /// Transparent action, next layer will be checked. Serialized as 0x0001. + /// Transparent action, next layer will be checked Transparent, /// A single action, such as triggering a key, or activating a layer. Action is triggered when pressed and cancelled when released. Single(Action), @@ -292,11 +292,9 @@ impl PartialEq for KeyAction { pub enum Action { /// Default action, no action. No, - /// Transparent action, next layer will be checked. - Transparent, /// A normal key stroke, uses for all keycodes defined in `KeyCode` enum, including mouse key, consumer/system control, etc. Key(KeyCode), - /// Modifier Combination, used for oneshot keyaction. + /// Modifier Combination, used in tap hold Modifier(ModifierCombination), /// Key stroke with modifier combination triggered. KeyWithModifier(KeyCode, ModifierCombination), @@ -312,6 +310,8 @@ pub enum Action { DefaultLayer(u8), /// Activate a layer and deactivate all other layers(except default layer) LayerToggleOnly(u8), + TriLayerLower, + TriLayerUpper, /// Triggers the Macro at the 'index'. TriggerMacro(u8), /// Oneshot layer, keep the layer active until the next key is triggered. @@ -323,14 +323,14 @@ pub enum Action { /// Actions for controlling lights Light(LightAction), /// Actions for controlling the keyboard - Keyboard(KeyboardAction), + KeyboardControl(KeyboardAction), /// Special Keys Special(SpecialKey), /// User Keys User(u8), } -/// Actions for controlling the keyboard, for example, enable/disable a particular function +/// Actions for controlling the keyboard or changing the keyboard's state, for example, enable/disable a particular function #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(postcard::experimental::max_size::MaxSize)] @@ -346,8 +346,6 @@ pub enum KeyboardAction { ComboOff, ComboToggle, CapsWordToggle, - TriLayerLower, - TriLayerUpper, } /// Actions for controlling lights diff --git a/rmk/src/host/via/keycode_convert.rs b/rmk/src/host/via/keycode_convert.rs index cc33263fd..34f9ee1fc 100644 --- a/rmk/src/host/via/keycode_convert.rs +++ b/rmk/src/host/via/keycode_convert.rs @@ -45,6 +45,8 @@ pub(crate) fn to_via_keycode(key_action: KeyAction) -> u16 { Action::LayerOn(l) => 0x5220 | l as u16, Action::DefaultLayer(l) => 0x5240 | l as u16, Action::LayerToggle(l) => 0x5260 | l as u16, + Action::TriLayerLower => 0x7c77, + Action::TriLayerUpper => 0x7c78, Action::TriggerMacro(idx) => { // if idx < 32 { 0x7700 + (idx as u16) @@ -68,17 +70,15 @@ pub(crate) fn to_via_keycode(key_action: KeyAction) -> u16 { 0 } } - Action::Keyboard(keyboard_action) => match keyboard_action { + Action::KeyboardControl(c) => match c { KeyboardAction::Bootloader => 0x7c00, KeyboardAction::Reboot => 0x7c01, KeyboardAction::ComboOn => 0x7c50, KeyboardAction::ComboOff => 0x7c51, KeyboardAction::ComboToggle => 0x7c52, KeyboardAction::CapsWordToggle => 0x7c73, - KeyboardAction::TriLayerLower => 0x7c77, - KeyboardAction::TriLayerUpper => 0x7c78, _ => { - warn!("KeyboardAction: {:?} vial is not supported yet", keyboard_action); + warn!("KeyboardAction: {:?} vial is not supported yet", c); 0 } }, @@ -208,15 +208,15 @@ pub(crate) fn from_via_keycode(via_keycode: u16) -> KeyAction { warn!("Backlight and RGB configuration key not supported"); KeyAction::No } - 0x7C00 => KeyAction::Single(Action::Keyboard(KeyboardAction::Bootloader)), - 0x7C01 => KeyAction::Single(Action::Keyboard(KeyboardAction::Reboot)), - 0x7C50 => KeyAction::Single(Action::Keyboard(KeyboardAction::ComboOn)), - 0x7C51 => KeyAction::Single(Action::Keyboard(KeyboardAction::ComboOff)), - 0x7C52 => KeyAction::Single(Action::Keyboard(KeyboardAction::ComboToggle)), + 0x7C00 => KeyAction::Single(Action::KeyboardControl(KeyboardAction::Bootloader)), + 0x7C01 => KeyAction::Single(Action::KeyboardControl(KeyboardAction::Reboot)), + 0x7C50 => KeyAction::Single(Action::KeyboardControl(KeyboardAction::ComboOn)), + 0x7C51 => KeyAction::Single(Action::KeyboardControl(KeyboardAction::ComboOff)), + 0x7C52 => KeyAction::Single(Action::KeyboardControl(KeyboardAction::ComboToggle)), 0x7C16 => KeyAction::Single(Action::Special(SpecialKey::GraveEscape)), - 0x7C73 => KeyAction::Single(Action::Keyboard(KeyboardAction::CapsWordToggle)), - 0x7C77 => KeyAction::Single(Action::Keyboard(KeyboardAction::TriLayerLower)), - 0x7C78 => KeyAction::Single(Action::Keyboard(KeyboardAction::TriLayerUpper)), + 0x7C73 => KeyAction::Single(Action::KeyboardControl(KeyboardAction::CapsWordToggle)), + 0x7C77 => KeyAction::Single(Action::TriLayerLower), + 0x7C78 => KeyAction::Single(Action::TriLayerUpper), 0x7C79 => KeyAction::Single(Action::Special(SpecialKey::Repeat)), 0x7C02..=0x7C5F => { // TODO: Reset/Space Cadet/Haptic/Auto shift(AS)/Dynamic macro @@ -406,7 +406,7 @@ mod test { // ComboOff let via_keycode = 0x7C51; assert_eq!( - KeyAction::Single(Action::Keyboard(KeyboardAction::ComboOff)), + KeyAction::Single(Action::KeyboardControl(KeyboardAction::ComboOff)), from_via_keycode(via_keycode) ); @@ -551,7 +551,7 @@ mod test { assert_eq!(0x5039, to_via_keycode(a)); // ComboOff - let a = KeyAction::Single(Action::Keyboard(KeyboardAction::ComboOff)); + let a = KeyAction::Single(Action::KeyboardControl(KeyboardAction::ComboOff)); assert_eq!(0x7C51, to_via_keycode(a)); // GraveEscape diff --git a/rmk/src/keyboard.rs b/rmk/src/keyboard.rs index a4281adc3..d08e11f69 100644 --- a/rmk/src/keyboard.rs +++ b/rmk/src/keyboard.rs @@ -1126,7 +1126,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E async fn process_key_action_normal(&mut self, action: Action, event: KeyboardEvent) { match action { - Action::No | Action::Transparent => {} + Action::No => {} Action::Key(key) => self.process_action_key(key, event).await, Action::LayerOn(layer_num) => self.process_action_layer_switch(layer_num, event), Action::LayerOff(layer_num) => { @@ -1208,9 +1208,19 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E } Action::OneShotKey(_k) => warn!("One-shot key is not supported: {:?}", action), Action::Light(_light_action) => warn!("Light controll is not supported"), - Action::Keyboard(keyboard_action) => self.process_action_keyboard_control(keyboard_action, event).await, + Action::KeyboardControl(c) => self.process_action_keyboard_control(c, event).await, Action::Special(special_key) => self.process_action_special(special_key, event).await, Action::User(id) => self.process_user(id, event).await, + Action::TriLayerLower => { + // Tri-layer lower, turn layer 1 on and update layer state + self.process_action_layer_switch(1, event); + self.keymap.borrow_mut().update_fn_layer_state(); + } + Action::TriLayerUpper => { + // Tri-layer upper, turn layer 2 on and update layer state + self.process_action_layer_switch(2, event); + self.keymap.borrow_mut().update_fn_layer_state(); + } } } @@ -1431,16 +1441,6 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize, const NUM_E async fn process_action_keyboard_control(&mut self, keyboard_control: KeyboardAction, event: KeyboardEvent) { match keyboard_control { - KeyboardAction::TriLayerLower => { - // Tri-layer lower, turn layer 1 on and update layer state - self.process_action_layer_switch(1, event); - self.keymap.borrow_mut().update_fn_layer_state(); - } - KeyboardAction::TriLayerUpper => { - // Tri-layer upper, turn layer 2 on and update layer state - self.process_action_layer_switch(2, event); - self.keymap.borrow_mut().update_fn_layer_state(); - } KeyboardAction::CapsWordToggle => { // Handle Caps Word if event.pressed {