diff --git a/dispatch/CHANGELOG.md b/dispatch/CHANGELOG.md index 2100ac1..be66ea2 100644 --- a/dispatch/CHANGELOG.md +++ b/dispatch/CHANGELOG.md @@ -5,8 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + - +## [0.3.0] - 2025-03-21 + +- Make `Dispatch` generic over the buffer size, rename `MESSAGE_SIZE` to `DEFAULT_MESSAGE_SIZE`, remove the `Message` type and add a `DefaultDispatch` type alias for `Dispatch<_, _, DEFAULT_MESSAGE_SIZE>`. + ## [0.2.0] - 2025-01-08 - Optimize stack usage of `Dispatch::poll` diff --git a/dispatch/Cargo.toml b/dispatch/Cargo.toml index 131cbff..6c24bf6 100644 --- a/dispatch/Cargo.toml +++ b/dispatch/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ctaphid-dispatch" -version = "0.2.0" +version = "0.3.0" description = "Dispatch layer after usbd-ctaphid" authors.workspace = true @@ -22,6 +22,7 @@ std = ["delog/std"] log-all = [] log-none = [] +log-trace = [] log-info = [] log-debug = [] log-warn = [] diff --git a/dispatch/src/dispatch.rs b/dispatch/src/dispatch.rs index 61769b7..a5d6e3a 100644 --- a/dispatch/src/dispatch.rs +++ b/dispatch/src/dispatch.rs @@ -1,18 +1,19 @@ use core::sync::atomic::Ordering; -use crate::types::{InterchangeResponse, Message, Responder, MESSAGE_SIZE}; +use crate::types::{InterchangeResponse, Responder}; use ctaphid_app::{App, Command, Error}; +use heapless_bytes::Bytes; use ref_swap::OptionRefSwap; use trussed_core::InterruptFlag; -pub struct Dispatch<'pipe, 'interrupt> { - responder: Responder<'pipe>, +pub struct Dispatch<'pipe, 'interrupt, const N: usize> { + responder: Responder<'pipe, N>, interrupt: Option<&'interrupt OptionRefSwap<'interrupt, InterruptFlag>>, } -impl<'pipe> Dispatch<'pipe, '_> { - pub fn new(responder: Responder<'pipe>) -> Self { +impl<'pipe, const N: usize> Dispatch<'pipe, '_, N> { + pub fn new(responder: Responder<'pipe, N>) -> Self { Dispatch { responder, interrupt: None, @@ -20,9 +21,9 @@ impl<'pipe> Dispatch<'pipe, '_> { } } -impl<'pipe, 'interrupt> Dispatch<'pipe, 'interrupt> { +impl<'pipe, 'interrupt, const N: usize> Dispatch<'pipe, 'interrupt, N> { pub fn with_interrupt( - responder: Responder<'pipe>, + responder: Responder<'pipe, N>, interrupt: Option<&'interrupt OptionRefSwap<'interrupt, InterruptFlag>>, ) -> Self { Dispatch { @@ -33,8 +34,8 @@ impl<'pipe, 'interrupt> Dispatch<'pipe, 'interrupt> { fn find_app<'a, 'b>( command: Command, - apps: &'a mut [&'b mut dyn App<'interrupt, MESSAGE_SIZE>], - ) -> Option<&'a mut &'b mut dyn App<'interrupt, MESSAGE_SIZE>> { + apps: &'a mut [&'b mut dyn App<'interrupt, N>], + ) -> Option<&'a mut &'b mut dyn App<'interrupt, N>> { apps.iter_mut() .find(|app| app.commands().contains(&command)) } @@ -53,7 +54,7 @@ impl<'pipe, 'interrupt> Dispatch<'pipe, 'interrupt> { self.reply_or_cancel(InterchangeResponse(Err(error))) } - fn reply_or_cancel(&mut self, response: InterchangeResponse) { + fn reply_or_cancel(&mut self, response: InterchangeResponse) { if self.responder.respond(response).is_ok() { return; } @@ -62,6 +63,7 @@ impl<'pipe, 'interrupt> Dispatch<'pipe, 'interrupt> { panic!("Unexpected state: {:?}", self.responder.state()); } } + fn send_reply_or_cancel(&mut self) { if self.responder.send_response().is_ok() { return; @@ -73,12 +75,7 @@ impl<'pipe, 'interrupt> Dispatch<'pipe, 'interrupt> { } #[inline(never)] - fn call_app( - &mut self, - app: &mut dyn App<'interrupt, MESSAGE_SIZE>, - command: Command, - request: &Message, - ) { + fn call_app(&mut self, app: &mut dyn App<'interrupt, N>, command: Command, request: &Bytes) { let response_buffer = self .responder .response_mut() @@ -109,9 +106,9 @@ impl<'pipe, 'interrupt> Dispatch<'pipe, 'interrupt> { } #[inline(never)] - pub fn poll(&mut self, apps: &mut [&mut dyn App<'interrupt, MESSAGE_SIZE>]) -> bool { + pub fn poll(&mut self, apps: &mut [&mut dyn App<'interrupt, N>]) -> bool { // We could call take_request directly, but for some reason this doubles stack usage. - let mut message_buffer = Message::new(); + let mut message_buffer = Bytes::new(); if let Ok((command, message)) = self.responder.request() { // info_now!("cmd: {}", u8::from(command)); // info_now!("cmd: {:?}", command); diff --git a/dispatch/src/lib.rs b/dispatch/src/lib.rs index 8f00a84..fe85e13 100644 --- a/dispatch/src/lib.rs +++ b/dispatch/src/lib.rs @@ -19,4 +19,6 @@ mod types; pub use ctaphid_app as app; pub use dispatch::Dispatch; -pub use types::{Channel, InterchangeResponse, Message, Requester, Responder, MESSAGE_SIZE}; +pub use types::{Channel, InterchangeResponse, Requester, Responder, DEFAULT_MESSAGE_SIZE}; + +pub type DefaultDispatch<'pipe, 'interrupt> = Dispatch<'pipe, 'interrupt, DEFAULT_MESSAGE_SIZE>; diff --git a/dispatch/src/types.rs b/dispatch/src/types.rs index a7fa6c7..4170af4 100644 --- a/dispatch/src/types.rs +++ b/dispatch/src/types.rs @@ -1,31 +1,32 @@ use ctaphid_app::{Command, Error}; use heapless_bytes::Bytes; -pub const MESSAGE_SIZE: usize = 7609; - -pub type Message = Bytes; +pub const DEFAULT_MESSAGE_SIZE: usize = 7609; /// Wrapper struct that implements [`Default`][] to be able to use [`response_mut`](interchange::Responder::response_mut) -pub struct InterchangeResponse(pub Result); +pub struct InterchangeResponse(pub Result, Error>); -impl Default for InterchangeResponse { +impl Default for InterchangeResponse { fn default() -> Self { - InterchangeResponse(Ok(Message::new())) + InterchangeResponse(Ok(Default::default())) } } -impl From> for InterchangeResponse { - fn from(value: Result) -> Self { +impl From, Error>> for InterchangeResponse { + fn from(value: Result, Error>) -> Self { Self(value) } } -impl From for Result { - fn from(value: InterchangeResponse) -> Self { +impl From> for Result, Error> { + fn from(value: InterchangeResponse) -> Self { value.0 } } -pub type Responder<'pipe> = interchange::Responder<'pipe, (Command, Message), InterchangeResponse>; -pub type Requester<'pipe> = interchange::Requester<'pipe, (Command, Message), InterchangeResponse>; -pub type Channel = interchange::Channel<(Command, Message), InterchangeResponse>; +pub type Responder<'pipe, const N: usize> = + interchange::Responder<'pipe, (Command, Bytes), InterchangeResponse>; +pub type Requester<'pipe, const N: usize> = + interchange::Requester<'pipe, (Command, Bytes), InterchangeResponse>; +pub type Channel = + interchange::Channel<(Command, Bytes), InterchangeResponse>;