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}