tokio_i2c/
lib.rs

1// Copyright © 2018, 2025 Rouven Spreckels <rs@qu1x.dev>
2//
3// Usage of the works is permitted provided that
4// this instrument is retained with the works, so that
5// any entity that uses the works is notified of this instrument.
6//
7// DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
8
9//! Asynchronous I²C API adaptation for Tokio
10//!
11//! This module contains utility methods and adapter types for the operating
12//! system's I²C API, for use within (and only within) a Tokio runtime.
13//! Currently, only the [Linux I²C API] is supported.
14//!
15//! Tasks run by *worker* threads should not block, as this could delay
16//! servicing reactor events. Most operating system's I²C APIs are blocking,
17//! however. This module offers adapters which use a `blocking` annotation to
18//! inform the runtime that a blocking operation is required. When necessary,
19//! this allows the runtime to convert the current thread from a *worker* to a
20//! *backup* thread, where blocking is acceptable. This is the same approach as
21//! for the `tokio-fs` module.
22//!
23//! When the overhead of this asynchronization approach for many small I²C
24//! messages is a concern, consider to pack multiple I²C messages into a single
25//! I²C transfer or even to pack multiple I²C transfers into a single `Future`
26//! when appropriate, see `i2c_transfer` and `i2c_transfers`.
27//!
28//! [Linux I²C API]: https://www.kernel.org/doc/Documentation/i2c/dev-interface
29
30extern crate i2c_linux_sys;
31extern crate tokio;
32extern crate tokio_threadpool;
33#[macro_use]
34extern crate bitflags;
35#[macro_use]
36extern crate smallvec;
37
38use i2c_linux_sys::{
39    Flags, I2C_FUNC_10BIT_ADDR, I2C_FUNC_I2C, I2C_FUNC_NOSTART, I2C_FUNC_PROTOCOL_MANGLING,
40    I2C_FUNC_SLAVE, I2C_FUNC_SMBUS_BLOCK_DATA, I2C_FUNC_SMBUS_BLOCK_PROC_CALL, I2C_FUNC_SMBUS_BYTE,
41    I2C_FUNC_SMBUS_BYTE_DATA, I2C_FUNC_SMBUS_EMUL, I2C_FUNC_SMBUS_HOST_NOTIFY,
42    I2C_FUNC_SMBUS_I2C_BLOCK, I2C_FUNC_SMBUS_PEC, I2C_FUNC_SMBUS_PROC_CALL, I2C_FUNC_SMBUS_QUICK,
43    I2C_FUNC_SMBUS_READ_BLOCK_DATA, I2C_FUNC_SMBUS_READ_BYTE, I2C_FUNC_SMBUS_READ_BYTE_DATA,
44    I2C_FUNC_SMBUS_READ_I2C_BLOCK, I2C_FUNC_SMBUS_READ_WORD_DATA, I2C_FUNC_SMBUS_WORD_DATA,
45    I2C_FUNC_SMBUS_WRITE_BLOCK_DATA, I2C_FUNC_SMBUS_WRITE_BYTE, I2C_FUNC_SMBUS_WRITE_BYTE_DATA,
46    I2C_FUNC_SMBUS_WRITE_I2C_BLOCK, I2C_FUNC_SMBUS_WRITE_WORD_DATA, I2C_M_IGNORE_NAK,
47    I2C_M_NO_RD_ACK, I2C_M_NOSTART, I2C_M_RD, I2C_M_RECV_LEN, I2C_M_REV_DIR_ADDR, I2C_M_STOP,
48    I2C_RDWR_IOCTL_MAX_MSGS, I2C_SMBUS_BLOCK_MAX, i2c_get_functionality, i2c_msg, i2c_pec,
49    i2c_rdwr, i2c_set_retries, i2c_set_slave_address, i2c_set_slave_address_10bit,
50    i2c_set_timeout_ms, i2c_smbus_block_process_call, i2c_smbus_process_call,
51    i2c_smbus_read_block_data, i2c_smbus_read_byte, i2c_smbus_read_byte_data,
52    i2c_smbus_read_i2c_block_data, i2c_smbus_read_word_data, i2c_smbus_write_block_data,
53    i2c_smbus_write_byte, i2c_smbus_write_byte_data, i2c_smbus_write_i2c_block_data,
54    i2c_smbus_write_quick, i2c_smbus_write_word_data,
55};
56use smallvec::{Array, SmallVec};
57use tokio::prelude::{Async::*, *};
58
59use std::fs::{File, OpenOptions};
60use std::io::{
61    self,
62    ErrorKind::{UnexpectedEof, WouldBlock},
63    Read,
64};
65use std::mem::{MaybeUninit, transmute};
66use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
67use std::path::Path;
68use std::time::Duration;
69
70/// A "prelude" for users of the `tokio-i2c` crate.
71///
72/// This prelude is similar to the standard library's prelude in that you'll
73/// almost always want to import its entire contents, but unlike the standard
74/// library's prelude you'll have to do so manually:
75///
76/// ```
77/// use tokio_i2c::prelude::*;
78/// ```
79///
80/// The prelude may grow over time as additional items see ubiquitous use.
81pub mod prelude {
82    pub use super::{Functionality, Master, Message, MessageFlags, TEN_BIT};
83    pub use smallvec::SmallVec;
84    pub use std::time::Duration;
85    pub use tokio::prelude::*;
86}
87
88pub struct Message<A>
89where
90    A: Array<Item = u8> + Send + 'static,
91{
92    pub address: u16,
93    pub data: SmallVec<A>,
94    pub flags: MessageFlags,
95}
96
97impl<A> Message<A>
98where
99    A: Array<Item = u8> + Send + 'static,
100{
101    pub const fn is_read(&self) -> bool {
102        self.flags.contains(MessageFlags::READ)
103    }
104    pub const fn is_write(&self) -> bool {
105        !self.is_read()
106    }
107    fn as_i2c_msg(&mut self) -> i2c_msg {
108        let mut flags = Flags::from_bits_truncate(self.flags.bits());
109        if is_ten_bit(self.address) {
110            flags.insert(Flags::TEN);
111        }
112        i2c_msg {
113            addr: to_address(self.address),
114            flags,
115            len: u16::try_from(self.data.len()).expect("too large message data"),
116            buf: self.data.as_mut_ptr(),
117        }
118    }
119}
120
121bitflags! {
122    pub struct Functionality: u32 {
123        const I2C = I2C_FUNC_I2C;
124        const TEN_BIT_ADDR = I2C_FUNC_10BIT_ADDR;
125        const PROTOCOL_MANGLING = I2C_FUNC_PROTOCOL_MANGLING;
126        const SMBUS_PEC = I2C_FUNC_SMBUS_PEC;
127        const NO_START = I2C_FUNC_NOSTART;
128        const SLAVE = I2C_FUNC_SLAVE;
129        const SMBUS_BLOCK_PROC_CALL = I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
130        const SMBUS_QUICK = I2C_FUNC_SMBUS_QUICK;
131        const SMBUS_READ_BYTE = I2C_FUNC_SMBUS_READ_BYTE;
132        const SMBUS_WRITE_BYTE = I2C_FUNC_SMBUS_WRITE_BYTE;
133        const SMBUS_READ_BYTE_DATA = I2C_FUNC_SMBUS_READ_BYTE_DATA;
134        const SMBUS_WRITE_BYTE_DATA = I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
135        const SMBUS_READ_WORD_DATA = I2C_FUNC_SMBUS_READ_WORD_DATA;
136        const SMBUS_WRITE_WORD_DATA = I2C_FUNC_SMBUS_WRITE_WORD_DATA;
137        const SMBUS_PROC_CALL = I2C_FUNC_SMBUS_PROC_CALL;
138        const SMBUS_READ_BLOCK_DATA = I2C_FUNC_SMBUS_READ_BLOCK_DATA;
139        const SMBUS_WRITE_BLOCK_DATA = I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
140        const SMBUS_READ_I2C_BLOCK = I2C_FUNC_SMBUS_READ_I2C_BLOCK;
141        const SMBUS_WRITE_I2C_BLOCK = I2C_FUNC_SMBUS_WRITE_I2C_BLOCK;
142        const SMBUS_HOST_NOTIFY = I2C_FUNC_SMBUS_HOST_NOTIFY;
143        const SMBUS_BYTE = I2C_FUNC_SMBUS_BYTE;
144        const SMBUS_BYTE_DATA = I2C_FUNC_SMBUS_BYTE_DATA;
145        const SMBUS_WORD_DATA = I2C_FUNC_SMBUS_WORD_DATA;
146        const SMBUS_BLOCK_DATA = I2C_FUNC_SMBUS_BLOCK_DATA;
147        const SMBUS_I2C_BLOCK = I2C_FUNC_SMBUS_I2C_BLOCK;
148        const SMBUS_EMUL = I2C_FUNC_SMBUS_EMUL;
149    }
150}
151
152bitflags! {
153    #[derive(Default)]
154    pub struct MessageFlags: u16 {
155        const READ = I2C_M_RD;
156        const EXACT = EXACT;
157        const RECEIVE_LEN = I2C_M_RECV_LEN;
158        const NACK = I2C_M_NO_RD_ACK;
159        const IGNORE_NACK = I2C_M_IGNORE_NAK;
160        const REVERSE_RW = I2C_M_REV_DIR_ADDR;
161        const NO_START = I2C_M_NOSTART;
162        const STOP = I2C_M_STOP;
163    }
164}
165
166const EXACT: u16 = 0x0100;
167
168impl From<Functionality> for MessageFlags {
169    fn from(functionality: Functionality) -> Self {
170        let mut flags = Self::READ | Self::EXACT | Self::RECEIVE_LEN;
171        if functionality.contains(Functionality::PROTOCOL_MANGLING) {
172            flags.insert(Self::NACK);
173            flags.insert(Self::IGNORE_NACK);
174            flags.insert(Self::REVERSE_RW);
175            flags.insert(Self::STOP);
176        }
177        if functionality.contains(Functionality::NO_START) {
178            flags.insert(Self::NO_START);
179        }
180        flags
181    }
182}
183
184pub const TEN_BIT: u16 = 0xa000;
185
186const fn is_ten_bit(address: u16) -> bool {
187    address & TEN_BIT == TEN_BIT
188}
189
190const fn to_address(address: u16) -> u16 {
191    address & !TEN_BIT
192}
193
194pub struct Master<F>
195where
196    F: AsRawFd + Send + 'static,
197{
198    bus: F,
199    address: Option<u16>,
200    functionality: Functionality,
201}
202
203impl<F> Master<F>
204where
205    F: AsRawFd + Send + 'static,
206{
207    pub fn into_inner(self) -> F {
208        self.bus
209    }
210    pub const fn inner_ref(&self) -> &F {
211        &self.bus
212    }
213    pub const fn inner_mut(&mut self) -> &mut F {
214        &mut self.bus
215    }
216}
217
218impl<F> AsRawFd for Master<F>
219where
220    F: AsRawFd + Send + 'static,
221{
222    fn as_raw_fd(&self) -> RawFd {
223        self.bus.as_raw_fd()
224    }
225}
226
227impl<F> IntoRawFd for Master<F>
228where
229    F: AsRawFd + IntoRawFd + Send + 'static,
230{
231    fn into_raw_fd(self) -> RawFd {
232        self.bus.into_raw_fd()
233    }
234}
235
236impl Master<File> {
237    pub fn from_path<P>(path: P) -> impl Future<Item = Self, Error = io::Error> + Send + 'static
238    where
239        P: AsRef<Path> + Send + 'static,
240    {
241        FromPathFuture { path: Some(path) }
242    }
243}
244
245impl<F> Master<F>
246where
247    F: AsRawFd + Send + 'static,
248{
249    pub fn set_retries(
250        self,
251        retries: usize,
252    ) -> impl Future<Item = Self, Error = io::Error> + Send + 'static {
253        SetRetriesFuture {
254            item: Some(self),
255            retries,
256        }
257    }
258    pub fn set_timeout(
259        self,
260        duration: Duration,
261    ) -> impl Future<Item = Self, Error = io::Error> + Send + 'static {
262        SetTimeoutFuture {
263            item: Some(self),
264            duration,
265        }
266    }
267    pub fn set_slave_address(
268        self,
269        address: u16,
270    ) -> impl Future<Item = Self, Error = io::Error> + Send + 'static {
271        SetSlaveAddressFuture {
272            item: Some(self),
273            address,
274        }
275    }
276    pub const fn functionality(&self) -> Functionality {
277        self.functionality
278    }
279    pub fn transfer_flags(&self) -> MessageFlags {
280        self.functionality.into()
281    }
282    /// # Panics
283    ///
284    /// Panics for more messages than `I2C_RDWR_IOCTL_MAX_MSGS`.
285    pub fn transfer<A, M>(
286        self,
287        messages: SmallVec<M>,
288    ) -> impl Future<Item = (SmallVec<M>, Self), Error = io::Error> + Send + 'static
289    where
290        A: Array<Item = u8> + Send + 'static,
291        M: Array<Item = Message<A>> + Send + 'static,
292    {
293        assert!(messages.len() <= I2C_RDWR_IOCTL_MAX_MSGS);
294        TransferFuture {
295            item: Some((messages, self)),
296        }
297    }
298    /// # Panics
299    ///
300    /// Panics for more total messages than `I2C_RDWR_IOCTL_MAX_MSGS`.
301    pub fn transfers<A, M, T>(
302        self,
303        transfers: SmallVec<T>,
304    ) -> impl Future<Item = (SmallVec<T>, Self), Error = io::Error> + Send + 'static
305    where
306        A: Array<Item = u8> + Send + 'static,
307        M: Array<Item = Message<A>> + Send + 'static,
308        T: Array<Item = SmallVec<M>> + Send + 'static,
309    {
310        transfers
311            .iter()
312            .for_each(|messages| assert!(messages.len() <= I2C_RDWR_IOCTL_MAX_MSGS));
313        TransfersFuture {
314            item: Some((transfers, self)),
315        }
316    }
317    pub fn read_block_data<A>(
318        self,
319        command: u8,
320        data: SmallVec<A>,
321        exact: bool,
322    ) -> impl Future<Item = (SmallVec<A>, Self), Error = io::Error> + Send + 'static
323    where
324        A: Array<Item = u8> + Send + 'static,
325    {
326        ReadBlockDataFuture {
327            item: Some((data, self)),
328            command,
329            exact,
330        }
331    }
332    pub fn write_block_data<A>(
333        self,
334        command: u8,
335        data: SmallVec<A>,
336    ) -> impl Future<Item = Self, Error = io::Error> + Send + 'static
337    where
338        A: Array<Item = u8> + Send + 'static,
339    {
340        WriteBlockDataFuture {
341            item: Some((data, self)),
342            command,
343        }
344    }
345}
346
347impl<F> Master<F>
348where
349    F: AsRawFd + Read + Send + 'static,
350{
351    pub fn read<A>(
352        self,
353        data: SmallVec<A>,
354        exact: bool,
355    ) -> impl Future<Item = (SmallVec<A>, Self), Error = io::Error> + Send + 'static
356    where
357        A: Array<Item = u8> + Send + 'static,
358    {
359        ReadFuture {
360            item: Some((data, self)),
361            exact,
362        }
363    }
364}
365
366impl<F> Master<F>
367where
368    F: AsRawFd + Write + Send + 'static,
369{
370    pub fn write<A>(
371        self,
372        data: SmallVec<A>,
373        exact: bool,
374    ) -> impl Future<Item = (SmallVec<A>, Self), Error = io::Error> + Send + 'static
375    where
376        A: Array<Item = u8> + Send + 'static,
377    {
378        WriteFuture {
379            item: Some((data, self)),
380            exact,
381        }
382    }
383}
384
385impl<F> Master<F>
386where
387    F: AsRawFd + Send + 'static,
388{
389    /// Enables/Disables Packet Error Checking (PEC).
390    ///
391    /// A Packet Error Code (PEC) is appended at the end of each message
392    /// transfer by the device that supplied the last data byte, that excludes
393    /// `smbus_write_bit()`. An invalid PEC byte will not be acknowledged and
394    /// result in an `io::Error`.
395    ///
396    /// Available since version 1.1 of the `SMBus` specification.
397    pub fn smbus_set_pec(
398        self,
399        pec: bool,
400    ) -> impl Future<Item = Self, Error = io::Error> + Send + 'static {
401        SmbusSetPecFuture {
402            item: Some(self),
403            pec,
404        }
405    }
406    /// Writes a command/data `bit` at the place of the direction bit.
407    ///
408    /// No PEC byte will be appended, see `smbus_set_pec()`.
409    ///
410    /// ```text
411    /// S address bit [A] P
412    /// ```
413    pub fn smbus_write_bit(
414        self,
415        bit: bool,
416    ) -> impl Future<Item = Self, Error = io::Error> + Send + 'static {
417        SmbusWriteBitFuture {
418            item: Some(self),
419            bit,
420        }
421    }
422    /// Reads a command/data byte.
423    ///
424    /// ```text
425    /// S address R [A] [byte] N P
426    /// ```
427    pub fn smbus_read_byte(
428        self,
429    ) -> impl Future<Item = (u8, Self), Error = io::Error> + Send + 'static {
430        SmbusReadByteFuture { item: Some(self) }
431    }
432    /// Writes a command/data byte.
433    ///
434    /// ```text
435    /// S address W [A] byte [A] P
436    /// ```
437    pub fn smbus_write_byte(
438        self,
439        byte: u8,
440    ) -> impl Future<Item = Self, Error = io::Error> + Send + 'static {
441        SmbusWriteByteFuture {
442            item: Some(self),
443            byte,
444        }
445    }
446    /// Writes the `command` byte and reads a data byte.
447    ///
448    /// ```text
449    /// S address W [A] command  [A]
450    /// S address R [A]   [data]  N  P
451    /// ```
452    pub fn smbus_read_byte_data<A>(
453        self,
454        command: u8,
455    ) -> impl Future<Item = (u8, Self), Error = io::Error> + Send + 'static {
456        SmbusReadByteDataFuture {
457            item: Some(self),
458            command,
459        }
460    }
461    /// Writes the `command` byte and the `data` byte.
462    ///
463    /// ```text
464    /// S address W [A] command [A] [data] [A] P
465    /// ```
466    pub fn smbus_write_byte_data(
467        self,
468        command: u8,
469        data: u8,
470    ) -> impl Future<Item = Self, Error = io::Error> + Send + 'static {
471        SmbusWriteByteDataFuture {
472            item: Some(self),
473            command,
474            data,
475        }
476    }
477    /// Writes the `command` byte and reads a data word.
478    ///
479    /// A data word comprises a low and a high data byte in the order mentioned.
480    ///
481    /// ```text
482    /// S address W [A]   command  [A]
483    /// S address R [A] [data_low]  A  [data_high] N P
484    /// ```
485    pub fn smbus_read_word_data(
486        self,
487        command: u8,
488    ) -> impl Future<Item = (u16, Self), Error = io::Error> + Send + 'static {
489        SmbusReadWordDataFuture {
490            item: Some(self),
491            command,
492        }
493    }
494    /// Writes the `command` byte and the `data` word.
495    ///
496    /// A data word comprises a low and a high data byte in the order mentioned.
497    ///
498    /// ```text
499    /// S address W [A] command [A] data_low [A] data_high [A] P
500    /// ```
501    pub fn smbus_write_word_data(
502        self,
503        command: u8,
504        data: u16,
505    ) -> impl Future<Item = Self, Error = io::Error> + Send + 'static {
506        SmbusWriteWordDataFuture {
507            item: Some(self),
508            command,
509            data,
510        }
511    }
512    /// Writes the `command` byte and the `data` word and then reads a data word
513    /// in return.
514    ///
515    /// A data word comprises a low and a high data byte in the order mentioned.
516    ///
517    /// ```text
518    /// S address W [A] command [A]  data_low  [A]  data_high  [A]
519    /// S address R [A]             [data_low]  A  [data_high]  N  P
520    /// ```
521    pub fn smbus_process_call(
522        self,
523        command: u8,
524        data: u16,
525    ) -> impl Future<Item = (u16, Self), Error = io::Error> + Send + 'static {
526        SmbusProcessCallFuture {
527            item: Some(self),
528            command,
529            data,
530        }
531    }
532    /// Writes the `command` byte and reads a length byte followed by a `data`
533    /// block of that length.
534    ///
535    /// The data block length ranges from 1 to 32 bytes.
536    ///
537    /// ```text
538    /// S address W [A] command  [A]
539    /// S address R [A] [length]  A  [data#1] A ... [data#length] N P
540    /// ```
541    pub fn smbus_read_block_data<A>(
542        self,
543        command: u8,
544        data: SmallVec<A>,
545        exact: bool,
546    ) -> impl Future<Item = (SmallVec<A>, Self), Error = io::Error> + Send + 'static
547    where
548        A: Array<Item = u8> + Send + 'static,
549    {
550        SmbusReadBlockDataFuture {
551            item: Some((data, self)),
552            command,
553            exact,
554        }
555    }
556    /// Writes the `command` byte and a length byte followed by the `data` block
557    /// of that length.
558    ///
559    /// The data block length ranges from 1 to 32 bytes.
560    ///
561    /// ```text
562    /// S address W [A] command [A]
563    ///                  length [A] data#1 [A] ... data#length [A] P
564    /// ```
565    pub fn smbus_write_block_data<A>(
566        self,
567        command: u8,
568        data: SmallVec<A>,
569    ) -> impl Future<Item = Self, Error = io::Error> + Send + 'static
570    where
571        A: Array<Item = u8> + Send + 'static,
572    {
573        SmbusWriteBlockDataFuture {
574            item: Some((data, self)),
575            command,
576        }
577    }
578    /// Writes the `command` byte and a length byte followed by the `write_data`
579    /// block of that length and then reads a length byte followed by a
580    /// `read_data` block of that length in return.
581    ///
582    /// The data block length ranges from 1 to 32 bytes.
583    ///
584    /// Available since version 2.0 of the `SMBus` specification.
585    ///
586    /// ```text
587    /// S address W [A] command  [A]
588    ///                  length  [A]  data#1  [A] ...  data#length  [A]
589    /// S address R [A] [length]  A  [data#1]  A  ... [data#length]  N  P
590    /// ```
591    pub fn smbus_block_process_call<A, B>(
592        self,
593        command: u8,
594        write_data: SmallVec<A>,
595        read_data: SmallVec<B>,
596        exact: bool,
597    ) -> impl Future<Item = (SmallVec<B>, Self), Error = io::Error> + Send + 'static
598    where
599        A: Array<Item = u8> + Send + 'static,
600        B: Array<Item = u8> + Send + 'static,
601    {
602        SmbusBlockProcessCallFuture {
603            item: Some((write_data, read_data, self)),
604            command,
605            exact,
606        }
607    }
608}
609
610struct FromPathFuture<P>
611where
612    P: AsRef<Path> + Send + 'static,
613{
614    path: Option<P>,
615}
616
617impl<P> Future for FromPathFuture<P>
618where
619    P: AsRef<Path> + Send + 'static,
620{
621    type Item = Master<File>;
622    type Error = io::Error;
623
624    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
625        let path = self.path.take().expect(ERR_RESOLVED);
626        if let Ready(master) = blocking_io(|| {
627            let bus = OpenOptions::new().read(true).write(true).open(&path)?;
628            let bits = i2c_get_functionality(bus.as_raw_fd())?.bits();
629            Ok(Master {
630                bus,
631                address: None,
632                functionality: Functionality::from_bits_truncate(bits),
633            })
634        })? {
635            Ok(Ready(master))
636        } else {
637            self.path = Some(path);
638            Ok(NotReady)
639        }
640    }
641}
642
643struct SetRetriesFuture<F>
644where
645    F: AsRawFd + Send + 'static,
646{
647    item: Option<Master<F>>,
648    retries: usize,
649}
650
651impl<F> Future for SetRetriesFuture<F>
652where
653    F: AsRawFd + Send + 'static,
654{
655    type Item = Master<F>;
656    type Error = io::Error;
657
658    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
659        let master = self.item.take().expect(ERR_RESOLVED);
660        if blocking_io(|| i2c_set_retries(master.as_raw_fd(), self.retries))? == Ready(()) {
661            Ok(Ready(master))
662        } else {
663            self.item = Some(master);
664            Ok(NotReady)
665        }
666    }
667}
668
669struct SetTimeoutFuture<F>
670where
671    F: AsRawFd + Send + 'static,
672{
673    item: Option<Master<F>>,
674    duration: Duration,
675}
676
677impl<F> Future for SetTimeoutFuture<F>
678where
679    F: AsRawFd + Send + 'static,
680{
681    type Item = Master<F>;
682    type Error = io::Error;
683
684    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
685        let master = self.item.take().expect(ERR_RESOLVED);
686        if blocking_io(|| {
687            let duration = usize::try_from(self.duration.as_millis()).expect("too large duration");
688            i2c_set_timeout_ms(master.as_raw_fd(), duration)
689        })? == Ready(())
690        {
691            Ok(Ready(master))
692        } else {
693            self.item = Some(master);
694            Ok(NotReady)
695        }
696    }
697}
698
699struct SetSlaveAddressFuture<F>
700where
701    F: AsRawFd + Send + 'static,
702{
703    item: Option<Master<F>>,
704    address: u16,
705}
706
707impl<F> Future for SetSlaveAddressFuture<F>
708where
709    F: AsRawFd + Send + 'static,
710{
711    type Item = Master<F>;
712    type Error = io::Error;
713
714    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
715        let master = self.item.take().expect(ERR_RESOLVED);
716        if blocking_io(|| {
717            let address = to_address(self.address);
718            let ten_bit = is_ten_bit(self.address);
719            if master.address.is_some_and(is_ten_bit) != ten_bit {
720                i2c_set_slave_address_10bit(master.as_raw_fd(), ten_bit)?;
721            }
722            if master.address.map(to_address) != Some(address) {
723                i2c_set_slave_address(master.as_raw_fd(), address, false)?;
724            }
725            Ok(())
726        })? == Ready(())
727        {
728            Ok(Ready(master))
729        } else {
730            self.item = Some(master);
731            Ok(NotReady)
732        }
733    }
734}
735
736struct TransferFuture<F, A, M>
737where
738    F: AsRawFd + Send + 'static,
739    A: Array<Item = u8> + Send + 'static,
740    M: Array<Item = Message<A>>,
741{
742    item: Option<(SmallVec<M>, Master<F>)>,
743}
744
745impl<F, A, M> Future for TransferFuture<F, A, M>
746where
747    F: AsRawFd + Send + 'static,
748    A: Array<Item = u8> + Send + 'static,
749    M: Array<Item = Message<A>>,
750{
751    type Item = (SmallVec<M>, Master<F>);
752    type Error = io::Error;
753
754    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
755        let (mut messages, master) = self.item.take().expect(ERR_RESOLVED);
756        if blocking_io(|| i2c_transfer(master.as_raw_fd(), &mut messages))? == Ready(()) {
757            Ok(Ready((messages, master)))
758        } else {
759            self.item = Some((messages, master));
760            Ok(NotReady)
761        }
762    }
763}
764
765struct TransfersFuture<F, A, M, T>
766where
767    F: AsRawFd + Send + 'static,
768    A: Array<Item = u8> + Send + 'static,
769    M: Array<Item = Message<A>>,
770    T: Array<Item = SmallVec<M>>,
771{
772    item: Option<(SmallVec<T>, Master<F>)>,
773}
774
775impl<F, A, M, T> Future for TransfersFuture<F, A, M, T>
776where
777    F: AsRawFd + Send + 'static,
778    A: Array<Item = u8> + Send + 'static,
779    M: Array<Item = Message<A>>,
780    T: Array<Item = SmallVec<M>>,
781{
782    type Item = (SmallVec<T>, Master<F>);
783    type Error = io::Error;
784
785    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
786        let (mut transfers, master) = self.item.take().expect(ERR_RESOLVED);
787        if blocking_io(|| {
788            transfers
789                .iter_mut()
790                .try_for_each(|messages| i2c_transfer(master.as_raw_fd(), messages))
791        })? == Ready(())
792        {
793            Ok(Ready((transfers, master)))
794        } else {
795            self.item = Some((transfers, master));
796            Ok(NotReady)
797        }
798    }
799}
800
801struct ReadBlockDataFuture<F, A>
802where
803    F: AsRawFd + Send + 'static,
804    A: Array<Item = u8> + Send + 'static,
805{
806    item: Option<(SmallVec<A>, Master<F>)>,
807    command: u8,
808    exact: bool,
809}
810
811impl<F, A> Future for ReadBlockDataFuture<F, A>
812where
813    F: AsRawFd + Send + 'static,
814    A: Array<Item = u8> + Send + 'static,
815{
816    type Item = (SmallVec<A>, Master<F>);
817    type Error = io::Error;
818
819    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
820        let (mut data, master) = self.item.take().expect(ERR_RESOLVED);
821        if blocking_io(|| {
822            let functionality = master.functionality;
823            if functionality.contains(Functionality::I2C)
824                && (!functionality.contains(Functionality::SMBUS_READ_I2C_BLOCK)
825                    || data.len() > I2C_SMBUS_BLOCK_MAX)
826            {
827                if let Some(address) = master.address {
828                    let mut messages = SmallVec::<[Message<A>; 2]>::from_buf([
829                        Message {
830                            address,
831                            data: smallvec![self.command],
832                            flags: MessageFlags::empty(),
833                        },
834                        Message {
835                            address,
836                            data: data.clone(), // TODO
837                            flags: MessageFlags::READ,
838                        },
839                    ]);
840                    i2c_transfer(master.as_raw_fd(), &mut messages)?;
841                    data = messages.swap_remove(1).data;
842                    Ok(())
843                } else {
844                    Err(io::Error::other("No slave address set"))
845                }
846            } else {
847                data.truncate(I2C_SMBUS_BLOCK_MAX);
848                i2c_smbus_read_i2c_block_data(master.as_raw_fd(), self.command, &mut data).and_then(
849                    |len| {
850                        if self.exact && len != data.len() {
851                            Err(UnexpectedEof.into())
852                        } else {
853                            data.truncate(len);
854                            Ok(())
855                        }
856                    },
857                )
858            }
859        })? == Ready(())
860        {
861            Ok(Ready((data, master)))
862        } else {
863            self.item = Some((data, master));
864            Ok(NotReady)
865        }
866    }
867}
868
869struct WriteBlockDataFuture<F, A>
870where
871    F: AsRawFd + Send + 'static,
872    A: Array<Item = u8> + Send + 'static,
873{
874    item: Option<(SmallVec<A>, Master<F>)>,
875    command: u8,
876}
877
878impl<F, A> Future for WriteBlockDataFuture<F, A>
879where
880    F: AsRawFd + Send + 'static,
881    A: Array<Item = u8> + Send + 'static,
882{
883    type Item = Master<F>;
884    type Error = io::Error;
885
886    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
887        type Messages<A> = SmallVec<[Message<A>; 1]>;
888        let (data, master) = self.item.take().expect(ERR_RESOLVED);
889        if blocking_io(|| {
890            let functionality = master.functionality;
891            if functionality.contains(Functionality::I2C)
892                && (!functionality.contains(Functionality::SMBUS_READ_I2C_BLOCK)
893                    || data.len() > I2C_SMBUS_BLOCK_MAX)
894            {
895                if let Some(address) = master.address {
896                    if functionality.contains(Functionality::NO_START) {
897                        type Messages<A> = SmallVec<[Message<A>; 2]>;
898                        let mut messages = Messages::from_buf([
899                            Message {
900                                address,
901                                data: smallvec![self.command],
902                                flags: MessageFlags::empty(),
903                            },
904                            Message {
905                                address,
906                                data: data.clone(), // TODO
907                                flags: MessageFlags::NO_START,
908                            },
909                        ]);
910                        i2c_transfer(master.as_raw_fd(), &mut messages)?;
911                    } else {
912                        let mut command_data = SmallVec::<A>::new();
913                        command_data.push(self.command);
914                        command_data.copy_from_slice(&data);
915                        let mut messages = Messages::from_buf([Message {
916                            address,
917                            data: command_data,
918                            flags: MessageFlags::empty(),
919                        }]);
920                        i2c_transfer(master.as_raw_fd(), &mut messages)?;
921                    }
922                    Ok(())
923                } else {
924                    Err(io::Error::new(
925                        io::ErrorKind::InvalidInput,
926                        "No slave address set",
927                    ))
928                }
929            } else {
930                i2c_smbus_write_i2c_block_data(master.as_raw_fd(), self.command, &data)
931            }
932        })? == Ready(())
933        {
934            Ok(Ready(master))
935        } else {
936            self.item = Some((data, master));
937            Ok(NotReady)
938        }
939    }
940}
941
942fn i2c_transfer<A, M>(fd: RawFd, messages: &mut SmallVec<M>) -> io::Result<()>
943where
944    A: Array<Item = u8> + Send + 'static,
945    M: Array<Item = Message<A>>,
946{
947    let mut msgs = [MaybeUninit::<i2c_msg>::uninit(); I2C_RDWR_IOCTL_MAX_MSGS];
948    msgs.iter_mut()
949        .zip(messages.iter_mut())
950        .for_each(|(msg, message)| {
951            msg.write(message.as_i2c_msg());
952        });
953    let mut msgs = unsafe {
954        transmute::<
955            [MaybeUninit<i2c_msg>; I2C_RDWR_IOCTL_MAX_MSGS],
956            [i2c_msg; I2C_RDWR_IOCTL_MAX_MSGS],
957        >(msgs)
958    };
959    unsafe { i2c_rdwr(fd, &mut msgs[..messages.len()])? };
960    msgs.iter()
961        .zip(messages.iter_mut())
962        .try_for_each(|(msg, message)| {
963            if message
964                .flags
965                .contains(MessageFlags::READ | MessageFlags::EXACT)
966                && msg.len as usize != message.data.len()
967            {
968                Err(UnexpectedEof.into())
969            } else {
970                message.data.truncate(msg.len as usize);
971                Ok(())
972            }
973        })
974}
975
976struct ReadFuture<F, A>
977where
978    F: AsRawFd + Read + Send + 'static,
979    A: Array<Item = u8> + Send + 'static,
980{
981    item: Option<(SmallVec<A>, Master<F>)>,
982    exact: bool,
983}
984
985impl<F, A> Future for ReadFuture<F, A>
986where
987    F: AsRawFd + Read + Send + 'static,
988    A: Array<Item = u8> + Send + 'static,
989{
990    type Item = (SmallVec<A>, Master<F>);
991    type Error = io::Error;
992
993    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
994        let (mut data, mut master) = self.item.take().expect(ERR_RESOLVED);
995        if blocking_io(|| {
996            master.bus.read(&mut data).and_then(|len| {
997                if self.exact && len != data.len() {
998                    Err(UnexpectedEof.into())
999                } else {
1000                    data.truncate(len);
1001                    Ok(())
1002                }
1003            })
1004        })? == Ready(())
1005        {
1006            Ok(Ready((data, master)))
1007        } else {
1008            self.item = Some((data, master));
1009            Ok(NotReady)
1010        }
1011    }
1012}
1013
1014struct WriteFuture<F, A>
1015where
1016    F: AsRawFd + Write + Send + 'static,
1017    A: Array<Item = u8> + Send + 'static,
1018{
1019    item: Option<(SmallVec<A>, Master<F>)>,
1020    exact: bool,
1021}
1022
1023impl<F, A> Future for WriteFuture<F, A>
1024where
1025    F: AsRawFd + Write + Send + 'static,
1026    A: Array<Item = u8> + Send + 'static,
1027{
1028    type Item = (SmallVec<A>, Master<F>);
1029    type Error = io::Error;
1030
1031    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1032        let (mut data, mut master) = self.item.take().expect(ERR_RESOLVED);
1033        if blocking_io(|| {
1034            master.bus.write(data.as_mut_slice()).and_then(|len| {
1035                if self.exact && len != data.len() {
1036                    Err(UnexpectedEof.into())
1037                } else {
1038                    data.drain(..len).for_each(drop);
1039                    Ok(())
1040                }
1041            })
1042        })? == Ready(())
1043        {
1044            Ok(Ready((data, master)))
1045        } else {
1046            self.item = Some((data, master));
1047            Ok(NotReady)
1048        }
1049    }
1050}
1051
1052struct SmbusSetPecFuture<F>
1053where
1054    F: AsRawFd + Send + 'static,
1055{
1056    item: Option<Master<F>>,
1057    pec: bool,
1058}
1059
1060impl<F> Future for SmbusSetPecFuture<F>
1061where
1062    F: AsRawFd + Send + 'static,
1063{
1064    type Item = Master<F>;
1065    type Error = io::Error;
1066
1067    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1068        let master = self.item.take().expect(ERR_RESOLVED);
1069        if blocking_io(|| i2c_pec(master.as_raw_fd(), self.pec))? == Ready(()) {
1070            Ok(Ready(master))
1071        } else {
1072            self.item = Some(master);
1073            Ok(NotReady)
1074        }
1075    }
1076}
1077
1078struct SmbusWriteBitFuture<F>
1079where
1080    F: AsRawFd + Send + 'static,
1081{
1082    item: Option<Master<F>>,
1083    bit: bool,
1084}
1085
1086impl<F> Future for SmbusWriteBitFuture<F>
1087where
1088    F: AsRawFd + Send + 'static,
1089{
1090    type Item = Master<F>;
1091    type Error = io::Error;
1092
1093    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1094        let master = self.item.take().expect(ERR_RESOLVED);
1095        if blocking_io(|| {
1096            i2c_smbus_write_quick(
1097                master.as_raw_fd(),
1098                if self.bit {
1099                    i2c_linux_sys::SmbusReadWrite::Read
1100                } else {
1101                    i2c_linux_sys::SmbusReadWrite::Write
1102                },
1103            )
1104        })? == Ready(())
1105        {
1106            Ok(Ready(master))
1107        } else {
1108            self.item = Some(master);
1109            Ok(NotReady)
1110        }
1111    }
1112}
1113
1114struct SmbusReadByteFuture<F>
1115where
1116    F: AsRawFd + Send + 'static,
1117{
1118    item: Option<Master<F>>,
1119}
1120
1121impl<F> Future for SmbusReadByteFuture<F>
1122where
1123    F: AsRawFd + Send + 'static,
1124{
1125    type Item = (u8, Master<F>);
1126    type Error = io::Error;
1127
1128    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1129        let master = self.item.take().expect(ERR_RESOLVED);
1130        if let Ready(byte) = blocking_io(|| i2c_smbus_read_byte(master.as_raw_fd()))? {
1131            Ok(Ready((byte, master)))
1132        } else {
1133            self.item = Some(master);
1134            Ok(NotReady)
1135        }
1136    }
1137}
1138
1139struct SmbusWriteByteFuture<F>
1140where
1141    F: AsRawFd + Send + 'static,
1142{
1143    item: Option<Master<F>>,
1144    byte: u8,
1145}
1146
1147impl<F> Future for SmbusWriteByteFuture<F>
1148where
1149    F: AsRawFd + Send + 'static,
1150{
1151    type Item = Master<F>;
1152    type Error = io::Error;
1153
1154    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1155        let master = self.item.take().expect(ERR_RESOLVED);
1156        if blocking_io(|| i2c_smbus_write_byte(master.as_raw_fd(), self.byte))? == Ready(()) {
1157            Ok(Ready(master))
1158        } else {
1159            self.item = Some(master);
1160            Ok(NotReady)
1161        }
1162    }
1163}
1164
1165struct SmbusReadByteDataFuture<F>
1166where
1167    F: AsRawFd + Send + 'static,
1168{
1169    item: Option<Master<F>>,
1170    command: u8,
1171}
1172
1173impl<F> Future for SmbusReadByteDataFuture<F>
1174where
1175    F: AsRawFd + Send + 'static,
1176{
1177    type Item = (u8, Master<F>);
1178    type Error = io::Error;
1179
1180    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1181        let master = self.item.take().expect(ERR_RESOLVED);
1182        if let Ready(data) =
1183            blocking_io(|| i2c_smbus_read_byte_data(master.as_raw_fd(), self.command))?
1184        {
1185            Ok(Ready((data, master)))
1186        } else {
1187            self.item = Some(master);
1188            Ok(NotReady)
1189        }
1190    }
1191}
1192
1193struct SmbusWriteByteDataFuture<F>
1194where
1195    F: AsRawFd + Send + 'static,
1196{
1197    item: Option<Master<F>>,
1198    command: u8,
1199    data: u8,
1200}
1201
1202impl<F> Future for SmbusWriteByteDataFuture<F>
1203where
1204    F: AsRawFd + Send + 'static,
1205{
1206    type Item = Master<F>;
1207    type Error = io::Error;
1208
1209    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1210        let master = self.item.take().expect(ERR_RESOLVED);
1211        if blocking_io(|| i2c_smbus_write_byte_data(master.as_raw_fd(), self.command, self.data))?
1212            == Ready(())
1213        {
1214            Ok(Ready(master))
1215        } else {
1216            self.item = Some(master);
1217            Ok(NotReady)
1218        }
1219    }
1220}
1221
1222struct SmbusReadWordDataFuture<F>
1223where
1224    F: AsRawFd + Send + 'static,
1225{
1226    item: Option<Master<F>>,
1227    command: u8,
1228}
1229
1230impl<F> Future for SmbusReadWordDataFuture<F>
1231where
1232    F: AsRawFd + Send + 'static,
1233{
1234    type Item = (u16, Master<F>);
1235    type Error = io::Error;
1236
1237    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1238        let master = self.item.take().expect(ERR_RESOLVED);
1239        if let Ready(data) =
1240            blocking_io(|| i2c_smbus_read_word_data(master.as_raw_fd(), self.command))?
1241        {
1242            Ok(Ready((data, master)))
1243        } else {
1244            self.item = Some(master);
1245            Ok(NotReady)
1246        }
1247    }
1248}
1249
1250struct SmbusWriteWordDataFuture<F>
1251where
1252    F: AsRawFd + Send + 'static,
1253{
1254    item: Option<Master<F>>,
1255    command: u8,
1256    data: u16,
1257}
1258
1259impl<F> Future for SmbusWriteWordDataFuture<F>
1260where
1261    F: AsRawFd + Send + 'static,
1262{
1263    type Item = Master<F>;
1264    type Error = io::Error;
1265
1266    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1267        let master = self.item.take().expect(ERR_RESOLVED);
1268        if blocking_io(|| i2c_smbus_write_word_data(master.as_raw_fd(), self.command, self.data))?
1269            == Ready(())
1270        {
1271            Ok(Ready(master))
1272        } else {
1273            self.item = Some(master);
1274            Ok(NotReady)
1275        }
1276    }
1277}
1278
1279struct SmbusProcessCallFuture<F>
1280where
1281    F: AsRawFd + Send + 'static,
1282{
1283    item: Option<Master<F>>,
1284    command: u8,
1285    data: u16,
1286}
1287
1288impl<F> Future for SmbusProcessCallFuture<F>
1289where
1290    F: AsRawFd + Send + 'static,
1291{
1292    type Item = (u16, Master<F>);
1293    type Error = io::Error;
1294
1295    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1296        let master = self.item.take().expect(ERR_RESOLVED);
1297        if let Ready(data) =
1298            blocking_io(|| i2c_smbus_process_call(master.as_raw_fd(), self.command, self.data))?
1299        {
1300            Ok(Ready((data, master)))
1301        } else {
1302            self.item = Some(master);
1303            Ok(NotReady)
1304        }
1305    }
1306}
1307
1308struct SmbusReadBlockDataFuture<F, A>
1309where
1310    F: AsRawFd + Send + 'static,
1311    A: Array<Item = u8> + Send + 'static,
1312{
1313    item: Option<(SmallVec<A>, Master<F>)>,
1314    command: u8,
1315    exact: bool,
1316}
1317
1318impl<F, A> Future for SmbusReadBlockDataFuture<F, A>
1319where
1320    F: AsRawFd + Send + 'static,
1321    A: Array<Item = u8> + Send + 'static,
1322{
1323    type Item = (SmallVec<A>, Master<F>);
1324    type Error = io::Error;
1325
1326    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1327        let (mut data, master) = self.item.take().expect(ERR_RESOLVED);
1328        if blocking_io(|| {
1329            data.truncate(I2C_SMBUS_BLOCK_MAX);
1330            i2c_smbus_read_block_data(master.as_raw_fd(), self.command, &mut data).and_then(|len| {
1331                if self.exact && len != data.len() {
1332                    Err(UnexpectedEof.into())
1333                } else {
1334                    data.truncate(len);
1335                    Ok(())
1336                }
1337            })
1338        })? == Ready(())
1339        {
1340            Ok(Ready((data, master)))
1341        } else {
1342            self.item = Some((data, master));
1343            Ok(NotReady)
1344        }
1345    }
1346}
1347
1348struct SmbusWriteBlockDataFuture<F, A>
1349where
1350    F: AsRawFd + Send + 'static,
1351    A: Array<Item = u8> + Send + 'static,
1352{
1353    item: Option<(SmallVec<A>, Master<F>)>,
1354    command: u8,
1355}
1356
1357impl<F, A> Future for SmbusWriteBlockDataFuture<F, A>
1358where
1359    F: AsRawFd + Send + 'static,
1360    A: Array<Item = u8> + Send + 'static,
1361{
1362    type Item = Master<F>;
1363    type Error = io::Error;
1364
1365    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1366        let (data, master) = self.item.take().expect(ERR_RESOLVED);
1367        if blocking_io(|| i2c_smbus_write_block_data(master.as_raw_fd(), self.command, &data))?
1368            == Ready(())
1369        {
1370            Ok(Ready(master))
1371        } else {
1372            self.item = Some((data, master));
1373            Ok(NotReady)
1374        }
1375    }
1376}
1377
1378struct SmbusBlockProcessCallFuture<F, A, B>
1379where
1380    F: AsRawFd + Send + 'static,
1381    A: Array<Item = u8> + Send + 'static,
1382    B: Array<Item = u8> + Send + 'static,
1383{
1384    item: Option<(SmallVec<A>, SmallVec<B>, Master<F>)>,
1385    command: u8,
1386    exact: bool,
1387}
1388
1389impl<F, A, B> Future for SmbusBlockProcessCallFuture<F, A, B>
1390where
1391    F: AsRawFd + Send + 'static,
1392    A: Array<Item = u8> + Send + 'static,
1393    B: Array<Item = u8> + Send + 'static,
1394{
1395    type Item = (SmallVec<B>, Master<F>);
1396    type Error = io::Error;
1397
1398    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
1399        let (write_data, mut read_data, master) = self.item.take().expect(ERR_RESOLVED);
1400        if blocking_io(|| {
1401            read_data.truncate(I2C_SMBUS_BLOCK_MAX);
1402            i2c_smbus_block_process_call(
1403                master.as_raw_fd(),
1404                self.command,
1405                &write_data,
1406                &mut read_data,
1407            )
1408            .and_then(|len| {
1409                if self.exact && len != read_data.len() {
1410                    Err(UnexpectedEof.into())
1411                } else {
1412                    read_data.truncate(len);
1413                    Ok(())
1414                }
1415            })
1416        })? == Ready(())
1417        {
1418            Ok(Ready((read_data, master)))
1419        } else {
1420            self.item = Some((write_data, read_data, master));
1421            Ok(NotReady)
1422        }
1423    }
1424}
1425
1426fn blocking_io<F, T>(f: F) -> Poll<T, io::Error>
1427where
1428    F: FnOnce() -> io::Result<T>,
1429{
1430    match tokio_threadpool::blocking(f) {
1431        Ok(Ready(Ok(ok))) => Ok(ok.into()),
1432        Ok(Ready(Err(err))) => match err.kind() {
1433            WouldBlock => Ok(NotReady),
1434            _ => Err(err),
1435        },
1436        Ok(NotReady) => Ok(NotReady),
1437        Err(err) => Err(io::Error::other(err)),
1438    }
1439}
1440
1441const ERR_RESOLVED: &str = "I²C Future already resolved";