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} }