Skip to content

Commit f51ad83

Browse files
committed
Add function to query current SPI device configuration
This commit introduces the `query_configuration` function which reads the current configuration from the SPI device and returns a `SpidevOptions` object.
1 parent 473db93 commit f51ad83

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

src/lib.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,36 @@ impl Spidev {
245245
Ok(())
246246
}
247247

248+
/// Read the current configuration from this device
249+
pub fn query_configuration(&self) -> io::Result<SpidevOptions> {
250+
let fd = self.devfile.as_raw_fd();
251+
252+
let bpw = spidevioctl::get_bits_per_word(fd)?;
253+
let speed = spidevioctl::get_max_speed_hz(fd)?;
254+
let lsb_first = (spidevioctl::get_lsb_first(fd)?) != 0;
255+
256+
// Try to get the mode as 32-bit (RD_MODE32). Older kernels may return ENOTTY
257+
// indicating 32-bit is not supported. In that case we retry in 8-bit mode.
258+
let mode_bits = spidevioctl::get_mode_u32(fd).or_else(|err| {
259+
if err.raw_os_error() == Some(libc::ENOTTY) {
260+
spidevioctl::get_mode(fd).map(|value| value as u32)
261+
} else {
262+
Err(err)
263+
}
264+
})?;
265+
266+
let mode = SpiModeFlags::from_bits_retain(mode_bits);
267+
268+
let options = SpidevOptions::new()
269+
.bits_per_word(bpw)
270+
.max_speed_hz(speed)
271+
.lsb_first(lsb_first)
272+
.mode(mode)
273+
.build();
274+
275+
Ok(options)
276+
}
277+
248278
/// Perform a single transfer
249279
pub fn transfer(&self, transfer: &mut SpidevTransfer) -> io::Result<()> {
250280
spidevioctl::transfer(self.devfile.as_raw_fd(), transfer)

src/spidevioctl.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,12 @@ pub fn get_mode(fd: RawFd) -> io::Result<u8> {
191191
Ok(mode)
192192
}
193193

194+
pub fn get_mode_u32(fd: RawFd) -> io::Result<u32> {
195+
let mut mode: u32 = 0;
196+
from_nix_result(unsafe { ioctl::get_mode_u32(fd, &mut mode) })?;
197+
Ok(mode)
198+
}
199+
194200
pub fn set_mode(fd: RawFd, mode: SpiModeFlags) -> io::Result<()> {
195201
// we will always use the 8-bit mode write unless bits not in
196202
// the 8-bit mask are used. This is because WR_MODE32 was not

0 commit comments

Comments
 (0)