capsules_extra/
lsm303dlhc.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//! SyscallDriver for the LSM303DLHC 3D accelerometer and 3D magnetometer sensor.
6//!
7//! May be used with NineDof and Temperature
8//!
9//! I2C Interface
10//!
11//! <https://www.st.com/en/mems-and-sensors/lsm303dlhc.html>
12//!
13//! The syscall interface is described in [lsm303dlhc.md](https://github.com/tock/tock/tree/master/doc/syscalls/70006_lsm303dlhc.md)
14//!
15//! Usage
16//! -----
17//!
18//! ```rust,ignore
19//! let mux_i2c = components::i2c::I2CMuxComponent::new(&stm32f3xx::i2c::I2C1)
20//!     .finalize(components::i2c_mux_component_helper!());
21//!
22//! let lsm303dlhc = components::lsm303dlhc::Lsm303dlhcI2CComponent::new()
23//!    .finalize(components::lsm303dlhc_i2c_component_helper!(mux_i2c));
24//!
25//! lsm303dlhc.configure(
26//!    lsm303dlhc::Lsm303AccelDataRate::DataRate25Hz,
27//!    false,
28//!    lsm303dlhc::Lsm303Scale::Scale2G,
29//!    false,
30//!    true,
31//!    lsm303dlhc::Lsm303MagnetoDataRate::DataRate3_0Hz,
32//!    lsm303dlhc::Lsm303Range::Range4_7G,
33//!);
34//! ```
35//!
36//! NideDof Example
37//!
38//! ```rust,ignore
39//! let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
40//! let grant_ninedof = board_kernel.create_grant(&grant_cap);
41//!
42//! // use as primary NineDof Sensor
43//! let ninedof = static_init!(
44//!    capsules::ninedof::NineDof<'static>,
45//!    capsules::ninedof::NineDof::new(lsm303dlhc, grant_ninedof)
46//! );
47//!
48//! hil::sensors::NineDof::set_client(lsm303dlhc, ninedof);
49//!
50//! // use as secondary NineDof Sensor
51//! let lsm303dlhc_secondary = static_init!(
52//!    capsules::ninedof::NineDofNode<'static, &'static dyn hil::sensors::NineDof>,
53//!    capsules::ninedof::NineDofNode::new(lsm303dlhc)
54//! );
55//! ninedof.add_secondary_driver(lsm303dlhc_secondary);
56//! hil::sensors::NineDof::set_client(lsm303dlhc, ninedof);
57//! ```
58//!
59//! Temperature Example
60//!
61//! ```rust,ignore
62//! let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
63//! let grant_temp = board_kernel.create_grant(&grant_cap);
64//!
65//! lsm303dlhc.configure(
66//!    lsm303dlhc::Lsm303AccelDataRate::DataRate25Hz,
67//!    false,
68//!    lsm303dlhc::Lsm303Scale::Scale2G,
69//!    false,
70//!    true,
71//!    lsm303dlhc::Lsm303MagnetoDataRate::DataRate3_0Hz,
72//!    lsm303dlhc::Lsm303Range::Range4_7G,
73//!);
74//! let temp = static_init!(
75//! capsules::temperature::TemperatureSensor<'static>,
76//!     capsules::temperature::TemperatureSensor::new(lsm303dlhc, grant_temperature));
77//! kernel::hil::sensors::TemperatureDriver::set_client(lsm303dlhc, temp);
78//! ```
79//!
80//! Author: Alexandru Radovici <msg4alex@gmail.com>
81//!
82
83#![allow(non_camel_case_types)]
84
85use core::cell::Cell;
86
87use enum_primitive::cast::FromPrimitive;
88use enum_primitive::enum_from_primitive;
89
90use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
91use kernel::hil::i2c;
92use kernel::hil::sensors;
93use kernel::syscall::{CommandReturn, SyscallDriver};
94use kernel::utilities::cells::{OptionalCell, TakeCell};
95use kernel::{ErrorCode, ProcessId};
96
97use crate::lsm303xx::{
98    AccelerometerRegisters, Lsm303AccelDataRate, Lsm303MagnetoDataRate, Lsm303Range, Lsm303Scale,
99    CTRL_REG1, CTRL_REG4, RANGE_FACTOR_X_Y, RANGE_FACTOR_Z, SCALE_FACTOR,
100};
101
102use capsules_core::driver;
103
104/// Syscall driver number.
105pub const DRIVER_NUM: usize = driver::NUM::Lsm303dlch as usize;
106
107/// Register values
108const REGISTER_AUTO_INCREMENT: u8 = 0x80;
109
110enum_from_primitive! {
111    enum MagnetometerRegisters {
112        CRA_REG_M = 0x00,
113        CRB_REG_M = 0x01,
114        OUT_X_H_M = 0x03,
115        OUT_X_L_M = 0x04,
116        OUT_Z_H_M = 0x05,
117        OUT_Z_L_M = 0x06,
118        OUT_Y_H_M = 0x07,
119        OUT_Y_L_M = 0x08,
120        TEMP_OUT_H_M = 0x31,
121        TEMP_OUT_L_M = 0x32,
122    }
123}
124
125// Experimental
126const TEMP_OFFSET: i32 = 17;
127
128#[derive(Clone, Copy, PartialEq)]
129enum State {
130    Idle,
131    IsPresent,
132    SetPowerMode,
133    SetScaleAndResolution,
134    ReadAccelerationXYZ,
135    SetTemperatureDataRate,
136    SetRange,
137    ReadTemperature,
138    ReadMagnetometerXYZ,
139}
140
141pub struct Lsm303dlhcI2C<'a, I: i2c::I2CDevice> {
142    config_in_progress: Cell<bool>,
143    i2c_accelerometer: &'a I,
144    i2c_magnetometer: &'a I,
145    state: Cell<State>,
146    accel_scale: Cell<Lsm303Scale>,
147    mag_range: Cell<Lsm303Range>,
148    accel_high_resolution: Cell<bool>,
149    mag_data_rate: Cell<Lsm303MagnetoDataRate>,
150    accel_data_rate: Cell<Lsm303AccelDataRate>,
151    low_power: Cell<bool>,
152    temperature: Cell<bool>,
153    buffer: TakeCell<'static, [u8]>,
154    nine_dof_client: OptionalCell<&'a dyn sensors::NineDofClient>,
155    temperature_client: OptionalCell<&'a dyn sensors::TemperatureClient>,
156    current_process: OptionalCell<ProcessId>,
157    apps: Grant<App, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<0>>,
158}
159
160#[derive(Default)]
161pub struct App {}
162
163impl<'a, I: i2c::I2CDevice> Lsm303dlhcI2C<'a, I> {
164    pub fn new(
165        i2c_accelerometer: &'a I,
166        i2c_magnetometer: &'a I,
167        buffer: &'static mut [u8],
168        grant: Grant<App, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<0>>,
169    ) -> Lsm303dlhcI2C<'a, I> {
170        // setup and return struct
171        Lsm303dlhcI2C {
172            config_in_progress: Cell::new(false),
173            i2c_accelerometer,
174            i2c_magnetometer,
175            state: Cell::new(State::Idle),
176            accel_scale: Cell::new(Lsm303Scale::Scale2G),
177            mag_range: Cell::new(Lsm303Range::Range1G),
178            accel_high_resolution: Cell::new(false),
179            mag_data_rate: Cell::new(Lsm303MagnetoDataRate::DataRate0_75Hz),
180            accel_data_rate: Cell::new(Lsm303AccelDataRate::DataRate1Hz),
181            low_power: Cell::new(false),
182            temperature: Cell::new(false),
183            buffer: TakeCell::new(buffer),
184            nine_dof_client: OptionalCell::empty(),
185            temperature_client: OptionalCell::empty(),
186            current_process: OptionalCell::empty(),
187            apps: grant,
188        }
189    }
190
191    pub fn configure(
192        &self,
193        accel_data_rate: Lsm303AccelDataRate,
194        low_power: bool,
195        accel_scale: Lsm303Scale,
196        accel_high_resolution: bool,
197        temperature: bool,
198        mag_data_rate: Lsm303MagnetoDataRate,
199        mag_range: Lsm303Range,
200    ) -> Result<(), ErrorCode> {
201        if self.state.get() == State::Idle {
202            self.config_in_progress.set(true);
203
204            self.accel_scale.set(accel_scale);
205            self.accel_high_resolution.set(accel_high_resolution);
206            self.temperature.set(temperature);
207            self.mag_data_rate.set(mag_data_rate);
208            self.mag_range.set(mag_range);
209            self.accel_data_rate.set(accel_data_rate);
210            self.low_power.set(low_power);
211
212            self.set_power_mode(accel_data_rate, low_power)
213        } else {
214            Err(ErrorCode::BUSY)
215        }
216    }
217
218    fn is_present(&self) -> Result<(), ErrorCode> {
219        if self.state.get() != State::Idle {
220            self.state.set(State::IsPresent);
221            self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buf| {
222                // turn on i2c to send commands
223                buf[0] = 0x0F;
224                self.i2c_magnetometer.enable();
225                if let Err((error, buf)) = self.i2c_magnetometer.write_read(buf, 1, 1) {
226                    self.buffer.replace(buf);
227                    self.state.set(State::Idle);
228                    Err(error.into())
229                } else {
230                    Ok(())
231                }
232            })
233        } else {
234            Err(ErrorCode::BUSY)
235        }
236    }
237
238    fn set_power_mode(
239        &self,
240        data_rate: Lsm303AccelDataRate,
241        low_power: bool,
242    ) -> Result<(), ErrorCode> {
243        if self.state.get() == State::Idle {
244            self.state.set(State::SetPowerMode);
245            self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buf| {
246                buf[0] = AccelerometerRegisters::CTRL_REG1 as u8;
247                buf[1] = (CTRL_REG1::ODR.val(data_rate as u8)
248                    + CTRL_REG1::LPEN.val(low_power as u8)
249                    + CTRL_REG1::ZEN::SET
250                    + CTRL_REG1::YEN::SET
251                    + CTRL_REG1::XEN::SET)
252                    .value;
253                self.i2c_accelerometer.enable();
254                if let Err((error, buf)) = self.i2c_accelerometer.write(buf, 2) {
255                    self.state.set(State::Idle);
256                    self.buffer.replace(buf);
257                    Err(error.into())
258                } else {
259                    Ok(())
260                }
261            })
262        } else {
263            Err(ErrorCode::BUSY)
264        }
265    }
266
267    fn set_scale_and_resolution(
268        &self,
269        scale: Lsm303Scale,
270        high_resolution: bool,
271    ) -> Result<(), ErrorCode> {
272        if self.state.get() == State::Idle {
273            self.state.set(State::SetScaleAndResolution);
274            // TODO move these in completed
275            self.accel_scale.set(scale);
276            self.accel_high_resolution.set(high_resolution);
277            self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buf| {
278                buf[0] = AccelerometerRegisters::CTRL_REG4 as u8;
279                buf[1] = (CTRL_REG4::FS.val(scale as u8)
280                    + CTRL_REG4::HR.val(high_resolution as u8))
281                .value;
282                self.i2c_accelerometer.enable();
283                if let Err((error, buf)) = self.i2c_accelerometer.write(buf, 2) {
284                    self.state.set(State::Idle);
285                    self.buffer.replace(buf);
286                    Err(error.into())
287                } else {
288                    Ok(())
289                }
290            })
291        } else {
292            Err(ErrorCode::BUSY)
293        }
294    }
295
296    fn read_acceleration_xyz(&self) -> Result<(), ErrorCode> {
297        if self.state.get() == State::Idle {
298            self.state.set(State::ReadAccelerationXYZ);
299            self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buf| {
300                buf[0] = AccelerometerRegisters::OUT_X_L_A as u8 | REGISTER_AUTO_INCREMENT;
301                self.i2c_accelerometer.enable();
302                if let Err((error, buf)) = self.i2c_accelerometer.write_read(buf, 1, 6) {
303                    self.state.set(State::Idle);
304                    self.buffer.replace(buf);
305                    Err(error.into())
306                } else {
307                    Ok(())
308                }
309            })
310        } else {
311            Err(ErrorCode::BUSY)
312        }
313    }
314
315    fn set_temperature_and_magneto_data_rate(
316        &self,
317        temperature: bool,
318        data_rate: Lsm303MagnetoDataRate,
319    ) -> Result<(), ErrorCode> {
320        if self.state.get() == State::Idle {
321            self.state.set(State::SetTemperatureDataRate);
322            self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buf| {
323                buf[0] = MagnetometerRegisters::CRA_REG_M as u8;
324                buf[1] = ((data_rate as u8) << 2) | if temperature { 1 << 7 } else { 0 };
325                self.i2c_magnetometer.enable();
326                if let Err((error, buf)) = self.i2c_magnetometer.write(buf, 2) {
327                    self.state.set(State::Idle);
328                    self.buffer.replace(buf);
329                    Err(error.into())
330                } else {
331                    Ok(())
332                }
333            })
334        } else {
335            Err(ErrorCode::BUSY)
336        }
337    }
338
339    fn set_range(&self, range: Lsm303Range) -> Result<(), ErrorCode> {
340        if self.state.get() == State::Idle {
341            self.state.set(State::SetRange);
342            // TODO move these in completed
343            self.mag_range.set(range);
344            self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buf| {
345                buf[0] = MagnetometerRegisters::CRB_REG_M as u8;
346                buf[1] = (range as u8) << 5;
347                buf[2] = 0;
348                self.i2c_magnetometer.enable();
349                if let Err((error, buf)) = self.i2c_magnetometer.write(buf, 3) {
350                    self.state.set(State::Idle);
351                    self.buffer.replace(buf);
352                    Err(error.into())
353                } else {
354                    Ok(())
355                }
356            })
357        } else {
358            Err(ErrorCode::BUSY)
359        }
360    }
361
362    fn read_temperature(&self) -> Result<(), ErrorCode> {
363        if self.state.get() == State::Idle {
364            self.state.set(State::ReadTemperature);
365            self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buf| {
366                buf[0] = MagnetometerRegisters::TEMP_OUT_H_M as u8;
367                self.i2c_magnetometer.enable();
368                if let Err((error, buf)) = self.i2c_magnetometer.write_read(buf, 1, 2) {
369                    self.state.set(State::Idle);
370                    self.buffer.replace(buf);
371                    Err(error.into())
372                } else {
373                    Ok(())
374                }
375            })
376        } else {
377            Err(ErrorCode::BUSY)
378        }
379    }
380
381    fn read_magnetometer_xyz(&self) -> Result<(), ErrorCode> {
382        if self.state.get() == State::Idle {
383            self.state.set(State::ReadMagnetometerXYZ);
384            self.buffer.take().map_or(Err(ErrorCode::NOMEM), |buf| {
385                buf[0] = MagnetometerRegisters::OUT_X_H_M as u8;
386                self.i2c_magnetometer.enable();
387                if let Err((error, buf)) = self.i2c_magnetometer.write_read(buf, 1, 6) {
388                    self.state.set(State::Idle);
389                    self.buffer.replace(buf);
390                    Err(error.into())
391                } else {
392                    Ok(())
393                }
394            })
395        } else {
396            Err(ErrorCode::BUSY)
397        }
398    }
399}
400
401impl<I: i2c::I2CDevice> i2c::I2CClient for Lsm303dlhcI2C<'_, I> {
402    fn command_complete(&self, buffer: &'static mut [u8], status: Result<(), i2c::Error>) {
403        match self.state.get() {
404            State::IsPresent => {
405                let present = status.is_ok() && buffer[0] == 60;
406
407                self.current_process.map(|process_id| {
408                    let _ = self.apps.enter(process_id, |_grant, upcalls| {
409                        upcalls
410                            .schedule_upcall(0, (usize::from(present), 0, 0))
411                            .ok();
412                    });
413                });
414
415                self.buffer.replace(buffer);
416                self.i2c_magnetometer.disable();
417                self.state.set(State::Idle);
418            }
419            State::SetPowerMode => {
420                let set_power = status == Ok(());
421
422                self.current_process.map(|process_id| {
423                    let _ = self.apps.enter(process_id, |_grant, upcalls| {
424                        upcalls
425                            .schedule_upcall(0, (usize::from(set_power), 0, 0))
426                            .ok();
427                    });
428                });
429
430                self.buffer.replace(buffer);
431                self.i2c_accelerometer.disable();
432                self.state.set(State::Idle);
433                if self.config_in_progress.get() {
434                    let _ = self.set_scale_and_resolution(
435                        self.accel_scale.get(),
436                        self.accel_high_resolution.get(),
437                    );
438                }
439            }
440            State::SetScaleAndResolution => {
441                let set_scale_and_resolution = status == Ok(());
442
443                self.current_process.map(|process_id| {
444                    let _ = self.apps.enter(process_id, |_grant, upcalls| {
445                        upcalls
446                            .schedule_upcall(0, (usize::from(set_scale_and_resolution), 0, 0))
447                            .ok();
448                    });
449                });
450
451                self.buffer.replace(buffer);
452                self.i2c_accelerometer.disable();
453                self.state.set(State::Idle);
454                if self.config_in_progress.get() {
455                    if let Err(_error) = self.set_temperature_and_magneto_data_rate(
456                        self.temperature.get(),
457                        self.mag_data_rate.get(),
458                    ) {
459                        self.config_in_progress.set(false);
460                    }
461                }
462            }
463            State::ReadAccelerationXYZ => {
464                let mut x: usize = 0;
465                let mut y: usize = 0;
466                let mut z: usize = 0;
467                let values = if status == Ok(()) {
468                    self.nine_dof_client.map(|client| {
469                        // compute using only integers
470                        let scale_factor = self.accel_scale.get() as usize;
471                        x = (((buffer[0] as i16 | ((buffer[1] as i16) << 8)) as i32)
472                            * (SCALE_FACTOR[scale_factor] as i32)
473                            * 1000
474                            / 32768) as usize;
475                        y = (((buffer[2] as i16 | ((buffer[3] as i16) << 8)) as i32)
476                            * (SCALE_FACTOR[scale_factor] as i32)
477                            * 1000
478                            / 32768) as usize;
479                        z = (((buffer[4] as i16 | ((buffer[5] as i16) << 8)) as i32)
480                            * (SCALE_FACTOR[scale_factor] as i32)
481                            * 1000
482                            / 32768) as usize;
483                        client.callback(x, y, z);
484                    });
485
486                    x = (buffer[0] as i16 | ((buffer[1] as i16) << 8)) as usize;
487                    y = (buffer[2] as i16 | ((buffer[3] as i16) << 8)) as usize;
488                    z = (buffer[4] as i16 | ((buffer[5] as i16) << 8)) as usize;
489                    true
490                } else {
491                    self.nine_dof_client.map(|client| {
492                        client.callback(0, 0, 0);
493                    });
494                    false
495                };
496
497                self.current_process.map(|process_id| {
498                    let _ = self.apps.enter(process_id, |_grant, upcalls| {
499                        if values {
500                            upcalls.schedule_upcall(0, (x, y, z)).ok();
501                        } else {
502                            upcalls.schedule_upcall(0, (0, 0, 0)).ok();
503                        }
504                    });
505                });
506
507                self.buffer.replace(buffer);
508                self.i2c_accelerometer.disable();
509                self.state.set(State::Idle);
510            }
511            State::SetTemperatureDataRate => {
512                let set_temperature_and_magneto_data_rate = status == Ok(());
513
514                self.current_process.map(|process_id| {
515                    let _ = self.apps.enter(process_id, |_grant, upcalls| {
516                        upcalls
517                            .schedule_upcall(
518                                0,
519                                (usize::from(set_temperature_and_magneto_data_rate), 0, 0),
520                            )
521                            .ok();
522                    });
523                });
524
525                self.buffer.replace(buffer);
526                self.i2c_magnetometer.disable();
527                self.state.set(State::Idle);
528                if self.config_in_progress.get() {
529                    if let Err(_error) = self.set_range(self.mag_range.get()) {
530                        self.config_in_progress.set(false);
531                    }
532                }
533            }
534            State::SetRange => {
535                let set_range = status == Ok(());
536
537                self.current_process.map(|process_id| {
538                    let _ = self.apps.enter(process_id, |_grant, upcalls| {
539                        upcalls
540                            .schedule_upcall(0, (usize::from(set_range), 0, 0))
541                            .ok();
542                    });
543                });
544
545                if self.config_in_progress.get() {
546                    self.config_in_progress.set(false);
547                }
548                self.buffer.replace(buffer);
549                self.i2c_magnetometer.disable();
550                self.state.set(State::Idle);
551            }
552            State::ReadTemperature => {
553                let values = match status {
554                    Ok(()) => Ok(
555                        ((buffer[1] as i16 | ((buffer[0] as i16) << 8)) >> 4) as i32 / 8
556                            + TEMP_OFFSET,
557                    ),
558                    Err(i2c_error) => Err(i2c_error.into()),
559                };
560                self.temperature_client.map(|client| {
561                    client.callback(values);
562                });
563
564                self.current_process.map(|process_id| {
565                    let _ = self.apps.enter(process_id, |_grant, upcalls| {
566                        if let Ok(temp) = values {
567                            upcalls.schedule_upcall(0, (temp as usize, 0, 0)).ok();
568                        } else {
569                            upcalls.schedule_upcall(0, (0, 0, 0)).ok();
570                        }
571                    });
572                });
573
574                self.buffer.replace(buffer);
575                self.i2c_magnetometer.disable();
576                self.state.set(State::Idle);
577            }
578            State::ReadMagnetometerXYZ => {
579                let mut x: usize = 0;
580                let mut y: usize = 0;
581                let mut z: usize = 0;
582                let values = if status == Ok(()) {
583                    self.nine_dof_client.map(|client| {
584                        // compute using only integers
585                        let range = self.mag_range.get() as usize;
586                        x = (((buffer[1] as i16 | ((buffer[0] as i16) << 8)) as i32) * 100
587                            / RANGE_FACTOR_X_Y[range] as i32) as usize;
588                        z = (((buffer[3] as i16 | ((buffer[2] as i16) << 8)) as i32) * 100
589                            / RANGE_FACTOR_X_Y[range] as i32) as usize;
590                        y = (((buffer[5] as i16 | ((buffer[4] as i16) << 8)) as i32) * 100
591                            / RANGE_FACTOR_Z[range] as i32) as usize;
592                        client.callback(x, y, z);
593                    });
594
595                    x = ((buffer[1] as u16 | ((buffer[0] as u16) << 8)) as i16) as usize;
596                    z = ((buffer[3] as u16 | ((buffer[2] as u16) << 8)) as i16) as usize;
597                    y = ((buffer[5] as u16 | ((buffer[4] as u16) << 8)) as i16) as usize;
598                    true
599                } else {
600                    self.nine_dof_client.map(|client| {
601                        client.callback(0, 0, 0);
602                    });
603                    false
604                };
605
606                self.current_process.map(|process_id| {
607                    let _ = self.apps.enter(process_id, |_grant, upcalls| {
608                        if values {
609                            upcalls.schedule_upcall(0, (x, y, z)).ok();
610                        } else {
611                            upcalls.schedule_upcall(0, (0, 0, 0)).ok();
612                        }
613                    });
614                });
615
616                self.buffer.replace(buffer);
617                self.i2c_magnetometer.disable();
618                self.state.set(State::Idle);
619            }
620            _ => {
621                self.i2c_magnetometer.disable();
622                self.i2c_accelerometer.disable();
623                self.buffer.replace(buffer);
624            }
625        }
626    }
627}
628
629impl<I: i2c::I2CDevice> SyscallDriver for Lsm303dlhcI2C<'_, I> {
630    fn command(
631        &self,
632        command_num: usize,
633        data1: usize,
634        data2: usize,
635        process_id: ProcessId,
636    ) -> CommandReturn {
637        if command_num == 0 {
638            // Handle this first as it should be returned
639            // unconditionally
640            return CommandReturn::success();
641        }
642
643        // Check if this non-virtualized driver is already in use by
644        // some (alive) process
645        let match_or_empty_or_nonexistant = self.current_process.map_or(true, |current_process| {
646            self.apps
647                .enter(current_process, |_, _| current_process == process_id)
648                .unwrap_or(true)
649        });
650
651        if match_or_empty_or_nonexistant {
652            self.current_process.set(process_id);
653        } else {
654            return CommandReturn::failure(ErrorCode::NOMEM);
655        }
656
657        match command_num {
658            // Check is sensor is correctly connected
659            1 => {
660                if self.state.get() == State::Idle {
661                    match self.is_present() {
662                        Ok(()) => CommandReturn::success(),
663                        Err(error) => CommandReturn::failure(error),
664                    }
665                } else {
666                    CommandReturn::failure(ErrorCode::BUSY)
667                }
668            }
669            // Set Accelerometer Power Mode
670            2 => {
671                if self.state.get() == State::Idle {
672                    if let Some(data_rate) = Lsm303AccelDataRate::from_usize(data1) {
673                        match self.set_power_mode(data_rate, data2 != 0) {
674                            Ok(()) => CommandReturn::success(),
675                            Err(error) => CommandReturn::failure(error),
676                        }
677                    } else {
678                        CommandReturn::failure(ErrorCode::INVAL)
679                    }
680                } else {
681                    CommandReturn::failure(ErrorCode::BUSY)
682                }
683            }
684            // Set Accelerometer Scale And Resolution
685            3 => {
686                if self.state.get() == State::Idle {
687                    if let Some(scale) = Lsm303Scale::from_usize(data1) {
688                        match self.set_scale_and_resolution(scale, data2 != 0) {
689                            Ok(()) => CommandReturn::success(),
690                            Err(error) => CommandReturn::failure(error),
691                        }
692                    } else {
693                        CommandReturn::failure(ErrorCode::INVAL)
694                    }
695                } else {
696                    CommandReturn::failure(ErrorCode::BUSY)
697                }
698            }
699            // Set Magnetometer Temperature Enable and Data Rate
700            4 => {
701                if self.state.get() == State::Idle {
702                    if let Some(data_rate) = Lsm303MagnetoDataRate::from_usize(data1) {
703                        match self.set_temperature_and_magneto_data_rate(data2 != 0, data_rate) {
704                            Ok(()) => CommandReturn::success(),
705                            Err(error) => CommandReturn::failure(error),
706                        }
707                    } else {
708                        CommandReturn::failure(ErrorCode::INVAL)
709                    }
710                } else {
711                    CommandReturn::failure(ErrorCode::BUSY)
712                }
713            }
714            // Set Magnetometer Range
715            5 => {
716                if self.state.get() == State::Idle {
717                    if let Some(range) = Lsm303Range::from_usize(data1) {
718                        match self.set_range(range) {
719                            Ok(()) => CommandReturn::success(),
720                            Err(error) => CommandReturn::failure(error),
721                        }
722                    } else {
723                        CommandReturn::failure(ErrorCode::INVAL)
724                    }
725                } else {
726                    CommandReturn::failure(ErrorCode::BUSY)
727                }
728            }
729            // default
730            _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
731        }
732    }
733
734    fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
735        self.apps.enter(processid, |_, _| {})
736    }
737}
738
739impl<'a, I: i2c::I2CDevice> sensors::NineDof<'a> for Lsm303dlhcI2C<'a, I> {
740    fn set_client(&self, nine_dof_client: &'a dyn sensors::NineDofClient) {
741        self.nine_dof_client.replace(nine_dof_client);
742    }
743
744    fn read_accelerometer(&self) -> Result<(), ErrorCode> {
745        self.read_acceleration_xyz()
746    }
747
748    fn read_magnetometer(&self) -> Result<(), ErrorCode> {
749        self.read_magnetometer_xyz()
750    }
751}
752
753impl<'a, I: i2c::I2CDevice> sensors::TemperatureDriver<'a> for Lsm303dlhcI2C<'a, I> {
754    fn set_client(&self, temperature_client: &'a dyn sensors::TemperatureClient) {
755        self.temperature_client.replace(temperature_client);
756    }
757
758    fn read_temperature(&self) -> Result<(), ErrorCode> {
759        self.read_temperature()
760    }
761}