i2c-linux 0.1.0

Linux I2C device interface
Documentation
use i2c_gen as i2c;

use std::os::unix::io::AsRawFd;
use std::io;
use resize_slice::ResizeSlice;
use i2c_gen::{ReadFlags as I2cReadFlags, WriteFlags as I2cWriteFlags};
use super::{I2c, ReadFlags, WriteFlags, ReadWrite};

impl<I: AsRawFd> i2c::Master for I2c<I> {
    type Error = io::Error;
}

impl<I: AsRawFd> i2c::Address for I2c<I> {
    fn set_slave_address(&mut self, addr: u16, tenbit: bool) -> Result<(), Self::Error> {
        I2c::smbus_set_slave_address(self, addr, tenbit)
    }
}

impl<I: AsRawFd> i2c::Smbus for I2c<I> {
    fn smbus_write_quick(&mut self, value: bool) -> Result<(), Self::Error> {
        I2c::smbus_write_quick(self, if value { ReadWrite::Read } else { ReadWrite::Write })
    }

    fn smbus_read_byte(&mut self) -> Result<u8, Self::Error> {
        I2c::smbus_read_byte(self)
    }

    fn smbus_write_byte(&mut self, value: u8) -> Result<(), Self::Error> {
        I2c::smbus_write_byte(self, value)
    }

    fn smbus_read_byte_data(&mut self, command: u8) -> Result<u8, Self::Error> {
        I2c::smbus_read_byte_data(self, command)
    }

    fn smbus_write_byte_data(&mut self, command: u8, value: u8) -> Result<(), Self::Error> {
        I2c::smbus_write_byte_data(self, command, value)
    }

    fn smbus_read_word_data(&mut self, command: u8) -> Result<u16, Self::Error> {
        I2c::smbus_read_word_data(self, command)
    }

    fn smbus_write_word_data(&mut self, command: u8, value: u16) -> Result<(), Self::Error> {
        I2c::smbus_write_word_data(self, command, value)
    }

    fn smbus_process_call(&mut self, command: u8, value: u16) -> Result<u16, Self::Error> {
        I2c::smbus_process_call(self, command, value)
    }

    fn smbus_read_block_data(&mut self, command: u8, value: &mut [u8]) -> Result<usize, Self::Error> {
        I2c::smbus_read_block_data(self, command, value)
    }

    fn smbus_write_block_data(&mut self, command: u8, value: &[u8]) -> Result<(), Self::Error> {
        I2c::smbus_write_block_data(self, command, value)
    }
}

impl<I: AsRawFd> i2c::Smbus20 for I2c<I> {
    fn smbus_process_call_block(&mut self, command: u8, write: &[u8], read: &mut [u8]) -> Result<usize, Self::Error> {
        I2c::smbus_block_process_call(self, command, write, read)
    }
}

impl<I: AsRawFd> i2c::SmbusPec for I2c<I> {
    fn smbus_set_pec(&mut self, pec: bool) -> Result<(), Self::Error> {
        I2c::smbus_set_pec(self, pec)
    }
}

impl<I: AsRawFd> i2c::BlockTransfer for I2c<I> {
    fn i2c_read_block_data(&mut self, command: u8, value: &mut [u8]) -> Result<usize, Self::Error> {
        I2c::i2c_read_block_data(self, command, value)
    }

    fn i2c_write_block_data(&mut self, command: u8, value: &[u8]) -> Result<(), Self::Error> {
        I2c::i2c_write_block_data(self, command, value)
    }
}

impl<I: AsRawFd> i2c::BulkTransfer for I2c<I> {
    fn i2c_transfer_support(&mut self) -> Result<(i2c::ReadFlags, i2c::WriteFlags), Self::Error> {
        I2c::i2c_transfer_flags(self).map(|(read, write)| (read.into(), write.into()))
    }

    fn i2c_transfer(&mut self, messages: &mut [i2c::Message]) -> Result<(), Self::Error> {
        assert!(messages.len() <= self.message_buffer.len());

        self.message_buffer.iter_mut().zip(messages.iter_mut())
            .for_each(|(out, msg)| *out = match *msg {
                i2c::Message::Read { address, ref mut data, flags } => ::i2c::i2c_msg {
                    addr: address,
                    flags: ::i2c::Flags::from_bits_truncate(ReadFlags::from(flags).bits()) | ::i2c::Flags::RD,
                    len: data.len() as _,
                    buf: data.as_mut_ptr(),
                },
                i2c::Message::Write { address, ref data, flags } => ::i2c::i2c_msg {
                    addr: address,
                    flags: ::i2c::Flags::from_bits_truncate(WriteFlags::from(flags).bits()),
                    len: data.len() as _,
                    buf: data.as_ptr() as *mut _,
                },
            });

        let res = unsafe {
            ::i2c::i2c_rdwr(self.as_raw_fd(), &mut self.message_buffer[..messages.len()])?;
        };

        self.message_buffer.iter().zip(messages.iter_mut())
            .for_each(|(msg, out)| match *out {
                i2c::Message::Read { ref mut data, .. } => data.resize_to(msg.len as usize),
                i2c::Message::Write { .. } => (),
            });

        Ok(res)
    }
}

macro_rules! impl_flags {
    ($my:ident >< $f:ident => { $($tt:tt)* }) => {
        impl_flags! { @impl $my >< $f => { $($tt)* } }
        impl_flags! { @impl $f >< $my => { $($tt)* } }
    };
    (@impl $my:ident >< $f:ident => {
        $($flag:ident,)*
    }) => {
        impl From<$my> for $f {
            fn from(f: $my) -> Self {
                let mut out = Self::empty();
                $(
                if f.contains($my::$flag) {
                    out.set($f::$flag, true);
                }
                )*
                out
            }
        }
    };
}

impl_flags! { ReadFlags >< I2cReadFlags => {
    RECEIVE_LEN,
    NACK,
    REVERSE_RW,
    NO_START,
    STOP,
} }

impl_flags! { WriteFlags >< I2cWriteFlags => {
    IGNORE_NACK,
    REVERSE_RW,
    NO_START,
    STOP,
} }