]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/protocol/lufa/lufa.c
Revert "core: LUFA: Fix checking num of endpoints for 32u2"
[max/tmk_keyboard.git] / tmk_core / protocol / lufa / lufa.c
1 /*
2  * Copyright 2012 Jun Wako <wakojun@gmail.com>
3  * This file is based on:
4  *     LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
5  *     LUFA-120219/Demos/Device/Lowlevel/GenericHID
6  */
7
8 /*
9              LUFA Library
10      Copyright (C) Dean Camera, 2012.
11
12   dean [at] fourwalledcubicle [dot] com
13            www.lufa-lib.org
14 */
15
16 /*
17   Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com)
18   Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)
19
20   Permission to use, copy, modify, distribute, and sell this
21   software and its documentation for any purpose is hereby granted
22   without fee, provided that the above copyright notice appear in
23   all copies and that both that the copyright notice and this
24   permission notice and warranty disclaimer appear in supporting
25   documentation, and that the name of the author not be used in
26   advertising or publicity pertaining to distribution of the
27   software without specific, written prior permission.
28
29   The author disclaim all warranties with regard to this
30   software, including all implied warranties of merchantability
31   and fitness.  In no event shall the author be liable for any
32   special, indirect or consequential damages or any damages
33   whatsoever resulting from loss of use, data or profits, whether
34   in an action of contract, negligence or other tortious action,
35   arising out of or in connection with the use or performance of
36   this software.
37 */
38
39 #include "report.h"
40 #include "host.h"
41 #include "host_driver.h"
42 #include "keyboard.h"
43 #include "action.h"
44 #include "led.h"
45 #include "sendchar.h"
46 #include "debug.h"
47 #ifdef SLEEP_LED_ENABLE
48 #include "sleep_led.h"
49 #endif
50 #include "suspend.h"
51 #include "hook.h"
52
53 #ifdef LUFA_DEBUG_SUART
54 #include "avr/suart.h"
55 #endif
56
57 #include "matrix.h"
58 #include "descriptor.h"
59 #include "lufa.h"
60
61
62 //#define LUFA_DEBUG
63
64
65 uint8_t keyboard_idle = 0;
66 /* 0: Boot Protocol, 1: Report Protocol(default) */
67 uint8_t keyboard_protocol = 1;
68 static uint8_t keyboard_led_stats = 0;
69
70 static report_keyboard_t keyboard_report_sent;
71
72
73 /* Host driver */
74 static uint8_t keyboard_leds(void);
75 static void send_keyboard(report_keyboard_t *report);
76 static void send_mouse(report_mouse_t *report);
77 static void send_system(uint16_t data);
78 static void send_consumer(uint16_t data);
79 host_driver_t lufa_driver = {
80     keyboard_leds,
81     send_keyboard,
82     send_mouse,
83     send_system,
84     send_consumer
85 };
86
87
88 /*******************************************************************************
89  * Console
90  ******************************************************************************/
91 #ifdef CONSOLE_ENABLE
92 static void Console_Task(void)
93 {
94     /* Device must be connected and configured for the task to run */
95     if (USB_DeviceState != DEVICE_STATE_Configured)
96         return;
97
98     uint8_t ep = Endpoint_GetCurrentEndpoint();
99
100 #if 0
101     // TODO: impl receivechar()/recvchar()
102     Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
103
104     /* Check to see if a packet has been sent from the host */
105     if (Endpoint_IsOUTReceived())
106     {
107         /* Check to see if the packet contains data */
108         if (Endpoint_IsReadWriteAllowed())
109         {
110             /* Create a temporary buffer to hold the read in report from the host */
111             uint8_t ConsoleData[CONSOLE_EPSIZE];
112
113             /* Read Console Report Data */
114             Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
115
116             /* Process Console Report Data */
117             //ProcessConsoleHIDReport(ConsoleData);
118         }
119
120         /* Finalize the stream transfer to send the last packet */
121         Endpoint_ClearOUT();
122     }
123 #endif
124
125     /* IN packet */
126     Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
127     if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
128         Endpoint_SelectEndpoint(ep);
129         return;
130     }
131
132     // fill empty bank
133     while (Endpoint_IsReadWriteAllowed())
134         Endpoint_Write_8(0);
135
136     // flash senchar packet
137     if (Endpoint_IsINReady()) {
138         Endpoint_ClearIN();
139     }
140
141     Endpoint_SelectEndpoint(ep);
142 }
143 #else
144 static void Console_Task(void)
145 {
146 }
147 #endif
148
149
150 /*******************************************************************************
151  * USB Events
152  ******************************************************************************/
153 /*
154  * Event Order of Plug in:
155  * 0) EVENT_USB_Device_Connect
156  * 1) EVENT_USB_Device_Suspend
157  * 2) EVENT_USB_Device_Reset
158  * 3) EVENT_USB_Device_Wake
159 */
160 void EVENT_USB_Device_Connect(void)
161 {
162     print("[C]");
163     /* For battery powered device */
164     if (!USB_IsInitialized) {
165         USB_Disable();
166         USB_Init();
167         USB_Device_EnableSOFEvents();
168     }
169 }
170
171 void EVENT_USB_Device_Disconnect(void)
172 {
173     print("[D]");
174     /* For battery powered device */
175     USB_IsInitialized = false;
176 /* TODO: This doesn't work. After several plug in/outs can not be enumerated.
177     if (USB_IsInitialized) {
178         USB_Disable();  // Disable all interrupts
179         USB_Controller_Enable();
180         USB_INT_Enable(USB_INT_VBUSTI);
181     }
182 */
183 }
184
185 void EVENT_USB_Device_Reset(void)
186 {
187 #ifdef LUFA_DEBUG
188     print("[R]");
189 #endif
190 }
191
192 void EVENT_USB_Device_Suspend()
193 {
194 #ifdef LUFA_DEBUG
195     print("[S]");
196 #endif
197     hook_usb_suspend_entry();
198 }
199
200 void EVENT_USB_Device_WakeUp()
201 {
202 #ifdef LUFA_DEBUG
203     print("[W]");
204 #endif
205     hook_usb_wakeup();
206 }
207
208 #ifdef CONSOLE_ENABLE
209 static bool console_flush = false;
210 #define CONSOLE_FLUSH_SET(b)   do { \
211     uint8_t sreg = SREG; cli(); console_flush = b; SREG = sreg; \
212 } while (0)
213
214 // called every 1ms
215 void EVENT_USB_Device_StartOfFrame(void)
216 {
217     static uint8_t count;
218     if (++count % 50) return;
219     count = 0;
220
221     if (!console_flush) return;
222     Console_Task();
223     console_flush = false;
224 }
225 #endif
226
227 /** Event handler for the USB_ConfigurationChanged event.
228  * This is fired when the host sets the current configuration of the USB device after enumeration.
229  *
230  * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4,
231  * it is safe to use singl bank for all endpoints.
232  */
233 void EVENT_USB_Device_ConfigurationChanged(void)
234 {
235 #ifdef LUFA_DEBUG
236     print("[c]");
237 #endif
238     bool ConfigSuccess = true;
239
240     /* Setup Keyboard HID Report Endpoints */
241     ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
242                                      KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
243
244 #ifdef MOUSE_ENABLE
245     /* Setup Mouse HID Report Endpoint */
246     ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
247                                      MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
248 #endif
249
250 #ifdef EXTRAKEY_ENABLE
251     /* Setup Extra HID Report Endpoint */
252     ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
253                                      EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
254 #endif
255
256 #ifdef CONSOLE_ENABLE
257     /* Setup Console HID Report Endpoints */
258     ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
259                                      CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
260 #if 0
261     ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
262                                      CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
263 #endif
264 #endif
265
266 #ifdef NKRO_ENABLE
267     /* Setup NKRO HID Report Endpoints */
268     ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
269                                      NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
270 #endif
271 }
272
273 /*
274 Appendix G: HID Request Support Requirements
275
276 The following table enumerates the requests that need to be supported by various types of HID class devices.
277
278 Device type     GetReport   SetReport   GetIdle     SetIdle     GetProtocol SetProtocol
279 ------------------------------------------------------------------------------------------
280 Boot Mouse      Required    Optional    Optional    Optional    Required    Required
281 Non-Boot Mouse  Required    Optional    Optional    Optional    Optional    Optional
282 Boot Keyboard   Required    Optional    Required    Required    Required    Required
283 Non-Boot Keybrd Required    Optional    Required    Required    Optional    Optional
284 Other Device    Required    Optional    Optional    Optional    Optional    Optional
285 */
286 /** Event handler for the USB_ControlRequest event.
287  *  This is fired before passing along unhandled control requests to the library for processing internally.
288  */
289 void EVENT_USB_Device_ControlRequest(void)
290 {
291     uint8_t* ReportData = NULL;
292     uint8_t  ReportSize = 0;
293
294     /* Handle HID Class specific requests */
295     switch (USB_ControlRequest.bRequest)
296     {
297         case HID_REQ_GetReport:
298             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
299             {
300                 Endpoint_ClearSETUP();
301
302                 // Interface
303                 switch (USB_ControlRequest.wIndex) {
304                 case KEYBOARD_INTERFACE:
305                     // TODO: test/check
306                     ReportData = (uint8_t*)&keyboard_report_sent;
307                     ReportSize = sizeof(keyboard_report_sent);
308                     break;
309                 }
310
311                 /* Write the report data to the control endpoint */
312                 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
313                 Endpoint_ClearOUT();
314 #ifdef LUFA_DEBUG
315                 xprintf("[r%d]", USB_ControlRequest.wIndex);
316 #endif
317             }
318
319             break;
320         case HID_REQ_SetReport:
321             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
322             {
323
324                 // Interface
325                 switch (USB_ControlRequest.wIndex) {
326                 case KEYBOARD_INTERFACE:
327 #ifdef NKRO_ENABLE
328                 case NKRO_INTERFACE:
329 #endif
330                     Endpoint_ClearSETUP();
331
332                     while (!(Endpoint_IsOUTReceived())) {
333                         if (USB_DeviceState == DEVICE_STATE_Unattached)
334                           return;
335                     }
336                     keyboard_led_stats = Endpoint_Read_8();
337
338                     Endpoint_ClearOUT();
339                     Endpoint_ClearStatusStage();
340 #ifdef LUFA_DEBUG
341                     xprintf("[L%d]", USB_ControlRequest.wIndex);
342 #endif
343                     break;
344                 }
345
346             }
347
348             break;
349
350         case HID_REQ_GetProtocol:
351             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
352             {
353                 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
354                     Endpoint_ClearSETUP();
355                     while (!(Endpoint_IsINReady()));
356                     Endpoint_Write_8(keyboard_protocol);
357                     Endpoint_ClearIN();
358                     Endpoint_ClearStatusStage();
359 #ifdef LUFA_DEBUG
360                     print("[p]");
361 #endif
362                 }
363             }
364
365             break;
366         case HID_REQ_SetProtocol:
367             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
368             {
369                 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
370                     Endpoint_ClearSETUP();
371                     Endpoint_ClearStatusStage();
372
373                     keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
374                     clear_keyboard();
375 #ifdef LUFA_DEBUG
376                     print("[P]");
377 #endif
378                 }
379             }
380
381             break;
382         case HID_REQ_SetIdle:
383             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
384             {
385                 Endpoint_ClearSETUP();
386                 Endpoint_ClearStatusStage();
387
388                 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
389 #ifdef LUFA_DEBUG
390                 xprintf("[I%d]%d", USB_ControlRequest.wIndex, (USB_ControlRequest.wValue & 0xFF00) >> 8);
391 #endif
392             }
393
394             break;
395         case HID_REQ_GetIdle:
396             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
397             {
398                 Endpoint_ClearSETUP();
399                 while (!(Endpoint_IsINReady()));
400                 Endpoint_Write_8(keyboard_idle);
401                 Endpoint_ClearIN();
402                 Endpoint_ClearStatusStage();
403 #ifdef LUFA_DEBUG
404                 print("[i]");
405 #endif
406             }
407
408             break;
409     }
410 }
411
412 /*******************************************************************************
413  * Host driver
414  ******************************************************************************/
415 static uint8_t keyboard_leds(void)
416 {
417     return keyboard_led_stats;
418 }
419
420 static void send_keyboard(report_keyboard_t *report)
421 {
422     uint8_t timeout = 255;
423
424     if (USB_DeviceState != DEVICE_STATE_Configured)
425         return;
426
427     /* Select the Keyboard Report Endpoint */
428 #ifdef NKRO_ENABLE
429     if (keyboard_protocol && keyboard_nkro) {
430         /* Report protocol - NKRO */
431         Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
432
433         /* Check if write ready for a polling interval around 1ms */
434         while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(8);
435         if (!Endpoint_IsReadWriteAllowed()) return;
436
437         /* Write Keyboard Report Data */
438         Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
439     }
440     else
441 #endif
442     {
443         /* Boot protocol */
444         Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
445
446         /* Check if write ready for a polling interval around 10ms */
447         while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
448         if (!Endpoint_IsReadWriteAllowed()) return;
449
450         /* Write Keyboard Report Data */
451         Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
452     }
453
454     /* Finalize the stream transfer to send the last packet */
455     Endpoint_ClearIN();
456
457     keyboard_report_sent = *report;
458 }
459
460 static void send_mouse(report_mouse_t *report)
461 {
462 #ifdef MOUSE_ENABLE
463     uint8_t timeout = 255;
464
465     if (USB_DeviceState != DEVICE_STATE_Configured)
466         return;
467
468     /* Select the Mouse Report Endpoint */
469     Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
470
471     /* Check if write ready for a polling interval around 10ms */
472     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
473     if (!Endpoint_IsReadWriteAllowed()) return;
474
475     /* Write Mouse Report Data */
476     Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
477
478     /* Finalize the stream transfer to send the last packet */
479     Endpoint_ClearIN();
480 #endif
481 }
482
483 static void send_system(uint16_t data)
484 {
485     uint8_t timeout = 255;
486
487     if (USB_DeviceState != DEVICE_STATE_Configured)
488         return;
489
490     report_extra_t r = {
491         .report_id = REPORT_ID_SYSTEM,
492         .usage = data
493     };
494     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
495
496     /* Check if write ready for a polling interval around 10ms */
497     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
498     if (!Endpoint_IsReadWriteAllowed()) return;
499
500     Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
501     Endpoint_ClearIN();
502 }
503
504 static void send_consumer(uint16_t data)
505 {
506     uint8_t timeout = 255;
507
508     if (USB_DeviceState != DEVICE_STATE_Configured)
509         return;
510
511     report_extra_t r = {
512         .report_id = REPORT_ID_CONSUMER,
513         .usage = data
514     };
515     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
516
517     /* Check if write ready for a polling interval around 10ms */
518     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
519     if (!Endpoint_IsReadWriteAllowed()) return;
520
521     Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
522     Endpoint_ClearIN();
523 }
524
525
526 /*******************************************************************************
527  * sendchar
528  ******************************************************************************/
529 #ifdef CONSOLE_ENABLE
530 #define SEND_TIMEOUT 5
531 int8_t sendchar(uint8_t c)
532 {
533 #ifdef LUFA_DEBUG_SUART
534     xmit(c);
535 #endif
536     // Not wait once timeouted.
537     // Because sendchar() is called so many times, waiting each call causes big lag.
538     static bool timeouted = false;
539
540     // prevents Console_Task() from running during sendchar() runs.
541     // or char will be lost. These two function is mutually exclusive.
542     CONSOLE_FLUSH_SET(false);
543
544     if (USB_DeviceState != DEVICE_STATE_Configured)
545         return -1;
546
547     uint8_t ep = Endpoint_GetCurrentEndpoint();
548     Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
549     if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
550         goto ERROR_EXIT;
551     }
552
553     if (timeouted && !Endpoint_IsReadWriteAllowed()) {
554         goto ERROR_EXIT;
555     }
556
557     timeouted = false;
558
559     uint8_t timeout = SEND_TIMEOUT;
560     while (!Endpoint_IsReadWriteAllowed()) {
561         if (USB_DeviceState != DEVICE_STATE_Configured) {
562             goto ERROR_EXIT;
563         }
564         if (Endpoint_IsStalled()) {
565             goto ERROR_EXIT;
566         }
567         if (!(timeout--)) {
568             timeouted = true;
569             goto ERROR_EXIT;
570         }
571         _delay_ms(1);
572     }
573
574     Endpoint_Write_8(c);
575
576     // send when bank is full
577     if (!Endpoint_IsReadWriteAllowed()) {
578         while (!(Endpoint_IsINReady()));
579         Endpoint_ClearIN();
580     } else {
581         CONSOLE_FLUSH_SET(true);
582     }
583
584     Endpoint_SelectEndpoint(ep);
585     return 0;
586 ERROR_EXIT:
587     Endpoint_SelectEndpoint(ep);
588     return -1;
589 }
590 #else
591 int8_t sendchar(uint8_t c)
592 {
593 #ifdef LUFA_DEBUG_SUART
594     xmit(c);
595 #endif
596     return 0;
597 }
598 #endif
599
600
601 /*******************************************************************************
602  * main
603  ******************************************************************************/
604 static void setup_mcu(void)
605 {
606     /* Disable watchdog if enabled by bootloader/fuses */
607     MCUSR &= ~(1 << WDRF);
608     wdt_disable();
609
610     /* Disable clock division */
611     clock_prescale_set(clock_div_1);
612 }
613
614 static void setup_usb(void)
615 {
616     // Leonardo needs. Without this USB device is not recognized.
617     USB_Disable();
618
619     USB_Init();
620
621     // for Console_Task
622     USB_Device_EnableSOFEvents();
623 }
624
625 int main(void)  __attribute__ ((weak));
626 int main(void)
627 {
628     setup_mcu();
629
630 #ifdef LUFA_DEBUG_SUART
631     SUART_OUT_DDR |= (1<<SUART_OUT_BIT);
632     SUART_OUT_PORT |= (1<<SUART_OUT_BIT);
633 #endif
634     print_set_sendchar(sendchar);
635     print("\r\ninit\n");
636
637     hook_early_init();
638     keyboard_setup();
639     setup_usb();
640     sei();
641
642     /* wait for USB startup & debug output */
643     while (USB_DeviceState != DEVICE_STATE_Configured) {
644 #if defined(INTERRUPT_CONTROL_ENDPOINT)
645         ;
646 #else
647         USB_USBTask();
648 #endif
649     }
650     print("USB configured.\n");
651
652     /* init modules */
653     keyboard_init();
654     host_set_driver(&lufa_driver);
655 #ifdef SLEEP_LED_ENABLE
656     sleep_led_init();
657 #endif
658
659     print("Keyboard start.\n");
660     hook_late_init();
661     while (1) {
662         while (USB_DeviceState == DEVICE_STATE_Suspended) {
663 #ifdef LUFA_DEBUG
664             print("[s]");
665 #endif
666             hook_usb_suspend_loop();
667         }
668
669         keyboard_task();
670
671 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
672         USB_USBTask();
673 #endif
674     }
675 }
676
677
678 /* hooks */
679 __attribute__((weak))
680 void hook_early_init(void) {}
681
682 __attribute__((weak))
683 void hook_late_init(void) {}
684
685 static uint8_t _led_stats = 0;
686  __attribute__((weak))
687 void hook_usb_suspend_entry(void)
688 {
689     // Turn LED off to save power
690     // Set 0 with putting aside status before suspend and restore
691     // it after wakeup, then LED is updated at keyboard_task() in main loop
692     _led_stats = keyboard_led_stats;
693     keyboard_led_stats = 0;
694     led_set(keyboard_led_stats);
695
696     matrix_clear();
697     clear_keyboard();
698 #ifdef SLEEP_LED_ENABLE
699     sleep_led_enable();
700 #endif
701 }
702
703 __attribute__((weak))
704 void hook_usb_suspend_loop(void)
705 {
706     suspend_power_down();
707     if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
708         USB_Device_SendRemoteWakeup();
709     }
710 }
711
712 __attribute__((weak))
713 void hook_usb_wakeup(void)
714 {
715     suspend_wakeup_init();
716 #ifdef SLEEP_LED_ENABLE
717     sleep_led_disable();
718 #endif
719
720     // Restore LED status
721     // BIOS/grub won't recognize/enumerate if led_set() takes long(around 40ms?)
722     // Converters fall into the case and miss wakeup event(timeout to reply?) in the end.
723     //led_set(host_keyboard_leds());
724     // Instead, restore stats and update at keyboard_task() in main loop
725     keyboard_led_stats = _led_stats;
726 }