i2c_linux/
lib.rs

1#![deny(missing_docs)]
2#![doc(html_root_url = "http://arcnmx.github.io/i2c-linux-rs/")]
3
4//! A safe interface to the Linux I2C and SMBus userspace subsystem.
5//!
6//! # Example
7//!
8//! ```rust,no_run
9//! extern crate i2c_linux;
10//! use i2c_linux::I2c;
11//!
12//! # fn main_res() -> ::std::io::Result<()> {
13//! let mut i2c = I2c::from_path("/dev/i2c-0")?;
14//! i2c.smbus_set_slave_address(0x50, false)?;
15//! let data = i2c.smbus_read_byte()?;
16//! println!("Read I2C data: {}", data);
17//! # Ok(())
18//! # }
19//! # fn main() { main_res().unwrap() }
20//! ```
21//!
22//! # Cargo Features
23//!
24//! - `i2c` will impl [i2c](https://crates.io/crates/i2c) traits for `I2c`.
25//! - `udev` must be enabled to use `Enumerator`.
26
27#[macro_use]
28extern crate bitflags;
29extern crate resize_slice;
30extern crate i2c_linux_sys as i2c;
31#[cfg(feature = "i2c")]
32extern crate i2c as i2c_gen;
33#[cfg(feature = "udev")]
34extern crate udev;
35
36use std::time::Duration;
37use std::path::Path;
38use std::os::unix::io::{AsRawFd, IntoRawFd, FromRawFd, RawFd};
39use std::io::{self, Read, Write};
40use std::fs::{File, OpenOptions};
41use std::{mem, cmp, iter};
42use resize_slice::ResizeSlice;
43
44pub use i2c::{SmbusReadWrite as ReadWrite, Functionality};
45
46#[cfg(feature = "udev")]
47mod enumerate;
48
49#[cfg(feature = "udev")]
50pub use enumerate::Enumerator;
51
52#[cfg(feature = "i2c")]
53mod i2c_impl;
54
55/// Part of a combined I2C transaction.
56pub enum Message<'a> {
57    /// I2C read command
58    Read {
59        /// The slave address of the device to read from.
60        address: u16,
61        /// A data buffer to read into.
62        data: &'a mut [u8],
63        /// Additional flags can modify the operation to work around device quirks.
64        flags: ReadFlags,
65    },
66    /// I2C write command
67    Write {
68        /// The slave address of the device to write to.
69        address: u16,
70        /// The data to write.
71        data: &'a [u8],
72        /// Additional flags can modify the operation to work around device quirks.
73        flags: WriteFlags,
74    },
75}
76
77impl<'a> Message<'a> {
78    /// Byte length of the message data buffer.
79    pub fn len(&self) -> usize {
80        match *self {
81            Message::Read { ref data, .. } => data.len(),
82            Message::Write { ref data, .. } => data.len(),
83        }
84    }
85
86    /// Address of the message's slave.
87    pub fn address(&self) -> u16 {
88        match *self {
89            Message::Read { address, .. } => address,
90            Message::Write { address, .. } => address,
91        }
92    }
93}
94
95bitflags! {
96    /// Flags to work around device quirks.
97    #[derive(Default)]
98    pub struct ReadFlags: u16 {
99        /// This is a 10-bit chip address.
100        const TENBIT_ADDR = i2c::I2C_M_TEN;
101        /// The first received byte will indicate the remaining length of the transfer.
102        const RECEIVE_LEN = i2c::I2C_M_RECV_LEN;
103        /// NACK bit is generated for this read.
104        ///
105        /// Requires `Functionality::PROTOCOL_MANGLING`
106        const NACK = i2c::I2C_M_NO_RD_ACK;
107        /// Flips the meaning of the read/write address bit for misbehaving devices.
108        ///
109        /// Requires `Functionality::PROTOCOL_MANGLING`
110        const REVERSE_RW = i2c::I2C_M_REV_DIR_ADDR;
111        /// Do not generate a START condition or the address start byte. When
112        /// used for the first message, a START condition is still generated.
113        ///
114        /// This can be used to combine multiple buffers into a single I2C transfer,
115        /// usually without a direction change.
116        ///
117        /// Requires `Functionality::NO_START`
118        const NO_START = i2c::I2C_M_NOSTART;
119        /// Force a STOP condition after this message.
120        ///
121        /// Requires `Functionality::PROTOCOL_MANGLING`
122        const STOP = i2c::I2C_M_STOP;
123    }
124}
125
126bitflags! {
127    /// Flags to work around device quirks.
128    #[derive(Default)]
129    pub struct WriteFlags: u16 {
130        /// This is a 10-bit chip address.
131        const TENBIT_ADDR = i2c::I2C_M_TEN;
132        /// Treat NACK as an ACK and prevent it from interrupting the transfer.
133        ///
134        /// Requires `Functionality::PROTOCOL_MANGLING`
135        const IGNORE_NACK = i2c::I2C_M_IGNORE_NAK;
136        /// Flips the meaning of the read/write address bit for misbehaving devices.
137        ///
138        /// Requires `Functionality::PROTOCOL_MANGLING`
139        const REVERSE_RW = i2c::I2C_M_REV_DIR_ADDR;
140        /// Do not generate a START condition or the address start byte. When
141        /// used for the first message, a START condition is still generated.
142        ///
143        /// This can be used to combine multiple buffers into a single I2C transfer,
144        /// usually without a direction change.
145        ///
146        /// Requires `Functionality::NO_START`
147        const NO_START = i2c::I2C_M_NOSTART;
148        /// Force a STOP condition after this message.
149        ///
150        /// Requires `Functionality::PROTOCOL_MANGLING`
151        const STOP = i2c::I2C_M_STOP;
152    }
153}
154
155/// A safe wrapper around an I2C device.
156pub struct I2c<I> {
157    inner: I,
158    address: Option<u16>,
159    address_10bit: bool,
160    functionality: Option<Functionality>,
161}
162
163impl I2c<File> {
164    /// Open an I2C device
165    pub fn from_path<P: AsRef<Path>>(p: P) -> io::Result<Self> {
166        OpenOptions::new().read(true).write(true)
167            .open(p).map(Self::new)
168    }
169}
170
171impl<I> I2c<I> {
172    /// Creates a new I2C handle with the given file descriptor
173    pub fn new(device: I) -> Self {
174        I2c {
175            inner: device,
176            address: None,
177            address_10bit: false,
178            functionality: None,
179        }
180    }
181
182    /// Consumes the I2C handle to return the inner file descriptor.
183    pub fn into_inner(self) -> I {
184        self.inner
185    }
186
187    /// Borrows the inner file descriptor.
188    pub fn inner_ref(&self) -> &I {
189        &self.inner
190    }
191
192    /// Mutably borrows the inner file descriptor.
193    pub fn inner_mut(&mut self) -> &mut I {
194        &mut self.inner
195    }
196}
197
198impl<I: AsRawFd> AsRawFd for I2c<I> {
199    fn as_raw_fd(&self) -> RawFd {
200        self.inner.as_raw_fd()
201    }
202}
203
204impl<I: IntoRawFd> IntoRawFd for I2c<I> {
205    fn into_raw_fd(self) -> RawFd {
206        self.inner.into_raw_fd()
207    }
208}
209
210impl FromRawFd for I2c<File> {
211    unsafe fn from_raw_fd(fd: RawFd) -> Self {
212        Self::new(File::from_raw_fd(fd))
213    }
214}
215
216// TODO: add assertions for block lengths, return a proper io::Error
217impl<I: AsRawFd> I2c<I> {
218    fn update_functionality(&mut self) -> Option<Functionality> {
219        if let Some(func) = self.functionality.clone() {
220            Some(func)
221        } else {
222            let functionality = self.i2c_functionality().ok();
223            self.functionality = functionality.clone();
224            functionality
225        }
226    }
227
228    /// Sets the number of times to retry communication before failing.
229    pub fn i2c_set_retries(&self, value: usize) -> io::Result<()> {
230        i2c::i2c_set_retries(self.as_raw_fd(), value)
231    }
232
233    /// Sets a timeout for I2C operations
234    pub fn i2c_set_timeout(&self, duration: Duration) -> io::Result<()> {
235        let value = duration.as_secs() as usize * 1000 + duration.subsec_nanos() as usize / 1000000;
236        i2c::i2c_set_timeout_ms(self.as_raw_fd(), value as _)
237    }
238
239    /// Set the slave address to communicate with.
240    pub fn smbus_set_slave_address(&mut self, address: u16, tenbit: bool) -> io::Result<()> {
241        if let Some(func) = self.update_functionality() {
242            if func.contains(Functionality::TENBIT_ADDR) || tenbit {
243                i2c::i2c_set_slave_address_10bit(self.as_raw_fd(), tenbit)?;
244            }
245        }
246
247        let res = i2c::i2c_set_slave_address(self.as_raw_fd(), address, false);
248
249        if res.is_ok() {
250            self.address = Some(address);
251            self.address_10bit = tenbit;
252        }
253
254        res
255    }
256
257    /// Enable or disable SMBus Packet Error Checking.
258    pub fn smbus_set_pec(&self, pec: bool) -> io::Result<()> {
259        i2c::i2c_pec(self.as_raw_fd(), pec)
260    }
261
262    /// Retrieve the capabilities of the I2C device. These should be checked
263    /// before attempting to use certain SMBus commands or I2C flags.
264    pub fn i2c_functionality(&self) -> io::Result<Functionality> {
265        i2c::i2c_get_functionality(self.as_raw_fd())
266    }
267
268    /// `i2c_transfer` capabilities of the I2C device. These should be checked
269    /// before attempting to use any of the protocol mangling flags.
270    pub fn i2c_transfer_flags(&self) -> io::Result<(ReadFlags, WriteFlags)> {
271        let func = self.i2c_functionality()?;
272        let (mut read, mut write) = (ReadFlags::empty(), WriteFlags::empty());
273        if func.contains(Functionality::PROTOCOL_MANGLING) {
274            read.set(ReadFlags::NACK, true);
275            read.set(ReadFlags::REVERSE_RW, true);
276            read.set(ReadFlags::STOP, true);
277            write.set(WriteFlags::IGNORE_NACK, true);
278            write.set(WriteFlags::REVERSE_RW, true);
279            write.set(WriteFlags::STOP, true);
280        }
281        if func.contains(Functionality::NO_START) {
282            read.set(ReadFlags::NO_START, true);
283            write.set(WriteFlags::NO_START, true);
284        }
285        if func.contains(Functionality::TENBIT_ADDR) {
286            read.set(ReadFlags::TENBIT_ADDR, true);
287            write.set(WriteFlags::TENBIT_ADDR, true);
288        }
289        Ok((read, write))
290    }
291
292    /// Executes a queue of I2C transfers, separated by repeat START conditions.
293    /// Data buffers are truncated to the actual read length on completion.
294    ///
295    /// See the `I2C_RDWR` ioctl for more information.
296    pub fn i2c_transfer(&mut self, messages: &mut [Message]) -> io::Result<()> {
297        let mut message_buffer: [i2c::i2c_msg; i2c::I2C_RDWR_IOCTL_MAX_MSGS] = unsafe {
298            mem::uninitialized()
299        };
300        assert!(messages.len() <= message_buffer.len());
301
302        message_buffer.iter_mut().zip(messages.iter_mut())
303            .for_each(|(out, msg)| *out = match *msg {
304                Message::Read { address, ref mut data, flags } => i2c::i2c_msg {
305                    addr: address,
306                    flags: i2c::Flags::from_bits_truncate(flags.bits()) | i2c::Flags::RD,
307                    len: data.len() as _,
308                    buf: data.as_mut_ptr(),
309                },
310                Message::Write { address, ref data, flags } => i2c::i2c_msg {
311                    addr: address,
312                    flags: i2c::Flags::from_bits_truncate(flags.bits()),
313                    len: data.len() as _,
314                    buf: data.as_ptr() as *mut _,
315                },
316            });
317
318        let res = unsafe {
319            i2c::i2c_rdwr(self.as_raw_fd(), &mut message_buffer[..messages.len()])?;
320        };
321
322        message_buffer.iter().zip(messages.iter_mut())
323            .for_each(|(msg, out)| match *out {
324                Message::Read { ref mut data, .. } => data.resize_to(msg.len as usize),
325                Message::Write { .. } => (),
326            });
327
328        Ok(res)
329    }
330
331    /// Sends a single bit to the device, in the place of the Rd/Wr address bit.
332    pub fn smbus_write_quick(&mut self, value: ReadWrite) -> io::Result<()> {
333        i2c::i2c_smbus_write_quick(self.as_raw_fd(), value)
334    }
335
336    /// Reads a single byte from a device without specifying a register.
337    ///
338    /// Some devices are so simple that this interface is enough; for others, it
339    /// is a shorthand if you want to read the same register as in the previous
340    /// SMBus command.
341    pub fn smbus_read_byte(&mut self) -> io::Result<u8> {
342        i2c::i2c_smbus_read_byte(self.as_raw_fd())
343    }
344
345    /// Sends a single byte to a device.
346    pub fn smbus_write_byte(&mut self, value: u8) -> io::Result<()> {
347        i2c::i2c_smbus_write_byte(self.as_raw_fd(), value)
348    }
349
350    /// Reads a single byte from a device from the designated register.
351    pub fn smbus_read_byte_data(&mut self, command: u8) -> io::Result<u8> {
352        i2c::i2c_smbus_read_byte_data(self.as_raw_fd(), command)
353    }
354
355    /// Writes a single byte to a device to the designated register.
356    pub fn smbus_write_byte_data(&mut self, command: u8, value: u8) -> io::Result<()> {
357        i2c::i2c_smbus_write_byte_data(self.as_raw_fd(), command, value)
358    }
359
360    /// Reads a 16-bit word from the device register.
361    pub fn smbus_read_word_data(&mut self, command: u8) -> io::Result<u16> {
362        i2c::i2c_smbus_read_word_data(self.as_raw_fd(), command)
363    }
364
365    /// Writes a 16-bit word to the device register.
366    pub fn smbus_write_word_data(&mut self, command: u8, value: u16) -> io::Result<()> {
367        i2c::i2c_smbus_write_word_data(self.as_raw_fd(), command, value)
368    }
369
370    /// Selects a device register, sends a 16-bit word to it, and read 16-bits
371    /// of data in return.
372    pub fn smbus_process_call(&mut self, command: u8, value: u16) -> io::Result<u16> {
373        i2c::i2c_smbus_process_call(self.as_raw_fd(), command, value)
374    }
375
376    /// Read up to 32 bytes from the designated device register.
377    ///
378    /// Returns the amount of data read.
379    pub fn smbus_read_block_data(&mut self, command: u8, value: &mut [u8]) -> io::Result<usize> {
380        let len = cmp::min(value.len(), i2c::I2C_SMBUS_BLOCK_MAX);
381        i2c::i2c_smbus_read_block_data(self.as_raw_fd(), command, &mut value[..len])
382    }
383
384    /// Write up to 32 bytes to the designated device register.
385    pub fn smbus_write_block_data(&mut self, command: u8, value: &[u8]) -> io::Result<()> {
386        i2c::i2c_smbus_write_block_data(self.as_raw_fd(), command, value)
387    }
388
389    /// Sends up to 31 bytes of data to the designated device register, and reads
390    /// up to 31 bytes in return.
391    ///
392    /// This was introduced in SMBus 2.0
393    pub fn smbus_block_process_call(&mut self, command: u8, write: &[u8], read: &mut [u8]) -> io::Result<usize> {
394        let read_len = cmp::min(read.len(), i2c::I2C_SMBUS_BLOCK_MAX);
395        i2c::i2c_smbus_block_process_call(self.as_raw_fd(), command, write, &mut read[..read_len])
396    }
397
398    /// Reads a block of bytes from the designated device register.
399    ///
400    /// Unlike smbus_read_block_data this does not receive a data length. This
401    /// is limited to 32 bytes due to the use of the Linux SMBus interface. Use
402    /// `i2c_transfer()` if more data is needed. `write()`+`read()` may also be
403    /// an option, though will produce an I2C STOP condition between the
404    /// transfers, which may be undesirable.
405    pub fn i2c_read_block_data(&mut self, command: u8, value: &mut [u8]) -> io::Result<usize> {
406        // Compatibility/emulation
407        if let Some(func) = self.update_functionality() {
408            if !func.contains(Functionality::SMBUS_READ_I2C_BLOCK) || value.len() > i2c::I2C_SMBUS_BLOCK_MAX {
409                if func.contains(Functionality::I2C) {
410                    if let Some(address) = self.address {
411                        let mut msgs = [
412                            Message::Write {
413                                address: address,
414                                data: &[command],
415                                flags: if self.address_10bit { WriteFlags::TENBIT_ADDR } else { WriteFlags::default() },
416                            },
417                            Message::Read {
418                                address: address,
419                                data: value,
420                                flags: if self.address_10bit { ReadFlags::TENBIT_ADDR } else { ReadFlags::default() },
421                            },
422                        ];
423                        return self.i2c_transfer(&mut msgs)
424                            .map(|_| msgs[1].len())
425                    }
426                }
427            }
428        }
429
430        let len = cmp::min(value.len(), i2c::I2C_SMBUS_BLOCK_MAX);
431        i2c::i2c_smbus_read_i2c_block_data(self.as_raw_fd(), command, &mut value[..len])
432    }
433
434    /// Writes a block of bytes from the designated device register.
435    ///
436    /// Unlike smbus_write_block_data this does not transfer the data length.
437    /// This is limited to 32 bytes due to the use of the Linux SMBus interface.
438    /// Use `i2c_transfer()` or `write()` instead if more data is needed.
439    pub fn i2c_write_block_data(&mut self, command: u8, value: &[u8]) -> io::Result<()> {
440        // Compatibility/emulation
441        if let Some(func) = self.update_functionality() {
442            if !func.contains(Functionality::SMBUS_WRITE_I2C_BLOCK) || value.len() > i2c::I2C_SMBUS_BLOCK_MAX {
443                if func.contains(Functionality::I2C) {
444                    if let Some(address) = self.address {
445                        let flags = if self.address_10bit { WriteFlags::TENBIT_ADDR } else { WriteFlags::default() };
446                        return if func.contains(Functionality::NO_START) {
447                            self.i2c_transfer(&mut [
448                                Message::Write {
449                                    address: address,
450                                    data: &[command],
451                                    flags: flags,
452                                },
453                                Message::Write {
454                                    address: address,
455                                    data: value,
456                                    flags: flags | WriteFlags::NO_START,
457                                },
458                            ])
459                        } else {
460                            self.i2c_transfer(&mut [
461                                Message::Write {
462                                    address: address,
463                                    data: &iter::once(command).chain(value.iter().cloned()).collect::<Vec<_>>(),
464                                    flags: flags,
465                                },
466                            ])
467                        }
468                    } else {
469                        // could also just use i2c_transfer, not much difference
470                    }
471                }
472            }
473        }
474
475        i2c::i2c_smbus_write_i2c_block_data(self.as_raw_fd(), command, value)
476    }
477}
478
479impl<I: Read> Read for I2c<I> {
480    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
481        self.inner.read(buf)
482    }
483}
484
485impl<I: Write> Write for I2c<I> {
486    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
487        self.inner.write(buf)
488    }
489
490    fn flush(&mut self) -> io::Result<()> {
491        self.inner.flush()
492    }
493}