kernel/hil/
sensors.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Interfaces for environment sensors
6
7use crate::errorcode::ErrorCode;
8
9/// A basic interface for a temperature sensor
10pub trait TemperatureDriver<'a> {
11    fn set_client(&self, client: &'a dyn TemperatureClient);
12    fn read_temperature(&self) -> Result<(), ErrorCode>;
13}
14
15/// Client for receiving temperature readings.
16pub trait TemperatureClient {
17    /// Called when a temperature reading has completed.
18    ///
19    /// - `value`: the most recently read temperature in hundredths of degrees
20    /// centigrade (centiCelsius), or Err on failure.
21    fn callback(&self, value: Result<i32, ErrorCode>);
22}
23
24/// A basic interface for a humidity sensor
25pub trait HumidityDriver<'a> {
26    fn set_client(&self, client: &'a dyn HumidityClient);
27    fn read_humidity(&self) -> Result<(), ErrorCode>;
28}
29
30/// Client for receiving humidity readings.
31pub trait HumidityClient {
32    /// Called when a humidity reading has completed.
33    ///
34    /// - `value`: the most recently read humidity in hundredths of percent.
35    fn callback(&self, value: usize);
36}
37
38/// A basic interface for a moisture sensor
39pub trait MoistureDriver<'a> {
40    fn set_client(&self, client: &'a dyn MoistureClient);
41
42    /// Read the moisture value from a sensor. The value is returned
43    /// via the `MoistureClient` callback.
44    ///
45    /// This function might return the following errors:
46    /// - `BUSY`: Indicates that the hardware is busy with an existing operation
47    ///   or initialisation/calibration.
48    /// - `NOSUPPORT`: Indicates that this data type isn't supported.
49    fn read_moisture(&self) -> Result<(), ErrorCode>;
50}
51
52/// Client for receiving moisture readings.
53pub trait MoistureClient {
54    /// Called when a moisture reading has completed.
55    ///
56    /// - `value`: the most recently read moisture in hundredths of
57    /// percent, or Err on failure.
58    ///
59    /// This function might return the following errors:
60    /// - `BUSY`: Indicates that the hardware is busy with an existing operation
61    ///   or initialisation/calibration.
62    /// - `NOSUPPORT`: Indicates that this data type isn't supported.
63    fn callback(&self, value: Result<usize, ErrorCode>);
64}
65
66/// A basic interface for a Air Quality sensor
67pub trait AirQualityDriver<'a> {
68    /// Set the client to be notified when the capsule has data ready.
69    fn set_client(&self, client: &'a dyn AirQualityClient);
70
71    /// Specify the temperature and humidity used in calculating the air
72    /// quality.
73    ///
74    /// The temperature is specified in degrees Celsius and the humidity
75    /// is specified as a percentage.
76    ///
77    /// This is an optional call and doesn't have to be used, but on most
78    /// hardware can be used to improve the measurement accuracy.
79    ///
80    /// This function might return the following errors:
81    /// - `BUSY`: Indicates that the hardware is busy with an existing operation
82    ///   or initialisation/calibration.
83    /// - `NOSUPPORT`: Indicates that this data type isn't supported.
84    fn specify_environment(
85        &self,
86        temp: Option<i32>,
87        humidity: Option<u32>,
88    ) -> Result<(), ErrorCode>;
89
90    /// Read the CO2 or equivalent CO2 (eCO2) from the sensor.
91    /// This will trigger the `AirQualityClient` `co2_data_available()`
92    /// callback when the data is ready.
93    ///
94    /// This function might return the following errors:
95    /// - `BUSY`: Indicates that the hardware is busy with an existing operation
96    ///   or initialisation/calibration.
97    /// - `NOSUPPORT`: Indicates that this data type isn't supported.
98    fn read_co2(&self) -> Result<(), ErrorCode>;
99
100    /// Read the Total Organic Compound (TVOC) from the sensor.
101    /// This will trigger the `AirQualityClient` `tvoc_data_available()`
102    /// callback when the data is ready.
103    ///
104    /// This function might return the following errors:
105    /// - `BUSY`: Indicates that the hardware is busy with an existing operation
106    ///   or initialisation/calibration.
107    /// - `NOSUPPORT`: Indicates that this data type isn't supported.
108    fn read_tvoc(&self) -> Result<(), ErrorCode>;
109}
110
111/// Client for receiving Air Quality readings
112pub trait AirQualityClient {
113    /// Called when the environment specify command has completed.
114    fn environment_specified(&self, result: Result<(), ErrorCode>);
115
116    /// Called when a CO2 or equivalent CO2 (eCO2) reading has completed.
117    ///
118    /// - `value`: will contain the latest CO2 reading in ppm. An example value
119    ///   might be `400`.
120    fn co2_data_available(&self, value: Result<u32, ErrorCode>);
121
122    /// Called when a Total Organic Compound (TVOC) reading has completed.
123    ///
124    /// - `value`: will contain the latest TVOC reading in ppb. An example value
125    ///   might be `0`.
126    fn tvoc_data_available(&self, value: Result<u32, ErrorCode>);
127}
128
129/// A basic interface for a proximity sensor
130pub trait ProximityDriver<'a> {
131    fn set_client(&self, client: &'a dyn ProximityClient);
132    /// Callback issued after sensor reads proximity value
133    fn read_proximity(&self) -> Result<(), ErrorCode>;
134    /// Callback issued after sensor reads proximity value greater than 'high_threshold' or less than 'low_threshold'
135    ///
136    /// To elaborate, the callback is not issued by the driver until (prox_reading >= high_threshold || prox_reading <= low_threshold).
137    /// When (prox_reading >= high_threshold || prox_reading <= low_threshold) is read by the sensor, an I2C interrupt is generated and sent to the kernel
138    /// which prompts the driver to collect the proximity reading from the sensor and perform the callback.
139    /// Any apps issuing this command will have to wait for the proximity reading to fall within the aforementioned ranges in order to received a callback.
140    /// Threshold: A value of range [0 , 255] which represents at what proximity reading ranges an interrupt will occur.
141    fn read_proximity_on_interrupt(
142        &self,
143        low_threshold: u8,
144        high_threshold: u8,
145    ) -> Result<(), ErrorCode>;
146}
147
148pub trait ProximityClient {
149    /// Called when a proximity reading has completed.
150    ///
151    /// - `value`: the most recently read proximity value which ranges [0 , 255]...
152    /// where 255 -> object is closest readable distance, 0 -> object is farthest readable distance.
153    fn callback(&self, value: u8);
154}
155
156/// A basic interface for an ambient light sensor.
157pub trait AmbientLight<'a> {
158    /// Set the client to be notified when the capsule has data ready or has
159    /// finished some command.  This is likely called in a board's `main.rs`.
160    fn set_client(&self, client: &'a dyn AmbientLightClient);
161
162    /// Get a single instantaneous reading of the ambient light intensity.
163    fn read_light_intensity(&self) -> Result<(), ErrorCode> {
164        Err(ErrorCode::NODEVICE)
165    }
166}
167
168/// Client for receiving light intensity readings.
169pub trait AmbientLightClient {
170    /// Called when an ambient light reading has completed.
171    ///
172    /// - `lux`: the most recently read ambient light reading in lux (lx).
173    fn callback(&self, lux: usize);
174}
175
176/// A basic interface for a 9-DOF compatible chip.
177///
178/// This trait provides a standard interface for chips that implement
179/// some or all of a nine degrees of freedom (accelerometer, magnetometer,
180/// gyroscope) sensor. Any interface functions that a chip cannot implement
181/// can be ignored by the chip capsule and an error will automatically be
182/// returned.
183pub trait NineDof<'a> {
184    /// Set the client to be notified when the capsule has data ready or
185    /// has finished some command. This is likely called in a board's main.rs
186    /// and is set to the virtual_ninedof.rs driver.
187    fn set_client(&self, client: &'a dyn NineDofClient);
188
189    /// Get a single instantaneous reading of the acceleration in the
190    /// X,Y,Z directions.
191    fn read_accelerometer(&self) -> Result<(), ErrorCode> {
192        Err(ErrorCode::NODEVICE)
193    }
194
195    /// Get a single instantaneous reading from the magnetometer in all
196    /// three directions.
197    fn read_magnetometer(&self) -> Result<(), ErrorCode> {
198        Err(ErrorCode::NODEVICE)
199    }
200
201    /// Get a single instantaneous reading from the gyroscope of the rotation
202    /// around all three axes.
203    fn read_gyroscope(&self) -> Result<(), ErrorCode> {
204        Err(ErrorCode::NODEVICE)
205    }
206}
207
208/// Client for receiving done events from the chip.
209pub trait NineDofClient {
210    /// Signals a command has finished. The arguments will most likely be passed
211    /// over the syscall interface to an application.
212    fn callback(&self, arg1: usize, arg2: usize, arg3: usize);
213}
214
215/// Basic Interface for Sound Pressure
216pub trait SoundPressure<'a> {
217    /// Read the sound pressure level
218    fn read_sound_pressure(&self) -> Result<(), ErrorCode>;
219
220    /// Enable
221    ///
222    /// As this is usually a microphone, some boards require an explicit enable
223    /// so that they can turn on an LED. This function enables that microphone and LED.
224    /// Not calling this function may result in inaccurate readings.
225    fn enable(&self) -> Result<(), ErrorCode>;
226
227    /// Disable
228    ///
229    /// As this is usually a microphone, some boards require an explicit enable
230    /// so that they can turn on an LED. This function turns off that microphone. Readings
231    /// performed after this function call might return inaccurate.
232    fn disable(&self) -> Result<(), ErrorCode>;
233
234    /// Set the client
235    fn set_client(&self, client: &'a dyn SoundPressureClient);
236}
237
238pub trait SoundPressureClient {
239    /// Signals the sound pressure in dB
240    fn callback(&self, ret: Result<(), ErrorCode>, sound_pressure: u8);
241}
242
243/// A Basic interface for a barometer sensor.
244pub trait PressureDriver<'a> {
245    /// Used to initialize a atmospheric pressure reading
246    ///
247    /// This function might return the following errors:
248    /// - `BUSY`: Indicates that the hardware is busy with an existing operation
249    ///   or initialisation/calibration.
250    /// - `FAIL`: Failed to correctly communicate over communication protocol.
251    /// - `NOSUPPORT`: Indicates that this data type isn't supported.
252    fn read_atmospheric_pressure(&self) -> Result<(), ErrorCode>;
253
254    /// Set the client
255    fn set_client(&self, client: &'a dyn PressureClient);
256}
257
258pub trait PressureClient {
259    /// Called when a atmospheric pressure reading has completed.
260    ///
261    /// Returns the value in hPa.
262    fn callback(&self, pressure: Result<u32, ErrorCode>);
263}
264
265/// A basic interface for distance sensor.
266pub trait Distance<'a> {
267    /// Set the client
268    fn set_client(&self, client: &'a dyn DistanceClient);
269
270    /// Initiates a distance reading from the sensor.
271    ///
272    /// This function might return the following errors:
273    /// - `BUSY`: Indicates that the hardware is currently busy.
274    /// - `FAIL`: Indicates that there was a failure in communication.
275    fn read_distance(&self) -> Result<(), ErrorCode>;
276
277    /// Get the maximum distance the sensor can measure in mm
278    fn get_maximum_distance(&self) -> u32;
279
280    /// Get the minimum distance the sensor can measure in mm
281    fn get_minimum_distance(&self) -> u32;
282}
283
284/// Client for receiving distance readings.
285pub trait DistanceClient {
286    /// Called when a distance measurement has completed.
287    ///
288    /// - `distance`: the most recently measured distance in millimeters. If
289    ///   there was an error, this will be `Err(ErrorCode)`.
290    fn callback(&self, distance: Result<u32, ErrorCode>);
291}
292
293/// A basic interface for a rain fall sensor
294pub trait RainFallDriver<'a> {
295    fn set_client(&self, client: &'a dyn RainFallClient);
296
297    /// Read the rain fall value from a sensor. The value is returned
298    /// via the `RainFallClient` callback.
299    ///
300    /// - `hours`: the number of hours of rainfall to report. 1 to 24 hours are
301    ///   valid values (if supported by the hardware).
302    ///
303    /// This function might return the following errors:
304    /// - `BUSY`: Indicates that the hardware is busy with an existing operation
305    ///   or initialisation/calibration.
306    /// - `NOSUPPORT`: Indicates that the value of `hours` is not supported.
307    fn read_rainfall(&self, hours: usize) -> Result<(), ErrorCode>;
308}
309
310/// Client for receiving moisture readings.
311pub trait RainFallClient {
312    /// Called when a moisture reading has completed.
313    ///
314    /// - `value`: the number of um of rain in the time period specified, or Err
315    ///   on failure.
316    ///
317    /// This function might return the following errors:
318    /// - `BUSY`: Indicates that the hardware is busy with an existing operation
319    ///   or initialisation/calibration.
320    /// - `NOSUPPORT`: Indicates that the value of `hours` is not supported.
321    fn callback(&self, value: Result<usize, ErrorCode>);
322}