]> git.donarmstrong.com Git - tmk_firmware.git/blob - protocol/lufa/lufa.c
Make NKRO deafult when it is available
[tmk_firmware.git] / 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 "debug.h"
47 #ifdef SLEEP_LED_ENABLE
48 #include "sleep_led.h"
49 #endif
50 #include "suspend.h"
51
52 #include "descriptor.h"
53 #include "lufa.h"
54
55 uint8_t keyboard_idle = 0;
56 uint8_t keyboard_protocol = 1;
57 static uint8_t keyboard_led_stats = 0;
58
59 static report_keyboard_t keyboard_report_sent;
60
61
62 /* Host driver */
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 = {
69     keyboard_leds,
70     send_keyboard,
71     send_mouse,
72     send_system,
73     send_consumer
74 };
75
76
77 /*******************************************************************************
78  * Console
79  ******************************************************************************/
80 #ifdef CONSOLE_ENABLE
81 static void Console_Task(void)
82 {
83     /* Device must be connected and configured for the task to run */
84     if (USB_DeviceState != DEVICE_STATE_Configured)
85         return;
86
87     uint8_t ep = Endpoint_GetCurrentEndpoint();
88
89 #if 0
90     // TODO: impl receivechar()/recvchar()
91     Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
92
93     /* Check to see if a packet has been sent from the host */
94     if (Endpoint_IsOUTReceived())
95     {
96         /* Check to see if the packet contains data */
97         if (Endpoint_IsReadWriteAllowed())
98         {
99             /* Create a temporary buffer to hold the read in report from the host */
100             uint8_t ConsoleData[CONSOLE_EPSIZE];
101  
102             /* Read Console Report Data */
103             Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
104  
105             /* Process Console Report Data */
106             //ProcessConsoleHIDReport(ConsoleData);
107         }
108
109         /* Finalize the stream transfer to send the last packet */
110         Endpoint_ClearOUT();
111     }
112 #endif
113
114     /* IN packet */
115     Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
116     if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
117         Endpoint_SelectEndpoint(ep);
118         return;
119     }
120
121     // fill empty bank
122     while (Endpoint_IsReadWriteAllowed())
123         Endpoint_Write_8(0);
124
125     // flash senchar packet
126     if (Endpoint_IsINReady()) {
127         Endpoint_ClearIN();
128     }
129
130     Endpoint_SelectEndpoint(ep);
131 }
132 #else
133 static void Console_Task(void)
134 {
135 }
136 #endif
137
138
139 /*******************************************************************************
140  * USB Events
141  ******************************************************************************/
142 /*
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
148 */
149 void EVENT_USB_Device_Connect(void)
150 {
151 }
152
153 void EVENT_USB_Device_Disconnect(void)
154 {
155 }
156
157 void EVENT_USB_Device_Reset(void)
158 {
159 }
160
161 void EVENT_USB_Device_Suspend()
162 {
163 #ifdef SLEEP_LED_ENABLE
164     sleep_led_enable();
165 #endif
166 }
167
168 void EVENT_USB_Device_WakeUp()
169 {
170     suspend_wakeup_init();
171
172 #ifdef SLEEP_LED_ENABLE
173     sleep_led_disable();
174     // NOTE: converters may not accept this
175     led_set(host_keyboard_leds());
176 #endif
177 }
178
179 void EVENT_USB_Device_StartOfFrame(void)
180 {
181     Console_Task();
182 }
183
184 /** Event handler for the USB_ConfigurationChanged event.
185  * This is fired when the host sets the current configuration of the USB device after enumeration.
186  */
187 void EVENT_USB_Device_ConfigurationChanged(void)
188 {
189     bool ConfigSuccess = true;
190
191     /* Setup Keyboard HID Report Endpoints */
192     ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
193                                      KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
194
195 #ifdef MOUSE_ENABLE
196     /* Setup Mouse HID Report Endpoint */
197     ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
198                                      MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
199 #endif
200
201 #ifdef EXTRAKEY_ENABLE
202     /* Setup Extra HID Report Endpoint */
203     ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
204                                      EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
205 #endif
206
207 #ifdef CONSOLE_ENABLE
208     /* Setup Console HID Report Endpoints */
209     ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
210                                      CONSOLE_EPSIZE, ENDPOINT_BANK_DOUBLE);
211     ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
212                                      CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
213 #endif
214
215 #ifdef NKRO_ENABLE
216     /* Setup NKRO HID Report Endpoints */
217     ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
218                                      NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
219 #endif
220 }
221
222 /*
223 Appendix G: HID Request Support Requirements
224
225 The following table enumerates the requests that need to be supported by various types of HID class devices.
226
227 Device type     GetReport   SetReport   GetIdle     SetIdle     GetProtocol SetProtocol
228 ------------------------------------------------------------------------------------------
229 Boot Mouse      Required    Optional    Optional    Optional    Required    Required
230 Non-Boot Mouse  Required    Optional    Optional    Optional    Optional    Optional
231 Boot Keyboard   Required    Optional    Required    Required    Required    Required
232 Non-Boot Keybrd Required    Optional    Required    Required    Optional    Optional
233 Other Device    Required    Optional    Optional    Optional    Optional    Optional
234 */
235 /** Event handler for the USB_ControlRequest event.
236  *  This is fired before passing along unhandled control requests to the library for processing internally.
237  */
238 void EVENT_USB_Device_ControlRequest(void)
239 {
240     uint8_t* ReportData = NULL;
241     uint8_t  ReportSize = 0;
242
243     /* Handle HID Class specific requests */
244     switch (USB_ControlRequest.bRequest)
245     {
246         case HID_REQ_GetReport:
247             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
248             {
249                 Endpoint_ClearSETUP();
250
251                 // Interface
252                 switch (USB_ControlRequest.wIndex) {
253                 case KEYBOARD_INTERFACE:
254                     // TODO: test/check
255                     ReportData = (uint8_t*)&keyboard_report_sent;
256                     ReportSize = sizeof(keyboard_report_sent);
257                     break;
258                 }
259
260                 /* Write the report data to the control endpoint */
261                 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
262                 Endpoint_ClearOUT();
263             }
264
265             break;
266         case HID_REQ_SetReport:
267             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
268             {
269
270                 // Interface
271                 switch (USB_ControlRequest.wIndex) {
272                 case KEYBOARD_INTERFACE:
273                     Endpoint_ClearSETUP();
274
275                     while (!(Endpoint_IsOUTReceived())) {
276                         if (USB_DeviceState == DEVICE_STATE_Unattached)
277                           return;
278                     }
279                     keyboard_led_stats = Endpoint_Read_8();
280
281                     Endpoint_ClearOUT();
282                     Endpoint_ClearStatusStage();
283                     break;
284                 }
285
286             }
287
288             break;
289
290         case HID_REQ_GetProtocol:
291             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
292             {
293                 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
294                     Endpoint_ClearSETUP();
295                     while (!(Endpoint_IsINReady()));
296                     Endpoint_Write_8(keyboard_protocol);
297                     Endpoint_ClearIN();
298                     Endpoint_ClearStatusStage();
299                 }
300             }
301
302             break;
303         case HID_REQ_SetProtocol:
304             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
305             {
306                 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
307                     Endpoint_ClearSETUP();
308                     Endpoint_ClearStatusStage();
309
310                     keyboard_protocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
311                     clear_keyboard();
312                 }
313             }
314
315             break;
316         case HID_REQ_SetIdle:
317             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
318             {
319                 Endpoint_ClearSETUP();
320                 Endpoint_ClearStatusStage();
321
322                 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
323             }
324
325             break;
326         case HID_REQ_GetIdle:
327             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
328             {
329                 Endpoint_ClearSETUP();
330                 while (!(Endpoint_IsINReady()));
331                 Endpoint_Write_8(keyboard_idle);
332                 Endpoint_ClearIN();
333                 Endpoint_ClearStatusStage();
334             }
335
336             break;
337     }
338 }
339
340 /*******************************************************************************
341  * Host driver 
342  ******************************************************************************/
343 static uint8_t keyboard_leds(void)
344 {
345     return keyboard_led_stats;
346 }
347
348 static void send_keyboard(report_keyboard_t *report)
349 {
350     uint8_t timeout = 255;
351
352     if (USB_DeviceState != DEVICE_STATE_Configured)
353         return;
354
355     /* Select the Keyboard Report Endpoint */
356 #ifdef NKRO_ENABLE
357     if (keyboard_nkro && keyboard_protocol) {
358         /* Report protocol - NKRO */
359         Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
360
361         /* Check if write ready for a polling interval around 1ms */
362         while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
363         if (!Endpoint_IsReadWriteAllowed()) return;
364
365         /* Write Keyboard Report Data */
366         Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
367     }
368     else
369 #endif
370     {
371         /* Boot protocol */
372         Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
373
374         /* Check if write ready for a polling interval around 10ms */
375         while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
376         if (!Endpoint_IsReadWriteAllowed()) return;
377
378         /* Write Keyboard Report Data */
379         Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
380     }
381
382     /* Finalize the stream transfer to send the last packet */
383     Endpoint_ClearIN();
384
385     keyboard_report_sent = *report;
386 }
387
388 static void send_mouse(report_mouse_t *report)
389 {
390 #ifdef MOUSE_ENABLE
391     uint8_t timeout = 255;
392
393     if (USB_DeviceState != DEVICE_STATE_Configured)
394         return;
395
396     /* Select the Mouse Report Endpoint */
397     Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
398
399     /* Check if write ready for a polling interval around 10ms */
400     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
401     if (!Endpoint_IsReadWriteAllowed()) return;
402
403     /* Write Mouse Report Data */
404     Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
405
406     /* Finalize the stream transfer to send the last packet */
407     Endpoint_ClearIN();
408 #endif
409 }
410
411 static void send_system(uint16_t data)
412 {
413     uint8_t timeout = 255;
414
415     if (USB_DeviceState != DEVICE_STATE_Configured)
416         return;
417
418     report_extra_t r = {
419         .report_id = REPORT_ID_SYSTEM,
420         .usage = data
421     };
422     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
423
424     /* Check if write ready for a polling interval around 10ms */
425     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
426     if (!Endpoint_IsReadWriteAllowed()) return;
427
428     Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
429     Endpoint_ClearIN();
430 }
431
432 static void send_consumer(uint16_t data)
433 {
434     uint8_t timeout = 255;
435
436     if (USB_DeviceState != DEVICE_STATE_Configured)
437         return;
438
439     report_extra_t r = {
440         .report_id = REPORT_ID_CONSUMER,
441         .usage = data
442     };
443     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
444
445     /* Check if write ready for a polling interval around 10ms */
446     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
447     if (!Endpoint_IsReadWriteAllowed()) return;
448
449     Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
450     Endpoint_ClearIN();
451 }
452
453
454 /*******************************************************************************
455  * sendchar
456  ******************************************************************************/
457 #ifdef CONSOLE_ENABLE
458 #define SEND_TIMEOUT 5
459 int8_t sendchar(uint8_t c)
460 {
461     // Not wait once timeouted.
462     // Because sendchar() is called so many times, waiting each call causes big lag.
463     static bool timeouted = false;
464
465     if (USB_DeviceState != DEVICE_STATE_Configured)
466         return -1;
467
468     uint8_t ep = Endpoint_GetCurrentEndpoint();
469     Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
470     if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
471         Endpoint_SelectEndpoint(ep);
472         return -1;
473     }
474
475     if (timeouted && !Endpoint_IsReadWriteAllowed()) {
476         Endpoint_SelectEndpoint(ep);
477         return - 1;
478     }
479
480     timeouted = false;
481
482     uint8_t timeout = SEND_TIMEOUT;
483     uint16_t prevFN = USB_Device_GetFrameNumber();
484     while (!Endpoint_IsReadWriteAllowed()) {
485         switch (USB_DeviceState) {
486         case DEVICE_STATE_Unattached:
487         case DEVICE_STATE_Suspended:
488             return -1;
489         }
490         if (Endpoint_IsStalled()) {
491             Endpoint_SelectEndpoint(ep);
492             return -1;
493         }
494         if (prevFN != USB_Device_GetFrameNumber()) {
495             if (!(timeout--)) {
496                 timeouted = true;
497                 Endpoint_SelectEndpoint(ep);
498                 return -1;
499             }
500             prevFN = USB_Device_GetFrameNumber();
501         }
502     }
503
504     Endpoint_Write_8(c);
505
506     // send when bank is full
507     if (!Endpoint_IsReadWriteAllowed())
508         Endpoint_ClearIN();
509
510     Endpoint_SelectEndpoint(ep);
511     return 0;
512 }
513 #else
514 int8_t sendchar(uint8_t c)
515 {
516     return 0;
517 }
518 #endif
519
520
521 /*******************************************************************************
522  * main
523  ******************************************************************************/
524 static void SetupHardware(void)
525 {
526     /* Disable watchdog if enabled by bootloader/fuses */
527     MCUSR &= ~(1 << WDRF);
528     wdt_disable();
529
530     /* Disable clock division */
531     clock_prescale_set(clock_div_1);
532
533     // Leonardo needs. Without this USB device is not recognized.
534     USB_Disable();
535
536     USB_Init();
537
538     // for Console_Task
539     USB_Device_EnableSOFEvents();
540     print_set_sendchar(sendchar);
541 }
542
543 int main(void)  __attribute__ ((weak));
544 int main(void)
545 {
546     SetupHardware();
547     sei();
548
549     /* wait for USB startup & debug output */
550     while (USB_DeviceState != DEVICE_STATE_Configured) {
551 #if defined(INTERRUPT_CONTROL_ENDPOINT)
552         ;
553 #else
554         USB_USBTask();
555 #endif
556     }
557     print("USB configured.\n");
558
559     /* init modules */
560     keyboard_init();
561     host_set_driver(&lufa_driver);
562 #ifdef SLEEP_LED_ENABLE
563     sleep_led_init();
564 #endif
565
566     print("Keyboard start.\n");
567     while (1) {
568         while (USB_DeviceState == DEVICE_STATE_Suspended) {
569             suspend_power_down();
570             if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
571                     USB_Device_SendRemoteWakeup();
572             }
573         }
574
575         keyboard_task();
576
577 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
578         USB_USBTask();
579 #endif
580     }
581 }