diff --git a/examples/transactional-i2c.rs b/examples/transactional-i2c.rs new file mode 100644 index 0000000..451ae43 --- /dev/null +++ b/examples/transactional-i2c.rs @@ -0,0 +1,35 @@ +extern crate embedded_hal; +extern crate linux_embedded_hal; +use embedded_hal::blocking::i2c::{Operation as I2cOperation, Transactional}; +use linux_embedded_hal::I2cdev; + +const ADDR: u8 = 0x12; + +struct Driver { + i2c: I2C, +} + +impl Driver +where + I2C: Transactional, +{ + pub fn new(i2c: I2C) -> Self { + Driver { i2c } + } + + fn read_something(&mut self) -> Result { + let mut read_buffer = [0]; + let mut ops = [ + I2cOperation::Write(&[0xAB]), + I2cOperation::Read(&mut read_buffer), + ]; + self.i2c.try_exec(ADDR, &mut ops).and(Ok(read_buffer[0])) + } +} + +fn main() { + let dev = I2cdev::new("/dev/i2c-1").unwrap(); + let mut driver = Driver::new(dev); + let value = driver.read_something().unwrap(); + println!("Read value: {}", value); +} diff --git a/src/lib.rs b/src/lib.rs index af89635..e2d579c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,7 @@ use std::time::Duration; use std::{ops, thread}; use cast::{u32, u64}; +use hal::blocking::i2c::Operation as I2cOperation; use i2cdev::core::{I2CDevice, I2CMessage, I2CTransfer}; use i2cdev::linux::LinuxI2CMessage; use spidev::SpidevTransfer; @@ -207,6 +208,28 @@ impl hal::blocking::i2c::WriteRead for I2cdev { } } +impl hal::blocking::i2c::Transactional for I2cdev { + type Error = i2cdev::linux::LinuxI2CError; + + fn try_exec<'a, O>(&mut self, address: u8, mut operations: O) -> Result<(), Self::Error> + where + O: AsMut<[I2cOperation<'a>]>, + { + // Map operations from generic to linux objects + let mut messages: Vec<_> = operations + .as_mut() + .iter_mut() + .map(|a| match a { + I2cOperation::Write(w) => LinuxI2CMessage::write(w), + I2cOperation::Read(r) => LinuxI2CMessage::read(r), + }) + .collect(); + + self.set_address(address)?; + self.inner.transfer(&mut messages).map(drop) + } +} + impl ops::Deref for I2cdev { type Target = i2cdev::linux::LinuxI2CDevice;