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"
47 #ifdef SLEEP_LED_ENABLE
48 #include "sleep_led.h"
52 #include "descriptor.h"
55 uint8_t keyboard_idle = 0;
56 uint8_t keyboard_protocol = 1;
57 static uint8_t keyboard_led_stats = 0;
59 static report_keyboard_t keyboard_report_sent;
63 static uint8_t keyboard_leds(void);
64 static void send_keyboard(report_keyboard_t *report);
65 static void send_mouse(report_mouse_t *report);
66 static void send_system(uint16_t data);
67 static void send_consumer(uint16_t data);
68 host_driver_t lufa_driver = {
77 /*******************************************************************************
79 ******************************************************************************/
81 static void Console_Task(void)
83 /* Device must be connected and configured for the task to run */
84 if (USB_DeviceState != DEVICE_STATE_Configured)
87 uint8_t ep = Endpoint_GetCurrentEndpoint();
90 // TODO: impl receivechar()/recvchar()
91 Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
93 /* Check to see if a packet has been sent from the host */
94 if (Endpoint_IsOUTReceived())
96 /* Check to see if the packet contains data */
97 if (Endpoint_IsReadWriteAllowed())
99 /* Create a temporary buffer to hold the read in report from the host */
100 uint8_t ConsoleData[CONSOLE_EPSIZE];
102 /* Read Console Report Data */
103 Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
105 /* Process Console Report Data */
106 //ProcessConsoleHIDReport(ConsoleData);
109 /* Finalize the stream transfer to send the last packet */
115 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
116 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
117 Endpoint_SelectEndpoint(ep);
122 while (Endpoint_IsReadWriteAllowed())
125 // flash senchar packet
126 if (Endpoint_IsINReady()) {
130 Endpoint_SelectEndpoint(ep);
133 static void Console_Task(void)
139 /*******************************************************************************
141 ******************************************************************************/
143 * Event Order of Plug in:
144 * 0) EVENT_USB_Device_Connect
145 * 1) EVENT_USB_Device_Suspend
146 * 2) EVENT_USB_Device_Reset
147 * 3) EVENT_USB_Device_Wake
149 void EVENT_USB_Device_Connect(void)
152 /* For battery powered device */
153 if (!USB_IsInitialized) {
155 USB_Device_EnableSOFEvents();
159 void EVENT_USB_Device_Disconnect(void)
162 /* For battery powered device */
163 /* TODO: This doesn't work. After several plug in/outs can not be enumerated.
164 if (USB_IsInitialized) {
165 USB_Disable(); // Disable all interrupts
166 USB_Controller_Enable();
167 USB_INT_Enable(USB_INT_VBUSTI);
172 void EVENT_USB_Device_Reset(void)
177 void EVENT_USB_Device_Suspend()
180 #ifdef SLEEP_LED_ENABLE
185 void EVENT_USB_Device_WakeUp()
188 suspend_wakeup_init();
190 #ifdef SLEEP_LED_ENABLE
192 // NOTE: converters may not accept this
193 led_set(host_keyboard_leds());
197 void EVENT_USB_Device_StartOfFrame(void)
202 /** Event handler for the USB_ConfigurationChanged event.
203 * This is fired when the host sets the current configuration of the USB device after enumeration.
205 void EVENT_USB_Device_ConfigurationChanged(void)
207 bool ConfigSuccess = true;
209 /* Setup Keyboard HID Report Endpoints */
210 ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
211 KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
214 /* Setup Mouse HID Report Endpoint */
215 ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
216 MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
219 #ifdef EXTRAKEY_ENABLE
220 /* Setup Extra HID Report Endpoint */
221 ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
222 EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
225 #ifdef CONSOLE_ENABLE
226 /* Setup Console HID Report Endpoints */
227 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
228 CONSOLE_EPSIZE, ENDPOINT_BANK_DOUBLE);
230 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
231 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
236 /* Setup NKRO HID Report Endpoints */
237 ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
238 NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
243 Appendix G: HID Request Support Requirements
245 The following table enumerates the requests that need to be supported by various types of HID class devices.
247 Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
248 ------------------------------------------------------------------------------------------
249 Boot Mouse Required Optional Optional Optional Required Required
250 Non-Boot Mouse Required Optional Optional Optional Optional Optional
251 Boot Keyboard Required Optional Required Required Required Required
252 Non-Boot Keybrd Required Optional Required Required Optional Optional
253 Other Device Required Optional Optional Optional Optional Optional
255 /** Event handler for the USB_ControlRequest event.
256 * This is fired before passing along unhandled control requests to the library for processing internally.
258 void EVENT_USB_Device_ControlRequest(void)
260 uint8_t* ReportData = NULL;
261 uint8_t ReportSize = 0;
263 /* Handle HID Class specific requests */
264 switch (USB_ControlRequest.bRequest)
266 case HID_REQ_GetReport:
267 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
269 Endpoint_ClearSETUP();
272 switch (USB_ControlRequest.wIndex) {
273 case KEYBOARD_INTERFACE:
275 ReportData = (uint8_t*)&keyboard_report_sent;
276 ReportSize = sizeof(keyboard_report_sent);
280 /* Write the report data to the control endpoint */
281 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
286 case HID_REQ_SetReport:
287 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
291 switch (USB_ControlRequest.wIndex) {
292 case KEYBOARD_INTERFACE:
296 Endpoint_ClearSETUP();
298 while (!(Endpoint_IsOUTReceived())) {
299 if (USB_DeviceState == DEVICE_STATE_Unattached)
302 keyboard_led_stats = Endpoint_Read_8();
305 Endpoint_ClearStatusStage();
313 case HID_REQ_GetProtocol:
314 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
316 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
317 Endpoint_ClearSETUP();
318 while (!(Endpoint_IsINReady()));
319 Endpoint_Write_8(keyboard_protocol);
321 Endpoint_ClearStatusStage();
326 case HID_REQ_SetProtocol:
327 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
329 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
330 Endpoint_ClearSETUP();
331 Endpoint_ClearStatusStage();
333 keyboard_protocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
335 keyboard_nkro = !!keyboard_protocol;
342 case HID_REQ_SetIdle:
343 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
345 Endpoint_ClearSETUP();
346 Endpoint_ClearStatusStage();
348 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
352 case HID_REQ_GetIdle:
353 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
355 Endpoint_ClearSETUP();
356 while (!(Endpoint_IsINReady()));
357 Endpoint_Write_8(keyboard_idle);
359 Endpoint_ClearStatusStage();
366 /*******************************************************************************
368 ******************************************************************************/
369 static uint8_t keyboard_leds(void)
371 return keyboard_led_stats;
374 static void send_keyboard(report_keyboard_t *report)
376 uint8_t timeout = 255;
378 if (USB_DeviceState != DEVICE_STATE_Configured)
381 /* Select the Keyboard Report Endpoint */
384 /* Report protocol - NKRO */
385 Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
387 /* Check if write ready for a polling interval around 1ms */
388 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
389 if (!Endpoint_IsReadWriteAllowed()) return;
391 /* Write Keyboard Report Data */
392 Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
398 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
400 /* Check if write ready for a polling interval around 10ms */
401 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
402 if (!Endpoint_IsReadWriteAllowed()) return;
404 /* Write Keyboard Report Data */
405 Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
408 /* Finalize the stream transfer to send the last packet */
411 keyboard_report_sent = *report;
414 static void send_mouse(report_mouse_t *report)
417 uint8_t timeout = 255;
419 if (USB_DeviceState != DEVICE_STATE_Configured)
422 /* Select the Mouse Report Endpoint */
423 Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
425 /* Check if write ready for a polling interval around 10ms */
426 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
427 if (!Endpoint_IsReadWriteAllowed()) return;
429 /* Write Mouse Report Data */
430 Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
432 /* Finalize the stream transfer to send the last packet */
437 static void send_system(uint16_t data)
439 uint8_t timeout = 255;
441 if (USB_DeviceState != DEVICE_STATE_Configured)
445 .report_id = REPORT_ID_SYSTEM,
448 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
450 /* Check if write ready for a polling interval around 10ms */
451 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
452 if (!Endpoint_IsReadWriteAllowed()) return;
454 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
458 static void send_consumer(uint16_t data)
460 uint8_t timeout = 255;
462 if (USB_DeviceState != DEVICE_STATE_Configured)
466 .report_id = REPORT_ID_CONSUMER,
469 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
471 /* Check if write ready for a polling interval around 10ms */
472 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
473 if (!Endpoint_IsReadWriteAllowed()) return;
475 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
480 /*******************************************************************************
482 ******************************************************************************/
483 #ifdef CONSOLE_ENABLE
484 #define SEND_TIMEOUT 5
485 int8_t sendchar(uint8_t c)
487 // Not wait once timeouted.
488 // Because sendchar() is called so many times, waiting each call causes big lag.
489 static bool timeouted = false;
491 if (USB_DeviceState != DEVICE_STATE_Configured)
494 uint8_t ep = Endpoint_GetCurrentEndpoint();
495 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
496 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
500 if (timeouted && !Endpoint_IsReadWriteAllowed()) {
506 uint8_t timeout = SEND_TIMEOUT;
507 while (!Endpoint_IsReadWriteAllowed()) {
508 if (USB_DeviceState != DEVICE_STATE_Configured) {
511 if (Endpoint_IsStalled()) {
523 // send when bank is full
524 if (!Endpoint_IsReadWriteAllowed())
527 Endpoint_SelectEndpoint(ep);
530 Endpoint_SelectEndpoint(ep);
534 int8_t sendchar(uint8_t c)
541 /*******************************************************************************
543 ******************************************************************************/
544 static void SetupHardware(void)
546 /* Disable watchdog if enabled by bootloader/fuses */
547 MCUSR &= ~(1 << WDRF);
550 /* Disable clock division */
551 clock_prescale_set(clock_div_1);
553 // Leonardo needs. Without this USB device is not recognized.
559 USB_Device_EnableSOFEvents();
560 print_set_sendchar(sendchar);
563 int main(void) __attribute__ ((weak));
569 /* wait for USB startup & debug output */
570 while (USB_DeviceState != DEVICE_STATE_Configured) {
571 #if defined(INTERRUPT_CONTROL_ENDPOINT)
577 print("USB configured.\n");
581 host_set_driver(&lufa_driver);
582 #ifdef SLEEP_LED_ENABLE
586 print("Keyboard start.\n");
588 while (USB_DeviceState == DEVICE_STATE_Suspended) {
590 suspend_power_down();
591 if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
592 USB_Device_SendRemoteWakeup();
598 #if !defined(INTERRUPT_CONTROL_ENDPOINT)