1use core::{I2CDevice, I2CTransfer};
10use ffi;
11use nix;
12use std::error::Error;
13use std::fmt;
14use std::fs::File;
15use std::fs::OpenOptions;
16use std::io;
17use std::io::prelude::*;
18use std::marker::PhantomData;
19use std::os::unix::prelude::*;
20use std::path::Path;
21
22pub use core::I2CMessage;
24
25pub struct LinuxI2CDevice {
27 devfile: File,
28 slave_address: u16,
29 pec: bool,
30}
31
32pub struct LinuxI2CBus {
34 devfile: File,
35}
36
37#[derive(Debug)]
39pub enum LinuxI2CError {
40 Errno(i32),
51 Io(io::Error),
53}
54
55impl From<nix::Error> for LinuxI2CError {
56 fn from(e: nix::Error) -> Self {
57 LinuxI2CError::Errno(e as i32)
58 }
59}
60
61impl From<io::Error> for LinuxI2CError {
62 fn from(e: io::Error) -> Self {
63 LinuxI2CError::Io(e)
64 }
65}
66
67impl From<LinuxI2CError> for io::Error {
68 fn from(e: LinuxI2CError) -> io::Error {
69 match e {
70 LinuxI2CError::Io(e) => e,
71 LinuxI2CError::Errno(e) => io::Error::from_raw_os_error(e),
72 }
73 }
74}
75
76impl fmt::Display for LinuxI2CError {
77 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78 match *self {
79 LinuxI2CError::Errno(e) => {
80 let error = nix::Error::from_i32(e);
81 fmt::Display::fmt(&error, f)
82 }
83 LinuxI2CError::Io(ref e) => fmt::Display::fmt(e, f),
84 }
85 }
86}
87
88impl Error for LinuxI2CError {
89 fn cause(&self) -> Option<&dyn Error> {
90 match *self {
91 LinuxI2CError::Io(ref e) => Some(e),
92 LinuxI2CError::Errno(_) => None,
93 }
94 }
95}
96
97impl AsRawFd for LinuxI2CDevice {
98 fn as_raw_fd(&self) -> RawFd {
99 self.devfile.as_raw_fd()
100 }
101}
102
103impl AsRawFd for LinuxI2CBus {
104 fn as_raw_fd(&self) -> RawFd {
105 self.devfile.as_raw_fd()
106 }
107}
108
109impl LinuxI2CDevice {
110 pub fn new<P: AsRef<Path>>(
112 path: P,
113 slave_address: u16,
114 ) -> Result<LinuxI2CDevice, LinuxI2CError> {
115 let file = OpenOptions::new().read(true).write(true).open(path)?;
116 let mut device = LinuxI2CDevice {
117 devfile: file,
118 slave_address: 0, pec: false,
120 };
121 device.set_slave_address(slave_address)?;
122 device.set_smbus_pec(false)?;
123 Ok(device)
124 }
125
126 pub unsafe fn force_new<P: AsRef<Path>>(
133 path: P,
134 slave_address: u16,
135 ) -> Result<LinuxI2CDevice, LinuxI2CError> {
136 let file = OpenOptions::new().read(true).write(true).open(path)?;
137 let mut device = LinuxI2CDevice {
138 devfile: file,
139 slave_address: 0, pec: false,
141 };
142 device.force_set_slave_address(slave_address)?;
143 device.set_smbus_pec(false)?;
144 Ok(device)
145 }
146
147 pub fn set_slave_address(&mut self, slave_address: u16) -> Result<(), LinuxI2CError> {
159 ffi::i2c_set_slave_address(self.as_raw_fd(), slave_address)?;
160 self.slave_address = slave_address;
161 Ok(())
162 }
163
164 unsafe fn force_set_slave_address(&mut self, slave_address: u16) -> Result<(), LinuxI2CError> {
169 ffi::i2c_set_slave_address_force(self.as_raw_fd(), slave_address)?;
170 self.slave_address = slave_address;
171 Ok(())
172 }
173
174 pub fn set_smbus_pec(&mut self, enable: bool) -> Result<(), LinuxI2CError> {
180 ffi::i2c_set_smbus_pec(self.as_raw_fd(), enable)?;
181 self.pec = enable;
182 Ok(())
183 }
184}
185
186impl I2CDevice for LinuxI2CDevice {
187 type Error = LinuxI2CError;
188
189 fn read(&mut self, data: &mut [u8]) -> Result<(), LinuxI2CError> {
191 self.devfile.read_exact(data).map_err(From::from).map(drop)
192 }
193
194 fn write(&mut self, data: &[u8]) -> Result<(), LinuxI2CError> {
196 self.devfile.write(data).map_err(From::from).map(drop)
197 }
198
199 fn smbus_write_quick(&mut self, bit: bool) -> Result<(), LinuxI2CError> {
201 ffi::i2c_smbus_write_quick(self.as_raw_fd(), bit).map_err(From::from)
202 }
203
204 fn smbus_read_byte(&mut self) -> Result<u8, LinuxI2CError> {
210 ffi::i2c_smbus_read_byte(self.as_raw_fd()).map_err(From::from)
211 }
212
213 fn smbus_write_byte(&mut self, value: u8) -> Result<(), LinuxI2CError> {
218 ffi::i2c_smbus_write_byte(self.as_raw_fd(), value).map_err(From::from)
219 }
220
221 fn smbus_read_byte_data(&mut self, register: u8) -> Result<u8, LinuxI2CError> {
225 ffi::i2c_smbus_read_byte_data(self.as_raw_fd(), register).map_err(From::from)
226 }
227
228 fn smbus_write_byte_data(&mut self, register: u8, value: u8) -> Result<(), LinuxI2CError> {
232 ffi::i2c_smbus_write_byte_data(self.as_raw_fd(), register, value).map_err(From::from)
233 }
234
235 fn smbus_read_word_data(&mut self, register: u8) -> Result<u16, LinuxI2CError> {
237 ffi::i2c_smbus_read_word_data(self.as_raw_fd(), register).map_err(From::from)
238 }
239
240 fn smbus_write_word_data(&mut self, register: u8, value: u16) -> Result<(), LinuxI2CError> {
242 ffi::i2c_smbus_write_word_data(self.as_raw_fd(), register, value).map_err(From::from)
243 }
244
245 fn smbus_process_word(&mut self, register: u8, value: u16) -> Result<u16, LinuxI2CError> {
247 ffi::i2c_smbus_process_call(self.as_raw_fd(), register, value).map_err(From::from)
248 }
249
250 fn smbus_read_block_data(&mut self, register: u8) -> Result<Vec<u8>, LinuxI2CError> {
256 ffi::i2c_smbus_read_block_data(self.as_raw_fd(), register).map_err(From::from)
257 }
258
259 fn smbus_read_i2c_block_data(
261 &mut self,
262 register: u8,
263 len: u8,
264 ) -> Result<Vec<u8>, LinuxI2CError> {
265 ffi::i2c_smbus_read_i2c_block_data(self.as_raw_fd(), register, len).map_err(From::from)
266 }
267
268 fn smbus_write_block_data(&mut self, register: u8, values: &[u8]) -> Result<(), LinuxI2CError> {
274 ffi::i2c_smbus_write_block_data(self.as_raw_fd(), register, values).map_err(From::from)
275 }
276
277 fn smbus_write_i2c_block_data(
279 &mut self,
280 register: u8,
281 values: &[u8],
282 ) -> Result<(), LinuxI2CError> {
283 ffi::i2c_smbus_write_i2c_block_data(self.as_raw_fd(), register, values).map_err(From::from)
284 }
285
286 fn smbus_process_block(
289 &mut self,
290 register: u8,
291 values: &[u8],
292 ) -> Result<Vec<u8>, LinuxI2CError> {
293 ffi::i2c_smbus_process_call_block(self.as_raw_fd(), register, values).map_err(From::from)
294 }
295}
296
297impl<'a> I2CTransfer<'a> for LinuxI2CDevice {
298 type Error = LinuxI2CError;
299 type Message = LinuxI2CMessage<'a>;
300
301 fn transfer(&mut self, messages: &'a mut [Self::Message]) -> Result<u32, LinuxI2CError> {
303 let msg_type = |flag: u16| flag & I2CMessageFlags::READ.bits();
304 let mut prev_msg_type = None;
305 for msg in messages.iter_mut() {
306 msg.addr = self.slave_address;
307
308 let cur_msg_type = msg_type(msg.flags);
309 if prev_msg_type
310 .map(|prev| prev == cur_msg_type)
311 .unwrap_or_default()
312 {
313 msg.flags |= I2CMessageFlags::NO_START.bits();
314 } else {
315 prev_msg_type = Some(cur_msg_type);
316 }
317 }
318 ffi::i2c_rdwr(self.as_raw_fd(), messages).map_err(From::from)
319 }
320}
321
322impl LinuxI2CBus {
323 pub fn new<P: AsRef<Path>>(path: P) -> Result<LinuxI2CBus, LinuxI2CError> {
325 let file = OpenOptions::new().read(true).write(true).open(path)?;
326 let bus = LinuxI2CBus { devfile: file };
327 Ok(bus)
328 }
329}
330
331pub use ffi::i2c_msg as LinuxI2CMessage;
332
333impl<'a> I2CTransfer<'a> for LinuxI2CBus {
334 type Error = LinuxI2CError;
335 type Message = LinuxI2CMessage<'a>;
336
337 fn transfer(&mut self, msgs: &'a mut [Self::Message]) -> Result<u32, LinuxI2CError> {
339 ffi::i2c_rdwr(self.as_raw_fd(), msgs).map_err(From::from)
340 }
341}
342
343bitflags! {
344 pub struct I2CMessageFlags: u16 {
349 const TEN_BIT_ADDRESS = 0x0010;
351 const READ = 0x0001;
353 const STOP = 0x8000;
355 const NO_START = 0x4000;
357 const INVERT_COMMAND = 0x2000;
359 const IGNORE_NACK = 0x1000;
361 const IGNORE_ACK = 0x0800;
363 const USE_RECEIVE_LENGTH = 0x0400;
365 }
366}
367
368impl<'a> I2CMessage<'a> for LinuxI2CMessage<'a> {
369 fn read(data: &'a mut [u8]) -> LinuxI2CMessage<'a> {
370 Self {
371 addr: 0, flags: I2CMessageFlags::READ.bits(),
373 len: data.len() as u16,
374 buf: data.as_ptr(),
375 _p: PhantomData,
376 }
377 }
378
379 fn write(data: &'a [u8]) -> LinuxI2CMessage<'a> {
380 Self {
381 addr: 0, flags: I2CMessageFlags::empty().bits(),
383 len: data.len() as u16,
384 buf: data.as_ptr(),
385 _p: PhantomData,
386 }
387 }
388}
389
390impl<'a> LinuxI2CMessage<'a> {
391 pub fn with_address(self, slave_address: u16) -> Self {
393 Self {
394 addr: slave_address,
395 flags: self.flags,
396 len: self.len,
397 buf: self.buf,
398 _p: PhantomData,
399 }
400 }
401
402 pub fn with_flags(self, flags: I2CMessageFlags) -> Self {
404 Self {
405 addr: self.addr,
406 flags: flags.bits(),
407 len: self.len,
408 buf: self.buf,
409 _p: PhantomData,
410 }
411 }
412}