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
10 Copyright (C) Dean Camera, 2012.
12 dean [at] fourwalledcubicle [dot] com
17 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
18 Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com)
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.
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
41 #include "host_driver.h"
48 #ifdef SLEEP_LED_ENABLE
49 #include "sleep_led.h"
55 #ifdef TMK_LUFA_DEBUG_SUART
56 #include "avr/suart.h"
59 #ifdef TMK_LUFA_DEBUG_UART
64 #include "descriptor.h"
68 //#define TMK_LUFA_DEBUG
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;
76 static report_keyboard_t keyboard_report_sent;
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 = {
94 /*******************************************************************************
96 ******************************************************************************/
98 #define SENDBUF_SIZE 256
99 static uint8_t sbuf[SENDBUF_SIZE];
100 static ringbuf_t sendbuf = {
104 .size_mask = SENDBUF_SIZE - 1
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)
112 static bool hid_listen_ready = false;
113 if (!hid_listen_ready) {
114 if (timer_read32() < 2500)
116 hid_listen_ready = true;
121 static bool console_putc(uint8_t c)
123 // return immediately if called while interrupt
124 if (!(SREG & (1<<SREG_I)))
127 if (USB_DeviceState != DEVICE_STATE_Configured && !ringbuf_is_full(&sendbuf))
130 if (!console_is_ready() && !ringbuf_is_full(&sendbuf))
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.
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();
147 uint8_t ep = Endpoint_GetCurrentEndpoint();
148 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
151 if (Endpoint_IsStalled() || !Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
152 goto EXIT_RESTORE_EP;
155 // write from buffer to endpoint bank
156 while (!ringbuf_is_empty(&sendbuf) && Endpoint_IsReadWriteAllowed()) {
157 Endpoint_Write_8(ringbuf_get(&sendbuf));
159 // clear bank when it is full
160 if (!Endpoint_IsReadWriteAllowed() && Endpoint_IsINReady()) {
162 timeout = CONSOLE_TIMOUT; // re-enable retry only when host can receive
166 // write c to bank directly if there is no others in buffer
167 if (ringbuf_is_empty(&sendbuf) && Endpoint_IsReadWriteAllowed()) {
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()) {
179 timeout = CONSOLE_TIMOUT; // re-enable retry only when host can receive
183 Endpoint_SelectEndpoint(ep);
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.
191 if (ringbuf_is_full(&sendbuf) && timeout) {
192 uint16_t curr = timer_read();
201 Endpoint_SelectEndpoint(ep);
203 return ringbuf_put(&sendbuf, c);
206 static void console_flush(void)
208 if (!console_is_ready())
211 if (USB_DeviceState != DEVICE_STATE_Configured)
214 uint8_t ep = Endpoint_GetCurrentEndpoint();
216 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
217 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
218 Endpoint_SelectEndpoint(ep);
222 // write from buffer to endpoint bank
223 while (!ringbuf_is_empty(&sendbuf) && Endpoint_IsReadWriteAllowed()) {
224 Endpoint_Write_8(ringbuf_get(&sendbuf));
226 // clear bank when it is full
227 if (!Endpoint_IsReadWriteAllowed() && Endpoint_IsINReady()) {
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()) {
241 Endpoint_SelectEndpoint(ep);
244 static void console_task(void)
246 static uint16_t fn = 0;
247 if (fn == USB_Device_GetFrameNumber()) {
250 fn = USB_Device_GetFrameNumber();
256 /*******************************************************************************
258 ******************************************************************************/
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
266 void EVENT_USB_Device_Connect(void)
268 #ifdef TMK_LUFA_DEBUG
271 /* For battery powered device */
272 if (!USB_IsInitialized) {
275 USB_Device_EnableSOFEvents();
279 void EVENT_USB_Device_Disconnect(void)
281 #ifdef TMK_LUFA_DEBUG
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);
295 void EVENT_USB_Device_Reset(void)
297 #ifdef TMK_LUFA_DEBUG
302 void EVENT_USB_Device_Suspend()
304 #ifdef TMK_LUFA_DEBUG
307 hook_usb_suspend_entry();
310 void EVENT_USB_Device_WakeUp()
312 #ifdef TMK_LUFA_DEBUG
319 void EVENT_USB_Device_StartOfFrame(void)
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.
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.
329 void EVENT_USB_Device_ConfigurationChanged(void)
331 #ifdef TMK_LUFA_DEBUG
334 bool ConfigSuccess = true;
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);
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);
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);
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);
357 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
358 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
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);
370 Appendix G: HID Request Support Requirements
372 The following table enumerates the requests that need to be supported by various types of HID class devices.
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
382 /** Event handler for the USB_ControlRequest event.
383 * This is fired before passing along unhandled control requests to the library for processing internally.
385 void EVENT_USB_Device_ControlRequest(void)
387 uint8_t* ReportData = NULL;
388 uint8_t ReportSize = 0;
390 /* Handle HID Class specific requests */
391 switch (USB_ControlRequest.bRequest)
393 case HID_REQ_GetReport:
394 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
396 Endpoint_ClearSETUP();
399 switch (USB_ControlRequest.wIndex) {
400 case KEYBOARD_INTERFACE:
402 ReportData = (uint8_t*)&keyboard_report_sent;
403 ReportSize = sizeof(keyboard_report_sent);
407 /* Write the report data to the control endpoint */
408 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
410 #ifdef TMK_LUFA_DEBUG
411 xprintf("[r%d]", USB_ControlRequest.wIndex);
416 case HID_REQ_SetReport:
417 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
421 switch (USB_ControlRequest.wIndex) {
422 case KEYBOARD_INTERFACE:
426 Endpoint_ClearSETUP();
428 while (!(Endpoint_IsOUTReceived())) {
429 if (USB_DeviceState == DEVICE_STATE_Unattached)
432 keyboard_led_stats = Endpoint_Read_8();
435 Endpoint_ClearStatusStage();
436 #ifdef TMK_LUFA_DEBUG
437 xprintf("[L%d]", USB_ControlRequest.wIndex);
446 case HID_REQ_GetProtocol:
447 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
449 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
450 Endpoint_ClearSETUP();
451 while (!(Endpoint_IsINReady()));
452 Endpoint_Write_8(keyboard_protocol);
454 Endpoint_ClearStatusStage();
455 #ifdef TMK_LUFA_DEBUG
462 case HID_REQ_SetProtocol:
463 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
465 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
466 Endpoint_ClearSETUP();
467 Endpoint_ClearStatusStage();
469 keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
471 #ifdef TMK_LUFA_DEBUG
478 case HID_REQ_SetIdle:
479 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
481 Endpoint_ClearSETUP();
482 Endpoint_ClearStatusStage();
484 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
485 #ifdef TMK_LUFA_DEBUG
486 xprintf("[I%d]%d", USB_ControlRequest.wIndex, (USB_ControlRequest.wValue & 0xFF00) >> 8);
491 case HID_REQ_GetIdle:
492 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
494 Endpoint_ClearSETUP();
495 while (!(Endpoint_IsINReady()));
496 Endpoint_Write_8(keyboard_idle);
498 Endpoint_ClearStatusStage();
499 #ifdef TMK_LUFA_DEBUG
508 /*******************************************************************************
510 ******************************************************************************/
511 static uint8_t keyboard_leds(void)
513 return keyboard_led_stats;
516 static void send_keyboard(report_keyboard_t *report)
518 uint8_t timeout = 128;
520 if (USB_DeviceState != DEVICE_STATE_Configured)
523 /* Select the Keyboard Report Endpoint */
525 if (keyboard_protocol && keyboard_nkro) {
526 /* Report protocol - NKRO */
527 Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
529 /* Check if write ready for a polling interval around 1ms */
530 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(8);
531 if (!Endpoint_IsReadWriteAllowed()) return;
533 /* Write Keyboard Report Data */
534 Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
540 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
542 /* Check if write ready for a polling interval around 10ms */
543 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(80);
544 if (!Endpoint_IsReadWriteAllowed()) return;
546 /* Write Keyboard Report Data */
547 Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
550 /* Finalize the stream transfer to send the last packet */
553 keyboard_report_sent = *report;
556 static void send_mouse(report_mouse_t *report)
559 uint8_t timeout = 255;
561 if (USB_DeviceState != DEVICE_STATE_Configured)
564 /* Select the Mouse Report Endpoint */
565 Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
567 /* Check if write ready for a polling interval around 10ms */
568 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
569 if (!Endpoint_IsReadWriteAllowed()) return;
571 /* Write Mouse Report Data */
572 Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
574 /* Finalize the stream transfer to send the last packet */
579 static void send_system(uint16_t data)
581 #ifdef EXTRAKEY_ENABLE
582 uint8_t timeout = 255;
584 if (USB_DeviceState != DEVICE_STATE_Configured)
588 .report_id = REPORT_ID_SYSTEM,
589 .usage = data - SYSTEM_POWER_DOWN + 1
591 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
593 /* Check if write ready for a polling interval around 10ms */
594 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
595 if (!Endpoint_IsReadWriteAllowed()) return;
597 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
602 static void send_consumer(uint16_t data)
604 #ifdef EXTRAKEY_ENABLE
605 uint8_t timeout = 255;
607 if (USB_DeviceState != DEVICE_STATE_Configured)
611 .report_id = REPORT_ID_CONSUMER,
614 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
616 /* Check if write ready for a polling interval around 10ms */
617 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
618 if (!Endpoint_IsReadWriteAllowed()) return;
620 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
626 /*******************************************************************************
628 ******************************************************************************/
629 int8_t sendchar(uint8_t c)
631 #ifdef TMK_LUFA_DEBUG_SUART
635 #ifdef TMK_LUFA_DEBUG_UART
639 #ifdef CONSOLE_ENABLE
647 /*******************************************************************************
649 ******************************************************************************/
650 static void setup_mcu(void)
652 /* Disable watchdog if enabled by bootloader/fuses */
653 MCUSR &= ~(1 << WDRF);
656 /* Disable clock division */
657 clock_prescale_set(clock_div_1);
660 static void setup_usb(void)
662 // Leonardo needs. Without this USB device is not recognized.
667 USB_Device_EnableSOFEvents();
670 int main(void) __attribute__ ((weak));
675 #ifdef TMK_LUFA_DEBUG_SUART
676 SUART_OUT_DDR |= (1<<SUART_OUT_BIT);
677 SUART_OUT_PORT |= (1<<SUART_OUT_BIT);
680 #ifdef TMK_LUFA_DEBUG_UART
684 // setup sendchar: DO NOT USE print functions before this line
685 print_set_sendchar(sendchar);
686 host_set_driver(&lufa_driver);
688 print("\n\nTMK:" STR(TMK_VERSION) "/LUFA\n\n");
692 #ifdef SLEEP_LED_ENABLE
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)
708 hook_usb_startup_wait_loop();
710 print("\nUSB configured.\n");
715 print("\nKeyboard start.\n");
717 #ifndef NO_USB_SUSPEND_LOOP
718 while (USB_DeviceState == DEVICE_STATE_Suspended) {
719 hook_usb_suspend_loop();
725 #ifdef CONSOLE_ENABLE
729 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
737 __attribute__((weak))
738 void hook_early_init(void) {}
740 __attribute__((weak))
741 void hook_late_init(void) {}
743 static uint8_t _led_stats = 0;
744 __attribute__((weak))
745 void hook_usb_suspend_entry(void)
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;
752 // Calling long task here can prevent USB state transition
756 #ifdef SLEEP_LED_ENABLE
761 __attribute__((weak))
762 void hook_usb_suspend_loop(void)
764 #ifndef TMK_LUFA_DEBUG_UART
765 // This corrupts debug print when suspend
766 suspend_power_down();
768 if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
769 USB_Device_SendRemoteWakeup();
773 __attribute__((weak))
774 void hook_usb_wakeup(void)
776 suspend_wakeup_init();
777 #ifdef SLEEP_LED_ENABLE
781 // Restore LED status and update at keyboard_task() in main loop
782 keyboard_led_stats = _led_stats;
784 // Calling long task here can prevent USB state transition
787 __attribute__((weak))
788 void hook_usb_startup_wait_loop(void) {}