input_pipeline/light_sensor/
light_sensor_binding.rs1use super::types::Rgbc;
6use crate::input_device::{
7 self, Handled, InputDeviceBinding, InputDeviceDescriptor, InputDeviceStatus, InputEvent,
8};
9use crate::metrics;
10use anyhow::{format_err, Error};
11use async_trait::async_trait;
12use fidl_fuchsia_input_report::{InputDeviceProxy, InputReport, SensorDescriptor, SensorType};
13use fuchsia_inspect::health::Reporter;
14
15use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
16use metrics_registry::*;
17
18#[derive(Clone, Debug)]
19pub struct LightSensorEvent {
20 pub(crate) device_proxy: InputDeviceProxy,
21 pub(crate) rgbc: Rgbc<u16>,
22}
23
24impl PartialEq for LightSensorEvent {
25 fn eq(&self, other: &Self) -> bool {
26 self.rgbc == other.rgbc
27 }
28}
29
30impl Eq for LightSensorEvent {}
31
32impl LightSensorEvent {
33 pub fn record_inspect(&self, node: &fuchsia_inspect::Node) {
34 node.record_uint("red", u64::from(self.rgbc.red));
35 node.record_uint("green", u64::from(self.rgbc.green));
36 node.record_uint("blue", u64::from(self.rgbc.blue));
37 node.record_uint("clear", u64::from(self.rgbc.clear));
38 }
39}
40
41pub(crate) struct LightSensorBinding {
45 event_sender: UnboundedSender<input_device::InputEvent>,
47
48 device_descriptor: LightSensorDeviceDescriptor,
50}
51
52#[derive(Copy, Clone, Debug, Eq, PartialEq)]
53pub struct LightSensorDeviceDescriptor {
54 pub(crate) vendor_id: u32,
56
57 pub(crate) product_id: u32,
59
60 pub(crate) device_id: u32,
62
63 pub(crate) sensor_layout: Rgbc<usize>,
65}
66
67#[async_trait]
68impl InputDeviceBinding for LightSensorBinding {
69 fn input_event_sender(&self) -> UnboundedSender<InputEvent> {
70 self.event_sender.clone()
71 }
72
73 fn get_device_descriptor(&self) -> InputDeviceDescriptor {
74 InputDeviceDescriptor::LightSensor(self.device_descriptor.clone())
75 }
76}
77
78impl LightSensorBinding {
79 pub(crate) async fn new(
94 device_proxy: InputDeviceProxy,
95 device_id: u32,
96 input_event_sender: UnboundedSender<input_device::InputEvent>,
97 device_node: fuchsia_inspect::Node,
98 metrics_logger: metrics::MetricsLogger,
99 ) -> Result<Self, Error> {
100 let (device_binding, mut inspect_status) = Self::bind_device(
101 &device_proxy,
102 device_id,
103 input_event_sender,
104 device_node,
105 metrics_logger.clone(),
106 )
107 .await?;
108 inspect_status.health_node.set_ok();
109 input_device::initialize_report_stream(
110 device_proxy.clone(),
111 device_binding.get_device_descriptor(),
112 device_binding.input_event_sender(),
113 inspect_status,
114 metrics_logger,
115 move |report,
116 previous_report,
117 device_descriptor,
118 input_event_sender,
119 inspect_status,
120 metrics_logger| {
121 Self::process_reports(
122 report,
123 previous_report,
124 device_descriptor,
125 input_event_sender,
126 device_proxy.clone(),
127 inspect_status,
128 metrics_logger,
129 )
130 },
131 );
132
133 Ok(device_binding)
134 }
135
136 async fn bind_device(
148 device: &InputDeviceProxy,
149 device_id: u32,
150 input_event_sender: UnboundedSender<input_device::InputEvent>,
151 device_node: fuchsia_inspect::Node,
152 metrics_logger: metrics::MetricsLogger,
153 ) -> Result<(Self, InputDeviceStatus), Error> {
154 let mut input_device_status = InputDeviceStatus::new(device_node);
155 let descriptor = match device.get_descriptor().await {
156 Ok(descriptor) => descriptor,
157 Err(_) => {
158 input_device_status.health_node.set_unhealthy("Could not get device descriptor.");
159 return Err(format_err!("Could not get descriptor for device_id: {}", device_id));
160 }
161 };
162 let device_info = descriptor.device_information.ok_or_else(|| {
163 input_device_status.health_node.set_unhealthy("Empty device_info in descriptor.");
164 metrics_logger.log_error(
167 InputPipelineErrorMetricDimensionEvent::LightEmptyDeviceInfo,
168 std::format!("DRIVER BUG: empty device_info for device_id: {}", device_id),
169 );
170 format_err!("empty device info for device_id: {}", device_id)
171 })?;
172 match descriptor.sensor {
173 Some(SensorDescriptor { input: Some(input_descriptors), .. }) => {
174 let sensor_layout = input_descriptors
175 .into_iter()
176 .filter_map(|input_descriptor| {
177 input_descriptor.values.and_then(|values| {
178 let mut red_value = None;
179 let mut green_value = None;
180 let mut blue_value = None;
181 let mut clear_value = None;
182 for (i, value) in values.iter().enumerate() {
183 let old = match value.type_ {
184 SensorType::LightRed => {
185 std::mem::replace(&mut red_value, Some(i))
186 }
187 SensorType::LightGreen => {
188 std::mem::replace(&mut green_value, Some(i))
189 }
190 SensorType::LightBlue => {
191 std::mem::replace(&mut blue_value, Some(i))
192 }
193 SensorType::LightIlluminance => {
194 std::mem::replace(&mut clear_value, Some(i))
195 }
196 type_ => {
197 log::warn!(
198 "unexpected sensor type {type_:?} found on light \
199 sensor device"
200 );
201 None
202 }
203 };
204 if old.is_some() {
205 log::warn!(
206 "existing index for light sensor {:?} replaced",
207 value.type_
208 );
209 }
210 }
211
212 red_value.and_then(|red| {
213 green_value.and_then(|green| {
214 blue_value.and_then(|blue| {
215 clear_value.map(|clear| Rgbc { red, green, blue, clear })
216 })
217 })
218 })
219 })
220 })
221 .next()
222 .ok_or_else(|| {
223 input_device_status.health_node.set_unhealthy("Missing light sensor data.");
224 format_err!("missing sensor data in device")
225 })?;
226 Ok((
227 LightSensorBinding {
228 event_sender: input_event_sender,
229 device_descriptor: LightSensorDeviceDescriptor {
230 vendor_id: device_info.vendor_id.unwrap_or_default(),
231 product_id: device_info.product_id.unwrap_or_default(),
232 device_id,
233 sensor_layout,
234 },
235 },
236 input_device_status,
237 ))
238 }
239 device_descriptor => {
240 input_device_status
241 .health_node
242 .set_unhealthy("Light Sensor Device Descriptor failed to parse.");
243 Err(format_err!(
244 "Light Sensor Device Descriptor failed to parse: \n {:?}",
245 device_descriptor
246 ))
247 }
248 }
249 }
250
251 fn process_reports(
268 report: InputReport,
269 previous_report: Option<InputReport>,
270 device_descriptor: &input_device::InputDeviceDescriptor,
271 input_event_sender: &mut UnboundedSender<input_device::InputEvent>,
272 device_proxy: InputDeviceProxy,
273 inspect_status: &InputDeviceStatus,
274 metrics_logger: &metrics::MetricsLogger,
275 ) -> (Option<InputReport>, Option<UnboundedReceiver<InputEvent>>) {
276 inspect_status.count_received_report(&report);
277 let light_sensor_descriptor =
278 if let input_device::InputDeviceDescriptor::LightSensor(ref light_sensor_descriptor) =
279 device_descriptor
280 {
281 light_sensor_descriptor
282 } else {
283 unreachable!()
284 };
285
286 let sensor = match &report.sensor {
288 None => {
289 inspect_status.count_filtered_report();
290 return (previous_report, None);
291 }
292 Some(sensor) => sensor,
293 };
294
295 let values = match &sensor.values {
296 None => {
297 inspect_status.count_filtered_report();
298 return (None, None);
299 }
300 Some(values) => values,
301 };
302
303 let event = input_device::InputEvent {
304 device_event: input_device::InputDeviceEvent::LightSensor(LightSensorEvent {
305 device_proxy,
306 rgbc: Rgbc {
307 red: values[light_sensor_descriptor.sensor_layout.red] as u16,
308 green: values[light_sensor_descriptor.sensor_layout.green] as u16,
309 blue: values[light_sensor_descriptor.sensor_layout.blue] as u16,
310 clear: values[light_sensor_descriptor.sensor_layout.clear] as u16,
311 },
312 }),
313 device_descriptor: device_descriptor.clone(),
314 event_time: zx::MonotonicInstant::get(),
315 handled: Handled::No,
316 trace_id: None,
317 };
318
319 if let Err(e) = input_event_sender.unbounded_send(event.clone()) {
320 metrics_logger.log_error(
321 InputPipelineErrorMetricDimensionEvent::LightFailedToSendEvent,
322 std::format!("Failed to send LightSensorEvent with error: {e:?}"),
323 );
324 } else {
325 inspect_status.count_generated_event(event);
326 }
327
328 (Some(report), None)
329 }
330}