aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb-logger/src/lib.rs
diff options
context:
space:
mode:
authorBjorn <[email protected]>2024-10-31 22:51:03 -0700
committerBjorn <[email protected]>2024-10-31 22:51:03 -0700
commit333d8584812c0ea3e1f9262922befbd3fe709775 (patch)
tree4b9079f70f4283185ac7a7b94247ee7752e42967 /embassy-usb-logger/src/lib.rs
parentf319f1bc1b36cd6c7860391e49083ee64c079547 (diff)
Added ReceiverHandler to logger
Diffstat (limited to 'embassy-usb-logger/src/lib.rs')
-rw-r--r--embassy-usb-logger/src/lib.rs92
1 files changed, 79 insertions, 13 deletions
diff --git a/embassy-usb-logger/src/lib.rs b/embassy-usb-logger/src/lib.rs
index 11188b4ef..29c102f10 100644
--- a/embassy-usb-logger/src/lib.rs
+++ b/embassy-usb-logger/src/lib.rs
@@ -3,6 +3,7 @@
3#![warn(missing_docs)] 3#![warn(missing_docs)]
4 4
5use core::fmt::Write as _; 5use core::fmt::Write as _;
6use core::future::Future;
6 7
7use embassy_futures::join::join; 8use embassy_futures::join::join;
8use embassy_sync::pipe::Pipe; 9use embassy_sync::pipe::Pipe;
@@ -13,6 +14,25 @@ use log::{Metadata, Record};
13 14
14type CS = embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 15type CS = embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
15 16
17/// A trait that can be implemented and then passed to the
18pub trait ReceiverHandler {
19 /// Data comes in from the serial port with each command and runs this function
20 fn handle_data(&self, data: &[u8]) -> impl Future<Output = ()> + Send;
21
22 /// Create a new instance of the Handler
23 fn new() -> Self;
24}
25
26/// Use this Handler if you don't wish to use any handler
27pub struct DummyHandler;
28
29impl ReceiverHandler for DummyHandler {
30 async fn handle_data(&self, _data: &[u8]) {}
31 fn new() -> Self {
32 Self {}
33 }
34}
35
16/// The logger state containing buffers that must live as long as the USB peripheral. 36/// The logger state containing buffers that must live as long as the USB peripheral.
17pub struct LoggerState<'d> { 37pub struct LoggerState<'d> {
18 state: State<'d>, 38 state: State<'d>,
@@ -39,17 +59,19 @@ impl<'d> LoggerState<'d> {
39pub const MAX_PACKET_SIZE: u8 = 64; 59pub const MAX_PACKET_SIZE: u8 = 64;
40 60
41/// The logger handle, which contains a pipe with configurable size for buffering log messages. 61/// The logger handle, which contains a pipe with configurable size for buffering log messages.
42pub struct UsbLogger<const N: usize> { 62pub struct UsbLogger<const N: usize, T: ReceiverHandler + Send + Sync> {
43 buffer: Pipe<CS, N>, 63 buffer: Pipe<CS, N>,
44 custom_style: Option<fn(&Record, &mut Writer<'_, N>) -> ()>, 64 custom_style: Option<fn(&Record, &mut Writer<'_, N>) -> ()>,
65 recieve_handler: Option<T>,
45} 66}
46 67
47impl<const N: usize> UsbLogger<N> { 68impl<const N: usize, T: ReceiverHandler + Send + Sync> UsbLogger<N, T> {
48 /// Create a new logger instance. 69 /// Create a new logger instance.
49 pub const fn new() -> Self { 70 pub const fn new() -> Self {
50 Self { 71 Self {
51 buffer: Pipe::new(), 72 buffer: Pipe::new(),
52 custom_style: None, 73 custom_style: None,
74 recieve_handler: None,
53 } 75 }
54 } 76 }
55 77
@@ -58,9 +80,15 @@ impl<const N: usize> UsbLogger<N> {
58 Self { 80 Self {
59 buffer: Pipe::new(), 81 buffer: Pipe::new(),
60 custom_style: Some(custom_style), 82 custom_style: Some(custom_style),
83 recieve_handler: None,
61 } 84 }
62 } 85 }
63 86
87 /// Add a command handler to the logger
88 pub fn with_handler(&mut self, handler: T) {
89 self.recieve_handler = Some(handler);
90 }
91
64 /// Run the USB logger using the state and USB driver. Never returns. 92 /// Run the USB logger using the state and USB driver. Never returns.
65 pub async fn run<'d, D>(&'d self, state: &'d mut LoggerState<'d>, driver: D) -> ! 93 pub async fn run<'d, D>(&'d self, state: &'d mut LoggerState<'d>, driver: D) -> !
66 where 94 where
@@ -118,15 +146,22 @@ impl<const N: usize> UsbLogger<N> {
118 } 146 }
119 } 147 }
120 }; 148 };
121 let discard_fut = async { 149 let reciever_fut = async {
122 let mut discard_buf: [u8; MAX_PACKET_SIZE as usize] = [0; MAX_PACKET_SIZE as usize]; 150 let mut reciever_buf: [u8; MAX_PACKET_SIZE as usize] = [0; MAX_PACKET_SIZE as usize];
123 receiver.wait_connection().await; 151 receiver.wait_connection().await;
124 loop { 152 loop {
125 let _ = receiver.read_packet(&mut discard_buf).await; 153 let n = receiver.read_packet(&mut reciever_buf).await.unwrap();
154 match &self.recieve_handler {
155 Some(handler) => {
156 let data = &reciever_buf[..n];
157 handler.handle_data(data).await;
158 }
159 None => (),
160 }
126 } 161 }
127 }; 162 };
128 163
129 join(log_fut, discard_fut).await; 164 join(log_fut, reciever_fut).await;
130 } 165 }
131 166
132 /// Creates the futures needed for the logger from a given class 167 /// Creates the futures needed for the logger from a given class
@@ -142,7 +177,7 @@ impl<const N: usize> UsbLogger<N> {
142 } 177 }
143} 178}
144 179
145impl<const N: usize> log::Log for UsbLogger<N> { 180impl<const N: usize, T: ReceiverHandler + Send + Sync> log::Log for UsbLogger<N, T> {
146 fn enabled(&self, _metadata: &Metadata) -> bool { 181 fn enabled(&self, _metadata: &Metadata) -> bool {
147 true 182 true
148 } 183 }
@@ -182,7 +217,7 @@ impl<'d, const N: usize> core::fmt::Write for Writer<'d, N> {
182 217
183/// Initialize and run the USB serial logger, never returns. 218/// Initialize and run the USB serial logger, never returns.
184/// 219///
185/// Arguments specify the buffer size, log level and the USB driver, respectively. 220/// Arguments specify the buffer size, log level and the USB driver, respectively. You can optionally add a RecieverHandler.
186/// 221///
187/// # Usage 222/// # Usage
188/// 223///
@@ -196,17 +231,27 @@ impl<'d, const N: usize> core::fmt::Write for Writer<'d, N> {
196#[macro_export] 231#[macro_export]
197macro_rules! run { 232macro_rules! run {
198 ( $x:expr, $l:expr, $p:ident ) => { 233 ( $x:expr, $l:expr, $p:ident ) => {
199 static LOGGER: ::embassy_usb_logger::UsbLogger<$x> = ::embassy_usb_logger::UsbLogger::new(); 234 static LOGGER: ::embassy_usb_logger::UsbLogger<$x, ::embassy_usb_logger::DummyHandler> =
235 ::embassy_usb_logger::UsbLogger::new();
200 unsafe { 236 unsafe {
201 let _ = ::log::set_logger_racy(&LOGGER).map(|()| log::set_max_level_racy($l)); 237 let _ = ::log::set_logger_racy(&LOGGER).map(|()| log::set_max_level_racy($l));
202 } 238 }
203 let _ = LOGGER.run(&mut ::embassy_usb_logger::LoggerState::new(), $p).await; 239 let _ = LOGGER.run(&mut ::embassy_usb_logger::LoggerState::new(), $p).await;
204 }; 240 };
241
242 ( $x:expr, $l:expr, $p:ident, $h:ty ) => {
243 unsafe {
244 static mut LOGGER: ::embassy_usb_logger::UsbLogger<$x, $h> = ::embassy_usb_logger::UsbLogger::new();
245 LOGGER.with_handler(<$h>::new());
246 let _ = ::log::set_logger_racy(&LOGGER).map(|()| log::set_max_level_racy($l));
247 let _ = LOGGER.run(&mut ::embassy_usb_logger::LoggerState::new(), $p).await;
248 }
249 };
205} 250}
206 251
207/// Initialize the USB serial logger from a serial class and return the future to run it. 252/// Initialize the USB serial logger from a serial class and return the future to run it.
208/// 253///
209/// Arguments specify the buffer size, log level and the serial class, respectively. 254/// Arguments specify the buffer size, log level and the serial class, respectively. You can optionally add a RecieverHandler.
210/// 255///
211/// # Usage 256/// # Usage
212/// 257///
@@ -220,19 +265,29 @@ macro_rules! run {
220#[macro_export] 265#[macro_export]
221macro_rules! with_class { 266macro_rules! with_class {
222 ( $x:expr, $l:expr, $p:ident ) => {{ 267 ( $x:expr, $l:expr, $p:ident ) => {{
223 static LOGGER: ::embassy_usb_logger::UsbLogger<$x> = ::embassy_usb_logger::UsbLogger::new(); 268 static LOGGER: ::embassy_usb_logger::UsbLogger<$x, ::embassy_usb_logger::DummyHandler> =
269 ::embassy_usb_logger::UsbLogger::new();
224 unsafe { 270 unsafe {
225 let _ = ::log::set_logger_racy(&LOGGER).map(|()| log::set_max_level_racy($l)); 271 let _ = ::log::set_logger_racy(&LOGGER).map(|()| log::set_max_level_racy($l));
226 } 272 }
227 LOGGER.create_future_from_class($p) 273 LOGGER.create_future_from_class($p)
228 }}; 274 }};
275
276 ( $x:expr, $l:expr, $p:ident, $h:ty ) => {{
277 unsafe {
278 static mut LOGGER: ::embassy_usb_logger::UsbLogger<$x, $h> = ::embassy_usb_logger::UsbLogger::new();
279 LOGGER.with_handler(<$h>::new());
280 let _ = ::log::set_logger_racy(&LOGGER).map(|()| log::set_max_level_racy($l));
281 LOGGER.create_future_from_class($p)
282 }
283 }};
229} 284}
230 285
231/// Initialize the USB serial logger from a serial class and return the future to run it. 286/// Initialize the USB serial logger from a serial class and return the future to run it.
232/// This version of the macro allows for a custom style function to be passed in. 287/// This version of the macro allows for a custom style function to be passed in.
233/// The custom style function will be called for each log record and is responsible for writing the log message to the buffer. 288/// The custom style function will be called for each log record and is responsible for writing the log message to the buffer.
234/// 289///
235/// Arguments specify the buffer size, log level, the serial class and the custom style function, respectively. 290/// Arguments specify the buffer size, log level, the serial class and the custom style function, respectively. You can optionally add a RecieverHandler.
236/// 291///
237/// # Usage 292/// # Usage
238/// 293///
@@ -250,10 +305,21 @@ macro_rules! with_class {
250#[macro_export] 305#[macro_export]
251macro_rules! with_custom_style { 306macro_rules! with_custom_style {
252 ( $x:expr, $l:expr, $p:ident, $s:expr ) => {{ 307 ( $x:expr, $l:expr, $p:ident, $s:expr ) => {{
253 static LOGGER: ::embassy_usb_logger::UsbLogger<$x> = ::embassy_usb_logger::UsbLogger::with_custom_style($s); 308 static LOGGER: ::embassy_usb_logger::UsbLogger<$x, ::embassy_usb_logger::DummyHandler> =
309 ::embassy_usb_logger::UsbLogger::with_custom_style($s);
254 unsafe { 310 unsafe {
255 let _ = ::log::set_logger_racy(&LOGGER).map(|()| log::set_max_level_racy($l)); 311 let _ = ::log::set_logger_racy(&LOGGER).map(|()| log::set_max_level_racy($l));
256 } 312 }
257 LOGGER.create_future_from_class($p) 313 LOGGER.create_future_from_class($p)
258 }}; 314 }};
315
316 ( $x:expr, $l:expr, $p:ident, $s:expr, $h:ty ) => {{
317 unsafe {
318 static mut LOGGER: ::embassy_usb_logger::UsbLogger<$x, $h> =
319 ::embassy_usb_logger::UsbLogger::with_custom_style($s);
320 LOGGER.with_handler(<$h>::new());
321 let _ = ::log::set_logger_racy(&LOGGER).map(|()| log::set_max_level_racy($l));
322 LOGGER.create_future_from_class($p)
323 }
324 }};
259} 325}