Skip to content

Commit

Permalink
i2c: Split out embedded-hal 0.2 implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
chrysn committed Jan 21, 2024
1 parent 548197f commit f386fdd
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 98 deletions.
106 changes: 106 additions & 0 deletions src/i2c/impl_0_2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//! Implementation of embedded-hal 0.2's I2C for [I2CDevice]
//!
//! As the implementation is on the [I2CDevice directly], all that is in this module is the
//! suitable [Error] type.
use embedded_hal_0_2::blocking;

use super::*;

use riot_sys::libc;
use riot_sys::{i2c_acquire, i2c_read_bytes, i2c_release, i2c_write_bytes};

#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
AcquireError,
WriteError(i32),
ReadError(i32),
}

impl blocking::i2c::WriteRead for I2CDevice {
type Error = Error;

fn write_read(
&mut self,
address: u8,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Self::Error> {
unsafe { i2c_acquire(self.dev) };
let err = unsafe {
i2c_write_bytes(
self.dev,
address as u16,
bytes.as_ptr() as *const libc::c_void,
bytes.len() as _,
0,
)
};
if err != 0 {
unsafe { i2c_release(self.dev) };
return Err(Error::WriteError(err));
}
let err = unsafe {
i2c_read_bytes(
self.dev,
address as u16,
buffer.as_ptr() as *mut libc::c_void,
buffer.len() as _,
0,
)
};
if err != 0 {
unsafe { i2c_release(self.dev) };
return Err(Error::ReadError(err));
}
unsafe { i2c_release(self.dev) };
Ok(())
}
}

impl blocking::i2c::Write for I2CDevice {
type Error = Error;

fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
unsafe { i2c_acquire(self.dev) };
let err = unsafe {
i2c_write_bytes(
self.dev,
address as u16,
bytes.as_ptr() as *const libc::c_void,
bytes.len() as _,
0,
)
};
if err != 0 {
unsafe { i2c_release(self.dev) };
return Err(Error::WriteError(err));
}
unsafe { i2c_release(self.dev) };
Ok(())
}
}

impl blocking::i2c::Read for I2CDevice {
type Error = Error;

fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
unsafe { i2c_acquire(self.dev) };
let err = unsafe {
i2c_read_bytes(
self.dev,
address as u16,
buffer.as_ptr() as *mut libc::c_void,
buffer.len() as _,
0,
)
};
if err != 0 {
unsafe { i2c_release(self.dev) };
return Err(Error::ReadError(err));
}
unsafe { i2c_release(self.dev) };
Ok(())
}
}
104 changes: 6 additions & 98 deletions src/i2c/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Controlling the I²C bus
use embedded_hal_0_2::blocking;
pub mod impl_0_2;

use riot_sys::i2c_t;

/// An I²C master backed by RIOT's [I2C implementation]
Expand All @@ -24,100 +25,7 @@ impl I2CDevice {
}
}

#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
AcquireError,
WriteError(i32),
ReadError(i32),
}

use riot_sys::libc;
use riot_sys::{i2c_acquire, i2c_read_bytes, i2c_release, i2c_write_bytes};

impl blocking::i2c::WriteRead for I2CDevice {
type Error = Error;

fn write_read(
&mut self,
address: u8,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Self::Error> {
unsafe { i2c_acquire(self.dev) };
let err = unsafe {
i2c_write_bytes(
self.dev,
address as u16,
bytes.as_ptr() as *const libc::c_void,
bytes.len() as _,
0,
)
};
if err != 0 {
unsafe { i2c_release(self.dev) };
return Err(Error::WriteError(err));
}
let err = unsafe {
i2c_read_bytes(
self.dev,
address as u16,
buffer.as_ptr() as *mut libc::c_void,
buffer.len() as _,
0,
)
};
if err != 0 {
unsafe { i2c_release(self.dev) };
return Err(Error::ReadError(err));
}
unsafe { i2c_release(self.dev) };
Ok(())
}
}

impl blocking::i2c::Write for I2CDevice {
type Error = Error;

fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
unsafe { i2c_acquire(self.dev) };
let err = unsafe {
i2c_write_bytes(
self.dev,
address as u16,
bytes.as_ptr() as *const libc::c_void,
bytes.len() as _,
0,
)
};
if err != 0 {
unsafe { i2c_release(self.dev) };
return Err(Error::WriteError(err));
}
unsafe { i2c_release(self.dev) };
Ok(())
}
}

impl blocking::i2c::Read for I2CDevice {
type Error = Error;

fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
unsafe { i2c_acquire(self.dev) };
let err = unsafe {
i2c_read_bytes(
self.dev,
address as u16,
buffer.as_ptr() as *mut libc::c_void,
buffer.len() as _,
0,
)
};
if err != 0 {
unsafe { i2c_release(self.dev) };
return Err(Error::ReadError(err));
}
unsafe { i2c_release(self.dev) };
Ok(())
}
}
#[deprecated(
note = "This error type applies to embedded-hal 0.2 only, use it through the impl_0_2 module."
)]
pub use impl_0_2::Error;

0 comments on commit f386fdd

Please sign in to comment.