]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/protocol/lufa/lufa.c
core: lufa: Add delay for console startup
[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 #ifdef EXTRAKEY_ENABLE
486     uint8_t timeout = 255;
487
488     if (USB_DeviceState != DEVICE_STATE_Configured)
489         return;
490
491     report_extra_t r = {
492         .report_id = REPORT_ID_SYSTEM,
493         .usage = data
494     };
495     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
496
497     /* Check if write ready for a polling interval around 10ms */
498     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
499     if (!Endpoint_IsReadWriteAllowed()) return;
500
501     Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
502     Endpoint_ClearIN();
503 #endif
504 }
505
506 static void send_consumer(uint16_t data)
507 {
508 #ifdef EXTRAKEY_ENABLE
509     uint8_t timeout = 255;
510
511     if (USB_DeviceState != DEVICE_STATE_Configured)
512         return;
513
514     report_extra_t r = {
515         .report_id = REPORT_ID_CONSUMER,
516         .usage = data
517     };
518     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
519
520     /* Check if write ready for a polling interval around 10ms */
521     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
522     if (!Endpoint_IsReadWriteAllowed()) return;
523
524     Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
525     Endpoint_ClearIN();
526 #endif
527 }
528
529
530 /*******************************************************************************
531  * sendchar
532  ******************************************************************************/
533 #ifdef CONSOLE_ENABLE
534 #define SEND_TIMEOUT 5
535 int8_t sendchar(uint8_t c)
536 {
537 #ifdef LUFA_DEBUG_SUART
538     xmit(c);
539 #endif
540     // Not wait once timeouted.
541     // Because sendchar() is called so many times, waiting each call causes big lag.
542     static bool timeouted = false;
543
544     // prevents Console_Task() from running during sendchar() runs.
545     // or char will be lost. These two function is mutually exclusive.
546     CONSOLE_FLUSH_SET(false);
547
548     if (USB_DeviceState != DEVICE_STATE_Configured)
549         return -1;
550
551     uint8_t ep = Endpoint_GetCurrentEndpoint();
552     Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
553     if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
554         goto ERROR_EXIT;
555     }
556
557     if (timeouted && !Endpoint_IsReadWriteAllowed()) {
558         goto ERROR_EXIT;
559     }
560
561     timeouted = false;
562
563     uint8_t timeout = SEND_TIMEOUT;
564     while (!Endpoint_IsReadWriteAllowed()) {
565         if (USB_DeviceState != DEVICE_STATE_Configured) {
566             goto ERROR_EXIT;
567         }
568         if (Endpoint_IsStalled()) {
569             goto ERROR_EXIT;
570         }
571         if (!(timeout--)) {
572             timeouted = true;
573             goto ERROR_EXIT;
574         }
575         _delay_ms(1);
576     }
577
578     Endpoint_Write_8(c);
579
580     // send when bank is full
581     if (!Endpoint_IsReadWriteAllowed()) {
582         while (!(Endpoint_IsINReady()));
583         Endpoint_ClearIN();
584     } else {
585         CONSOLE_FLUSH_SET(true);
586     }
587
588     Endpoint_SelectEndpoint(ep);
589     return 0;
590 ERROR_EXIT:
591     Endpoint_SelectEndpoint(ep);
592     return -1;
593 }
594 #else
595 int8_t sendchar(uint8_t c)
596 {
597 #ifdef LUFA_DEBUG_SUART
598     xmit(c);
599 #endif
600     return 0;
601 }
602 #endif
603
604
605 /*******************************************************************************
606  * main
607  ******************************************************************************/
608 static void setup_mcu(void)
609 {
610     /* Disable watchdog if enabled by bootloader/fuses */
611     MCUSR &= ~(1 << WDRF);
612     wdt_disable();
613
614     /* Disable clock division */
615     clock_prescale_set(clock_div_1);
616 }
617
618 static void setup_usb(void)
619 {
620     // Leonardo needs. Without this USB device is not recognized.
621     USB_Disable();
622
623     USB_Init();
624
625     // for Console_Task
626     USB_Device_EnableSOFEvents();
627 }
628
629 int main(void)  __attribute__ ((weak));
630 int main(void)
631 {
632     setup_mcu();
633
634 #ifdef LUFA_DEBUG_SUART
635     SUART_OUT_DDR |= (1<<SUART_OUT_BIT);
636     SUART_OUT_PORT |= (1<<SUART_OUT_BIT);
637 #endif
638     print_set_sendchar(sendchar);
639     print("\r\ninit\n");
640
641     hook_early_init();
642     keyboard_setup();
643     setup_usb();
644     sei();
645
646     /* wait for USB startup & debug output */
647     while (USB_DeviceState != DEVICE_STATE_Configured) {
648 #if defined(INTERRUPT_CONTROL_ENDPOINT)
649         ;
650 #else
651         USB_USBTask();
652 #endif
653     }
654
655     /* wait for Console startup */
656     // TODO: long delay often works anyhoo but proper startup would be better
657     uint16_t delay = 2000;
658     while (delay--) {
659 #ifndef INTERRUPT_CONTROL_ENDPOINT
660         USB_USBTask();
661 #endif
662         _delay_ms(1);
663     }
664
665     print("USB configured.\n");
666
667     /* init modules */
668     keyboard_init();
669     host_set_driver(&lufa_driver);
670 #ifdef SLEEP_LED_ENABLE
671     sleep_led_init();
672 #endif
673
674     print("Keyboard start.\n");
675     hook_late_init();
676     while (1) {
677         while (USB_DeviceState == DEVICE_STATE_Suspended) {
678 #ifdef LUFA_DEBUG
679             print("[s]");
680 #endif
681             hook_usb_suspend_loop();
682         }
683
684         keyboard_task();
685
686 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
687         USB_USBTask();
688 #endif
689     }
690 }
691
692
693 /* hooks */
694 __attribute__((weak))
695 void hook_early_init(void) {}
696
697 __attribute__((weak))
698 void hook_late_init(void) {}
699
700 static uint8_t _led_stats = 0;
701  __attribute__((weak))
702 void hook_usb_suspend_entry(void)
703 {
704     // Turn LED off to save power
705     // Set 0 with putting aside status before suspend and restore
706     // it after wakeup, then LED is updated at keyboard_task() in main loop
707     _led_stats = keyboard_led_stats;
708     keyboard_led_stats = 0;
709     led_set(keyboard_led_stats);
710
711     matrix_clear();
712     clear_keyboard();
713 #ifdef SLEEP_LED_ENABLE
714     sleep_led_enable();
715 #endif
716 }
717
718 __attribute__((weak))
719 void hook_usb_suspend_loop(void)
720 {
721     suspend_power_down();
722     if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
723         USB_Device_SendRemoteWakeup();
724     }
725 }
726
727 __attribute__((weak))
728 void hook_usb_wakeup(void)
729 {
730     suspend_wakeup_init();
731 #ifdef SLEEP_LED_ENABLE
732     sleep_led_disable();
733 #endif
734
735     // Restore LED status
736     // BIOS/grub won't recognize/enumerate if led_set() takes long(around 40ms?)
737     // Converters fall into the case and miss wakeup event(timeout to reply?) in the end.
738     //led_set(host_keyboard_leds());
739     // Instead, restore stats and update at keyboard_task() in main loop
740     keyboard_led_stats = _led_stats;
741 }