use byteorder::{ByteOrder, LittleEndian};
use std::error::Error;
pub trait I2CDevice {
type Error: Error;
fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error>;
fn write(&mut self, data: &[u8]) -> Result<(), Self::Error>;
fn smbus_write_quick(&mut self, bit: bool) -> Result<(), Self::Error>;
fn smbus_read_byte(&mut self) -> Result<u8, Self::Error> {
let mut buf = [0_u8];
self.read(&mut buf)?;
Ok(buf[0])
}
fn smbus_write_byte(&mut self, value: u8) -> Result<(), Self::Error> {
self.write(&mut [value])
}
fn smbus_read_byte_data(&mut self, register: u8) -> Result<u8, Self::Error> {
self.smbus_write_byte(register)?;
self.smbus_read_byte()
}
fn smbus_write_byte_data(&mut self, register: u8, value: u8) -> Result<(), Self::Error> {
self.write(&mut [register, value])
}
fn smbus_read_word_data(&mut self, register: u8) -> Result<u16, Self::Error> {
let mut buf: [u8; 2] = [0x00; 2];
self.smbus_write_byte(register)?;
self.read(&mut buf)?;
Ok(LittleEndian::read_u16(&buf))
}
fn smbus_write_word_data(&mut self, register: u8, value: u16) -> Result<(), Self::Error> {
let mut buf: [u8; 3] = [register, 0, 0];
LittleEndian::write_u16(&mut buf[1..], value);
self.write(&buf)
}
fn smbus_process_word(&mut self, register: u8, value: u16) -> Result<u16, Self::Error> {
let mut buf: [u8; 2] = [0x00; 2];
self.smbus_write_word_data(register, value)?;
self.read(&mut buf)?;
Ok(LittleEndian::read_u16(&buf))
}
fn smbus_read_block_data(&mut self, register: u8) -> Result<Vec<u8>, Self::Error>;
fn smbus_read_i2c_block_data(&mut self, register: u8, len: u8) -> Result<Vec<u8>, Self::Error>;
fn smbus_write_block_data(&mut self, register: u8, values: &[u8]) -> Result<(), Self::Error>;
fn smbus_write_i2c_block_data(&mut self, register: u8, values: &[u8]) -> Result<(), Self::Error>;
fn smbus_process_block(&mut self, register: u8, values: &[u8]) -> Result<Vec<u8>, Self::Error>;
}
pub trait I2CBus {
type Error: Error;
fn rdwr<'a>(&mut self, msgs: &mut Vec<I2CMsg<'a>>) -> Result<i32, Self::Error>;
}
bitflags! {
pub struct I2CMsgFlags: u16 {
const I2C_M_TEN = 0x0010;
const I2C_M_RD = 0x0001;
const I2C_M_STOP = 0x8000;
const I2C_M_NOSTART = 0x4000;
const I2C_M_REV_DIR_ADDR = 0x2000;
const I2C_M_IGNORE_NAK = 0x1000;
const I2C_M_NO_RD_ACK = 0x0800;
const I2C_M_RECV_LEN = 0x0400;
}
}
pub struct I2CMsg<'a> {
pub(crate) addr: u16,
pub(crate) flags: u16,
pub(crate) data: &'a mut Vec<u8>,
}
impl<'a> I2CMsg<'a> {
pub fn new(addr: u16, data: &'a mut Vec<u8>) -> Self {
I2CMsg {
addr,
flags: 0,
data
}
}
pub fn set_flags(&mut self, flags: u16) {
self.flags = flags;
}
pub fn flags(&mut self) -> u16 {
self.flags
}
pub fn set_addr(&mut self, addr: u16) {
self.addr = addr;
}
pub fn addr(&mut self) -> u16 {
self.addr
}
pub fn set_data(&mut self, data: &'a mut Vec<u8>) {
self.data = data;
}
pub fn data(&mut self) -> Vec<u8> {
self.data.clone()
}
pub fn set_read(&mut self) {
self.flags |= I2CMsgFlags::I2C_M_RD.bits;
}
}