1 // Copyright 2019 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 mod data;
6 
7 use data::{MapEntry, KEYCODE_MAP};
8 use std::collections::HashMap;
9 
10 /// Specifies which type of scancode to convert *from* in the KeycodeTranslator.
11 #[allow(dead_code)]
12 pub enum KeycodeTypes {
13     XkbScancode,
14     WindowsScancode,
15     MacScancode,
16 }
17 
18 /// Translates scancodes of a particular type into Linux keycodes.
19 #[allow(dead_code)]
20 pub struct KeycodeTranslator {
21     keycode_map: HashMap<u32, MapEntry>,
22 }
23 
24 impl KeycodeTranslator {
25     /// Create a new KeycodeTranslator that translates from the `from_type` type to Linux keycodes.
26     #[allow(dead_code)]
new(from_type: KeycodeTypes) -> KeycodeTranslator27     pub fn new(from_type: KeycodeTypes) -> KeycodeTranslator {
28         let mut kcm: HashMap<u32, MapEntry> = HashMap::new();
29         for entry in KEYCODE_MAP.iter() {
30             kcm.insert(
31                 match from_type {
32                     KeycodeTypes::XkbScancode => entry.xkb,
33                     KeycodeTypes::WindowsScancode => entry.win,
34                     KeycodeTypes::MacScancode => entry.mac,
35                 },
36                 *entry,
37             );
38         }
39         KeycodeTranslator { keycode_map: kcm }
40     }
41 
42     /// Translates the scancode in `from_code` into a Linux keycode.
43     #[allow(dead_code)]
translate(&self, from_code: u32) -> Option<u16>44     pub fn translate(&self, from_code: u32) -> Option<u16> {
45         Some(self.keycode_map.get(&from_code)?.linux_keycode)
46     }
47 }
48 
49 #[cfg(test)]
50 mod tests {
51     use crate::keycode_converter::KeycodeTranslator;
52     use crate::keycode_converter::KeycodeTypes;
53 
54     #[test]
test_translate_win_lin()55     fn test_translate_win_lin() {
56         let translator = KeycodeTranslator::new(KeycodeTypes::WindowsScancode);
57         let translated_code = translator.translate(0x47);
58         assert!(translated_code.is_some());
59         assert_eq!(translated_code.unwrap(), 71);
60     }
61 
62     #[test]
test_translate_missing_entry()63     fn test_translate_missing_entry() {
64         let translator = KeycodeTranslator::new(KeycodeTypes::WindowsScancode);
65 
66         // No keycodes are this large.
67         let translated_code = translator.translate(0x9999999);
68         assert!(translated_code.is_none());
69     }
70 }
71