Skip to main content

rmk_types/keycode/
hid.rs

1//! USB HID keycodes.
2
3use postcard::experimental::max_size::MaxSize;
4use serde::{Deserialize, Serialize};
5use strum::FromRepr;
6
7use super::consumer::ConsumerKey;
8use super::system_control::SystemControlKey;
9use crate::modifier::ModifierCombination;
10
11// All key codes defined in HID spec
12#[repr(u8)]
13#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, FromRepr, MaxSize)]
14#[cfg_attr(feature = "_codegen", derive(strum::EnumIter, strum::VariantNames))]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
17#[cfg_attr(feature = "wasm", tsify(into_wasm_abi, from_wasm_abi))]
18pub enum HidKeyCode {
19    /// Reserved, no-key.
20    No = 0x0000,
21    /// Keyboard roll over error, too many keys are pressed simultaneously, not a physical key.
22    /// NKRO: n-key rollover.
23    ErrorRollover = 0x0001,
24    /// Keyboard post fail error, not a physical key.
25    PostFail = 0x0002,
26    /// An undefined error, not a physical key.
27    ErrorUndefined = 0x0003,
28    /// `a` and `A`
29    A = 0x0004,
30    /// `b` and `B`
31    B = 0x0005,
32    /// `c` and `C`
33    C = 0x0006,
34    /// `d` and `D`
35    D = 0x0007,
36    /// `e` and `E`
37    E = 0x0008,
38    /// `f` and `F`
39    F = 0x0009,
40    /// `g` and `G`
41    G = 0x000A,
42    /// `h` and `H`
43    H = 0x000B,
44    /// `i` and `I`
45    I = 0x000C,
46    /// `j` and `J`
47    J = 0x000D,
48    /// `k` and `K`
49    K = 0x000E,
50    /// `l` and `L`
51    L = 0x000F,
52    /// `m` and `M`
53    M = 0x0010,
54    /// `n` and `N`
55    N = 0x0011,
56    /// `o` and `O`
57    O = 0x0012,
58    /// `p` and `P`
59    P = 0x0013,
60    /// `q` and `Q`
61    Q = 0x0014,
62    /// `r` and `R`
63    R = 0x0015,
64    /// `s` and `S`
65    S = 0x0016,
66    /// `t` and `T`
67    T = 0x0017,
68    /// `u` and `U`
69    U = 0x0018,
70    /// `v` and `V`
71    V = 0x0019,
72    /// `w` and `W`
73    W = 0x001A,
74    /// `x` and `X`
75    X = 0x001B,
76    /// `y` and `Y`
77    Y = 0x001C,
78    /// `z` and `Z`
79    Z = 0x001D,
80    /// `1` and `!`
81    Kc1 = 0x001E,
82    /// `2` and `@`
83    Kc2 = 0x001F,
84    /// `3` and `#`
85    Kc3 = 0x0020,
86    /// `4` and `$`
87    Kc4 = 0x0021,
88    /// `5` and `%`
89    Kc5 = 0x0022,
90    /// `6` and `^`
91    Kc6 = 0x0023,
92    /// `7` and `&`
93    Kc7 = 0x0024,
94    /// `8` and `*`
95    Kc8 = 0x0025,
96    /// `9` and `(`
97    Kc9 = 0x0026,
98    /// `0` and `)`
99    Kc0 = 0x0027,
100    /// `Enter`
101    Enter = 0x0028,
102    /// `Esc`
103    Escape = 0x0029,
104    /// `Backspace`
105    Backspace = 0x002A,
106    /// `Tab`
107    Tab = 0x002B,
108    /// `Space`
109    Space = 0x002C,
110    /// `-` and `_`
111    Minus = 0x002D,
112    /// `=` and `+`
113    Equal = 0x002E,
114    /// `[` and `{`
115    LeftBracket = 0x002F,
116    /// `]` and `}`
117    RightBracket = 0x0030,
118    /// `\` and `|`
119    Backslash = 0x0031,
120    /// Non-US `#` and `~`
121    NonusHash = 0x0032,
122    /// `;` and `:`
123    Semicolon = 0x0033,
124    /// `'` and `"`
125    Quote = 0x0034,
126    /// `~` and `\``
127    Grave = 0x0035,
128    /// `,` and `<`
129    Comma = 0x0036,
130    /// `.` and `>`
131    Dot = 0x0037,
132    /// `/` and `?`
133    Slash = 0x0038,
134    /// `CapsLock`
135    CapsLock = 0x0039,
136    /// `F1`
137    F1 = 0x003A,
138    /// `F2`
139    F2 = 0x003B,
140    /// `F3`
141    F3 = 0x003C,
142    /// `F4`
143    F4 = 0x003D,
144    /// `F5`
145    F5 = 0x003E,
146    /// `F6`
147    F6 = 0x003F,
148    /// `F7`
149    F7 = 0x0040,
150    /// `F8`
151    F8 = 0x0041,
152    /// `F9`
153    F9 = 0x0042,
154    /// `F10`
155    F10 = 0x0043,
156    /// `F11`
157    F11 = 0x0044,
158    /// `F12`
159    F12 = 0x0045,
160    /// Print Screen
161    PrintScreen = 0x0046,
162    /// Scroll Lock
163    ScrollLock = 0x0047,
164    /// Pause
165    Pause = 0x0048,
166    /// Insert
167    Insert = 0x0049,
168    /// Home
169    Home = 0x004A,
170    /// Page Up
171    PageUp = 0x004B,
172    /// Delete
173    Delete = 0x004C,
174    /// End
175    End = 0x004D,
176    /// Page Down
177    PageDown = 0x004E,
178    /// Right arrow
179    Right = 0x004F,
180    /// Left arrow
181    Left = 0x0050,
182    /// Down arrow
183    Down = 0x0051,
184    /// Up arrow
185    Up = 0x0052,
186    /// Nums Lock
187    NumLock = 0x0053,
188    /// `/` on keypad
189    KpSlash = 0x0054,
190    /// `*` on keypad
191    KpAsterisk = 0x0055,
192    /// `-` on keypad
193    KpMinus = 0x0056,
194    /// `+` on keypad
195    KpPlus = 0x0057,
196    /// `Enter` on keypad
197    KpEnter = 0x0058,
198    /// `1` on keypad
199    Kp1 = 0x0059,
200    /// `2` on keypad
201    Kp2 = 0x005A,
202    /// `3` on keypad
203    Kp3 = 0x005B,
204    /// `4` on keypad
205    Kp4 = 0x005C,
206    /// `5` on keypad
207    Kp5 = 0x005D,
208    /// `6` on keypad
209    Kp6 = 0x005E,
210    /// `7` on keypad
211    Kp7 = 0x005F,
212    /// `8` on keypad
213    Kp8 = 0x0060,
214    /// `9` on keypad
215    Kp9 = 0x0061,
216    /// `0` on keypad
217    Kp0 = 0x0062,
218    /// `.` on keypad
219    KpDot = 0x0063,
220    /// Non-US `\` or `|`
221    NonusBackslash = 0x0064,
222    /// `Application`
223    Application = 0x0065,
224    /// `Power`
225    KbPower = 0x0066,
226    /// `=` on keypad
227    KpEqual = 0x0067,
228    /// `F13`
229    F13 = 0x0068,
230    /// `F14`
231    F14 = 0x0069,
232    /// `F15`
233    F15 = 0x006A,
234    /// `F16`
235    F16 = 0x006B,
236    /// `F17`
237    F17 = 0x006C,
238    /// `F18`
239    F18 = 0x006D,
240    /// `F19`
241    F19 = 0x006E,
242    /// `F20`
243    F20 = 0x006F,
244    /// `F21`
245    F21 = 0x0070,
246    /// `F22`
247    F22 = 0x0071,
248    /// `F23`
249    F23 = 0x0072,
250    /// `F24`
251    F24 = 0x0073,
252    Execute = 0x0074,
253    Help = 0x0075,
254    Menu = 0x0076,
255    Select = 0x0077,
256    Stop = 0x0078,
257    Again = 0x0079,
258    Undo = 0x007A,
259    Cut = 0x007B,
260    Copy = 0x007C,
261    Paste = 0x007D,
262    Find = 0x007E,
263    /// Mute
264    KbMute = 0x007F,
265    /// Volume Up
266    KbVolumeUp = 0x0080,
267    /// Volume Down
268    KbVolumeDown = 0x0081,
269    /// Locking Caps Lock
270    LockingCapsLock = 0x0082,
271    /// Locking Num Lock
272    LockingNumLock = 0x0083,
273    /// Locking scroll lock
274    LockingScrollLock = 0x0084,
275    KpComma = 0x0085,
276    KpEqualAs400 = 0x0086,
277    International1 = 0x0087,
278    International2 = 0x0088,
279    International3 = 0x0089,
280    International4 = 0x008A,
281    International5 = 0x008B,
282    International6 = 0x008C,
283    International7 = 0x008D,
284    International8 = 0x008E,
285    International9 = 0x008F,
286    Language1 = 0x0090,
287    Language2 = 0x0091,
288    Language3 = 0x0092,
289    Language4 = 0x0093,
290    Language5 = 0x0094,
291    Language6 = 0x0095,
292    Language7 = 0x0096,
293    Language8 = 0x0097,
294    Language9 = 0x0098,
295    AlternateErase = 0x0099,
296    SystemRequest = 0x009A,
297    Cancel = 0x009B,
298    Clear = 0x009C,
299    Prior = 0x009D,
300    Return = 0x009E,
301    Separator = 0x009F,
302    Out = 0x00A0,
303    Oper = 0x00A1,
304    ClearAgain = 0x00A2,
305    Crsel = 0x00A3,
306    Exsel = 0x00A4,
307    SystemPower = 0x00A5,
308    SystemSleep = 0x00A6,
309    SystemWake = 0x00A7,
310    AudioMute = 0x00A8,
311    AudioVolUp = 0x00A9,
312    AudioVolDown = 0x00AA,
313    MediaNextTrack = 0x00AB,
314    MediaPrevTrack = 0x00AC,
315    MediaStop = 0x00AD,
316    MediaPlayPause = 0x00AE,
317    MediaSelect = 0x00AF,
318    MediaEject = 0x00B0,
319    Mail = 0x00B1,
320    Calculator = 0x00B2,
321    MyComputer = 0x00B3,
322    WwwSearch = 0x00B4,
323    WwwHome = 0x00B5,
324    WwwBack = 0x00B6,
325    WwwForward = 0x00B7,
326    WwwStop = 0x00B8,
327    WwwRefresh = 0x00B9,
328    WwwFavorites = 0x00BA,
329    MediaFastForward = 0x00BB,
330    MediaRewind = 0x00BC,
331    /// Brightness Up
332    BrightnessUp = 0x00BD,
333    /// Brightness Down
334    BrightnessDown = 0x00BE,
335    ControlPanel = 0x00BF,
336    Assistant = 0x00C0,
337    MissionControl = 0x00C1,
338    Launchpad = 0x00C2,
339    /// Mouse Up
340    MouseUp = 0x00CD,
341    /// Mouse Down
342    MouseDown = 0x00CE,
343    /// Mouse Left
344    MouseLeft = 0x00CF,
345    /// Mouse Right
346    MouseRight = 0x00D0,
347    /// Mouse Button 1(Left)
348    MouseBtn1 = 0x00D1,
349    /// Mouse Button 2(Right)
350    MouseBtn2 = 0x00D2,
351    /// Mouse Button 3(Middle)
352    MouseBtn3 = 0x00D3,
353    /// Mouse Button 4(Back)
354    MouseBtn4 = 0x00D4,
355    /// Mouse Button 5(Forward)
356    MouseBtn5 = 0x00D5,
357    MouseBtn6 = 0x00D6,
358    MouseBtn7 = 0x00D7,
359    MouseBtn8 = 0x00D8,
360    MouseWheelUp = 0x00D9,
361    MouseWheelDown = 0x00DA,
362    MouseWheelLeft = 0x00DB,
363    MouseWheelRight = 0x00DC,
364    MouseAccel0 = 0x00DD,
365    MouseAccel1 = 0x00DE,
366    MouseAccel2 = 0x00DF,
367    /// Left Control
368    LCtrl = 0x00E0,
369    /// Left Shift
370    LShift = 0x00E1,
371    /// Left Alt
372    LAlt = 0x00E2,
373    /// Left GUI
374    LGui = 0x00E3,
375    /// Right Control
376    RCtrl = 0x00E4,
377    /// Right Shift
378    RShift = 0x00E5,
379    /// Right Alt
380    RAlt = 0x00E6,
381    /// Right GUI
382    RGui = 0x00E7,
383}
384
385impl HidKeyCode {
386    /// Host-only: list all HID keycodes, in declaration order.
387    #[cfg(feature = "_codegen")]
388    pub fn all() -> impl Iterator<Item = Self> {
389        <Self as strum::IntoEnumIterator>::iter()
390    }
391
392    /// Returns `true` if the keycode is a simple keycode defined in HID spec
393    pub fn is_simple_key(self) -> bool {
394        HidKeyCode::No <= self && self <= HidKeyCode::MouseAccel2
395    }
396
397    /// Returns `true` if the keycode is a modifier keycode
398    pub fn is_modifier(self) -> bool {
399        HidKeyCode::LCtrl <= self && self <= HidKeyCode::RGui
400    }
401
402    /// Returns `true` if the keycode is a mouse keycode
403    pub fn is_mouse_key(self) -> bool {
404        HidKeyCode::MouseUp <= self && self <= HidKeyCode::MouseAccel2
405    }
406
407    /// Returns the byte with the bit corresponding to the USB HID
408    /// modifier bitfield set.
409    pub fn to_hid_modifiers(self) -> ModifierCombination {
410        match self {
411            HidKeyCode::LCtrl => ModifierCombination::LCTRL,
412            HidKeyCode::LShift => ModifierCombination::LSHIFT,
413            HidKeyCode::LAlt => ModifierCombination::LALT,
414            HidKeyCode::LGui => ModifierCombination::LGUI,
415            HidKeyCode::RCtrl => ModifierCombination::RCTRL,
416            HidKeyCode::RShift => ModifierCombination::RSHIFT,
417            HidKeyCode::RAlt => ModifierCombination::RALT,
418            HidKeyCode::RGui => ModifierCombination::RGUI,
419            _ => ModifierCombination::new(),
420        }
421    }
422
423    /// Does current keycode continues Caps Word?
424    pub fn is_caps_word_continue_key(self) -> bool {
425        if self >= HidKeyCode::A && self <= HidKeyCode::Z {
426            return true;
427        }
428        if self >= HidKeyCode::Kc1 && self <= HidKeyCode::Kc0 {
429            return true;
430        }
431        if self == HidKeyCode::Minus || self == HidKeyCode::Backspace || self == HidKeyCode::Delete {
432            return true;
433        }
434        false
435    }
436
437    /// Does current keycode is to be shifted by Caps Word?
438    pub fn is_caps_word_shifted_key(self) -> bool {
439        if self >= HidKeyCode::A && self <= HidKeyCode::Z {
440            return true;
441        }
442        if self == HidKeyCode::Minus {
443            return true;
444        }
445        false
446    }
447
448    /// Some hid keycodes are processed as consumer keys, for compatibility
449    pub fn process_as_consumer(&self) -> Option<ConsumerKey> {
450        match self {
451            HidKeyCode::AudioMute => Some(ConsumerKey::Mute),
452            HidKeyCode::AudioVolUp => Some(ConsumerKey::VolumeIncrement),
453            HidKeyCode::AudioVolDown => Some(ConsumerKey::VolumeDecrement),
454            HidKeyCode::MediaNextTrack => Some(ConsumerKey::NextTrack),
455            HidKeyCode::MediaPrevTrack => Some(ConsumerKey::PrevTrack),
456            HidKeyCode::MediaStop => Some(ConsumerKey::StopPlay),
457            HidKeyCode::MediaPlayPause => Some(ConsumerKey::PlayPause),
458            HidKeyCode::MediaSelect => Some(ConsumerKey::Record),
459            HidKeyCode::MediaEject => Some(ConsumerKey::Eject),
460            HidKeyCode::Mail => Some(ConsumerKey::Email),
461            HidKeyCode::Calculator => Some(ConsumerKey::Calculator),
462            HidKeyCode::MyComputer => Some(ConsumerKey::LocalBrowser),
463            HidKeyCode::WwwSearch => Some(ConsumerKey::Search),
464            HidKeyCode::WwwHome => Some(ConsumerKey::Home),
465            HidKeyCode::WwwBack => Some(ConsumerKey::Back),
466            HidKeyCode::WwwForward => Some(ConsumerKey::Forward),
467            HidKeyCode::WwwStop => Some(ConsumerKey::Stop),
468            HidKeyCode::WwwRefresh => Some(ConsumerKey::Refresh),
469            HidKeyCode::WwwFavorites => Some(ConsumerKey::Bookmarks),
470            HidKeyCode::MediaFastForward => Some(ConsumerKey::FastForward),
471            HidKeyCode::MediaRewind => Some(ConsumerKey::Rewind),
472            HidKeyCode::BrightnessUp => Some(ConsumerKey::BrightnessUp),
473            HidKeyCode::BrightnessDown => Some(ConsumerKey::BrightnessDown),
474            HidKeyCode::ControlPanel => Some(ConsumerKey::ControlPanel),
475            HidKeyCode::Assistant => Some(ConsumerKey::Assistant),
476            HidKeyCode::MissionControl => Some(ConsumerKey::DesktopShowAllWindows),
477            HidKeyCode::Launchpad => Some(ConsumerKey::AcSoftKeyLeft),
478            _ => None,
479        }
480    }
481
482    /// Some hid keycodes are processed as system control keys, for compatibility
483    pub fn process_as_system_control(&self) -> Option<SystemControlKey> {
484        match self {
485            HidKeyCode::SystemPower => Some(SystemControlKey::PowerDown),
486            HidKeyCode::SystemSleep => Some(SystemControlKey::Sleep),
487            HidKeyCode::SystemWake => Some(SystemControlKey::WakeUp),
488            _ => None,
489        }
490    }
491}
492
493impl From<u8> for HidKeyCode {
494    fn from(value: u8) -> Self {
495        Self::from_repr(value).unwrap_or(HidKeyCode::No)
496    }
497}