1#[cfg(feature = "std")]
2mod distinct_reports;
3mod event_scheduler;
4pub mod hid_keyboard_reporter;
6
7use core::cmp::PartialEq;
8use core::fmt::Debug;
9use core::marker::Copy;
10use core::ops::Index;
11
12use serde::Deserialize;
13
14use crate::input;
15use crate::key;
16
17use key::Event;
18
19#[cfg(feature = "std")]
20pub use distinct_reports::DistinctReports;
21use event_scheduler::EventScheduler;
22use hid_keyboard_reporter::HIDKeyboardReporter;
23
24pub const MAX_PRESSED_KEYS: usize = 16;
26
27const MAX_QUEUED_INPUT_EVENTS: usize = 32;
28
29pub const INPUT_QUEUE_TICK_DELAY: u8 = 1;
31
32#[derive(Debug, PartialEq)]
34pub struct KeymapOutput {
35 pressed_key_codes: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }>,
36}
37
38impl Default for KeymapOutput {
39 fn default() -> Self {
40 Self {
41 pressed_key_codes: heapless::Vec::new(),
42 }
43 }
44}
45
46impl KeymapOutput {
47 pub fn new(pressed_key_codes: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }>) -> Self {
49 Self { pressed_key_codes }
50 }
51
52 pub fn pressed_key_codes(&self) -> heapless::Vec<u8, 24> {
54 let mut result = heapless::Vec::new();
55
56 let modifiers = self
57 .pressed_key_codes
58 .iter()
59 .fold(key::KeyboardModifiers::new(), |acc, &ko| {
60 acc.union(&ko.key_modifiers())
61 });
62
63 result.extend(modifiers.as_key_codes());
64
65 result.extend(
66 self.pressed_key_codes
67 .iter()
68 .flat_map(|ko| match ko.key_code() {
69 key::KeyUsage::Keyboard(kc) => Some(kc),
70 _ => None,
71 }),
72 );
73
74 result
75 }
76
77 pub fn as_hid_boot_keyboard_report(&self) -> [u8; 8] {
79 let mut report = [0u8; 8];
80
81 let modifiers = self
82 .pressed_key_codes
83 .iter()
84 .fold(key::KeyboardModifiers::new(), |acc, &ko| {
85 acc.union(&ko.key_modifiers())
86 });
87
88 report[0] = modifiers.as_byte();
89
90 let key_codes = self
91 .pressed_key_codes
92 .iter()
93 .flat_map(|ko| match ko.key_code() {
94 key::KeyUsage::Keyboard(kc) => Some(kc),
95 _ => None,
96 })
97 .filter(|&kc| kc != 0);
98
99 for (i, key_code) in key_codes.take(6).enumerate() {
100 report[i + 2] = key_code;
101 }
102
103 report
104 }
105
106 pub fn pressed_custom_codes(&self) -> heapless::Vec<u8, 24> {
108 self.pressed_key_codes
109 .iter()
110 .flat_map(|ko| match ko.key_code() {
111 key::KeyUsage::Custom(kc) => Some(kc),
112 _ => None,
113 })
114 .collect()
115 }
116}
117
118#[derive(Debug)]
119struct PendingState<Ev, PKS> {
120 key_path: key::KeyPath,
121 pending_key_state: PKS,
122 queued_events: heapless::Vec<key::Event<Ev>, { MAX_PRESSED_KEYS }>,
123}
124
125#[derive(Deserialize, Debug, Clone, Copy, Eq, PartialEq)]
127pub enum KeymapCallback {
128 Reset,
130 ResetToBootloader,
132 Custom(u8, u8),
134}
135
136#[derive(Debug, Clone, Copy)]
138pub struct KeymapContext {
139 pub time_ms: u32,
141
142 pub idle_time_ms: u32,
144}
145
146pub const DEFAULT_KEYMAP_CONTEXT: KeymapContext = KeymapContext {
148 time_ms: 0,
149 idle_time_ms: 0,
150};
151
152pub trait SetKeymapContext {
154 fn set_keymap_context(&mut self, context: KeymapContext);
156}
157
158#[derive(Debug, Clone, Copy, PartialEq, Eq)]
160pub enum KeymapEvent {
161 Callback(KeymapCallback),
163 ResolvedKeyOutput {
165 keymap_index: u16,
167 key_output: key::KeyOutput,
169 },
170}
171
172#[derive(Debug)]
173enum CallbackFunction {
174 ExternC(extern "C" fn() -> ()),
176 Rust(fn() -> ()),
178}
179
180pub struct Keymap<Ctx, Ev: Debug, PKS, KS, I> {
182 key_definitions: I,
183 context: Ctx,
184 pressed_inputs: heapless::Vec<input::PressedInput<KS>, { MAX_PRESSED_KEYS }>,
185 event_scheduler: EventScheduler<Ev>,
186 ms_per_tick: u8,
187 idle_time: u32,
188 hid_reporter: HIDKeyboardReporter,
189 pending_key_state: Option<PendingState<Ev, PKS>>,
190 input_queue: heapless::spsc::Queue<input::Event, { MAX_QUEUED_INPUT_EVENTS }>,
191 input_queue_delay_counter: u8,
192 callbacks: heapless::LinearMap<KeymapCallback, CallbackFunction, 2>,
193}
194
195impl<
196 Ctx: Debug,
197 Ev: Debug,
198 PKS: Debug,
199 KS: Debug,
200 K: key::Key<Context = Ctx, Event = Ev, PendingKeyState = PKS, KeyState = KS> + ?Sized,
201 I: Index<usize, Output = K>,
202 > core::fmt::Debug for Keymap<Ctx, Ev, PKS, KS, I>
203{
204 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
205 f.debug_struct("Keymap")
206 .field("context", &self.context)
207 .field("event_scheduler", &self.event_scheduler)
208 .field("ms_per_tick", &self.ms_per_tick)
209 .field("idle_time", &self.idle_time)
210 .field("hid_reporter", &self.hid_reporter)
211 .field("input_queue", &self.input_queue)
212 .field("input_queue_delay_counter", &self.input_queue_delay_counter)
213 .field("pending_key_state", &self.pending_key_state)
214 .field("pressed_inputs", &self.pressed_inputs)
215 .finish_non_exhaustive()
216 }
217}
218
219impl<
220 Ctx: key::Context<Event = Ev> + SetKeymapContext,
221 Ev: Copy + Debug + PartialEq,
222 PKS,
223 KS: key::KeyState<Context = Ctx, Event = Ev> + Copy,
224 K: key::Key<Context = Ctx, Event = Ev, PendingKeyState = PKS, KeyState = KS> + ?Sized,
225 I: Index<usize, Output = K>,
226 > Keymap<Ctx, Ev, PKS, KS, I>
227{
228 pub const fn new(key_definitions: I, context: Ctx) -> Self {
230 Self {
231 key_definitions,
232 context,
233 pressed_inputs: heapless::Vec::new(),
234 event_scheduler: EventScheduler::new(),
235 ms_per_tick: 1,
236 idle_time: 0,
237 hid_reporter: HIDKeyboardReporter::new(),
238 pending_key_state: None,
239 input_queue: heapless::spsc::Queue::new(),
240 input_queue_delay_counter: 0,
241 callbacks: heapless::LinearMap::new(),
242 }
243 }
244
245 pub fn init(&mut self) {
247 self.pressed_inputs.clear();
248 self.event_scheduler.init();
249 self.hid_reporter.init();
250 self.pending_key_state = None;
251 while !self.input_queue.is_empty() {
252 self.input_queue.dequeue().unwrap();
253 }
254 self.input_queue_delay_counter = 0;
255 self.ms_per_tick = 1;
256 self.idle_time = 0;
257 }
258
259 pub fn set_callback(&mut self, callback_id: KeymapCallback, callback_fn: fn() -> ()) {
263 self.callbacks
264 .insert(callback_id, CallbackFunction::Rust(callback_fn))
265 .unwrap();
266 }
267
268 pub fn set_callback_extern(
272 &mut self,
273 callback_id: KeymapCallback,
274 callback_fn: extern "C" fn() -> (),
275 ) {
276 self.callbacks
277 .insert(callback_id, CallbackFunction::ExternC(callback_fn))
278 .unwrap();
279 }
280
281 pub fn set_ms_per_tick(&mut self, ms_per_tick: u8) {
283 self.ms_per_tick = ms_per_tick;
284 }
285
286 fn resolve_pending_key_state(&mut self, key_state: KS) {
289 if let Some(PendingState {
290 key_path,
291 queued_events,
292 ..
293 }) = self.pending_key_state.take()
294 {
295 let keymap_index = key_path[0];
297 self.event_scheduler
298 .cancel_events_for_keymap_index(keymap_index);
299
300 self.pressed_inputs
302 .push(input::PressedInput::pressed_key(key_state, keymap_index))
303 .unwrap();
304
305 let mut i = 1;
309 let mut old_input_queue: heapless::spsc::Queue<input::Event, MAX_QUEUED_INPUT_EVENTS> =
310 core::mem::take(&mut self.input_queue);
311
312 let (pending_input_ev, queued_events): (
316 heapless::Vec<key::Event<Ev>, { MAX_PRESSED_KEYS }>,
317 heapless::Vec<key::Event<Ev>, { MAX_PRESSED_KEYS }>,
318 ) = queued_events.iter().partition(|ev| match ev {
319 key::Event::Input(input::Event::Press {
320 keymap_index: queued_kmi,
321 }) => *queued_kmi == keymap_index,
322 key::Event::Input(input::Event::Release {
323 keymap_index: queued_kmi,
324 }) => *queued_kmi == keymap_index,
325 key::Event::Key {
326 keymap_index: queued_kmi,
327 ..
328 } => *queued_kmi == keymap_index,
329 _ => false,
330 });
331
332 for ev in queued_events.iter().chain(pending_input_ev.last()) {
333 match ev {
334 key::Event::Input(ie) => {
335 self.input_queue.enqueue(*ie).unwrap();
336 }
337 _ => {
338 self.event_scheduler.schedule_after(i, *ev);
339 i += 1;
340 }
341 }
342 }
343
344 while let Some(ie) = old_input_queue.dequeue() {
345 self.input_queue.enqueue(ie).unwrap();
346 }
347
348 self.handle_pending_events();
349
350 if let Some(key_state) = key_state.key_output() {
352 let km_ev = KeymapEvent::ResolvedKeyOutput {
353 keymap_index,
354 key_output: key_state,
355 };
356 self.handle_event(key::Event::Keymap(km_ev));
357 }
358 }
359 }
360
361 pub fn handle_input(&mut self, ev: input::Event) {
363 self.idle_time = 0;
364
365 if self.input_queue.is_full() {
366 return;
367 }
368
369 self.input_queue.enqueue(ev).unwrap();
370
371 if self.input_queue_delay_counter == 0 {
372 let ie = self.input_queue.dequeue().unwrap();
373 self.process_input(ie);
374 self.input_queue_delay_counter = INPUT_QUEUE_TICK_DELAY;
375 }
376 }
377
378 fn has_pressed_input_with_keymap_index(&self, keymap_index: u16) -> bool {
379 self.pressed_inputs.iter().any(|pi| match pi {
380 &input::PressedInput::Key(input::PressedKey {
381 keymap_index: ki, ..
382 }) => keymap_index == ki,
383 _ => false,
384 })
385 }
386
387 fn process_input(&mut self, ev: input::Event) {
388 if let Some(PendingState {
389 key_path,
390 pending_key_state,
391 queued_events,
392 ..
393 }) = &mut self.pending_key_state
394 {
395 queued_events.push(ev.into()).unwrap();
396
397 let pending_key = &self.key_definitions[key_path[0] as usize];
398 let pending_key = pending_key.lookup(&key_path[1..]);
399 let (ks, pke) = pending_key.handle_event(
400 pending_key_state,
401 &self.context,
402 key_path.clone(),
403 ev.into(),
404 );
405
406 pke.into_iter()
407 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
408
409 match ks {
410 Some(key::PressedKeyResult::Resolved(ks)) => {
411 self.resolve_pending_key_state(ks);
412 }
413 Some(key::PressedKeyResult::Pending(kp, pks)) => {
414 *key_path = kp;
415 *pending_key_state = pks;
416 }
417 None => {}
418 }
419 } else {
420 self.pressed_inputs.iter_mut().for_each(|pi| {
422 if let input::PressedInput::Key(pressed_key) = pi {
423 pressed_key
424 .handle_event(&self.context, ev.into())
425 .into_iter()
426 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
427 }
428 });
429
430 self.context
431 .handle_event(ev.into())
432 .into_iter()
433 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
434
435 match ev {
436 input::Event::Press { keymap_index }
437 if !self.has_pressed_input_with_keymap_index(keymap_index) =>
438 {
439 let key = &self.key_definitions[keymap_index as usize];
440
441 let mut key_path = key::KeyPath::new();
442 key_path.push(keymap_index).unwrap();
443 let (pk, pke) = key.new_pressed_key(&self.context, key_path);
444
445 pke.into_iter()
446 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
447
448 match pk {
449 key::PressedKeyResult::Resolved(key_state) => {
450 self.pressed_inputs
451 .push(input::PressedInput::pressed_key(key_state, keymap_index))
452 .unwrap();
453
454 if let Some(key_output) = key_state.key_output() {
456 let km_ev = KeymapEvent::ResolvedKeyOutput {
457 keymap_index,
458 key_output,
459 };
460 self.handle_event(key::Event::Keymap(km_ev));
461 }
462 }
463 key::PressedKeyResult::Pending(key_path, pending_key_state) => {
464 self.pending_key_state = Some(PendingState {
465 key_path,
466 pending_key_state,
467 queued_events: heapless::Vec::new(),
468 });
469 }
470 }
471 }
472 input::Event::Release { keymap_index } => {
473 self.pressed_inputs
474 .iter()
475 .position(|pi| match pi {
476 &input::PressedInput::Key(input::PressedKey {
477 keymap_index: ki,
478 ..
479 }) => keymap_index == ki,
480 _ => false,
481 })
482 .map(|i| self.pressed_inputs.remove(i));
483
484 self.event_scheduler
485 .cancel_events_for_keymap_index(keymap_index);
486 }
487
488 input::Event::VirtualKeyPress { key_output } => {
489 let pressed_key = input::PressedInput::Virtual(key_output);
490 self.pressed_inputs.push(pressed_key).unwrap();
491 }
492 input::Event::VirtualKeyRelease { key_output } => {
493 self.pressed_inputs
495 .iter()
496 .position(|k| match k {
497 input::PressedInput::Virtual(ko) => key_output == *ko,
498 _ => false,
499 })
500 .map(|i| self.pressed_inputs.remove(i));
501 }
502
503 _ => {}
504 }
505 }
506
507 self.handle_pending_events();
508 }
509
510 fn handle_event(&mut self, ev: key::Event<Ev>) {
513 if let key::Event::Keymap(KeymapEvent::Callback(callback_id)) = ev {
514 match self.callbacks.get(&callback_id) {
515 Some(CallbackFunction::Rust(callback_fn)) => {
516 callback_fn();
517 }
518 Some(CallbackFunction::ExternC(callback_fn)) => {
519 callback_fn();
520 }
521 None => {}
522 }
523 }
524
525 if let Some(PendingState {
527 key_path,
528 pending_key_state,
529 ..
530 }) = &mut self.pending_key_state
531 {
532 let pending_key = &self.key_definitions[key_path[0] as usize];
533 let pending_key = pending_key.lookup(&key_path[1..]);
534 let (ks, pke) =
535 pending_key.handle_event(pending_key_state, &self.context, key_path.clone(), ev);
536
537 pke.into_iter()
538 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
539
540 match ks {
541 Some(key::PressedKeyResult::Resolved(ks)) => {
542 self.resolve_pending_key_state(ks);
543 }
544 Some(key::PressedKeyResult::Pending(kp, pks)) => {
545 *key_path = kp;
546 *pending_key_state = pks;
547 }
548 None => {}
549 }
550 }
551
552 self.pressed_inputs.iter_mut().for_each(|pi| {
554 if let input::PressedInput::Key(input::PressedKey {
555 key_state,
556 keymap_index,
557 }) = pi
558 {
559 key_state
560 .handle_event(&self.context, *keymap_index, ev)
561 .into_iter()
562 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
563 }
564 });
565
566 self.context
568 .handle_event(ev)
569 .into_iter()
570 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
571
572 if let Event::Input(input_ev) = ev {
573 self.process_input(input_ev);
574 }
575 }
576
577 fn handle_pending_events(&mut self) {
578 while let Some(ev) = self.event_scheduler.dequeue() {
580 self.handle_event(ev);
581 }
582 }
583
584 pub fn tick(&mut self) {
586 let km_context = KeymapContext {
587 time_ms: self.event_scheduler.schedule_counter,
588 idle_time_ms: self.idle_time,
589 };
590 self.context.set_keymap_context(km_context);
591
592 if !self.input_queue.is_empty() && self.input_queue_delay_counter == 0 {
593 let ie = self.input_queue.dequeue().unwrap();
594 self.process_input(ie);
595 self.input_queue_delay_counter = INPUT_QUEUE_TICK_DELAY;
596 }
597
598 if self.input_queue_delay_counter > 0 {
599 self.input_queue_delay_counter -= 1;
600 }
601
602 self.event_scheduler.tick(self.ms_per_tick);
603
604 self.handle_pending_events();
605
606 self.idle_time += self.ms_per_tick as u32;
607 }
608
609 pub fn pressed_keys(&self) -> heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> {
611 let pressed_key_codes = self.pressed_inputs.iter().filter_map(|pi| match pi {
612 input::PressedInput::Key(pressed_key) => pressed_key.key_output(),
613 &input::PressedInput::Virtual(key_output) => Some(key_output),
614 });
615
616 pressed_key_codes.collect()
617 }
618
619 pub fn report_output(&mut self) -> KeymapOutput {
621 self.hid_reporter.update(self.pressed_keys());
622 self.hid_reporter.report_sent();
623
624 KeymapOutput::new(self.hid_reporter.reportable_key_outputs())
625 }
626
627 #[doc(hidden)]
629 pub fn boot_keyboard_report(&self) -> [u8; 8] {
630 KeymapOutput::new(self.pressed_keys()).as_hid_boot_keyboard_report()
631 }
632
633 #[doc(hidden)]
634 pub fn has_scheduled_events(&self) -> bool {
635 !self.event_scheduler.pending_events.is_empty()
636 || !self.event_scheduler.scheduled_events.is_empty()
637 || !self.input_queue.is_empty()
638 }
639}
640
641#[cfg(test)]
642mod tests {
643 use super::*;
644
645 use crate::tuples;
646
647 #[test]
648 fn test_keymap_output_pressed_key_codes_includes_modifier_key_code() {
649 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
651 input.push(key::KeyOutput::from_key_code(0x04)).unwrap();
652 input.push(key::KeyOutput::from_key_code(0xE0)).unwrap();
653
654 let keymap_output = KeymapOutput::new(input);
656 let pressed_key_codes = keymap_output.pressed_key_codes();
657
658 assert!(pressed_key_codes.contains(&0xE0))
660 }
661
662 #[test]
663 fn test_keymap_output_as_hid_boot_keyboard_report_gathers_modifiers() {
664 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
666 input.push(key::KeyOutput::from_key_code(0x04)).unwrap();
667 input.push(key::KeyOutput::from_key_code(0xE0)).unwrap();
668
669 let keymap_output = KeymapOutput::new(input);
671 let actual_report: [u8; 8] = keymap_output.as_hid_boot_keyboard_report();
672
673 let expected_report: [u8; 8] = [0x01, 0, 0x04, 0, 0, 0, 0, 0];
675 assert_eq!(expected_report, actual_report);
676 }
677
678 #[test]
679 fn test_keymap_with_keyboard_key_with_composite_context() {
680 use key::composite;
681 use key::keyboard;
682 use tuples::Keys1;
683
684 use composite::{Context, Event, KeyState, PendingKeyState};
685
686 type Ctx = Context;
688 type K = composite::Chorded<composite::Layered<composite::TapHold<keyboard::Key>>>;
689 let keys: Keys1<K, Context, Event, PendingKeyState, KeyState> =
690 Keys1::new((composite::Chorded(composite::Layered(composite::TapHold(
691 keyboard::Key::new(0x04),
692 ))),));
693 let context: Ctx = composite::DEFAULT_CONTEXT;
694 let mut keymap = Keymap::new(keys, context);
695
696 keymap.handle_input(input::Event::Press { keymap_index: 0 });
698 let actual_report = keymap.boot_keyboard_report();
699
700 let expected_report: [u8; 8] = [0, 0, 0x04, 0, 0, 0, 0, 0];
702 assert_eq!(expected_report, actual_report);
703 }
704
705 #[test]
706 fn test_keymap_with_composite_keyboard_key() {
707 use key::{composite, keyboard};
708 use tuples::Keys1;
709
710 use composite::{Context, Event, KeyState, PendingKeyState};
711
712 let keys: Keys1<composite::Key, Context, Event, PendingKeyState, KeyState> =
714 Keys1::new((composite::Key::keyboard(keyboard::Key::new(0x04)),));
715 let context: Context = composite::DEFAULT_CONTEXT;
716 let mut keymap = Keymap::new(keys, context);
717
718 keymap.handle_input(input::Event::Press { keymap_index: 0 });
720 let actual_report = keymap.boot_keyboard_report();
721
722 let expected_report: [u8; 8] = [0, 0, 0x04, 0, 0, 0, 0, 0];
724 assert_eq!(expected_report, actual_report);
725 }
726
727 #[test]
728 fn test_keymap_many_input_events_without_tick_or_report() {
729 use key::{composite, keyboard};
730 use tuples::Keys1;
731
732 use composite::{Context, Event, KeyState, PendingKeyState};
733
734 let keys: Keys1<composite::Key, Context, Event, PendingKeyState, KeyState> =
736 Keys1::new((composite::Key::keyboard(keyboard::Key::new(0x04)),));
737 let context: Context = composite::DEFAULT_CONTEXT;
738 let mut keymap = Keymap::new(keys, context);
739
740 for _ in 0..100 {
742 keymap.handle_input(input::Event::Press { keymap_index: 0 });
743 keymap.handle_input(input::Event::Release { keymap_index: 0 });
744 }
745
746 }
749}