From 49fe99e60da2b1611b237cea1796d758fe957a44 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Fri, 20 Dec 2024 19:58:27 +0800 Subject: [PATCH 1/2] feat(log): support log over USB using `embassy-usb-logger` Signed-off-by: Haobo Gu --- .../nrf52840_ble/.cargo/config.toml | 2 +- rmk-macro/src/keyboard.rs | 1 - rmk-macro/src/split/peripheral.rs | 1 - rmk/Cargo.toml | 60 +++-- rmk/src/action.rs | 7 +- rmk/src/ble/device_info.rs | 2 +- rmk/src/ble/esp/mod.rs | 1 - rmk/src/ble/esp/server.rs | 1 - rmk/src/ble/mod.rs | 5 +- rmk/src/ble/nrf/battery_service.rs | 11 +- rmk/src/ble/nrf/bonder.rs | 46 ++-- rmk/src/ble/nrf/hid_service.rs | 12 +- rmk/src/ble/nrf/mod.rs | 32 ++- rmk/src/ble/nrf/profile.rs | 1 - rmk/src/ble/nrf/server.rs | 11 +- rmk/src/ble/nrf/vial_service.rs | 6 +- rmk/src/direct_pin.rs | 3 +- rmk/src/hid.rs | 4 +- rmk/src/keyboard.rs | 22 +- rmk/src/keycode.rs | 38 +-- rmk/src/keymap.rs | 1 - rmk/src/lib.rs | 27 ++- rmk/src/light.rs | 6 +- rmk/src/logger/mod.rs | 229 ++++++++++++++++++ rmk/src/logger/usb_logger.rs | 172 +++++++++++++ rmk/src/matrix.rs | 8 +- rmk/src/split/central.rs | 4 +- rmk/src/split/driver.rs | 10 +- rmk/src/split/mod.rs | 3 +- rmk/src/split/nrf/central.rs | 13 +- rmk/src/split/nrf/peripheral.rs | 15 +- rmk/src/split/peripheral.rs | 1 - rmk/src/split/serial/mod.rs | 1 - rmk/src/storage/eeconfig.rs | 4 + rmk/src/storage/mod.rs | 17 +- rmk/src/storage/nor_flash/esp_partition.rs | 1 - rmk/src/usb/mod.rs | 34 ++- rmk/src/via/keycode_convert.rs | 3 +- rmk/src/via/process.rs | 10 +- rmk/src/via/vial.rs | 1 - 40 files changed, 657 insertions(+), 169 deletions(-) create mode 100644 rmk/src/logger/mod.rs create mode 100644 rmk/src/logger/usb_logger.rs diff --git a/examples/use_config/nrf52840_ble/.cargo/config.toml b/examples/use_config/nrf52840_ble/.cargo/config.toml index 784fa95f..c7f57922 100644 --- a/examples/use_config/nrf52840_ble/.cargo/config.toml +++ b/examples/use_config/nrf52840_ble/.cargo/config.toml @@ -35,4 +35,4 @@ target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) # target = "thumbv8m.main-none-eabihf" # Cortex-M33 (with FPU) [env] -DEFMT_LOG = "debug" \ No newline at end of file +DEFMT_LOG = "trace" \ No newline at end of file diff --git a/rmk-macro/src/keyboard.rs b/rmk-macro/src/keyboard.rs index 8e79918a..386e310b 100644 --- a/rmk-macro/src/keyboard.rs +++ b/rmk-macro/src/keyboard.rs @@ -95,7 +95,6 @@ pub(crate) fn gen_imports(config: &KeyboardConfig) -> TokenStream2 { // TODO: remove static var? quote! { - use defmt::*; #imports #keyboard_info_static_var diff --git a/rmk-macro/src/split/peripheral.rs b/rmk-macro/src/split/peripheral.rs index fb523b08..5cc3f764 100644 --- a/rmk-macro/src/split/peripheral.rs +++ b/rmk-macro/src/split/peripheral.rs @@ -56,7 +56,6 @@ pub(crate) fn parse_split_peripheral_mod( quote! { use defmt_rtt as _; use panic_probe as _; - use defmt::*; #main_function_sig { ::defmt::info!("RMK start!"); diff --git a/rmk/Cargo.toml b/rmk/Cargo.toml index 23fdcfb1..69b2bcf2 100644 --- a/rmk/Cargo.toml +++ b/rmk/Cargo.toml @@ -12,38 +12,36 @@ resolver = "2" [dependencies] rmk-macro = { version = "=0.4.0", path = "../rmk-macro" } -embedded-hal = { version = "1.0.0", features = ["defmt-03"] } -embedded-hal-async = { version = "1.0.0", features = [ - "defmt-03", -], optional = true } -embedded-io-async = { version = "0.6", features = ["defmt-03"] } +embedded-hal = { version = "1.0.0" } +embedded-hal-async = { version = "1.0.0", optional = true } +embedded-io-async = { version = "0.6" } embedded-storage = "0.3" embedded-storage-async = "0.4" embassy-embedded-hal = { version = "0.2" } -embassy-time = { version = "0.3", features = ["defmt"] } +embassy-time = { version = "0.3" } embassy-usb = { version = "0.3", features = [ - "defmt", "usbd-hid", "max-interface-count-8", "max-handler-count-8", ] } heapless = "0.8.0" -embassy-sync = { version = "0.6", features = ["defmt"] } -embassy-futures = { version = "0.1", features = ["defmt"] } -embassy-executor = { version = "0.6", features = ["defmt"] } +embassy-sync = { version = "0.6" } +embassy-futures = { version = "0.1" } +embassy-executor = { version = "0.6" } -usbd-hid = { version = "0.8.2", features = ["defmt"] } +usbd-hid = { version = "0.8.2" } ssmarshal = { version = "1.0", default-features = false } -defmt = "0.3" +defmt = { version = "0.3", optional = true } +log = { version = "0.4", optional = true } static_cell = "2" num_enum = { version = "0.7", default-features = false } bitfield-struct = "0.9" byteorder = { version = "1", default-features = false } futures = { version = "0.3", default-features = false } -sequential-storage = { version = "3.0.0", features = ["defmt-03"] } +sequential-storage = { version = "3.0.0" } serde = { version = "1", default-features = false, features = ["derive"] } -postcard = { version = "1", features = ["experimental-derive", "use-defmt"] } +postcard = { version = "1", features = ["experimental-derive"] } # Optional dependencies # nRF dependencies @@ -51,7 +49,6 @@ once_cell = { version = "1.19", features = [ "atomic-polyfill", ], default-features = false, optional = true } nrf-softdevice = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-softdevice", rev = "d5f023b", features = [ - "defmt", "ble-peripheral", "critical-section-impl", "ble-gatt-server", @@ -59,7 +56,6 @@ nrf-softdevice = { version = "0.1.0", git = "https://github.com/embassy-rs/nrf-s "ble-sec", ], optional = true } embassy-nrf = { version = "0.2.0", features = [ - "defmt", "unstable-pac", "time", ], optional = true } @@ -79,10 +75,31 @@ features = ["split"] cortex-m = { version = "0.7" } [features] -default = ["col2row"] +default = ["col2row", "defmt"] + ## If your PCB diode's direction is col2row, enable this feature. If it's row2col, disable this feature. col2row = [] +## Enable defmt feature +defmt = [ + "dep:defmt", + "embedded-hal/defmt-03", + "embedded-hal-async?/defmt-03", + "embedded-io-async/defmt-03", + "embassy-time/defmt", + "embassy-usb/defmt", + "embassy-sync/defmt", + "embassy-futures/defmt", + "embassy-executor/defmt", + "usbd-hid/defmt", + "sequential-storage/defmt-03", + "embassy-nrf?/defmt", + "nrf-softdevice?/defmt", + "postcard/use-defmt", +] + +log = ["dep:log"] + ## Enable async matrix scan async_matrix = ["dep:embedded-hal-async"] @@ -146,15 +163,10 @@ esp32c6_ble = ["_esp_ble"] esp32s3_ble = ["_esp_ble"] _esp_ble = [ "_ble", - "_no_usb", # ESP doesn't have USB support right now + "_no_usb", # ESP doesn't have USB support right now "ssmarshal/std", "dep:esp32-nimble", "dep:esp-idf-svc", ] -_nrf_ble = [ - "_ble", - "dep:nrf-softdevice", - "dep:embassy-nrf", - "dep:once_cell", -] +_nrf_ble = ["_ble", "dep:nrf-softdevice", "dep:embassy-nrf", "dep:once_cell"] _ble = ["_no_external_storage"] diff --git a/rmk/src/action.rs b/rmk/src/action.rs index a29d18b1..09359b7d 100644 --- a/rmk/src/action.rs +++ b/rmk/src/action.rs @@ -1,5 +1,4 @@ use crate::keycode::{KeyCode, ModifierCombination}; -use defmt::{error, Format}; /// A KeyAction is the action at a keyboard position, stored in keymap. /// It can be a single action like triggering a key, or a composite keyboard action like tap/hold @@ -13,7 +12,8 @@ use defmt::{error, Format}; /// The `BasicAction` represents only a single key action of keycodes defined in HID spec. The `Action` represents all actions defined in the following `Action` enum, including modifier combination and layer switch. /// /// The KeyActionType bits varies between different types of a KeyAction, see docs of each enum variant. -#[derive(Format, Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum KeyAction { /// No action. Serialized as 0x0000. No, @@ -81,7 +81,8 @@ impl KeyAction { /// A single basic action that a keyboard can execute. /// An Action can be represented in 12 bits, aka 0x000 ~ 0xFFF -#[derive(Debug, Format, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Action { /// A normal key stroke, uses for all keycodes defined in `KeyCode` enum, including mouse key, consumer/system control, etc. /// diff --git a/rmk/src/ble/device_info.rs b/rmk/src/ble/device_info.rs index 0de0f6b6..8d20a4b4 100644 --- a/rmk/src/ble/device_info.rs +++ b/rmk/src/ble/device_info.rs @@ -16,7 +16,7 @@ pub(crate) struct PnPID { pub(crate) product_version: u16, } -#[derive(Debug, Default, defmt::Format)] +#[derive(Debug, Default)] pub(crate) struct DeviceInformation { pub(crate) manufacturer_name: Option<&'static str>, pub(crate) model_number: Option<&'static str>, diff --git a/rmk/src/ble/esp/mod.rs b/rmk/src/ble/esp/mod.rs index 95f71d62..2bda0775 100644 --- a/rmk/src/ble/esp/mod.rs +++ b/rmk/src/ble/esp/mod.rs @@ -15,7 +15,6 @@ use crate::{ keymap::KeyMap, }; use core::cell::RefCell; -use defmt::{debug, info, warn}; use embassy_futures::select::{select, select4}; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel}; use embedded_hal::digital::OutputPin; diff --git a/rmk/src/ble/esp/server.rs b/rmk/src/ble/esp/server.rs index 67ee04ad..f1f60740 100644 --- a/rmk/src/ble/esp/server.rs +++ b/rmk/src/ble/esp/server.rs @@ -1,6 +1,5 @@ extern crate alloc; use alloc::sync::Arc; -use defmt::{debug, error, info, warn}; use embassy_futures::block_on; use embassy_sync::{blocking_mutex::raw::RawMutex, channel::Receiver}; use embassy_time::Timer; diff --git a/rmk/src/ble/mod.rs b/rmk/src/ble/mod.rs index d79828a4..6b5ffb74 100644 --- a/rmk/src/ble/mod.rs +++ b/rmk/src/ble/mod.rs @@ -6,7 +6,6 @@ pub mod esp; #[cfg(feature = "_nrf_ble")] pub mod nrf; -use defmt::{debug, error}; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Receiver}; use embassy_time::Timer; #[cfg(any(feature = "nrf52840_ble", feature = "nrf52833_ble"))] @@ -48,12 +47,12 @@ pub(crate) async fn ble_communication_task< match report { KeyboardReportMessage::KeyboardReport(report) => { debug!( - "Send keyboard report via BLE: {=[u8]:#X}, modifier: {:b}", + "Send keyboard report via BLE: {:?}, modifier: {:b}", report.keycodes, report.modifier ); match ble_keyboard_writer.write_serialize(&report).await { Ok(()) => {} - Err(e) => error!("Send keyboard report error: {}", e), + Err(e) => error!("Send keyboard report error: {:?}", e), }; } KeyboardReportMessage::CompositeReport(report, report_type) => { diff --git a/rmk/src/ble/nrf/battery_service.rs b/rmk/src/ble/nrf/battery_service.rs index 1df1dac9..549c6b97 100644 --- a/rmk/src/ble/nrf/battery_service.rs +++ b/rmk/src/ble/nrf/battery_service.rs @@ -1,5 +1,4 @@ use crate::config::BleBatteryConfig; -use defmt::{error, info}; use embassy_time::Timer; use nrf_softdevice::ble::Connection; @@ -56,7 +55,9 @@ impl<'a> BatteryService { Ok(_) => info!("Battery value: {}", val), Err(e) => match self.battery_level_set(&val) { Ok(_) => info!("Battery value set: {}", val), - Err(e2) => error!("Battery value notify error: {}, set error: {}", e, e2), + Err(e2) => { + error!("Battery value notify error: {:?}, set error: {:?}", e, e2) + } }, } if val < 10 { @@ -64,7 +65,7 @@ impl<'a> BatteryService { if let Some(ref mut charge_led) = battery_config.charge_led_pin { charge_led.toggle(); } - Timer::after_millis(200).await; + Timer::after_secs(200).await; continue; } else { // Turn off the led @@ -91,7 +92,7 @@ impl<'a> BatteryService { // TODO: Make battery calculation user customizable fn get_battery_percent(&self, val: i16, battery_config: &BleBatteryConfig<'a>) -> u8 { - info!("Detected adc value: {=i16}", val); + info!("Detected adc value: {:?}", val); // Avoid overflow let val = val as i32; @@ -133,7 +134,7 @@ impl BleServer { Ok(_) => info!("Battery value: {}", val), Err(e) => match self.bas.battery_level_set(val) { Ok(_) => info!("Battery value set: {}", val), - Err(e2) => error!("Battery value notify error: {}, set error: {}", e, e2), + Err(e2) => error!("Battery value notify error: {:?}, set error: {:?}", e, e2), }, } } diff --git a/rmk/src/ble/nrf/bonder.rs b/rmk/src/ble/nrf/bonder.rs index f906c06d..694ebe12 100644 --- a/rmk/src/ble/nrf/bonder.rs +++ b/rmk/src/ble/nrf/bonder.rs @@ -5,7 +5,6 @@ use crate::{ CONNECTION_STATE, }; use core::{cell::RefCell, sync::atomic::Ordering}; -use defmt::{debug, error, info, warn, Format}; use heapless::FnvIndexMap; use nrf_softdevice::ble::{ gatt_server::{get_sys_attrs, set_sys_attrs}, @@ -15,7 +14,8 @@ use nrf_softdevice::ble::{ }; // Bond info which will be stored in flash -#[derive(Clone, Copy, Debug, Format, Default)] +#[derive(Clone, Copy, Debug, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct BondInfo { pub(crate) slot_num: u8, pub(crate) peer: Peer, @@ -24,7 +24,8 @@ pub(crate) struct BondInfo { } #[repr(C)] -#[derive(Clone, Copy, Debug, Format)] +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct Peer { pub(crate) master_id: MasterId, pub(crate) key: EncryptionInfo, @@ -45,7 +46,8 @@ impl Default for Peer { } #[repr(C)] -#[derive(Clone, Copy, Debug, Format)] +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct SystemAttribute { pub(crate) length: usize, pub(crate) data: [u8; 62], @@ -108,11 +110,11 @@ impl SecurityHandler for MultiBonder { } fn display_passkey(&self, passkey: &[u8; 6]) { - info!("BLE passkey: {:#X}", passkey); + info!("BLE passkey: {:?}", passkey); } fn on_security_update(&self, _conn: &Connection, security_mode: SecurityMode) { - info!("on_security_update, new security mode: {}", security_mode); + info!("on_security_update, new security mode: {:?}", security_mode); // Security updated, indicating that the connection is established? CONNECTION_STATE.store(true, Ordering::Release); } @@ -125,7 +127,7 @@ impl SecurityHandler for MultiBonder { peer_id: IdentityKey, ) { // First time - debug!("On bonded: storing bond for {}", master_id); + debug!("On bonded: storing bond for {:?}", master_id); // Get slot num, if the device has been bonded, reuse the slot num. Otherwise get a new slot num let slot_num = ACTIVE_PROFILE.load(Ordering::Acquire); @@ -163,7 +165,7 @@ impl SecurityHandler for MultiBonder { fn get_key(&self, conn: &Connection, master_id: MasterId) -> Option { // Reconnecting with an existing bond - debug!("Getting bond for {}", master_id); + debug!("Getting bond for {:?}", master_id); let info = self .bond_info @@ -206,7 +208,7 @@ impl SecurityHandler for MultiBonder { && info.sys_attr.data[0..sys_attr_len] == buf[0..sys_attr_len]) { debug!( - "Updating sys_attr:\nnew: {},{}\nold: {},{}", + "Updating sys_attr:\nnew: {:?},{:?}\nold: {:?},{:?}", buf, sys_attr_len, info.sys_attr.data, info.sys_attr.length ); // Update bond info @@ -227,17 +229,17 @@ impl SecurityHandler for MultiBonder { } } Err(e) => { - error!("Get system attr for {} erro: {}", info, e); + error!("Get system attr for {:?} erro: {:?}", info, e); } } } else { - info!("Peer doesn't match: {}", conn.peer_address()); + info!("Peer doesn't match: {:?}", conn.peer_address()); } } fn load_sys_attrs(&self, conn: &Connection) { let addr = conn.peer_address(); - info!("Loading system attributes for {}", addr); + info!("Loading system attributes for {:?}", addr); let bond_info = self.bond_info.borrow(); @@ -247,7 +249,7 @@ impl SecurityHandler for MultiBonder { .find(|(_, b)| b.peer.peer_id.is_match(addr)) .map(|(_, b)| &b.sys_attr.data[0..b.sys_attr.length]); - // info!("call set_sys_attrs in load_sys_attrs: {}", sys_attr); + // info!("call set_sys_attrs in load_sys_attrs: {:?}", sys_attr); if let Err(err) = set_sys_attrs(conn, sys_attr) { warn!("SecurityHandler failed to set sys attrs: {:?}", err); } @@ -279,11 +281,11 @@ impl SecurityHandler for Bonder { } fn display_passkey(&self, passkey: &[u8; 6]) { - info!("BLE passkey: {:#X}", passkey); + info!("BLE passkey: {:?}", passkey); } fn on_security_update(&self, _conn: &Connection, security_mode: SecurityMode) { - info!("on_security_update, new security mode: {}", security_mode); + info!("on_security_update, new security mode: {:?}", security_mode); } fn on_bonded( @@ -294,7 +296,7 @@ impl SecurityHandler for Bonder { peer_id: IdentityKey, ) { // First time - debug!("On bonded: storing bond for {}", master_id); + debug!("On bonded: storing bond for {:?}", master_id); // Get slot num, if the device has been bonded, reuse the slot num. Otherwise get a new slot num let slot_num = self @@ -350,7 +352,7 @@ impl SecurityHandler for Bonder { fn get_key(&self, conn: &Connection, master_id: MasterId) -> Option { // Reconnecting with an existing bond - debug!("Getting bond for {}", master_id); + debug!("Getting bond for {:?}", master_id); let info = self .bond_info @@ -385,7 +387,7 @@ impl SecurityHandler for Bonder { && info.sys_attr.data[0..sys_attr_len] == buf[0..sys_attr_len]) { debug!( - "Updating sys_attr:\nnew: {},{}\nold: {},{}", + "Updating sys_attr:\nnew: {:?},{:?}\nold: {:?},{:?}", buf, sys_attr_len, info.sys_attr.data, info.sys_attr.length ); // Update bond info @@ -406,17 +408,17 @@ impl SecurityHandler for Bonder { } } Err(e) => { - error!("Get system attr for {} erro: {}", info, e); + error!("Get system attr for {:?} erro: {:?}", info, e); } } } else { - info!("Peer doesn't match: {}", conn.peer_address()); + info!("Peer doesn't match: {:?}", conn.peer_address()); } } fn load_sys_attrs(&self, conn: &Connection) { let addr = conn.peer_address(); - info!("Loading system attributes for {}", addr); + info!("Loading system attributes for {:?}", addr); let bond_info = self.bond_info.borrow(); @@ -426,7 +428,7 @@ impl SecurityHandler for Bonder { .find(|(_, b)| b.peer.peer_id.is_match(addr)) .map(|(_, b)| &b.sys_attr.data[0..b.sys_attr.length]); - // info!("call set_sys_attrs in load_sys_attrs: {}", sys_attr); + // info!("call set_sys_attrs in load_sys_attrs: {:?}", sys_attr); if let Err(err) = set_sys_attrs(conn, sys_attr) { warn!("SecurityHandler failed to set sys attrs: {:?}", err); } diff --git a/rmk/src/ble/nrf/hid_service.rs b/rmk/src/ble/nrf/hid_service.rs index b182932f..0cd21e72 100644 --- a/rmk/src/ble/nrf/hid_service.rs +++ b/rmk/src/ble/nrf/hid_service.rs @@ -3,7 +3,6 @@ use crate::{ ble::descriptor::{BleCompositeReportType, BleKeyboardReport}, light::{LedIndicator, LED_CHANNEL}, }; -use defmt::{error, info, warn, Format}; use nrf_softdevice::{ ble::{ gatt_server::{ @@ -19,7 +18,7 @@ use nrf_softdevice::{ use usbd_hid::descriptor::SerializedDescriptor as _; #[allow(dead_code)] -#[derive(Debug, defmt::Format)] +#[derive(Debug)] pub(crate) struct HidService { hid_info: u16, report_map: u16, @@ -158,13 +157,13 @@ impl HidService { pub(crate) fn send_ble_keyboard_report(&self, conn: &Connection, data: &[u8]) { gatt_server::notify_value(conn, self.input_keyboard, data) - .map_err(|e| error!("send keyboard report error: {}", e)) + .map_err(|e| error!("send keyboard report error: {:?}", e)) .ok(); } pub(crate) fn send_ble_media_report(&self, conn: &Connection, data: &[u8]) { gatt_server::notify_value(conn, self.input_media_keys, data) - .map_err(|e| error!("send keyboard report error: {}", e)) + .map_err(|e| error!("send keyboard report error: {:?}", e)) .ok(); } } @@ -184,7 +183,7 @@ impl gatt_server::Service for HidService { } else if handle == self.output_keyboard { // Fires if a keyboard output is changed - e.g. the caps lock LED let led_indicator = LedIndicator::from_bits(data[0]); - info!("HID output keyboard: {}", led_indicator); + info!("HID output keyboard: {:?}", led_indicator); // Retry 3 times in case the channel is full(which is really rare) for _i in 0..3 { match LED_CHANNEL.try_send(led_indicator) { @@ -200,7 +199,8 @@ impl gatt_server::Service for HidService { } #[allow(unused)] -#[derive(Debug, Format)] +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) enum HidServiceEvent { InputKeyboardCccdWrite, InputMediaKeyCccdWrite, diff --git a/rmk/src/ble/nrf/mod.rs b/rmk/src/ble/nrf/mod.rs index 408b5be0..b055e052 100644 --- a/rmk/src/ble/nrf/mod.rs +++ b/rmk/src/ble/nrf/mod.rs @@ -13,6 +13,8 @@ use crate::config::BleBatteryConfig; use crate::keyboard::{keyboard_report_channel, REPORT_CHANNEL_SIZE}; use crate::matrix::MatrixTrait; use crate::storage::StorageKeys; +#[cfg(feature = "log")] +use crate::USB_LOGGER; use crate::{ ble::{ ble_communication_task, @@ -31,7 +33,6 @@ use crate::{CONNECTION_STATE, KEYBOARD_STATE}; use bonder::MultiBonder; use core::sync::atomic::{AtomicU8, Ordering}; use core::{cell::RefCell, mem}; -use defmt::{debug, error, info, unwrap, warn}; use embassy_executor::Spawner; use embassy_futures::join::join; use embassy_futures::select::{select, select4, Either4}; @@ -238,7 +239,9 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< // Use the immutable ref of `Softdevice` to run the softdevice_task // The mumtable ref is used for configuring Flash and BleServer let sdv = unsafe { nrf_softdevice::Softdevice::steal() }; - unwrap!(spawner.spawn(softdevice_task(sdv))) + spawner + .spawn(softdevice_task(sdv)) + .expect("Failed to start softdevice task") }; // Flash and keymap configuration @@ -271,6 +274,9 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< #[cfg(feature = "_no_usb")] CONNECTION_TYPE.store(0, Ordering::Relaxed); + // FIXME: test usem remove + CONNECTION_TYPE.store(1, Ordering::Relaxed); + // Get all saved bond info, config BLE bonder let mut bond_info: FnvIndexMap = FnvIndexMap::new(); for key in 0..BONDED_DEVICE_NUM { @@ -287,7 +293,8 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< static BONDER: StaticCell = StaticCell::new(); let bonder = BONDER.init(MultiBonder::new(RefCell::new(bond_info))); - let ble_server = unwrap!(BleServer::new(sd, keyboard_config.usb_config, bonder)); + let ble_server = + BleServer::new(sd, keyboard_config.usb_config, bonder).expect("Failed to start ble server"); let keyboard_report_sender = keyboard_report_channel.sender(); let keyboard_report_receiver = keyboard_report_channel.receiver(); @@ -359,7 +366,16 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< ); continue; } - bonder.load_sys_attrs(&conn); + // bonder.load_sys_attrs(&conn); + #[cfg(feature = "log")] + let logger_fut = { + let log_sender = &mut usb_device.usb_logger_sender; + let log_receiver = &mut usb_device.usb_logger_receiver; + + USB_LOGGER.run_logger_class(log_sender, log_receiver) + }; + #[cfg(feature = "log")] + futures::pin_mut!(logger_fut); // Run the ble keyboard, wait for disconnection or USB connect match select3( run_ble_keyboard( @@ -373,6 +389,10 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< &mut keyboard_config.ble_battery_config, &keyboard_report_receiver, ), + // wait_for_usb_enabled(), + #[cfg(feature = "log")] + join(usb_device.device.run(), logger_fut), + #[cfg(not(feature = "log"))] wait_for_usb_enabled(), update_profile(bonder), ) @@ -411,7 +431,7 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< error!("Bonded peer address doesn't match active profile, disconnect"); continue; } - bonder.load_sys_attrs(&conn); + // bonder.load_sys_attrs(&conn); // Run the ble keyboard, wait for disconnection match select3( run_ble_keyboard( @@ -447,7 +467,7 @@ pub(crate) async fn initialize_nrf_ble_keyboard_and_run< #[cfg(feature = "_no_usb")] match peripheral::advertise_pairable(sd, adv, &config, bonder).await { Ok(conn) => { - bonder.load_sys_attrs(&conn); + // bonder.load_sys_attrs(&conn); select( run_ble_keyboard( &conn, diff --git a/rmk/src/ble/nrf/profile.rs b/rmk/src/ble/nrf/profile.rs index 7ae5438f..413383f1 100644 --- a/rmk/src/ble/nrf/profile.rs +++ b/rmk/src/ble/nrf/profile.rs @@ -3,7 +3,6 @@ use core::sync::atomic::Ordering; -use defmt::info; use embassy_futures::yield_now; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel}; diff --git a/rmk/src/ble/nrf/server.rs b/rmk/src/ble/nrf/server.rs index 2b23eeb7..c5e74266 100644 --- a/rmk/src/ble/nrf/server.rs +++ b/rmk/src/ble/nrf/server.rs @@ -9,7 +9,6 @@ use crate::{ ble::device_info::{DeviceInformation, PnPID, VidSource}, hid::{ConnectionType, ConnectionTypeWrapper, HidError, HidReaderWrapper, HidWriterWrapper}, }; -use defmt::{error, info}; use nrf_softdevice::{ ble::{ gatt_server::{self, RegisterError, Service, WriteOp}, @@ -44,7 +43,7 @@ impl<'a, const N: usize> HidWriterWrapper for BleHidWriter<'a, N> { async fn write(&mut self, report: &[u8]) -> Result<(), HidError> { gatt_server::notify_value(self.conn, self.handle, report).map_err(|e| { - error!("Send ble report error: {}", e); + error!("Send ble report error: {:?}", e); match e { gatt_server::NotifyValueError::Disconnected => HidError::BleDisconnected, gatt_server::NotifyValueError::Raw(_) => HidError::BleRawError, @@ -77,7 +76,7 @@ impl<'a, const N: usize> HidReaderWrapper for BleHidReader<'a, N> { let mut buffer = [0u8; 16]; gatt_server::get_value(self.sd, self.handle, &mut buffer) .map_err(|e| { - error!("Read value from ble error: {}", e); + error!("Read value from ble error: {:?}", e); HidError::BleRawError }) .map(|s| { @@ -158,7 +157,7 @@ impl gatt_server::Server for BleServer { | HidServiceEvent::InputMediaKeyCccdWrite | HidServiceEvent::InputMouseKeyCccdWrite | HidServiceEvent::InputSystemKeyCccdWrite => { - info!("{}, handle: {}, data: {}", event, handle, data); + info!("{:?}, handle: {}, data: {:?}", event, handle, data); self.bonder.save_sys_attrs(conn) } HidServiceEvent::OutputKeyboard => (), @@ -168,7 +167,7 @@ impl gatt_server::Server for BleServer { match event { BatteryServiceEvent::BatteryLevelCccdWrite { notifications } => { info!( - "BatteryLevelCccdWrite, handle: {}, data: {}, notif: {}", + "BatteryLevelCccdWrite, handle: {}, data: {:?}, notif: {}", handle, data, notifications ); self.bonder.save_sys_attrs(conn) @@ -178,7 +177,7 @@ impl gatt_server::Server for BleServer { if let Some(event) = self.vial.on_write(handle, data) { match event { VialServiceEvent::InputVialKeyCccdWrite => { - info!("InputVialCccdWrite, handle: {}, data: {}", handle, data); + info!("InputVialCccdWrite, handle: {}, data: {:?}", handle, data); self.bonder.save_sys_attrs(conn) } VialServiceEvent::OutputVial => (), diff --git a/rmk/src/ble/nrf/vial_service.rs b/rmk/src/ble/nrf/vial_service.rs index 55ed78a4..af06f623 100644 --- a/rmk/src/ble/nrf/vial_service.rs +++ b/rmk/src/ble/nrf/vial_service.rs @@ -1,4 +1,3 @@ -use defmt::{debug, error, Format}; use embassy_futures::block_on; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel}; use nrf_softdevice::{ @@ -119,7 +118,7 @@ impl BleVialService { pub(crate) fn send_ble_vial_report(&self, conn: &Connection, data: &[u8]) { gatt_server::notify_value(conn, self.input_vial, data) - .map_err(|e| error!("send vial report error: {}", e)) + .map_err(|e| error!("send vial report error: {:?}", e)) .ok(); } } @@ -193,7 +192,8 @@ impl<'a> HidWriterWrapper for VialReaderWriter<'a> { } } -#[derive(Debug, Format)] +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) enum VialServiceEvent { InputVialKeyCccdWrite, OutputVial, diff --git a/rmk/src/direct_pin.rs b/rmk/src/direct_pin.rs index f0a56c67..5878b593 100644 --- a/rmk/src/direct_pin.rs +++ b/rmk/src/direct_pin.rs @@ -21,7 +21,6 @@ use crate::ble::nrf::initialize_nrf_ble_keyboard_and_run; ))] use crate::initialize_usb_keyboard_and_run; -use defmt::info; #[cfg(not(feature = "_esp_ble"))] use embassy_executor::Spawner; use embassy_time::Instant; @@ -203,7 +202,7 @@ pub async fn run_rmk_direct_pin_with_async_flash< .await; // The fut should never return. // If there's no fut, the feature flags must not be correct. - defmt::panic!("The run_rmk should never return"); + panic!("The run_rmk should never return"); } /// DirectPinMartex only has input pins. diff --git a/rmk/src/hid.rs b/rmk/src/hid.rs index 9f1c3edd..b60a8e89 100644 --- a/rmk/src/hid.rs +++ b/rmk/src/hid.rs @@ -1,13 +1,13 @@ //! A thin hid wrapper layer which supports writing/reading HID reports via USB and BLE -use defmt::Format; use embassy_usb::{ class::hid::{HidReader, HidReaderWriter, HidWriter, ReadError}, driver::Driver, }; use usbd_hid::descriptor::AsInputReport; -#[derive(PartialEq, Debug, Format)] +#[derive(PartialEq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) enum HidError { UsbDisabled, UsbPartialRead, diff --git a/rmk/src/keyboard.rs b/rmk/src/keyboard.rs index 35bad243..d3bb3eeb 100644 --- a/rmk/src/keyboard.rs +++ b/rmk/src/keyboard.rs @@ -10,7 +10,6 @@ use crate::{ KEYBOARD_STATE, }; use core::cell::RefCell; -use defmt::{debug, error, info, warn, Format}; use embassy_futures::{select::select, yield_now}; use embassy_sync::{ blocking_mutex::raw::CriticalSectionRawMutex, @@ -22,7 +21,8 @@ use postcard::experimental::max_size::MaxSize; use serde::{Deserialize, Serialize}; use usbd_hid::descriptor::KeyboardReport; -#[derive(Serialize, Deserialize, Clone, Copy, Debug, Format, MaxSize)] +#[derive(Serialize, Deserialize, Clone, Copy, Debug, MaxSize)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct KeyEvent { pub(crate) row: u8, pub(crate) col: u8, @@ -90,7 +90,7 @@ pub(crate) async fn communication_task<'a, W: HidWriterWrapper, W2: HidWriterWra KeyboardReportMessage::KeyboardReport(report) => { match keybooard_hid_writer.write_serialize(&report).await { Ok(()) => {} - Err(e) => error!("Send keyboard report error: {}", e), + Err(e) => error!("Send keyboard report error: {:?}", e), }; } KeyboardReportMessage::CompositeReport(report, report_type) => { @@ -111,12 +111,13 @@ pub(crate) async fn write_other_report_to_host( buf[0] = report_type as u8; match report.serialize(&mut buf[1..], report_type) { Ok(s) => { + #[cfg(feature = "defmt")] debug!("Sending other report: {=[u8]:#X}", buf[0..s + 1]); if let Err(e) = match other_hid_writer.get_conn_type() { ConnectionType::Usb => other_hid_writer.write(&buf[0..s + 1]).await, ConnectionType::Ble => other_hid_writer.write(&buf[1..s + 1]).await, } { - error!("Send other report error: {}", e); + error!("Send other report error: {:?}", e); } } Err(_) => error!("Serialize other report error"), @@ -537,7 +538,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> match select(hold_timeout, key_event_channel.receive()).await { embassy_futures::select::Either::First(_) => { // Timeout, trigger hold - debug!("Hold timeout, got HOLD: {}, {}", hold_action, key_event); + debug!("Hold timeout, got HOLD: {:?}, {:?}", hold_action, key_event); self.process_key_action_normal(hold_action, key_event).await; } embassy_futures::select::Either::Second(e) => { @@ -545,7 +546,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> // If it's same key event and releasing within `hold_timeout`, trigger tap if !e.pressed { let elapsed = self.timer[col][row].unwrap().elapsed().as_millis(); - debug!("TAP action: {}, time elapsed: {}ms", tap_action, elapsed); + debug!("TAP action: {:?}, time elapsed: {}ms", tap_action, elapsed); self.process_key_action_tap(tap_action, key_event).await; // Clear timer @@ -585,7 +586,10 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> && key_event.col == self.hold_after_tap.0.col { // Release the hold after tap key - info!("Hold after tap, hold the tap: {} {}", tap_action, key_event); + info!( + "Hold after tap, hold the tap: {:?} {:?}", + tap_action, key_event + ); self.process_key_action_normal(tap_action, key_event).await; self.hold_after_tap = (key_event, false); return; @@ -594,7 +598,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> if let Some(_) = self.timer[col][row] { // Release hold action, wait for `post_wait_time`, then clear timer debug!( - "HOLD releasing: {}, {}, wait for `post_wait_time` for new releases", + "HOLD releasing: {:?}, {}, wait for `post_wait_time` for new releases", hold_action, key_event.pressed ); let wait_release = async { @@ -626,7 +630,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> self.timer[col][row] = None; } else { // The timer has been reset, fire hold release event - debug!("HOLD releasing: {}, {}", hold_action, key_event.pressed); + debug!("HOLD releasing: {:?}, {}", hold_action, key_event.pressed); self.process_key_action_normal(hold_action, key_event).await; } } diff --git a/rmk/src/keycode.rs b/rmk/src/keycode.rs index 01403b65..1241d45c 100644 --- a/rmk/src/keycode.rs +++ b/rmk/src/keycode.rs @@ -1,7 +1,6 @@ use core::ops::BitOr; use bitfield_struct::bitfield; -use defmt::Format; use num_enum::FromPrimitive; /// To represent all combinations of modifiers, at least 5 bits are needed. @@ -12,6 +11,7 @@ use num_enum::FromPrimitive; /// | L/R | GUI | ALT |SHIFT| CTRL| #[bitfield(u8, order = Lsb)] #[derive(Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ModifierCombination { #[bits(1)] pub(crate) ctrl: bool, @@ -27,19 +27,20 @@ pub struct ModifierCombination { _reserved: u8, } -impl Format for ModifierCombination { - fn format(&self, fmt: defmt::Formatter) { - defmt::write!( - fmt, - "ModifierCombination {{ ctrl: {=bool}, shift: {=bool}, alt: {=bool}, gui: {=bool}, right: {=bool} }}", - self.ctrl(), - self.shift(), - self.alt(), - self.gui(), - self.right() - ) - } -} +// #[cfg(feature = "defmt")] +// impl defmt::Format for ModifierCombination { +// fn format(&self, fmt: defmt::Formatter) { +// defmt::write!( +// fmt, +// "ModifierCombination {{ ctrl: {=bool}, shift: {=bool}, alt: {=bool}, gui: {=bool}, right: {=bool} }}", +// self.ctrl(), +// self.shift(), +// self.alt(), +// self.gui(), +// self.right() +// ) +// } +// } impl BitOr for ModifierCombination { type Output = Self; @@ -118,8 +119,9 @@ impl ModifierCombination { /// Keys in consumer page /// Ref: #[non_exhaustive] -#[derive(Debug, Format, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive)] #[repr(u16)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ConsumerKey { #[num_enum(default)] Zero = 0x00, @@ -185,8 +187,9 @@ pub enum ConsumerKey { /// Keys in `Generic Desktop Page`, generally used for system control /// Ref: #[non_exhaustive] -#[derive(Debug, Format, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive)] #[repr(u16)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SystemControlKey { #[num_enum(default)] Zero = 0x00, @@ -198,8 +201,9 @@ pub enum SystemControlKey { /// KeyCode is the internal representation of all keycodes, keyboard operations, etc. /// Use flat representation of keycodes. -#[derive(Debug, Format, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, Hash)] #[repr(u16)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, FromPrimitive, Hash)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum KeyCode { /// Reserved, no-key. #[num_enum(default)] diff --git a/rmk/src/keymap.rs b/rmk/src/keymap.rs index b4674eb8..4b90db41 100644 --- a/rmk/src/keymap.rs +++ b/rmk/src/keymap.rs @@ -6,7 +6,6 @@ use crate::{ reboot_keyboard, storage::Storage, }; -use defmt::{error, warn}; use embedded_storage_async::nor_flash::NorFlash; use num_enum::FromPrimitive; diff --git a/rmk/src/lib.rs b/rmk/src/lib.rs index 05ef8fec..cdb951a7 100644 --- a/rmk/src/lib.rs +++ b/rmk/src/lib.rs @@ -20,6 +20,8 @@ use crate::config::RmkConfig; use crate::debounce::default_bouncer::DefaultDebouncer; #[cfg(feature = "rapid_debouncer")] use crate::debounce::fast_debouncer::RapidDebouncer; +#[cfg(feature = "log")] +use crate::logger::usb_logger::{DummyHandler, UsbLogger}; use crate::{ light::{led_hid_task, LightService}, via::vial_task, @@ -30,7 +32,6 @@ use core::{ sync::atomic::{AtomicBool, AtomicU8}, }; use debounce::DebouncerTrait; -use defmt::{error, warn}; #[cfg(not(feature = "_esp_ble"))] use embassy_executor::Spawner; use embassy_futures::select::{select, select4, Either4}; @@ -57,6 +58,9 @@ use via::process::VialService; #[cfg(any(feature = "_nrf_ble", not(feature = "_no_external_storage")))] use {embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash, storage::Storage}; +// This mod MUST go first, so that the others see its macros. +pub(crate) mod logger; + pub mod action; #[cfg(feature = "_ble")] pub mod ble; @@ -78,6 +82,10 @@ mod storage; mod usb; mod via; +#[cfg(feature = "log")] +// Global logger over USB serial +pub(crate) static USB_LOGGER: UsbLogger<1024, DummyHandler> = UsbLogger::new(); + /// Keyboard state, true for started, false for stopped pub(crate) static KEYBOARD_STATE: AtomicBool = AtomicBool::new(false); /// Current connection type: @@ -220,7 +228,7 @@ pub async fn run_rmk_with_async_flash< // The fut should never return. // If there's no fut, the feature flags must not be correct. - defmt::panic!("The run_rmk should never return"); + panic!("The run_rmk should never return"); } pub(crate) async fn initialize_usb_keyboard_and_run< @@ -334,6 +342,16 @@ pub(crate) async fn run_usb_keyboard< #[cfg(any(feature = "_nrf_ble", not(feature = "_no_external_storage")))] pin_mut!(storage_fut); + #[cfg(feature = "log")] + let logger_fut = { + let log_sender = &mut usb_device.usb_logger_sender; + let log_receiver = &mut usb_device.usb_logger_receiver; + + USB_LOGGER.run_logger_class(log_sender, log_receiver) + }; + #[cfg(feature = "log")] + pin_mut!(logger_fut); + match select4( select(usb_fut, keyboard_fut), #[cfg(any(feature = "_nrf_ble", not(feature = "_no_external_storage")))] @@ -341,6 +359,9 @@ pub(crate) async fn run_usb_keyboard< #[cfg(all(not(feature = "_nrf_ble"), feature = "_no_external_storage"))] #[cfg(feature = "_no_external_storage")] via_fut, + #[cfg(feature = "log")] + select(logger_fut, led_fut), + #[cfg(not(feature = "log"))] led_fut, select(matrix_fut, communication_fut), ) @@ -348,7 +369,7 @@ pub(crate) async fn run_usb_keyboard< { Either4::First(_) => error!("Usb or keyboard task has died"), Either4::Second(_) => error!("Storage or vial task has died"), - Either4::Third(_) => error!("Led task has died"), + Either4::Third(_) => error!("Logger or led task has died"), Either4::Fourth(_) => error!("Communication task has died"), } diff --git a/rmk/src/light.rs b/rmk/src/light.rs index 3ba8505c..132b9ca7 100644 --- a/rmk/src/light.rs +++ b/rmk/src/light.rs @@ -1,7 +1,6 @@ use crate::config::{LightConfig, LightPinConfig}; use crate::hid::HidReaderWrapper; use bitfield_struct::bitfield; -use defmt::{debug, error, warn, Format}; use embassy_futures::select::select; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel}; use embedded_hal::digital::{Error, OutputPin, PinState}; @@ -38,7 +37,7 @@ pub(crate) async fn hid_read_led(keyboard_hid_reader: &mut LED_CHANNEL.send(indicator).await; } Err(e) => { - error!("Read keyboard state error: {}", e); + error!("Read keyboard state error: {:?}", e); embassy_time::Timer::after_secs(1).await; } } @@ -63,7 +62,8 @@ pub(crate) async fn led_hid_task( } #[bitfield(u8)] -#[derive(Format, Eq, PartialEq)] +#[derive(Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct LedIndicator { #[bits(1)] numslock: bool, diff --git a/rmk/src/logger/mod.rs b/rmk/src/logger/mod.rs new file mode 100644 index 00000000..e603d5af --- /dev/null +++ b/rmk/src/logger/mod.rs @@ -0,0 +1,229 @@ +#![macro_use] +#![allow(unused_macros)] + +#[cfg(feature = "log")] +pub(crate) mod usb_logger; + +#[cfg(all(feature = "defmt", feature = "log"))] +compile_error!("You may not enable both `defmt` and `log` features."); + +macro_rules! assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert!($($x)*); + } + }; +} + +macro_rules! assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_eq!($($x)*); + } + }; +} + +macro_rules! assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_ne!($($x)*); + } + }; +} + +macro_rules! debug_assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert!($($x)*); + } + }; +} + +macro_rules! debug_assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_eq!($($x)*); + } + }; +} + +macro_rules! debug_assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_ne!($($x)*); + } + }; +} + +macro_rules! todo { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::todo!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::todo!($($x)*); + } + }; +} + +macro_rules! unreachable { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } + }; +} + +// macro_rules! panic { +// ($($x:tt)*) => { +// { +// #[cfg(not(feature = "defmt"))] +// ::core::panic!($($x)*); +// #[cfg(feature = "defmt")] +// ::defmt::panic!($($x)*); +// } +// }; +// } + +macro_rules! trace { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::trace!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::trace!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! debug { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::debug!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::debug!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! info { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::info!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::info!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! warn { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::warn!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::warn!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! error { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::error!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::error!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unwrap { + ($($x:tt)*) => { + ::defmt::unwrap!($($x)*) + }; +} + +#[cfg(not(feature = "defmt"))] +macro_rules! unwrap { + ($arg:expr) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); + } + } + }; + ($arg:expr, $($msg:expr),+ $(,)? ) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); + } + } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct NoneError; + +pub trait Try { + type Ok; + type Error; + #[allow(dead_code)] + fn into_result(self) -> Result; +} + +impl Try for Option { + type Ok = T; + type Error = NoneError; + + #[inline] + fn into_result(self) -> Result { + self.ok_or(NoneError) + } +} + +impl Try for Result { + type Ok = T; + type Error = E; + + #[inline] + fn into_result(self) -> Self { + self + } +} diff --git a/rmk/src/logger/usb_logger.rs b/rmk/src/logger/usb_logger.rs new file mode 100644 index 00000000..5033f05a --- /dev/null +++ b/rmk/src/logger/usb_logger.rs @@ -0,0 +1,172 @@ +use core::fmt::Write as _; +use core::future::Future; + +use embassy_futures::join::join; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::pipe::Pipe; +use embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender, State}; +use embassy_usb::driver::Driver; +use log::{Metadata, Record}; + +/// A trait that can be implemented and then passed to the usb logger +pub trait ReceiverHandler { + /// Data comes in from the serial port with each command and runs this function + fn handle_data(&self, data: &[u8]) -> impl Future + Send; + + /// Create a new instance of the Handler + fn new() -> Self; +} + +/// Use this Handler if you don't wish to use any handler +pub struct DummyHandler; + +impl ReceiverHandler for DummyHandler { + async fn handle_data(&self, _data: &[u8]) {} + fn new() -> Self { + Self {} + } +} + +/// The logger state containing buffers that must live as long as the USB peripheral. +pub struct LoggerState<'d> { + pub(crate) state: State<'d>, + config_descriptor: [u8; 128], + bos_descriptor: [u8; 16], + msos_descriptor: [u8; 256], + control_buf: [u8; 64], +} + +impl<'d> LoggerState<'d> { + /// Create a new instance of the logger state. + pub fn new() -> Self { + Self { + state: State::new(), + config_descriptor: [0; 128], + bos_descriptor: [0; 16], + msos_descriptor: [0; 256], + control_buf: [0; 64], + } + } +} + +/// The packet size used in the usb logger, to be used with `create_future_from_class` +pub const MAX_PACKET_SIZE: u8 = 64; + +/// The logger handle, which contains a pipe with configurable size for buffering log messages. +pub struct UsbLogger { + buffer: Pipe, + custom_style: Option) -> ()>, + recieve_handler: Option, +} + +impl UsbLogger { + /// Create a new logger instance. + pub const fn new() -> Self { + Self { + buffer: Pipe::new(), + custom_style: None, + recieve_handler: None, + } + } + + /// Create a new logger instance with a custom formatter. + pub const fn with_custom_style(custom_style: fn(&Record, &mut Writer<'_, N>) -> ()) -> Self { + Self { + buffer: Pipe::new(), + custom_style: Some(custom_style), + recieve_handler: None, + } + } + + /// Add a command handler to the logger + pub fn with_handler(&mut self, handler: T) { + self.recieve_handler = Some(handler); + } + + pub async fn run_logger_class<'d, D>( + &self, + sender: &mut Sender<'d, D>, + receiver: &mut Receiver<'d, D>, + ) where + D: Driver<'d>, + { + let log_fut = async { + let mut rx: [u8; MAX_PACKET_SIZE as usize] = [0; MAX_PACKET_SIZE as usize]; + sender.wait_connection().await; + loop { + let len = self.buffer.read(&mut rx[..]).await; + let _ = sender.write_packet(&rx[..len]).await; + if len as u8 == MAX_PACKET_SIZE { + let _ = sender.write_packet(&[]).await; + } + } + }; + let reciever_fut = async { + let mut reciever_buf: [u8; MAX_PACKET_SIZE as usize] = [0; MAX_PACKET_SIZE as usize]; + receiver.wait_connection().await; + loop { + if let Ok(n) = receiver.read_packet(&mut reciever_buf).await { + match &self.recieve_handler { + Some(handler) => { + let data = &reciever_buf[..n]; + handler.handle_data(data).await; + } + None => (), + } + }; + } + }; + + join(log_fut, reciever_fut).await; + } + + /// Creates the futures needed for the logger from a given class + /// This can be used in cases where the usb device is already in use for another connection + pub async fn create_future_from_class<'d, D>(&'d self, class: CdcAcmClass<'d, D>) + where + D: Driver<'d>, + { + let (mut sender, mut receiver) = class.split(); + loop { + self.run_logger_class(&mut sender, &mut receiver).await; + } + } +} + +impl log::Log for UsbLogger { + fn enabled(&self, _metadata: &Metadata) -> bool { + true + } + + fn log(&self, record: &Record) { + if self.enabled(record.metadata()) { + if let Some(custom_style) = self.custom_style { + custom_style(record, &mut Writer(&self.buffer)); + } else { + let _ = write!(Writer(&self.buffer), "{}\r\n", record.args()); + } + } + } + + fn flush(&self) {} +} + +/// A writer that writes to the USB logger buffer. +pub struct Writer<'d, const N: usize>(&'d Pipe); + +impl<'d, const N: usize> core::fmt::Write for Writer<'d, N> { + fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { + // The Pipe is implemented in such way that we cannot + // write across the wraparound discontinuity. + let b = s.as_bytes(); + if let Ok(n) = self.0.try_write(b) { + if n < b.len() { + // We wrote some data but not all, attempt again + // as the reason might be a wraparound in the + // ring buffer, which resolves on second attempt. + let _ = self.0.try_write(&b[n..]); + } + } + Ok(()) + } +} diff --git a/rmk/src/matrix.rs b/rmk/src/matrix.rs index 614f0266..30512e76 100644 --- a/rmk/src/matrix.rs +++ b/rmk/src/matrix.rs @@ -3,7 +3,6 @@ use crate::{ keyboard::{key_event_channel, KeyEvent}, CONNECTION_STATE, }; -use defmt::{error, info, Format}; use embassy_time::{Instant, Timer}; use embedded_hal::digital::{InputPin, OutputPin}; #[cfg(feature = "async_matrix")] @@ -28,7 +27,7 @@ pub(crate) trait MatrixTrait { // Run the matrix async fn run(&mut self) { - // We don't check disconnected state because disconnection means the task will be dropped + // We don't check disconnected state because disconnection means the task will be dropped loop { self.wait_for_connected().await; self.scan().await; @@ -59,7 +58,8 @@ pub(crate) trait MatrixTrait { } /// KeyState represents the state of a key. -#[derive(Copy, Clone, Debug, Format)] +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct KeyState { // True if the key is pressed pub(crate) pressed: bool, @@ -187,7 +187,7 @@ impl< /// Do matrix scanning, the result is stored in matrix's key_state field. async fn scan(&mut self) { - defmt::info!("Matrix scanning"); + info!("Matrix scanning"); loop { #[cfg(feature = "async_matrix")] self.wait_for_key().await; diff --git a/rmk/src/split/central.rs b/rmk/src/split/central.rs index bea8718d..e59ccf7d 100644 --- a/rmk/src/split/central.rs +++ b/rmk/src/split/central.rs @@ -1,6 +1,5 @@ use core::cell::RefCell; -use defmt::info; use embassy_executor::Spawner; use embassy_time::{Instant, Timer}; use embassy_usb::driver::Driver; @@ -343,7 +342,7 @@ impl< const COL: usize = INPUT_PIN_NUM; async fn scan(&mut self) { - defmt::info!("Central matrix scanning"); + info!("Central matrix scanning"); loop { #[cfg(feature = "async_matrix")] self.wait_for_key().await; @@ -412,7 +411,6 @@ impl< #[cfg(feature = "async_matrix")] async fn wait_for_key(&mut self) { - use defmt::info; use embassy_futures::select::select_slice; use heapless::Vec; diff --git a/rmk/src/split/driver.rs b/rmk/src/split/driver.rs index b7264542..872382c0 100644 --- a/rmk/src/split/driver.rs +++ b/rmk/src/split/driver.rs @@ -5,10 +5,10 @@ use core::sync::atomic::Ordering; use super::SplitMessage; use crate::keyboard::{key_event_channel, KeyEvent}; use crate::CONNECTION_STATE; -use defmt::{debug, error, warn}; use embassy_futures::select::select; -#[derive(Debug, Clone, Copy, defmt::Format)] +#[derive(Debug, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) enum SplitDriverError { SerialError, EmptyMessage, @@ -70,13 +70,13 @@ impl< .write(&SplitMessage::ConnectionState(conn_state)) .await { - error!("SplitDriver write error: {}", e); + error!("SplitDriver write error: {:?}", e); } loop { match select(self.receiver.read(), embassy_time::Timer::after_millis(200)).await { embassy_futures::select::Either::First(read_result) => match read_result { Ok(received_message) => { - debug!("Received peripheral message: {}", received_message); + debug!("Received peripheral message: {:?}", received_message); if let SplitMessage::Key(e) = received_message { // Check row/col if e.row as usize > ROW || e.col as usize > COL { @@ -112,7 +112,7 @@ impl< .write(&SplitMessage::ConnectionState(conn_state)) .await { - error!("SplitDriver write error: {}", e); + error!("SplitDriver write error: {:?}", e); }; } } diff --git a/rmk/src/split/mod.rs b/rmk/src/split/mod.rs index 0396807a..0860f1d3 100644 --- a/rmk/src/split/mod.rs +++ b/rmk/src/split/mod.rs @@ -16,8 +16,9 @@ pub(crate) mod serial; pub const SPLIT_MESSAGE_MAX_SIZE: usize = SplitMessage::POSTCARD_MAX_SIZE + 4; /// Message used from central & peripheral communication -#[derive(Serialize, Deserialize, Debug, Clone, Copy, MaxSize, defmt::Format)] #[repr(u8)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, MaxSize)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) enum SplitMessage { /// Key event from peripheral to central Key(KeyEvent), diff --git a/rmk/src/split/nrf/central.rs b/rmk/src/split/nrf/central.rs index 2ed88acd..21ba3567 100644 --- a/rmk/src/split/nrf/central.rs +++ b/rmk/src/split/nrf/central.rs @@ -1,6 +1,5 @@ use core::sync::atomic::{AtomicBool, Ordering}; -use defmt::{error, info}; use embassy_futures::{join::join, select::select}; use embassy_sync::{ blocking_mutex::raw::CriticalSectionRawMutex, @@ -84,11 +83,11 @@ pub(crate) async fn run_ble_client( if let Ok(_) = CONNECTING_CLIENT.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) { - info!("Starting connect to {}", addrs); + info!("Starting connect to {:?}", addrs); let conn = match central::connect(sd, &config).await { Ok(conn) => conn, Err(e) => { - error!("BLE peripheral connect error: {}", e); + error!("BLE peripheral connect error: {:?}", e); CONNECTING_CLIENT.store(false, Ordering::SeqCst); continue; } @@ -103,14 +102,14 @@ pub(crate) async fn run_ble_client( let ble_client: BleSplitCentralClient = match gatt_client::discover(&conn).await { Ok(client) => client, Err(e) => { - error!("BLE discover error: {}", e); + error!("BLE discover error: {:?}", e); continue; } }; // Enable notifications from the peripherals if let Err(e) = ble_client.message_to_central_cccd_write(true).await { - error!("BLE message_to_central_cccd_write error: {}", e); + error!("BLE message_to_central_cccd_write error: {:?}", e); continue; } @@ -120,7 +119,7 @@ pub(crate) async fn run_ble_client( match postcard::from_bytes(&message) { Ok(split_message) => { if let Err(e) = receive_sender.try_send(split_message) { - error!("BLE_SYNC_CHANNEL send message error: {}", e); + error!("BLE_SYNC_CHANNEL send message error: {:?}", e); } } Err(e) => { @@ -138,7 +137,7 @@ pub(crate) async fn run_ble_client( match postcard::to_slice(&message, &mut buf) { Ok(_bytes) => { if let Err(e) = ble_client.message_to_peripheral_write(&buf).await { - error!("BLE message_to_peripheral_write error: {}", e); + error!("BLE message_to_peripheral_write error: {:?}", e); } } Err(e) => error!("Postcard serialize split message error: {}", e), diff --git a/rmk/src/split/nrf/peripheral.rs b/rmk/src/split/nrf/peripheral.rs index 69244192..3c99315d 100644 --- a/rmk/src/split/nrf/peripheral.rs +++ b/rmk/src/split/nrf/peripheral.rs @@ -4,7 +4,6 @@ use crate::split::peripheral::SplitPeripheral; use crate::split::{SplitMessage, SPLIT_MESSAGE_MAX_SIZE}; use crate::MatrixTrait; use core::mem; -use defmt::error; use embassy_executor::Spawner; use embassy_futures::block_on; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; @@ -95,7 +94,6 @@ pub(crate) async fn initialize_nrf_ble_split_peripheral_and_run< peripheral_addr: [u8; 6], spawner: Spawner, ) -> ! { - use defmt::info; use embassy_futures::select::select3; use nrf_softdevice::ble::gatt_server; @@ -156,10 +154,13 @@ pub(crate) async fn initialize_nrf_ble_split_peripheral_and_run< // Use the immutable ref of `Softdevice` to run the softdevice_task // The mumtable ref is used for configuring Flash and BleServer let sdv = unsafe { nrf_softdevice::Softdevice::steal() }; - defmt::unwrap!(spawner.spawn(softdevice_task(sdv))) + spawner + .spawn(softdevice_task(sdv)) + .expect("Failed to start softdevice task"); }; - let server = defmt::unwrap!(BleSplitPeripheralServer::new(sd)); + let server = + BleSplitPeripheralServer::new(sd).expect("Failed to start BLE split peripheral server"); loop { CONNECTION_STATE.store(false, core::sync::atomic::Ordering::Release); @@ -170,7 +171,7 @@ pub(crate) async fn initialize_nrf_ble_split_peripheral_and_run< let conn = match advertise_connectable(sd, advertisement, &Default::default()).await { Ok(conn) => conn, Err(e) => { - defmt::error!("Split peripheral advertise error: {}", e); + error!("Split peripheral advertise error: {:?}", e); continue; } }; @@ -196,7 +197,7 @@ pub(crate) async fn initialize_nrf_ble_split_peripheral_and_run< let mut success = false; for _i in 0..3 { if let Err(e) = sender.try_send(message) { - error!("Send split message to reader error: {}", e); + error!("Send split message to reader error: {:?}", e); continue; } success = true; @@ -207,7 +208,7 @@ pub(crate) async fn initialize_nrf_ble_split_peripheral_and_run< block_on(sender.send(message)); } } - Err(e) => defmt::error!("Postcard deserialize split message error: {}", e), + Err(e) => error!("Postcard deserialize split message error: {}", e), } } }, diff --git a/rmk/src/split/peripheral.rs b/rmk/src/split/peripheral.rs index 1a1efa00..370dfa29 100644 --- a/rmk/src/split/peripheral.rs +++ b/rmk/src/split/peripheral.rs @@ -9,7 +9,6 @@ use crate::direct_pin::DirectPinMatrix; use crate::keyboard::key_event_channel; use crate::matrix::Matrix; use crate::CONNECTION_STATE; -use defmt::{error, info}; #[cfg(feature = "_nrf_ble")] use embassy_executor::Spawner; use embassy_futures::select::select; diff --git a/rmk/src/split/serial/mod.rs b/rmk/src/split/serial/mod.rs index 66503bf4..3e9e3a70 100644 --- a/rmk/src/split/serial/mod.rs +++ b/rmk/src/split/serial/mod.rs @@ -1,4 +1,3 @@ -use defmt::{error, info}; use embedded_io_async::{Read, Write}; use crate::{ diff --git a/rmk/src/storage/eeconfig.rs b/rmk/src/storage/eeconfig.rs index d96dee09..45979603 100644 --- a/rmk/src/storage/eeconfig.rs +++ b/rmk/src/storage/eeconfig.rs @@ -14,6 +14,7 @@ pub(crate) struct Eeconfig { #[bitfield(u16, order = Msb)] #[derive(PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct EeKeymapConfig { #[bits(1)] swap_control_capslock: bool, @@ -47,6 +48,7 @@ pub(crate) struct EeKeymapConfig { #[bitfield(u8, order = Msb)] #[derive(PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct EeBacklightConfig { #[bits(1)] enable: bool, @@ -60,6 +62,7 @@ pub(crate) struct EeBacklightConfig { #[bitfield(u8, order = Msb)] #[derive(PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct EeAudioConfig { #[bits(1)] enable: bool, @@ -71,6 +74,7 @@ pub(crate) struct EeAudioConfig { #[bitfield(u64, order = Msb)] #[derive(PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) struct EeRgbLightConfig { #[bits(1)] enable: bool, diff --git a/rmk/src/storage/mod.rs b/rmk/src/storage/mod.rs index f2c2b9ef..1829b724 100644 --- a/rmk/src/storage/mod.rs +++ b/rmk/src/storage/mod.rs @@ -5,7 +5,6 @@ use crate::config::StorageConfig; use byteorder::{BigEndian, ByteOrder}; use core::fmt::Debug; use core::ops::Range; -use defmt::{debug, error, info, Format}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; use embedded_storage::nor_flash::NorFlash; @@ -31,7 +30,8 @@ pub(crate) static FLASH_CHANNEL: Channel { - info!("Saving bond info: {}", b); + info!("Saving bond info: {:?}", b); let data = StorageData::BondInfo(b); store_item::( &mut self.flash, diff --git a/rmk/src/storage/nor_flash/esp_partition.rs b/rmk/src/storage/nor_flash/esp_partition.rs index e6e615ff..b74efa9c 100644 --- a/rmk/src/storage/nor_flash/esp_partition.rs +++ b/rmk/src/storage/nor_flash/esp_partition.rs @@ -4,7 +4,6 @@ use core::{ ops::Deref, }; -use defmt::{info, warn}; use embassy_time::Timer; use embedded_storage_async::nor_flash::{ ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash, diff --git a/rmk/src/usb/mod.rs b/rmk/src/usb/mod.rs index 7b724a33..41f3439c 100644 --- a/rmk/src/usb/mod.rs +++ b/rmk/src/usb/mod.rs @@ -1,7 +1,6 @@ pub(crate) mod descriptor; use core::sync::atomic::{AtomicU8, Ordering}; -use defmt::info; use embassy_time::Timer; use embassy_usb::{ class::hid::{Config, HidReaderWriter, HidWriter, ReportId, RequestHandler, State}, @@ -19,6 +18,12 @@ use crate::{ CONNECTION_STATE, }; +#[cfg(feature = "log")] +use { + crate::logger::usb_logger::{LoggerState, MAX_PACKET_SIZE}, + embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender}, +}; + pub(crate) static USB_STATE: AtomicU8 = AtomicU8::new(UsbState::Disabled as u8); /// USB state @@ -79,6 +84,10 @@ pub(crate) struct KeyboardUsbDevice<'d, D: Driver<'d>> { pub(crate) keyboard_hid_reader: UsbHidReader<'d, D, 1>, pub(crate) other_hid_writer: UsbHidWriter<'d, D, 9>, pub(crate) via_hid: UsbHidReaderWriter<'d, D, 32, 32>, + #[cfg(feature = "log")] + pub(crate) usb_logger_sender: Sender<'d, D>, + #[cfg(feature = "log")] + pub(crate) usb_logger_receiver: Receiver<'d, D>, } impl> KeyboardUsbDevice<'static, D> { @@ -160,6 +169,23 @@ impl> KeyboardUsbDevice<'static, D> { let via_hid: HidReaderWriter<'_, D, 32, 32> = HidReaderWriter::new(&mut builder, VIA_STATE.init(State::new()), via_config); + #[cfg(feature = "log")] + let (sender, receiver) = { + static LOGGER_STATE: StaticCell> = StaticCell::new(); + let usb_logger: CdcAcmClass<'_, D> = CdcAcmClass::new( + &mut builder, + &mut LOGGER_STATE.init(LoggerState::new()).state, + MAX_PACKET_SIZE as u16, + ); + + // This should be only run once + unsafe { + let _ = log::set_logger_racy(&crate::USB_LOGGER) + .map(|()| log::set_max_level_racy(log::LevelFilter::Trace)); + } + usb_logger.split() + }; + // Build usb device let usb = builder.build(); let (reader, writer) = keyboard_hid.split(); @@ -169,6 +195,10 @@ impl> KeyboardUsbDevice<'static, D> { keyboard_hid_writer: UsbHidWriter::new(writer), other_hid_writer: UsbHidWriter::new(other_hid), via_hid: UsbHidReaderWriter::new(via_hid), + #[cfg(feature = "log")] + usb_logger_sender: sender, + #[cfg(feature = "log")] + usb_logger_receiver: receiver, } } } @@ -177,7 +207,7 @@ struct UsbRequestHandler {} impl RequestHandler for UsbRequestHandler { fn set_report(&mut self, id: ReportId, data: &[u8]) -> OutResponse { - info!("Set report for {}: {}", id, data); + info!("Set report for {:?}: {:?}", id, data); OutResponse::Accepted } } diff --git a/rmk/src/via/keycode_convert.rs b/rmk/src/via/keycode_convert.rs index 132e5e88..fa4ff86a 100644 --- a/rmk/src/via/keycode_convert.rs +++ b/rmk/src/via/keycode_convert.rs @@ -1,4 +1,3 @@ -use defmt::warn; use num_enum::FromPrimitive; use crate::{ @@ -74,7 +73,7 @@ pub(crate) fn to_via_keycode(key_action: KeyAction) -> u16 { } KeyAction::TapHold(tap, hold) => { warn!( - "Tap hold action is not supported: tap: {}, hold: {}", + "Tap hold action is not supported: tap: {:?}, hold: {:?}", tap, hold ); 0 diff --git a/rmk/src/via/process.rs b/rmk/src/via/process.rs index e6018421..a1383d22 100644 --- a/rmk/src/via/process.rs +++ b/rmk/src/via/process.rs @@ -10,7 +10,6 @@ use crate::{ }; use byteorder::{BigEndian, ByteOrder, LittleEndian}; use core::cell::RefCell; -use defmt::{debug, error, info, warn}; use embassy_time::Instant; use num_enum::{FromPrimitive, TryFromPrimitive}; @@ -51,7 +50,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> match hid_interface.write_serialize(&via_report).await { Ok(_) => Ok(()), Err(e) => { - error!("Send via report error: {}", e); + error!("Send via report error: {:?}", e); // Printed error message, ignore the error type Err(()) } @@ -60,7 +59,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> Err(e) => { if e != HidError::UsbDisabled && e != HidError::BleDisconnected { // Don't print message if the USB endpoint is disabled(aka not connected) - error!("Read via report error: {}", e); + error!("Read via report error: {:?}", e); } // Printed error message, ignore the error type Err(()) @@ -148,7 +147,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> let keycode = BigEndian::read_u16(&report.output_data[4..6]); let action = from_via_keycode(keycode); info!( - "Setting keycode: 0x{:02X} at ({},{}), layer {} as {}", + "Setting keycode: 0x{:X} at ({},{}), layer {} as {:?}", keycode, row, col, layer, action ); keymap.borrow_mut().set_action_at( @@ -205,7 +204,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> report.input_data[4..4 + size] .copy_from_slice(&self.keymap.borrow().macro_cache[offset..offset + size]); debug!( - "Get macro buffer: offset: {}, data: {:02X}", + "Get macro buffer: offset: {}, data: {:?}", offset, report.input_data ); } else { @@ -228,6 +227,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> // Update macro cache info!("Setting macro buffer, offset: {}, size: {}", offset, size); + #[cfg(feature = "defmt")] info!("Data: {=[u8]:x}", report.output_data[4..]); self.keymap.borrow_mut().macro_cache[offset as usize..end as usize] .copy_from_slice(&report.output_data[4..4 + size as usize]); diff --git a/rmk/src/via/vial.rs b/rmk/src/via/vial.rs index 42d07128..8ba7dffc 100644 --- a/rmk/src/via/vial.rs +++ b/rmk/src/via/vial.rs @@ -1,5 +1,4 @@ use byteorder::{ByteOrder, LittleEndian}; -use defmt::debug; use num_enum::FromPrimitive; use crate::usb::descriptor::ViaReport; From 78ab737220492178dcab1eef1442e6fdc7d7bb36 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Mon, 23 Dec 2024 11:59:40 +0800 Subject: [PATCH 2/2] chore: update log Signed-off-by: Haobo Gu --- rmk/src/keyboard.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rmk/src/keyboard.rs b/rmk/src/keyboard.rs index e08e7b6a..dbb54481 100644 --- a/rmk/src/keyboard.rs +++ b/rmk/src/keyboard.rs @@ -583,7 +583,7 @@ impl<'a, const ROW: usize, const COL: usize, const NUM_LAYER: usize> return false; }) { // Release the hold after tap key - info!("Releasing hold after tap: {} {}", tap_action, key_event); + info!("Releasing hold after tap: {:?} {:?}", tap_action, key_event); self.process_key_action_normal(tap_action, key_event).await; self.hold_after_tap[index] = None; return;