From 7f6971b329cea35bb43f4aa8b9f59ca1c3fbaf42 Mon Sep 17 00:00:00 2001 From: Joakim Hulthe Date: Wed, 20 Dec 2023 16:34:25 +0100 Subject: [PATCH] Some cleanup --- lib/src/event.rs | 2 +- lib/src/keyboard.rs | 30 +++++++++++++----- lib/src/usb/keyboard.rs | 57 +++++++++++++++++++++------------- lib/src/usb/keyboard/report.rs | 8 ++--- 4 files changed, 64 insertions(+), 33 deletions(-) diff --git a/lib/src/event.rs b/lib/src/event.rs index 9483cc0..bfc9498 100644 --- a/lib/src/event.rs +++ b/lib/src/event.rs @@ -41,7 +41,7 @@ pub mod button { /// A usb keyboard button was pressed or released. /// - /// This is a lower-level event than a [SwitchEvent], as things like ModTap and Compose are + /// This is a lower-level event than a [switch::Event], as things like ModTap and Compose are /// converted to Presses and Releases. #[derive(Clone, Debug, PartialEq, Eq)] pub enum Event { diff --git a/lib/src/keyboard.rs b/lib/src/keyboard.rs index 4265ced..c8e9f89 100644 --- a/lib/src/keyboard.rs +++ b/lib/src/keyboard.rs @@ -51,8 +51,13 @@ struct State { lights: Lights, } +/// Number of [KbEvents] returned by [KeyboardConfig::create]. pub const KB_SUBSCRIBERS: usize = 2; + +/// Max number of subscribers for [KB_EVENTS]. Equals [KB_SUBSCRIBERS] plus the two used by +/// [layer_switch_task] and [lights::task]. const ACTUAL_KB_SUBSCRIBERS: usize = KB_SUBSCRIBERS + 2; + const KB_EVENT_CAP: usize = 128; static KB_EVENTS: PubSubChannel = PubSubChannel::new(); @@ -115,7 +120,9 @@ impl KeyboardConfig { spawner.must_spawn(layer_switch_task( KbEvents { publisher: KB_EVENTS.immediate_publisher(), - subscriber: KB_EVENTS.subscriber().unwrap(), + subscriber: KB_EVENTS + .subscriber() + .expect("Not enough KbEvents allocated"), }, state, )); @@ -123,14 +130,20 @@ impl KeyboardConfig { spawner.must_spawn(lights::task( KbEvents { publisher: KB_EVENTS.immediate_publisher(), - subscriber: KB_EVENTS.subscriber().unwrap(), + subscriber: KB_EVENTS + .subscriber() + .expect("Not enough KbEvents allocated"), }, state, )); - Some([(); KB_SUBSCRIBERS].map(|_| KbEvents { - publisher: KB_EVENTS.immediate_publisher(), - subscriber: KB_EVENTS.subscriber().unwrap(), + Some([(); KB_SUBSCRIBERS].map(|_| { + KbEvents { + publisher: KB_EVENTS.immediate_publisher(), + subscriber: KB_EVENTS + .subscriber() + .expect("Not enough KbEvents allocated"), + } })) } } @@ -187,8 +200,11 @@ async fn switch_task(switch_num: usize, pin: AnyPin, state: &'static State) -> ! // get current layer let (x, y) = state.current_layer.load(Ordering::Relaxed); - let Some(Layer { buttons }) = state.layers.get(usize::from(y)) - .and_then(|row| row.get(usize::from(x))) else { + let Some(Layer { buttons }) = state + .layers + .get(usize::from(y)) + .and_then(|row| row.get(usize::from(x))) + else { // currently layer is null, do nothing pin.wait_for_high().await; continue; diff --git a/lib/src/usb/keyboard.rs b/lib/src/usb/keyboard.rs index f17d28d..554a4fe 100644 --- a/lib/src/usb/keyboard.rs +++ b/lib/src/usb/keyboard.rs @@ -22,21 +22,15 @@ use usbd_hid::descriptor::SerializedDescriptor; use crate::{ event::button, keyboard::KbEvents, + keypress_handler::keypress_handler, usb::keyboard::report::{KeyboardReport, EMPTY_KEYBOARD_REPORT}, - util::CS, keypress_handler::keypress_handler, + util::CS, }; use super::MAX_PACKET_SIZE; struct Handler; -static CONTEXT: StaticCell = StaticCell::new(); - -static KB_REPORT: Mutex = Mutex::new(Reports { - actual: EMPTY_KEYBOARD_REPORT, - unsent: EMPTY_KEYBOARD_REPORT, -}); - struct Reports { /// The report to be sent to the host machine. actual: KeyboardReport, @@ -50,13 +44,26 @@ struct Context { state: hid::State<'static>, } +/// Set up a USB HID keyboard. This function panics if called more than once. pub async fn setup(builder: &mut Builder<'static, Driver<'static, USB>>, events: KbEvents) { log::info!("setting up usb hid"); - let context = CONTEXT.init(Context { - handler: Handler, - state: hid::State::new(), - }); + let context = { + static CONTEXT: StaticCell = StaticCell::new(); + // this panics if the functon is called twice + CONTEXT.init(Context { + handler: Handler, + state: hid::State::new(), + }) + }; + + let reports = { + static KB_REPORT: Mutex = Mutex::new(Reports { + actual: EMPTY_KEYBOARD_REPORT, + unsent: EMPTY_KEYBOARD_REPORT, + }); + &KB_REPORT + }; let config = hid::Config { //report_descriptor: MouseReport::desc(), @@ -70,8 +77,8 @@ pub async fn setup(builder: &mut Builder<'static, Driver<'static, USB>>, events: let spawner = Spawner::for_current_executor().await; - spawner.must_spawn(task(stream, &context.handler)); - spawner.must_spawn(listen_to_events(events)); + spawner.must_spawn(report_task(stream, &context.handler, reports)); + spawner.must_spawn(event_listener_task(events, reports)); log::info!("done setting up usb keyboard"); } @@ -103,7 +110,7 @@ impl RequestHandler for Handler { type HidStream = HidReaderWriter<'static, Driver<'static, USB>, 256, 256>; #[embassy_executor::task] -async fn listen_to_events(mut events: KbEvents) { +async fn event_listener_task(mut events: KbEvents, reports: &'static Mutex) { let button_events = PubSubChannel::::new(); let mut button_pub = button_events.publisher().unwrap(); let mut button_sub = button_events.subscriber().unwrap(); @@ -117,7 +124,7 @@ async fn listen_to_events(mut events: KbEvents) { }; loop { - let mut r = KB_REPORT.lock().await; + let mut r = reports.lock().await; match event { button::Event::PressKey(k) => { r.actual.press_key(k); @@ -154,21 +161,29 @@ async fn listen_to_events(mut events: KbEvents) { } #[embassy_executor::task] -async fn task(stream: HidStream, handler: &'static Handler) { - if let Err(e) = keyboard_report(stream, handler).await { +async fn report_task( + stream: HidStream, + handler: &'static Handler, + reports: &'static Mutex, +) { + if let Err(e) = keyboard_report(stream, handler, reports).await { log::error!("keyboard error: {e:?}"); } } -async fn keyboard_report(mut stream: HidStream, _handler: &'static Handler) -> Result<(), Error> { +async fn keyboard_report( + mut stream: HidStream, + _handler: &'static Handler, + reports: &'static Mutex, +) -> Result<(), Error> { stream.ready().await; loop { Timer::after(Duration::from_millis(2)).await; let report = { - let mut reports = KB_REPORT.lock().await; + let mut reports = reports.lock().await; reports.unsent = EMPTY_KEYBOARD_REPORT; - reports.actual.clone() + reports.actual }; if report.keycodes != EMPTY_KEYBOARD_REPORT.keycodes { diff --git a/lib/src/usb/keyboard/report.rs b/lib/src/usb/keyboard/report.rs index f09a3a8..3cec46d 100644 --- a/lib/src/usb/keyboard/report.rs +++ b/lib/src/usb/keyboard/report.rs @@ -50,9 +50,9 @@ fn key_to_byte_mask(key: Key) -> (usize, u8) { impl KeyboardReport { #[inline(always)] pub fn set_key(&mut self, key: Key, pressed: bool) { - let (byte, mask) = key_to_byte_mask(key); + let (byte_i, mask) = key_to_byte_mask(key); - if let Some(k) = self.keycodes.get_mut(byte as usize) { + if let Some(k) = self.keycodes.get_mut(byte_i) { if pressed { *k |= mask; } else { @@ -75,8 +75,8 @@ impl KeyboardReport { #[inline(always)] pub fn key_pressed(&mut self, key: Key) -> bool { - let (byte, mask) = key_to_byte_mask(key); - if let Some(k) = self.keycodes.get_mut(byte as usize) { + let (byte_i, mask) = key_to_byte_mask(key); + if let Some(k) = self.keycodes.get_mut(byte_i) { (*k & mask) != 0 } else { log::warn!("Tried to get out-of-range keycode: 0x{:x}", u8::from(key));