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 percent, or
57 /// 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
133 /// Callback issued after sensor reads proximity value
134 fn read_proximity(&self) -> Result<(), ErrorCode>;
135
136 /// Callback issued after sensor reads proximity value greater
137 /// than 'high_threshold' or less than 'low_threshold'
138 ///
139 /// To elaborate, the callback is not issued by the driver until
140 /// (prox_reading >= high_threshold || prox_reading <= low_threshold).
141 /// When (prox_reading >= high_threshold || prox_reading <= low_threshold)
142 /// is read by the sensor, an I2C interrupt is generated and sent to the
143 /// kernel which prompts the driver to collect the proximity reading from
144 /// the sensor and perform the callback. Any apps issuing this command will
145 /// have to wait for the proximity reading to fall within the
146 /// aforementioned ranges in order to received a callback. Threshold: A
147 /// value of range [0 , 255] which represents at what proximity reading
148 /// ranges an interrupt will occur.
149 fn read_proximity_on_interrupt(
150 &self,
151 low_threshold: u8,
152 high_threshold: u8,
153 ) -> Result<(), ErrorCode>;
154}
155
156pub trait ProximityClient {
157 /// Called when a proximity reading has completed.
158 ///
159 /// - `value`: the most recently read proximity value which ranges
160 /// [0 , 255]... where 255 -> object is closest readable distance, 0 ->
161 /// object is farthest readable distance.
162 fn callback(&self, value: u8);
163}
164
165/// A basic interface for an ambient light sensor.
166pub trait AmbientLight<'a> {
167 /// Set the client to be notified when the capsule has data ready or has
168 /// finished some command. This is likely called in a board's `main.rs`.
169 fn set_client(&self, client: &'a dyn AmbientLightClient);
170
171 /// Get a single instantaneous reading of the ambient light intensity.
172 fn read_light_intensity(&self) -> Result<(), ErrorCode> {
173 Err(ErrorCode::NODEVICE)
174 }
175}
176
177/// Client for receiving light intensity readings.
178pub trait AmbientLightClient {
179 /// Called when an ambient light reading has completed.
180 ///
181 /// - `lux`: the most recently read ambient light reading in lux (lx).
182 fn callback(&self, lux: usize);
183}
184
185/// A basic interface for a 9-DOF compatible chip.
186///
187/// This trait provides a standard interface for chips that implement
188/// some or all of a nine degrees of freedom (accelerometer, magnetometer,
189/// gyroscope) sensor. Any interface functions that a chip cannot implement
190/// can be ignored by the chip capsule and an error will automatically be
191/// returned.
192pub trait NineDof<'a> {
193 /// Set the client to be notified when the capsule has data ready or
194 /// has finished some command. This is likely called in a board's main.rs
195 /// and is set to the virtual_ninedof.rs driver.
196 fn set_client(&self, client: &'a dyn NineDofClient);
197
198 /// Get a single instantaneous reading of the acceleration in the
199 /// X,Y,Z directions.
200 fn read_accelerometer(&self) -> Result<(), ErrorCode> {
201 Err(ErrorCode::NODEVICE)
202 }
203
204 /// Get a single instantaneous reading from the magnetometer in all
205 /// three directions.
206 fn read_magnetometer(&self) -> Result<(), ErrorCode> {
207 Err(ErrorCode::NODEVICE)
208 }
209
210 /// Get a single instantaneous reading from the gyroscope of the rotation
211 /// around all three axes.
212 fn read_gyroscope(&self) -> Result<(), ErrorCode> {
213 Err(ErrorCode::NODEVICE)
214 }
215}
216
217/// Client for receiving done events from the chip.
218pub trait NineDofClient {
219 /// Signals a command has finished. The arguments will most likely be passed
220 /// over the syscall interface to an application.
221 fn callback(&self, arg1: usize, arg2: usize, arg3: usize);
222}
223
224/// Basic Interface for Sound Pressure
225pub trait SoundPressure<'a> {
226 /// Read the sound pressure level
227 fn read_sound_pressure(&self) -> Result<(), ErrorCode>;
228
229 /// Enable
230 ///
231 /// As this is usually a microphone, some boards require an explicit enable
232 /// so that they can turn on an LED. This function enables that microphone and LED.
233 /// Not calling this function may result in inaccurate readings.
234 fn enable(&self) -> Result<(), ErrorCode>;
235
236 /// Disable
237 ///
238 /// As this is usually a microphone, some boards require an explicit enable
239 /// so that they can turn on an LED. This function turns off that microphone. Readings
240 /// performed after this function call might return inaccurate.
241 fn disable(&self) -> Result<(), ErrorCode>;
242
243 /// Set the client
244 fn set_client(&self, client: &'a dyn SoundPressureClient);
245}
246
247pub trait SoundPressureClient {
248 /// Signals the sound pressure in dB
249 fn callback(&self, ret: Result<(), ErrorCode>, sound_pressure: u8);
250}
251
252/// A Basic interface for a barometer sensor.
253pub trait PressureDriver<'a> {
254 /// Used to initialize a atmospheric pressure reading
255 ///
256 /// This function might return the following errors:
257 /// - `BUSY`: Indicates that the hardware is busy with an existing operation
258 /// or initialisation/calibration.
259 /// - `FAIL`: Failed to correctly communicate over communication protocol.
260 /// - `NOSUPPORT`: Indicates that this data type isn't supported.
261 fn read_atmospheric_pressure(&self) -> Result<(), ErrorCode>;
262
263 /// Set the client
264 fn set_client(&self, client: &'a dyn PressureClient);
265}
266
267pub trait PressureClient {
268 /// Called when a atmospheric pressure reading has completed.
269 ///
270 /// Returns the value in hPa.
271 fn callback(&self, pressure: Result<u32, ErrorCode>);
272}
273
274/// A basic interface for distance sensor.
275pub trait Distance<'a> {
276 /// Set the client
277 fn set_client(&self, client: &'a dyn DistanceClient);
278
279 /// Initiates a distance reading from the sensor.
280 ///
281 /// This function might return the following errors:
282 /// - `BUSY`: Indicates that the hardware is currently busy.
283 /// - `FAIL`: Indicates that there was a failure in communication.
284 fn read_distance(&self) -> Result<(), ErrorCode>;
285
286 /// Get the maximum distance the sensor can measure in mm
287 fn get_maximum_distance(&self) -> u32;
288
289 /// Get the minimum distance the sensor can measure in mm
290 fn get_minimum_distance(&self) -> u32;
291}
292
293/// Client for receiving distance readings.
294pub trait DistanceClient {
295 /// Called when a distance measurement has completed.
296 ///
297 /// - `distance`: the most recently measured distance in millimeters. If
298 /// there was an error, this will be `Err(ErrorCode)`.
299 fn callback(&self, distance: Result<u32, ErrorCode>);
300}
301
302/// A basic interface for a rain fall sensor
303pub trait RainFallDriver<'a> {
304 fn set_client(&self, client: &'a dyn RainFallClient);
305
306 /// Read the rain fall value from a sensor. The value is returned
307 /// via the `RainFallClient` callback.
308 ///
309 /// - `hours`: the number of hours of rainfall to report. 1 to 24 hours are
310 /// valid values (if supported by the hardware).
311 ///
312 /// This function might return the following errors:
313 /// - `BUSY`: Indicates that the hardware is busy with an existing operation
314 /// or initialisation/calibration.
315 /// - `NOSUPPORT`: Indicates that the value of `hours` is not supported.
316 fn read_rainfall(&self, hours: usize) -> Result<(), ErrorCode>;
317}
318
319/// Client for receiving moisture readings.
320pub trait RainFallClient {
321 /// Called when a moisture reading has completed.
322 ///
323 /// - `value`: the number of um of rain in the time period specified, or Err
324 /// on failure.
325 ///
326 /// This function might return the following errors:
327 /// - `BUSY`: Indicates that the hardware is busy with an existing operation
328 /// or initialisation/calibration.
329 /// - `NOSUPPORT`: Indicates that the value of `hours` is not supported.
330 fn callback(&self, value: Result<usize, ErrorCode>);
331}