Skip to content

Commit cb90512

Browse files
committed
Reuse I2CTransfer for I2CDevice
1 parent 7552959 commit cb90512

File tree

5 files changed

+107
-16
lines changed

5 files changed

+107
-16
lines changed

examples/pca9956b.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ fn main() {
5555
// 2) Read 10 bytes from the current register onwards
5656
let mut data = [0; 10];
5757
let mut msgs = [
58-
LinuxI2CMessage::write(ADDR, &[0b1000_0000]),
59-
LinuxI2CMessage::read(ADDR, &mut data),
58+
LinuxI2CMessage::write(&[0b1000_0000]).with_address(ADDR),
59+
LinuxI2CMessage::read(&mut data).with_address(ADDR),
6060
];
6161

6262
// Send the messages to the kernel to process

src/core.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ pub trait I2CTransfer<'a> {
136136
/// Read/Write I2C message
137137
pub trait I2CMessage<'a> {
138138
/// Read data from device
139-
fn read(slave_address: u16, data: &'a mut [u8]) -> Self;
139+
fn read(data: &'a mut [u8]) -> Self;
140140

141141
/// Write data to device
142-
fn write(slave_address: u16, data: &'a [u8]) -> Self;
142+
fn write(data: &'a [u8]) -> Self;
143143
}

src/lib.rs

+32-7
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@
1414
//! https://www.kernel.org/doc/Documentation/i2c/dev-interface
1515
//! ```rust,no_run
1616
//! extern crate i2cdev;
17-
//!
17+
//!
1818
//! use std::thread;
1919
//! use std::time::Duration;
2020
//!
2121
//! use i2cdev::core::*;
2222
//! use i2cdev::linux::{LinuxI2CDevice, LinuxI2CError};
2323
//!
2424
//! const NUNCHUCK_SLAVE_ADDR: u16 = 0x52;
25-
//!
25+
//!
2626
//! // real code should probably not use unwrap()
2727
//! fn i2cfun() -> Result<(), LinuxI2CError> {
2828
//! let mut dev = LinuxI2CDevice::new("/dev/i2c-1", NUNCHUCK_SLAVE_ADDR)?;
@@ -41,28 +41,53 @@
4141
//! }
4242
//! }
4343
//! ```
44-
//!
44+
//!
4545
//! ```rust,no_run
4646
//! extern crate i2cdev;
4747
//!
4848
//! use std::thread;
4949
//! use std::time::Duration;
5050
//!
5151
//! use i2cdev::core::*;
52-
//! use i2cdev::linux::{LinuxI2CBus, LinuxI2CError, LinuxI2CMessage};
52+
//! use i2cdev::linux::{LinuxI2CDevice, LinuxI2CError, LinuxI2CMessage};
5353
//!
5454
//! const SLAVE_ADDR: u16 = 0x57;
5555
//!
5656
//! fn write_read_transaction() -> Result<(), LinuxI2CError> {
57+
//! let mut dev = LinuxI2CDevice::new("/dev/i2c-1", SLAVE_ADDR)?;
58+
//!
59+
//! let mut read_data = [0; 2];
60+
//! let mut msgs = [
61+
//! LinuxI2CMessage::write(&[0x01]),
62+
//! LinuxI2CMessage::read(&mut read_data)
63+
//! ];
64+
//! dev.transfer(&mut msgs)?;
65+
//!
66+
//! println!("Reading: {:?}", read_data);
67+
//! Ok(())
68+
//! }
69+
//! ```
70+
//!
71+
//! ```rust,no_run
72+
//! extern crate i2cdev;
73+
//!
74+
//! use std::thread;
75+
//! use std::time::Duration;
76+
//!
77+
//! use i2cdev::core::*;
78+
//! use i2cdev::linux::{LinuxI2CBus, LinuxI2CError, LinuxI2CMessage};
79+
//!
80+
//! const SLAVE_ADDR: u16 = 0x57;
81+
//!
82+
//! fn write_read_transaction_using_bus() -> Result<(), LinuxI2CError> {
5783
//! let mut dev = LinuxI2CBus::new("/dev/i2c-1")?;
5884
//!
5985
//! let mut read_data = [0; 2];
6086
//! let mut msgs = [
61-
//! LinuxI2CMessage::write(SLAVE_ADDR, &[0x01]),
62-
//! LinuxI2CMessage::read(SLAVE_ADDR, &mut read_data)
87+
//! LinuxI2CMessage::write(&[0x01]).with_address(SLAVE_ADDR),
88+
//! LinuxI2CMessage::read(&mut read_data).with_address(SLAVE_ADDR)
6389
//! ];
6490
//! dev.transfer(&mut msgs)?;
65-
//! thread::sleep(Duration::from_millis(100));
6691
//!
6792
//! println!("Reading: {:?}", read_data);
6893
//! Ok(())

src/linux.rs

+27-4
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,20 @@ impl I2CDevice for LinuxI2CDevice {
235235
}
236236
}
237237

238+
impl<'a> I2CTransfer<'a> for LinuxI2CDevice {
239+
type Error = LinuxI2CError;
240+
type Message = LinuxI2CMessage<'a>;
241+
242+
/// Issue the provided sequence of I2C transactions
243+
fn transfer(&mut self, messages: &'a mut [Self::Message]) -> Result<u32, LinuxI2CError> {
244+
for msg in messages.iter_mut() {
245+
(*msg).addr = self.slave_address;
246+
}
247+
ffi::i2c_rdwr(self.as_raw_fd(), messages).map_err(From::from)
248+
}
249+
}
250+
251+
238252
impl LinuxI2CBus {
239253
/// Create a new LinuxI2CBus for the specified path
240254
pub fn new<P: AsRef<Path>>(path: P)
@@ -289,18 +303,18 @@ bitflags! {
289303
}
290304

291305
impl<'a> I2CMessage<'a> for LinuxI2CMessage<'a> {
292-
fn read(slave_address: u16, data: &'a mut [u8]) -> LinuxI2CMessage {
306+
fn read(data: &'a mut [u8]) -> LinuxI2CMessage {
293307
Self {
294-
addr: slave_address,
308+
addr: 0, // will be filled later
295309
flags: I2CMessageFlags::READ.bits(),
296310
len: data.len() as u16,
297311
buf: data.as_ptr(),
298312
}
299313
}
300314

301-
fn write(slave_address: u16, data: &'a [u8]) -> LinuxI2CMessage {
315+
fn write(data: &'a [u8]) -> LinuxI2CMessage {
302316
Self {
303-
addr: slave_address,
317+
addr: 0, // will be filled later
304318
flags: I2CMessageFlags::empty().bits(),
305319
len: data.len() as u16,
306320
buf: data.as_ptr(),
@@ -309,6 +323,15 @@ impl<'a> I2CMessage<'a> for LinuxI2CMessage<'a> {
309323
}
310324

311325
impl<'a> LinuxI2CMessage<'a> {
326+
pub fn with_address(self, slave_address: u16) -> Self {
327+
Self {
328+
addr: slave_address,
329+
flags: self.flags,
330+
len: self.len,
331+
buf: self.buf,
332+
}
333+
}
334+
312335
pub fn with_flags(self, flags: I2CMessageFlags) -> Self {
313336
Self {
314337
addr: self.addr,

src/mock.rs

+44-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
8-
use core::I2CDevice;
8+
use core::{I2CDevice, I2CMessage, I2CTransfer};
99
use std::io;
1010

1111
pub type I2CResult<T> = io::Result<T>;
@@ -100,3 +100,46 @@ impl I2CDevice for MockI2CDevice {
100100
unimplemented!()
101101
}
102102
}
103+
104+
#[derive(Debug)]
105+
enum MessageType<'a> {
106+
Write(&'a [u8]),
107+
Read(&'a mut [u8]),
108+
}
109+
110+
pub struct MockI2CMessage<'a> {
111+
msg_type: MessageType<'a>
112+
}
113+
114+
impl<'a> I2CMessage<'a> for MockI2CMessage<'a> {
115+
fn read(data: &'a mut [u8]) -> Self {
116+
Self {
117+
msg_type: MessageType::Read(data),
118+
}
119+
}
120+
121+
/// Write data to device
122+
fn write(data: &'a [u8]) -> Self {
123+
Self {
124+
msg_type: MessageType::Write(data),
125+
}
126+
}
127+
}
128+
129+
impl<'a> I2CTransfer<'a> for MockI2CDevice
130+
where MockI2CDevice: I2CDevice {
131+
type Error = io::Error;
132+
type Message = MockI2CMessage<'a>;
133+
134+
/// Issue the provided sequence of I2C transactions
135+
fn transfer(&mut self, messages: &'a mut [Self::Message]) -> Result<u32, Self::Error> {
136+
for msg in messages.iter_mut() {
137+
match &mut msg.msg_type {
138+
MessageType::Read(data) => self.read(data)?,
139+
MessageType::Write(data) => self.write(data)?,
140+
}
141+
}
142+
Ok(messages.len() as u32)
143+
}
144+
}
145+

0 commit comments

Comments
 (0)