From 1d80dcc01c2bab21ba4114daf7f7083633050408 Mon Sep 17 00:00:00 2001 From: Noah Gold Date: Wed, 11 Dec 2019 10:26:59 -0800 Subject: [PATCH] Add keycode translator. The keycode translates scancodes into Linux keycodes so they can be sent to the virtio-input device. The translation is based on Chromium's existing table, but converted into Rust. BUG=chromium:1023975 TEST=None Change-Id: Icd709e40c6d12775fdce0738f3dde3620f6c7da5 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1962872 Tested-by: kokoro Commit-Queue: Noah Gold Reviewed-by: Zach Reizner --- gpu_display/src/keycode_converter/data.rs | 539 ++++++++++++++++++++++ gpu_display/src/keycode_converter/mod.rs | 66 +++ gpu_display/src/lib.rs | 1 + 3 files changed, 606 insertions(+) create mode 100644 gpu_display/src/keycode_converter/data.rs create mode 100644 gpu_display/src/keycode_converter/mod.rs diff --git a/gpu_display/src/keycode_converter/data.rs b/gpu_display/src/keycode_converter/data.rs new file mode 100644 index 0000000000..a54cf0e240 --- /dev/null +++ b/gpu_display/src/keycode_converter/data.rs @@ -0,0 +1,539 @@ +#[derive(Debug, Clone, Copy)] +pub struct MapEntry { + pub linux_keycode: u16, + pub xkb: u32, + pub win: u32, + pub mac: u32, +} + +// Based on Chromium's chromium/chromium/ui/events/keycodes/dom/keycode_converter_data.inc. +pub const KEYCODE_MAP: [MapEntry; 88] = [ + MapEntry { + linux_keycode: 30, + xkb: 0x0026, + win: 0x001e, + mac: 0x0000, + }, + MapEntry { + linux_keycode: 48, + xkb: 0x0038, + win: 0x0030, + mac: 0x000b, + }, + MapEntry { + linux_keycode: 46, + xkb: 0x0036, + win: 0x002e, + mac: 0x0008, + }, + MapEntry { + linux_keycode: 32, + xkb: 0x0028, + win: 0x0020, + mac: 0x0002, + }, + MapEntry { + linux_keycode: 18, + xkb: 0x001a, + win: 0x0012, + mac: 0x000e, + }, + MapEntry { + linux_keycode: 33, + xkb: 0x0029, + win: 0x0021, + mac: 0x0003, + }, + MapEntry { + linux_keycode: 34, + xkb: 0x002a, + win: 0x0022, + mac: 0x0005, + }, + MapEntry { + linux_keycode: 35, + xkb: 0x002b, + win: 0x0023, + mac: 0x0004, + }, + MapEntry { + linux_keycode: 23, + xkb: 0x001f, + win: 0x0017, + mac: 0x0022, + }, + MapEntry { + linux_keycode: 36, + xkb: 0x002c, + win: 0x0024, + mac: 0x0026, + }, + MapEntry { + linux_keycode: 37, + xkb: 0x002d, + win: 0x0025, + mac: 0x0028, + }, + MapEntry { + linux_keycode: 38, + xkb: 0x002e, + win: 0x0026, + mac: 0x0025, + }, + MapEntry { + linux_keycode: 50, + xkb: 0x003a, + win: 0x0032, + mac: 0x002e, + }, + MapEntry { + linux_keycode: 49, + xkb: 0x0039, + win: 0x0031, + mac: 0x002d, + }, + MapEntry { + linux_keycode: 24, + xkb: 0x0020, + win: 0x0018, + mac: 0x001f, + }, + MapEntry { + linux_keycode: 25, + xkb: 0x0021, + win: 0x0019, + mac: 0x0023, + }, + MapEntry { + linux_keycode: 16, + xkb: 0x0018, + win: 0x0010, + mac: 0x000c, + }, + MapEntry { + linux_keycode: 19, + xkb: 0x001b, + win: 0x0013, + mac: 0x000f, + }, + MapEntry { + linux_keycode: 31, + xkb: 0x0027, + win: 0x001f, + mac: 0x0001, + }, + MapEntry { + linux_keycode: 20, + xkb: 0x001c, + win: 0x0014, + mac: 0x0011, + }, + MapEntry { + linux_keycode: 22, + xkb: 0x001e, + win: 0x0016, + mac: 0x0020, + }, + MapEntry { + linux_keycode: 47, + xkb: 0x0037, + win: 0x002f, + mac: 0x0009, + }, + MapEntry { + linux_keycode: 17, + xkb: 0x0019, + win: 0x0011, + mac: 0x000d, + }, + MapEntry { + linux_keycode: 45, + xkb: 0x0035, + win: 0x002d, + mac: 0x0007, + }, + MapEntry { + linux_keycode: 21, + xkb: 0x001d, + win: 0x0015, + mac: 0x0010, + }, + MapEntry { + linux_keycode: 44, + xkb: 0x0034, + win: 0x002c, + mac: 0x0006, + }, + MapEntry { + linux_keycode: 2, + xkb: 0x000a, + win: 0x0002, + mac: 0x0012, + }, + MapEntry { + linux_keycode: 3, + xkb: 0x000b, + win: 0x0003, + mac: 0x0013, + }, + MapEntry { + linux_keycode: 4, + xkb: 0x000c, + win: 0x0004, + mac: 0x0014, + }, + MapEntry { + linux_keycode: 5, + xkb: 0x000d, + win: 0x0005, + mac: 0x0015, + }, + MapEntry { + linux_keycode: 6, + xkb: 0x000e, + win: 0x0006, + mac: 0x0017, + }, + MapEntry { + linux_keycode: 7, + xkb: 0x000f, + win: 0x0007, + mac: 0x0016, + }, + MapEntry { + linux_keycode: 8, + xkb: 0x0010, + win: 0x0008, + mac: 0x001a, + }, + MapEntry { + linux_keycode: 9, + xkb: 0x0011, + win: 0x0009, + mac: 0x001c, + }, + MapEntry { + linux_keycode: 10, + xkb: 0x0012, + win: 0x000a, + mac: 0x0019, + }, + MapEntry { + linux_keycode: 11, + xkb: 0x0013, + win: 0x000b, + mac: 0x001d, + }, + MapEntry { + linux_keycode: 28, + xkb: 0x0024, + win: 0x001c, + mac: 0x0024, + }, + MapEntry { + linux_keycode: 1, + xkb: 0x0009, + win: 0x0001, + mac: 0x0035, + }, + MapEntry { + linux_keycode: 14, + xkb: 0x0016, + win: 0x000e, + mac: 0x0033, + }, + MapEntry { + linux_keycode: 15, + xkb: 0x0017, + win: 0x000f, + mac: 0x0030, + }, + MapEntry { + linux_keycode: 57, + xkb: 0x0041, + win: 0x0039, + mac: 0x0031, + }, + MapEntry { + linux_keycode: 12, + xkb: 0x0014, + win: 0x000c, + mac: 0x001b, + }, + MapEntry { + linux_keycode: 13, + xkb: 0x0015, + win: 0x000d, + mac: 0x0018, + }, + MapEntry { + linux_keycode: 26, + xkb: 0x0022, + win: 0x001a, + mac: 0x0021, + }, + MapEntry { + linux_keycode: 27, + xkb: 0x0023, + win: 0x001b, + mac: 0x001e, + }, + MapEntry { + linux_keycode: 43, + xkb: 0x0033, + win: 0x002b, + mac: 0x002a, + }, + MapEntry { + linux_keycode: 39, + xkb: 0x002f, + win: 0x0027, + mac: 0x0029, + }, + MapEntry { + linux_keycode: 40, + xkb: 0x0030, + win: 0x0028, + mac: 0x0027, + }, + MapEntry { + linux_keycode: 399, + xkb: 0x0031, + win: 0x0029, + mac: 0x0032, + }, + MapEntry { + linux_keycode: 51, + xkb: 0x003b, + win: 0x0033, + mac: 0x002b, + }, + MapEntry { + linux_keycode: 52, + xkb: 0x003c, + win: 0x0034, + mac: 0x002f, + }, + MapEntry { + linux_keycode: 53, + xkb: 0x003d, + win: 0x0035, + mac: 0x002c, + }, + MapEntry { + linux_keycode: 58, + xkb: 0x0042, + win: 0x003a, + mac: 0x0039, + }, + MapEntry { + linux_keycode: 119, + xkb: 0x007f, + win: 0x0045, + mac: 0xffff, + }, + MapEntry { + linux_keycode: 110, + xkb: 0x0076, + win: 0xe052, + mac: 0x0072, + }, + MapEntry { + linux_keycode: 102, + xkb: 0x006e, + win: 0xe047, + mac: 0x0073, + }, + MapEntry { + linux_keycode: 104, + xkb: 0x0070, + win: 0xe049, + mac: 0x0074, + }, + MapEntry { + linux_keycode: 111, + xkb: 0x0077, + win: 0xe053, + mac: 0x0075, + }, + MapEntry { + linux_keycode: 107, + xkb: 0x0073, + win: 0xe04f, + mac: 0x0077, + }, + MapEntry { + linux_keycode: 109, + xkb: 0x0075, + win: 0xe051, + mac: 0x0079, + }, + MapEntry { + linux_keycode: 106, + xkb: 0x0072, + win: 0xe04d, + mac: 0x007c, + }, + MapEntry { + linux_keycode: 105, + xkb: 0x0071, + win: 0xe04b, + mac: 0x007b, + }, + MapEntry { + linux_keycode: 108, + xkb: 0x0074, + win: 0xe050, + mac: 0x007d, + }, + MapEntry { + linux_keycode: 103, + xkb: 0x006f, + win: 0xe048, + mac: 0x007e, + }, + MapEntry { + linux_keycode: 69, + xkb: 0x004d, + win: 0xe045, + mac: 0x0047, + }, + MapEntry { + linux_keycode: 98, + xkb: 0x006a, + win: 0xe035, + mac: 0x004b, + }, + MapEntry { + linux_keycode: 78, + xkb: 0x0056, + win: 0x004e, + mac: 0x0045, + }, + MapEntry { + linux_keycode: 28, + xkb: 0x0068, + win: 0xe01c, + mac: 0x004c, + }, + MapEntry { + linux_keycode: 79, + xkb: 0x0057, + win: 0x004f, + mac: 0x0053, + }, + MapEntry { + linux_keycode: 80, + xkb: 0x0058, + win: 0x0050, + mac: 0x0054, + }, + MapEntry { + linux_keycode: 81, + xkb: 0x0059, + win: 0x0051, + mac: 0x0055, + }, + MapEntry { + linux_keycode: 75, + xkb: 0x0053, + win: 0x004b, + mac: 0x0056, + }, + MapEntry { + linux_keycode: 76, + xkb: 0x0054, + win: 0x004c, + mac: 0x0057, + }, + MapEntry { + linux_keycode: 77, + xkb: 0x0055, + win: 0x004d, + mac: 0x0058, + }, + MapEntry { + linux_keycode: 71, + xkb: 0x004f, + win: 0x0047, + mac: 0x0059, + }, + MapEntry { + linux_keycode: 72, + xkb: 0x0050, + win: 0x0048, + mac: 0x005b, + }, + MapEntry { + linux_keycode: 73, + xkb: 0x0051, + win: 0x0049, + mac: 0x005c, + }, + MapEntry { + linux_keycode: 82, + xkb: 0x005a, + win: 0x0052, + mac: 0x0052, + }, + MapEntry { + linux_keycode: 116, + xkb: 0x007c, + win: 0xe05e, + mac: 0xffff, + }, + MapEntry { + linux_keycode: 121, + xkb: 0x0081, + win: 0x007e, + mac: 0x005f, + }, + MapEntry { + linux_keycode: 29, + xkb: 0x0025, + win: 0x001d, + mac: 0x003b, + }, + MapEntry { + linux_keycode: 42, + xkb: 0x0032, + win: 0x002a, + mac: 0x0038, + }, + MapEntry { + linux_keycode: 56, + xkb: 0x0040, + win: 0x0038, + mac: 0x003a, + }, + MapEntry { + linux_keycode: 125, + xkb: 0x0085, + win: 0xe05b, + mac: 0x0037, + }, + MapEntry { + linux_keycode: 97, + xkb: 0x0069, + win: 0xe01d, + mac: 0x003e, + }, + MapEntry { + linux_keycode: 54, + xkb: 0x003e, + win: 0x0036, + mac: 0x003c, + }, + MapEntry { + linux_keycode: 100, + xkb: 0x006c, + win: 0xe038, + mac: 0x003d, + }, + MapEntry { + linux_keycode: 126, + xkb: 0x0086, + win: 0xe05c, + mac: 0x0036, + }, +]; diff --git a/gpu_display/src/keycode_converter/mod.rs b/gpu_display/src/keycode_converter/mod.rs new file mode 100644 index 0000000000..40fdb9537b --- /dev/null +++ b/gpu_display/src/keycode_converter/mod.rs @@ -0,0 +1,66 @@ +// Copyright 2019 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +mod data; + +use data::{MapEntry, KEYCODE_MAP}; +use std::collections::HashMap; + +/// Specifies which type of scancode to convert *from* in the KeycodeTranslator. +pub enum KeycodeTypes { + XkbScancode, + WindowsScancode, + MacScancode, +} + +/// Translates scancodes of a particular type into Linux keycodes. +pub struct KeycodeTranslator { + keycode_map: HashMap, +} + +impl KeycodeTranslator { + /// Create a new KeycodeTranslator that translates from the `from_type` type to Linux keycodes. + pub fn new(from_type: KeycodeTypes) -> KeycodeTranslator { + let mut kcm: HashMap = HashMap::new(); + for entry in KEYCODE_MAP.into_iter() { + kcm.insert( + match from_type { + KeycodeTypes::XkbScancode => entry.xkb, + KeycodeTypes::WindowsScancode => entry.win, + KeycodeTypes::MacScancode => entry.mac, + }, + *entry, + ); + } + KeycodeTranslator { keycode_map: kcm } + } + + /// Translates the scancode in `from_code` into a Linux keycode. + pub fn translate(&self, from_code: u32) -> Option { + Some(self.keycode_map.get(&from_code)?.linux_keycode) + } +} + +#[cfg(test)] +mod tests { + use crate::keycode_converter::KeycodeTranslator; + use crate::keycode_converter::KeycodeTypes; + + #[test] + fn test_translate_win_lin() { + let translator = KeycodeTranslator::new(KeycodeTypes::WindowsScancode); + let translated_code = translator.translate(0x47); + assert!(translated_code.is_some()); + assert_eq!(translated_code.unwrap(), 71); + } + + #[test] + fn test_translate_missing_entry() { + let translator = KeycodeTranslator::new(KeycodeTypes::WindowsScancode); + + // No keycodes are this large. + let translated_code = translator.translate(0x9999999); + assert!(translated_code.is_none()); + } +} diff --git a/gpu_display/src/lib.rs b/gpu_display/src/lib.rs index 8cc018a5fa..8985405004 100644 --- a/gpu_display/src/lib.rs +++ b/gpu_display/src/lib.rs @@ -15,6 +15,7 @@ mod event_device; mod gpu_display_wl; #[cfg(feature = "x")] mod gpu_display_x; +mod keycode_converter; pub use event_device::{EventDevice, EventDeviceKind, EventEncoded};