@@ -143,6 +143,55 @@ hotkey_combo_t *check_all_hotkeys(hid_keyboard_report_t *report, device_t *state
143143 return NULL ;
144144}
145145
146+ /* ==================================================== *
147+ * Keyboard State Management
148+ * ==================================================== */
149+
150+ /* Update the keyboard state for a specific device */
151+ void update_kbd_state (device_t * state , hid_keyboard_report_t * report , uint8_t device_idx ) {
152+ /* Ensure device_idx is within bounds */
153+ if (device_idx >= MAX_DEVICES )
154+ return ;
155+
156+ /* Ensure local devices never use the last slot, which is reserved for the remote device */
157+ if (device_idx == MAX_DEVICES - 1 && device_idx != 0 ) {
158+ /* Use the previous slot instead */
159+ device_idx = MAX_DEVICES - 2 ;
160+ }
161+
162+ /* Update the keyboard state for this device */
163+ memcpy (& state -> kbd_states [device_idx ], report , sizeof (hid_keyboard_report_t ));
164+
165+ /* Ensure kbd_device_count is at least device_idx + 1 */
166+ if (state -> kbd_device_count <= device_idx )
167+ state -> kbd_device_count = device_idx + 1 ;
168+ }
169+
170+ /* Combine keyboard states from all devices into a single report */
171+ void combine_kbd_states (device_t * state , hid_keyboard_report_t * combined_report ) {
172+ /* Initialize combined report */
173+ memset (combined_report , 0 , sizeof (hid_keyboard_report_t ));
174+
175+ /* Combine modifiers and keys from all devices */
176+ for (uint8_t i = 0 ; i < state -> kbd_device_count ; i ++ ) {
177+ /* Combine modifiers with OR operation */
178+ combined_report -> modifier |= state -> kbd_states [i ].modifier ;
179+
180+ /* Add keys from this device to the combined report */
181+ for (uint8_t j = 0 ; j < KEYS_IN_USB_REPORT ; j ++ ) {
182+ if (state -> kbd_states [i ].keycode [j ] != 0 ) {
183+ /* Find an empty slot in the combined report */
184+ for (uint8_t k = 0 ; k < KEYS_IN_USB_REPORT ; k ++ ) {
185+ if (combined_report -> keycode [k ] == 0 ) {
186+ combined_report -> keycode [k ] = state -> kbd_states [i ].keycode [j ];
187+ break ;
188+ }
189+ }
190+ }
191+ }
192+ }
193+ }
194+
146195/* ==================================================== *
147196 * Keyboard Queue Section
148197 * ==================================================== */
@@ -184,16 +233,29 @@ void queue_kbd_report(hid_keyboard_report_t *report, device_t *state) {
184233
185234void release_all_keys (device_t * state ) {
186235 static hid_keyboard_report_t no_keys_pressed_report = {0 , 0 , {0 }};
236+
237+ /* Clear keyboard states for all devices */
238+ for (uint8_t i = 0 ; i < state -> kbd_device_count ; i ++ ) {
239+ memset (& state -> kbd_states [i ], 0 , sizeof (hid_keyboard_report_t ));
240+ }
241+
242+ /* Send a report with no keys pressed */
187243 queue_try_add (& state -> kbd_queue , & no_keys_pressed_report );
188244}
189245
190246/* If keys need to go locally, queue packet to kbd queue, else send them through UART */
191247void send_key (hid_keyboard_report_t * report , device_t * state ) {
248+ /* Create a combined report from all device states */
249+ hid_keyboard_report_t combined_report ;
250+ combine_kbd_states (state , & combined_report );
251+
192252 if (CURRENT_BOARD_IS_ACTIVE_OUTPUT ) {
193- queue_kbd_report (report , state );
253+ /* Queue the combined report */
254+ queue_kbd_report (& combined_report , state );
194255 state -> last_activity [BOARD_ROLE ] = time_us_64 ();
195256 } else {
196- queue_packet ((uint8_t * )report , KEYBOARD_REPORT_MSG , KBD_REPORT_LENGTH );
257+ /* Send the combined report to ensure all keys are included */
258+ queue_packet ((uint8_t * )& combined_report , KEYBOARD_REPORT_MSG , KBD_REPORT_LENGTH );
197259 }
198260}
199261
@@ -235,6 +297,9 @@ void process_keyboard_report(uint8_t *raw_report, int length, uint8_t itf, hid_i
235297
236298 extract_kbd_data (raw_report , length , itf , iface , & new_report );
237299
300+ /* Update the keyboard state for this device */
301+ update_kbd_state (state , & new_report , itf );
302+
238303 /* Check if any hotkey was pressed */
239304 hotkey = check_all_hotkeys (& new_report , state );
240305
@@ -259,6 +324,7 @@ void process_keyboard_report(uint8_t *raw_report, int length, uint8_t itf, hid_i
259324void process_consumer_report (uint8_t * raw_report , int length , uint8_t itf , hid_interface_t * iface ) {
260325 uint8_t new_report [CONSUMER_CONTROL_LENGTH ] = {0 };
261326 uint16_t * report_ptr = (uint16_t * )new_report ;
327+ device_t * state = & global_state ;
262328
263329 /* If consumer control is variable, read the values from cc_array and send as array. */
264330 if (iface -> consumer .is_variable ) {
@@ -276,12 +342,21 @@ void process_consumer_report(uint8_t *raw_report, int length, uint8_t itf, hid_i
276342 new_report [i ] = raw_report [i + 1 ];
277343 }
278344
279- send_consumer_control (new_report , & global_state );
345+ if (CURRENT_BOARD_IS_ACTIVE_OUTPUT ) {
346+ send_consumer_control (new_report , state );
347+ } else {
348+ queue_packet ((uint8_t * )new_report , CONSUMER_CONTROL_MSG , CONSUMER_CONTROL_LENGTH );
349+ }
280350}
281351
282352void process_system_report (uint8_t * raw_report , int length , uint8_t itf , hid_interface_t * iface ) {
283353 uint16_t new_report = raw_report [1 ];
284354 uint8_t * report_ptr = (uint8_t * )& new_report ;
355+ device_t * state = & global_state ;
285356
286- send_system_control (report_ptr , & global_state );
357+ if (CURRENT_BOARD_IS_ACTIVE_OUTPUT ) {
358+ send_system_control (report_ptr , state );
359+ } else {
360+ queue_packet (report_ptr , SYSTEM_CONTROL_MSG , SYSTEM_CONTROL_LENGTH );
361+ }
287362}
0 commit comments