const KBD: u32 = 0x0007_0000;
const CONSUMER: u32 = 0x000C_0000;
static KEYS: &[(u16, u32)] = &[
(30, KBD | 0x04), (48, KBD | 0x05), (46, KBD | 0x06), (32, KBD | 0x07), (18, KBD | 0x08), (33, KBD | 0x09), (34, KBD | 0x0A), (35, KBD | 0x0B), (23, KBD | 0x0C), (36, KBD | 0x0D), (37, KBD | 0x0E), (38, KBD | 0x0F), (50, KBD | 0x10), (49, KBD | 0x11), (24, KBD | 0x12), (25, KBD | 0x13), (16, KBD | 0x14), (19, KBD | 0x15), (31, KBD | 0x16), (20, KBD | 0x17), (22, KBD | 0x18), (47, KBD | 0x19), (17, KBD | 0x1A), (45, KBD | 0x1B), (21, KBD | 0x1C), (44, KBD | 0x1D), (2, KBD | 0x1E), (3, KBD | 0x1F), (4, KBD | 0x20), (5, KBD | 0x21), (6, KBD | 0x22), (7, KBD | 0x23), (8, KBD | 0x24), (9, KBD | 0x25), (10, KBD | 0x26), (11, KBD | 0x27), (28, KBD | 0x28), (1, KBD | 0x29), (14, KBD | 0x2A), (15, KBD | 0x2B), (57, KBD | 0x2C), (12, KBD | 0x2D), (13, KBD | 0x2E), (26, KBD | 0x2F), (27, KBD | 0x30), (43, KBD | 0x31), (39, KBD | 0x33), (40, KBD | 0x34), (41, KBD | 0x35), (51, KBD | 0x36), (52, KBD | 0x37), (53, KBD | 0x38), (58, KBD | 0x39), (59, KBD | 0x3A), (60, KBD | 0x3B), (61, KBD | 0x3C), (62, KBD | 0x3D), (63, KBD | 0x3E), (64, KBD | 0x3F), (65, KBD | 0x40), (66, KBD | 0x41), (67, KBD | 0x42), (68, KBD | 0x43), (87, KBD | 0x44), (88, KBD | 0x45), (99, KBD | 0x46), (70, KBD | 0x47), (119, KBD | 0x48), (110, KBD | 0x49), (102, KBD | 0x4A), (104, KBD | 0x4B), (111, KBD | 0x4C), (107, KBD | 0x4D), (109, KBD | 0x4E), (106, KBD | 0x4F), (105, KBD | 0x50), (108, KBD | 0x51), (103, KBD | 0x52), (69, KBD | 0x53), (98, KBD | 0x54), (55, KBD | 0x55), (74, KBD | 0x56), (78, KBD | 0x57), (96, KBD | 0x58), (79, KBD | 0x59), (80, KBD | 0x5A), (81, KBD | 0x5B), (75, KBD | 0x5C), (76, KBD | 0x5D), (77, KBD | 0x5E), (71, KBD | 0x5F), (72, KBD | 0x60), (73, KBD | 0x61), (82, KBD | 0x62), (83, KBD | 0x63), (86, KBD | 0x64), (127, KBD | 0x65), (117, KBD | 0x67), (183, KBD | 0x68), (184, KBD | 0x69), (185, KBD | 0x6A), (186, KBD | 0x6B), (187, KBD | 0x6C), (188, KBD | 0x6D), (189, KBD | 0x6E), (190, KBD | 0x6F), (191, KBD | 0x70), (192, KBD | 0x71), (193, KBD | 0x72), (194, KBD | 0x73), (139, KBD | 0x76), (89, KBD | 0x87), (93, KBD | 0x88), (124, KBD | 0x89), (92, KBD | 0x8A), (94, KBD | 0x8B), (122, KBD | 0x90), (123, KBD | 0x91), (90, KBD | 0x92), (91, KBD | 0x93), (85, KBD | 0x94), (29, KBD | 0xE0), (42, KBD | 0xE1), (56, KBD | 0xE2), (125, KBD | 0xE3), (97, KBD | 0xE4), (54, KBD | 0xE5), (100, KBD | 0xE6), (126, KBD | 0xE7), (163, CONSUMER | 0xB5), (165, CONSUMER | 0xB6), (166, CONSUMER | 0xB7), (164, CONSUMER | 0xCD), (113, CONSUMER | 0xE2), (115, CONSUMER | 0xE9), (114, CONSUMER | 0xEA), (155, CONSUMER | 0x18A), (140, CONSUMER | 0x192), (172, CONSUMER | 0x223), ];
pub(super) fn hid_from_evdev(code: u16) -> Option<u32> {
KEYS.iter()
.find(|&&(evdev, _)| evdev == code)
.map(|&(_, hid)| hid)
}
pub(super) fn evdev_from_hid(usage: u32) -> Option<u16> {
KEYS.iter()
.find(|&&(_, hid)| hid == usage)
.map(|&(evdev, _)| evdev)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn evdev_from_hid_every_entry_round_trips() {
let table = KEYS;
for &(evdev, hid) in table {
let back = hid_from_evdev(evdev).and_then(evdev_from_hid);
assert_eq!(back, Some(evdev), "evdev {evdev} / usage {hid:#x}");
assert_eq!(hid_from_evdev(evdev), Some(hid));
}
}
#[test]
fn keys_table_has_no_duplicate_codes_or_usages() {
let mut codes: Vec<u16> = KEYS.iter().map(|&(evdev, _)| evdev).collect();
let mut usages: Vec<u32> = KEYS.iter().map(|&(_, hid)| hid).collect();
codes.sort_unstable();
usages.sort_unstable();
assert!(codes.windows(2).all(|pair| pair[0] != pair[1]));
assert!(usages.windows(2).all(|pair| pair[0] != pair[1]));
}
#[test]
fn hid_from_evdev_known_keys_match_usage_tables() {
let expected = [
(30, 0x0007_0004),
(28, 0x0007_0028),
(125, 0x0007_00E3),
(113, 0x000C_00E2),
];
for (evdev, usage) in expected {
let hid = hid_from_evdev(evdev);
assert_eq!(hid, Some(usage), "evdev {evdev}");
}
}
}