mirror of
https://github.com/trussed-dev/ctaphid-dispatch.git
synced 2026-06-20 04:16:18 -07:00
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.
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
+15
-18
@@ -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<N>) {
|
||||
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<N>) {
|
||||
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);
|
||||
|
||||
+3
-1
@@ -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>;
|
||||
|
||||
+14
-13
@@ -1,31 +1,32 @@
|
||||
use ctaphid_app::{Command, Error};
|
||||
use heapless_bytes::Bytes;
|
||||
|
||||
pub const MESSAGE_SIZE: usize = 7609;
|
||||
|
||||
pub type Message = Bytes<MESSAGE_SIZE>;
|
||||
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<Message, Error>);
|
||||
pub struct InterchangeResponse<const N: usize>(pub Result<Bytes<N>, Error>);
|
||||
|
||||
impl Default for InterchangeResponse {
|
||||
impl<const N: usize> Default for InterchangeResponse<N> {
|
||||
fn default() -> Self {
|
||||
InterchangeResponse(Ok(Message::new()))
|
||||
InterchangeResponse(Ok(Default::default()))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Result<Message, Error>> for InterchangeResponse {
|
||||
fn from(value: Result<Message, Error>) -> Self {
|
||||
impl<const N: usize> From<Result<Bytes<N>, Error>> for InterchangeResponse<N> {
|
||||
fn from(value: Result<Bytes<N>, Error>) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InterchangeResponse> for Result<Message, Error> {
|
||||
fn from(value: InterchangeResponse) -> Self {
|
||||
impl<const N: usize> From<InterchangeResponse<N>> for Result<Bytes<N>, Error> {
|
||||
fn from(value: InterchangeResponse<N>) -> 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<N>), InterchangeResponse<N>>;
|
||||
pub type Requester<'pipe, const N: usize> =
|
||||
interchange::Requester<'pipe, (Command, Bytes<N>), InterchangeResponse<N>>;
|
||||
pub type Channel<const N: usize> =
|
||||
interchange::Channel<(Command, Bytes<N>), InterchangeResponse<N>>;
|
||||
|
||||
Reference in New Issue
Block a user