smart_keymap/keymap/
hid_keyboard_reporter.rs1use core::fmt::Debug;
2
3use crate::key;
4
5use super::MAX_PRESSED_KEYS;
6
7#[derive(Debug)]
12pub struct HIDKeyboardReporter {
13 pressed_key_outputs: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }>,
14 num_reportable_keys: u8,
15}
16
17impl Default for HIDKeyboardReporter {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl HIDKeyboardReporter {
24 pub const fn new() -> Self {
26 Self {
27 pressed_key_outputs: heapless::Vec::new(),
28 num_reportable_keys: 1,
29 }
30 }
31
32 pub fn init(&mut self) {
34 self.pressed_key_outputs.clear();
35 self.num_reportable_keys = 1;
36 }
37
38 pub fn update(
40 &mut self,
41 pressed_key_outputs: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }>,
42 ) {
43 let mut prev_iter = self.pressed_key_outputs.iter();
48 let new_iter = pressed_key_outputs.iter();
49
50 for new_key_output in new_iter {
51 for prev_key_output in prev_iter.by_ref() {
52 if prev_key_output == new_key_output {
53 break;
55 } else {
56 if self.num_reportable_keys > 1 {
59 self.num_reportable_keys -= 1;
60 }
61 }
62 }
63 }
64
65 for _ in prev_iter {
66 if self.num_reportable_keys > 1 {
69 self.num_reportable_keys -= 1;
70 }
71 }
72
73 self.pressed_key_outputs = pressed_key_outputs;
74 }
75
76 pub fn report_sent(&mut self) {
78 if self.pressed_key_outputs.len() > self.num_reportable_keys.into() {
79 self.num_reportable_keys += 1;
80 }
81 }
82
83 pub fn reportable_key_outputs(&self) -> heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> {
85 self.pressed_key_outputs
86 .clone()
87 .into_iter()
88 .take(self.num_reportable_keys as usize)
89 .collect()
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::super::*;
96 use super::*;
97
98 #[test]
99 fn test_hid_keyboard_reporter_reports_single_keypress() {
100 let mut input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = heapless::Vec::new();
102 input.push(key::KeyOutput::from_key_code(0x04)).unwrap();
103
104 let mut reporter = HIDKeyboardReporter::new();
105
106 reporter.update(input);
108 let actual_outputs = reporter.reportable_key_outputs();
109
110 let expected_outputs: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = [0x04]
112 .iter()
113 .map(|&kc| key::KeyOutput::from_key_code(kc))
114 .collect();
115 assert_eq!(expected_outputs, actual_outputs);
116 }
117
118 #[test]
119 fn test_hid_keyboard_reporter_reports_single_new_keypress_per_report_sent() {
120 let input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = [0x04, 0x05]
122 .iter()
123 .map(|&kc| key::KeyOutput::from_key_code(kc))
124 .collect();
125
126 let mut reporter = HIDKeyboardReporter::new();
127
128 reporter.update(input);
130 let actual_outputs = reporter.reportable_key_outputs();
131
132 let expected_outputs: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = [0x04]
134 .iter()
135 .map(|&kc| key::KeyOutput::from_key_code(kc))
136 .collect();
137 assert_eq!(expected_outputs, actual_outputs);
138 }
139
140 #[test]
141 fn test_hid_keyboard_reporter_reports_more_keypresses_after_report_sent() {
142 let input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = [0x04, 0x05]
144 .iter()
145 .map(|&kc| key::KeyOutput::from_key_code(kc))
146 .collect();
147
148 let mut reporter = HIDKeyboardReporter::new();
149
150 reporter.update(input);
152 reporter.report_sent();
153 let actual_outputs = reporter.reportable_key_outputs();
154
155 let expected_outputs: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = [0x04, 0x05]
157 .iter()
158 .map(|&kc| key::KeyOutput::from_key_code(kc))
159 .collect();
160 assert_eq!(expected_outputs, actual_outputs);
161 }
162
163 #[test]
164 fn test_hid_keyboard_reporter_reports_updates_for_key_releases() {
165 let input: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = [0x04, 0x05]
167 .iter()
168 .map(|&kc| key::KeyOutput::from_key_code(kc))
169 .collect();
170 let input_after_key_released: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = [0x05]
171 .iter()
172 .map(|&kc| key::KeyOutput::from_key_code(kc))
173 .collect();
174 let input_after_more_keys_pressed: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> =
175 [0x05, 0x06, 0x07]
176 .iter()
177 .map(|&kc| key::KeyOutput::from_key_code(kc))
178 .collect();
179
180 let mut reporter = HIDKeyboardReporter::new();
181
182 reporter.update(input);
184 reporter.report_sent(); assert_eq!(2, reporter.num_reportable_keys);
186 reporter.update(input_after_key_released); assert_eq!(1, reporter.num_reportable_keys);
188 reporter.report_sent();
189 assert_eq!(1, reporter.num_reportable_keys);
190 reporter.update(input_after_more_keys_pressed); reporter.report_sent();
192 assert_eq!(2, reporter.num_reportable_keys);
193 let actual_outputs = reporter.reportable_key_outputs();
194
195 let expected_outputs: heapless::Vec<key::KeyOutput, { MAX_PRESSED_KEYS }> = [0x05, 0x06]
197 .iter()
198 .map(|&kc| key::KeyOutput::from_key_code(kc))
199 .collect();
200 assert_eq!(
201 KeymapOutput::new(expected_outputs).as_hid_boot_keyboard_report(),
202 KeymapOutput::new(actual_outputs).as_hid_boot_keyboard_report(),
203 );
204 }
205}