1use fidl_fuchsia_ui_test_input as futinput;
6use sorted_vec_map::{SortedVecMap, SortedVecSet};
7use starnix_logging::log_warn;
8use starnix_uapi::errors::Errno;
9use starnix_uapi::{error, uapi};
10
11type SlotId = usize;
12type TrackingId = u32;
13
14const LIFTED_TRACKING_ID: i32 = -1;
16
17enum MtPosition {
19 X(i64),
20 Y(i64),
21}
22
23#[derive(Debug, Default, PartialEq)]
46pub struct LinuxTouchEventParser {
47 slot_id_to_tracking_id: SortedVecMap<SlotId, TrackingId>,
50 slot_id_to_contact: SortedVecMap<SlotId, futinput::ContactInputReport>,
52
53 cached_events: Vec<uapi::input_event>,
55
56 current_slot_id: Option<SlotId>,
61 processed_slots: SortedVecSet<SlotId>,
64
65 single_pointer_sequence: bool,
68}
69
70impl LinuxTouchEventParser {
71 pub fn create() -> Self {
73 Self {
74 slot_id_to_tracking_id: SortedVecMap::new(),
75 slot_id_to_contact: SortedVecMap::new(),
76 cached_events: vec![],
77 current_slot_id: None,
78 processed_slots: SortedVecSet::new(),
79 single_pointer_sequence: false,
80 }
81 }
82
83 fn reset_state(&mut self) {
85 self.cached_events = vec![];
86 self.slot_id_to_tracking_id = SortedVecMap::new();
87 self.slot_id_to_contact = SortedVecMap::new();
88
89 self.reset_sequence_state();
90 }
91
92 fn reset_sequence_state(&mut self) {
94 self.current_slot_id = None;
95 self.processed_slots = SortedVecSet::new();
96 self.single_pointer_sequence = false;
97 }
98
99 fn mt_slot(&mut self, new_slot_id: SlotId) -> Result<(), Errno> {
109 if self.single_pointer_sequence {
110 log_warn!("sequence contains events in slot and out of slot");
111 self.reset_state();
112 return error!(EINVAL);
113 }
114
115 if self.processed_slots.contains(&new_slot_id) {
116 log_warn!("duplicated slot_id in one sequence, slot_id = {}", new_slot_id);
117 self.reset_state();
118 return error!(EINVAL);
119 }
120
121 self.processed_slots.insert(new_slot_id);
122 self.current_slot_id = Some(new_slot_id);
123
124 if !self.slot_id_to_contact.contains_key(&new_slot_id) {
125 self.slot_id_to_contact.insert(
126 new_slot_id,
127 futinput::ContactInputReport {
128 contact_id: Some(new_slot_id as u32),
129 ..Default::default()
130 },
131 );
132 }
133
134 Ok(())
135 }
136
137 fn get_current_slot_id_or_err(&mut self, curr_event: &str) -> Result<SlotId, Errno> {
141 match self.current_slot_id {
142 Some(slot_id) => Ok(slot_id),
143 None => {
144 log_warn!(
145 "{:?} is not following ABS_MT_SLOT, fallback to single_pointer_sequence",
146 curr_event
147 );
148 let res = self.mt_slot(0);
149 match res {
150 Ok(_) => {
151 self.single_pointer_sequence = true;
152 Ok(0)
153 }
154 Err(e) => Err(e),
155 }
156 }
157 }
158 }
159
160 fn mt_tracking_id(&mut self, tracking_id: i32) -> Result<(), Errno> {
172 let slot_id = self.get_current_slot_id_or_err("ABS_MT_TRACKING_ID")?;
173
174 if tracking_id < LIFTED_TRACKING_ID {
175 log_warn!("invalid TRACKING_ID {}", tracking_id);
177 self.reset_state();
178 return error!(EINVAL);
179 }
180
181 if tracking_id == LIFTED_TRACKING_ID {
182 self.slot_id_to_tracking_id.remove(&slot_id);
183 self.slot_id_to_contact.remove(&slot_id);
184
185 return Ok(());
186 }
187
188 let tid = tracking_id as TrackingId;
190 match self.slot_id_to_tracking_id.get(&slot_id) {
191 Some(id) => {
192 if tid != *id {
193 log_warn!(
194 "TRACKING_ID changed form {} to {} for unknown reason for slot {}",
195 *id,
196 tid,
197 slot_id
198 );
199 self.reset_state();
200 return error!(EINVAL);
201 }
202 }
203 None => {
204 self.slot_id_to_tracking_id.insert(slot_id, tid);
205 }
206 }
207
208 Ok(())
209 }
210
211 fn mt_position_x_y(&mut self, mt_position: MtPosition) -> Result<(), Errno> {
215 let ty = match mt_position {
216 MtPosition::X(_) => "ABS_MT_POSITION_X",
217 MtPosition::Y(_) => "ABS_MT_POSITION_Y",
218 };
219 let slot_id = self.get_current_slot_id_or_err(ty)?;
220
221 match self.slot_id_to_contact.get_mut(&slot_id) {
222 Some(contact) => {
223 match mt_position {
224 MtPosition::X(x) => {
225 contact.position_x = Some(x);
226 }
227 MtPosition::Y(y) => {
228 contact.position_y = Some(y);
229 }
230 }
231 Ok(())
232 }
233 None => {
234 log_warn!("current_contact is None when set position");
235 self.reset_state();
236 return error!(EINVAL);
237 }
238 }
239 }
240
241 fn produce_input_report(&mut self) -> Result<Option<futinput::TouchInputReport>, Errno> {
242 self.reset_sequence_state();
243
244 let cached_events = std::mem::take(&mut self.cached_events);
245
246 for e in cached_events {
247 match e.code as u32 {
248 uapi::ABS_MT_SLOT => {
249 let slot_id = e.value as SlotId;
250 self.mt_slot(slot_id)?;
251 }
252 uapi::ABS_MT_TRACKING_ID => {
253 self.mt_tracking_id(e.value)?;
254 }
255 uapi::ABS_MT_POSITION_X => {
256 self.mt_position_x_y(MtPosition::X(e.value as i64))?;
257 }
258 uapi::ABS_MT_POSITION_Y => {
259 self.mt_position_x_y(MtPosition::Y(e.value as i64))?;
260 }
261 _ => {
262 unreachable!();
264 }
265 }
266 }
267
268 let mut contacts: Vec<futinput::ContactInputReport> = vec![];
269 for contact in self.slot_id_to_contact.values() {
270 if validate_contact_input_report(contact) {
271 contacts.push(contact.clone());
272 } else {
273 log_warn!(
274 "current contact does not have required information, current_contact = {:?}",
275 contact
276 );
277 self.reset_state();
278 return error!(EINVAL);
279 }
280 }
281
282 contacts.sort_by(|a, b| a.contact_id.unwrap().cmp(&b.contact_id.unwrap()));
284
285 let res =
286 Ok(Some(futinput::TouchInputReport { contacts: Some(contacts), ..Default::default() }));
287
288 self.reset_sequence_state();
289
290 res
291 }
292
293 pub fn handle(
295 &mut self,
296 e: uapi::input_event,
297 ) -> Result<Option<futinput::TouchInputReport>, Errno> {
298 let event_code = e.code as u32;
299 match e.type_ as u32 {
300 uapi::EV_SYN => match event_code {
301 uapi::SYN_REPORT => self.produce_input_report(),
302 uapi::SYN_MT_REPORT => {
303 log_warn!("Touchscreen got 'Type A' event SYN_MT_REPORT");
304 self.reset_state();
305 error!(EINVAL)
306 }
307 _ => {
308 log_warn!("Touchscreen got unexpected EV_SYN, event = {:?}", e);
309 self.reset_state();
310 error!(EINVAL)
311 }
312 },
313 uapi::EV_ABS => match event_code {
314 uapi::ABS_MT_SLOT
315 | uapi::ABS_MT_TRACKING_ID
316 | uapi::ABS_MT_POSITION_X
317 | uapi::ABS_MT_POSITION_Y => {
318 self.cached_events.push(e);
319 Ok(None)
320 }
321 uapi::ABS_MT_TOUCH_MAJOR
322 | uapi::ABS_MT_TOUCH_MINOR
323 | uapi::ABS_MT_WIDTH_MAJOR
324 | uapi::ABS_MT_WIDTH_MINOR
325 | uapi::ABS_MT_ORIENTATION
326 | uapi::ABS_MT_TOOL_TYPE
327 | uapi::ABS_MT_BLOB_ID
328 | uapi::ABS_MT_PRESSURE
329 | uapi::ABS_MT_DISTANCE
330 | uapi::ABS_MT_TOOL_X
331 | uapi::ABS_MT_TOOL_Y => {
332 Ok(None)
334 }
335 _ => {
336 log_warn!("Touchscreen got unexpected EV_ABS, event = {:?}", e);
337 self.reset_state();
338 error!(EINVAL)
339 }
340 },
341 uapi::EV_KEY => {
342 match event_code {
343 uapi::BTN_TOUCH => Ok(None),
345 _ => {
346 log_warn!("Touchscreen got unexpected EV_KEY, event = {:?}", e);
347 self.reset_state();
348 error!(EINVAL)
349 }
350 }
351 }
352 _ => {
353 log_warn!("Touchscreen got unexpected event type, got = {:?}", e);
354 self.reset_state();
355 error!(EINVAL)
356 }
357 }
358 }
359}
360
361fn validate_contact_input_report(c: &futinput::ContactInputReport) -> bool {
363 match c {
364 &futinput::ContactInputReport {
365 contact_id: Some(_),
366 position_x: Some(_),
367 position_y: Some(_),
368 ..
369 } => true,
370 _ => false,
371 }
372}
373
374#[cfg(test)]
375mod touchscreen_linux_fuchsia_tests {
376 use super::*;
377 use pretty_assertions::assert_eq;
378 use test_case::test_case;
379 use uapi::timeval;
380
381 fn input_event(ty: u32, code: u32, value: i32) -> uapi::input_event {
382 uapi::input_event { time: timeval::default(), type_: ty as u16, code: code as u16, value }
383 }
384
385 #[test]
386 fn handle_btn_touch_ok_does_not_produce_input_report() {
387 let e = input_event(uapi::EV_KEY, uapi::BTN_TOUCH, 1);
388 let mut parser = LinuxTouchEventParser::create();
389 assert_eq!(parser.handle(e), Ok(None));
390 assert_eq!(parser, LinuxTouchEventParser::default());
391 }
392
393 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_SLOT, 1); "ABS_MT_SLOT")]
394 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_TRACKING_ID, 1); "ABS_MT_TRACKING_ID")]
395 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_X, 1); "ABS_MT_POSITION_X")]
396 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_Y, 1); "ABS_MT_POSITION_Y")]
397 fn handle_input_event_ok_does_not_produce_input_report(e: uapi::input_event) {
398 let mut parser = LinuxTouchEventParser::create();
399 assert_eq!(parser.handle(e), Ok(None));
400 assert_eq!(
401 parser,
402 LinuxTouchEventParser {
403 cached_events: vec![e],
404 slot_id_to_tracking_id: SortedVecMap::new(),
405 ..LinuxTouchEventParser::default()
406 }
407 );
408 }
409
410 #[test_case(input_event(uapi::EV_KEY, uapi::KEY_A, 1); "unsupported keycode")]
411 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_PRESSURE, 1); "unsupported ABS event")]
412 #[test_case(input_event(uapi::EV_SYN, uapi::SYN_MT_REPORT, 1); "Type A")]
413 #[test_case(input_event(uapi::EV_SYN, uapi::SYN_CONFIG, 1); "unsupported SYN event")]
414 fn handle_input_event_error(e: uapi::input_event) {
415 let mut parser = LinuxTouchEventParser::create();
416 assert_eq!(parser.handle(e), error!(EINVAL));
417 assert_eq!(parser, LinuxTouchEventParser::default());
418 }
419
420 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_TOUCH_MAJOR, 1); "ignore ABS_MT_TOUCH_MAJOR event")]
421 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_TOUCH_MINOR, 1); "ignore ABS_MT_TOUCH_MINOR event")]
422 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_WIDTH_MAJOR, 1); "ignore ABS_MT_WIDTH_MAJOR event")]
423 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_WIDTH_MINOR, 1); "ignore ABS_MT_WIDTH_MINOR event")]
424 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_ORIENTATION, 1); "ignore ABS_MT_ORIENTATION event")]
425 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_TOOL_TYPE, 1); "ignore ABS_MT_TOOL_TYPE event")]
426 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_BLOB_ID, 1); "ignore ABS_MT_BLOB_ID event")]
427 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_PRESSURE, 1); "ignore ABS_MT_PRESSURE event")]
428 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_DISTANCE, 1); "ignore ABS_MT_DISTANCE event")]
429 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_TOOL_X, 1); "ignore ABS_MT_TOOL_X event")]
430 #[test_case(input_event(uapi::EV_ABS, uapi::ABS_MT_TOOL_Y , 1); "ignore ABS_MT_TOOL_Y event")]
431 fn handle_input_event_ignore(e: uapi::input_event) {
432 let mut parser = LinuxTouchEventParser::create();
433 assert_eq!(parser.handle(e), Ok(None));
434 assert_eq!(parser, LinuxTouchEventParser::default());
435 }
436
437 #[test]
438 fn no_slot_leading_event_fallback_to_single_pointer_mode() {
439 let syn = input_event(uapi::EV_SYN, uapi::SYN_REPORT, 0);
440
441 let mut parser = LinuxTouchEventParser::create();
442 assert_eq!(parser.handle(input_event(uapi::EV_ABS, uapi::ABS_MT_TRACKING_ID, 1)), Ok(None));
443 assert_eq!(parser.handle(input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_X, 2)), Ok(None));
444 assert_eq!(parser.handle(input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_Y, 3)), Ok(None));
445 assert_eq!(
446 parser.handle(syn),
447 Ok(Some(futinput::TouchInputReport {
448 contacts: Some(vec![futinput::ContactInputReport {
449 contact_id: Some(0),
450 position_x: Some(2),
451 position_y: Some(3),
452 ..Default::default()
453 }]),
454 ..Default::default()
455 }))
456 );
457 assert_eq!(
458 parser,
459 LinuxTouchEventParser {
460 cached_events: vec![],
461 slot_id_to_tracking_id: SortedVecMap::from([(0, 1)]),
462 slot_id_to_contact: SortedVecMap::from([(
463 0,
464 futinput::ContactInputReport {
465 contact_id: Some(0),
466 position_x: Some(2),
467 position_y: Some(3),
468 ..Default::default()
469 }
470 )]),
471 ..LinuxTouchEventParser::default()
472 }
473 );
474 }
475
476 #[test]
477 fn single_pointer_mode_slot_does_not_have_enough_information() {
478 let syn = input_event(uapi::EV_SYN, uapi::SYN_REPORT, 0);
479
480 let mut parser = LinuxTouchEventParser::create();
481 assert_eq!(parser.handle(input_event(uapi::EV_ABS, uapi::ABS_MT_TRACKING_ID, 1)), Ok(None));
482 assert_eq!(parser.handle(input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_X, 2)), Ok(None));
483 assert_eq!(parser.handle(input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_Y, 3)), Ok(None));
484 assert_eq!(
485 parser.handle(syn),
486 Ok(Some(futinput::TouchInputReport {
487 contacts: Some(vec![futinput::ContactInputReport {
488 contact_id: Some(0),
489 position_x: Some(2),
490 position_y: Some(3),
491 ..Default::default()
492 }]),
493 ..Default::default()
494 }))
495 );
496 assert_eq!(
497 parser,
498 LinuxTouchEventParser {
499 cached_events: vec![],
500 slot_id_to_tracking_id: SortedVecMap::from([(0, 1)]),
501 slot_id_to_contact: SortedVecMap::from([(
502 0,
503 futinput::ContactInputReport {
504 contact_id: Some(0),
505 position_x: Some(2),
506 position_y: Some(3),
507 ..Default::default()
508 }
509 )]),
510 ..LinuxTouchEventParser::default()
511 }
512 );
513
514 assert_eq!(parser.handle(input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_Y, 4)), Ok(None));
516 assert_eq!(
517 parser.handle(syn),
518 Ok(Some(futinput::TouchInputReport {
519 contacts: Some(vec![futinput::ContactInputReport {
520 contact_id: Some(0),
521 position_x: Some(2),
522 position_y: Some(4),
523 ..Default::default()
524 }]),
525 ..Default::default()
526 }))
527 );
528 assert_eq!(
529 parser,
530 LinuxTouchEventParser {
531 cached_events: vec![],
532 slot_id_to_tracking_id: SortedVecMap::from([(0, 1)]),
533 slot_id_to_contact: SortedVecMap::from([(
534 0,
535 futinput::ContactInputReport {
536 contact_id: Some(0),
537 position_x: Some(2),
538 position_y: Some(4),
539 ..Default::default()
540 }
541 )]),
542 ..LinuxTouchEventParser::default()
543 }
544 );
545
546 assert_eq!(parser.handle(input_event(uapi::EV_ABS, uapi::ABS_MT_PRESSURE, 10)), Ok(None));
548 assert_eq!(
549 parser.handle(syn),
550 Ok(Some(futinput::TouchInputReport {
551 contacts: Some(vec![futinput::ContactInputReport {
552 contact_id: Some(0),
553 position_x: Some(2),
554 position_y: Some(4),
555 ..Default::default()
556 }]),
557 ..Default::default()
558 }))
559 );
560 assert_eq!(
561 parser,
562 LinuxTouchEventParser {
563 cached_events: vec![],
564 slot_id_to_tracking_id: SortedVecMap::from([(0, 1)]),
565 slot_id_to_contact: SortedVecMap::from([(
566 0,
567 futinput::ContactInputReport {
568 contact_id: Some(0),
569 position_x: Some(2),
570 position_y: Some(4),
571 ..Default::default()
572 }
573 )]),
574 ..LinuxTouchEventParser::default()
575 }
576 );
577 }
578
579 #[test]
580 fn slot_has_only_pressure_event() {
581 let slot_0 = input_event(uapi::EV_ABS, uapi::ABS_MT_SLOT, 0);
582 let syn = input_event(uapi::EV_SYN, uapi::SYN_REPORT, 0);
583
584 let mut parser = LinuxTouchEventParser::create();
585 assert_eq!(parser.handle(slot_0), Ok(None));
586 assert_eq!(parser.handle(input_event(uapi::EV_ABS, uapi::ABS_MT_TRACKING_ID, 1)), Ok(None));
587 assert_eq!(parser.handle(input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_X, 2)), Ok(None));
588 assert_eq!(parser.handle(input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_Y, 3)), Ok(None));
589 assert_eq!(
590 parser.handle(syn),
591 Ok(Some(futinput::TouchInputReport {
592 contacts: Some(vec![futinput::ContactInputReport {
593 contact_id: Some(0),
594 position_x: Some(2),
595 position_y: Some(3),
596 ..Default::default()
597 }]),
598 ..Default::default()
599 }))
600 );
601 assert_eq!(
602 parser,
603 LinuxTouchEventParser {
604 cached_events: vec![],
605 slot_id_to_tracking_id: SortedVecMap::from([(0, 1)]),
606 slot_id_to_contact: SortedVecMap::from([(
607 0,
608 futinput::ContactInputReport {
609 contact_id: Some(0),
610 position_x: Some(2),
611 position_y: Some(3),
612 ..Default::default()
613 }
614 )]),
615 ..LinuxTouchEventParser::default()
616 }
617 );
618
619 assert_eq!(parser.handle(slot_0), Ok(None));
621 assert_eq!(parser.handle(input_event(uapi::EV_ABS, uapi::ABS_MT_PRESSURE, 10)), Ok(None));
622 assert_eq!(
623 parser.handle(syn),
624 Ok(Some(futinput::TouchInputReport {
625 contacts: Some(vec![futinput::ContactInputReport {
626 contact_id: Some(0),
627 position_x: Some(2),
628 position_y: Some(3),
629 ..Default::default()
630 }]),
631 ..Default::default()
632 }))
633 );
634 assert_eq!(
635 parser,
636 LinuxTouchEventParser {
637 cached_events: vec![],
638 slot_id_to_tracking_id: SortedVecMap::from([(0, 1)]),
639 slot_id_to_contact: SortedVecMap::from([(
640 0,
641 futinput::ContactInputReport {
642 contact_id: Some(0),
643 position_x: Some(2),
644 position_y: Some(3),
645 ..Default::default()
646 }
647 )]),
648 ..LinuxTouchEventParser::default()
649 }
650 );
651 }
652
653 #[test]
654 fn slot_does_not_have_enough_information() {
655 let slot_0 = input_event(uapi::EV_ABS, uapi::ABS_MT_SLOT, 0);
656 let syn = input_event(uapi::EV_SYN, uapi::SYN_REPORT, 0);
657
658 let mut parser = LinuxTouchEventParser::create();
659
660 assert_eq!(parser.handle(slot_0), Ok(None));
662 assert_eq!(parser.handle(syn), error!(EINVAL));
663 assert_eq!(parser, LinuxTouchEventParser::default());
664
665 let slot_1 = input_event(uapi::EV_ABS, uapi::ABS_MT_SLOT, 1);
667 assert_eq!(parser.handle(slot_0), Ok(None));
668 assert_eq!(parser.handle(slot_1), Ok(None));
669 assert_eq!(parser.handle(syn), error!(EINVAL));
670 assert_eq!(parser, LinuxTouchEventParser::default());
671 }
672
673 #[test]
674 fn same_slot_id_in_one_event() {
675 let slot_0 = input_event(uapi::EV_ABS, uapi::ABS_MT_SLOT, 0);
676 let traking_id = input_event(uapi::EV_ABS, uapi::ABS_MT_TRACKING_ID, 0);
677 let x = input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_X, 0);
678 let y = input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_Y, 0);
679 let syn = input_event(uapi::EV_SYN, uapi::SYN_REPORT, 0);
680
681 let mut parser = LinuxTouchEventParser::create();
682 assert_eq!(parser.handle(slot_0), Ok(None));
683 assert_eq!(parser.handle(traking_id), Ok(None));
684 assert_eq!(parser.handle(x), Ok(None));
685 assert_eq!(parser.handle(y), Ok(None));
686 assert_eq!(parser.handle(slot_0), Ok(None));
687 assert_eq!(parser.handle(syn), error!(EINVAL));
688 assert_eq!(parser, LinuxTouchEventParser::default());
689 }
690
691 #[test]
692 fn tracking_id_changed_in_slot() {
693 let slot_0 = input_event(uapi::EV_ABS, uapi::ABS_MT_SLOT, 0);
694 let traking_id_0 = input_event(uapi::EV_ABS, uapi::ABS_MT_TRACKING_ID, 0);
695 let traking_id_1 = input_event(uapi::EV_ABS, uapi::ABS_MT_TRACKING_ID, 1);
696 let syn = input_event(uapi::EV_SYN, uapi::SYN_REPORT, 0);
697
698 let mut parser = LinuxTouchEventParser::create();
699 assert_eq!(parser.handle(slot_0), Ok(None));
700 assert_eq!(parser.handle(traking_id_0), Ok(None));
701 assert_eq!(parser.handle(traking_id_1), Ok(None));
702 assert_eq!(parser.handle(syn), error!(EINVAL));
703 assert_eq!(parser, LinuxTouchEventParser::default());
704 }
705
706 #[test]
707 fn tracking_id_different_with_parser_recorded() {
708 let slot_0 = input_event(uapi::EV_ABS, uapi::ABS_MT_SLOT, 0);
709 let traking_id_1 = input_event(uapi::EV_ABS, uapi::ABS_MT_TRACKING_ID, 1);
710 let syn = input_event(uapi::EV_SYN, uapi::SYN_REPORT, 0);
711
712 let mut parser = LinuxTouchEventParser::create();
713 parser.slot_id_to_tracking_id.insert(0, 0);
714 assert_eq!(parser.handle(slot_0), Ok(None));
715 assert_eq!(parser.handle(traking_id_1), Ok(None));
716 assert_eq!(parser.handle(syn), error!(EINVAL));
717 assert_eq!(parser, LinuxTouchEventParser::default());
718 }
719
720 #[test]
721 fn produce_input_report() {
722 let slot_0 = input_event(uapi::EV_ABS, uapi::ABS_MT_SLOT, 0);
724 let traking_id_0 = input_event(uapi::EV_ABS, uapi::ABS_MT_TRACKING_ID, 1);
725 let x_0 = input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_X, 2);
726 let y_0 = input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_Y, 3);
727 let syn = input_event(uapi::EV_SYN, uapi::SYN_REPORT, 0);
728
729 let mut parser = LinuxTouchEventParser::create();
730 assert_eq!(parser.handle(slot_0), Ok(None));
731 assert_eq!(parser.handle(traking_id_0), Ok(None));
732 assert_eq!(parser.handle(x_0), Ok(None));
733 assert_eq!(parser.handle(y_0), Ok(None));
734 assert_eq!(
735 parser.handle(syn),
736 Ok(Some(futinput::TouchInputReport {
737 contacts: Some(vec![futinput::ContactInputReport {
738 contact_id: Some(0),
739 position_x: Some(2),
740 position_y: Some(3),
741 ..Default::default()
742 }]),
743 ..Default::default()
744 }))
745 );
746 assert_eq!(
747 parser,
748 LinuxTouchEventParser {
749 cached_events: vec![],
750 slot_id_to_tracking_id: SortedVecMap::from([(0, 1)]),
751 slot_id_to_contact: SortedVecMap::from([(
752 0,
753 futinput::ContactInputReport {
754 contact_id: Some(0),
755 position_x: Some(2),
756 position_y: Some(3),
757 ..Default::default()
758 }
759 )]),
760 ..LinuxTouchEventParser::default()
761 }
762 );
763
764 let x_0 = input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_X, 4);
766 let y_0 = input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_Y, 5);
767
768 let slot_1 = input_event(uapi::EV_ABS, uapi::ABS_MT_SLOT, 1);
769 let traking_id_1 = input_event(uapi::EV_ABS, uapi::ABS_MT_TRACKING_ID, 2);
770 let x_1 = input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_X, 10);
771 let y_1 = input_event(uapi::EV_ABS, uapi::ABS_MT_POSITION_Y, 11);
772
773 assert_eq!(parser.handle(slot_0), Ok(None));
774 assert_eq!(parser.handle(x_0), Ok(None));
775 assert_eq!(parser.handle(y_0), Ok(None));
776 assert_eq!(parser.handle(slot_1), Ok(None));
777 assert_eq!(parser.handle(traking_id_1), Ok(None));
778 assert_eq!(parser.handle(x_1), Ok(None));
779 assert_eq!(parser.handle(y_1), Ok(None));
780 assert_eq!(
781 parser.handle(syn),
782 Ok(Some(futinput::TouchInputReport {
783 contacts: Some(vec![
784 futinput::ContactInputReport {
785 contact_id: Some(0),
786 position_x: Some(4),
787 position_y: Some(5),
788 ..Default::default()
789 },
790 futinput::ContactInputReport {
791 contact_id: Some(1),
792 position_x: Some(10),
793 position_y: Some(11),
794 ..Default::default()
795 },
796 ]),
797 ..Default::default()
798 }))
799 );
800 assert_eq!(
801 parser,
802 LinuxTouchEventParser {
803 cached_events: vec![],
804 slot_id_to_tracking_id: SortedVecMap::from([(0, 1), (1, 2)]),
805 slot_id_to_contact: SortedVecMap::from([
806 (
807 0,
808 futinput::ContactInputReport {
809 contact_id: Some(0),
810 position_x: Some(4),
811 position_y: Some(5),
812 ..Default::default()
813 }
814 ),
815 (
816 1,
817 futinput::ContactInputReport {
818 contact_id: Some(1),
819 position_x: Some(10),
820 position_y: Some(11),
821 ..Default::default()
822 }
823 )
824 ]),
825 ..LinuxTouchEventParser::default()
826 }
827 );
828
829 let tracking_id_lifted = input_event(uapi::EV_ABS, uapi::ABS_MT_TRACKING_ID, -1);
831
832 assert_eq!(parser.handle(slot_0), Ok(None));
833 assert_eq!(parser.handle(tracking_id_lifted), Ok(None));
834 assert_eq!(parser.handle(slot_1), Ok(None));
835 assert_eq!(parser.handle(x_1), Ok(None));
836 assert_eq!(parser.handle(y_1), Ok(None));
837 assert_eq!(
838 parser.handle(syn),
839 Ok(Some(futinput::TouchInputReport {
840 contacts: Some(vec![futinput::ContactInputReport {
841 contact_id: Some(1),
842 position_x: Some(10),
843 position_y: Some(11),
844 ..Default::default()
845 }]),
846 ..Default::default()
847 }))
848 );
849 assert_eq!(
851 parser,
852 LinuxTouchEventParser {
853 cached_events: vec![],
854 slot_id_to_tracking_id: SortedVecMap::from([(1, 2)]),
855 slot_id_to_contact: SortedVecMap::from([(
856 1,
857 futinput::ContactInputReport {
858 contact_id: Some(1),
859 position_x: Some(10),
860 position_y: Some(11),
861 ..Default::default()
862 }
863 )]),
864 ..LinuxTouchEventParser::default()
865 }
866 );
867
868 assert_eq!(parser.handle(slot_1), Ok(None));
870 assert_eq!(parser.handle(tracking_id_lifted), Ok(None));
871 assert_eq!(
872 parser.handle(syn),
873 Ok(Some(futinput::TouchInputReport { contacts: Some(vec![]), ..Default::default() }))
874 );
875 assert_eq!(parser, LinuxTouchEventParser::default());
877 }
878}