Skip to main content

rpi_pal/
i2c.rs

1//! Interface for the I2C peripheral.
2//!
3//! The Broadcom Serial Controller (BSC) peripheral controls a proprietary bus
4//! compliant with the I2C bus/interface. rpi-pal communicates with the BSC
5//! using the `i2cdev` device interface.
6//!
7//! ## I2C buses
8//!
9//! The Raspberry Pi 3 B+ and earlier models support three hardware I2C buses,
10//! however only the I2C bus on physical pins 3 and 5 should be used to communicate
11//! with slave devices. The other two buses are used internally as an HDMI
12//! interface, and for HAT identification.
13//!
14//! On the Raspberry Pi 4 B, 400 and 5, three additional I2C buses are available,
15//! depending on your configuration, as explained below.
16//!
17//! ### I2C0 / I2C1
18//!
19//! On the Raspberry Pi B Rev 1, physical pins 3 (SDA) and 5 (SCL) are tied to I2C0.
20//! On every other Raspberry Pi model, they're connected to I2C1.
21//!
22//! The I2C bus connected to these pins is disabled by
23//! default. You can enable it through `sudo raspi-config`, or by manually
24//! adding `dtparam=i2c_arm=on` to `/boot/firmware/config.txt`. Remember to reboot
25//! the Raspberry Pi afterwards.
26//!
27//! * SDA: BCM GPIO 2 (physical pin 3)
28//! * SCL: BCM GPIO 3 (physical pin 5)
29//!
30//! ### I2C3
31//!
32//! I2C3 can be enabled by adding `dtoverlay=i2c3` to `/boot/firmware/config.txt`.
33//!
34//! * SDA: BCM GPIO 4 (physical pin 7)
35//! * SCL: BCM GPIO 5 (physical pin 29)
36//!
37//! ### I2C4
38//!
39//! I2C4 can be enabled by adding `dtoverlay=i2c4` to `/boot/firmware/config.txt`.
40//!
41//! * SDA: BCM GPIO 8 (physical pin 24)
42//! * SCL: BCM GPIO 9 (physical pin 21)
43//!
44//! ### I2C5
45//!
46//! I2C5 can be enabled by adding `dtoverlay=i2c5` to `/boot/firmware/config.txt`.
47//!
48//! * SDA: BCM GPIO 12 (physical pin 32)
49//! * SCL: BCM GPIO 13 (physical pin 33)
50//!
51//! ### I2C6
52//!
53//! I2C6 can be enabled by adding `dtoverlay=i2c6` to `/boot/firmware/config.txt`.
54//!
55//! * SDA: BCM GPIO 22 (physical pin 15)
56//! * SCL: BCM GPIO 23 (physical pin 16)
57//!
58//! ### Alternative pins
59//!
60//! The GPIO pin numbers mentioned above are part of the default configuration.
61//! Some of their functionality can be moved to different pins. Read
62//! `/boot/overlays/README` for more information.
63//!
64//! ### Software I2C
65//!
66//! In addition to the hardware I2C buses, it's possible to configure a
67//! bit-banged software I2C bus on any available GPIO pins through the `i2c-gpio`
68//! device tree overlay. More details on enabling and configuring `i2c-gpio`
69//! can be found in `/boot/overlays/README`.
70//!
71//! ## Transmission speed
72//!
73//! The BSC supports I2C data transfer rates up to 400 kbit/s (Fast-mode).
74//!
75//! By default, the I2C bus clock speed is set to 100 kHz. Transferring
76//! 1 bit takes 1 clock cycle. You can change the
77//! transfer rate by adding `dtparam=i2c_arm_baudrate=X` to
78//! `/boot/firmware/config.txt`, where `X` should be replaced with the
79//! clock frequency in hertz (Hz). Remember to reboot
80//! the Raspberry Pi afterwards.
81//!
82//! ## Not supported
83//!
84//! Some I2C and SMBus features aren't fully supported by the `i2cdev` interface, the underlying driver or
85//! the BCM283x SoC: 10-bit slave addresses, SMBus Block Read, SMBus Block Process Call, SMBus Host Notify,
86//! SMBus Read/Write 32/64, and the SMBus Address Resolution Protocol.
87//!
88//! While clock stretching is supported, a bug exists in the implementation on the BCM283x SoC that will result
89//! in corrupted data when a slave device uses clock stretching at arbitrary points during the transfer.
90//! Clock stretching only works properly during read operations, directly after the ACK phase, when the additional
91//! delay is longer than half of a clock period. More information can be found [here](https://elinux.org/BCM2835_datasheet_errata#p35_I2C_clock_stretching).
92//!
93//! A possible workaround for slave devices that require clock stretching at other points during the transfer is
94//! to use a bit-banged software I2C bus by configuring the `i2c-gpio` device tree overlay as described in `/boot/overlays/README`.
95//!
96//! ## Troubleshooting
97//!
98//! ### Permission denied
99//!
100//! If [`new`] or [`with_bus`] returns an `io::ErrorKind::PermissionDenied`
101//! error, make sure the file permissions for `/dev/i2c-1` or `/dev/i2c-0`
102//! are correct, and the current user is a member of the `i2c` group.
103//!
104//! ### Timed out
105//!
106//! Transactions return an `io::ErrorKind::TimedOut` error when their duration
107//! exceeds the timeout value. You can change the timeout using [`set_timeout`].
108//!
109//! [`new`]: struct.I2c.html#method.new
110//! [`with_bus`]: struct.I2c.html#method.with_bus
111//! [`set_timeout`]: struct.I2c.html#method.set_timeout
112
113#![allow(dead_code)]
114
115use std::error;
116use std::fmt;
117use std::fs::{File, OpenOptions};
118use std::io;
119use std::io::{Read, Write};
120use std::marker::PhantomData;
121use std::os::unix::io::AsRawFd;
122use std::result;
123
124use libc::c_ulong;
125
126use crate::system;
127use crate::system::{DeviceInfo, Model};
128
129#[cfg(any(
130    feature = "embedded-hal-0",
131    feature = "embedded-hal",
132    feature = "embedded-hal-nb"
133))]
134mod hal;
135mod ioctl;
136
137pub use self::ioctl::Capabilities;
138
139/// Errors that can occur when accessing the I2C peripheral.
140#[derive(Debug)]
141pub enum Error {
142    /// I/O error.
143    Io(io::Error),
144    /// Invalid slave address.
145    ///
146    /// I2C supports 7-bit and 10-bit addresses. Several 7-bit addresses
147    /// can't be used as slave addresses.
148    InvalidSlaveAddress(u16),
149    /// I2C/SMBus feature not supported.
150    ///
151    /// The underlying drivers don't support the selected I2C feature or SMBus protocol.
152    FeatureNotSupported,
153    /// Unknown model.
154    ///
155    /// The Raspberry Pi model or SoC can't be identified. Support for
156    /// new models is usually added shortly after they are officially
157    /// announced and available to the public. Make sure you're using
158    /// the latest release of rpi-pal.
159    ///
160    /// You may also encounter this error if your Linux distribution
161    /// doesn't provide any of the common user-accessible system files
162    /// that are used to identify the model and SoC.
163    UnknownModel,
164}
165
166impl fmt::Display for Error {
167    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168        match *self {
169            Error::Io(ref err) => write!(f, "I/O error: {}", err),
170            Error::InvalidSlaveAddress(address) => write!(f, "Invalid slave address: {}", address),
171            Error::FeatureNotSupported => write!(f, "I2C/SMBus feature not supported"),
172            Error::UnknownModel => write!(f, "Unknown Raspberry Pi model"),
173        }
174    }
175}
176
177impl error::Error for Error {}
178
179impl From<io::Error> for Error {
180    fn from(err: io::Error) -> Error {
181        Error::Io(err)
182    }
183}
184
185impl From<system::Error> for Error {
186    fn from(_err: system::Error) -> Error {
187        Error::UnknownModel
188    }
189}
190
191/// Result type returned from methods that can have `i2c::Error`s.
192pub type Result<T> = result::Result<T, Error>;
193
194/// Provides access to the Raspberry Pi's I2C peripheral.
195///
196/// Before using `I2c`, make sure your Raspberry Pi has the necessary I2C buses
197/// enabled. More information can be found [here].
198///
199/// Besides basic I2C communication through buffer reads and writes, `I2c` can
200/// also be used with devices that require SMBus (System Management Bus) support.
201/// SMBus is based on I2C, and defines more structured message transactions
202/// through its various protocols. More details can be found in the latest SMBus
203/// [specification].
204///
205/// The `embedded-hal` trait implementations for `I2c` can be enabled by specifying
206/// the optional `hal` feature in the dependency declaration for the `rpi_pal` crate.
207///
208/// [here]: index.html#i2c-buses
209/// [specification]: http://smbus.org/specs/SMBus_3_1_20180319.pdf
210#[derive(Debug)]
211pub struct I2c {
212    bus: u8,
213    funcs: Capabilities,
214    i2cdev: File,
215    addr_10bit: bool,
216    address: u16,
217    // The not_sync field is a workaround to force !Sync. I2c isn't safe for
218    // Sync because of ioctl() and the underlying drivers. This avoids needing
219    // #![feature(optin_builtin_traits)] to manually add impl !Sync for I2c.
220    not_sync: PhantomData<*const ()>,
221}
222
223impl I2c {
224    /// Constructs a new `I2c`.
225    ///
226    /// `new` attempts to identify which I2C bus is bound to physical pins 3 (SDA)
227    /// and 5 (SCL) based on the Raspberry Pi model.
228    ///
229    /// More information on configuring the I2C buses can be found [here].
230    ///
231    /// [here]: index.html#i2c-buses
232    pub fn new() -> Result<I2c> {
233        match DeviceInfo::new()?.model() {
234            // Pi B Rev 1 uses I2C0
235            Model::RaspberryPiBRev1 => I2c::with_bus(0),
236            _ => {
237                // Pi 4B or later could have I2C3 enabled on pins 3 and 5
238                I2c::with_bus(1).or_else(|_| I2c::with_bus(3))
239            }
240        }
241    }
242
243    /// Constructs a new `I2c` using the specified bus.
244    ///
245    /// `bus` indicates the selected I2C bus. You'll typically want to select the
246    /// bus that's bound to physical pins 3 (SDA) and 5 (SCL). On the Raspberry
247    /// Pi B Rev 1, those pins are tied to bus 0. On every other Raspberry
248    /// Pi model, they're connected to bus 1. Additional I2C buses are available
249    /// on the Raspberry Pi 4 B, 400 and 5.
250    ///
251    /// More information on configuring the I2C buses can be found [here].
252    ///
253    /// [here]: index.html#i2c-buses
254    pub fn with_bus(bus: u8) -> Result<I2c> {
255        // bus is a u8, because any 8-bit bus ID could potentially
256        // be configured for bit banging I2C using i2c-gpio.
257        let i2cdev = OpenOptions::new()
258            .read(true)
259            .write(true)
260            .open(format!("/dev/i2c-{}", bus))?;
261
262        let capabilities = ioctl::funcs(i2cdev.as_raw_fd())?;
263
264        // Disable 10-bit addressing if it's supported
265        if capabilities.addr_10bit() {
266            ioctl::set_addr_10bit(i2cdev.as_raw_fd(), 0)?;
267        }
268
269        // Disable PEC if it's supported
270        if capabilities.smbus_pec() {
271            ioctl::set_pec(i2cdev.as_raw_fd(), 0)?;
272        }
273
274        Ok(I2c {
275            bus,
276            funcs: capabilities,
277            i2cdev,
278            addr_10bit: false,
279            address: 0,
280            not_sync: PhantomData,
281        })
282    }
283
284    /// Returns information on the functionality supported by the underlying drivers.
285    ///
286    /// The returned [`Capabilities`] instance lists the available
287    /// I2C and SMBus features.
288    ///
289    /// [`Capabilities`]: struct.Capabilities.html
290    pub fn capabilities(&self) -> Capabilities {
291        self.funcs
292    }
293
294    /// Returns the I2C bus ID.
295    pub fn bus(&self) -> u8 {
296        self.bus
297    }
298
299    /// Returns the clock frequency in hertz (Hz).
300    pub fn clock_speed(&self) -> Result<u32> {
301        let mut buffer = [0u8; 4];
302
303        File::open(format!(
304            "/sys/class/i2c-adapter/i2c-{}/of_node/clock-frequency",
305            self.bus
306        ))?
307        .read_exact(&mut buffer)?;
308
309        Ok(u32::from(buffer[3])
310            | (u32::from(buffer[2]) << 8)
311            | (u32::from(buffer[1]) << 16)
312            | (u32::from(buffer[0]) << 24))
313    }
314
315    /// Sets a 7-bit or 10-bit slave address.
316    ///
317    /// `slave_address` refers to the slave device you're communicating with.
318    /// The specified address shouldn't include the R/W bit.
319    ///
320    /// By default, 10-bit addressing is disabled, which means
321    /// `set_slave_address` only accepts 7-bit addresses. 10-bit addressing
322    /// can be enabled with [`set_addr_10bit`]. Note that setting a 7-bit
323    /// address when 10-bit addressing is enabled won't correctly target a
324    /// slave device that doesn't support 10-bit addresses.
325    ///
326    /// [`set_addr_10bit`]: #method.set_addr_10bit
327    pub fn set_slave_address(&mut self, slave_address: u16) -> Result<()> {
328        // Filter out invalid and unsupported addresses
329        if (!self.addr_10bit && ((slave_address >> 3) == 0b1111 || slave_address > 0x7F))
330            || (self.addr_10bit && slave_address > 0x03FF)
331        {
332            return Err(Error::InvalidSlaveAddress(slave_address));
333        }
334
335        ioctl::set_slave_address(self.i2cdev.as_raw_fd(), c_ulong::from(slave_address))?;
336
337        self.address = slave_address;
338
339        Ok(())
340    }
341
342    /// Sets the maximum duration of a transaction in milliseconds (ms).
343    ///
344    /// Transactions that take longer than `timeout` return an
345    /// `io::ErrorKind::TimedOut` error.
346    ///
347    /// `timeout` has a resolution of 10ms.
348    pub fn set_timeout(&self, timeout: u32) -> Result<()> {
349        // Contrary to the i2cdev documentation, this seems to
350        // be used as a timeout for (part of?) the I2C transaction.
351        ioctl::set_timeout(self.i2cdev.as_raw_fd(), timeout as c_ulong)?;
352
353        Ok(())
354    }
355
356    fn set_retries(&self, retries: u32) -> Result<()> {
357        // Set to private. While i2cdev implements retries, the underlying drivers don't.
358        ioctl::set_retries(self.i2cdev.as_raw_fd(), retries as c_ulong)?;
359
360        Ok(())
361    }
362
363    /// Enables or disables 10-bit addressing.
364    ///
365    /// 10-bit addressing currently isn't supported on the Raspberry Pi. `set_addr_10bit` returns
366    /// `Err(`[`Error::FeatureNotSupported`]`)` unless underlying driver support is detected.
367    ///
368    /// By default, `addr_10bit` is set to `false`.
369    ///
370    /// [`Error::FeatureNotSupported`]: enum.Error.html#variant.FeatureNotSupported
371    pub fn set_addr_10bit(&mut self, addr_10bit: bool) -> Result<()> {
372        if !self.capabilities().addr_10bit() {
373            return Err(Error::FeatureNotSupported);
374        }
375
376        ioctl::set_addr_10bit(self.i2cdev.as_raw_fd(), addr_10bit as c_ulong)?;
377
378        self.addr_10bit = addr_10bit;
379
380        Ok(())
381    }
382
383    /// Receives incoming data from the slave device and writes it to `buffer`.
384    ///
385    /// `read` reads as many bytes as can fit in `buffer`.
386    ///
387    /// Sequence: START → Address + Read Bit → Incoming Bytes → STOP
388    ///
389    /// Returns how many bytes were read.
390    pub fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
391        Ok(self.i2cdev.read(buffer)?)
392    }
393
394    /// Sends the outgoing data contained in `buffer` to the slave device.
395    ///
396    /// Sequence: START → Address + Write Bit → Outgoing Bytes → STOP
397    ///
398    /// Returns how many bytes were written.
399    pub fn write(&mut self, buffer: &[u8]) -> Result<usize> {
400        Ok(self.i2cdev.write(buffer)?)
401    }
402
403    /// Sends the outgoing data contained in `write_buffer` to the slave device, and
404    /// then fills `read_buffer` with incoming data.
405    ///
406    /// Compared to calling [`write`] and [`read`] separately, `write_read` doesn't
407    /// issue a STOP condition in between the write and read operation. A repeated
408    /// START is sent instead.
409    ///
410    /// `write_read` reads as many bytes as can fit in `read_buffer`. The maximum
411    /// number of bytes in either `write_buffer` or `read_buffer` can't exceed 8192.
412    ///
413    /// Sequence: START → Address + Write Bit → Outgoing Bytes → Repeated START →
414    /// Address + Read Bit → Incoming Bytes → STOP
415    ///
416    /// [`write`]: #method.write
417    /// [`read`]: #method.read
418    pub fn write_read(&self, write_buffer: &[u8], read_buffer: &mut [u8]) -> Result<()> {
419        ioctl::i2c_write_read(
420            self.i2cdev.as_raw_fd(),
421            self.address,
422            self.addr_10bit,
423            write_buffer,
424            read_buffer,
425        )?;
426
427        Ok(())
428    }
429
430    /// Sends an 8-bit `command`, and then fills a multi-byte `buffer` with
431    /// incoming data.
432    ///
433    /// `block_read` can read a maximum of 32 bytes.
434    ///
435    /// Although `block_read` isn't part of the SMBus protocol, it uses the
436    /// SMBus functionality to offer this commonly used I2C transaction format.
437    /// The difference between `block_read` and [`smbus_block_read`] is that the
438    /// latter also expects a byte count from the slave device.
439    ///
440    /// Sequence: START → Address + Write Bit → Command → Repeated START
441    /// → Address + Read Bit → Incoming Bytes → STOP
442    ///
443    /// [`smbus_block_read`]: #method.smbus_block_read
444    pub fn block_read(&self, command: u8, buffer: &mut [u8]) -> Result<()> {
445        ioctl::i2c_block_read(self.i2cdev.as_raw_fd(), command, buffer)?;
446
447        Ok(())
448    }
449
450    /// Sends an 8-bit `command` followed by a multi-byte `buffer`.
451    ///
452    /// `block_write` can write a maximum of 32 bytes. Any additional data contained
453    /// in `buffer` is ignored.
454    ///
455    /// Although `block_write` isn't part of the SMBus protocol, it uses the
456    /// SMBus functionality to offer this commonly used I2C transaction format. The
457    /// difference between `block_write` and [`smbus_block_write`] is that the latter
458    /// also sends a byte count to the slave device.
459    ///
460    /// Sequence: START → Address + Write Bit → Command → Outgoing Bytes → STOP
461    ///
462    /// [`smbus_block_write`]: #method.smbus_block_write
463    pub fn block_write(&self, command: u8, buffer: &[u8]) -> Result<()> {
464        ioctl::i2c_block_write(self.i2cdev.as_raw_fd(), command, buffer)?;
465
466        Ok(())
467    }
468
469    // Note: smbus_read/write_32/64 could theoretically be emulated using block_read/write
470    // provided the PEC value is calculated in software
471
472    /// Sends a 1-bit `command` in place of the R/W bit.
473    ///
474    /// Sequence: START → Address + Command Bit → STOP
475    pub fn smbus_quick_command(&self, command: bool) -> Result<()> {
476        ioctl::smbus_quick_command(self.i2cdev.as_raw_fd(), command)?;
477
478        Ok(())
479    }
480
481    /// Receives an 8-bit value.
482    ///
483    /// Sequence: START → Address + Read Bit → Incoming Byte → STOP
484    pub fn smbus_receive_byte(&self) -> Result<u8> {
485        Ok(ioctl::smbus_receive_byte(self.i2cdev.as_raw_fd())?)
486    }
487
488    /// Sends an 8-bit `value`.
489    ///
490    /// Sequence: START → Address + Write Bit → Outgoing Byte → STOP
491    pub fn smbus_send_byte(&self, value: u8) -> Result<()> {
492        ioctl::smbus_send_byte(self.i2cdev.as_raw_fd(), value)?;
493
494        Ok(())
495    }
496
497    /// Sends an 8-bit `command`, and receives an 8-bit value.
498    ///
499    /// Sequence: START → Address + Write Bit → Command → Repeated START
500    /// → Address + Read Bit → Incoming Byte → STOP
501    pub fn smbus_read_byte(&self, command: u8) -> Result<u8> {
502        Ok(ioctl::smbus_read_byte(self.i2cdev.as_raw_fd(), command)?)
503    }
504
505    /// Sends an 8-bit `command` and an 8-bit `value`.
506    ///
507    /// Sequence: START → Address + Write Bit → Command → Outgoing Byte → STOP
508    pub fn smbus_write_byte(&self, command: u8, value: u8) -> Result<()> {
509        ioctl::smbus_write_byte(self.i2cdev.as_raw_fd(), command, value)?;
510
511        Ok(())
512    }
513
514    /// Sends an 8-bit `command`, and receives a 16-bit value.
515    ///
516    /// Based on the SMBus protocol definition, the first byte received is
517    /// stored as the low byte of the 16-bit value, and the second byte as
518    /// the high byte. Some devices may require you to swap these bytes. In those
519    /// cases you can use the convenience method [`smbus_read_word_swapped`] instead.
520    ///
521    /// Sequence: START → Address + Write Bit → Command → Repeated START
522    /// → Address + Read Bit → Incoming Byte Low → Incoming Byte High → STOP
523    ///
524    /// [`smbus_read_word_swapped`]: #method.smbus_read_word_swapped
525    pub fn smbus_read_word(&self, command: u8) -> Result<u16> {
526        Ok(ioctl::smbus_read_word(self.i2cdev.as_raw_fd(), command)?)
527    }
528
529    /// Sends an 8-bit `command`, and receives a 16-bit `value` in a non-standard swapped byte order.
530    ///
531    /// `smbus_read_word_swapped` is a convenience method that works similarly to [`smbus_read_word`],
532    /// but reverses the byte order of the incoming 16-bit value. The high byte is received first,
533    /// and the low byte second.
534    ///
535    /// Sequence: START → Address + Write Bit → Command → Repeated START
536    /// → Address + Read Bit → Incoming Byte High → Incoming Byte Low → STOP
537    ///
538    /// [`smbus_read_word`]: #method.smbus_read_word
539    pub fn smbus_read_word_swapped(&self, command: u8) -> Result<u16> {
540        let value = ioctl::smbus_read_word(self.i2cdev.as_raw_fd(), command)?;
541
542        Ok(((value & 0xFF00) >> 8) | ((value & 0xFF) << 8))
543    }
544
545    /// Sends an 8-bit `command` and a 16-bit `value`.
546    ///
547    /// Based on the SMBus protocol definition, the first byte sent is the low byte
548    /// of the 16-bit value, and the second byte is the high byte. Some devices may
549    /// require you to swap these bytes. In those cases you can use the convenience method
550    /// [`smbus_write_word_swapped`] instead.
551    ///
552    /// Sequence: START → Address + Write Bit → Command → Outgoing Byte Low → Outgoing Byte High → STOP
553    ///
554    /// [`smbus_write_word_swapped`]: #method.smbus_write_word_swapped
555    pub fn smbus_write_word(&self, command: u8, value: u16) -> Result<()> {
556        ioctl::smbus_write_word(self.i2cdev.as_raw_fd(), command, value)?;
557
558        Ok(())
559    }
560
561    /// Sends an 8-bit `command` and a 16-bit `value` in a non-standard swapped byte order.
562    ///
563    /// `smbus_write_word_swapped` is a convenience method that works similarly to [`smbus_write_word`], but reverses the byte
564    /// order of the outgoing 16-bit value. The high byte is sent first, and the low byte second.
565    ///
566    /// Sequence: START → Address + Write Bit → Command → Outgoing Byte High → Outgoing Byte Low → STOP
567    ///
568    /// [`smbus_write_word`]: #method.smbus_write_word
569    pub fn smbus_write_word_swapped(&self, command: u8, value: u16) -> Result<()> {
570        ioctl::smbus_write_word(
571            self.i2cdev.as_raw_fd(),
572            command,
573            ((value & 0xFF00) >> 8) | ((value & 0xFF) << 8),
574        )?;
575
576        Ok(())
577    }
578
579    /// Sends an 8-bit `command` and a 16-bit `value`, and then receives a 16-bit value in response.
580    ///
581    /// Based on the SMBus protocol definition, for both the outgoing and incoming 16-bit value,
582    /// the first byte transferred is the low byte of the 16-bit value, and the second byte is the
583    /// high byte. Some devices may require you to swap these bytes. In those cases you can use the
584    /// convenience method [`smbus_process_call_swapped`] instead.
585    ///
586    /// Sequence: START → Address + Write Bit → Command → Outgoing Byte Low →
587    /// Outgoing Byte High → Repeated START → Address + Read Bit → Incoming Byte Low →
588    /// Incoming Byte High → STOP
589    ///
590    /// [`smbus_process_call_swapped`]: #method.smbus_process_call_swapped
591    pub fn smbus_process_call(&self, command: u8, value: u16) -> Result<u16> {
592        Ok(ioctl::smbus_process_call(
593            self.i2cdev.as_raw_fd(),
594            command,
595            value,
596        )?)
597    }
598
599    /// Sends an 8-bit `command` and a 16-bit `value`, and then receives a 16-bit value in response, in
600    /// a non-standard byte order.
601    ///
602    /// `smbus_process_call_swapped` is a convenience method that works similarly to [`smbus_process_call`],
603    /// but reverses the byte order of the outgoing and incoming 16-bit value. The high byte is transferred
604    /// first, and the low byte second.
605    ///
606    /// Sequence: START → Address + Write Bit → Command → Outgoing Byte High →
607    /// Outgoing Byte Low → Repeated START → Address + Read Bit → Incoming Byte High →
608    /// Incoming Byte Low → STOP
609    ///
610    /// [`smbus_process_call`]: #method.smbus_process_call
611    pub fn smbus_process_call_swapped(&self, command: u8, value: u16) -> Result<u16> {
612        let response = ioctl::smbus_process_call(
613            self.i2cdev.as_raw_fd(),
614            command,
615            ((value & 0xFF00) >> 8) | ((value & 0xFF) << 8),
616        )?;
617
618        Ok(((response & 0xFF00) >> 8) | ((response & 0xFF) << 8))
619    }
620
621    /// Sends an 8-bit `command`, and then receives an 8-bit byte count along with a
622    /// multi-byte `buffer`.
623    ///
624    /// `smbus_block_read` currently isn't supported on the Raspberry Pi, and returns
625    /// `Err(`[`Error::FeatureNotSupported`]`)` unless underlying driver support is
626    /// detected. You might be able to emulate the `smbus_block_read` functionality
627    /// with [`write_read`], [`block_read`] or [`read`] provided the length of the
628    /// expected incoming data is known beforehand, or the slave device allows the
629    /// master to read more data than it needs to send.
630    ///
631    /// `smbus_block_read` can read a maximum of 32 bytes.
632    ///
633    /// Sequence: START → Address + Write Bit → Command → Repeated START →
634    /// Address + Read Bit → Incoming Byte Count → Incoming Bytes → STOP
635    ///
636    /// Returns how many bytes were read.
637    ///
638    /// [`Error::FeatureNotSupported`]: enum.Error.html#variant.FeatureNotSupported
639    /// [`write_read`]: #method.write_read
640    /// [`block_read`]: #method.block_read
641    /// [`read`]: #method.read
642    pub fn smbus_block_read(&self, command: u8, buffer: &mut [u8]) -> Result<usize> {
643        if !self.capabilities().smbus_block_read() {
644            return Err(Error::FeatureNotSupported);
645        }
646
647        Ok(ioctl::smbus_block_read(
648            self.i2cdev.as_raw_fd(),
649            command,
650            buffer,
651        )?)
652    }
653
654    /// Sends an 8-bit `command` and an 8-bit byte count along with a multi-byte `buffer`.
655    ///
656    /// `smbus_block_write` can write a maximum of 32 bytes. Any additional data contained
657    /// in `buffer` is ignored.
658    ///
659    /// Sequence: START → Address + Write Bit → Command → Outgoing Byte Count
660    /// → Outgoing Bytes → STOP
661    pub fn smbus_block_write(&self, command: u8, buffer: &[u8]) -> Result<()> {
662        ioctl::smbus_block_write(self.i2cdev.as_raw_fd(), command, buffer)?;
663
664        Ok(())
665    }
666
667    /// Enables or disables SMBus Packet Error Checking.
668    ///
669    /// Packet Error Checking inserts a CRC-8 Packet Error Code (PEC) byte before each STOP
670    /// condition for all SMBus protocols, except Quick Command and Host Notify.
671    ///
672    /// The PEC is calculated on all message bytes except the START, STOP, ACK and NACK bits.
673    ///
674    /// By default, `pec` is set to `false`.
675    pub fn set_smbus_pec(&self, pec: bool) -> Result<()> {
676        ioctl::set_pec(self.i2cdev.as_raw_fd(), pec as c_ulong)?;
677
678        Ok(())
679    }
680}
681
682// Send is safe for I2c, but we're marked !Send because of the dummy pointer that's
683// needed to force !Sync.
684unsafe impl Send for I2c {}