1use async_utils::event::Event as AsyncEvent;
6use fidl_fuchsia_input::Key;
7use fidl_fuchsia_input_injection::InputDeviceRegistryMarker;
8use fidl_fuchsia_input_report::{
9 ConsumerControlInputReport, ContactInputReport, DeviceInformation, InputReport,
10 KeyboardInputReport, MouseInputReport, TouchInputReport,
11};
12use fidl_fuchsia_ui_input::KeyboardReport;
13use fidl_fuchsia_ui_test_input::{
14 CoordinateUnit, KeyboardMarker, KeyboardRequest, KeyboardRequestStream,
15 MediaButtonsDeviceMarker, MediaButtonsDeviceRequest, MediaButtonsDeviceRequestStream,
16 MouseMarker, MouseRequest, MouseRequestStream,
17 RegistryRegisterKeyboardAndGetDeviceInfoResponse,
18 RegistryRegisterMediaButtonsDeviceAndGetDeviceInfoResponse,
19 RegistryRegisterMouseAndGetDeviceInfoResponse,
20 RegistryRegisterTouchScreenAndGetDeviceInfoResponse, RegistryRequest, RegistryRequestStream,
21 TouchScreenMarker, TouchScreenRequest, TouchScreenRequestStream,
22};
23use fuchsia_component::client::connect_to_protocol;
24use futures::{StreamExt, TryStreamExt};
25use keymaps::inverse_keymap::{InverseKeymap, Shift};
26use keymaps::usages::{Usages, hid_usage_to_input3_key};
27use log::{error, info, warn};
28use std::time::Duration;
29use {
30 fidl_fuchsia_math as math, fidl_fuchsia_ui_display_singleton as display_info,
31 fuchsia_async as fasync,
32};
33
34mod input_device;
35mod input_device_registry;
36mod input_reports_reader;
37
38fn new_fake_device_info() -> DeviceInformation {
40 DeviceInformation {
41 product_id: Some(42),
42 vendor_id: Some(43),
43 version: Some(u32::MAX),
44 polling_rate: Some(1000),
45 ..Default::default()
46 }
47}
48
49fn derive_key_sequence(keymap: &keymaps::Keymap<'_>, input: &str) -> Option<Vec<KeyboardReport>> {
75 let inverse_keymap = InverseKeymap::new(keymap);
76 let mut reports = vec![];
77 let mut shift_pressed = false;
78 let mut last_usage = None;
79
80 for ch in input.chars() {
81 let key_stroke = inverse_keymap.get(&ch)?;
82
83 match key_stroke.shift {
84 Shift::Yes if !shift_pressed => {
85 shift_pressed = true;
86 last_usage = Some(0);
87 }
88 Shift::No if shift_pressed => {
89 shift_pressed = false;
90 last_usage = Some(0);
91 }
92 _ => {
93 if last_usage == Some(key_stroke.usage) {
94 last_usage = Some(0);
95 }
96 }
97 }
98
99 if let Some(0) = last_usage {
100 reports.push(KeyboardReport {
101 pressed_keys: if shift_pressed {
102 vec![Usages::HidUsageKeyLeftShift as u32]
103 } else {
104 vec![]
105 },
106 });
107 }
108
109 last_usage = Some(key_stroke.usage);
110
111 reports.push(KeyboardReport {
112 pressed_keys: if shift_pressed {
113 vec![key_stroke.usage, Usages::HidUsageKeyLeftShift as u32]
114 } else {
115 vec![key_stroke.usage]
116 },
117 });
118 }
119
120 reports.push(KeyboardReport { pressed_keys: vec![] });
121
122 Some(reports)
123}
124
125fn convert_keyboard_report_to_keys(report: &KeyboardReport) -> Vec<Key> {
126 report
127 .pressed_keys
128 .iter()
129 .map(|&usage| {
130 hid_usage_to_input3_key(usage.try_into().expect("failed to convert usage to u16"))
131 .unwrap_or_else(|| panic!("no Key for usage {:?}", usage))
132 })
133 .collect()
134}
135
136async fn register_touch_screen(
137 mut registry: input_device_registry::InputDeviceRegistry,
138 task_group: &mut fasync::TaskGroup,
139 device_server_end: fidl::endpoints::ServerEnd<TouchScreenMarker>,
140 got_input_reports_reader: AsyncEvent,
141 min_x: i64,
142 max_x: i64,
143 min_y: i64,
144 max_y: i64,
145) -> input_device::DeviceId {
146 let device = registry
147 .add_touchscreen_device(min_x, max_x, min_y, max_y)
148 .await
149 .expect("failed to create fake touchscreen device");
150 let device_id = device.device_id;
151
152 task_group.spawn(async move {
153 handle_touchscreen_request_stream(device, device_server_end.into_stream()).await;
154 });
155
156 info!("wait for input-pipeline setup input-reader");
157 let _ = got_input_reports_reader.wait().await;
158 info!("input-pipeline setup input-reader.");
159
160 device_id
161}
162
163async fn register_media_button(
164 mut registry: input_device_registry::InputDeviceRegistry,
165 task_group: &mut fasync::TaskGroup,
166 device_server_end: fidl::endpoints::ServerEnd<MediaButtonsDeviceMarker>,
167 got_input_reports_reader: AsyncEvent,
168) -> input_device::DeviceId {
169 let device = registry
170 .add_media_buttons_device()
171 .await
172 .expect("failed to create fake media buttons device");
173 let device_id = device.device_id;
174
175 task_group.spawn(async move {
176 handle_media_buttons_device_request_stream(device, device_server_end.into_stream()).await;
177 });
178
179 info!("wait for input-pipeline setup input-reader");
180 let _ = got_input_reports_reader.wait().await;
181 info!("input-pipeline setup input-reader.");
182
183 device_id
184}
185
186async fn register_keyboard(
187 mut registry: input_device_registry::InputDeviceRegistry,
188 task_group: &mut fasync::TaskGroup,
189 device_server_end: fidl::endpoints::ServerEnd<KeyboardMarker>,
190 got_input_reports_reader: AsyncEvent,
191) -> input_device::DeviceId {
192 let device = registry.add_keyboard_device().await.expect("failed to create fake keyboard");
193 let device_id = device.device_id;
194
195 task_group.spawn(async move {
196 handle_keyboard_request_stream(device, device_server_end.into_stream()).await;
197 });
198
199 info!("wait for input-pipeline setup input-reader");
200 let _ = got_input_reports_reader.wait().await;
201 info!("input-pipeline setup input-reader.");
202
203 device_id
204}
205
206async fn register_mouse(
207 mut registry: input_device_registry::InputDeviceRegistry,
208 task_group: &mut fasync::TaskGroup,
209 device_server_end: fidl::endpoints::ServerEnd<MouseMarker>,
210 got_input_reports_reader: AsyncEvent,
211) -> input_device::DeviceId {
212 let device = registry.add_mouse_device().await.expect("failed to create fake mouse");
213 let device_id = device.device_id;
214
215 task_group.spawn(async move {
216 handle_mouse_request_stream(device, device_server_end.into_stream()).await;
217 });
218
219 info!("wait for input-pipeline setup input-reader");
220 let _ = got_input_reports_reader.wait().await;
221 info!("input-pipeline setup input-reader.");
222
223 device_id
224}
225
226pub async fn handle_registry_request_stream(request_stream: RegistryRequestStream) {
228 request_stream
229 .try_for_each_concurrent(None, |request| async {
230 let input_device_registry = connect_to_protocol::<InputDeviceRegistryMarker>()
231 .expect("connect to input_device_registry");
232 let got_input_reports_reader = AsyncEvent::new();
233
234 let registry = input_device_registry::InputDeviceRegistry::new(
235 input_device_registry,
236 got_input_reports_reader.clone(),
237 );
238 let mut task_group = fasync::TaskGroup::new();
239
240 match request {
241 RegistryRequest::RegisterTouchScreen { payload, responder, .. } => {
242 info!("register touchscreen");
243 let device = payload
244 .device
245 .expect("no touchscreen device provided in registration request");
246 let (min_x, max_x, min_y, max_y) = match payload.coordinate_unit {
247 Some(CoordinateUnit::PhysicalPixels) => {
248 let display_info_proxy =
249 connect_to_protocol::<display_info::InfoMarker>()
250 .expect("failed to connect to display info service");
251 let display_dimensions = display_info_proxy
252 .get_metrics()
253 .await
254 .expect("failed to get display metrics")
255 .extent_in_px
256 .expect("display metrics missing extent in px");
257 (
258 0,
259 display_dimensions.width as i64,
260 0,
261 display_dimensions.height as i64,
262 )
263 }
264 Some(CoordinateUnit::RegisteredDimensions) => {
265 let dimensions =
266 payload.display_dimensions.expect("missing dimensions");
267 if dimensions.min_x >= dimensions.max_x
268 || dimensions.min_y >= dimensions.max_y
269 {
270 panic!("invalid dimensions");
271 }
272 (dimensions.min_x, dimensions.max_x, dimensions.min_y, dimensions.max_y)
273 }
274 _ => (-1000, 1000, -1000, 1000),
275 };
276
277 register_touch_screen(
278 registry,
279 &mut task_group,
280 device,
281 got_input_reports_reader,
282 min_x,
283 max_x,
284 min_y,
285 max_y,
286 )
287 .await;
288
289 responder.send().expect("Failed to respond to RegisterTouchScreen request");
290 }
291 RegistryRequest::RegisterTouchScreenAndGetDeviceInfo {
292 payload, responder, ..
293 } => {
294 info!("register touchscreen");
295 let device = payload
296 .device
297 .expect("no touchscreen device provided in registration request");
298 let (min_x, max_x, min_y, max_y) = match payload.coordinate_unit {
299 Some(CoordinateUnit::PhysicalPixels) => {
300 let display_info_proxy =
301 connect_to_protocol::<display_info::InfoMarker>()
302 .expect("failed to connect to display info service");
303 let display_dimensions = display_info_proxy
304 .get_metrics()
305 .await
306 .expect("failed to get display metrics")
307 .extent_in_px
308 .expect("display metrics missing extent in px");
309 (
310 0,
311 display_dimensions.width as i64,
312 0,
313 display_dimensions.height as i64,
314 )
315 }
316 Some(CoordinateUnit::RegisteredDimensions) => {
317 let dimensions =
318 payload.display_dimensions.expect("missing dimensions");
319 if dimensions.min_x >= dimensions.max_x
320 || dimensions.min_y >= dimensions.max_y
321 {
322 panic!("invalid dimensions");
323 }
324 (dimensions.min_x, dimensions.max_x, dimensions.min_y, dimensions.max_y)
325 }
326 _ => (-1000, 1000, -1000, 1000),
327 };
328
329 let device_id = register_touch_screen(
330 registry,
331 &mut task_group,
332 device,
333 got_input_reports_reader,
334 min_x,
335 max_x,
336 min_y,
337 max_y,
338 )
339 .await;
340
341 responder
342 .send(RegistryRegisterTouchScreenAndGetDeviceInfoResponse {
343 device_id: Some(device_id),
344 ..Default::default()
345 })
346 .expect("Failed to respond to RegisterTouchScreenAndGetDeviceInfo request");
347 }
348 RegistryRequest::RegisterMediaButtonsDevice { payload, responder, .. } => {
349 info!("register media buttons device");
350 let device = payload
351 .device
352 .expect("no media buttons device provided in registration request");
353
354 register_media_button(
355 registry,
356 &mut task_group,
357 device,
358 got_input_reports_reader,
359 )
360 .await;
361
362 responder
363 .send()
364 .expect("Failed to respond to RegisterMediaButtonsDevice request");
365 }
366 RegistryRequest::RegisterMediaButtonsDeviceAndGetDeviceInfo {
367 payload,
368 responder,
369 ..
370 } => {
371 info!("register media buttons device");
372 let device = payload
373 .device
374 .expect("no media buttons device provided in registration request");
375
376 let device_id = register_media_button(
377 registry,
378 &mut task_group,
379 device,
380 got_input_reports_reader,
381 )
382 .await;
383
384 responder.send(RegistryRegisterMediaButtonsDeviceAndGetDeviceInfoResponse {
385 device_id: Some(device_id),
386 ..Default::default()
387 }).expect(
388 "Failed to respond to RegisterMediaButtonsDeviceAndGetDeviceInfo request",
389 );
390 }
391 RegistryRequest::RegisterKeyboard { payload, responder, .. } => {
392 info!("register keyboard device");
393 let device = payload
394 .device
395 .expect("no keyboard device provided in registration request");
396
397 register_keyboard(registry, &mut task_group, device, got_input_reports_reader)
398 .await;
399
400 responder.send().expect("Failed to respond to RegisterKeyboard request");
401 }
402 RegistryRequest::RegisterKeyboardAndGetDeviceInfo {
403 payload, responder, ..
404 } => {
405 info!("register keyboard device");
406 let device = payload
407 .device
408 .expect("no keyboard device provided in registration request");
409
410 let device_id = register_keyboard(
411 registry,
412 &mut task_group,
413 device,
414 got_input_reports_reader,
415 )
416 .await;
417
418 responder
419 .send(RegistryRegisterKeyboardAndGetDeviceInfoResponse {
420 device_id: Some(device_id),
421 ..Default::default()
422 })
423 .expect("Failed to respond to RegisterKeyboardAndGetDeviceInfo request");
424 }
425 RegistryRequest::RegisterMouse { payload, responder } => {
426 info!("register mouse device");
427 let device = payload.device.expect("no mouse provided in registration request");
428
429 register_mouse(registry, &mut task_group, device, got_input_reports_reader)
430 .await;
431
432 responder.send().expect("Failed to respond to RegisterMouse request");
433 }
434 RegistryRequest::RegisterMouseAndGetDeviceInfo { payload, responder } => {
435 info!("register mouse device");
436 let device = payload.device.expect("no mouse provided in registration request");
437
438 let device_id =
439 register_mouse(registry, &mut task_group, device, got_input_reports_reader)
440 .await;
441
442 responder
443 .send(RegistryRegisterMouseAndGetDeviceInfoResponse {
444 device_id: Some(device_id),
445 ..Default::default()
446 })
447 .expect("Failed to respond to RegisterMouse request");
448 }
449 }
450
451 task_group.join().await;
452 Ok(())
453 })
454 .await
455 .expect("failed to serve test realm factory request stream");
456}
457
458fn input_report_for_touch_contacts(
459 contacts: Vec<(u32, math::Vec_)>,
460 trace_id: Option<u64>,
461) -> InputReport {
462 let contact_input_reports = contacts
463 .into_iter()
464 .map(|(contact_id, location)| ContactInputReport {
465 contact_id: Some(contact_id),
466 position_x: Some(location.x as i64),
467 position_y: Some(location.y as i64),
468 contact_width: Some(0),
469 contact_height: Some(0),
470 ..Default::default()
471 })
472 .collect();
473
474 let touch_input_report = TouchInputReport {
475 contacts: Some(contact_input_reports),
476 pressed_buttons: Some(vec![]),
477 ..Default::default()
478 };
479
480 InputReport {
481 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
482 touch: Some(touch_input_report),
483 trace_id,
484 ..Default::default()
485 }
486}
487
488async fn handle_touchscreen_request_stream(
490 touchscreen_device: input_device::InputDevice,
491 mut request_stream: TouchScreenRequestStream,
492) {
493 while let Some(request) = request_stream.next().await {
494 match request {
495 Ok(TouchScreenRequest::SimulateTap { payload, responder }) => {
496 let tap_location = payload.tap_location.expect("missing tap location");
497 {
498 fuchsia_trace::duration!(c"input", c"simulate_tap_down");
499 let trace_id = fuchsia_trace::Id::random();
500 fuchsia_trace::flow_begin!(c"input", c"input_report", trace_id);
501 touchscreen_device
502 .send_input_report(input_report_for_touch_contacts(
503 vec![(1, tap_location)],
504 Some(trace_id.into()),
505 ))
506 .expect("Failed to send touch down input report");
507 }
508
509 fuchsia_trace::duration!(c"input", c"simulate_tap_up");
512 let trace_id = fuchsia_trace::Id::random();
513 fuchsia_trace::flow_begin!(c"input", c"input_report", trace_id);
514 touchscreen_device
515 .send_input_report(input_report_for_touch_contacts(
516 vec![],
517 Some(trace_id.into()),
518 ))
519 .expect("failed to send touch up input report");
520
521 responder.send().expect("Failed to send SimulateTap response");
522 }
523 Ok(TouchScreenRequest::SimulateSwipe { payload, responder }) => {
524 let start_location = payload.start_location.expect("missing start location");
526 let end_location = payload.end_location.expect("missing end location");
527 let move_event_count = payload.move_event_count.expect("missing move event count");
528 assert_ne!(move_event_count, 0);
529 let duration_nanos = payload.duration.unwrap_or(0);
530 let delay_nanos = duration_nanos / ((move_event_count as i64) + 1);
531 let delay = fasync::MonotonicDuration::from_nanos(delay_nanos);
532
533 let start_x_f = start_location.x as f64;
534 let start_y_f = start_location.y as f64;
535 let end_x_f = end_location.x as f64;
536 let end_y_f = end_location.y as f64;
537 let move_event_count_f = move_event_count as f64;
538 let step_size_x = (end_x_f - start_x_f) / move_event_count_f;
539 let step_size_y = (end_y_f - start_y_f) / move_event_count_f;
540
541 for i in 0..move_event_count + 1 {
544 let i_f = i as f64;
545 let event_x = start_x_f + (i_f * step_size_x);
546 let event_y = start_y_f + (i_f * step_size_y);
547
548 {
549 fuchsia_trace::duration!(c"input", c"simulate_swipe_move", "idx"=>i);
550 let trace_id = fuchsia_trace::Id::random();
551 fuchsia_trace::flow_begin!(c"input", c"input_report", trace_id);
552
553 touchscreen_device
554 .send_input_report(input_report_for_touch_contacts(
555 vec![(1, math::Vec_ { x: event_x as i32, y: event_y as i32 })],
556 Some(trace_id.into()),
557 ))
558 .expect("Failed to send tap input report");
559 }
560 fasync::Timer::new(delay).await;
561 }
562
563 fuchsia_trace::duration!(c"input", c"simulate_swipe_up");
566 let trace_id = fuchsia_trace::Id::random();
567 fuchsia_trace::flow_begin!(c"input", c"input_report", trace_id);
568 touchscreen_device
569 .send_input_report(input_report_for_touch_contacts(
570 vec![],
571 Some(trace_id.into()),
572 ))
573 .expect("failed to send empty input report");
574
575 responder.send().expect("Failed to send SimulateSwipe response");
576 }
577 Ok(TouchScreenRequest::SimulateMultiTap { payload, responder }) => {
578 let tap_locations = payload.tap_locations.expect("missing tap locations");
579
580 {
581 fuchsia_trace::duration!(c"input", c"simulate_multi_tap_down");
582 let trace_id = fuchsia_trace::Id::random();
583 fuchsia_trace::flow_begin!(c"input", c"input_report", trace_id);
584 touchscreen_device
585 .send_input_report(input_report_for_touch_contacts(
586 tap_locations
587 .into_iter()
588 .enumerate()
589 .map(|(i, it)| (i as u32, it))
590 .collect(),
591 Some(trace_id.into()),
592 ))
593 .expect("Failed to send tap input report");
594 }
595
596 fuchsia_trace::duration!(c"input", c"simulate_multi_tap_up");
599 let trace_id = fuchsia_trace::Id::random();
600 fuchsia_trace::flow_begin!(c"input", c"input_report", trace_id);
601 touchscreen_device
602 .send_input_report(input_report_for_touch_contacts(
603 vec![],
604 Some(trace_id.into()),
605 ))
606 .expect("failed to send empty input report");
607 responder.send().expect("Failed to send SimulateMultiTap response");
608 }
609 Ok(TouchScreenRequest::SimulateMultiFingerGesture { payload, responder }) => {
610 let start_locations = payload.start_locations.expect("missing start locations");
612 let end_locations = payload.end_locations.expect("missing end locations");
613 let move_event_count = payload.move_event_count.expect("missing move event count");
614 let finger_count = payload.finger_count.expect("missing finger count") as usize;
615
616 let move_event_count_f = move_event_count as f32;
617
618 let mut steps: Vec<math::VecF> = vec![];
619
620 for finger in 0..finger_count {
621 let start_x = start_locations[finger].x as f32;
622 let start_y = start_locations[finger].y as f32;
623 let end_x = end_locations[finger].x as f32;
624 let end_y = end_locations[finger].y as f32;
625 let step_x = (end_x - start_x) / move_event_count_f;
626 let step_y = (end_y - start_y) / move_event_count_f;
627 steps.push(math::VecF { x: step_x, y: step_y });
628 }
629
630 for i in 0..move_event_count {
633 let i_f = i as f32;
634
635 let mut contacts: Vec<(u32, math::Vec_)> = vec![];
636
637 for finger in 0..finger_count {
638 let start_x = start_locations[finger].x as f32;
639 let start_y = start_locations[finger].y as f32;
640 let event_x = (start_x + i_f * steps[finger].x) as i32;
641 let event_y = (start_y + i_f * steps[finger].y) as i32;
642 contacts.push((finger as u32, math::Vec_ { x: event_x, y: event_y }));
643 }
644
645 fuchsia_trace::duration!(c"input", c"simulate_multi_finger_gesture_move", "idx"=>i);
646 let trace_id = fuchsia_trace::Id::random();
647 fuchsia_trace::flow_begin!(c"input", c"input_report", trace_id);
648
649 touchscreen_device
650 .send_input_report(input_report_for_touch_contacts(
651 contacts,
652 Some(trace_id.into()),
653 ))
654 .expect("Failed to send tap input report");
655 }
656
657 fuchsia_trace::duration!(c"input", c"simulate_multi_finger_gesture_up");
660 let trace_id = fuchsia_trace::Id::random();
661 fuchsia_trace::flow_begin!(c"input", c"input_report", trace_id);
662 touchscreen_device
663 .send_input_report(input_report_for_touch_contacts(
664 vec![],
665 Some(trace_id.into()),
666 ))
667 .expect("failed to send empty input report");
668
669 responder.send().expect("Failed to send SimulateMultiFingerGesture response");
670 }
671 Ok(TouchScreenRequest::SimulateTouchEvent { report, responder }) => {
672 fuchsia_trace::duration!(c"input", c"simulate_touch_event");
673 let trace_id = fuchsia_trace::Id::random();
674 fuchsia_trace::flow_begin!(c"input", c"input_report", trace_id);
675 let input_report = InputReport {
676 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
677 touch: Some(report),
678 trace_id: Some(trace_id.into()),
679 ..Default::default()
680 };
681 touchscreen_device
682 .send_input_report(input_report)
683 .expect("failed to send empty input report");
684 responder.send().expect("Failed to send SimulateTouchEvent response");
685 }
686 Err(e) => {
687 error!("Error on touchscreen channel: {}", e);
688 return;
689 }
690 }
691 }
692}
693
694async fn handle_media_buttons_device_request_stream(
696 media_buttons_device: input_device::InputDevice,
697 mut request_stream: MediaButtonsDeviceRequestStream,
698) {
699 while let Some(request) = request_stream.next().await {
700 match request {
701 Ok(MediaButtonsDeviceRequest::SimulateButtonPress { payload, responder }) => {
702 if let Some(button) = payload.button {
703 let media_buttons_input_report = ConsumerControlInputReport {
704 pressed_buttons: Some(vec![button]),
705 ..Default::default()
706 };
707
708 let input_report = InputReport {
709 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
710 consumer_control: Some(media_buttons_input_report),
711 ..Default::default()
712 };
713
714 media_buttons_device
715 .send_input_report(input_report)
716 .expect("Failed to send button press input report");
717
718 let empty_report = InputReport {
722 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
723 consumer_control: Some(ConsumerControlInputReport {
724 pressed_buttons: Some(vec![]),
725 ..Default::default()
726 }),
727 ..Default::default()
728 };
729
730 media_buttons_device
731 .send_input_report(empty_report)
732 .expect("Failed to send button release input report");
733
734 responder.send().expect("Failed to send SimulateButtonPress response");
735 } else {
736 warn!("SimulateButtonPress request missing button");
737 }
738 }
739 Ok(MediaButtonsDeviceRequest::SendButtonsState { payload, responder }) => {
740 let buttons = match payload.buttons {
741 Some(buttons) => buttons,
742 None => vec![],
743 };
744 let input_report = InputReport {
745 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
746 consumer_control: Some(ConsumerControlInputReport {
747 pressed_buttons: Some(buttons),
748 ..Default::default()
749 }),
750 ..Default::default()
751 };
752
753 media_buttons_device
754 .send_input_report(input_report)
755 .expect("Failed to send button press input report");
756
757 responder.send().expect("Failed to send SimulateButtonsPress response");
758 }
759 Err(e) => {
760 error!("Error on media buttons device channel: {}", e);
761 return;
762 }
763 }
764 }
765}
766
767async fn handle_keyboard_request_stream(
769 keyboard_device: input_device::InputDevice,
770 mut request_stream: KeyboardRequestStream,
771) {
772 while let Some(request) = request_stream.next().await {
773 match request {
774 Ok(KeyboardRequest::SimulateUsAsciiTextEntry { payload, responder }) => {
775 if let Some(text) = payload.text {
776 let key_sequence = derive_key_sequence(&keymaps::US_QWERTY, &text)
777 .expect("Failed to derive key sequence");
778
779 let mut key_iter = key_sequence.into_iter().peekable();
780 while let Some(keyboard_report) = key_iter.next() {
781 let input_report = InputReport {
782 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
783 keyboard: Some(KeyboardInputReport {
784 pressed_keys3: Some(convert_keyboard_report_to_keys(
785 &keyboard_report,
786 )),
787 ..Default::default()
788 }),
789 ..Default::default()
790 };
791
792 keyboard_device
793 .send_input_report(input_report)
794 .expect("Failed to send key event report");
795
796 if key_iter.peek().is_some() {
797 fuchsia_async::Timer::new(Duration::from_millis(100)).await;
798 }
799 }
800
801 responder.send().expect("Failed to send SimulateTextEntry response");
802 } else {
803 warn!("SimulateTextEntry request missing text");
804 }
805 }
806 Ok(KeyboardRequest::SimulateKeyEvent { payload, responder }) => {
807 let keyboard_report = payload.report.expect("no report");
808 let input_report = InputReport {
809 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
810 keyboard: Some(keyboard_report),
811 ..Default::default()
812 };
813
814 keyboard_device
815 .send_input_report(input_report)
816 .expect("Failed to send key event report");
817
818 responder.send().expect("Failed to send SimulateKeyEvent response");
819 }
820 Ok(KeyboardRequest::SimulateKeyPress { payload, responder }) => {
821 let key_code = payload.key_code.expect("no key code");
822
823 let down_report = InputReport {
824 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
825 keyboard: Some(KeyboardInputReport {
826 pressed_keys3: Some(vec![key_code]),
827 ..Default::default()
828 }),
829 ..Default::default()
830 };
831
832 let up_report = InputReport {
833 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
834 keyboard: Some(KeyboardInputReport {
835 pressed_keys3: Some(vec![]),
836 ..Default::default()
837 }),
838 ..Default::default()
839 };
840
841 keyboard_device.send_input_report(down_report).expect("Failed to send key down");
842
843 keyboard_device.send_input_report(up_report).expect("Failed to send key up");
844
845 responder.send().expect("Failed to send SimulateKeyPress response");
846 }
847 Err(e) => {
848 error!("Error on keyboard device channel: {}", e);
849 return;
850 }
851 }
852 }
853}
854
855async fn handle_mouse_request_stream(
857 mouse_device: input_device::InputDevice,
858 mut request_stream: MouseRequestStream,
859) {
860 while let Some(request) = request_stream.next().await {
861 match request {
862 Ok(MouseRequest::SimulateMouseEvent { payload, responder }) => {
863 let mut mouse_input_report = MouseInputReport {
864 movement_x: payload.movement_x,
865 movement_y: payload.movement_y,
866 scroll_v: payload.scroll_v_detent,
867 scroll_h: payload.scroll_h_detent,
868 ..Default::default()
869 };
870 if let Some(pressed_buttons) = payload.pressed_buttons {
871 mouse_input_report.pressed_buttons = Some(
872 pressed_buttons
873 .into_iter()
874 .map(|b| {
875 b.into_primitive()
876 .try_into()
877 .expect("failed to convert MouseButton to u8")
878 })
879 .collect(),
880 );
881 }
882
883 let input_report = InputReport {
884 event_time: Some(fasync::MonotonicInstant::now().into_nanos()),
885 mouse: Some(mouse_input_report),
886 ..Default::default()
887 };
888
889 mouse_device
890 .send_input_report(input_report)
891 .expect("Failed to send key event report");
892
893 responder.send().expect("Failed to send SimulateMouseEvent response");
894 }
895 Err(e) => {
896 error!("Error on keyboard device channel: {}", e);
897 return;
898 }
899 }
900 }
901}
902
903#[cfg(test)]
904mod tests {
905 use super::{KeyboardReport, Usages, derive_key_sequence};
912 use pretty_assertions::assert_eq;
913
914 macro_rules! reports {
916 ( $( [ $( $usages:expr ),* ] ),* $( , )? ) => {
917 Some(vec![
918 $(
919 KeyboardReport {
920 pressed_keys: vec![$($usages as u32),*]
921 }
922 ),*
923 ])
924 }
925 }
926
927 #[test]
928 fn lowercase() {
929 assert_eq!(
930 derive_key_sequence(&keymaps::US_QWERTY, "lowercase"),
931 reports![
932 [Usages::HidUsageKeyL],
933 [Usages::HidUsageKeyO],
934 [Usages::HidUsageKeyW],
935 [Usages::HidUsageKeyE],
936 [Usages::HidUsageKeyR],
937 [Usages::HidUsageKeyC],
938 [Usages::HidUsageKeyA],
939 [Usages::HidUsageKeyS],
940 [Usages::HidUsageKeyE],
941 [],
942 ]
943 );
944 }
945
946 #[test]
947 fn numerics() {
948 assert_eq!(
949 derive_key_sequence(&keymaps::US_QWERTY, "0123456789"),
950 reports![
951 [Usages::HidUsageKey0],
952 [Usages::HidUsageKey1],
953 [Usages::HidUsageKey2],
954 [Usages::HidUsageKey3],
955 [Usages::HidUsageKey4],
956 [Usages::HidUsageKey5],
957 [Usages::HidUsageKey6],
958 [Usages::HidUsageKey7],
959 [Usages::HidUsageKey8],
960 [Usages::HidUsageKey9],
961 [],
962 ]
963 );
964 }
965
966 #[test]
967 fn internet_text_entry() {
968 assert_eq!(
969 derive_key_sequence(&keymaps::US_QWERTY, "http://127.0.0.1:8080"),
970 reports![
971 [Usages::HidUsageKeyH],
972 [Usages::HidUsageKeyT],
973 [],
974 [Usages::HidUsageKeyT],
975 [Usages::HidUsageKeyP],
976 [Usages::HidUsageKeyLeftShift],
980 [Usages::HidUsageKeySemicolon, Usages::HidUsageKeyLeftShift],
981 [],
982 [Usages::HidUsageKeySlash],
983 [],
984 [Usages::HidUsageKeySlash],
985 [Usages::HidUsageKey1],
986 [Usages::HidUsageKey2],
987 [Usages::HidUsageKey7],
988 [Usages::HidUsageKeyDot],
989 [Usages::HidUsageKey0],
990 [Usages::HidUsageKeyDot],
991 [Usages::HidUsageKey0],
992 [Usages::HidUsageKeyDot],
993 [Usages::HidUsageKey1],
994 [Usages::HidUsageKeyLeftShift],
995 [Usages::HidUsageKeySemicolon, Usages::HidUsageKeyLeftShift],
996 [],
997 [Usages::HidUsageKey8],
998 [Usages::HidUsageKey0],
999 [Usages::HidUsageKey8],
1000 [Usages::HidUsageKey0],
1001 [],
1002 ]
1003 );
1004 }
1005
1006 #[test]
1007 fn sentence() {
1008 assert_eq!(
1009 derive_key_sequence(&keymaps::US_QWERTY, "Hello, world!"),
1010 reports![
1011 [Usages::HidUsageKeyLeftShift],
1012 [Usages::HidUsageKeyH, Usages::HidUsageKeyLeftShift],
1013 [],
1014 [Usages::HidUsageKeyE],
1015 [Usages::HidUsageKeyL],
1016 [],
1017 [Usages::HidUsageKeyL],
1018 [Usages::HidUsageKeyO],
1019 [Usages::HidUsageKeyComma],
1020 [Usages::HidUsageKeySpace],
1021 [Usages::HidUsageKeyW],
1022 [Usages::HidUsageKeyO],
1023 [Usages::HidUsageKeyR],
1024 [Usages::HidUsageKeyL],
1025 [Usages::HidUsageKeyD],
1026 [Usages::HidUsageKeyLeftShift],
1027 [Usages::HidUsageKey1, Usages::HidUsageKeyLeftShift],
1028 [],
1029 ]
1030 );
1031 }
1032
1033 #[test]
1034 fn hold_shift() {
1035 assert_eq!(
1036 derive_key_sequence(&keymaps::US_QWERTY, "ALL'S WELL!"),
1037 reports![
1038 [Usages::HidUsageKeyLeftShift],
1039 [Usages::HidUsageKeyA, Usages::HidUsageKeyLeftShift],
1040 [Usages::HidUsageKeyL, Usages::HidUsageKeyLeftShift],
1041 [Usages::HidUsageKeyLeftShift],
1042 [Usages::HidUsageKeyL, Usages::HidUsageKeyLeftShift],
1043 [],
1044 [Usages::HidUsageKeyApostrophe],
1045 [Usages::HidUsageKeyLeftShift],
1046 [Usages::HidUsageKeyS, Usages::HidUsageKeyLeftShift],
1047 [Usages::HidUsageKeySpace, Usages::HidUsageKeyLeftShift],
1048 [Usages::HidUsageKeyW, Usages::HidUsageKeyLeftShift],
1049 [Usages::HidUsageKeyE, Usages::HidUsageKeyLeftShift],
1050 [Usages::HidUsageKeyL, Usages::HidUsageKeyLeftShift],
1051 [Usages::HidUsageKeyLeftShift],
1052 [Usages::HidUsageKeyL, Usages::HidUsageKeyLeftShift],
1053 [Usages::HidUsageKey1, Usages::HidUsageKeyLeftShift],
1054 [],
1055 ]
1056 );
1057 }
1058
1059 #[test]
1060 fn tab_and_newline() {
1061 assert_eq!(
1062 derive_key_sequence(&keymaps::US_QWERTY, "\tHello\n"),
1063 reports![
1064 [Usages::HidUsageKeyTab],
1065 [Usages::HidUsageKeyLeftShift],
1066 [Usages::HidUsageKeyH, Usages::HidUsageKeyLeftShift],
1067 [],
1068 [Usages::HidUsageKeyE],
1069 [Usages::HidUsageKeyL],
1070 [],
1071 [Usages::HidUsageKeyL],
1072 [Usages::HidUsageKeyO],
1073 [Usages::HidUsageKeyEnter],
1074 [],
1075 ]
1076 );
1077 }
1078}