diff --git a/.travis.yml b/.travis.yml index bd6bd6af0..81d86a4f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: rust sudo: false rust: - - 1.22.1 + - 1.26.0 # MSRV - stable - beta - nightly diff --git a/Cargo.toml b/Cargo.toml index 7706d2381..f9c3afa71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "spidev" -version = "0.3.0" +version = "0.4.0" authors = ["Paul Osborne "] license = "MIT/Apache-2.0" repository = "https://github.com/rust-embedded/rust-spidev" @@ -14,6 +14,6 @@ half-duplex SPI access, and full-duplex SPI access. """ [dependencies] -libc = "0.2.2" -bitflags = "0.3.3" -nix = "0.6.0" +libc = "0.2" +bitflags = "1.0" +nix = "0.14" diff --git a/README.md b/README.md index d39fdcb57..6c82eb35f 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,11 @@ The following features are implemented and planned for the library: - [x] Support for configuring spidev device - [ ] Support for querying spidev configuration state +## Minimum Supported Rust Version (MSRV) + +This crate is guaranteed to compile on stable Rust 1.26 and up. It *might* +compile with older versions but that may change in any new patch release. + ## Cross Compiling Most likely, the machine you are running on is not your development diff --git a/examples/spidev-bidir.rs b/examples/spidev-bidir.rs index dadb0f229..42f8d51e1 100644 --- a/examples/spidev-bidir.rs +++ b/examples/spidev-bidir.rs @@ -1,5 +1,5 @@ extern crate spidev; -use spidev::{Spidev, SpidevOptions, SPI_MODE_0}; +use spidev::{Spidev, SpidevOptions, SpiModeFlags}; use spidev::spidevioctl::SpidevTransfer; fn main() { @@ -8,7 +8,7 @@ fn main() { .bits_per_word(8) .max_speed_hz(5000) .lsb_first(false) - .mode(SPI_MODE_0) + .mode(SpiModeFlags::SPI_MODE_0) .build(); spidev.configure(&options).unwrap(); diff --git a/src/lib.rs b/src/lib.rs index 9626c326a..17160879e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,14 +25,14 @@ //! extern crate spidev; //! use std::io; //! use std::io::prelude::*; -//! use spidev::{Spidev, SpidevOptions, SpidevTransfer, SPI_MODE_0}; +//! use spidev::{Spidev, SpidevOptions, SpidevTransfer, SpiModeFlags}; //! //! fn create_spi() -> io::Result { //! let mut spi = try!(Spidev::open("/dev/spidev0.0")); //! let options = SpidevOptions::new() //! .bits_per_word(8) //! .max_speed_hz(20_000) -//! .mode(SPI_MODE_0) +//! .mode(SpiModeFlags::SPI_MODE_0) //! .build(); //! try!(spi.configure(&options)); //! Ok(spi) @@ -85,40 +85,40 @@ use std::os::unix::prelude::*; // Constants extracted from linux/spi/spidev.h bitflags! { - flags SpiModeFlags: u32 { + pub struct SpiModeFlags: u32 { /// Clock Phase - const SPI_CPHA = 0x01, + const SPI_CPHA = 0x01; /// Clock Polarity - const SPI_CPOL = 0x02, + const SPI_CPOL = 0x02; /// Chipselect Active High? - const SPI_CS_HIGH = 0x04, + const SPI_CS_HIGH = 0x04; /// Per-word Bits On Wire - const SPI_LSB_FIRST = 0x08, + const SPI_LSB_FIRST = 0x08; /// SI/SO Signals Shared - const SPI_3WIRE = 0x10, + const SPI_3WIRE = 0x10; /// Loopback Mode - const SPI_LOOP = 0x20, - /// 1 dev/bus, no chipselect - const SPI_NO_CS = 0x40, + const SPI_LOOP = 0x20; + /// 1 dev/bus; no chipselect + const SPI_NO_CS = 0x40; /// Slave pulls low to pause - const SPI_READY = 0x80, + const SPI_READY = 0x80; // Common Configurations - const SPI_MODE_0 = 0x00, - const SPI_MODE_1 = SPI_CPHA.bits, - const SPI_MODE_2 = SPI_CPOL.bits, - const SPI_MODE_3 = (SPI_CPOL.bits | SPI_CPHA.bits), + const SPI_MODE_0 = 0x00; + const SPI_MODE_1 = Self::SPI_CPHA.bits; + const SPI_MODE_2 = Self::SPI_CPOL.bits; + const SPI_MODE_3 = (Self::SPI_CPOL.bits | Self::SPI_CPHA.bits); // == Only Supported with 32-bits == /// Transmit with 2 wires - const SPI_TX_DUAL = 0x100, + const SPI_TX_DUAL = 0x100; /// Transmit with 4 wires - const SPI_TX_QUAD = 0x200, + const SPI_TX_QUAD = 0x200; /// Receive with 2 wires - const SPI_RX_DUAL = 0x400, + const SPI_RX_DUAL = 0x400; /// Receive with 4 wires - const SPI_RX_QUAD = 0x800, + const SPI_RX_QUAD = 0x800; } } @@ -290,8 +290,7 @@ impl Write for Spidev { #[cfg(test)] mod test { - - use super::{SpidevOptions, SPI_MODE_0}; + use super::{SpidevOptions, SpiModeFlags}; #[test] fn test_spidev_options_all() { @@ -299,12 +298,12 @@ mod test { .bits_per_word(8) .max_speed_hz(20_000) .lsb_first(false) - .mode(SPI_MODE_0) + .mode(SpiModeFlags::SPI_MODE_0) .build(); assert_eq!(options.bits_per_word, Some(8)); assert_eq!(options.max_speed_hz, Some(20_000)); assert_eq!(options.lsb_first, Some(false)); - assert_eq!(options.spi_mode, Some(SPI_MODE_0)); + assert_eq!(options.spi_mode, Some(SpiModeFlags::SPI_MODE_0)); } #[test] diff --git a/src/spidevioctl.rs b/src/spidevioctl.rs index 0952b1a9c..f2e207f94 100644 --- a/src/spidevioctl.rs +++ b/src/spidevioctl.rs @@ -8,14 +8,14 @@ #![allow(dead_code)] +use nix; use std::io; use std::marker::PhantomData; -use std::mem; use std::os::unix::prelude::*; use super::SpiModeFlags; fn from_nix_error(err: ::nix::Error) -> io::Error { - io::Error::from_raw_os_error(err.errno() as i32) + io::Error::from_raw_os_error(err.as_errno().unwrap_or_else(|| nix::errno::Errno::UnknownErrno) as i32) } fn from_nix_result(res: ::nix::Result) -> io::Result { @@ -123,26 +123,26 @@ mod ioctl { const SPI_IOC_NR_MAX_SPEED_HZ: u8 = 4; const SPI_IOC_NR_MODE32: u8 = 5; - ioctl!(read get_mode_u8 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u8); - ioctl!(read get_mode_u32 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u32); - ioctl!(write set_mode_u8 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u8); - ioctl!(write set_mode_u32 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE32; u32); + ioctl_read!(get_mode_u8, SPI_IOC_MAGIC, SPI_IOC_NR_MODE, u8); + ioctl_read!(get_mode_u32, SPI_IOC_MAGIC, SPI_IOC_NR_MODE32, u32); + ioctl_write_ptr!(set_mode, SPI_IOC_MAGIC, SPI_IOC_NR_MODE, u8); + ioctl_write_ptr!(set_mode32, SPI_IOC_MAGIC, SPI_IOC_NR_MODE32, u32); - ioctl!(read get_lsb_first with SPI_IOC_MAGIC, SPI_IOC_NR_LSB_FIRST; u8); - ioctl!(write set_lsb_first with SPI_IOC_MAGIC, SPI_IOC_NR_LSB_FIRST; u8); + ioctl_read!(get_lsb_first, SPI_IOC_MAGIC, SPI_IOC_NR_LSB_FIRST, u8); + ioctl_write_ptr!(set_lsb_first, SPI_IOC_MAGIC, SPI_IOC_NR_LSB_FIRST, u8); - ioctl!(read get_bits_per_word with SPI_IOC_MAGIC, SPI_IOC_NR_BITS_PER_WORD; u8); - ioctl!(write set_bits_per_word with SPI_IOC_MAGIC, SPI_IOC_NR_BITS_PER_WORD; u8); + ioctl_read!(get_bits_per_word, SPI_IOC_MAGIC, SPI_IOC_NR_BITS_PER_WORD, u8); + ioctl_write_ptr!(set_bits_per_word, SPI_IOC_MAGIC, SPI_IOC_NR_BITS_PER_WORD, u8); - ioctl!(read get_max_speed_hz with SPI_IOC_MAGIC, SPI_IOC_NR_MAX_SPEED_HZ; u32); - ioctl!(write set_max_speed_hz with SPI_IOC_MAGIC, SPI_IOC_NR_MAX_SPEED_HZ; u32); + ioctl_read!(get_max_speed_hz, SPI_IOC_MAGIC, SPI_IOC_NR_MAX_SPEED_HZ, u32); + ioctl_write_ptr!(set_max_speed_hz, SPI_IOC_MAGIC, SPI_IOC_NR_MAX_SPEED_HZ, u32); // NOTE: this macro works for single transfers but cannot properly // calculate size for multi transfer whose length we will not know // until runtime. We fallback to using the underlying ioctl for that // use case. - ioctl!(write spidev_transfer with SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER; spi_ioc_transfer); - ioctl!(write buf spidev_transfer_buf with SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER; spi_ioc_transfer); + ioctl_write_ptr!(spidev_transfer, SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER, spi_ioc_transfer); + ioctl_write_buf!(spidev_transfer_buf, SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER, spi_ioc_transfer); } /// Representation of a spidev transfer that is shared @@ -161,10 +161,10 @@ pub fn set_mode(fd: RawFd, mode: SpiModeFlags) -> io::Result<()> { // added until later kernels. This provides a reasonable story // for forwards and backwards compatibility if (mode.bits & 0xFFFFFF00) != 0 { - try!(from_nix_result(unsafe { ioctl::set_mode_u32(fd, &mode.bits) })); + try!(from_nix_result(unsafe { ioctl::set_mode32(fd, &mode.bits) })); } else { let bits: u8 = mode.bits as u8; - try!(from_nix_result(unsafe { ioctl::set_mode_u8(fd, &bits) })); + try!(from_nix_result(unsafe { ioctl::set_mode(fd, &bits) })); } Ok(()) } @@ -215,10 +215,8 @@ pub fn transfer(fd: RawFd, transfer: &mut SpidevTransfer) -> io::Result<()> { } pub fn transfer_multiple(fd: RawFd, transfers: &mut [SpidevTransfer]) -> io::Result<()> { - let tot_size = transfers.len() * mem::size_of::(); - try!(from_nix_result(unsafe { - ioctl::spidev_transfer_buf(fd, transfers.as_mut_ptr(), tot_size) + ioctl::spidev_transfer_buf(fd, transfers) })); Ok(()) }