i2c_linux/
i2c_impl.rs

1use i2c_gen as i2c;
2
3use std::os::unix::io::AsRawFd;
4use std::io;
5use std::mem;
6use resize_slice::ResizeSlice;
7use i2c_gen::{ReadFlags as I2cReadFlags, WriteFlags as I2cWriteFlags};
8use super::{I2c, ReadFlags, WriteFlags, ReadWrite};
9
10impl<I: AsRawFd> i2c::Master for I2c<I> {
11    type Error = io::Error;
12}
13
14impl<I: AsRawFd> i2c::Address for I2c<I> {
15    fn set_slave_address(&mut self, addr: u16, tenbit: bool) -> Result<(), Self::Error> {
16        I2c::smbus_set_slave_address(self, addr, tenbit)
17    }
18}
19
20impl<I: AsRawFd> i2c::Smbus for I2c<I> {
21    fn smbus_write_quick(&mut self, value: bool) -> Result<(), Self::Error> {
22        I2c::smbus_write_quick(self, if value { ReadWrite::Read } else { ReadWrite::Write })
23    }
24
25    fn smbus_read_byte(&mut self) -> Result<u8, Self::Error> {
26        I2c::smbus_read_byte(self)
27    }
28
29    fn smbus_write_byte(&mut self, value: u8) -> Result<(), Self::Error> {
30        I2c::smbus_write_byte(self, value)
31    }
32
33    fn smbus_read_byte_data(&mut self, command: u8) -> Result<u8, Self::Error> {
34        I2c::smbus_read_byte_data(self, command)
35    }
36
37    fn smbus_write_byte_data(&mut self, command: u8, value: u8) -> Result<(), Self::Error> {
38        I2c::smbus_write_byte_data(self, command, value)
39    }
40
41    fn smbus_read_word_data(&mut self, command: u8) -> Result<u16, Self::Error> {
42        I2c::smbus_read_word_data(self, command)
43    }
44
45    fn smbus_write_word_data(&mut self, command: u8, value: u16) -> Result<(), Self::Error> {
46        I2c::smbus_write_word_data(self, command, value)
47    }
48
49    fn smbus_process_call(&mut self, command: u8, value: u16) -> Result<u16, Self::Error> {
50        I2c::smbus_process_call(self, command, value)
51    }
52
53    fn smbus_read_block_data(&mut self, command: u8, value: &mut [u8]) -> Result<usize, Self::Error> {
54        I2c::smbus_read_block_data(self, command, value)
55    }
56
57    fn smbus_write_block_data(&mut self, command: u8, value: &[u8]) -> Result<(), Self::Error> {
58        I2c::smbus_write_block_data(self, command, value)
59    }
60}
61
62impl<I: AsRawFd> i2c::Smbus20 for I2c<I> {
63    fn smbus_process_call_block(&mut self, command: u8, write: &[u8], read: &mut [u8]) -> Result<usize, Self::Error> {
64        I2c::smbus_block_process_call(self, command, write, read)
65    }
66}
67
68impl<I: AsRawFd> i2c::SmbusPec for I2c<I> {
69    fn smbus_set_pec(&mut self, pec: bool) -> Result<(), Self::Error> {
70        I2c::smbus_set_pec(self, pec)
71    }
72}
73
74impl<I: AsRawFd> i2c::BlockTransfer for I2c<I> {
75    fn i2c_read_block_data(&mut self, command: u8, value: &mut [u8]) -> Result<usize, Self::Error> {
76        I2c::i2c_read_block_data(self, command, value)
77    }
78
79    fn i2c_write_block_data(&mut self, command: u8, value: &[u8]) -> Result<(), Self::Error> {
80        I2c::i2c_write_block_data(self, command, value)
81    }
82}
83
84impl<I: AsRawFd> i2c::BulkTransfer for I2c<I> {
85    fn i2c_transfer_support(&mut self) -> Result<(i2c::ReadFlags, i2c::WriteFlags), Self::Error> {
86        I2c::i2c_transfer_flags(self).map(|(read, write)| (read.into(), write.into()))
87    }
88
89    fn i2c_transfer(&mut self, messages: &mut [i2c::Message]) -> Result<(), Self::Error> {
90        let mut message_buffer: [::i2c::i2c_msg; ::i2c::I2C_RDWR_IOCTL_MAX_MSGS] = unsafe {
91            mem::uninitialized()
92        };
93        assert!(messages.len() <= message_buffer.len());
94
95        message_buffer.iter_mut().zip(messages.iter_mut())
96            .for_each(|(out, msg)| *out = match *msg {
97                i2c::Message::Read { address, ref mut data, flags } => ::i2c::i2c_msg {
98                    addr: address,
99                    flags: ::i2c::Flags::from_bits_truncate(ReadFlags::from(flags).bits()) | ::i2c::Flags::RD,
100                    len: data.len() as _,
101                    buf: data.as_mut_ptr(),
102                },
103                i2c::Message::Write { address, ref data, flags } => ::i2c::i2c_msg {
104                    addr: address,
105                    flags: ::i2c::Flags::from_bits_truncate(WriteFlags::from(flags).bits()),
106                    len: data.len() as _,
107                    buf: data.as_ptr() as *mut _,
108                },
109            });
110
111        let res = unsafe {
112            ::i2c::i2c_rdwr(self.as_raw_fd(), &mut message_buffer[..messages.len()])?;
113        };
114
115        message_buffer.iter().zip(messages.iter_mut())
116            .for_each(|(msg, out)| match *out {
117                i2c::Message::Read { ref mut data, .. } => data.resize_to(msg.len as usize),
118                i2c::Message::Write { .. } => (),
119            });
120
121        Ok(res)
122    }
123}
124
125macro_rules! impl_flags {
126    ($my:ident >< $f:ident => { $($tt:tt)* }) => {
127        impl_flags! { @impl $my >< $f => { $($tt)* } }
128        impl_flags! { @impl $f >< $my => { $($tt)* } }
129    };
130    (@impl $my:ident >< $f:ident => {
131        $($flag:ident,)*
132    }) => {
133        impl From<$my> for $f {
134            fn from(f: $my) -> Self {
135                let mut out = Self::empty();
136                $(
137                if f.contains($my::$flag) {
138                    out.set($f::$flag, true);
139                }
140                )*
141                out
142            }
143        }
144    };
145}
146
147impl_flags! { ReadFlags >< I2cReadFlags => {
148    RECEIVE_LEN,
149    NACK,
150    REVERSE_RW,
151    NO_START,
152    STOP,
153} }
154
155impl_flags! { WriteFlags >< I2cWriteFlags => {
156    IGNORE_NACK,
157    REVERSE_RW,
158    NO_START,
159    STOP,
160} }