|
| 1 | +//! Implementation of [`embedded-hal`] I2C traits |
| 2 | +//! |
| 3 | +//! [`embedded-hal`]: https://docs.rs/embedded-hal |
| 4 | +
|
| 5 | +use std::ops; |
| 6 | +use std::path::{Path, PathBuf}; |
| 7 | + |
| 8 | +/// Newtype around [`i2cdev::linux::LinuxI2CDevice`] that implements the `embedded-hal` traits |
| 9 | +/// |
| 10 | +/// [`i2cdev::linux::LinuxI2CDevice`]: https://docs.rs/i2cdev/0.3.1/i2cdev/linux/struct.LinuxI2CDevice.html |
| 11 | +pub struct I2cdev { |
| 12 | + inner: i2cdev::linux::LinuxI2CDevice, |
| 13 | + path: PathBuf, |
| 14 | + address: Option<u8>, |
| 15 | +} |
| 16 | + |
| 17 | +impl I2cdev { |
| 18 | + /// See [`i2cdev::linux::LinuxI2CDevice::new`][0] for details. |
| 19 | + /// |
| 20 | + /// [0]: https://docs.rs/i2cdev/0.3.1/i2cdev/linux/struct.LinuxI2CDevice.html#method.new |
| 21 | + pub fn new<P>(path: P) -> Result<Self, i2cdev::linux::LinuxI2CError> |
| 22 | + where |
| 23 | + P: AsRef<Path>, |
| 24 | + { |
| 25 | + let dev = I2cdev { |
| 26 | + path: path.as_ref().to_path_buf(), |
| 27 | + inner: i2cdev::linux::LinuxI2CDevice::new(path, 0)?, |
| 28 | + address: None, |
| 29 | + }; |
| 30 | + Ok(dev) |
| 31 | + } |
| 32 | + |
| 33 | + fn set_address(&mut self, address: u8) -> Result<(), i2cdev::linux::LinuxI2CError> { |
| 34 | + if self.address != Some(address) { |
| 35 | + self.inner = i2cdev::linux::LinuxI2CDevice::new(&self.path, u16::from(address))?; |
| 36 | + self.address = Some(address); |
| 37 | + } |
| 38 | + Ok(()) |
| 39 | + } |
| 40 | +} |
| 41 | + |
| 42 | +impl ops::Deref for I2cdev { |
| 43 | + type Target = i2cdev::linux::LinuxI2CDevice; |
| 44 | + |
| 45 | + fn deref(&self) -> &Self::Target { |
| 46 | + &self.inner |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +impl ops::DerefMut for I2cdev { |
| 51 | + fn deref_mut(&mut self) -> &mut Self::Target { |
| 52 | + &mut self.inner |
| 53 | + } |
| 54 | +} |
| 55 | + |
| 56 | +mod embedded_hal_impl { |
| 57 | + use super::*; |
| 58 | + use embedded_hal::i2c::blocking::{ |
| 59 | + Operation as I2cOperation, Read, Transactional, Write, WriteRead, |
| 60 | + }; |
| 61 | + use i2cdev::core::{I2CDevice, I2CMessage, I2CTransfer}; |
| 62 | + use i2cdev::linux::LinuxI2CMessage; |
| 63 | + |
| 64 | + impl Read for I2cdev { |
| 65 | + type Error = i2cdev::linux::LinuxI2CError; |
| 66 | + |
| 67 | + fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { |
| 68 | + self.set_address(address)?; |
| 69 | + self.inner.read(buffer) |
| 70 | + } |
| 71 | + } |
| 72 | + |
| 73 | + impl Write for I2cdev { |
| 74 | + type Error = i2cdev::linux::LinuxI2CError; |
| 75 | + |
| 76 | + fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> { |
| 77 | + self.set_address(address)?; |
| 78 | + self.inner.write(bytes) |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + impl WriteRead for I2cdev { |
| 83 | + type Error = i2cdev::linux::LinuxI2CError; |
| 84 | + |
| 85 | + fn write_read( |
| 86 | + &mut self, |
| 87 | + address: u8, |
| 88 | + bytes: &[u8], |
| 89 | + buffer: &mut [u8], |
| 90 | + ) -> Result<(), Self::Error> { |
| 91 | + self.set_address(address)?; |
| 92 | + let mut messages = [LinuxI2CMessage::write(bytes), LinuxI2CMessage::read(buffer)]; |
| 93 | + self.inner.transfer(&mut messages).map(drop) |
| 94 | + } |
| 95 | + } |
| 96 | + |
| 97 | + impl Transactional for I2cdev { |
| 98 | + type Error = i2cdev::linux::LinuxI2CError; |
| 99 | + |
| 100 | + fn exec( |
| 101 | + &mut self, |
| 102 | + address: u8, |
| 103 | + operations: &mut [I2cOperation], |
| 104 | + ) -> Result<(), Self::Error> { |
| 105 | + // Map operations from generic to linux objects |
| 106 | + let mut messages: Vec<_> = operations |
| 107 | + .as_mut() |
| 108 | + .iter_mut() |
| 109 | + .map(|a| match a { |
| 110 | + I2cOperation::Write(w) => LinuxI2CMessage::write(w), |
| 111 | + I2cOperation::Read(r) => LinuxI2CMessage::read(r), |
| 112 | + }) |
| 113 | + .collect(); |
| 114 | + |
| 115 | + self.set_address(address)?; |
| 116 | + self.inner.transfer(&mut messages).map(drop) |
| 117 | + } |
| 118 | + } |
| 119 | +} |
0 commit comments