aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-usb-logger/src/lib.rs53
1 files changed, 50 insertions, 3 deletions
diff --git a/embassy-usb-logger/src/lib.rs b/embassy-usb-logger/src/lib.rs
index 34d1ca663..11188b4ef 100644
--- a/embassy-usb-logger/src/lib.rs
+++ b/embassy-usb-logger/src/lib.rs
@@ -41,12 +41,24 @@ pub const MAX_PACKET_SIZE: u8 = 64;
41/// The logger handle, which contains a pipe with configurable size for buffering log messages. 41/// The logger handle, which contains a pipe with configurable size for buffering log messages.
42pub struct UsbLogger<const N: usize> { 42pub struct UsbLogger<const N: usize> {
43 buffer: Pipe<CS, N>, 43 buffer: Pipe<CS, N>,
44 custom_style: Option<fn(&Record, &mut Writer<'_, N>) -> ()>,
44} 45}
45 46
46impl<const N: usize> UsbLogger<N> { 47impl<const N: usize> UsbLogger<N> {
47 /// Create a new logger instance. 48 /// Create a new logger instance.
48 pub const fn new() -> Self { 49 pub const fn new() -> Self {
49 Self { buffer: Pipe::new() } 50 Self {
51 buffer: Pipe::new(),
52 custom_style: None,
53 }
54 }
55
56 /// Create a new logger instance with a custom formatter.
57 pub const fn with_custom_style(custom_style: fn(&Record, &mut Writer<'_, N>) -> ()) -> Self {
58 Self {
59 buffer: Pipe::new(),
60 custom_style: Some(custom_style),
61 }
50 } 62 }
51 63
52 /// Run the USB logger using the state and USB driver. Never returns. 64 /// Run the USB logger using the state and USB driver. Never returns.
@@ -137,14 +149,19 @@ impl<const N: usize> log::Log for UsbLogger<N> {
137 149
138 fn log(&self, record: &Record) { 150 fn log(&self, record: &Record) {
139 if self.enabled(record.metadata()) { 151 if self.enabled(record.metadata()) {
140 let _ = write!(Writer(&self.buffer), "{}\r\n", record.args()); 152 if let Some(custom_style) = self.custom_style {
153 custom_style(record, &mut Writer(&self.buffer));
154 } else {
155 let _ = write!(Writer(&self.buffer), "{}\r\n", record.args());
156 }
141 } 157 }
142 } 158 }
143 159
144 fn flush(&self) {} 160 fn flush(&self) {}
145} 161}
146 162
147struct Writer<'d, const N: usize>(&'d Pipe<CS, N>); 163/// A writer that writes to the USB logger buffer.
164pub struct Writer<'d, const N: usize>(&'d Pipe<CS, N>);
148 165
149impl<'d, const N: usize> core::fmt::Write for Writer<'d, N> { 166impl<'d, const N: usize> core::fmt::Write for Writer<'d, N> {
150 fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { 167 fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
@@ -210,3 +227,33 @@ macro_rules! with_class {
210 LOGGER.create_future_from_class($p) 227 LOGGER.create_future_from_class($p)
211 }}; 228 }};
212} 229}
230
231/// 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.
233/// The custom style function will be called for each log record and is responsible for writing the log message to the buffer.
234///
235/// Arguments specify the buffer size, log level, the serial class and the custom style function, respectively.
236///
237/// # Usage
238///
239/// ```
240/// let log_fut = embassy_usb_logger::with_custom_style!(1024, log::LevelFilter::Info, logger_class, |record, writer| {
241/// use core::fmt::Write;
242/// let level = record.level().as_str();
243/// write!(writer, "[{level}] {}\r\n", record.args()).unwrap();
244/// });
245/// ```
246///
247/// # Safety
248///
249/// This macro should only be invoked only once since it is setting the global logging state of the application.
250#[macro_export]
251macro_rules! with_custom_style {
252 ( $x:expr, $l:expr, $p:ident, $s:expr ) => {{
253 static LOGGER: ::embassy_usb_logger::UsbLogger<$x> = ::embassy_usb_logger::UsbLogger::with_custom_style($s);
254 unsafe {
255 let _ = ::log::set_logger_racy(&LOGGER).map(|()| log::set_max_level_racy($l));
256 }
257 LOGGER.create_future_from_class($p)
258 }};
259}