1use heapless::Vec;
2use usbd_hid::descriptor::{KeyboardReport, MediaKeyboardReport, MouseReport};
3
4use crate::{
5 interface::state::{
6 KeymapInfo,
7 input_event::InputEvent,
8 output_event::{EventType, OutputEvent},
9 },
10 keycode::KeyCode,
11};
12
13#[derive(Debug, PartialEq, Clone)]
14pub struct Report {
15 pub keyboard_report: Option<KeyboardReport>,
16 pub mouse_report: Option<MouseReport>,
17 pub media_keyboard_report: Option<MediaKeyboardReport>,
18 pub highest_layer: u8,
19}
20
21pub struct HidReportState<
22 const LAYER: usize,
23 const ROW: usize,
24 const COL: usize,
25 const ENCODER_COUNT: usize,
26 const NORMAL_MAX_PRESSED_KEYS: usize,
27 const ONESHOT_STATE_SIZE: usize,
28 const TAP_DANCE_MAX_DEFINITIONS: usize,
29 const TAP_DANCE_MAX_REPEATS: usize,
30 const COMBO_KEY_MAX_DEFINITIONS: usize,
31 const COMBO_KEY_MAX_SOURCES: usize,
32> {
33 state: super::State<
34 LAYER,
35 ROW,
36 COL,
37 ENCODER_COUNT,
38 NORMAL_MAX_PRESSED_KEYS,
39 ONESHOT_STATE_SIZE,
40 TAP_DANCE_MAX_DEFINITIONS,
41 TAP_DANCE_MAX_REPEATS,
42 COMBO_KEY_MAX_DEFINITIONS,
43 COMBO_KEY_MAX_SOURCES,
44 >,
45 next_send_keyboard_report: bool,
46 next_send_mkb_report: bool,
47}
48
49impl<
50 const LAYER: usize,
51 const ROW: usize,
52 const COL: usize,
53 const ENCODER_COUNT: usize,
54 const NORMAL_MAX_PRESSED_KEYS: usize,
55 const ONESHOT_STATE_SIZE: usize,
56 const TAP_DANCE_MAX_DEFINITIONS: usize,
57 const TAP_DANCE_MAX_REPEATS: usize,
58 const COMBO_KEY_MAX_DEFINITIONS: usize,
59 const COMBO_KEY_MAX_SOURCES: usize,
60>
61 HidReportState<
62 LAYER,
63 ROW,
64 COL,
65 ENCODER_COUNT,
66 NORMAL_MAX_PRESSED_KEYS,
67 ONESHOT_STATE_SIZE,
68 TAP_DANCE_MAX_DEFINITIONS,
69 TAP_DANCE_MAX_REPEATS,
70 COMBO_KEY_MAX_DEFINITIONS,
71 COMBO_KEY_MAX_SOURCES,
72 >
73{
74 pub fn new(
75 keymap: crate::keymap::Keymap<
76 LAYER,
77 ROW,
78 COL,
79 ENCODER_COUNT,
80 TAP_DANCE_MAX_DEFINITIONS,
81 TAP_DANCE_MAX_REPEATS,
82 COMBO_KEY_MAX_DEFINITIONS,
83 COMBO_KEY_MAX_SOURCES,
84 >,
85 config: crate::interface::state::config::StateConfig,
86 ) -> Self {
87 Self {
88 state: super::State::new(keymap, config),
89 next_send_keyboard_report: false,
90 next_send_mkb_report: false,
91 }
92 }
93
94 pub fn update(&mut self, event: InputEvent, since_last_update: core::time::Duration) -> Report {
95 self.update_with_cb(event, since_last_update, |_| {})
96 }
97
98 pub fn update_with_cb(
99 &mut self,
100 event: InputEvent,
101 since_last_update: core::time::Duration,
102 mut cb: impl FnMut(OutputEvent),
103 ) -> Report {
104 let mut keyboard_change = self.next_send_keyboard_report;
105 self.next_send_keyboard_report = false;
106 let mut keys: Vec<u8, 6> = Vec::new();
107 let mut modifier = 0u8;
108
109 let mut mouse_change = false;
110 let mut movement = (0, 0);
111 let mut scroll = (0, 0);
112 let mut mouse_buttons = 0u8;
113
114 let mut media_keyboard_change = self.next_send_mkb_report;
115 let mut media_keys = 0u16;
116
117 self.state.update(event, since_last_update, |ev| {
118 match ev {
119 OutputEvent::KeyCode((kc, ev)) => {
120 match kc {
121 KeyCode::Key(key) => {
122 if ev != EventType::Pressing {
123 keyboard_change = true;
124 }
125 if ev != EventType::Released && !keys.contains(&(key as u8)) {
126 let _ = keys.push(key as u8);
127 }
128 if ev == EventType::Released && keys.contains(&(key as u8)) {
131 self.next_send_keyboard_report = true;
132 }
133 }
134 KeyCode::Media(m) => {
135 if ev != EventType::Pressing {
136 media_keyboard_change = true;
137 }
138 if ev != EventType::Released {
139 media_keys = m as u16;
140 }
141 if ev == EventType::Released && media_keys == m as u16 {
142 self.next_send_mkb_report = true;
143 }
144 }
145 KeyCode::Modifier(m) => {
146 if ev != EventType::Pressing {
147 keyboard_change = true;
148 }
149 if ev != EventType::Released {
150 modifier |= m as u8;
151 }
152 }
153 KeyCode::Mouse(m) => {
154 if ev != EventType::Pressing {
155 mouse_change = true;
156 }
157 if ev != EventType::Released {
158 mouse_buttons |= m as u8;
159 }
160 }
161 _ => {}
163 }
164 }
165 OutputEvent::MouseMove(m) => {
166 mouse_change = true;
167 movement.0 += m.0;
168 movement.1 += m.1;
169 }
170 OutputEvent::MouseScroll((pan, wheel)) => {
171 mouse_change = true;
172 scroll.0 += pan;
173 scroll.1 += wheel;
174 }
175 }
176 cb(ev);
177 });
178
179 Report {
180 keyboard_report: if keyboard_change {
181 keys.resize_default(6).unwrap();
182 let keycodes = keys.into_array().unwrap();
183 Some(KeyboardReport {
184 keycodes,
185 modifier,
186 leds: 0,
187 reserved: 0,
188 })
189 } else {
190 None
191 },
192 mouse_report: if mouse_change {
193 Some(MouseReport {
194 buttons: mouse_buttons,
195 x: movement.0,
196 y: movement.1,
197 pan: scroll.0,
198 wheel: scroll.1,
199 })
200 } else {
201 None
202 },
203 media_keyboard_report: if media_keyboard_change {
204 Some(MediaKeyboardReport {
205 usage_id: media_keys,
206 })
207 } else {
208 None
209 },
210 highest_layer: self.state.shared.highest_layer() as u8,
211 }
212 }
213
214 pub fn inner(
215 &self,
216 ) -> &super::State<
217 LAYER,
218 ROW,
219 COL,
220 ENCODER_COUNT,
221 NORMAL_MAX_PRESSED_KEYS,
222 ONESHOT_STATE_SIZE,
223 TAP_DANCE_MAX_DEFINITIONS,
224 TAP_DANCE_MAX_REPEATS,
225 COMBO_KEY_MAX_DEFINITIONS,
226 COMBO_KEY_MAX_SOURCES,
227 > {
228 &self.state
229 }
230
231 pub fn get_keymap_info() -> KeymapInfo {
232 KeymapInfo {
233 layer_count: LAYER as u8,
234 max_tap_dance_key_count: TAP_DANCE_MAX_DEFINITIONS as u8,
235 max_tap_dance_repeat_count: TAP_DANCE_MAX_REPEATS as u8,
236 oneshot_state_size: ONESHOT_STATE_SIZE as u8,
237 }
238 }
239}