i2cdev/
core.rs

1// Copyright 2015, Paul Osborne <osbpau@gmail.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/license/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option.  This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use byteorder::{ByteOrder, LittleEndian};
10use std::error::Error;
11
12/// Interface to an I2C Slave Device from an I2C Master
13///
14/// Typical implementations will store state with references to the bus
15/// in use and the address of the slave device.  The trait is based on the
16/// Linux i2cdev interface.
17pub trait I2CDevice {
18    /// Error type
19    type Error: Error;
20
21    /// Read data from the device to fill the provided slice
22    fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error>;
23
24    /// Write the provided buffer to the device
25    fn write(&mut self, data: &[u8]) -> Result<(), Self::Error>;
26
27    /// This sends a single bit to the device, at the place of the Rd/Wr bit
28    fn smbus_write_quick(&mut self, bit: bool) -> Result<(), Self::Error>;
29
30    /// Read a single byte from a device, without specifying a device register
31    ///
32    /// Some devices are so simple that this interface is enough; for
33    /// others, it is a shorthand if you want to read the same register as in
34    /// the previous SMBus command.
35    fn smbus_read_byte(&mut self) -> Result<u8, Self::Error> {
36        let mut buf = [0_u8];
37        self.read(&mut buf)?;
38        Ok(buf[0])
39    }
40
41    /// Write a single byte to a device, without specifying a device register
42    ///
43    /// This is the opposite operation as smbus_read_byte.  As with read_byte,
44    /// no register is specified.
45    fn smbus_write_byte(&mut self, value: u8) -> Result<(), Self::Error> {
46        self.write(&[value])
47    }
48
49    /// Read a single byte from a device, from a designated register
50    ///
51    /// The register is specified through the Comm byte.
52    fn smbus_read_byte_data(&mut self, register: u8) -> Result<u8, Self::Error> {
53        self.smbus_write_byte(register)?;
54        self.smbus_read_byte()
55    }
56
57    /// Write a single byte to a specific register on a device
58    ///
59    /// The register is specified through the Comm byte.
60    fn smbus_write_byte_data(&mut self, register: u8, value: u8) -> Result<(), Self::Error> {
61        self.write(&[register, value])
62    }
63
64    /// Read 2 bytes from a given register on a device (lsb first)
65    fn smbus_read_word_data(&mut self, register: u8) -> Result<u16, Self::Error> {
66        let mut buf: [u8; 2] = [0x00; 2];
67        self.smbus_write_byte(register)?;
68        self.read(&mut buf)?;
69        Ok(LittleEndian::read_u16(&buf))
70    }
71
72    /// Write 2 bytes to a given register on a device (lsb first)
73    fn smbus_write_word_data(&mut self, register: u8, value: u16) -> Result<(), Self::Error> {
74        let mut buf: [u8; 3] = [register, 0, 0];
75        LittleEndian::write_u16(&mut buf[1..], value);
76        self.write(&buf)
77    }
78
79    /// Select a register, send 16 bits of data to it, and read 16 bits of data
80    fn smbus_process_word(&mut self, register: u8, value: u16) -> Result<u16, Self::Error> {
81        let mut buf: [u8; 2] = [0x00; 2];
82        self.smbus_write_word_data(register, value)?;
83        self.read(&mut buf)?;
84        Ok(LittleEndian::read_u16(&buf))
85    }
86
87    /// Read a block of up to 32 bytes from a device
88    ///
89    /// The actual number of bytes available to read is returned in the count
90    /// byte.  This code returns a correctly sized vector containing the
91    /// count bytes read from the device.
92    fn smbus_read_block_data(&mut self, register: u8) -> Result<Vec<u8>, Self::Error>;
93
94    /// Read a block of up to 32 bytes from a device
95    ///
96    /// Uses read_i2c_block_data instead read_block_data.
97    fn smbus_read_i2c_block_data(&mut self, register: u8, len: u8) -> Result<Vec<u8>, Self::Error>;
98
99    /// Write a block of up to 32 bytes to a device
100    ///
101    /// The opposite of the Block Read command, this writes up to 32 bytes to
102    /// a device, to a designated register that is specified through the
103    /// Comm byte. The amount of data is specified in the Count byte.
104    fn smbus_write_block_data(&mut self, register: u8, values: &[u8]) -> Result<(), Self::Error>;
105
106    /// Write a block of up to 32 bytes from a device
107    ///
108    /// Uses write_i2c_block_data instead write_block_data.
109    fn smbus_write_i2c_block_data(
110        &mut self,
111        register: u8,
112        values: &[u8],
113    ) -> Result<(), Self::Error>;
114
115    /// Select a register, send 1 to 31 bytes of data to it, and reads
116    /// 1 to 31 bytes of data from it.
117    fn smbus_process_block(&mut self, register: u8, values: &[u8]) -> Result<Vec<u8>, Self::Error>;
118}
119
120/// Interface to an I2C Bus from an I2C Master
121///
122/// This is used when the client wants to interact directly with the bus
123/// without specifying an I2C slave address up-front, either because it needs
124/// to communicate with multiple addresses without creatings separate
125/// I2CDevice objects, or because it wants to make used of the I2C_RDWR ioctl
126/// which allows the client to send and transmit multiple sets I2C data in a
127/// single operation, potentially to different I2C slave addresses.
128///
129/// Typical implementations will store state with references to the bus
130/// in use.  The trait is based on the Linux i2cdev interface.
131pub trait I2CTransfer<'a> {
132    /// I2C transfer error type
133    type Error: Error;
134    /// I2C transfer message type
135    type Message: I2CMessage<'a>;
136
137    /// Performs multiple serially chained I2C read/write transactions.  On
138    /// success the return code is the number of successfully executed
139    /// transactions
140    fn transfer(&mut self, msgs: &'a mut [Self::Message]) -> Result<u32, Self::Error>;
141}
142
143/// Read/Write I2C message
144pub trait I2CMessage<'a> {
145    /// Read data from device
146    fn read(data: &'a mut [u8]) -> Self;
147
148    /// Write data to device
149    fn write(data: &'a [u8]) -> Self;
150}