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<R, Ev, PKS> {
120 keymap_index: u16,
121 key_ref: R,
122 pending_key_state: PKS,
123 queued_events: heapless::Vec<key::Event<Ev>, { MAX_PRESSED_KEYS }>,
124}
125
126#[derive(Deserialize, Debug, Clone, Copy, Eq, PartialEq)]
128pub enum KeymapCallback {
129 Reset,
131 ResetToBootloader,
133 Custom(u8, u8),
135}
136
137#[derive(Debug, Clone, Copy)]
139pub struct KeymapContext {
140 pub time_ms: u32,
142
143 pub idle_time_ms: u32,
145}
146
147pub const DEFAULT_KEYMAP_CONTEXT: KeymapContext = KeymapContext {
149 time_ms: 0,
150 idle_time_ms: 0,
151};
152
153pub trait SetKeymapContext {
155 fn set_keymap_context(&mut self, context: KeymapContext);
157}
158
159#[derive(Debug, Clone, Copy, PartialEq, Eq)]
161pub enum KeymapEvent {
162 Callback(KeymapCallback),
164 ResolvedKeyOutput {
166 keymap_index: u16,
168 key_output: key::KeyOutput,
170 },
171}
172
173#[derive(Debug)]
174enum CallbackFunction {
175 ExternC(extern "C" fn() -> ()),
177 Rust(fn() -> ()),
179}
180
181pub struct Keymap<I: Index<usize, Output = R>, R, Ctx, Ev: Debug, PKS, KS, S> {
183 key_refs: I,
184 key_system: S,
185 context: Ctx,
186 pressed_inputs: heapless::Vec<input::PressedInput<R, KS>, { MAX_PRESSED_KEYS }>,
187 event_scheduler: EventScheduler<Ev>,
188 ms_per_tick: u8,
189 idle_time: u32,
190 hid_reporter: HIDKeyboardReporter,
191 pending_key_state: Option<PendingState<R, Ev, PKS>>,
192 input_queue: heapless::spsc::Queue<input::Event, { MAX_QUEUED_INPUT_EVENTS }>,
193 input_queue_delay_counter: u8,
194 callbacks: heapless::LinearMap<KeymapCallback, CallbackFunction, 2>,
195}
196
197impl<
198 I: Debug + Index<usize, Output = R>,
199 R: Debug,
200 Ctx: Debug,
201 Ev: Debug,
202 PKS: Debug,
203 KS: Debug,
204 S: key::System<R, Ref = R, Context = Ctx, Event = Ev, PendingKeyState = PKS, KeyState = KS>,
205 > core::fmt::Debug for Keymap<I, R, Ctx, Ev, PKS, KS, S>
206{
207 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
208 f.debug_struct("Keymap")
209 .field("context", &self.context)
210 .field("event_scheduler", &self.event_scheduler)
211 .field("ms_per_tick", &self.ms_per_tick)
212 .field("idle_time", &self.idle_time)
213 .field("hid_reporter", &self.hid_reporter)
214 .field("input_queue", &self.input_queue)
215 .field("input_queue_delay_counter", &self.input_queue_delay_counter)
216 .field("pending_key_state", &self.pending_key_state)
217 .field("pressed_inputs", &self.pressed_inputs)
218 .finish_non_exhaustive()
219 }
220}
221
222impl<
223 I: Debug + Index<usize, Output = R>,
224 R: Copy + Debug,
225 Ctx: Debug + key::Context<Event = Ev> + SetKeymapContext,
226 Ev: Copy + Debug,
227 PKS: Debug,
228 KS: Copy + Debug,
229 S: key::System<R, Ref = R, Context = Ctx, Event = Ev, PendingKeyState = PKS, KeyState = KS>,
230 > Keymap<I, R, Ctx, Ev, PKS, KS, S>
231where
232 KS: From<key::NoOpKeyState>,
233{
234 pub const fn new(key_refs: I, context: Ctx, key_system: S) -> Self {
236 Self {
237 key_refs,
238 key_system,
239 context,
240 pressed_inputs: heapless::Vec::new(),
241 event_scheduler: EventScheduler::new(),
242 ms_per_tick: 1,
243 idle_time: 0,
244 hid_reporter: HIDKeyboardReporter::new(),
245 pending_key_state: None,
246 input_queue: heapless::spsc::Queue::new(),
247 input_queue_delay_counter: 0,
248 callbacks: heapless::LinearMap::new(),
249 }
250 }
251
252 pub fn init(&mut self) {
254 self.pressed_inputs.clear();
255 self.event_scheduler.init();
256 self.hid_reporter.init();
257 self.pending_key_state = None;
258 while !self.input_queue.is_empty() {
259 self.input_queue.dequeue().unwrap();
260 }
261 self.input_queue_delay_counter = 0;
262 self.ms_per_tick = 1;
263 self.idle_time = 0;
264 }
265
266 pub fn set_callback(&mut self, callback_id: KeymapCallback, callback_fn: fn() -> ()) {
270 self.callbacks
271 .insert(callback_id, CallbackFunction::Rust(callback_fn))
272 .unwrap();
273 }
274
275 pub fn set_callback_extern(
279 &mut self,
280 callback_id: KeymapCallback,
281 callback_fn: extern "C" fn() -> (),
282 ) {
283 self.callbacks
284 .insert(callback_id, CallbackFunction::ExternC(callback_fn))
285 .unwrap();
286 }
287
288 pub fn set_ms_per_tick(&mut self, ms_per_tick: u8) {
290 self.ms_per_tick = ms_per_tick;
291 }
292
293 fn resolve_pending_key_state(&mut self, key_state: KS) {
296 if let Some(PendingState {
297 keymap_index,
298 key_ref,
299 queued_events,
300 ..
301 }) = self.pending_key_state.take()
302 {
303 self.event_scheduler
305 .cancel_events_for_keymap_index(keymap_index);
306
307 self.pressed_inputs
309 .push(input::PressedInput::pressed_key(
310 keymap_index,
311 key_ref,
312 key_state,
313 ))
314 .unwrap();
315
316 let mut i = 1;
320 let mut old_input_queue: heapless::spsc::Queue<input::Event, MAX_QUEUED_INPUT_EVENTS> =
321 core::mem::take(&mut self.input_queue);
322
323 let (pending_input_ev, queued_events): (
327 heapless::Vec<key::Event<Ev>, { MAX_PRESSED_KEYS }>,
328 heapless::Vec<key::Event<Ev>, { MAX_PRESSED_KEYS }>,
329 ) = queued_events.iter().partition(|ev| match ev {
330 key::Event::Input(input::Event::Press {
331 keymap_index: queued_kmi,
332 }) => *queued_kmi == keymap_index,
333 key::Event::Input(input::Event::Release {
334 keymap_index: queued_kmi,
335 }) => *queued_kmi == keymap_index,
336 key::Event::Key {
337 keymap_index: queued_kmi,
338 ..
339 } => *queued_kmi == keymap_index,
340 _ => false,
341 });
342
343 for ev in queued_events.iter().chain(pending_input_ev.last()) {
344 match ev {
345 key::Event::Input(ie) => {
346 self.input_queue.enqueue(*ie).unwrap();
347 }
348 _ => {
349 self.event_scheduler.schedule_after(i, *ev);
350 i += 1;
351 }
352 }
353 }
354
355 while let Some(ie) = old_input_queue.dequeue() {
356 self.input_queue.enqueue(ie).unwrap();
357 }
358
359 self.handle_pending_events();
360
361 if let Some(key_output) = self.key_system.key_output(&key_ref, &key_state) {
363 let km_ev = KeymapEvent::ResolvedKeyOutput {
364 keymap_index,
365 key_output,
366 };
367 self.handle_event(key::Event::Keymap(km_ev));
368 }
369 }
370 }
371
372 pub fn handle_input(&mut self, ev: input::Event) {
374 self.idle_time = 0;
375
376 if self.input_queue.is_full() {
377 return;
378 }
379
380 self.input_queue.enqueue(ev).unwrap();
381
382 if self.input_queue_delay_counter == 0 {
383 let ie = self.input_queue.dequeue().unwrap();
384 self.process_input(ie);
385 self.input_queue_delay_counter = INPUT_QUEUE_TICK_DELAY;
386 }
387 }
388
389 fn has_pressed_input_with_keymap_index(&self, keymap_index: u16) -> bool {
390 self.pressed_inputs.iter().any(|pi| match pi {
391 &input::PressedInput::Key(input::PressedKey {
392 keymap_index: ki, ..
393 }) => keymap_index == ki,
394 _ => false,
395 })
396 }
397
398 fn update_pending_state(&mut self, ev: key::Event<Ev>) {
399 if let Some(PendingState {
400 keymap_index,
401 key_ref,
402 pending_key_state,
403 queued_events,
404 ..
405 }) = &mut self.pending_key_state
406 {
407 let (mut maybe_npk, pke) = self.key_system.update_pending_state(
408 pending_key_state,
409 *keymap_index,
410 &self.context,
411 *key_ref,
412 ev,
413 );
414
415 pke.into_iter()
416 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
417
418 while let Some(npk) = maybe_npk.take() {
419 let pkr = match npk {
420 key::NewPressedKey::Key(new_key_ref) => {
421 *key_ref = new_key_ref;
422 let (pkr, pke) = self.key_system.new_pressed_key(
423 *keymap_index,
424 &self.context,
425 new_key_ref,
426 );
427 pke.into_iter()
428 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
429 pkr
430 }
431 key::NewPressedKey::NoOp => {
432 let no_op_ks: KS = key::NoOpKeyState.into();
433 key::PressedKeyResult::Resolved(no_op_ks)
434 }
435 };
436
437 match pkr {
438 key::PressedKeyResult::Resolved(ks) => {
439 self.resolve_pending_key_state(ks);
440 break;
441 }
442 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(new_key_ref)) => {
443 maybe_npk = Some(key::NewPressedKey::Key(new_key_ref));
444 }
445 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp) => {
446 self.resolve_pending_key_state(key::NoOpKeyState.into());
447 break;
448 }
449 key::PressedKeyResult::Pending(pks) => {
450 *pending_key_state = pks;
451
452 let orig_input_queue = core::mem::take(&mut self.input_queue);
455 while let Some(ev) = queued_events.pop() {
456 if let key::Event::Input(input_ev) = ev {
457 self.input_queue.enqueue(input_ev).unwrap();
458 }
459 }
460 orig_input_queue.iter().for_each(|&ev| {
461 self.input_queue.enqueue(ev).unwrap();
462 });
463 }
464 }
465 }
466 }
467 }
468
469 fn process_input(&mut self, ev: input::Event) {
470 if let Some(pending_state) = &mut self.pending_key_state {
471 pending_state.queued_events.push(ev.into()).unwrap();
472 self.update_pending_state(ev.into());
473 } else {
474 self.pressed_inputs.iter_mut().for_each(|pi| {
476 if let input::PressedInput::Key(input::PressedKey {
477 key_ref,
478 key_state,
479 keymap_index,
480 }) = pi
481 {
482 self.key_system
483 .update_state(key_state, key_ref, &self.context, *keymap_index, ev.into())
484 .into_iter()
485 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
486 }
487 });
488
489 self.context
490 .handle_event(ev.into())
491 .into_iter()
492 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
493
494 match ev {
495 input::Event::Press { keymap_index }
496 if !self.has_pressed_input_with_keymap_index(keymap_index) =>
497 {
498 let mut maybe_key_ref = Some(self.key_refs[keymap_index as usize]);
499
500 while let Some(key_ref) = maybe_key_ref.take() {
501 let (pkr, pke) =
502 self.key_system
503 .new_pressed_key(keymap_index, &self.context, key_ref);
504
505 pke.into_iter()
506 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
507
508 match pkr {
509 key::PressedKeyResult::Resolved(key_state) => {
510 self.pressed_inputs
511 .push(input::PressedInput::pressed_key(
512 keymap_index,
513 key_ref,
514 key_state,
515 ))
516 .unwrap();
517
518 if let Some(key_output) =
520 self.key_system.key_output(&key_ref, &key_state)
521 {
522 let km_ev = KeymapEvent::ResolvedKeyOutput {
523 keymap_index,
524 key_output,
525 };
526 self.handle_event(key::Event::Keymap(km_ev));
527 }
528 }
529 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(
530 new_key_ref,
531 )) => {
532 maybe_key_ref = Some(new_key_ref);
533 }
534 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp) => {
535 let key_state: KS = key::NoOpKeyState.into();
536
537 self.pressed_inputs
538 .push(input::PressedInput::pressed_key(
539 keymap_index,
540 key_ref,
541 key_state,
542 ))
543 .unwrap();
544 }
545 key::PressedKeyResult::Pending(pending_key_state) => {
546 self.pending_key_state = Some(PendingState {
547 keymap_index,
548 key_ref,
549 pending_key_state,
550 queued_events: heapless::Vec::new(),
551 });
552 }
553 }
554 }
555 }
556 input::Event::Release { keymap_index } => {
557 self.pressed_inputs
558 .iter()
559 .position(|pi| match pi {
560 &input::PressedInput::Key(input::PressedKey {
561 keymap_index: ki,
562 ..
563 }) => keymap_index == ki,
564 _ => false,
565 })
566 .map(|i| self.pressed_inputs.remove(i));
567
568 self.event_scheduler
569 .cancel_events_for_keymap_index(keymap_index);
570 }
571
572 input::Event::VirtualKeyPress { key_output } => {
573 let pressed_key = input::PressedInput::Virtual(key_output);
574 self.pressed_inputs.push(pressed_key).unwrap();
575 }
576 input::Event::VirtualKeyRelease { key_output } => {
577 self.pressed_inputs
579 .iter()
580 .position(|k| match k {
581 input::PressedInput::Virtual(ko) => key_output == *ko,
582 _ => false,
583 })
584 .map(|i| self.pressed_inputs.remove(i));
585 }
586
587 _ => {}
588 }
589 }
590
591 self.handle_pending_events();
592 }
593
594 fn handle_event(&mut self, ev: key::Event<Ev>) {
597 if let key::Event::Keymap(KeymapEvent::Callback(callback_id)) = ev {
598 match self.callbacks.get(&callback_id) {
599 Some(CallbackFunction::Rust(callback_fn)) => {
600 callback_fn();
601 }
602 Some(CallbackFunction::ExternC(callback_fn)) => {
603 callback_fn();
604 }
605 None => {}
606 }
607 }
608
609 self.update_pending_state(ev);
611
612 self.pressed_inputs.iter_mut().for_each(|pi| {
614 if let input::PressedInput::Key(input::PressedKey {
615 key_state,
616 key_ref,
617 keymap_index,
618 }) = pi
619 {
620 self.key_system
621 .update_state(key_state, key_ref, &self.context, *keymap_index, ev)
622 .into_iter()
623 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
624 }
625 });
626
627 self.context
629 .handle_event(ev)
630 .into_iter()
631 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
632
633 if let Event::Input(input_ev) = ev {
634 self.process_input(input_ev);
635 }
636 }
637
638 fn handle_pending_events(&mut self) {
639 while let Some(ev) = self.event_scheduler.dequeue() {
641 self.handle_event(ev);
642 }
643 }
644
645 pub fn tick(&mut self) {
647 let km_context = KeymapContext {
648 time_ms: self.event_scheduler.schedule_counter,
649 idle_time_ms: self.idle_time,
650 };
651 self.context.set_keymap_context(km_context);
652
653 if !self.input_queue.is_empty() && self.input_queue_delay_counter == 0 {
654 let ie = self.input_queue.dequeue().unwrap();
655 self.process_input(ie);
656 self.input_queue_delay_counter = INPUT_QUEUE_TICK_DELAY;
657 }
658
659 if self.input_queue_delay_counter > 0 {
660 self.input_queue_delay_counter -= 1;
661 }
662
663 self.event_scheduler.tick(self.ms_per_tick);
664
665 self.handle_pending_events();
666
667 self.idle_time += self.ms_per_tick as u32;
668 }
669
670 pub fn pressed_keys(&self) -> heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> {
672 let pressed_key_codes = self.pressed_inputs.iter().filter_map(|pi| match pi {
673 input::PressedInput::Key(input::PressedKey {
674 key_ref, key_state, ..
675 }) => self.key_system.key_output(key_ref, key_state),
676 &input::PressedInput::Virtual(key_output) => Some(key_output),
677 });
678
679 pressed_key_codes.collect()
680 }
681
682 pub fn report_output(&mut self) -> KeymapOutput {
684 self.hid_reporter.update(self.pressed_keys());
685 self.hid_reporter.report_sent();
686
687 KeymapOutput::new(self.hid_reporter.reportable_key_outputs())
688 }
689
690 #[doc(hidden)]
692 pub fn boot_keyboard_report(&self) -> [u8; 8] {
693 KeymapOutput::new(self.pressed_keys()).as_hid_boot_keyboard_report()
694 }
695
696 #[doc(hidden)]
697 pub fn has_scheduled_events(&self) -> bool {
698 !self.event_scheduler.pending_events.is_empty()
699 || !self.event_scheduler.scheduled_events.is_empty()
700 || !self.input_queue.is_empty()
701 }
702}
703
704#[cfg(test)]
705mod tests {
706 use super::*;
707
708 #[test]
709 fn test_keymap_output_pressed_key_codes_includes_modifier_key_code() {
710 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
712 input.push(key::KeyOutput::from_key_code(0x04)).unwrap();
713 input.push(key::KeyOutput::from_key_code(0xE0)).unwrap();
714
715 let keymap_output = KeymapOutput::new(input);
717 let pressed_key_codes = keymap_output.pressed_key_codes();
718
719 assert!(pressed_key_codes.contains(&0xE0))
721 }
722
723 #[test]
724 fn test_keymap_output_as_hid_boot_keyboard_report_gathers_modifiers() {
725 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
727 input.push(key::KeyOutput::from_key_code(0x04)).unwrap();
728 input.push(key::KeyOutput::from_key_code(0xE0)).unwrap();
729
730 let keymap_output = KeymapOutput::new(input);
732 let actual_report: [u8; 8] = keymap_output.as_hid_boot_keyboard_report();
733
734 let expected_report: [u8; 8] = [0x01, 0, 0x04, 0, 0, 0, 0, 0];
736 assert_eq!(expected_report, actual_report);
737 }
738
739 #[test]
740 fn test_keymap_many_input_events_without_tick_or_report() {
741 let mut keymap = {
743 use crate as smart_keymap;
744 use smart_keymap::key::composite as key_system;
745
746 use key_system::Context;
747 use key_system::Ref;
748 const KEY_COUNT: usize = 1;
749 const KEY_REFS: [Ref; KEY_COUNT] = [smart_keymap::key::composite::Ref::Keyboard(
750 smart_keymap::key::keyboard::Ref::KeyCode(0x04),
751 )];
752 const CONTEXT: Context = Context::from_config(key_system::DEFAULT_CONFIG);
753
754 smart_keymap::keymap::Keymap::new(
755 KEY_REFS,
756 CONTEXT,
757 smart_keymap::key::composite::System::array_based(
758 smart_keymap::key::keyboard::System::new([]),
759 smart_keymap::key::callback::System::new([]),
760 smart_keymap::key::sticky::System::new([]),
761 smart_keymap::key::tap_dance::System::new([]),
762 smart_keymap::key::tap_hold::System::new([]),
763 smart_keymap::key::layered::System::new([], []),
764 smart_keymap::key::chorded::System::new([], []),
765 ),
766 )
767 };
768
769 for _ in 0..100 {
771 keymap.handle_input(input::Event::Press { keymap_index: 0 });
772 keymap.handle_input(input::Event::Release { keymap_index: 0 });
773 }
774
775 }
778}