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}