#![deny(missing_docs)]
#![doc(html_root_url = "http://arcnmx.github.io/i2c-rs/")]
#[macro_use]
extern crate bitflags;
use std::io::{self, Read, Write};
mod smbus;
pub use smbus::SmbusReadWrite;
pub trait Master {
type Error;
}
pub trait Address: Master {
fn set_slave_address(&mut self, addr: u16, tenbit: bool) -> Result<(), Self::Error>;
}
pub trait ReadWrite: Master {
fn i2c_read(&mut self, value: &mut [u8]) -> Result<usize, Self::Error>;
fn i2c_write(&mut self, value: &[u8]) -> Result<(), Self::Error>;
}
impl<T: Master + Read + Write> ReadWrite for T where T::Error: From<io::Error> {
fn i2c_read(&mut self, value: &mut [u8]) -> Result<usize, Self::Error> {
self.read(value).map_err(From::from)
}
fn i2c_write(&mut self, value: &[u8]) -> Result<(), Self::Error> {
self.write(value)
.and_then(|len| if len != value.len() {
Err(io::Error::new(io::ErrorKind::Interrupted, format!("I2C write was truncated to {} bytes", len)))
} else {
Ok(())
}).map_err(From::from)
}
}
pub trait Smbus: Master {
fn smbus_write_quick(&mut self, value: bool) -> Result<(), Self::Error>;
fn smbus_read_byte(&mut self) -> Result<u8, Self::Error>;
fn smbus_write_byte(&mut self, value: u8) -> Result<(), Self::Error>;
fn smbus_read_byte_data(&mut self, command: u8) -> Result<u8, Self::Error>;
fn smbus_write_byte_data(&mut self, command: u8, value: u8) -> Result<(), Self::Error>;
fn smbus_read_word_data(&mut self, command: u8) -> Result<u16, Self::Error>;
fn smbus_write_word_data(&mut self, command: u8, value: u16) -> Result<(), Self::Error>;
fn smbus_process_call(&mut self, command: u8, value: u16) -> Result<u16, Self::Error>;
fn smbus_read_block_data(&mut self, command: u8, value: &mut [u8]) -> Result<usize, Self::Error>;
fn smbus_write_block_data(&mut self, command: u8, value: &[u8]) -> Result<(), Self::Error>;
}
pub trait Smbus20: Smbus {
fn smbus_process_call_block(&mut self, command: u8, write: &[u8], read: &mut [u8]) -> Result<usize, Self::Error>;
}
pub trait SmbusPec: Smbus {
fn smbus_set_pec(&mut self, pec: bool) -> Result<(), Self::Error>;
}
pub trait BlockTransfer: Master {
fn i2c_read_block_data(&mut self, command: u8, value: &mut [u8]) -> Result<usize, Self::Error>;
fn i2c_write_block_data(&mut self, command: u8, value: &[u8]) -> Result<(), Self::Error>;
}
pub trait BulkTransfer: Master {
fn i2c_transfer_support(&mut self) -> Result<(ReadFlags, WriteFlags), Self::Error>;
fn i2c_transfer(&mut self, messages: &mut [Message]) -> Result<(), Self::Error>;
}
pub enum Message<'a> {
Read {
address: u16,
data: &'a mut [u8],
flags: ReadFlags,
},
Write {
address: u16,
data: &'a [u8],
flags: WriteFlags,
},
}
impl<'a> Message<'a> {
pub fn len(&self) -> usize {
match *self {
Message::Read { ref data, .. } => data.len(),
Message::Write { ref data, .. } => data.len(),
}
}
pub fn address(&self) -> u16 {
match *self {
Message::Read { address, .. } => address,
Message::Write { address, .. } => address,
}
}
pub fn data(&self) -> &[u8] {
match *self {
Message::Read { ref data, .. } => data,
Message::Write { data, .. } => data,
}
}
}
bitflags! {
#[derive(Default)]
pub struct ReadFlags: u16 {
const RECEIVE_LEN = 0x01;
const NACK = 0x02;
const REVERSE_RW = 0x04;
const NO_START = 0x08;
const STOP = 0x10;
}
}
bitflags! {
#[derive(Default)]
pub struct WriteFlags: u16 {
const IGNORE_NACK = 0x01;
const REVERSE_RW = 0x02;
const NO_START = 0x04;
const STOP = 0x08;
}
}