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