Skip to content

Commit 35ff43e

Browse files
committed
add transactional spi
1 parent 4d801ed commit 35ff43e

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,6 @@ openpty = "0.1.0"
3232
# we don't need the `Error` implementation
3333
default-features = false
3434
version = "0.2.2"
35+
36+
[patch.crates-io]
37+
embedded-hal = { git = "https://github.com/ryankurte/embedded-hal", branch = "feature/spi-transactions" }

src/lib.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,13 @@
1313
#![deny(missing_docs)]
1414

1515
extern crate cast;
16-
extern crate core;
1716
extern crate embedded_hal as hal;
1817
pub extern crate i2cdev;
1918
pub extern crate spidev;
2019
pub extern crate serial_unix;
2120
pub extern crate serial_core;
2221
pub extern crate nb;
2322

24-
2523
#[cfg(feature = "gpio_sysfs")]
2624
pub extern crate sysfs_gpio;
2725

@@ -194,7 +192,10 @@ impl hal::blocking::i2c::WriteRead for I2cdev {
194192
buffer: &mut [u8],
195193
) -> Result<(), Self::Error> {
196194
self.set_address(address)?;
197-
let mut messages = [LinuxI2CMessage::write(bytes), LinuxI2CMessage::read(buffer)];
195+
let mut messages = [
196+
LinuxI2CMessage::write(bytes),
197+
LinuxI2CMessage::read(buffer),
198+
];
198199
self.inner.transfer(&mut messages).map(drop)
199200
}
200201
}
@@ -249,6 +250,38 @@ impl hal::blocking::spi::Write<u8> for Spidev {
249250
}
250251
}
251252

253+
pub use hal::blocking::spi::{Operation as SpiOperation};
254+
255+
impl hal::blocking::spi::Transactional<u8> for Spidev {
256+
type Error = io::Error;
257+
258+
fn exec<'a>(&mut self, operations: &mut [SpiOperation<'a, u8>]) -> Result<(), Self::Error> {
259+
260+
// Map types from generic to linux objects
261+
let mut messages: Vec<_> = operations.iter_mut().map(|a| {
262+
match a {
263+
SpiOperation::Write(w) => SpidevTransfer::write(w),
264+
SpiOperation::Transfer(r) => {
265+
// TODO: is spidev okay with the same array pointer
266+
// being used twice? If not, need some kind of vector
267+
// pool that will outlive the transfer
268+
let w = unsafe {
269+
let p = r.as_ptr();
270+
std::slice::from_raw_parts(p, r.len())
271+
};
272+
273+
SpidevTransfer::read_write(w, r)
274+
},
275+
}
276+
}).collect();
277+
278+
// Execute transfer
279+
self.0.transfer_multiple(&mut messages)?;
280+
281+
Ok(())
282+
}
283+
}
284+
252285
impl ops::Deref for Spidev {
253286
type Target = spidev::Spidev;
254287

0 commit comments

Comments
 (0)