]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/protocol/lufa/lufa.c
lufa: Fix console_putc
[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     // 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 LUFA_DEBUG
269     print("[C]");
270 #endif
271     /* For battery powered device */
272     if (!USB_IsInitialized) {
273         USB_Disable();
274         USB_Init();
275         USB_Device_EnableSOFEvents();
276     }
277 }
278
279 void EVENT_USB_Device_Disconnect(void)
280 {
281 #ifdef LUFA_DEBUG
282     print("[D]");
283 #endif
284     /* For battery powered device */
285     USB_IsInitialized = false;
286 /* TODO: This doesn't work. After several plug in/outs can not be enumerated.
287     if (USB_IsInitialized) {
288         USB_Disable();  // Disable all interrupts
289         USB_Controller_Enable();
290         USB_INT_Enable(USB_INT_VBUSTI);
291     }
292 */
293 }
294
295 void EVENT_USB_Device_Reset(void)
296 {
297 #ifdef LUFA_DEBUG
298     print("[R]");
299 #endif
300 }
301
302 void EVENT_USB_Device_Suspend()
303 {
304 #ifdef LUFA_DEBUG
305     print("[S]");
306 #endif
307     hook_usb_suspend_entry();
308 }
309
310 void EVENT_USB_Device_WakeUp()
311 {
312 #ifdef LUFA_DEBUG
313     print("[W]");
314 #endif
315     hook_usb_wakeup();
316 }
317
318 // called every 1ms
319 void EVENT_USB_Device_StartOfFrame(void)
320 {
321 }
322
323 /** Event handler for the USB_ConfigurationChanged event.
324  * This is fired when the host sets the current configuration of the USB device after enumeration.
325  *
326  * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4,
327  * it is safe to use singl bank for all endpoints.
328  */
329 void EVENT_USB_Device_ConfigurationChanged(void)
330 {
331 #ifdef LUFA_DEBUG
332     print("[c]");
333 #endif
334     bool ConfigSuccess = true;
335
336     /* Setup Keyboard HID Report Endpoints */
337     ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
338                                      KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
339
340 #ifdef MOUSE_ENABLE
341     /* Setup Mouse HID Report Endpoint */
342     ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
343                                      MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
344 #endif
345
346 #ifdef EXTRAKEY_ENABLE
347     /* Setup Extra HID Report Endpoint */
348     ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
349                                      EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
350 #endif
351
352 #ifdef CONSOLE_ENABLE
353     /* Setup Console HID Report Endpoints */
354     ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
355                                      CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
356 #if 0
357     ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
358                                      CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
359 #endif
360 #endif
361
362 #ifdef NKRO_ENABLE
363     /* Setup NKRO HID Report Endpoints */
364     ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
365                                      NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
366 #endif
367 }
368
369 /*
370 Appendix G: HID Request Support Requirements
371
372 The following table enumerates the requests that need to be supported by various types of HID class devices.
373
374 Device type     GetReport   SetReport   GetIdle     SetIdle     GetProtocol SetProtocol
375 ------------------------------------------------------------------------------------------
376 Boot Mouse      Required    Optional    Optional    Optional    Required    Required
377 Non-Boot Mouse  Required    Optional    Optional    Optional    Optional    Optional
378 Boot Keyboard   Required    Optional    Required    Required    Required    Required
379 Non-Boot Keybrd Required    Optional    Required    Required    Optional    Optional
380 Other Device    Required    Optional    Optional    Optional    Optional    Optional
381 */
382 /** Event handler for the USB_ControlRequest event.
383  *  This is fired before passing along unhandled control requests to the library for processing internally.
384  */
385 void EVENT_USB_Device_ControlRequest(void)
386 {
387     uint8_t* ReportData = NULL;
388     uint8_t  ReportSize = 0;
389
390     /* Handle HID Class specific requests */
391     switch (USB_ControlRequest.bRequest)
392     {
393         case HID_REQ_GetReport:
394             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
395             {
396                 Endpoint_ClearSETUP();
397
398                 // Interface
399                 switch (USB_ControlRequest.wIndex) {
400                 case KEYBOARD_INTERFACE:
401                     // TODO: test/check
402                     ReportData = (uint8_t*)&keyboard_report_sent;
403                     ReportSize = sizeof(keyboard_report_sent);
404                     break;
405                 }
406
407                 /* Write the report data to the control endpoint */
408                 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
409                 Endpoint_ClearOUT();
410 #ifdef LUFA_DEBUG
411                 xprintf("[r%d]", USB_ControlRequest.wIndex);
412 #endif
413             }
414
415             break;
416         case HID_REQ_SetReport:
417             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
418             {
419
420                 // Interface
421                 switch (USB_ControlRequest.wIndex) {
422                 case KEYBOARD_INTERFACE:
423 #ifdef NKRO_ENABLE
424                 case NKRO_INTERFACE:
425 #endif
426                     Endpoint_ClearSETUP();
427
428                     while (!(Endpoint_IsOUTReceived())) {
429                         if (USB_DeviceState == DEVICE_STATE_Unattached)
430                           return;
431                     }
432                     keyboard_led_stats = Endpoint_Read_8();
433
434                     Endpoint_ClearOUT();
435                     Endpoint_ClearStatusStage();
436 #ifdef LUFA_DEBUG
437                     xprintf("[L%d]", USB_ControlRequest.wIndex);
438 #endif
439                     break;
440                 }
441
442             }
443
444             break;
445
446         case HID_REQ_GetProtocol:
447             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
448             {
449                 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
450                     Endpoint_ClearSETUP();
451                     while (!(Endpoint_IsINReady()));
452                     Endpoint_Write_8(keyboard_protocol);
453                     Endpoint_ClearIN();
454                     Endpoint_ClearStatusStage();
455 #ifdef LUFA_DEBUG
456                     print("[p]");
457 #endif
458                 }
459             }
460
461             break;
462         case HID_REQ_SetProtocol:
463             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
464             {
465                 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
466                     Endpoint_ClearSETUP();
467                     Endpoint_ClearStatusStage();
468
469                     keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
470                     clear_keyboard();
471 #ifdef LUFA_DEBUG
472                     print("[P]");
473 #endif
474                 }
475             }
476
477             break;
478         case HID_REQ_SetIdle:
479             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
480             {
481                 Endpoint_ClearSETUP();
482                 Endpoint_ClearStatusStage();
483
484                 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
485 #ifdef LUFA_DEBUG
486                 xprintf("[I%d]%d", USB_ControlRequest.wIndex, (USB_ControlRequest.wValue & 0xFF00) >> 8);
487 #endif
488             }
489
490             break;
491         case HID_REQ_GetIdle:
492             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
493             {
494                 Endpoint_ClearSETUP();
495                 while (!(Endpoint_IsINReady()));
496                 Endpoint_Write_8(keyboard_idle);
497                 Endpoint_ClearIN();
498                 Endpoint_ClearStatusStage();
499 #ifdef LUFA_DEBUG
500                 print("[i]");
501 #endif
502             }
503
504             break;
505     }
506 }
507
508 /*******************************************************************************
509  * Host driver
510  ******************************************************************************/
511 static uint8_t keyboard_leds(void)
512 {
513     return keyboard_led_stats;
514 }
515
516 static void send_keyboard(report_keyboard_t *report)
517 {
518     uint8_t timeout = 128;
519
520     if (USB_DeviceState != DEVICE_STATE_Configured)
521         return;
522
523     /* Select the Keyboard Report Endpoint */
524 #ifdef NKRO_ENABLE
525     if (keyboard_protocol && keyboard_nkro) {
526         /* Report protocol - NKRO */
527         Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
528
529         /* Check if write ready for a polling interval around 1ms */
530         while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(8);
531         if (!Endpoint_IsReadWriteAllowed()) return;
532
533         /* Write Keyboard Report Data */
534         Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
535     }
536     else
537 #endif
538     {
539         /* Boot protocol */
540         Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
541
542         /* Check if write ready for a polling interval around 10ms */
543         while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(80);
544         if (!Endpoint_IsReadWriteAllowed()) return;
545
546         /* Write Keyboard Report Data */
547         Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
548     }
549
550     /* Finalize the stream transfer to send the last packet */
551     Endpoint_ClearIN();
552
553     keyboard_report_sent = *report;
554 }
555
556 static void send_mouse(report_mouse_t *report)
557 {
558 #ifdef MOUSE_ENABLE
559     uint8_t timeout = 255;
560
561     if (USB_DeviceState != DEVICE_STATE_Configured)
562         return;
563
564     /* Select the Mouse Report Endpoint */
565     Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
566
567     /* Check if write ready for a polling interval around 10ms */
568     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
569     if (!Endpoint_IsReadWriteAllowed()) return;
570
571     /* Write Mouse Report Data */
572     Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
573
574     /* Finalize the stream transfer to send the last packet */
575     Endpoint_ClearIN();
576 #endif
577 }
578
579 static void send_system(uint16_t data)
580 {
581 #ifdef EXTRAKEY_ENABLE
582     uint8_t timeout = 255;
583
584     if (USB_DeviceState != DEVICE_STATE_Configured)
585         return;
586
587     report_extra_t r = {
588         .report_id = REPORT_ID_SYSTEM,
589         .usage = data - SYSTEM_POWER_DOWN + 1
590     };
591     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
592
593     /* Check if write ready for a polling interval around 10ms */
594     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
595     if (!Endpoint_IsReadWriteAllowed()) return;
596
597     Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
598     Endpoint_ClearIN();
599 #endif
600 }
601
602 static void send_consumer(uint16_t data)
603 {
604 #ifdef EXTRAKEY_ENABLE
605     uint8_t timeout = 255;
606
607     if (USB_DeviceState != DEVICE_STATE_Configured)
608         return;
609
610     report_extra_t r = {
611         .report_id = REPORT_ID_CONSUMER,
612         .usage = data
613     };
614     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
615
616     /* Check if write ready for a polling interval around 10ms */
617     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
618     if (!Endpoint_IsReadWriteAllowed()) return;
619
620     Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
621     Endpoint_ClearIN();
622 #endif
623 }
624
625
626 /*******************************************************************************
627  * sendchar
628  ******************************************************************************/
629 int8_t sendchar(uint8_t c)
630 {
631     #ifdef LUFA_DEBUG_SUART
632     xmit(c);
633     #endif
634
635     #ifdef LUFA_DEBUG_UART
636     uart_putchar(c);
637     #endif
638
639     #ifdef CONSOLE_ENABLE
640     console_putc(c);
641     #endif
642
643     return 0;
644 }
645
646
647 /*******************************************************************************
648  * main
649  ******************************************************************************/
650 static void setup_mcu(void)
651 {
652     /* Disable watchdog if enabled by bootloader/fuses */
653     MCUSR &= ~(1 << WDRF);
654     wdt_disable();
655
656     /* Disable clock division */
657     clock_prescale_set(clock_div_1);
658 }
659
660 static void setup_usb(void)
661 {
662     // Leonardo needs. Without this USB device is not recognized.
663     USB_Disable();
664
665     USB_Init();
666
667     USB_Device_EnableSOFEvents();
668 }
669
670 int main(void)  __attribute__ ((weak));
671 int main(void)
672 {
673     setup_mcu();
674
675 #ifdef LUFA_DEBUG_SUART
676     SUART_OUT_DDR |= (1<<SUART_OUT_BIT);
677     SUART_OUT_PORT |= (1<<SUART_OUT_BIT);
678 #endif
679
680 #ifdef LUFA_DEBUG_UART
681     uart_init(115200);
682 #endif
683
684     // setup sendchar: DO NOT USE print functions before this line
685     print_set_sendchar(sendchar);
686     host_set_driver(&lufa_driver);
687
688     print("\n\nTMK:" STR(TMK_VERSION) "/LUFA\n\n");
689     hook_early_init();
690     keyboard_setup();
691     setup_usb();
692 #ifdef SLEEP_LED_ENABLE
693     sleep_led_init();
694 #endif
695
696     sei();
697
698     keyboard_init();
699
700 #ifndef NO_USB_STARTUP_WAIT_LOOP
701     /* wait for USB startup */
702     while (USB_DeviceState != DEVICE_STATE_Configured) {
703 #if defined(INTERRUPT_CONTROL_ENDPOINT)
704         ;
705 #else
706         USB_USBTask();
707 #endif
708         hook_usb_startup_wait_loop();
709     }
710     print("\nUSB configured.\n");
711 #endif
712
713     hook_late_init();
714
715     print("\nKeyboard start.\n");
716     while (1) {
717 #ifndef NO_USB_SUSPEND_LOOP
718         while (USB_DeviceState == DEVICE_STATE_Suspended) {
719             hook_usb_suspend_loop();
720         }
721 #endif
722
723         keyboard_task();
724
725 #ifdef CONSOLE_ENABLE
726         console_task();
727 #endif
728
729 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
730         USB_USBTask();
731 #endif
732     }
733 }
734
735
736 /* hooks */
737 __attribute__((weak))
738 void hook_early_init(void) {}
739
740 __attribute__((weak))
741 void hook_late_init(void) {}
742
743 static uint8_t _led_stats = 0;
744  __attribute__((weak))
745 void hook_usb_suspend_entry(void)
746 {
747     // Turn off LED to save power and keep its status to resotre it later.
748     // LED status will be updated by keyboard_task() in main loop hopefully.
749     _led_stats = keyboard_led_stats;
750     keyboard_led_stats = 0;
751
752     // Calling long task here can prevent USB state transition
753
754     matrix_clear();
755     clear_keyboard();
756 #ifdef SLEEP_LED_ENABLE
757     sleep_led_enable();
758 #endif
759 }
760
761 __attribute__((weak))
762 void hook_usb_suspend_loop(void)
763 {
764 #ifndef LUFA_DEBUG_UART
765     // This corrupts debug print when suspend
766     suspend_power_down();
767 #endif
768     if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
769         USB_Device_SendRemoteWakeup();
770     }
771 }
772
773 __attribute__((weak))
774 void hook_usb_wakeup(void)
775 {
776     suspend_wakeup_init();
777 #ifdef SLEEP_LED_ENABLE
778     sleep_led_disable();
779 #endif
780
781     // Restore LED status and update at keyboard_task() in main loop
782     keyboard_led_stats = _led_stats;
783
784     // Calling long task here can prevent USB state transition
785 }
786
787 __attribute__((weak))
788 void hook_usb_startup_wait_loop(void) {}