Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ async-tokio = ["gpio-cdev/async-tokio"]
default = [ "gpio_cdev", "gpio_sysfs" ]

[dependencies]
embedded-hal = "=1.0.0-alpha.5"
embedded-hal = "=1.0.0-alpha.6"
gpio-cdev = { version = "0.5", optional = true }
sysfs_gpio = { version = "0.6", optional = true }

Expand Down
72 changes: 3 additions & 69 deletions src/delay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,16 @@
//!
//! [`embedded-hal`]: https://docs.rs/embedded-hal
use cast::{u32, u64};
use cast::u64;
use core::convert::Infallible;
use embedded_hal::delay::blocking::{DelayMs, DelayUs};
use embedded_hal::delay::blocking::DelayUs;
use std::thread;
use std::time::Duration;

/// Empty struct that provides delay functionality on top of `thread::sleep`
pub struct Delay;

impl DelayUs<u8> for Delay {
type Error = Infallible;

fn delay_us(&mut self, n: u8) -> Result<(), Self::Error> {
thread::sleep(Duration::new(0, u32(n) * 1000));
Ok(())
}
}

impl DelayUs<u16> for Delay {
type Error = Infallible;

fn delay_us(&mut self, n: u16) -> Result<(), Self::Error> {
thread::sleep(Duration::new(0, u32(n) * 1000));
Ok(())
}
}

impl DelayUs<u32> for Delay {
impl DelayUs for Delay {
type Error = Infallible;

fn delay_us(&mut self, n: u32) -> Result<(), Self::Error> {
Expand All @@ -40,51 +22,3 @@ impl DelayUs<u32> for Delay {
Ok(())
}
}

impl DelayUs<u64> for Delay {
type Error = Infallible;

fn delay_us(&mut self, n: u64) -> Result<(), Self::Error> {
let secs = n / 1_000_000;
let nsecs = ((n % 1_000_000) * 1_000) as u32;

thread::sleep(Duration::new(secs, nsecs));
Ok(())
}
}

impl DelayMs<u8> for Delay {
type Error = Infallible;

fn delay_ms(&mut self, n: u8) -> Result<(), Self::Error> {
thread::sleep(Duration::from_millis(u64(n)));
Ok(())
}
}

impl DelayMs<u16> for Delay {
type Error = Infallible;

fn delay_ms(&mut self, n: u16) -> Result<(), Self::Error> {
thread::sleep(Duration::from_millis(u64(n)));
Ok(())
}
}

impl DelayMs<u32> for Delay {
type Error = Infallible;

fn delay_ms(&mut self, n: u32) -> Result<(), Self::Error> {
thread::sleep(Duration::from_millis(u64(n)));
Ok(())
}
}

impl DelayMs<u64> for Delay {
type Error = Infallible;

fn delay_ms(&mut self, n: u64) -> Result<(), Self::Error> {
thread::sleep(Duration::from_millis(n));
Ok(())
}
}
45 changes: 37 additions & 8 deletions src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,25 +62,25 @@ mod embedded_hal_impl {
use i2cdev::linux::LinuxI2CMessage;

impl Read for I2cdev {
type Error = i2cdev::linux::LinuxI2CError;
type Error = I2CError;

fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
self.set_address(address)?;
self.inner.read(buffer)
self.inner.read(buffer).map_err(|err| I2CError { err })
}
}

impl Write for I2cdev {
type Error = i2cdev::linux::LinuxI2CError;
type Error = I2CError;

fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
self.set_address(address)?;
self.inner.write(bytes)
self.inner.write(bytes).map_err(|err| I2CError { err })
}
}

impl WriteRead for I2cdev {
type Error = i2cdev::linux::LinuxI2CError;
type Error = I2CError;

fn write_read(
&mut self,
Expand All @@ -90,12 +90,15 @@ mod embedded_hal_impl {
) -> Result<(), Self::Error> {
self.set_address(address)?;
let mut messages = [LinuxI2CMessage::write(bytes), LinuxI2CMessage::read(buffer)];
self.inner.transfer(&mut messages).map(drop)
self.inner
.transfer(&mut messages)
.map(drop)
.map_err(|err| I2CError { err })
}
}

impl Transactional for I2cdev {
type Error = i2cdev::linux::LinuxI2CError;
type Error = I2CError;

fn exec(
&mut self,
Expand All @@ -113,7 +116,33 @@ mod embedded_hal_impl {
.collect();

self.set_address(address)?;
self.inner.transfer(&mut messages).map(drop)
self.inner
.transfer(&mut messages)
.map(drop)
.map_err(|err| I2CError { err })
}
}
}

/// Error type wrapping [LinuxI2CError](i2cdev::linux::LinuxI2CError) to implement [embedded_hal::i2c::ErrorKind]
#[derive(Debug)]
pub struct I2CError {
err: i2cdev::linux::LinuxI2CError,
}

impl From<i2cdev::linux::LinuxI2CError> for I2CError {
fn from(err: i2cdev::linux::LinuxI2CError) -> Self {
Self { err }
}
}

impl embedded_hal::i2c::Error for I2CError {
fn kind(&self) -> embedded_hal::i2c::ErrorKind {
use embedded_hal::i2c::ErrorKind::*;
match &self.err {
// i2cdev::linux::LinuxI2CError::Nix(_) => todo!(),
// i2cdev::linux::LinuxI2CError::Io(_) => todo!(),
_ => Other,
}
}
}
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ mod spi;
mod timer;

pub use crate::delay::Delay;
pub use crate::i2c::I2cdev;
pub use crate::serial::Serial;
pub use crate::spi::Spidev;
pub use crate::i2c::{I2CError, I2cdev};
pub use crate::serial::{Serial, SerialError};
pub use crate::spi::{SPIError, Spidev};
pub use crate::timer::SysTimer;
64 changes: 60 additions & 4 deletions src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ impl Serial {
}

/// Helper to convert std::io::Error to the nb::Error
fn translate_io_errors(err: std::io::Error) -> nb::Error<IoErrorKind> {
fn translate_io_errors(err: std::io::Error) -> nb::Error<SerialError> {
match err.kind() {
IoErrorKind::WouldBlock | IoErrorKind::TimedOut | IoErrorKind::Interrupted => {
nb::Error::WouldBlock
}
err => nb::Error::Other(err),
err => nb::Error::Other(SerialError { err }),
}
}

impl embedded_hal::serial::nb::Read<u8> for Serial {
type Error = IoErrorKind;
type Error = SerialError;

fn read(&mut self) -> nb::Result<u8, Self::Error> {
let mut buffer = [0; 1];
Expand All @@ -44,7 +44,7 @@ impl embedded_hal::serial::nb::Read<u8> for Serial {
}

impl embedded_hal::serial::nb::Write<u8> for Serial {
type Error = IoErrorKind;
type Error = SerialError;

fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
self.0.write(&[word]).map_err(translate_io_errors)?;
Expand All @@ -56,6 +56,62 @@ impl embedded_hal::serial::nb::Write<u8> for Serial {
}
}

/// Error type wrapping [io::ErrorKind](IoErrorKind) to implement [embedded_hal::serial::ErrorKind]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct SerialError {
err: IoErrorKind,
}

impl embedded_hal::serial::Error for SerialError {
fn kind(&self) -> embedded_hal::serial::ErrorKind {
use embedded_hal::serial::ErrorKind::*;
match &self.err {
// IoErrorKind::NotFound => todo!(),
// IoErrorKind::PermissionDenied => todo!(),
// IoErrorKind::ConnectionRefused => todo!(),
// IoErrorKind::ConnectionReset => todo!(),
// IoErrorKind::HostUnreachable => todo!(),
// IoErrorKind::NetworkUnreachable => todo!(),
// IoErrorKind::ConnectionAborted => todo!(),
// IoErrorKind::NotConnected => todo!(),
// IoErrorKind::AddrInUse => todo!(),
// IoErrorKind::AddrNotAvailable => todo!(),
// IoErrorKind::NetworkDown => todo!(),
// IoErrorKind::BrokenPipe => todo!(),
// IoErrorKind::AlreadyExists => todo!(),
// IoErrorKind::WouldBlock => todo!(),
// IoErrorKind::NotADirectory => todo!(),
// IoErrorKind::IsADirectory => todo!(),
// IoErrorKind::DirectoryNotEmpty => todo!(),
// IoErrorKind::ReadOnlyFilesystem => todo!(),
// IoErrorKind::FilesystemLoop => todo!(),
// IoErrorKind::StaleNetworkFileHandle => todo!(),
// IoErrorKind::InvalidInput => todo!(),
// IoErrorKind::InvalidData => todo!(),
// IoErrorKind::TimedOut => todo!(),
// IoErrorKind::WriteZero => todo!(),
// IoErrorKind::StorageFull => todo!(),
// IoErrorKind::NotSeekable => todo!(),
// IoErrorKind::FilesystemQuotaExceeded => todo!(),
// IoErrorKind::FileTooLarge => todo!(),
// IoErrorKind::ResourceBusy => todo!(),
// IoErrorKind::ExecutableFileBusy => todo!(),
// IoErrorKind::Deadlock => todo!(),
// IoErrorKind::CrossesDevices => todo!(),
// IoErrorKind::TooManyLinks => todo!(),
// IoErrorKind::FilenameTooLong => todo!(),
// IoErrorKind::ArgumentListTooLong => todo!(),
// IoErrorKind::Interrupted => todo!(),
// IoErrorKind::Unsupported => todo!(),
// IoErrorKind::UnexpectedEof => todo!(),
// IoErrorKind::OutOfMemory => todo!(),
// IoErrorKind::Other => todo!(),
// IoErrorKind::Uncategorized => todo!(),
_ => Other,
}
}
}

#[cfg(test)]
mod test {
use std::path::Path;
Expand Down
Loading