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