]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/lufa/lufa.c
Merge commit 'a074364c3731d66b56d988c8a6c960a83ea0e0a1' as 'tmk_core'
[qmk_firmware.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 "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     print("[C]");
152     /* For battery powered device */
153     if (!USB_IsInitialized) {
154         USB_Disable();
155         USB_Init();
156         USB_Device_EnableSOFEvents();
157     }
158 }
159
160 void EVENT_USB_Device_Disconnect(void)
161 {
162     print("[D]");
163     /* For battery powered device */
164     USB_IsInitialized = false;
165 /* TODO: This doesn't work. After several plug in/outs can not be enumerated. 
166     if (USB_IsInitialized) {
167         USB_Disable();  // Disable all interrupts
168         USB_Controller_Enable();
169         USB_INT_Enable(USB_INT_VBUSTI);
170     }
171 */
172 }
173
174 void EVENT_USB_Device_Reset(void)
175 {
176     print("[R]");
177 }
178
179 void EVENT_USB_Device_Suspend()
180 {
181     print("[S]");
182     matrix_power_down();
183 #ifdef SLEEP_LED_ENABLE
184     sleep_led_enable();
185 #endif
186 }
187
188 void EVENT_USB_Device_WakeUp()
189 {
190     print("[W]");
191     suspend_wakeup_init();
192
193 #ifdef SLEEP_LED_ENABLE
194     sleep_led_disable();
195     // NOTE: converters may not accept this
196     led_set(host_keyboard_leds());
197 #endif
198 }
199
200 void EVENT_USB_Device_StartOfFrame(void)
201 {
202     Console_Task();
203 }
204
205 /** Event handler for the USB_ConfigurationChanged event.
206  * This is fired when the host sets the current configuration of the USB device after enumeration.
207  */
208 void EVENT_USB_Device_ConfigurationChanged(void)
209 {
210     bool ConfigSuccess = true;
211
212     /* Setup Keyboard HID Report Endpoints */
213     ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
214                                      KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
215
216 #ifdef MOUSE_ENABLE
217     /* Setup Mouse HID Report Endpoint */
218     ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
219                                      MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
220 #endif
221
222 #ifdef EXTRAKEY_ENABLE
223     /* Setup Extra HID Report Endpoint */
224     ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
225                                      EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
226 #endif
227
228 #ifdef CONSOLE_ENABLE
229     /* Setup Console HID Report Endpoints */
230     ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
231                                      CONSOLE_EPSIZE, ENDPOINT_BANK_DOUBLE);
232 #if 0
233     ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
234                                      CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
235 #endif
236 #endif
237
238 #ifdef NKRO_ENABLE
239     /* Setup NKRO HID Report Endpoints */
240     ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
241                                      NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
242 #endif
243 }
244
245 /*
246 Appendix G: HID Request Support Requirements
247
248 The following table enumerates the requests that need to be supported by various types of HID class devices.
249
250 Device type     GetReport   SetReport   GetIdle     SetIdle     GetProtocol SetProtocol
251 ------------------------------------------------------------------------------------------
252 Boot Mouse      Required    Optional    Optional    Optional    Required    Required
253 Non-Boot Mouse  Required    Optional    Optional    Optional    Optional    Optional
254 Boot Keyboard   Required    Optional    Required    Required    Required    Required
255 Non-Boot Keybrd Required    Optional    Required    Required    Optional    Optional
256 Other Device    Required    Optional    Optional    Optional    Optional    Optional
257 */
258 /** Event handler for the USB_ControlRequest event.
259  *  This is fired before passing along unhandled control requests to the library for processing internally.
260  */
261 void EVENT_USB_Device_ControlRequest(void)
262 {
263     uint8_t* ReportData = NULL;
264     uint8_t  ReportSize = 0;
265
266     /* Handle HID Class specific requests */
267     switch (USB_ControlRequest.bRequest)
268     {
269         case HID_REQ_GetReport:
270             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
271             {
272                 Endpoint_ClearSETUP();
273
274                 // Interface
275                 switch (USB_ControlRequest.wIndex) {
276                 case KEYBOARD_INTERFACE:
277                     // TODO: test/check
278                     ReportData = (uint8_t*)&keyboard_report_sent;
279                     ReportSize = sizeof(keyboard_report_sent);
280                     break;
281                 }
282
283                 /* Write the report data to the control endpoint */
284                 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
285                 Endpoint_ClearOUT();
286             }
287
288             break;
289         case HID_REQ_SetReport:
290             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
291             {
292
293                 // Interface
294                 switch (USB_ControlRequest.wIndex) {
295                 case KEYBOARD_INTERFACE:
296 #ifdef NKRO_ENABLE
297                 case NKRO_INTERFACE:
298 #endif
299                     Endpoint_ClearSETUP();
300
301                     while (!(Endpoint_IsOUTReceived())) {
302                         if (USB_DeviceState == DEVICE_STATE_Unattached)
303                           return;
304                     }
305                     keyboard_led_stats = Endpoint_Read_8();
306
307                     Endpoint_ClearOUT();
308                     Endpoint_ClearStatusStage();
309                     break;
310                 }
311
312             }
313
314             break;
315
316         case HID_REQ_GetProtocol:
317             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
318             {
319                 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
320                     Endpoint_ClearSETUP();
321                     while (!(Endpoint_IsINReady()));
322                     Endpoint_Write_8(keyboard_protocol);
323                     Endpoint_ClearIN();
324                     Endpoint_ClearStatusStage();
325                 }
326             }
327
328             break;
329         case HID_REQ_SetProtocol:
330             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
331             {
332                 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
333                     Endpoint_ClearSETUP();
334                     Endpoint_ClearStatusStage();
335
336                     keyboard_protocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
337 #ifdef NKRO_ENABLE
338                     keyboard_nkro = !!keyboard_protocol;
339 #endif
340                     clear_keyboard();
341                 }
342             }
343
344             break;
345         case HID_REQ_SetIdle:
346             if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
347             {
348                 Endpoint_ClearSETUP();
349                 Endpoint_ClearStatusStage();
350
351                 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
352             }
353
354             break;
355         case HID_REQ_GetIdle:
356             if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
357             {
358                 Endpoint_ClearSETUP();
359                 while (!(Endpoint_IsINReady()));
360                 Endpoint_Write_8(keyboard_idle);
361                 Endpoint_ClearIN();
362                 Endpoint_ClearStatusStage();
363             }
364
365             break;
366     }
367 }
368
369 /*******************************************************************************
370  * Host driver 
371  ******************************************************************************/
372 static uint8_t keyboard_leds(void)
373 {
374     return keyboard_led_stats;
375 }
376
377 static void send_keyboard(report_keyboard_t *report)
378 {
379     uint8_t timeout = 255;
380
381     if (USB_DeviceState != DEVICE_STATE_Configured)
382         return;
383
384     /* Select the Keyboard Report Endpoint */
385 #ifdef NKRO_ENABLE
386     if (keyboard_nkro) {
387         /* Report protocol - NKRO */
388         Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
389
390         /* Check if write ready for a polling interval around 1ms */
391         while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
392         if (!Endpoint_IsReadWriteAllowed()) return;
393
394         /* Write Keyboard Report Data */
395         Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
396     }
397     else
398 #endif
399     {
400         /* Boot protocol */
401         Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
402
403         /* Check if write ready for a polling interval around 10ms */
404         while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
405         if (!Endpoint_IsReadWriteAllowed()) return;
406
407         /* Write Keyboard Report Data */
408         Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
409     }
410
411     /* Finalize the stream transfer to send the last packet */
412     Endpoint_ClearIN();
413
414     keyboard_report_sent = *report;
415 }
416
417 static void send_mouse(report_mouse_t *report)
418 {
419 #ifdef MOUSE_ENABLE
420     uint8_t timeout = 255;
421
422     if (USB_DeviceState != DEVICE_STATE_Configured)
423         return;
424
425     /* Select the Mouse Report Endpoint */
426     Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
427
428     /* Check if write ready for a polling interval around 10ms */
429     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
430     if (!Endpoint_IsReadWriteAllowed()) return;
431
432     /* Write Mouse Report Data */
433     Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
434
435     /* Finalize the stream transfer to send the last packet */
436     Endpoint_ClearIN();
437 #endif
438 }
439
440 static void send_system(uint16_t data)
441 {
442     uint8_t timeout = 255;
443
444     if (USB_DeviceState != DEVICE_STATE_Configured)
445         return;
446
447     report_extra_t r = {
448         .report_id = REPORT_ID_SYSTEM,
449         .usage = data
450     };
451     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
452
453     /* Check if write ready for a polling interval around 10ms */
454     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
455     if (!Endpoint_IsReadWriteAllowed()) return;
456
457     Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
458     Endpoint_ClearIN();
459 }
460
461 static void send_consumer(uint16_t data)
462 {
463     uint8_t timeout = 255;
464
465     if (USB_DeviceState != DEVICE_STATE_Configured)
466         return;
467
468     report_extra_t r = {
469         .report_id = REPORT_ID_CONSUMER,
470         .usage = data
471     };
472     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
473
474     /* Check if write ready for a polling interval around 10ms */
475     while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
476     if (!Endpoint_IsReadWriteAllowed()) return;
477
478     Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
479     Endpoint_ClearIN();
480 }
481
482
483 /*******************************************************************************
484  * sendchar
485  ******************************************************************************/
486 #ifdef CONSOLE_ENABLE
487 #define SEND_TIMEOUT 5
488 int8_t sendchar(uint8_t c)
489 {
490     // Not wait once timeouted.
491     // Because sendchar() is called so many times, waiting each call causes big lag.
492     static bool timeouted = false;
493
494     if (USB_DeviceState != DEVICE_STATE_Configured)
495         return -1;
496
497     uint8_t ep = Endpoint_GetCurrentEndpoint();
498     Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
499     if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
500         goto ERROR_EXIT;
501     }
502
503     if (timeouted && !Endpoint_IsReadWriteAllowed()) {
504         goto ERROR_EXIT;
505     }
506
507     timeouted = false;
508
509     uint8_t timeout = SEND_TIMEOUT;
510     while (!Endpoint_IsReadWriteAllowed()) {
511         if (USB_DeviceState != DEVICE_STATE_Configured) {
512             goto ERROR_EXIT;
513         }
514         if (Endpoint_IsStalled()) {
515             goto ERROR_EXIT;
516         }
517         if (!(timeout--)) {
518             timeouted = true;
519             goto ERROR_EXIT;
520         }
521         _delay_ms(1);
522     }
523
524     Endpoint_Write_8(c);
525
526     // send when bank is full
527     if (!Endpoint_IsReadWriteAllowed())
528         Endpoint_ClearIN();
529
530     Endpoint_SelectEndpoint(ep);
531     return 0;
532 ERROR_EXIT:
533     Endpoint_SelectEndpoint(ep);
534     return -1;
535 }
536 #else
537 int8_t sendchar(uint8_t c)
538 {
539     return 0;
540 }
541 #endif
542
543
544 /*******************************************************************************
545  * main
546  ******************************************************************************/
547 static void SetupHardware(void)
548 {
549     /* Disable watchdog if enabled by bootloader/fuses */
550     MCUSR &= ~(1 << WDRF);
551     wdt_disable();
552
553     /* Disable clock division */
554     clock_prescale_set(clock_div_1);
555
556     // Leonardo needs. Without this USB device is not recognized.
557     USB_Disable();
558
559     USB_Init();
560
561     // for Console_Task
562     USB_Device_EnableSOFEvents();
563     print_set_sendchar(sendchar);
564 }
565
566 int main(void)  __attribute__ ((weak));
567 int main(void)
568 {
569     SetupHardware();
570     sei();
571
572     /* wait for USB startup & debug output */
573     while (USB_DeviceState != DEVICE_STATE_Configured) {
574 #if defined(INTERRUPT_CONTROL_ENDPOINT)
575         ;
576 #else
577         USB_USBTask();
578 #endif
579     }
580     print("USB configured.\n");
581
582     /* init modules */
583     keyboard_init();
584     host_set_driver(&lufa_driver);
585 #ifdef SLEEP_LED_ENABLE
586     sleep_led_init();
587 #endif
588
589     print("Keyboard start.\n");
590     while (1) {
591         while (USB_DeviceState == DEVICE_STATE_Suspended) {
592             print("[s]");
593             suspend_power_down();
594             if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
595                     USB_Device_SendRemoteWakeup();
596             }
597         }
598
599         keyboard_task();
600
601 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
602         USB_USBTask();
603 #endif
604     }
605 }