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::{Error, format_err};
11use async_trait::async_trait;
12use derivative::Derivative;
13use fidl_next_fuchsia_input_report::SensorType;
14use fuchsia_inspect::health::Reporter;
15use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
16use metrics_registry::*;
17
18#[derive(Derivative, Clone)]
19#[derivative(Debug)]
20pub struct LightSensorEvent {
21 #[derivative(Debug = "ignore")]
22 pub(crate) device_proxy:
23 fidl_next::Client<fidl_next_fuchsia_input_report::InputDevice, crate::Transport>,
24 pub(crate) rgbc: Rgbc<u16>,
25}
26
27impl PartialEq for LightSensorEvent {
28 fn eq(&self, other: &Self) -> bool {
29 self.rgbc == other.rgbc
30 }
31}
32
33impl Eq for LightSensorEvent {}
34
35impl LightSensorEvent {
36 pub fn record_inspect(&self, node: &fuchsia_inspect::Node) {
37 node.record_uint("red", u64::from(self.rgbc.red));
38 node.record_uint("green", u64::from(self.rgbc.green));
39 node.record_uint("blue", u64::from(self.rgbc.blue));
40 node.record_uint("clear", u64::from(self.rgbc.clear));
41 }
42}
43
44pub(crate) struct LightSensorBinding {
48 event_sender: UnboundedSender<Vec<InputEvent>>,
50
51 device_descriptor: LightSensorDeviceDescriptor,
53}
54
55#[derive(Copy, Clone, Debug, Eq, PartialEq)]
56pub struct LightSensorDeviceDescriptor {
57 pub(crate) vendor_id: u32,
59
60 pub(crate) product_id: u32,
62
63 pub(crate) device_id: u32,
65
66 pub(crate) sensor_layout: Rgbc<usize>,
68}
69
70#[async_trait]
71impl InputDeviceBinding for LightSensorBinding {
72 fn input_event_sender(&self) -> UnboundedSender<Vec<InputEvent>> {
73 self.event_sender.clone()
74 }
75
76 fn get_device_descriptor(&self) -> InputDeviceDescriptor {
77 InputDeviceDescriptor::LightSensor(self.device_descriptor.clone())
78 }
79}
80
81impl LightSensorBinding {
82 pub(crate) async fn new(
97 device_proxy: fidl_next::Client<
98 fidl_next_fuchsia_input_report::InputDevice,
99 crate::Transport,
100 >,
101 device_id: u32,
102 input_event_sender: UnboundedSender<Vec<InputEvent>>,
103 device_node: fuchsia_inspect::Node,
104 feature_flags: input_device::InputPipelineFeatureFlags,
105 metrics_logger: metrics::MetricsLogger,
106 ) -> Result<(Self, crate::dispatcher::TaskHandle<()>), Error> {
107 let (device_descriptor, mut inspect_status) =
108 Self::bind_device(&device_proxy, device_id, device_node, metrics_logger.clone())
109 .await?;
110 inspect_status.health_node.set_ok();
111 let task = input_device::initialize_report_stream(
112 device_proxy.clone(),
113 InputDeviceDescriptor::LightSensor(device_descriptor.clone()),
114 input_event_sender.clone(),
115 inspect_status,
116 metrics_logger,
117 feature_flags,
118 move |reports,
119 previous_state,
120 device_descriptor,
121 input_event_sender,
122 inspect_status,
123 metrics_logger,
124 _feature_flags| {
125 Self::process_reports(
126 reports,
127 previous_state,
128 device_descriptor,
129 input_event_sender,
130 device_proxy.clone(),
131 inspect_status,
132 metrics_logger,
133 )
134 },
135 );
136
137 Ok((LightSensorBinding { event_sender: input_event_sender, device_descriptor }, task))
138 }
139
140 async fn bind_device(
151 device: &fidl_next::Client<fidl_next_fuchsia_input_report::InputDevice, crate::Transport>,
152 device_id: u32,
153 device_node: fuchsia_inspect::Node,
154 metrics_logger: metrics::MetricsLogger,
155 ) -> Result<(LightSensorDeviceDescriptor, InputDeviceStatus), Error> {
156 let mut input_device_status = InputDeviceStatus::new(device_node);
157 let descriptor = match device.get_descriptor().await {
158 Ok(descriptor) => descriptor.descriptor,
159 Err(_) => {
160 input_device_status.health_node.set_unhealthy("Could not get device descriptor.");
161 return Err(format_err!("Could not get descriptor for device_id: {}", device_id));
162 }
163 };
164 let device_info = descriptor.device_information.ok_or_else(|| {
165 input_device_status.health_node.set_unhealthy("Empty device_info in descriptor.");
166 metrics_logger.log_error(
169 InputPipelineErrorMetricDimensionEvent::LightEmptyDeviceInfo,
170 std::format!("DRIVER BUG: empty device_info for device_id: {}", device_id),
171 );
172 format_err!("empty device info for device_id: {}", device_id)
173 })?;
174 match descriptor.sensor {
175 Some(fidl_next_fuchsia_input_report::SensorDescriptor {
176 input: Some(input_descriptors),
177 ..
178 }) => {
179 let sensor_layout = input_descriptors
180 .into_iter()
181 .filter_map(|input_descriptor| {
182 input_descriptor.values.and_then(|values| {
183 let mut red_value = None;
184 let mut green_value = None;
185 let mut blue_value = None;
186 let mut clear_value = None;
187 for (i, value) in values.iter().enumerate() {
188 let old = match value.type_ {
189 SensorType::LightRed => {
190 std::mem::replace(&mut red_value, Some(i))
191 }
192 SensorType::LightGreen => {
193 std::mem::replace(&mut green_value, Some(i))
194 }
195 SensorType::LightBlue => {
196 std::mem::replace(&mut blue_value, Some(i))
197 }
198 SensorType::LightIlluminance => {
199 std::mem::replace(&mut clear_value, Some(i))
200 }
201 type_ => {
202 log::warn!(
203 "unexpected sensor type {type_:?} found on light \
204 sensor device"
205 );
206 None
207 }
208 };
209 if old.is_some() {
210 log::warn!(
211 "existing index for light sensor {:?} replaced",
212 value.type_
213 );
214 }
215 }
216
217 red_value.and_then(|red| {
218 green_value.and_then(|green| {
219 blue_value.and_then(|blue| {
220 clear_value.map(|clear| Rgbc { red, green, blue, clear })
221 })
222 })
223 })
224 })
225 })
226 .next()
227 .ok_or_else(|| {
228 input_device_status.health_node.set_unhealthy("Missing light sensor data.");
229 format_err!("missing sensor data in device")
230 })?;
231 Ok((
232 LightSensorDeviceDescriptor {
233 vendor_id: device_info.vendor_id.unwrap_or_default(),
234 product_id: device_info.product_id.unwrap_or_default(),
235 device_id,
236 sensor_layout,
237 },
238 input_device_status,
239 ))
240 }
241 device_descriptor => {
242 input_device_status
243 .health_node
244 .set_unhealthy("Light Sensor Device Descriptor failed to parse.");
245 Err(format_err!(
246 "Light Sensor Device Descriptor failed to parse: \n {:?}",
247 device_descriptor
248 ))
249 }
250 }
251 }
252
253 fn process_reports(
272 reports: &[fidl_next_fuchsia_input_report::wire::InputReport<'_>],
273 mut previous_state: Option<input_device::PreviousDeviceState>,
274 device_descriptor: &input_device::InputDeviceDescriptor,
275 input_event_sender: &mut UnboundedSender<Vec<InputEvent>>,
276 device_proxy: fidl_next::Client<
277 fidl_next_fuchsia_input_report::InputDevice,
278 crate::Transport,
279 >,
280 inspect_status: &InputDeviceStatus,
281 metrics_logger: &metrics::MetricsLogger,
282 ) -> (Option<input_device::PreviousDeviceState>, Option<UnboundedReceiver<InputEvent>>) {
283 fuchsia_trace::duration!("input", "light-sensor-binding-process-reports", "num_reports" => reports.len());
284 for report in reports {
285 previous_state = Self::process_report(
286 report,
287 previous_state,
288 device_descriptor,
289 input_event_sender,
290 device_proxy.clone(),
291 inspect_status,
292 metrics_logger,
293 );
294 }
295 (previous_state, None)
296 }
297
298 fn process_report(
299 report: &fidl_next_fuchsia_input_report::wire::InputReport<'_>,
300 previous_state: Option<input_device::PreviousDeviceState>,
301 device_descriptor: &input_device::InputDeviceDescriptor,
302 input_event_sender: &mut UnboundedSender<Vec<InputEvent>>,
303 device_proxy: fidl_next::Client<
304 fidl_next_fuchsia_input_report::InputDevice,
305 crate::Transport,
306 >,
307 inspect_status: &InputDeviceStatus,
308 metrics_logger: &metrics::MetricsLogger,
309 ) -> Option<input_device::PreviousDeviceState> {
310 if let Some(trace_id) = report.trace_id() {
311 fuchsia_trace::flow_end!("input", "input_report", trace_id.0.into());
312 }
313
314 inspect_status.count_received_report_wire(report);
315 let light_sensor_descriptor =
316 if let input_device::InputDeviceDescriptor::LightSensor(light_sensor_descriptor) =
317 device_descriptor
318 {
319 light_sensor_descriptor
320 } else {
321 unreachable!()
322 };
323
324 let sensor = match report.sensor() {
326 None => {
327 inspect_status.count_filtered_report();
328 return previous_state;
329 }
330 Some(sensor) => sensor,
331 };
332
333 let values = match sensor.values() {
334 None => {
335 inspect_status.count_filtered_report();
336 return None;
337 }
338 Some(values) => values,
339 };
340
341 let event = input_device::InputEvent {
342 device_event: input_device::InputDeviceEvent::LightSensor(LightSensorEvent {
343 device_proxy,
344 rgbc: Rgbc {
345 red: values[light_sensor_descriptor.sensor_layout.red].0 as u16,
346 green: values[light_sensor_descriptor.sensor_layout.green].0 as u16,
347 blue: values[light_sensor_descriptor.sensor_layout.blue].0 as u16,
348 clear: values[light_sensor_descriptor.sensor_layout.clear].0 as u16,
349 },
350 }),
351 device_descriptor: device_descriptor.clone(),
352 event_time: zx::MonotonicInstant::get(),
353 handled: Handled::No,
354 trace_id: None,
355 };
356
357 let events = vec![event];
358 inspect_status.count_generated_events(&events);
359
360 if let Err(e) = input_event_sender.unbounded_send(events) {
361 metrics_logger.log_error(
362 InputPipelineErrorMetricDimensionEvent::LightFailedToSendEvent,
363 std::format!("Failed to send LightSensorEvent with error: {e:?}"),
364 );
365 }
366
367 Some(input_device::PreviousDeviceState::LightSensor)
368 }
369}