From 9a92c88a3b1e2361342c2e806ccddf3ee207e27c Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Fri, 21 Mar 2025 18:02:18 +0100 Subject: [PATCH] dispatch: Make Dispatch generic over buffer size The fixed buffer size can be problematic for some use cases, see: - https://github.com/trussed-dev/ctaphid-dispatch/pull/15 To avoid adding support for different buffer sizes to the crate, we can just make the dispatch implementation generic over the buffer size. For simple cases, a type alias is provided using the old buffer size. --- dispatch/CHANGELOG.md | 3 ++- dispatch/src/dispatch.rs | 33 +++++++++++++++------------------ dispatch/src/lib.rs | 4 +++- dispatch/src/types.rs | 27 ++++++++++++++------------- 4 files changed, 34 insertions(+), 33 deletions(-) diff --git a/dispatch/CHANGELOG.md b/dispatch/CHANGELOG.md index 2100ac1..55392ee 100644 --- a/dispatch/CHANGELOG.md +++ b/dispatch/CHANGELOG.md @@ -5,7 +5,8 @@ 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] -- + +- 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 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>;