starnix_modules_input_event_conversion/
button_fuchsia_to_linux.rs1use 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
29 pub touch_buttons: bit_vec::BitVec,
31}
32
33impl LinuxButtonEventBatch {
34 pub fn new() -> Self {
35 Self {
36 events: vec![],
37 event_time: zx::MonotonicInstant::get(),
38 power_is_pressed: false,
39 function_is_pressed: false,
40 touch_buttons: new_touch_buttons_bitvec(),
41 }
42 }
43}
44
45pub fn parse_fidl_media_button_event(
46 fidl_event: &MediaButtonsEvent,
47 power_was_pressed: bool,
48 function_was_pressed: bool,
49) -> LinuxButtonEventBatch {
50 let mut batch = LinuxButtonEventBatch::new();
51 let time = timeval_from_time(batch.event_time);
52 let sync_event = uapi::input_event {
53 time,
55 type_: uapi::EV_SYN as u16,
56 code: uapi::SYN_REPORT as u16,
57 value: 0,
58 };
59
60 batch.power_is_pressed = fidl_event.power.unwrap_or(false);
61 batch.function_is_pressed = fidl_event.function.unwrap_or(false);
62 for (button_was_pressed, button_is_pressed, key_code) in [
63 (power_was_pressed, batch.power_is_pressed, uapi::KEY_POWER),
64 (function_was_pressed, batch.function_is_pressed, uapi::KEY_VOLUMEDOWN),
65 ] {
66 if button_is_pressed != button_was_pressed {
68 batch.events.push(uapi::input_event {
69 time,
70 type_: uapi::EV_KEY as u16,
71 code: key_code as u16,
72 value: button_is_pressed as i32,
73 });
74 batch.events.push(sync_event);
75 }
76 }
77
78 batch
79}
80
81pub fn parse_fidl_touch_button_event(
82 fidl_event: &TouchButtonsEvent,
83 touch_buttons_were_pressed: &bit_vec::BitVec,
84) -> LinuxButtonEventBatch {
85 let mut batch = LinuxButtonEventBatch::new();
86 let time = timeval_from_time(batch.event_time);
87 let sync_event = uapi::input_event {
88 time,
90 type_: uapi::EV_SYN as u16,
91 code: uapi::SYN_REPORT as u16,
92 value: 0,
93 };
94
95 if let Some(buttons) = &fidl_event.pressed_buttons {
96 for button in buttons {
97 let index = button.into_primitive() as usize;
98 if index < batch.touch_buttons.len() {
99 batch.touch_buttons.set(index, true);
100 }
101 }
102 };
103
104 for (index, key_code) in [
105 (TouchButton::Palm.into_primitive() as usize, uapi::KEY_SLEEP),
106 (TouchButton::SwipeUp.into_primitive() as usize, uapi::KEY_UP),
107 (TouchButton::SwipeLeft.into_primitive() as usize, uapi::KEY_LEFT),
108 (TouchButton::SwipeRight.into_primitive() as usize, uapi::KEY_RIGHT),
109 (TouchButton::SwipeDown.into_primitive() as usize, uapi::KEY_DOWN),
110 ] {
111 let button_was_pressed = touch_buttons_were_pressed.get(index).unwrap_or(false);
112 let button_is_pressed = batch.touch_buttons.get(index).unwrap_or(false);
113
114 if button_is_pressed != button_was_pressed {
116 batch.events.push(uapi::input_event {
117 time,
118 type_: uapi::EV_KEY as u16,
119 code: key_code as u16,
120 value: button_is_pressed as i32,
121 });
122 batch.events.push(sync_event);
123 }
124 }
125
126 batch
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132 use assert_matches::assert_matches;
133 use pretty_assertions::assert_eq;
134
135 #[test]
136 fn test_ensure_touch_button_max() {
137 assert_matches!(TouchButton::from_primitive(MAX_TOUCH_BUTTON_VALUE + 1), None);
140 }
141
142 #[test]
143 fn test_media_button_press_power() {
144 let fidl_event = MediaButtonsEvent { power: Some(true), ..Default::default() };
145 let batch = parse_fidl_media_button_event(&fidl_event, false, false);
146
147 assert_eq!(batch.events.len(), 2);
148 assert_eq!(batch.events[0].type_, uapi::EV_KEY as u16);
149 assert_eq!(batch.events[0].code, uapi::KEY_POWER as u16);
150 assert_eq!(batch.events[0].value, 1);
151 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
152 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
153 }
154
155 #[test]
156 fn test_media_button_release_power() {
157 let fidl_event = MediaButtonsEvent { power: Some(false), ..Default::default() };
158 let batch = parse_fidl_media_button_event(&fidl_event, true, 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, 0);
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_no_change() {
170 let fidl_event = MediaButtonsEvent { power: Some(true), ..Default::default() };
171 let batch = parse_fidl_media_button_event(&fidl_event, true, false);
172
173 assert_eq!(batch.events.len(), 0);
174 }
175
176 use test_case::test_case;
177
178 #[test_case(TouchButton::Palm, uapi::KEY_SLEEP; "palm")]
179 #[test_case(TouchButton::SwipeUp, uapi::KEY_UP; "swipe up")]
180 #[test_case(TouchButton::SwipeLeft, uapi::KEY_LEFT; "swipe left")]
181 #[test_case(TouchButton::SwipeRight, uapi::KEY_RIGHT; "swipe right")]
182 #[test_case(TouchButton::SwipeDown, uapi::KEY_DOWN; "swipe down")]
183 fn test_touch_button_press(button: TouchButton, expected_key: u32) {
184 let fidl_event =
185 TouchButtonsEvent { pressed_buttons: Some(vec![button]), ..Default::default() };
186 let was_pressed = bit_vec::BitVec::from_elem(6, false);
187 let batch = parse_fidl_touch_button_event(&fidl_event, &was_pressed);
188
189 assert_eq!(batch.events.len(), 2);
190 assert_eq!(batch.events[0].type_, uapi::EV_KEY as u16);
191 assert_eq!(batch.events[0].code, expected_key as u16);
192 assert_eq!(batch.events[0].value, 1);
193 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
194 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
195 }
196
197 #[test_case(TouchButton::Palm, uapi::KEY_SLEEP; "palm")]
198 #[test_case(TouchButton::SwipeUp, uapi::KEY_UP; "swipe up")]
199 #[test_case(TouchButton::SwipeLeft, uapi::KEY_LEFT; "swipe left")]
200 #[test_case(TouchButton::SwipeRight, uapi::KEY_RIGHT; "swipe right")]
201 #[test_case(TouchButton::SwipeDown, uapi::KEY_DOWN; "swipe down")]
202 fn test_touch_button_release(button: TouchButton, expected_key: u32) {
203 let fidl_event = TouchButtonsEvent { pressed_buttons: Some(vec![]), ..Default::default() };
204 let mut was_pressed = bit_vec::BitVec::from_elem(6, false);
205 was_pressed.set(button.into_primitive() as usize, true);
206 let batch = parse_fidl_touch_button_event(&fidl_event, &was_pressed);
207
208 assert_eq!(batch.events.len(), 2);
209 assert_eq!(batch.events[0].type_, uapi::EV_KEY as u16);
210 assert_eq!(batch.events[0].code, expected_key as u16);
211 assert_eq!(batch.events[0].value, 0);
212 assert_eq!(batch.events[1].type_, uapi::EV_SYN as u16);
213 assert_eq!(batch.events[1].code, uapi::SYN_REPORT as u16);
214 }
215
216 #[test]
217 fn test_touch_button_no_change() {
218 let fidl_event = TouchButtonsEvent {
219 pressed_buttons: Some(vec![TouchButton::Palm]),
220 ..Default::default()
221 };
222 let mut was_pressed = bit_vec::BitVec::from_elem(6, false);
223 was_pressed.set(TouchButton::Palm.into_primitive() as usize, true);
224 let batch = parse_fidl_touch_button_event(&fidl_event, &was_pressed);
225
226 assert_eq!(batch.events.len(), 0);
227 }
228
229 #[test]
230 fn test_touch_button_multi_press() {
231 let fidl_event1 = TouchButtonsEvent {
233 pressed_buttons: Some(vec![TouchButton::Palm]),
234 ..Default::default()
235 };
236 let was_pressed1 = bit_vec::BitVec::from_elem(6, false);
237 let batch1 = parse_fidl_touch_button_event(&fidl_event1, &was_pressed1);
238
239 assert_eq!(batch1.events.len(), 2);
240 assert_eq!(batch1.events[0].type_, uapi::EV_KEY as u16);
241 assert_eq!(batch1.events[0].code, uapi::KEY_SLEEP as u16);
242 assert_eq!(batch1.events[0].value, 1);
243 assert_eq!(batch1.events[1].type_, uapi::EV_SYN as u16);
244 assert_eq!(batch1.events[1].code, uapi::SYN_REPORT as u16);
245
246 let fidl_event2 = TouchButtonsEvent {
248 pressed_buttons: Some(vec![TouchButton::Palm, TouchButton::SwipeUp]),
249 ..Default::default()
250 };
251 let was_pressed2 = batch1.touch_buttons;
252 let batch2 = parse_fidl_touch_button_event(&fidl_event2, &was_pressed2);
253
254 assert_eq!(batch2.events.len(), 2);
255 assert_eq!(batch2.events[0].type_, uapi::EV_KEY as u16);
256 assert_eq!(batch2.events[0].code, uapi::KEY_UP as u16);
257 assert_eq!(batch2.events[0].value, 1);
258 assert_eq!(batch2.events[1].type_, uapi::EV_SYN as u16);
259 assert_eq!(batch2.events[1].code, uapi::SYN_REPORT as u16);
260
261 let fidl_event3 = TouchButtonsEvent {
263 pressed_buttons: Some(vec![TouchButton::SwipeUp]),
264 ..Default::default()
265 };
266 let was_pressed3 = batch2.touch_buttons;
267 let batch3 = parse_fidl_touch_button_event(&fidl_event3, &was_pressed3);
268
269 assert_eq!(batch3.events.len(), 2);
270 assert_eq!(batch3.events[0].type_, uapi::EV_KEY as u16);
271 assert_eq!(batch3.events[0].code, uapi::KEY_SLEEP as u16);
272 assert_eq!(batch3.events[0].value, 0);
273 assert_eq!(batch3.events[1].type_, uapi::EV_SYN as u16);
274 assert_eq!(batch3.events[1].code, uapi::SYN_REPORT as u16);
275
276 let fidl_event4 = TouchButtonsEvent { pressed_buttons: Some(vec![]), ..Default::default() };
278 let was_pressed4 = batch3.touch_buttons;
279 let batch4 = parse_fidl_touch_button_event(&fidl_event4, &was_pressed4);
280
281 assert_eq!(batch4.events.len(), 2);
282 assert_eq!(batch4.events[0].type_, uapi::EV_KEY as u16);
283 assert_eq!(batch4.events[0].code, uapi::KEY_UP as u16);
284 assert_eq!(batch4.events[0].value, 0);
285 assert_eq!(batch4.events[1].type_, uapi::EV_SYN as u16);
286 assert_eq!(batch4.events[1].code, uapi::SYN_REPORT as u16);
287 }
288}