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                        let _ = upcalls.schedule_upcall(0, (usize::from(present), 0, 0));
416                    });
417                });
418                self.buffer.replace(buffer);
419                self.i2c_magnetometer.disable();
420                self.state.set(State::Idle);
421            }
422            State::SetPowerMode => {
423                let set_power = status == Ok(());
424                self.owning_process.map(|pid| {
425                    let _res = self.apps.enter(pid, |_app, upcalls| {
426                        let _ = upcalls.schedule_upcall(0, (usize::from(set_power), 0, 0));
427                    });
428                });
429                self.buffer.replace(buffer);
430                self.i2c_accelerometer.disable();
431                self.state.set(State::Idle);
432                if self.config_in_progress.get() {
433                    if let Err(_error) = self.set_scale_and_resolution(
434                        self.accel_scale.get(),
435                        self.accel_high_resolution.get(),
436                    ) {
437                        self.config_in_progress.set(false);
438                    }
439                }
440            }
441            State::SetScaleAndResolution => {
442                let set_scale_and_resolution = status == Ok(());
443                self.owning_process.map(|pid| {
444                    let _res = self.apps.enter(pid, |_app, upcalls| {
445                        let _ = upcalls
446                            .schedule_upcall(0, (usize::from(set_scale_and_resolution), 0, 0));
447                    });
448                });
449                self.buffer.replace(buffer);
450                self.i2c_accelerometer.disable();
451                self.state.set(State::Idle);
452                if self.config_in_progress.get() {
453                    if let Err(_error) = self.set_magneto_data_rate(self.mag_data_rate.get()) {
454                        self.config_in_progress.set(false);
455                    }
456                }
457            }
458            State::ReadAccelerationXYZ => {
459                let mut x: usize = 0;
460                let mut y: usize = 0;
461                let mut z: usize = 0;
462                let values = if status == Ok(()) {
463                    self.nine_dof_client.map(|client| {
464                        // compute using only integers
465                        let scale_factor = self.accel_scale.get() as usize;
466                        x = (((buffer[0] as i16 | ((buffer[1] as i16) << 8)) as i32)
467                            * (SCALE_FACTOR[scale_factor] as i32)
468                            * 1000
469                            / 32768) as usize;
470                        y = (((buffer[2] as i16 | ((buffer[3] as i16) << 8)) as i32)
471                            * (SCALE_FACTOR[scale_factor] as i32)
472                            * 1000
473                            / 32768) as usize;
474                        z = (((buffer[4] as i16 | ((buffer[5] as i16) << 8)) as i32)
475                            * (SCALE_FACTOR[scale_factor] as i32)
476                            * 1000
477                            / 32768) as usize;
478                        client.callback(x, y, z);
479                    });
480
481                    x = (buffer[0] as i16 | ((buffer[1] as i16) << 8)) as usize;
482                    y = (buffer[2] as i16 | ((buffer[3] as i16) << 8)) as usize;
483                    z = (buffer[4] as i16 | ((buffer[5] as i16) << 8)) as usize;
484                    true
485                } else {
486                    self.nine_dof_client.map(|client| {
487                        client.callback(0, 0, 0);
488                    });
489                    false
490                };
491                self.owning_process.map(|pid| {
492                    let _res = self.apps.enter(pid, |_app, upcalls| {
493                        if values {
494                            let _ = upcalls.schedule_upcall(0, (x, y, z));
495                        } else {
496                            let _ = upcalls.schedule_upcall(0, (0, 0, 0));
497                        }
498                    });
499                });
500                self.buffer.replace(buffer);
501                self.i2c_accelerometer.disable();
502                self.state.set(State::Idle);
503            }
504            State::SetDataRate => {
505                let set_magneto_data_rate = status == Ok(());
506                self.owning_process.map(|pid| {
507                    let _res = self.apps.enter(pid, |_app, upcalls| {
508                        let _ =
509                            upcalls.schedule_upcall(0, (usize::from(set_magneto_data_rate), 0, 0));
510                    });
511                });
512                self.buffer.replace(buffer);
513                self.i2c_magnetometer.disable();
514                self.state.set(State::Idle);
515                if self.config_in_progress.get() {
516                    if let Err(_error) = self.set_range(self.mag_range.get()) {
517                        self.config_in_progress.set(false);
518                    }
519                }
520            }
521            State::SetRange => {
522                let set_range = status == Ok(());
523                self.owning_process.map(|pid| {
524                    let _res = self.apps.enter(pid, |_app, upcalls| {
525                        let _ = upcalls.schedule_upcall(0, (usize::from(set_range), 0, 0));
526                    });
527                });
528                if self.config_in_progress.get() {
529                    self.config_in_progress.set(false);
530                }
531                self.buffer.replace(buffer);
532                self.i2c_magnetometer.disable();
533                self.state.set(State::Idle);
534            }
535            State::ReadTemperature => {
536                let values = match status {
537                    Ok(()) => Ok((buffer[1] as u16 as i16 | ((buffer[0] as i16) << 8)) as i32 / 8),
538                    Err(i2c_err) => Err(i2c_err.into()),
539                };
540                self.temperature_client.map(|client| {
541                    client.callback(values);
542                });
543                self.owning_process.map(|pid| {
544                    let _res = self.apps.enter(pid, |_app, upcalls| {
545                        if let Ok(temp) = values {
546                            let _ = upcalls.schedule_upcall(0, (temp as usize, 0, 0));
547                        } else {
548                            let _ = upcalls.schedule_upcall(0, (0, 0, 0));
549                        }
550                    });
551                });
552                self.buffer.replace(buffer);
553                self.i2c_accelerometer.disable();
554                self.state.set(State::Idle);
555            }
556            State::ReadMagnetometerXYZ => {
557                let mut x: usize = 0;
558                let mut y: usize = 0;
559                let mut z: usize = 0;
560                let values = if status == Ok(()) {
561                    self.nine_dof_client.map(|client| {
562                        // compute using only integers
563                        let range = self.mag_range.get() as usize;
564                        x = (((buffer[1] as i16 | ((buffer[0] as i16) << 8)) as i32) * 100
565                            / RANGE_FACTOR_X_Y[range] as i32) as usize;
566                        z = (((buffer[3] as i16 | ((buffer[2] as i16) << 8)) as i32) * 100
567                            / RANGE_FACTOR_X_Y[range] as i32) as usize;
568                        y = (((buffer[5] as i16 | ((buffer[4] as i16) << 8)) as i32) * 100
569                            / RANGE_FACTOR_Z[range] as i32) as usize;
570                        client.callback(x, y, z);
571                    });
572
573                    x = ((buffer[1] as u16 | ((buffer[0] as u16) << 8)) as i16) as usize;
574                    z = ((buffer[3] as u16 | ((buffer[2] as u16) << 8)) as i16) as usize;
575                    y = ((buffer[5] as u16 | ((buffer[4] as u16) << 8)) as i16) as usize;
576                    true
577                } else {
578                    self.nine_dof_client.map(|client| {
579                        client.callback(0, 0, 0);
580                    });
581                    false
582                };
583                self.owning_process.map(|pid| {
584                    let _res = self.apps.enter(pid, |_app, upcalls| {
585                        if values {
586                            let _ = upcalls.schedule_upcall(0, (x, y, z));
587                        } else {
588                            let _ = upcalls.schedule_upcall(0, (0, 0, 0));
589                        }
590                    });
591                });
592                self.buffer.replace(buffer);
593                self.i2c_magnetometer.disable();
594                self.state.set(State::Idle);
595            }
596            _ => {
597                self.i2c_magnetometer.disable();
598                self.i2c_accelerometer.disable();
599                self.buffer.replace(buffer);
600            }
601        }
602    }
603}
604
605impl<I: i2c::I2CDevice> SyscallDriver for Lsm303agrI2C<'_, I> {
606    fn command(
607        &self,
608        command_num: usize,
609        data1: usize,
610        data2: usize,
611        process_id: ProcessId,
612    ) -> CommandReturn {
613        if command_num == 0 {
614            // Handle this first as it should be returned
615            // unconditionally
616            return CommandReturn::success();
617        }
618
619        let match_or_empty_or_nonexistant = self.owning_process.map_or(true, |current_process| {
620            self.apps
621                .enter(current_process, |_, _| current_process == process_id)
622                .unwrap_or(true)
623        });
624        if match_or_empty_or_nonexistant {
625            self.owning_process.set(process_id);
626        } else {
627            return CommandReturn::failure(ErrorCode::RESERVE);
628        }
629
630        match command_num {
631            // Check is sensor is correctly connected
632            1 => {
633                if self.state.get() == State::Idle {
634                    match self.is_present() {
635                        Ok(()) => CommandReturn::success(),
636                        Err(error) => CommandReturn::failure(error),
637                    }
638                } else {
639                    CommandReturn::failure(ErrorCode::BUSY)
640                }
641            }
642            // Set Accelerometer Power Mode
643            2 => {
644                if self.state.get() == State::Idle {
645                    if let Some(data_rate) = Lsm303AccelDataRate::from_usize(data1) {
646                        match self.set_power_mode(data_rate, data2 != 0) {
647                            Ok(()) => CommandReturn::success(),
648                            Err(error) => CommandReturn::failure(error),
649                        }
650                    } else {
651                        CommandReturn::failure(ErrorCode::INVAL)
652                    }
653                } else {
654                    CommandReturn::failure(ErrorCode::BUSY)
655                }
656            }
657            // Set Accelerometer Scale And Resolution
658            3 => {
659                if self.state.get() == State::Idle {
660                    if let Some(scale) = Lsm303Scale::from_usize(data1) {
661                        match self.set_scale_and_resolution(scale, data2 != 0) {
662                            Ok(()) => CommandReturn::success(),
663                            Err(error) => CommandReturn::failure(error),
664                        }
665                    } else {
666                        CommandReturn::failure(ErrorCode::INVAL)
667                    }
668                } else {
669                    CommandReturn::failure(ErrorCode::BUSY)
670                }
671            }
672            // Set Magnetometer Temperature Enable and Data Rate
673            4 => {
674                if self.state.get() == State::Idle {
675                    if let Some(data_rate) = Lsm303MagnetoDataRate::from_usize(data1) {
676                        match self.set_magneto_data_rate(data_rate) {
677                            Ok(()) => CommandReturn::success(),
678                            Err(error) => CommandReturn::failure(error),
679                        }
680                    } else {
681                        CommandReturn::failure(ErrorCode::INVAL)
682                    }
683                } else {
684                    CommandReturn::failure(ErrorCode::BUSY)
685                }
686            }
687            // Set Magnetometer Range
688            5 => {
689                if self.state.get() == State::Idle {
690                    if let Some(range) = Lsm303Range::from_usize(data1) {
691                        match self.set_range(range) {
692                            Ok(()) => CommandReturn::success(),
693                            Err(error) => CommandReturn::failure(error),
694                        }
695                    } else {
696                        CommandReturn::failure(ErrorCode::INVAL)
697                    }
698                } else {
699                    CommandReturn::failure(ErrorCode::BUSY)
700                }
701            }
702            // default
703            _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
704        }
705    }
706
707    fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
708        self.apps.enter(processid, |_, _| {})
709    }
710}
711
712impl<'a, I: i2c::I2CDevice> sensors::NineDof<'a> for Lsm303agrI2C<'a, I> {
713    fn set_client(&self, nine_dof_client: &'a dyn sensors::NineDofClient) {
714        self.nine_dof_client.replace(nine_dof_client);
715    }
716
717    fn read_accelerometer(&self) -> Result<(), ErrorCode> {
718        self.read_acceleration_xyz()
719    }
720
721    fn read_magnetometer(&self) -> Result<(), ErrorCode> {
722        self.read_magnetometer_xyz()
723    }
724}
725
726impl<'a, I: i2c::I2CDevice> sensors::TemperatureDriver<'a> for Lsm303agrI2C<'a, I> {
727    fn set_client(&self, temperature_client: &'a dyn sensors::TemperatureClient) {
728        self.temperature_client.replace(temperature_client);
729    }
730
731    fn read_temperature(&self) -> Result<(), ErrorCode> {
732        self.read_temperature()
733    }
734}