diff --git a/src/cmd.rs b/src/cmd.rs index fc087b8..2d2adb5 100644 --- a/src/cmd.rs +++ b/src/cmd.rs @@ -2,9 +2,9 @@ use core::future::Future; -use crate::controller::{CmdError, ControllerCmdAsync, ControllerCmdSync, ErrorType}; -use crate::param::param; -use crate::{FixedSizeValue, FromHciBytes, HostToControllerPacket, PacketKind, WriteHci}; +use crate::controller::{ControllerCmdAsync, ControllerCmdSync}; +use crate::{param, FixedSizeValue, FromHciBytes, HostToControllerPacket, PacketKind, WriteHci}; +use embedded_io::ErrorType; pub mod controller_baseband; pub mod info; @@ -112,7 +112,7 @@ pub trait AsyncCmd: Cmd { fn exec>( &self, controller: &C, - ) -> impl Future::Error>>> { + ) -> impl Future::Error>>> { controller.exec(self) } } @@ -155,7 +155,7 @@ pub trait SyncCmd: Cmd { fn exec>( &self, controller: &C, - ) -> impl Future::Error>>> { + ) -> impl Future::Error>>> { controller.exec(self) } } diff --git a/src/controller.rs b/src/controller.rs index fe14bda..00e5d0e 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -9,6 +9,7 @@ use cmd::controller_baseband::Reset; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::signal::Signal; use embassy_sync::waitqueue::AtomicWaker; +use embedded_io::ErrorType; use futures_intrusive::sync::LocalSemaphore; use crate::cmd::{Cmd, CmdReturnBuf}; @@ -19,10 +20,6 @@ use crate::{cmd, data, ControllerToHostPacket, FixedSizeValue, FromHciBytes, Hos pub mod blocking; -pub trait ErrorType { - type Error: embedded_io::Error; -} - pub trait Controller: ErrorType { fn write_acl_data(&self, packet: &data::AclPacket) -> impl Future>; fn write_sync_data(&self, packet: &data::SyncPacket) -> impl Future>; @@ -31,21 +28,6 @@ pub trait Controller: ErrorType { fn read<'a>(&self, buf: &'a mut [u8]) -> impl Future, Self::Error>>; } -/// An error type for Bluetooth HCI commands. -#[derive(Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum CmdError { - Hci(param::Error), - Io(E), -} - -/// An error type for try operations. -impl From for CmdError { - fn from(e: param::Error) -> Self { - Self::Hci(e) - } -} - pub trait ControllerCmdSync: Controller { /// Note: Some implementations may require [`Controller::read()`] to be polled for this to return. fn exec(&self, cmd: &C) -> impl Future>>; @@ -56,15 +38,6 @@ pub trait ControllerCmdAsync: Controller { fn exec(&self, cmd: &C) -> impl Future>>; } -/// An external [`Controller`] with communication via [`Transport`] type `T`. -pub trait TryControllerCmdSync: TryController { - fn try_exec(&self, cmd: &C) -> Result>>; -} - -pub trait TryControllerCmdAsync: TryController { - fn try_exec(&self, cmd: &C) -> Result<(), TryError>>; -} - /// An external Bluetooth controller with communication via [`Transport`] type `T`. /// /// The controller state holds a number of command slots that can be used diff --git a/src/transport.rs b/src/transport.rs index 52dd518..4fd1f72 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -4,13 +4,15 @@ use core::future::Future; use embassy_sync::blocking_mutex::raw::RawMutex; use embassy_sync::mutex::Mutex; -use embedded_io::ReadExactError; +use embedded_io::{ErrorType, ReadExactError}; -use crate::{ControllerToHostPacket, FromHciBytesError, HostToControllerPacket, ReadHci, ReadHciError, WriteHci}; +use crate::{ + controller::blocking::TryError, ControllerToHostPacket, FromHciBytesError, HostToControllerPacket, ReadHci, + ReadHciError, WriteHci, +}; /// A packet-oriented HCI Transport Layer -pub trait Transport { - type Error: embedded_io::Error; +pub trait Transport: embedded_io::ErrorType { /// Read a complete HCI packet into the rx buffer fn read<'a>(&self, rx: &'a mut [u8]) -> impl Future, Self::Error>>; /// Write a complete HCI packet from the tx buffer @@ -73,6 +75,16 @@ impl Seria } } +impl< + M: RawMutex, + R: embedded_io::ErrorType, + W: embedded_io::ErrorType, + E: embedded_io::Error, + > ErrorType for SerialTransport +{ + type Error = Error; +} + impl< M: RawMutex, R: embedded_io_async::Read, @@ -80,7 +92,6 @@ impl< E: embedded_io::Error, > Transport for SerialTransport { - type Error = Error; async fn read<'a>(&self, rx: &'a mut [u8]) -> Result, Self::Error> { let mut r = self.reader.lock().await; ControllerToHostPacket::read_hci_async(&mut *r, rx) @@ -97,6 +108,25 @@ impl< } } +impl, W: embedded_io::Write, E: embedded_io::Error> + blocking::Transport for SerialTransport +{ + fn read<'a>(&self, rx: &'a mut [u8]) -> Result, TryError> { + let mut r = self.reader.try_lock().map_err(|_| TryError::Busy)?; + ControllerToHostPacket::read_hci(&mut *r, rx) + .map_err(Error::Read) + .map_err(TryError::Error) + } + + fn write(&self, tx: &T) -> Result<(), TryError> { + let mut w = self.writer.try_lock().map_err(|_| TryError::Busy)?; + WithIndicator(tx) + .write_hci(&mut *w) + .map_err(|e| Error::Write(e)) + .map_err(TryError::Error) + } +} + /// Wrapper for a [`HostToControllerPacket`] that will write the [`PacketKind`](crate::PacketKind) indicator byte before the packet itself /// when serialized with [`WriteHci`]. /// @@ -127,3 +157,16 @@ impl<'a, T: HostToControllerPacket> WriteHci for WithIndicator<'a, T> { self.0.write_hci_async(writer).await } } + +pub mod blocking { + use super::*; + use crate::controller::blocking::TryError; + + /// A packet-oriented HCI Transport Layer + pub trait Transport: embedded_io::ErrorType { + /// Read a complete HCI packet into the rx buffer + fn read<'a>(&self, rx: &'a mut [u8]) -> Result, TryError>; + /// Write a complete HCI packet from the tx buffer + fn write(&self, val: &T) -> Result<(), TryError>; + } +}