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::os::unix::prelude::*;
19use std::path::Path;
20
21pub use core::I2CMessage;
23
24pub struct LinuxI2CDevice {
26 devfile: File,
27 slave_address: u16,
28 pec: bool,
29}
30
31pub struct LinuxI2CBus {
33 devfile: File,
34}
35
36#[derive(Debug)]
38pub enum LinuxI2CError {
39 Nix(nix::Error),
41 Io(io::Error),
43}
44
45impl From<nix::Error> for LinuxI2CError {
46 fn from(e: nix::Error) -> Self {
47 LinuxI2CError::Nix(e)
48 }
49}
50
51impl From<io::Error> for LinuxI2CError {
52 fn from(e: io::Error) -> Self {
53 LinuxI2CError::Io(e)
54 }
55}
56
57impl From<LinuxI2CError> for io::Error {
58 fn from(e: LinuxI2CError) -> io::Error {
59 match e {
60 LinuxI2CError::Io(e) => e,
61 LinuxI2CError::Nix(e) => e.into(),
62 }
63 }
64}
65
66impl fmt::Display for LinuxI2CError {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 match *self {
69 LinuxI2CError::Nix(ref e) => fmt::Display::fmt(e, f),
70 LinuxI2CError::Io(ref e) => fmt::Display::fmt(e, f),
71 }
72 }
73}
74
75impl Error for LinuxI2CError {
76 fn cause(&self) -> Option<&dyn Error> {
77 match *self {
78 LinuxI2CError::Io(ref e) => Some(e),
79 LinuxI2CError::Nix(ref e) => Some(e),
80 }
81 }
82}
83
84impl AsRawFd for LinuxI2CDevice {
85 fn as_raw_fd(&self) -> RawFd {
86 self.devfile.as_raw_fd()
87 }
88}
89
90impl AsRawFd for LinuxI2CBus {
91 fn as_raw_fd(&self) -> RawFd {
92 self.devfile.as_raw_fd()
93 }
94}
95
96impl LinuxI2CDevice {
97 pub fn new<P: AsRef<Path>>(
99 path: P,
100 slave_address: u16,
101 ) -> Result<LinuxI2CDevice, LinuxI2CError> {
102 let file = OpenOptions::new().read(true).write(true).open(path)?;
103 let mut device = LinuxI2CDevice {
104 devfile: file,
105 slave_address: 0, pec: false,
107 };
108 device.set_slave_address(slave_address)?;
109 device.set_smbus_pec(false)?;
110 Ok(device)
111 }
112
113 pub unsafe fn force_new<P: AsRef<Path>>(
120 path: P,
121 slave_address: u16,
122 ) -> Result<LinuxI2CDevice, LinuxI2CError> {
123 let file = OpenOptions::new().read(true).write(true).open(path)?;
124 let mut device = LinuxI2CDevice {
125 devfile: file,
126 slave_address: 0, pec: false,
128 };
129 device.force_set_slave_address(slave_address)?;
130 device.set_smbus_pec(false)?;
131 Ok(device)
132 }
133
134 pub fn set_slave_address(&mut self, slave_address: u16) -> Result<(), LinuxI2CError> {
146 ffi::i2c_set_slave_address(self.as_raw_fd(), slave_address)?;
147 self.slave_address = slave_address;
148 Ok(())
149 }
150
151 unsafe fn force_set_slave_address(&mut self, slave_address: u16) -> Result<(), LinuxI2CError> {
156 ffi::i2c_set_slave_address_force(self.as_raw_fd(), slave_address)?;
157 self.slave_address = slave_address;
158 Ok(())
159 }
160
161 pub fn set_smbus_pec(&mut self, enable: bool) -> Result<(), LinuxI2CError> {
167 ffi::i2c_set_smbus_pec(self.as_raw_fd(), enable)?;
168 self.pec = enable;
169 Ok(())
170 }
171}
172
173impl I2CDevice for LinuxI2CDevice {
174 type Error = LinuxI2CError;
175
176 fn read(&mut self, data: &mut [u8]) -> Result<(), LinuxI2CError> {
178 self.devfile.read(data).map_err(From::from).map(drop)
179 }
180
181 fn write(&mut self, data: &[u8]) -> Result<(), LinuxI2CError> {
183 self.devfile.write(data).map_err(From::from).map(drop)
184 }
185
186 fn smbus_write_quick(&mut self, bit: bool) -> Result<(), LinuxI2CError> {
188 ffi::i2c_smbus_write_quick(self.as_raw_fd(), bit).map_err(From::from)
189 }
190
191 fn smbus_read_byte(&mut self) -> Result<u8, LinuxI2CError> {
197 ffi::i2c_smbus_read_byte(self.as_raw_fd()).map_err(From::from)
198 }
199
200 fn smbus_write_byte(&mut self, value: u8) -> Result<(), LinuxI2CError> {
205 ffi::i2c_smbus_write_byte(self.as_raw_fd(), value).map_err(From::from)
206 }
207
208 fn smbus_read_byte_data(&mut self, register: u8) -> Result<u8, LinuxI2CError> {
212 ffi::i2c_smbus_read_byte_data(self.as_raw_fd(), register).map_err(From::from)
213 }
214
215 fn smbus_write_byte_data(&mut self, register: u8, value: u8) -> Result<(), LinuxI2CError> {
219 ffi::i2c_smbus_write_byte_data(self.as_raw_fd(), register, value).map_err(From::from)
220 }
221
222 fn smbus_read_word_data(&mut self, register: u8) -> Result<u16, LinuxI2CError> {
224 ffi::i2c_smbus_read_word_data(self.as_raw_fd(), register).map_err(From::from)
225 }
226
227 fn smbus_write_word_data(&mut self, register: u8, value: u16) -> Result<(), LinuxI2CError> {
229 ffi::i2c_smbus_write_word_data(self.as_raw_fd(), register, value).map_err(From::from)
230 }
231
232 fn smbus_process_word(&mut self, register: u8, value: u16) -> Result<u16, LinuxI2CError> {
234 ffi::i2c_smbus_process_call(self.as_raw_fd(), register, value).map_err(From::from)
235 }
236
237 fn smbus_read_block_data(&mut self, register: u8) -> Result<Vec<u8>, LinuxI2CError> {
243 ffi::i2c_smbus_read_block_data(self.as_raw_fd(), register).map_err(From::from)
244 }
245
246 fn smbus_read_i2c_block_data(
248 &mut self,
249 register: u8,
250 len: u8,
251 ) -> Result<Vec<u8>, LinuxI2CError> {
252 ffi::i2c_smbus_read_i2c_block_data(self.as_raw_fd(), register, len).map_err(From::from)
253 }
254
255 fn smbus_write_block_data(&mut self, register: u8, values: &[u8]) -> Result<(), LinuxI2CError> {
261 ffi::i2c_smbus_write_block_data(self.as_raw_fd(), register, values).map_err(From::from)
262 }
263
264 fn smbus_write_i2c_block_data(
266 &mut self,
267 register: u8,
268 values: &[u8],
269 ) -> Result<(), LinuxI2CError> {
270 ffi::i2c_smbus_write_i2c_block_data(self.as_raw_fd(), register, values).map_err(From::from)
271 }
272
273 fn smbus_process_block(
276 &mut self,
277 register: u8,
278 values: &[u8],
279 ) -> Result<Vec<u8>, LinuxI2CError> {
280 ffi::i2c_smbus_process_call_block(self.as_raw_fd(), register, values).map_err(From::from)
281 }
282}
283
284impl<'a> I2CTransfer<'a> for LinuxI2CDevice {
285 type Error = LinuxI2CError;
286 type Message = LinuxI2CMessage<'a>;
287
288 fn transfer(&mut self, messages: &'a mut [Self::Message]) -> Result<u32, LinuxI2CError> {
290 for msg in messages.iter_mut() {
291 (*msg).addr = self.slave_address;
292 }
293 ffi::i2c_rdwr(self.as_raw_fd(), messages).map_err(From::from)
294 }
295}
296
297impl LinuxI2CBus {
298 pub fn new<P: AsRef<Path>>(path: P) -> Result<LinuxI2CBus, LinuxI2CError> {
300 let file = OpenOptions::new().read(true).write(true).open(path)?;
301 let bus = LinuxI2CBus { devfile: file };
302 Ok(bus)
303 }
304}
305
306pub type LinuxI2CMessage<'a> = ffi::i2c_msg;
308
309impl<'a> I2CTransfer<'a> for LinuxI2CBus {
310 type Error = LinuxI2CError;
311 type Message = LinuxI2CMessage<'a>;
312
313 fn transfer(&mut self, msgs: &'a mut [Self::Message]) -> Result<u32, LinuxI2CError> {
315 ffi::i2c_rdwr(self.as_raw_fd(), msgs).map_err(From::from)
316 }
317}
318
319bitflags! {
320 pub struct I2CMessageFlags: u16 {
325 const TEN_BIT_ADDRESS = 0x0010;
327 const READ = 0x0001;
329 const STOP = 0x8000;
331 const NO_START = 0x4000;
333 const INVERT_COMMAND = 0x2000;
335 const IGNORE_NACK = 0x1000;
337 const IGNORE_ACK = 0x0800;
339 const USE_RECEIVE_LENGTH = 0x0400;
341 }
342}
343
344impl<'a> I2CMessage<'a> for LinuxI2CMessage<'a> {
345 fn read(data: &'a mut [u8]) -> LinuxI2CMessage {
346 Self {
347 addr: 0, flags: I2CMessageFlags::READ.bits(),
349 len: data.len() as u16,
350 buf: data.as_ptr(),
351 }
352 }
353
354 fn write(data: &'a [u8]) -> LinuxI2CMessage {
355 Self {
356 addr: 0, flags: I2CMessageFlags::empty().bits(),
358 len: data.len() as u16,
359 buf: data.as_ptr(),
360 }
361 }
362}
363
364impl<'a> LinuxI2CMessage<'a> {
365 pub fn with_address(self, slave_address: u16) -> Self {
367 Self {
368 addr: slave_address,
369 flags: self.flags,
370 len: self.len,
371 buf: self.buf,
372 }
373 }
374
375 pub fn with_flags(self, flags: I2CMessageFlags) -> Self {
377 Self {
378 addr: self.addr,
379 flags: flags.bits(),
380 len: self.len,
381 buf: self.buf,
382 }
383 }
384}