RKTK API Docs RKTK Home Repo

rktk_keymanager/state/
hid_report.rs

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