1use fidl_fuchsia_ui_input::{MediaButtonsEvent, TouchButton, TouchButtonsEvent};
6use starnix_types::time::timeval_from_time;
7use starnix_uapi::uapi;
8
9const MAX_TOUCH_BUTTON_VALUE: u32 = 5;
11
12const TOUCH_BUTTON_BITVEC_SIZE: u32 = MAX_TOUCH_BUTTON_VALUE + 1;
14
15pub fn new_touch_buttons_bitvec() -> bit_vec::BitVec {
16 bit_vec::BitVec::from_elem(TOUCH_BUTTON_BITVEC_SIZE as usize, false)
17}
18
19pub struct LinuxButtonEventBatch {
20 pub events: Vec<uapi::input_event>,
21
22 pub event_time: zx::MonotonicInstant,
26 pub power_is_pressed: bool,
27 pub function_is_pressed: bool,
28 pub volume_up_is_pressed: bool,
29 pub volume_down_is_pressed: bool,
30
31 pub touch_buttons: bit_vec::BitVec,
33}
34
35impl LinuxButtonEventBatch {
36 pub fn new() -> Self {
37 Self {
38 events: vec![],
39 event_time: zx::MonotonicInstant::get(),
40 power_is_pressed: false,
41 function_is_pressed: false,
42 volume_up_is_pressed: false,
43 volume_down_is_pressed: false,
44 touch_buttons: new_touch_buttons_bitvec(),
45 }
46 }
47}
48
49pub fn parse_fidl_media_button_event(
50 fidl_event: &MediaButtonsEvent,
51 power_was_pressed: bool,
52 function_was_pressed: bool,
53 volume_up_was_pressed: bool,
54 volume_down_was_pressed: bool,
55) -> LinuxButtonEventBatch {
56 let mut batch = LinuxButtonEventBatch::new();
57 let time = timeval_from_time(batch.event_time);
58 let sync_event = uapi::input_event {
59 time,
61 type_: uapi::EV_SYN as u16,
62 code: uapi::SYN_REPORT as u16,
63 value: 0,
64 };
65
66 batch.power_is_pressed = fidl_event.power.unwrap_or(false);
67 batch.function_is_pressed = fidl_event.function.unwrap_or(false);
68
69 let volume = fidl_event.volume.unwrap_or(0);
70 batch.volume_up_is_pressed = volume > 0;
71 batch.volume_down_is_pressed = volume < 0;
72
73 for (button_was_pressed, button_is_pressed, key_code) in [
74 (power_was_pressed, batch.power_is_pressed, uapi::KEY_POWER),
75 (function_was_pressed, batch.function_is_pressed, uapi::KEY_VOLUMEDOWN),
76 (volume_up_was_pressed, batch.volume_up_is_pressed, uapi::KEY_VOLUMEUP),
77 (volume_down_was_pressed, batch.volume_down_is_pressed, uapi::KEY_VOLUMEDOWN),
78 ] {
79 if button_is_pressed != button_was_pressed {
81 batch.events.push(uapi::input_event {
82 time,
83 type_: uapi::EV_KEY as u16,
84 code: key_code as u16,
85 value: button_is_pressed as i32,
86 });
87 batch.events.push(sync_event);
88 }
89 }
90
91 batch
92}
93
94pub fn parse_fidl_touch_button_event(
95 fidl_event: &TouchButtonsEvent,
96 touch_buttons_were_pressed: &bit_vec::BitVec,
97) -> LinuxButtonEventBatch {
98 let mut batch = LinuxButtonEventBatch::new();
99 let time = timeval_from_time(batch.event_time);
100 let sync_event = uapi::input_event {
101 time,
103 type_: uapi::EV_SYN as u16,
104 code: uapi::SYN_REPORT as u16,
105 value: 0,
106 };
107
108 if let Some(buttons) = &fidl_event.pressed_buttons {
109 for button in buttons {
110 let index = button.into_primitive() as usize;
111 if index < batch.touch_buttons.len() {
112 batch.touch_buttons.set(index, true);
113 }
114 }
115 };
116
117 for (index, key_code) in [
118 (TouchButton::Palm.into_primitive() as usize, uapi::KEY_SLEEP),
119 (TouchButton::SwipeUp.into_primitive() as usize, uapi::KEY_UP),
120 (TouchButton::SwipeLeft.into_primitive() as usize, uapi::KEY_LEFT),
121 (TouchButton::SwipeRight.into_primitive() as usize, uapi::KEY_RIGHT),
122 (TouchButton::SwipeDown.into_primitive() as usize, uapi::KEY_DOWN),
123 ] {
124 let button_was_pressed = touch_buttons_were_pressed.get(index).unwrap_or(false);
125 let button_is_pressed = batch.touch_buttons.get(index).unwrap_or(false);
126
127 if button_is_pressed != button_was_pressed {
129 batch.events.push(uapi::input_event {
130 time,
131 type_: uapi::EV_KEY as u16,
132 code: key_code as u16,
133 value: button_is_pressed as i32,
134 });
135 batch.events.push(sync_event);
136 }
137 }
138
139 batch
140}
141
142#[cfg(test)]
143mod tests {
144 use super::*;
145 use assert_matches::assert_matches;
146 use pretty_assertions::assert_eq;
147
148 #[test]
149 fn test_ensure_touch_button_max() {
150 assert_matches!(TouchButton::from_primitive(MAX_TOUCH_BUTTON_VALUE + 1), None);
153 }
154
155 #[test]
156 fn test_media_button_press_power() {
157 let fidl_event = MediaButtonsEvent { power: Some(true), ..Default::default() };
158 let batch = parse_fidl_media_button_event(&fidl_event, false, false, false, false);
159
160 assert_eq!(batch.events.len(), 2);
161 assert_eq!(batch.events[0].type_, uapi::EV_KEY as u16);
162 assert_eq!(batch.events[0].code, uapi::KEY_POWER as u16);
163 assert_eq!(batch.events[0].value, 1);
164 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
165 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
166 }
167
168 #[test]
169 fn test_media_button_release_power() {
170 let fidl_event = MediaButtonsEvent { power: Some(false), ..Default::default() };
171 let batch = parse_fidl_media_button_event(&fidl_event, true, false, false, false);
172
173 assert_eq!(batch.events.len(), 2);
174 assert_eq!(batch.events[0].type_, uapi::EV_KEY as u16);
175 assert_eq!(batch.events[0].code, uapi::KEY_POWER as u16);
176 assert_eq!(batch.events[0].value, 0);
177 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
178 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
179 }
180
181 #[test]
182 fn test_media_button_no_change() {
183 let fidl_event = MediaButtonsEvent { power: Some(true), ..Default::default() };
184 let batch = parse_fidl_media_button_event(&fidl_event, true, false, false, false);
185
186 assert_eq!(batch.events.len(), 0);
187 }
188
189 #[test]
190 fn test_media_button_press_volume_up() {
191 let fidl_event = MediaButtonsEvent { volume: Some(1), ..Default::default() };
192 let batch = parse_fidl_media_button_event(&fidl_event, false, false, false, false);
193
194 assert_eq!(batch.events.len(), 2);
195 assert_eq!(batch.events[0].type_, uapi::EV_KEY as u16);
196 assert_eq!(batch.events[0].code, uapi::KEY_VOLUMEUP as u16);
197 assert_eq!(batch.events[0].value, 1);
198 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
199 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
200 assert!(batch.volume_up_is_pressed);
201 assert!(!batch.volume_down_is_pressed);
202 }
203
204 #[test]
205 fn test_media_button_release_volume_up() {
206 let fidl_event = MediaButtonsEvent { volume: Some(0), ..Default::default() };
207 let batch = parse_fidl_media_button_event(&fidl_event, false, false, true, false);
208
209 assert_eq!(batch.events.len(), 2);
210 assert_eq!(batch.events[0].type_, uapi::EV_KEY as u16);
211 assert_eq!(batch.events[0].code, uapi::KEY_VOLUMEUP as u16);
212 assert_eq!(batch.events[0].value, 0);
213 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
214 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
215 assert!(!batch.volume_up_is_pressed);
216 assert!(!batch.volume_down_is_pressed);
217 }
218
219 #[test]
220 fn test_media_button_press_volume_down() {
221 let fidl_event = MediaButtonsEvent { volume: Some(-1), ..Default::default() };
222 let batch = parse_fidl_media_button_event(&fidl_event, false, false, false, false);
223
224 assert_eq!(batch.events.len(), 2);
225 assert_eq!(batch.events[0].type_, uapi::EV_KEY as u16);
226 assert_eq!(batch.events[0].code, uapi::KEY_VOLUMEDOWN as u16);
227 assert_eq!(batch.events[0].value, 1);
228 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
229 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
230 assert!(!batch.volume_up_is_pressed);
231 assert!(batch.volume_down_is_pressed);
232 }
233
234 #[test]
235 fn test_media_button_release_volume_down() {
236 let fidl_event = MediaButtonsEvent { volume: Some(0), ..Default::default() };
237 let batch = parse_fidl_media_button_event(&fidl_event, false, false, false, true);
238
239 assert_eq!(batch.events.len(), 2);
240 assert_eq!(batch.events[0].type_, uapi::EV_KEY as u16);
241 assert_eq!(batch.events[0].code, uapi::KEY_VOLUMEDOWN as u16);
242 assert_eq!(batch.events[0].value, 0);
243 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
244 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
245 assert!(!batch.volume_up_is_pressed);
246 assert!(!batch.volume_down_is_pressed);
247 }
248
249 use test_case::test_case;
250
251 #[test_case(TouchButton::Palm, uapi::KEY_SLEEP; "palm")]
252 #[test_case(TouchButton::SwipeUp, uapi::KEY_UP; "swipe up")]
253 #[test_case(TouchButton::SwipeLeft, uapi::KEY_LEFT; "swipe left")]
254 #[test_case(TouchButton::SwipeRight, uapi::KEY_RIGHT; "swipe right")]
255 #[test_case(TouchButton::SwipeDown, uapi::KEY_DOWN; "swipe down")]
256 fn test_touch_button_press(button: TouchButton, expected_key: u32) {
257 let fidl_event =
258 TouchButtonsEvent { pressed_buttons: Some(vec![button]), ..Default::default() };
259 let was_pressed = bit_vec::BitVec::from_elem(6, false);
260 let batch = parse_fidl_touch_button_event(&fidl_event, &was_pressed);
261
262 assert_eq!(batch.events.len(), 2);
263 assert_eq!(batch.events[0].type_, uapi::EV_KEY as u16);
264 assert_eq!(batch.events[0].code, expected_key as u16);
265 assert_eq!(batch.events[0].value, 1);
266 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
267 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
268 }
269
270 #[test_case(TouchButton::Palm, uapi::KEY_SLEEP; "palm")]
271 #[test_case(TouchButton::SwipeUp, uapi::KEY_UP; "swipe up")]
272 #[test_case(TouchButton::SwipeLeft, uapi::KEY_LEFT; "swipe left")]
273 #[test_case(TouchButton::SwipeRight, uapi::KEY_RIGHT; "swipe right")]
274 #[test_case(TouchButton::SwipeDown, uapi::KEY_DOWN; "swipe down")]
275 fn test_touch_button_release(button: TouchButton, expected_key: u32) {
276 let fidl_event = TouchButtonsEvent { pressed_buttons: Some(vec![]), ..Default::default() };
277 let mut was_pressed = bit_vec::BitVec::from_elem(6, false);
278 was_pressed.set(button.into_primitive() as usize, true);
279 let batch = parse_fidl_touch_button_event(&fidl_event, &was_pressed);
280
281 assert_eq!(batch.events.len(), 2);
282 assert_eq!(batch.events[0].type_, uapi::EV_KEY as u16);
283 assert_eq!(batch.events[0].code, expected_key as u16);
284 assert_eq!(batch.events[0].value, 0);
285 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
286 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
287 }
288
289 #[test]
290 fn test_touch_button_no_change() {
291 let fidl_event = TouchButtonsEvent {
292 pressed_buttons: Some(vec![TouchButton::Palm]),
293 ..Default::default()
294 };
295 let mut was_pressed = bit_vec::BitVec::from_elem(6, false);
296 was_pressed.set(TouchButton::Palm.into_primitive() as usize, true);
297 let batch = parse_fidl_touch_button_event(&fidl_event, &was_pressed);
298
299 assert_eq!(batch.events.len(), 0);
300 }
301
302 #[test]
303 fn test_touch_button_multi_press() {
304 let fidl_event1 = TouchButtonsEvent {
306 pressed_buttons: Some(vec![TouchButton::Palm]),
307 ..Default::default()
308 };
309 let was_pressed1 = bit_vec::BitVec::from_elem(6, false);
310 let batch1 = parse_fidl_touch_button_event(&fidl_event1, &was_pressed1);
311
312 assert_eq!(batch1.events.len(), 2);
313 assert_eq!(batch1.events[0].type_, uapi::EV_KEY as u16);
314 assert_eq!(batch1.events[0].code, uapi::KEY_SLEEP as u16);
315 assert_eq!(batch1.events[0].value, 1);
316 assert_eq!(batch1.events[1].type_, uapi::EV_SYN as u16);
317 assert_eq!(batch1.events[1].code, uapi::SYN_REPORT as u16);
318
319 let fidl_event2 = TouchButtonsEvent {
321 pressed_buttons: Some(vec![TouchButton::Palm, TouchButton::SwipeUp]),
322 ..Default::default()
323 };
324 let was_pressed2 = batch1.touch_buttons;
325 let batch2 = parse_fidl_touch_button_event(&fidl_event2, &was_pressed2);
326
327 assert_eq!(batch2.events.len(), 2);
328 assert_eq!(batch2.events[0].type_, uapi::EV_KEY as u16);
329 assert_eq!(batch2.events[0].code, uapi::KEY_UP as u16);
330 assert_eq!(batch2.events[0].value, 1);
331 assert_eq!(batch2.events[1].type_, uapi::EV_SYN as u16);
332 assert_eq!(batch2.events[1].code, uapi::SYN_REPORT as u16);
333
334 let fidl_event3 = TouchButtonsEvent {
336 pressed_buttons: Some(vec![TouchButton::SwipeUp]),
337 ..Default::default()
338 };
339 let was_pressed3 = batch2.touch_buttons;
340 let batch3 = parse_fidl_touch_button_event(&fidl_event3, &was_pressed3);
341
342 assert_eq!(batch3.events.len(), 2);
343 assert_eq!(batch3.events[0].type_, uapi::EV_KEY as u16);
344 assert_eq!(batch3.events[0].code, uapi::KEY_SLEEP as u16);
345 assert_eq!(batch3.events[0].value, 0);
346 assert_eq!(batch3.events[1].type_, uapi::EV_SYN as u16);
347 assert_eq!(batch3.events[1].code, uapi::SYN_REPORT as u16);
348
349 let fidl_event4 = TouchButtonsEvent { pressed_buttons: Some(vec![]), ..Default::default() };
351 let was_pressed4 = batch3.touch_buttons;
352 let batch4 = parse_fidl_touch_button_event(&fidl_event4, &was_pressed4);
353
354 assert_eq!(batch4.events.len(), 2);
355 assert_eq!(batch4.events[0].type_, uapi::EV_KEY as u16);
356 assert_eq!(batch4.events[0].code, uapi::KEY_UP as u16);
357 assert_eq!(batch4.events[0].value, 0);
358 assert_eq!(batch4.events[1].type_, uapi::EV_SYN as u16);
359 assert_eq!(batch4.events[1].code, uapi::SYN_REPORT as u16);
360 }
361}