]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/protocol/lufa/lufa.c
lufa: Add debug print support with UART
[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 "ringbuf.h"
47 #include "debug.h"
48 #ifdef SLEEP_LED_ENABLE
49 #include "sleep_led.h"
50 #endif
51 #include "suspend.h"
52 #include "hook.h"
53 #include "timer.h"
54
55 #ifdef LUFA_DEBUG_SUART
56 #include "avr/suart.h"
57 #endif
58
59 #ifdef LUFA_DEBUG_UART
60 #include "uart.h"
61 #endif
62
63 #include "matrix.h"
64 #include "descriptor.h"
65 #include "lufa.h"
66
67
68 //#define LUFA_DEBUG
69
70
71 uint8_t keyboard_idle = 0;
72 /* 0: Boot Protocol, 1: Report Protocol(default) */
73 uint8_t keyboard_protocol = 1;
74 static uint8_t keyboard_led_stats = 0;
75
76 static report_keyboard_t keyboard_report_sent;
77
78
79 /* Host driver */
80 static uint8_t keyboard_leds(void);
81 static void send_keyboard(report_keyboard_t *report);
82 static void send_mouse(report_mouse_t *report);
83 static void send_system(uint16_t data);
84 static void send_consumer(uint16_t data);
85 host_driver_t lufa_driver = {
86     keyboard_leds,
87     send_keyboard,
88     send_mouse,
89     send_system,
90     send_consumer
91 };
92
93
94 /*******************************************************************************
95  * Console
96  ******************************************************************************/
97 #ifdef CONSOLE_ENABLE
98 #define SENDBUF_SIZE 256
99 static uint8_t sbuf[SENDBUF_SIZE];
100 static ringbuf_t sendbuf = {
101     .buffer = sbuf,
102     .head = 0,
103     .tail = 0,
104     .size_mask = SENDBUF_SIZE - 1
105 };
106
107 // TODO: Around 2500ms delay often works anyhoo but proper startup would be better
108 // 1000ms delay of hid_listen affects this probably
109 /* wait for Console startup */
110 static bool console_is_ready(void)
111 {
112     static bool hid_listen_ready = false;
113     if (!hid_listen_ready) {
114         if (timer_read32() < 2500)
115             return false;
116         hid_listen_ready = true;
117     }
118     return true;
119 }
120
121 static bool console_putc(uint8_t c)
122 {
123     if (!console_is_ready())
124         goto EXIT;
125
126     // return immediately if called while interrupt
127     if (!(SREG & (1<<SREG_I)))
128         goto EXIT;
129
130     if (USB_DeviceState != DEVICE_STATE_Configured)
131         goto EXIT;
132
133     uint8_t ep = Endpoint_GetCurrentEndpoint();
134
135     Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
136     if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
137         goto EXIT_RESTORE_EP;
138     }
139
140     // write from buffer to endpoint bank
141     while (!ringbuf_is_empty(&sendbuf) && Endpoint_IsReadWriteAllowed()) {
142         Endpoint_Write_8(ringbuf_get(&sendbuf));
143
144         // clear bank when it is full
145         if (!Endpoint_IsReadWriteAllowed() && Endpoint_IsINReady()) {
146             Endpoint_ClearIN();
147         }
148     }
149
150     // write c to bank directly if there is no others in buffer
151     if (ringbuf_is_empty(&sendbuf) && Endpoint_IsReadWriteAllowed()) {
152         Endpoint_Write_8(c);
153         Endpoint_SelectEndpoint(ep);
154         return true;
155     }
156
157 EXIT_RESTORE_EP:
158     Endpoint_SelectEndpoint(ep);
159 EXIT:
160     return ringbuf_put(&sendbuf, c);
161 }
162
163 static void console_flush(void)
164 {
165     if (!console_is_ready())
166         return;
167
168     if (USB_DeviceState != DEVICE_STATE_Configured)
169         return;
170
171     uint8_t ep = Endpoint_GetCurrentEndpoint();
172
173     Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
174     if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
175         Endpoint_SelectEndpoint(ep);
176         return;
177     }
178
179     // write from buffer to endpoint bank
180     while (!ringbuf_is_empty(&sendbuf) && Endpoint_IsReadWriteAllowed()) {
181         Endpoint_Write_8(ringbuf_get(&sendbuf));
182
183         // clear bank when it is full
184         if (!Endpoint_IsReadWriteAllowed() && Endpoint_IsINReady()) {
185             Endpoint_ClearIN();
186         }
187     }
188
189     // clear bank when there are chars in bank
190     if (Endpoint_BytesInEndpoint() && Endpoint_IsINReady()) {
191         // Windows needs to fill packet with 0
192         while (Endpoint_IsReadWriteAllowed()) {
193                 Endpoint_Write_8(0);
194         }
195         Endpoint_ClearIN();
196     }
197
198     Endpoint_SelectEndpoint(ep);
199 }
200
201 static void console_task(void)
202 {
203     static uint16_t fn = 0;
204     if (fn == USB_Device_GetFrameNumber()) {
205         return;
206     }
207     fn = USB_Device_GetFrameNumber();
208     console_flush();
209 }
210 #endif
211
212
213 /*******************************************************************************
214  * USB Events
215  ******************************************************************************/
216 /*
217  * Event Order of Plug in:
218  * 0) EVENT_USB_Device_Connect
219  * 1) EVENT_USB_Device_Suspend
220  * 2) EVENT_USB_Device_Reset
221  * 3) EVENT_USB_Device_Wake
222 */
223 void EVENT_USB_Device_Connect(void)
224 {
225 #ifdef LUFA_DEBUG
226     print("[C]");
227 #endif
228     /* For battery powered device */
229     if (!USB_IsInitialized) {
230         USB_Disable();
231         USB_Init();
232         USB_Device_EnableSOFEvents();
233     }
234 }
235
236 void EVENT_USB_Device_Disconnect(void)
237 {
238 #ifdef LUFA_DEBUG
239     print("[D]");
240 #endif
241     /* For battery powered device */
242     USB_IsInitialized = false;
243 /* TODO: This doesn't work. After several plug in/outs can not be enumerated.
244     if (USB_IsInitialized) {
245         USB_Disable();  // Disable all interrupts
246         USB_Controller_Enable();
247         USB_INT_Enable(USB_INT_VBUSTI);
248     }
249 */
250 }
251
252 void EVENT_USB_Device_Reset(void)
253 {
254 #ifdef LUFA_DEBUG
255     print("[R]");
256 #endif
257 }
258
259 void EVENT_USB_Device_Suspend()
260 {
261 #ifdef LUFA_DEBUG
262     print("[S]");
263 #endif
264     hook_usb_suspend_entry();
265 }
266
267 void EVENT_USB_Device_WakeUp()
268 {
269 #ifdef LUFA_DEBUG
270     print("[W]");
271 #endif
272     hook_usb_wakeup();
273 }
274
275 // called every 1ms
276 void EVENT_USB_Device_StartOfFrame(void)
277 {
278 }
279
280 /** Event handler for the USB_ConfigurationChanged event.
281  * This is fired when the host sets the current configuration of the USB device after enumeration.
282  *
283  * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4,
284  * it is safe to use singl bank for all endpoints.
285  */
286 void EVENT_USB_Device_ConfigurationChanged(void)
287 {
288 #ifdef LUFA_DEBUG
289     print("[c]");
290 #endif
291     bool ConfigSuccess = true;
292
293     /* Setup Keyboard HID Report Endpoints */
294     ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
295                                      KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
296
297 #ifdef MOUSE_ENABLE
298     /* Setup Mouse HID Report Endpoint */
299     ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
300                                      MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
301 #endif
302
303 #ifdef EXTRAKEY_ENABLE
304     /* Setup Extra HID Report Endpoint */
305     ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
306                                      EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
307 #endif
308
309 #ifdef CONSOLE_ENABLE
310     /* Setup Console HID Report Endpoints */
311     ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
312                                      CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
313 #if 0
314     ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
315                                      CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
316 #endif
317 #endif
318
319 #ifdef NKRO_ENABLE
320     /* Setup NKRO HID Report Endpoints */
321     ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
322                                      NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
323 #endif
324 }
325
326 /*
327 Appendix G: HID Request Support Requirements
328
329 The following table enumerates the requests that need to be supported by various types of HID class devices.
330
331 Device type     GetReport   SetReport   GetIdle     SetIdle     GetProtocol SetProtocol
332 ------------------------------------------------------------------------------------------
333 Boot Mouse      Required    Optional    Optional    Optional    Required    Required
334 Non-Boot Mouse  Required    Optional    Optional    Optional    Optional    Optional
335 Boot Keyboard   Required    Optional    Required    Required    Required    Required
336 Non-Boot Keybrd Required    Optional    Required    Required    Optional    Optional
337 Other Device    Required    Optional    Optional    Optional    Optional    Optional
338 */
339 /** Event handler for the USB_ControlRequest event.
340  *  This is fired before passing along unhandled control requests to the library for processing internally.
341  */
342 void EVENT_USB_Device_ControlRequest(void)
343 {
344     uint8_t* ReportData = NULL;
345     uint8_t  ReportSize = 0;
346
347     /* Handle HID Class specific requests */
348     switch (USB_ControlRequest.bRequest)
349     {
350         case HID_REQ_GetReport:
351             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
352             {
353                 Endpoint_ClearSETUP();
354
355                 // Interface
356                 switch (USB_ControlRequest.wIndex) {
357                 case KEYBOARD_INTERFACE:
358                     // TODO: test/check
359                     ReportData = (uint8_t*)&keyboard_report_sent;
360                     ReportSize = sizeof(keyboard_report_sent);
361                     break;
362                 }
363
364                 /* Write the report data to the control endpoint */
365                 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
366                 Endpoint_ClearOUT();
367 #ifdef LUFA_DEBUG
368                 xprintf("[r%d]", USB_ControlRequest.wIndex);
369 #endif
370             }
371
372             break;
373         case HID_REQ_SetReport:
374             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
375             {
376
377                 // Interface
378                 switch (USB_ControlRequest.wIndex) {
379                 case KEYBOARD_INTERFACE:
380 #ifdef NKRO_ENABLE
381                 case NKRO_INTERFACE:
382 #endif
383                     Endpoint_ClearSETUP();
384
385                     while (!(Endpoint_IsOUTReceived())) {
386                         if (USB_DeviceState == DEVICE_STATE_Unattached)
387                           return;
388                     }
389                     keyboard_led_stats = Endpoint_Read_8();
390
391                     Endpoint_ClearOUT();
392                     Endpoint_ClearStatusStage();
393 #ifdef LUFA_DEBUG
394                     xprintf("[L%d]", USB_ControlRequest.wIndex);
395 #endif
396                     break;
397                 }
398
399             }
400
401             break;
402
403         case HID_REQ_GetProtocol:
404             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
405             {
406                 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
407                     Endpoint_ClearSETUP();
408                     while (!(Endpoint_IsINReady()));
409                     Endpoint_Write_8(keyboard_protocol);
410                     Endpoint_ClearIN();
411                     Endpoint_ClearStatusStage();
412 #ifdef LUFA_DEBUG
413                     print("[p]");
414 #endif
415                 }
416             }
417
418             break;
419         case HID_REQ_SetProtocol:
420             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
421             {
422                 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
423                     Endpoint_ClearSETUP();
424                     Endpoint_ClearStatusStage();
425
426                     keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
427                     clear_keyboard();
428 #ifdef LUFA_DEBUG
429                     print("[P]");
430 #endif
431                 }
432             }
433
434             break;
435         case HID_REQ_SetIdle:
436             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
437             {
438                 Endpoint_ClearSETUP();
439                 Endpoint_ClearStatusStage();
440
441                 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
442 #ifdef LUFA_DEBUG
443                 xprintf("[I%d]%d", USB_ControlRequest.wIndex, (USB_ControlRequest.wValue & 0xFF00) >> 8);
444 #endif
445             }
446
447             break;
448         case HID_REQ_GetIdle:
449             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
450             {
451                 Endpoint_ClearSETUP();
452                 while (!(Endpoint_IsINReady()));
453                 Endpoint_Write_8(keyboard_idle);
454                 Endpoint_ClearIN();
455                 Endpoint_ClearStatusStage();
456 #ifdef LUFA_DEBUG
457                 print("[i]");
458 #endif
459             }
460
461             break;
462     }
463 }
464
465 /*******************************************************************************
466  * Host driver
467  ******************************************************************************/
468 static uint8_t keyboard_leds(void)
469 {
470     return keyboard_led_stats;
471 }
472
473 static void send_keyboard(report_keyboard_t *report)
474 {
475     uint8_t timeout = 128;
476
477     if (USB_DeviceState != DEVICE_STATE_Configured)
478         return;
479
480     /* Select the Keyboard Report Endpoint */
481 #ifdef NKRO_ENABLE
482     if (keyboard_protocol && keyboard_nkro) {
483         /* Report protocol - NKRO */
484         Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
485
486         /* Check if write ready for a polling interval around 1ms */
487         while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(8);
488         if (!Endpoint_IsReadWriteAllowed()) return;
489
490         /* Write Keyboard Report Data */
491         Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
492     }
493     else
494 #endif
495     {
496         /* Boot protocol */
497         Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
498
499         /* Check if write ready for a polling interval around 10ms */
500         while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(80);
501         if (!Endpoint_IsReadWriteAllowed()) return;
502
503         /* Write Keyboard Report Data */
504         Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
505     }
506
507     /* Finalize the stream transfer to send the last packet */
508     Endpoint_ClearIN();
509
510     keyboard_report_sent = *report;
511 }
512
513 static void send_mouse(report_mouse_t *report)
514 {
515 #ifdef MOUSE_ENABLE
516     uint8_t timeout = 255;
517
518     if (USB_DeviceState != DEVICE_STATE_Configured)
519         return;
520
521     /* Select the Mouse Report Endpoint */
522     Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
523
524     /* Check if write ready for a polling interval around 10ms */
525     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
526     if (!Endpoint_IsReadWriteAllowed()) return;
527
528     /* Write Mouse Report Data */
529     Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
530
531     /* Finalize the stream transfer to send the last packet */
532     Endpoint_ClearIN();
533 #endif
534 }
535
536 static void send_system(uint16_t data)
537 {
538 #ifdef EXTRAKEY_ENABLE
539     uint8_t timeout = 255;
540
541     if (USB_DeviceState != DEVICE_STATE_Configured)
542         return;
543
544     report_extra_t r = {
545         .report_id = REPORT_ID_SYSTEM,
546         .usage = data - SYSTEM_POWER_DOWN + 1
547     };
548     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
549
550     /* Check if write ready for a polling interval around 10ms */
551     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
552     if (!Endpoint_IsReadWriteAllowed()) return;
553
554     Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
555     Endpoint_ClearIN();
556 #endif
557 }
558
559 static void send_consumer(uint16_t data)
560 {
561 #ifdef EXTRAKEY_ENABLE
562     uint8_t timeout = 255;
563
564     if (USB_DeviceState != DEVICE_STATE_Configured)
565         return;
566
567     report_extra_t r = {
568         .report_id = REPORT_ID_CONSUMER,
569         .usage = data
570     };
571     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
572
573     /* Check if write ready for a polling interval around 10ms */
574     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
575     if (!Endpoint_IsReadWriteAllowed()) return;
576
577     Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
578     Endpoint_ClearIN();
579 #endif
580 }
581
582
583 /*******************************************************************************
584  * sendchar
585  ******************************************************************************/
586 int8_t sendchar(uint8_t c)
587 {
588     #ifdef LUFA_DEBUG_SUART
589     xmit(c);
590     #endif
591
592     #ifdef LUFA_DEBUG_UART
593     uart_putchar(c);
594     #endif
595
596     #ifdef CONSOLE_ENABLE
597     console_putc(c);
598     #endif
599
600     return 0;
601 }
602
603
604 /*******************************************************************************
605  * main
606  ******************************************************************************/
607 static void setup_mcu(void)
608 {
609     /* Disable watchdog if enabled by bootloader/fuses */
610     MCUSR &= ~(1 << WDRF);
611     wdt_disable();
612
613     /* Disable clock division */
614     clock_prescale_set(clock_div_1);
615 }
616
617 static void setup_usb(void)
618 {
619     // Leonardo needs. Without this USB device is not recognized.
620     USB_Disable();
621
622     USB_Init();
623
624     USB_Device_EnableSOFEvents();
625 }
626
627 int main(void)  __attribute__ ((weak));
628 int main(void)
629 {
630     setup_mcu();
631
632 #ifdef LUFA_DEBUG_SUART
633     SUART_OUT_DDR |= (1<<SUART_OUT_BIT);
634     SUART_OUT_PORT |= (1<<SUART_OUT_BIT);
635 #endif
636
637 #ifdef LUFA_DEBUG_UART
638     uart_init(115200);
639 #endif
640
641     // setup sendchar: DO NOT USE print functions before this line
642     print_set_sendchar(sendchar);
643     host_set_driver(&lufa_driver);
644
645     print("Keyboard init.\n");
646     hook_early_init();
647     keyboard_setup();
648     setup_usb();
649 #ifdef SLEEP_LED_ENABLE
650     sleep_led_init();
651 #endif
652
653     sei();
654
655     keyboard_init();
656
657     /* wait for USB startup */
658     while (USB_DeviceState != DEVICE_STATE_Configured) {
659 #if defined(INTERRUPT_CONTROL_ENDPOINT)
660         ;
661 #else
662         USB_USBTask();
663 #endif
664         matrix_scan();
665     }
666
667     hook_late_init();
668
669     print("\nKeyboard start.\n");
670     while (1) {
671         while (USB_DeviceState == DEVICE_STATE_Suspended) {
672 #ifdef LUFA_DEBUG
673             print("[s]");
674 #endif
675             hook_usb_suspend_loop();
676         }
677
678         keyboard_task();
679
680 #ifdef CONSOLE_ENABLE
681         console_task();
682 #endif
683
684 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
685         USB_USBTask();
686 #endif
687     }
688 }
689
690
691 /* hooks */
692 __attribute__((weak))
693 void hook_early_init(void) {}
694
695 __attribute__((weak))
696 void hook_late_init(void) {}
697
698 static uint8_t _led_stats = 0;
699  __attribute__((weak))
700 void hook_usb_suspend_entry(void)
701 {
702     // Turn LED off to save power
703     // Set 0 with putting aside status before suspend and restore
704     // it after wakeup, then LED is updated at keyboard_task() in main loop
705     _led_stats = keyboard_led_stats;
706     keyboard_led_stats = 0;
707     led_set(keyboard_led_stats);
708
709     matrix_clear();
710     clear_keyboard();
711 #ifdef SLEEP_LED_ENABLE
712     sleep_led_enable();
713 #endif
714 }
715
716 __attribute__((weak))
717 void hook_usb_suspend_loop(void)
718 {
719     suspend_power_down();
720     if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
721         USB_Device_SendRemoteWakeup();
722     }
723 }
724
725 __attribute__((weak))
726 void hook_usb_wakeup(void)
727 {
728     suspend_wakeup_init();
729 #ifdef SLEEP_LED_ENABLE
730     sleep_led_disable();
731 #endif
732
733     // Restore LED status
734     // BIOS/grub won't recognize/enumerate if led_set() takes long(around 40ms?)
735     // Converters fall into the case and miss wakeup event(timeout to reply?) in the end.
736     //led_set(host_keyboard_leds());
737     // Instead, restore stats and update at keyboard_task() in main loop
738     keyboard_led_stats = _led_stats;
739 }