From a98011a3b13e7d8bf83fbf883bff1ed47eeded29 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sat, 14 Mar 2020 00:29:57 +0100 Subject: [PATCH 1/7] Add optional support for embedded-hal 0.2 traits --- Cargo.toml | 3 +++ src/embedded.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +++ 3 files changed, 52 insertions(+) create mode 100644 src/embedded.rs diff --git a/Cargo.toml b/Cargo.toml index 25ad79c1..f156f2e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,9 +39,12 @@ features = [ [dependencies] serde = { version = "1.0", features = ["derive"], optional = true } +embedded-hal = { version = "0.2", optional = true } +nb = { version = "0.1", optional = true } [dev-dependencies] clap = "3.1.6" [features] default = ["libudev"] +embedded = ["embedded-hal", "nb"] diff --git a/src/embedded.rs b/src/embedded.rs new file mode 100644 index 00000000..a01e0ac6 --- /dev/null +++ b/src/embedded.rs @@ -0,0 +1,46 @@ +//! Opt-in support for embedded-hal traits. +//! +//! Can be enabled with the "embedded" cargo feature. + +use std::io; + +use embedded_hal::serial; + +use crate::SerialPort; + +fn io_error_to_nb(err: io::Error) -> nb::Error { + match err.kind() { + io::ErrorKind::WouldBlock | io::ErrorKind::TimedOut | io::ErrorKind::Interrupted => { + nb::Error::WouldBlock + } + other => nb::Error::Other(other), + } +} + +impl serial::Read for Box { + type Error = io::ErrorKind; + + fn read(&mut self) -> nb::Result { + let mut buffer = [0; 1]; + let bytes_read = io::Read::read(self, &mut buffer).map_err(io_error_to_nb)?; + if bytes_read > 0 { + Ok(buffer[0]) + } else { + Err(nb::Error::WouldBlock) + } + } +} + +impl serial::Write for Box { + type Error = io::ErrorKind; + + fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { + io::Write::write(self, &[word]) + .map_err(io_error_to_nb) + .map(|_| ()) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + io::Write::flush(self).map_err(io_error_to_nb) + } +} diff --git a/src/lib.rs b/src/lib.rs index cc3f2833..d0f0ebf8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,9 @@ mod windows; #[cfg(windows)] pub use windows::COMPort; +#[cfg(feature = "embedded")] +mod embedded; + /// A type for results generated by interacting with serial ports /// /// The `Err` type is hard-wired to [`serialport::Error`](struct.Error.html). From 0cd0c4d949e452eb307abd786e419f7973761ca6 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sat, 5 Feb 2022 22:58:01 +0100 Subject: [PATCH 2/7] embedded: Upgrade to embedded-hal 1.0.0-alpha.6 --- Cargo.toml | 4 ++-- src/embedded.rs | 31 ++++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f156f2e1..92da0eac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,8 +39,8 @@ features = [ [dependencies] serde = { version = "1.0", features = ["derive"], optional = true } -embedded-hal = { version = "0.2", optional = true } -nb = { version = "0.1", optional = true } +embedded-hal = { version = "=1.0.0-alpha.6", optional = true } +nb = { version = "1", optional = true } [dev-dependencies] clap = "3.1.6" diff --git a/src/embedded.rs b/src/embedded.rs index a01e0ac6..30814247 100644 --- a/src/embedded.rs +++ b/src/embedded.rs @@ -8,17 +8,30 @@ use embedded_hal::serial; use crate::SerialPort; -fn io_error_to_nb(err: io::Error) -> nb::Error { - match err.kind() { - io::ErrorKind::WouldBlock | io::ErrorKind::TimedOut | io::ErrorKind::Interrupted => { - nb::Error::WouldBlock +#[derive(Debug, Copy, Clone)] +pub struct SerialError { + kind: io::ErrorKind, +} + +// Implement serial::Error for SerialError +impl serial::Error for SerialError { + fn kind(&self) -> serial::ErrorKind { + #[allow(clippy::match_single_binding)] + match self.kind { + _other => serial::ErrorKind::Other, } - other => nb::Error::Other(other), } } -impl serial::Read for Box { - type Error = io::ErrorKind; +fn io_error_to_nb(err: io::Error) -> nb::Error { + match err.kind() { + io::ErrorKind::WouldBlock | io::ErrorKind::Interrupted => nb::Error::WouldBlock, + other => nb::Error::Other(SerialError { kind: other }), + } +} + +impl serial::nb::Read for Box { + type Error = SerialError; fn read(&mut self) -> nb::Result { let mut buffer = [0; 1]; @@ -31,8 +44,8 @@ impl serial::Read for Box { } } -impl serial::Write for Box { - type Error = io::ErrorKind; +impl serial::nb::Write for Box { + type Error = SerialError; fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { io::Write::write(self, &[word]) From da4280eac7c3c20813111f653245ae9d0b828dbc Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Mon, 11 Jul 2022 23:05:55 +0200 Subject: [PATCH 3/7] embedded: Upgrade to embedded-hal 1.0.0-alpha.7 --- Cargo.toml | 2 +- src/embedded.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 92da0eac..869f89cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ features = [ [dependencies] serde = { version = "1.0", features = ["derive"], optional = true } -embedded-hal = { version = "=1.0.0-alpha.6", optional = true } +embedded-hal = { version = "=1.0.0-alpha.7", optional = true } nb = { version = "1", optional = true } [dev-dependencies] diff --git a/src/embedded.rs b/src/embedded.rs index 30814247..a0f3304e 100644 --- a/src/embedded.rs +++ b/src/embedded.rs @@ -13,7 +13,7 @@ pub struct SerialError { kind: io::ErrorKind, } -// Implement serial::Error for SerialError +// Implement `serial::Error` for SerialError impl serial::Error for SerialError { fn kind(&self) -> serial::ErrorKind { #[allow(clippy::match_single_binding)] @@ -30,9 +30,11 @@ fn io_error_to_nb(err: io::Error) -> nb::Error { } } -impl serial::nb::Read for Box { +impl serial::ErrorType for Box { type Error = SerialError; +} +impl serial::nb::Read for Box { fn read(&mut self) -> nb::Result { let mut buffer = [0; 1]; let bytes_read = io::Read::read(self, &mut buffer).map_err(io_error_to_nb)?; @@ -45,8 +47,6 @@ impl serial::nb::Read for Box { } impl serial::nb::Write for Box { - type Error = SerialError; - fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { io::Write::write(self, &[word]) .map_err(io_error_to_nb) From c086382662abcbcb3db2ee60797e78adc553e395 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Mon, 11 Jul 2022 23:06:23 +0200 Subject: [PATCH 4/7] embedded: Upgrade to embedded-hal 1.0.0-alpha.8 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 869f89cd..a4d7cda4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ features = [ [dependencies] serde = { version = "1.0", features = ["derive"], optional = true } -embedded-hal = { version = "=1.0.0-alpha.7", optional = true } +embedded-hal = { version = "=1.0.0-alpha.8", optional = true } nb = { version = "1", optional = true } [dev-dependencies] From faedbd5a50f096ff5afab94ca738cfe9705b647a Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 13 Nov 2022 15:28:12 +0100 Subject: [PATCH 5/7] embedded: Upgrade to embedded-hal 1.0.0-alpha.9 Non-blocking types were moved to embedded-hal-nb. --- Cargo.toml | 5 +++-- src/embedded.rs | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a4d7cda4..dbdd217d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,8 @@ features = [ [dependencies] serde = { version = "1.0", features = ["derive"], optional = true } -embedded-hal = { version = "=1.0.0-alpha.8", optional = true } +embedded-hal = { version = "=1.0.0-alpha.9", optional = true } +embedded-hal-nb = { version = "=1.0.0-alpha.1", optional = true } nb = { version = "1", optional = true } [dev-dependencies] @@ -47,4 +48,4 @@ clap = "3.1.6" [features] default = ["libudev"] -embedded = ["embedded-hal", "nb"] +embedded = ["embedded-hal", "embedded-hal-nb", "nb"] diff --git a/src/embedded.rs b/src/embedded.rs index a0f3304e..712b4d0a 100644 --- a/src/embedded.rs +++ b/src/embedded.rs @@ -4,7 +4,7 @@ use std::io; -use embedded_hal::serial; +use embedded_hal_nb::serial; use crate::SerialPort; @@ -34,7 +34,7 @@ impl serial::ErrorType for Box { type Error = SerialError; } -impl serial::nb::Read for Box { +impl serial::Read for Box { fn read(&mut self) -> nb::Result { let mut buffer = [0; 1]; let bytes_read = io::Read::read(self, &mut buffer).map_err(io_error_to_nb)?; @@ -46,7 +46,7 @@ impl serial::nb::Read for Box { } } -impl serial::nb::Write for Box { +impl serial::Write for Box { fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { io::Write::write(self, &[word]) .map_err(io_error_to_nb) From 452df8f75183805972525a8cce886f43d3b6f1c3 Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 13 Nov 2022 15:43:19 +0100 Subject: [PATCH 6/7] Add embedded_hal example --- .github/workflows/build.yaml | 8 +++++++- Cargo.toml | 4 ++++ examples/embedded_hal.rs | 21 +++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 examples/embedded_hal.rs diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 57a4fd54..4b8a421d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -84,9 +84,15 @@ jobs: command: build args: --target=${{ inputs.target }} + - name: Build | build library with all features + uses: actions-rs/cargo@v1 + with: + command: build + args: --target=${{ inputs.target }} --all-features + - name: Build | build examples if: ${{ inputs.disable_extra_builds == false }} - run: cargo build --examples --target=${{ inputs.target }} + run: cargo build --examples --target=${{ inputs.target }} --all-features - name: Build | build tests if: ${{ inputs.disable_extra_builds == false }} diff --git a/Cargo.toml b/Cargo.toml index dbdd217d..c9728db7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,3 +49,7 @@ clap = "3.1.6" [features] default = ["libudev"] embedded = ["embedded-hal", "embedded-hal-nb", "nb"] + +[[example]] +name = "embedded_hal" +required-features = ["embedded"] diff --git a/examples/embedded_hal.rs b/examples/embedded_hal.rs new file mode 100644 index 00000000..b424dd33 --- /dev/null +++ b/examples/embedded_hal.rs @@ -0,0 +1,21 @@ +//! This example does not actually do anything, but it shows that a serialport +//! instance can be passed to functions / drivers that expect a type that +//! implements the embedded-hal traits. + +use embedded_hal_nb::serial; + +fn take_reader>(_r: &R) { + // do nothing, but things should typecheck +} + +fn take_writer>(_w: &W) { + // do nothing, but things should typecheck +} + +fn main() { + let port = serialport::new("/dev/null", 9600) + .open() + .expect("This example isn't meant for running. It just demonstrates compatibility with embedded-hal on a type level."); + take_reader(&port); + take_writer(&port); +} From 57985f9b306aa46c073b61ce1a832cefcc2d69eb Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Sun, 13 Nov 2022 17:53:01 +0100 Subject: [PATCH 7/7] embedded: Implement both blocking and non-blocking traits --- examples/embedded_hal.rs | 13 ++++--- src/embedded.rs | 80 +++++++++++++++++++++++++++------------- 2 files changed, 62 insertions(+), 31 deletions(-) diff --git a/examples/embedded_hal.rs b/examples/embedded_hal.rs index b424dd33..f463374a 100644 --- a/examples/embedded_hal.rs +++ b/examples/embedded_hal.rs @@ -2,13 +2,15 @@ //! instance can be passed to functions / drivers that expect a type that //! implements the embedded-hal traits. -use embedded_hal_nb::serial; +fn take_nonblocking_reader>(_r: &R) { + // do nothing, but things should typecheck +} -fn take_reader>(_r: &R) { +fn take_nonblocking_writer>(_w: &W) { // do nothing, but things should typecheck } -fn take_writer>(_w: &W) { +fn take_blocking_writer>(_w: &W) { // do nothing, but things should typecheck } @@ -16,6 +18,7 @@ fn main() { let port = serialport::new("/dev/null", 9600) .open() .expect("This example isn't meant for running. It just demonstrates compatibility with embedded-hal on a type level."); - take_reader(&port); - take_writer(&port); + take_nonblocking_reader(&port); + take_nonblocking_writer(&port); + take_blocking_writer(&port); } diff --git a/src/embedded.rs b/src/embedded.rs index 712b4d0a..bd263fd1 100644 --- a/src/embedded.rs +++ b/src/embedded.rs @@ -4,7 +4,7 @@ use std::io; -use embedded_hal_nb::serial; +use embedded_hal::serial::{ErrorType, ErrorKind}; use crate::SerialPort; @@ -13,47 +13,75 @@ pub struct SerialError { kind: io::ErrorKind, } -// Implement `serial::Error` for SerialError -impl serial::Error for SerialError { - fn kind(&self) -> serial::ErrorKind { +impl embedded_hal::serial::Error for SerialError { + fn kind(&self) -> ErrorKind { #[allow(clippy::match_single_binding)] match self.kind { - _other => serial::ErrorKind::Other, + _ => ErrorKind::Other, } } } -fn io_error_to_nb(err: io::Error) -> nb::Error { - match err.kind() { - io::ErrorKind::WouldBlock | io::ErrorKind::Interrupted => nb::Error::WouldBlock, - other => nb::Error::Other(SerialError { kind: other }), +impl From for SerialError { + fn from(e: io::Error) -> Self { + SerialError { + kind: e.kind(), + } } } -impl serial::ErrorType for Box { +impl ErrorType for Box { type Error = SerialError; } -impl serial::Read for Box { - fn read(&mut self) -> nb::Result { - let mut buffer = [0; 1]; - let bytes_read = io::Read::read(self, &mut buffer).map_err(io_error_to_nb)?; - if bytes_read > 0 { - Ok(buffer[0]) - } else { - Err(nb::Error::WouldBlock) + +mod nonblocking { + use super::*; + use embedded_hal_nb::serial; + + fn io_error_to_nb(err: io::Error) -> nb::Error { + match err.kind() { + io::ErrorKind::WouldBlock | io::ErrorKind::Interrupted => nb::Error::WouldBlock, + other => nb::Error::Other(SerialError { kind: other }), } } -} -impl serial::Write for Box { - fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { - io::Write::write(self, &[word]) - .map_err(io_error_to_nb) - .map(|_| ()) + impl serial::Read for Box { + fn read(&mut self) -> nb::Result { + let mut buffer = [0; 1]; + let bytes_read = io::Read::read(self, &mut buffer).map_err(io_error_to_nb)?; + if bytes_read > 0 { + Ok(buffer[0]) + } else { + Err(nb::Error::WouldBlock) + } + } } - fn flush(&mut self) -> nb::Result<(), Self::Error> { - io::Write::flush(self).map_err(io_error_to_nb) + impl serial::Write for Box { + fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { + io::Write::write(self, &[word]) + .map_err(io_error_to_nb) + .map(|_| ()) + } + + fn flush(&mut self) -> nb::Result<(), Self::Error> { + io::Write::flush(self).map_err(io_error_to_nb) + } + } +} + +mod blocking { + use super::*; + use embedded_hal::serial; + + impl serial::Write for Box { + fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { + Ok(io::Write::write_all(self, buffer)?) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + Ok(io::Write::flush(self)?) + } } }