1#[cfg(feature = "std")]
2mod distinct_reports;
3mod event_scheduler;
4pub mod hid_keyboard_reporter;
6mod input_event_queue;
7#[cfg(feature = "std")]
8mod observed_eb_keymap;
9#[cfg(feature = "std")]
10mod observed_keymap;
11mod pending;
12
13use core::cmp::PartialEq;
14use core::fmt::Debug;
15use core::marker::Copy;
16use core::ops::Index;
17
18use serde::Deserialize;
19
20use crate::input;
21use crate::key;
22
23use key::Event;
24
25#[cfg(feature = "std")]
26pub use distinct_reports::DistinctReports;
27use event_scheduler::EventScheduler;
28use hid_keyboard_reporter::HIDKeyboardReporter;
29use input_event_queue::InputEventQueue;
30#[cfg(feature = "std")]
31pub use observed_eb_keymap::ObservedKeymap as ObservedEventBasedKeymap;
32#[cfg(feature = "std")]
33pub use observed_keymap::ObservedKeymap;
34
35pub const MAX_PRESSED_KEYS: usize = 16;
37
38pub(crate) const MAX_QUEUED_INPUT_EVENTS: usize = 32;
39
40#[derive(Debug, Default, PartialEq)]
42pub struct KeymapOutput {
43 pressed_key_codes: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }>,
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_consumer_codes(&self) -> heapless::Vec<u8, 24> {
108 self.pressed_key_codes
109 .iter()
110 .flat_map(|ko| match ko.key_code() {
111 key::KeyUsage::Consumer(uc) => Some(uc),
112 _ => None,
113 })
114 .collect()
115 }
116
117 pub fn pressed_custom_codes(&self) -> heapless::Vec<u8, 24> {
119 self.pressed_key_codes
120 .iter()
121 .flat_map(|ko| match ko.key_code() {
122 key::KeyUsage::Custom(kc) => Some(kc),
123 _ => None,
124 })
125 .collect()
126 }
127
128 pub fn pressed_mouse_output(&self) -> key::MouseOutput {
130 self.pressed_key_codes
131 .iter()
132 .filter_map(|ko| match ko.key_code() {
133 key::KeyUsage::Mouse(mo) => Some(mo),
134 _ => None,
135 })
136 .fold(key::MouseOutput::NO_OUTPUT, |acc, mo| acc.combine(&mo))
137 }
138}
139
140#[derive(Deserialize, Debug, Clone, Copy, Eq, PartialEq)]
142pub enum BluetoothProfileCommand {
143 Disconnect,
145 Clear,
147 ClearAll,
149 Previous,
151 Next,
153 Select(u8),
155}
156
157#[derive(Deserialize, Debug, Clone, Copy, Eq, PartialEq)]
159pub enum KeymapCallback {
160 Reset,
162 ResetToBootloader,
164 Bluetooth(BluetoothProfileCommand),
166 Custom(u8, u8),
168}
169
170#[derive(Debug, Clone, Copy, Default)]
172pub struct KeymapContext {
173 pub time_ms: u32,
175
176 pub idle_time_ms: u32,
178}
179
180impl KeymapContext {
181 pub const fn new() -> Self {
183 KeymapContext {
184 time_ms: 0,
185 idle_time_ms: 0,
186 }
187 }
188}
189
190pub trait SetKeymapContext {
192 fn set_keymap_context(&mut self, context: KeymapContext);
194}
195
196#[derive(Debug, Clone, Copy, PartialEq, Eq)]
198pub enum KeymapEvent {
199 Callback(KeymapCallback),
201 ResolvedKeyOutput {
203 keymap_index: u16,
205 key_output: key::KeyOutput,
207 },
208}
209
210#[derive(Debug)]
211enum CallbackFunction {
212 ExternC(extern "C" fn() -> ()),
214 Rust(fn() -> ()),
216}
217
218pub struct Keymap<I: Index<usize, Output = R>, R, Ctx, Ev: Debug, PKS, KS, S> {
220 key_refs: I,
221 key_system: S,
222 context: Ctx,
223 pressed_inputs: heapless::Vec<input::PressedInput<R, KS>, { MAX_PRESSED_KEYS }>,
224 event_scheduler: EventScheduler<Ev>,
225 ms_per_tick: u8,
226 idle_time: u32,
227 hid_reporter: HIDKeyboardReporter,
228 pending_state: Option<pending::PendingState<R, Ev, PKS>>,
229 input_queue: InputEventQueue<{ MAX_QUEUED_INPUT_EVENTS }>,
230 callbacks: heapless::LinearMap<KeymapCallback, CallbackFunction, 2>,
231}
232
233impl<
234 I: Debug + Index<usize, Output = R>,
235 R: Debug,
236 Ctx: Debug,
237 Ev: Debug,
238 PKS: Debug,
239 KS: Debug,
240 S: Debug,
241 > core::fmt::Debug for Keymap<I, R, Ctx, Ev, PKS, KS, S>
242{
243 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
244 f.debug_struct("Keymap")
245 .field("context", &self.context)
246 .field("event_scheduler", &self.event_scheduler)
247 .field("ms_per_tick", &self.ms_per_tick)
248 .field("idle_time", &self.idle_time)
249 .field("hid_reporter", &self.hid_reporter)
250 .field("input_queue", &self.input_queue)
251 .field("pending_state", &self.pending_state)
252 .field("pressed_inputs", &self.pressed_inputs)
253 .finish_non_exhaustive()
254 }
255}
256
257impl<
258 I: Debug + Index<usize, Output = R>,
259 R: Copy + Debug,
260 Ctx: Debug + key::Context<Event = Ev> + SetKeymapContext,
261 Ev: Copy + Debug,
262 PKS: Debug,
263 KS: Copy + Debug + From<key::NoOpKeyState>,
264 S: key::System<R, Ref = R, Context = Ctx, Event = Ev, PendingKeyState = PKS, KeyState = KS>,
265 > Keymap<I, R, Ctx, Ev, PKS, KS, S>
266{
267 pub const fn new(key_refs: I, context: Ctx, key_system: S) -> Self {
269 Self {
270 key_refs,
271 key_system,
272 context,
273 pressed_inputs: heapless::Vec::new(),
274 event_scheduler: EventScheduler::new(),
275 ms_per_tick: 1,
276 idle_time: 0,
277 hid_reporter: HIDKeyboardReporter::new(),
278 pending_state: None,
279 input_queue: InputEventQueue::new(),
280 callbacks: heapless::LinearMap::new(),
281 }
282 }
283
284 pub fn init(&mut self) {
290 self.context.reset();
291 self.pressed_inputs.clear();
292 self.event_scheduler.init();
293 self.hid_reporter.init();
294 self.pending_state = None;
295 self.input_queue.clear();
296 self.ms_per_tick = 1;
297 self.idle_time = 0;
298 }
299
300 pub fn clear_callbacks(&mut self) {
302 self.callbacks.clear();
303 }
304
305 pub fn set_callback(&mut self, callback_id: KeymapCallback, callback_fn: fn() -> ()) {
309 let _ = self
310 .callbacks
311 .insert(callback_id, CallbackFunction::Rust(callback_fn));
312 }
313
314 pub fn set_callback_extern(
318 &mut self,
319 callback_id: KeymapCallback,
320 callback_fn: extern "C" fn() -> (),
321 ) {
322 let _ = self
323 .callbacks
324 .insert(callback_id, CallbackFunction::ExternC(callback_fn));
325 }
326
327 pub fn set_ms_per_tick(&mut self, ms_per_tick: u8) {
329 self.ms_per_tick = ms_per_tick;
330 }
331
332 fn resolve_pending_key_state(&mut self, key_state: KS) {
342 if let Some(pending::PendingState {
343 keymap_index,
344 key_ref,
345 mut queued_events,
346 mut ingest_queue,
347 ..
348 }) = self.pending_state.take()
349 {
350 self.event_scheduler
352 .cancel_events_for_keymap_index(keymap_index);
353
354 let _ = self.pressed_inputs.push(input::PressedInput::pressed_key(
356 keymap_index,
357 key_ref,
358 key_state,
359 ));
360
361 pending::dispatch_replayed_events(
364 pending::KeyResolution::Resolved { keymap_index },
365 &mut queued_events,
366 &mut self.input_queue,
367 &mut self.event_scheduler,
368 );
369
370 let mut remaining = ingest_queue.take_all();
372 self.input_queue.append_all(&mut remaining);
373
374 self.handle_pending_events();
375
376 if let Some(key_output) = self.key_system.key_output(&key_ref, &key_state) {
378 let km_ev = KeymapEvent::ResolvedKeyOutput {
379 keymap_index,
380 key_output,
381 };
382 self.handle_event(key::Event::Keymap(km_ev));
383 }
384 }
385 }
386
387 pub fn handle_input(&mut self, ev: input::Event) {
398 self.idle_time = 0;
399
400 let ready = if let Some(pending_state) = self.pending_state.as_mut() {
401 pending_state.ingest_queue.push_back_or_ignore(ev);
402 pending_state.ingest_queue.pop_front_if_ready()
403 } else {
404 self.input_queue.push_back_or_ignore(ev);
405 self.input_queue.pop_front_if_ready()
406 };
407
408 if let Some(ie) = ready {
409 self.process_input(ie);
410 self.set_active_input_delay();
411 }
412 }
413
414 fn set_active_input_delay(&mut self) {
419 if let Some(pending_state) = self.pending_state.as_mut() {
420 pending_state.ingest_queue.set_delay();
421 } else {
422 self.input_queue.set_delay();
423 }
424 }
425
426 fn has_pressed_input_with_keymap_index(&self, keymap_index: u16) -> bool {
427 self.pressed_inputs.iter().any(|pi| match pi {
428 &input::PressedInput::Key(input::PressedKey {
429 keymap_index: ki, ..
430 }) => keymap_index == ki,
431 _ => false,
432 })
433 }
434
435 fn update_pending_state(&mut self, ev: key::Event<Ev>) {
436 if let Some(pending::PendingState {
437 keymap_index,
438 key_ref,
439 pending_key_state,
440 queued_events,
441 ingest_queue,
442 ..
443 }) = self.pending_state.as_mut()
444 {
445 let (mut maybe_npk, pke) = self.key_system.update_pending_state(
446 pending_key_state,
447 *keymap_index,
448 &self.context,
449 *key_ref,
450 ev,
451 );
452
453 pke.into_iter()
454 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
455
456 while let Some(npk) = maybe_npk.take() {
457 let pkr = match npk {
458 key::NewPressedKey::Key(new_key_ref) => {
459 *key_ref = new_key_ref;
460 let (pkr, pke) = self.key_system.new_pressed_key(
461 *keymap_index,
462 &self.context,
463 new_key_ref,
464 );
465 pke.into_iter()
466 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
467 pkr
468 }
469 key::NewPressedKey::NoOp => {
470 let no_op_ks: KS = key::NoOpKeyState.into();
471 key::PressedKeyResult::Resolved(no_op_ks)
472 }
473 };
474
475 match pkr {
476 key::PressedKeyResult::Resolved(ks) => {
477 self.resolve_pending_key_state(ks);
478 break;
479 }
480 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(new_key_ref)) => {
481 maybe_npk = Some(key::NewPressedKey::Key(new_key_ref));
482 }
483 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp) => {
484 self.resolve_pending_key_state(key::NoOpKeyState.into());
485 break;
486 }
487 key::PressedKeyResult::Pending(pks) => {
488 *pending_key_state = pks;
489
490 pending::dispatch_replayed_events(
493 pending::KeyResolution::Pending,
494 queued_events,
495 ingest_queue,
496 &mut self.event_scheduler,
497 );
498 }
499 }
500 }
501 }
502 }
503
504 fn process_input(&mut self, ev: input::Event) {
505 if let Some(pending_state) = self.pending_state.as_mut() {
506 pending_state.record_input(ev);
508 self.update_pending_state(ev.into());
509 } else {
510 self.pressed_inputs.iter_mut().for_each(|pi| {
512 if let input::PressedInput::Key(input::PressedKey {
513 key_ref,
514 key_state,
515 keymap_index,
516 }) = pi
517 {
518 self.key_system
519 .update_state(key_state, key_ref, &self.context, *keymap_index, ev.into())
520 .into_iter()
521 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
522 }
523 });
524
525 self.context
526 .handle_event(ev.into())
527 .into_iter()
528 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
529
530 match ev {
531 input::Event::Press { keymap_index }
532 if !self.has_pressed_input_with_keymap_index(keymap_index) =>
533 {
534 let mut maybe_key_ref = Some(self.key_refs[keymap_index as usize]);
535
536 while let Some(key_ref) = maybe_key_ref.take() {
537 let (pkr, pke) =
538 self.key_system
539 .new_pressed_key(keymap_index, &self.context, key_ref);
540
541 pke.into_iter()
542 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
543
544 match pkr {
545 key::PressedKeyResult::Resolved(key_state) => {
546 let _ = self.pressed_inputs.push(input::PressedInput::pressed_key(
547 keymap_index,
548 key_ref,
549 key_state,
550 ));
551
552 if let Some(key_output) =
554 self.key_system.key_output(&key_ref, &key_state)
555 {
556 let km_ev = KeymapEvent::ResolvedKeyOutput {
557 keymap_index,
558 key_output,
559 };
560 self.handle_event(key::Event::Keymap(km_ev));
561 }
562 }
563 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(
564 new_key_ref,
565 )) => {
566 maybe_key_ref = Some(new_key_ref);
567 }
568 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp) => {
569 let key_state: KS = key::NoOpKeyState.into();
570
571 let _ = self.pressed_inputs.push(input::PressedInput::pressed_key(
572 keymap_index,
573 key_ref,
574 key_state,
575 ));
576 }
577 key::PressedKeyResult::Pending(pending_key_state) => {
578 let mut pending_state = pending::PendingState::new(
585 keymap_index,
586 key_ref,
587 pending_key_state,
588 );
589 let mut remaining = self.input_queue.take_all();
590 pending_state.ingest_queue.append_all(&mut remaining);
591 self.pending_state = Some(pending_state);
592 }
593 }
594 }
595 }
596 input::Event::Release { keymap_index } => {
597 self.pressed_inputs
598 .iter()
599 .position(|pi| match pi {
600 &input::PressedInput::Key(input::PressedKey {
601 keymap_index: ki,
602 ..
603 }) => keymap_index == ki,
604 _ => false,
605 })
606 .map(|i| self.pressed_inputs.remove(i));
607 }
608
609 input::Event::VirtualKeyPress { key_output } => {
610 let pressed_key = input::PressedInput::Virtual(key_output);
611 let _ = self.pressed_inputs.push(pressed_key);
612 }
613 input::Event::VirtualKeyRelease { key_output } => {
614 self.pressed_inputs
616 .iter()
617 .position(|k| match k {
618 input::PressedInput::Virtual(ko) => key_output == *ko,
619 _ => false,
620 })
621 .map(|i| self.pressed_inputs.remove(i));
622 }
623
624 _ => {}
625 }
626 }
627
628 self.handle_pending_events();
629 }
630
631 fn handle_event(&mut self, ev: key::Event<Ev>) {
634 if let key::Event::Keymap(KeymapEvent::Callback(callback_id)) = ev {
635 match self.callbacks.get(&callback_id) {
636 Some(CallbackFunction::Rust(callback_fn)) => {
637 callback_fn();
638 }
639 Some(CallbackFunction::ExternC(callback_fn)) => {
640 callback_fn();
641 }
642 None => {}
643 }
644 }
645
646 let was_pending = self.pending_state.is_some();
647
648 self.update_pending_state(ev);
650
651 self.pressed_inputs.iter_mut().for_each(|pi| {
653 if let input::PressedInput::Key(input::PressedKey {
654 key_state,
655 key_ref,
656 keymap_index,
657 }) = pi
658 {
659 self.key_system
660 .update_state(key_state, key_ref, &self.context, *keymap_index, ev)
661 .into_iter()
662 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
663 }
664 });
665
666 self.context
668 .handle_event(ev)
669 .into_iter()
670 .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev));
671
672 if let Event::Input(input_ev) = ev {
673 if was_pending {
674 if let Some(pending_state) = self.pending_state.as_mut() {
678 pending_state.record_input(input_ev);
679 }
680 self.handle_pending_events();
681 } else {
682 self.process_input(input_ev);
683 }
684 }
685 }
686
687 fn handle_pending_events(&mut self) {
688 while let Some(ev) = self.event_scheduler.dequeue() {
690 self.handle_event(ev);
691 }
692 }
693
694 pub fn tick(&mut self) {
696 let km_context = KeymapContext {
697 time_ms: self.event_scheduler.schedule_counter,
698 idle_time_ms: self.idle_time,
699 };
700 self.context.set_keymap_context(km_context);
701
702 let ready = if let Some(pending_state) = self.pending_state.as_mut() {
703 pending_state.ingest_queue.pop_front_if_ready()
704 } else {
705 self.input_queue.pop_front_if_ready()
706 };
707
708 if let Some(ie) = ready {
709 self.process_input(ie);
710 self.set_active_input_delay();
711 }
712
713 self.input_queue.tick_delay();
716 if let Some(pending_state) = self.pending_state.as_mut() {
717 pending_state.ingest_queue.tick_delay();
718 }
719
720 self.event_scheduler.tick(self.ms_per_tick);
721
722 self.handle_pending_events();
723
724 self.idle_time += self.ms_per_tick as u32;
725 }
726
727 pub fn pressed_keys(&self) -> heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> {
729 let pressed_key_codes = self.pressed_inputs.iter().filter_map(|pi| match pi {
730 input::PressedInput::Key(input::PressedKey {
731 key_ref, key_state, ..
732 }) => self.key_system.key_output(key_ref, key_state),
733 &input::PressedInput::Virtual(key_output) => Some(key_output),
734 });
735
736 pressed_key_codes.collect()
737 }
738
739 fn tick_by(&mut self, delta_ms: u32) {
740 if delta_ms == 0 {
741 self.tick();
742 } else {
743 for _ in 0..(delta_ms / self.ms_per_tick as u32) {
744 self.tick();
745 }
746 }
747 }
748
749 pub fn handle_input_after_time(&mut self, delta_ms: u32, ev: input::Event) -> Option<u32> {
756 self.tick_by(delta_ms);
757 self.handle_input(ev);
758 let next_event_time = self.event_scheduler.next_event_time();
759 debug_assert!(next_event_time != Some(0));
760 next_event_time
761 }
762
763 pub fn tick_to_next_scheduled_event(&mut self) -> Option<u32> {
769 if let Some(delta_ms) = self.event_scheduler.next_event_time() {
770 self.tick_by(delta_ms);
771 self.event_scheduler.next_event_time()
772 } else {
773 None
774 }
775 }
776
777 pub fn report_output(&mut self) -> KeymapOutput {
779 self.hid_reporter.update(self.pressed_keys());
780 self.hid_reporter.report_sent();
781
782 KeymapOutput::new(self.hid_reporter.reportable_key_outputs())
783 }
784
785 #[doc(hidden)]
787 pub fn boot_keyboard_report(&self) -> [u8; 8] {
788 KeymapOutput::new(self.pressed_keys()).as_hid_boot_keyboard_report()
789 }
790
791 pub fn requires_polling(&self) -> bool {
793 !self.event_scheduler.pending_events.is_empty()
794 || !self.input_queue.is_empty()
795 || self
796 .pending_state
797 .as_ref()
798 .is_some_and(|ps| !ps.ingest_queue.is_empty())
799 }
800
801 #[doc(hidden)]
802 pub fn has_scheduled_events(&self) -> bool {
803 !self.event_scheduler.pending_events.is_empty()
804 || !self.event_scheduler.scheduled_events.is_empty()
805 || !self.input_queue.is_empty()
806 || self
807 .pending_state
808 .as_ref()
809 .is_some_and(|ps| !ps.ingest_queue.is_empty())
810 }
811}
812
813#[cfg(feature = "std")]
818#[doc(hidden)]
819impl<
820 I: Debug + Index<usize, Output = R>,
821 R: Copy + Debug,
822 Ctx: Debug + key::Context<Event = Ev> + SetKeymapContext,
823 Ev: Copy + Debug,
824 PKS: Debug,
825 KS: Copy + Debug + From<key::NoOpKeyState>,
826 S: key::System<R, Ref = R, Context = Ctx, Event = Ev, PendingKeyState = PKS, KeyState = KS>,
827 > Keymap<I, R, Ctx, Ev, PKS, KS, S>
828{
829 pub fn test_is_pending(&self) -> bool {
831 self.pending_state.is_some()
832 }
833
834 pub fn test_pending_queued_events_len(&self) -> Option<usize> {
836 self.pending_state
837 .as_ref()
838 .map(|pending_state| pending_state.queued_events.len())
839 }
840
841 pub fn test_pending_session_log_inputs(&self) -> Option<heapless::Vec<input::Event, 16>> {
844 self.pending_state.as_ref().map(|pending_state| {
845 let mut inputs = heapless::Vec::new();
846 for ev in pending_state.queued_events.iter() {
847 if let key::Event::Input(ie) = ev {
848 let _ = inputs.push(*ie);
849 }
850 }
851 inputs
852 })
853 }
854
855 pub fn test_input_queue_len(&self) -> usize {
858 if let Some(pending_state) = self.pending_state.as_ref() {
859 pending_state.ingest_queue.len()
860 } else {
861 self.input_queue.len()
862 }
863 }
864
865 pub fn test_input_queue_delay(&self) -> bool {
868 if let Some(pending_state) = self.pending_state.as_ref() {
869 pending_state.ingest_queue.delay()
870 } else {
871 self.input_queue.delay()
872 }
873 }
874
875 pub fn test_handle_scheduled_key_event(&mut self, ev: key::Event<Ev>) {
877 self.event_scheduler
878 .schedule_event(key::ScheduledEvent::immediate(ev));
879 self.handle_pending_events();
880 }
881}
882
883#[cfg(test)]
884#[allow(clippy::unwrap_used, clippy::expect_used)]
885mod tests {
886 use super::*;
887
888 #[test]
889 fn test_keymap_output_pressed_key_codes_includes_modifier_key_code() {
890 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
892 input.push(key::KeyOutput::from_key_code(0x04)).unwrap();
893 input.push(key::KeyOutput::from_key_code(0xE0)).unwrap();
894
895 let keymap_output = KeymapOutput::new(input);
897 let pressed_key_codes = keymap_output.pressed_key_codes();
898
899 assert!(pressed_key_codes.contains(&0xE0))
901 }
902
903 #[test]
904 fn test_keymap_output_as_hid_boot_keyboard_report_gathers_modifiers() {
905 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
907 input.push(key::KeyOutput::from_key_code(0x04)).unwrap();
908 input.push(key::KeyOutput::from_key_code(0xE0)).unwrap();
909
910 let keymap_output = KeymapOutput::new(input);
912 let actual_report: [u8; 8] = keymap_output.as_hid_boot_keyboard_report();
913
914 let expected_report: [u8; 8] = [0x01, 0, 0x04, 0, 0, 0, 0, 0];
916 assert_eq!(expected_report, actual_report);
917 }
918
919 #[test]
920 fn test_keymap_output_pressed_consumer_codes() {
921 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
922 input
923 .push(key::KeyOutput::from_consumer_code(0xE9))
924 .unwrap();
925
926 let keymap_output = KeymapOutput::new(input);
927 assert_eq!(
928 heapless::Vec::<u8, 24>::from_slice(&[0xE9]).unwrap(),
929 keymap_output.pressed_consumer_codes()
930 );
931 }
932
933 #[test]
934 fn test_keymap_output_pressed_mouse_output_combines_buttons() {
935 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
936 input
937 .push(key::KeyOutput::from_mouse_output(key::MouseOutput {
938 pressed_buttons: 0b001,
939 ..key::MouseOutput::NO_OUTPUT
940 }))
941 .unwrap();
942 input
943 .push(key::KeyOutput::from_mouse_output(key::MouseOutput {
944 pressed_buttons: 0b010,
945 ..key::MouseOutput::NO_OUTPUT
946 }))
947 .unwrap();
948
949 let keymap_output = KeymapOutput::new(input);
950 assert_eq!(
951 key::MouseOutput {
952 pressed_buttons: 0b011,
953 ..key::MouseOutput::NO_OUTPUT
954 },
955 keymap_output.pressed_mouse_output()
956 );
957 }
958
959 #[test]
960 fn test_keymap_context_default_is_zeroed() {
961 let context = KeymapContext::new();
962 assert_eq!(0, context.time_ms);
963 assert_eq!(0, context.idle_time_ms);
964 }
965}