starnix_modules_input_report_event_conversion/
consumer_control.rs1use fidl_fuchsia_input_report as fir;
6use sorted_vec_map::SortedVecSet;
7use starnix_types::time::timeval_from_time;
8use starnix_uapi::uapi;
9
10pub fn consumer_control_button_to_linux_key(button: fir::ConsumerControlButton) -> Option<u32> {
12 match button {
13 fir::ConsumerControlButton::VolumeUp => Some(uapi::KEY_VOLUMEUP),
14 fir::ConsumerControlButton::VolumeDown => Some(uapi::KEY_VOLUMEDOWN),
15 fir::ConsumerControlButton::Power => Some(uapi::KEY_POWER),
16 fir::ConsumerControlButton::Pause => Some(uapi::KEY_PAUSE),
17 fir::ConsumerControlButton::MicMute => Some(uapi::KEY_MICMUTE),
18 fir::ConsumerControlButton::Reboot => Some(uapi::KEY_RESTART),
19 fir::ConsumerControlButton::CameraDisable => Some(uapi::KEY_CAMERA),
20 fir::ConsumerControlButton::Function => Some(uapi::KEY_VOLUMEDOWN),
21 _ => None,
22 }
23}
24
25#[derive(Debug, Default, PartialEq)]
27pub struct ConsumerControlReportConverter {
28 pressed_buttons: SortedVecSet<u16>,
29}
30
31impl ConsumerControlReportConverter {
32 pub fn new() -> Self {
33 Self::default()
34 }
35
36 pub fn handle(
37 &mut self,
38 report: &fir::ConsumerControlInputReport,
39 event_time: zx::MonotonicInstant,
40 ) -> Vec<uapi::input_event> {
41 let mut events = Vec::new();
42 let time = timeval_from_time(event_time);
43
44 let pressed_buttons = report.pressed_buttons.as_deref().unwrap_or(&[]);
45 let mut current_buttons = SortedVecSet::new();
46 for &btn in pressed_buttons.iter() {
47 if let Some(lkey) = consumer_control_button_to_linux_key(btn) {
48 current_buttons.insert(lkey as u16);
49 }
50 }
51
52 crate::emit_key_transitions(&mut self.pressed_buttons, current_buttons, time, &mut events);
53
54 if !events.is_empty() {
55 events.push(uapi::input_event {
56 time,
57 type_: uapi::EV_SYN as u16,
58 code: uapi::SYN_REPORT as u16,
59 value: 0,
60 });
61 }
62
63 events
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[::fuchsia::test]
72 fn test_consumer_control_report_buttons() {
73 let mut converter = ConsumerControlReportConverter::new();
74 let time = zx::MonotonicInstant::from_nanos(600_000_000);
75
76 let report1 = fir::ConsumerControlInputReport {
78 pressed_buttons: Some(vec![
79 fir::ConsumerControlButton::VolumeUp,
80 fir::ConsumerControlButton::Power,
81 ]),
82 ..Default::default()
83 };
84 let events1 = converter.handle(&report1, time);
85 assert!(events1.iter().any(|e| e.code == uapi::KEY_VOLUMEUP as u16 && e.value == 1));
86 assert!(events1.iter().any(|e| e.code == uapi::KEY_POWER as u16 && e.value == 1));
87 assert!(events1.iter().any(|e| e.code == uapi::SYN_REPORT as u16));
88
89 let report2 = fir::ConsumerControlInputReport {
91 pressed_buttons: Some(vec![
92 fir::ConsumerControlButton::Power,
93 fir::ConsumerControlButton::VolumeDown,
94 ]),
95 ..Default::default()
96 };
97 let events2 = converter.handle(&report2, time);
98 assert!(events2.iter().any(|e| e.code == uapi::KEY_VOLUMEUP as u16 && e.value == 0));
99 assert!(events2.iter().any(|e| e.code == uapi::KEY_VOLUMEDOWN as u16 && e.value == 1));
100 assert!(!events2.iter().any(|e| e.code == uapi::KEY_POWER as u16));
102
103 let report3 =
105 fir::ConsumerControlInputReport { pressed_buttons: Some(vec![]), ..Default::default() };
106 let events3 = converter.handle(&report3, time);
107 assert!(events3.iter().any(|e| e.code == uapi::KEY_POWER as u16 && e.value == 0));
108 assert!(events3.iter().any(|e| e.code == uapi::KEY_VOLUMEDOWN as u16 && e.value == 0));
109 }
110
111 #[::fuchsia::test]
112 fn test_empty_consumer_control_reports_return_empty_events() {
113 let time = zx::MonotonicInstant::from_nanos(400_000_000);
114 assert!(
115 ConsumerControlReportConverter::new()
116 .handle(&fir::ConsumerControlInputReport::default(), time)
117 .is_empty()
118 );
119 }
120
121 #[::fuchsia::test]
122 fn test_consumer_control_function_button_maps_to_volumedown() {
123 let mut converter = ConsumerControlReportConverter::new();
124 let time = zx::MonotonicInstant::from_nanos(500_000_000);
125
126 let report = fir::ConsumerControlInputReport {
127 pressed_buttons: Some(vec![fir::ConsumerControlButton::Function]),
128 ..Default::default()
129 };
130 let events = converter.handle(&report, time);
131 assert!(events.iter().any(|e| e.code == uapi::KEY_VOLUMEDOWN as u16 && e.value == 1));
132 assert!(events.iter().any(|e| e.code == uapi::SYN_REPORT as u16));
133 }
134
135 #[::fuchsia::test]
136 fn test_consumer_control_report_none_pressed_buttons_releases_held_buttons() {
137 let mut converter = ConsumerControlReportConverter::new();
138 let time = zx::MonotonicInstant::from_nanos(300_000_000);
139
140 let report1 = fir::ConsumerControlInputReport {
142 pressed_buttons: Some(vec![fir::ConsumerControlButton::VolumeUp]),
143 ..Default::default()
144 };
145 let events1 = converter.handle(&report1, time);
146 assert_eq!(
147 events1.iter().map(|e| (e.type_, e.code, e.value)).collect::<Vec<_>>(),
148 vec![
149 (uapi::EV_KEY as u16, uapi::KEY_VOLUMEUP as u16, 1),
150 (uapi::EV_SYN as u16, uapi::SYN_REPORT as u16, 0),
151 ]
152 );
153
154 let report2 =
156 fir::ConsumerControlInputReport { pressed_buttons: None, ..Default::default() };
157 let events2 = converter.handle(&report2, time);
158 assert_eq!(
159 events2.iter().map(|e| (e.type_, e.code, e.value)).collect::<Vec<_>>(),
160 vec![
161 (uapi::EV_KEY as u16, uapi::KEY_VOLUMEUP as u16, 0),
162 (uapi::EV_SYN as u16, uapi::SYN_REPORT as u16, 0),
163 ]
164 );
165
166 let report3 =
168 fir::ConsumerControlInputReport { pressed_buttons: None, ..Default::default() };
169 let events3 = converter.handle(&report3, time);
170 assert!(events3.is_empty());
171 }
172}