starnix_modules_input_report_event_conversion/
keyboard.rs1use fidl_fuchsia_input_report as fir;
6use sorted_vec_map::SortedVecSet;
7use starnix_modules_input_app_event_conversion::keymap::KEY_MAP;
8use starnix_types::time::timeval_from_time;
9use starnix_uapi::uapi;
10
11#[derive(Debug, Default, PartialEq)]
13pub struct KeyboardReportConverter {
14 pressed_keys: SortedVecSet<u16>,
15}
16
17impl KeyboardReportConverter {
18 pub fn new() -> Self {
19 Self::default()
20 }
21
22 pub fn handle(
23 &mut self,
24 report: &fir::KeyboardInputReport,
25 event_time: zx::MonotonicInstant,
26 ) -> Vec<uapi::input_event> {
27 let mut events = Vec::new();
28 let time = timeval_from_time(event_time);
29
30 let pressed_keys3 = report.pressed_keys3.as_deref().unwrap_or(&[]);
31 let mut current_keys = SortedVecSet::new();
32 for &key in pressed_keys3.iter() {
33 let lkey = KEY_MAP.fuchsia_input_key_to_linux_keycode(key);
34 if lkey != uapi::KEY_RESERVED {
35 current_keys.insert(lkey as u16);
36 }
37 }
38
39 crate::emit_key_transitions(&mut self.pressed_keys, current_keys, time, &mut events);
40
41 if !events.is_empty() {
42 events.push(uapi::input_event {
43 time,
44 type_: uapi::EV_SYN as u16,
45 code: uapi::SYN_REPORT as u16,
46 value: 0,
47 });
48 }
49
50 events
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use fidl_fuchsia_input::Key;
58
59 #[::fuchsia::test]
60 fn test_keyboard_report_keys() {
61 let mut converter = KeyboardReportConverter::new();
62 let time = zx::MonotonicInstant::from_nanos(500_000_000);
63
64 let report1 =
66 fir::KeyboardInputReport { pressed_keys3: Some(vec![Key::A]), ..Default::default() };
67 let events1 = converter.handle(&report1, time);
68 assert_eq!(
69 events1.iter().map(|e| (e.type_, e.code, e.value)).collect::<Vec<_>>(),
70 vec![
71 (uapi::EV_KEY as u16, uapi::KEY_A as u16, 1),
72 (uapi::EV_SYN as u16, uapi::SYN_REPORT as u16, 0),
73 ]
74 );
75
76 let report2 = fir::KeyboardInputReport {
78 pressed_keys3: Some(vec![Key::A, Key::B]),
79 ..Default::default()
80 };
81 let events2 = converter.handle(&report2, time);
82 assert_eq!(
83 events2.iter().map(|e| (e.type_, e.code, e.value)).collect::<Vec<_>>(),
84 vec![
85 (uapi::EV_KEY as u16, uapi::KEY_B as u16, 1),
86 (uapi::EV_SYN as u16, uapi::SYN_REPORT as u16, 0),
87 ]
88 );
89
90 let report3 =
92 fir::KeyboardInputReport { pressed_keys3: Some(vec![Key::B]), ..Default::default() };
93 let events3 = converter.handle(&report3, time);
94 assert_eq!(
95 events3.iter().map(|e| (e.type_, e.code, e.value)).collect::<Vec<_>>(),
96 vec![
97 (uapi::EV_KEY as u16, uapi::KEY_A as u16, 0),
98 (uapi::EV_SYN as u16, uapi::SYN_REPORT as u16, 0),
99 ]
100 );
101
102 let report4 =
104 fir::KeyboardInputReport { pressed_keys3: Some(vec![]), ..Default::default() };
105 let events4 = converter.handle(&report4, time);
106 assert_eq!(
107 events4.iter().map(|e| (e.type_, e.code, e.value)).collect::<Vec<_>>(),
108 vec![
109 (uapi::EV_KEY as u16, uapi::KEY_B as u16, 0),
110 (uapi::EV_SYN as u16, uapi::SYN_REPORT as u16, 0),
111 ]
112 );
113 }
114
115 #[::fuchsia::test]
116 fn test_keyboard_report_unmapped_key_filtered() {
117 let mut converter = KeyboardReportConverter::new();
118 let time = zx::MonotonicInstant::from_nanos(300_000_000);
119
120 let report = fir::KeyboardInputReport {
121 pressed_keys3: Some(vec![Key::Unknown]),
122 ..Default::default()
123 };
124 let events = converter.handle(&report, time);
125 assert!(events.is_empty());
127 }
128
129 #[::fuchsia::test]
130 fn test_empty_keyboard_reports_return_empty_events() {
131 let time = zx::MonotonicInstant::from_nanos(400_000_000);
132 assert!(
133 KeyboardReportConverter::new()
134 .handle(&fir::KeyboardInputReport::default(), time)
135 .is_empty()
136 );
137 }
138
139 #[::fuchsia::test]
140 fn test_keyboard_report_none_pressed_keys_releases_held_keys() {
141 let mut converter = KeyboardReportConverter::new();
142 let time = zx::MonotonicInstant::from_nanos(400_000_000);
143
144 let report1 =
146 fir::KeyboardInputReport { pressed_keys3: Some(vec![Key::A]), ..Default::default() };
147 let events1 = converter.handle(&report1, time);
148 assert_eq!(
149 events1.iter().map(|e| (e.type_, e.code, e.value)).collect::<Vec<_>>(),
150 vec![
151 (uapi::EV_KEY as u16, uapi::KEY_A as u16, 1),
152 (uapi::EV_SYN as u16, uapi::SYN_REPORT as u16, 0),
153 ]
154 );
155
156 let report2 = fir::KeyboardInputReport { pressed_keys3: None, ..Default::default() };
158 let events2 = converter.handle(&report2, time);
159 assert_eq!(
160 events2.iter().map(|e| (e.type_, e.code, e.value)).collect::<Vec<_>>(),
161 vec![
162 (uapi::EV_KEY as u16, uapi::KEY_A as u16, 0),
163 (uapi::EV_SYN as u16, uapi::SYN_REPORT as u16, 0),
164 ]
165 );
166
167 let report3 = fir::KeyboardInputReport { pressed_keys3: None, ..Default::default() };
169 let events3 = converter.handle(&report3, time);
170 assert!(events3.is_empty());
171 }
172}