diff options
Diffstat (limited to 'embassy-usb-logger/src')
| -rw-r--r-- | embassy-usb-logger/src/lib.rs | 53 |
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. |
| 42 | pub struct UsbLogger<const N: usize> { | 42 | pub 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 | ||
| 46 | impl<const N: usize> UsbLogger<N> { | 47 | impl<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 | ||
| 147 | struct Writer<'d, const N: usize>(&'d Pipe<CS, N>); | 163 | /// A writer that writes to the USB logger buffer. |
| 164 | pub struct Writer<'d, const N: usize>(&'d Pipe<CS, N>); | ||
| 148 | 165 | ||
| 149 | impl<'d, const N: usize> core::fmt::Write for Writer<'d, N> { | 166 | impl<'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] | ||
| 251 | macro_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 | } | ||
