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