]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/protocol/chibios/usb_main.c
Fix chibios/usb_main GET_REPORT handing.
[max/tmk_keyboard.git] / tmk_core / protocol / chibios / usb_main.c
1 /*
2  * (c) 2015 flabberast <s3+flabbergast@sdfeu.org>
3  *
4  * Based on the following work:
5  *  - Guillaume Duc's raw hid example (MIT License)
6  *    https://github.com/guiduc/usb-hid-chibios-example
7  *  - PJRC Teensy examples (MIT License)
8  *    https://www.pjrc.com/teensy/usb_keyboard.html
9  *  - hasu's TMK keyboard code (GPL v2 and some code Modified BSD)
10  *    https://github.com/tmk/tmk_keyboard/
11  *  - ChibiOS demo code (Apache 2.0 License)
12  *    http://www.chibios.org
13  *
14  * Since some GPL'd code is used, this work is licensed under
15  * GPL v2 or later.
16  */
17
18 #include "ch.h"
19 #include "hal.h"
20
21 #include "usb_main.h"
22
23 #include "host.h"
24 #include "debug.h"
25 #ifdef SLEEP_LED_ENABLE
26 #include "sleep_led.h"
27 #include "led.h"
28 #endif
29
30 /* ---------------------------------------------------------
31  *       Global interface variables and declarations
32  * ---------------------------------------------------------
33  */
34
35 uint8_t keyboard_idle = 0;
36 uint8_t keyboard_protocol = 1;
37 uint16_t keyboard_led_stats = 0;
38 volatile uint16_t keyboard_idle_count = 0;
39 static virtual_timer_t keyboard_idle_timer;
40 static void keyboard_idle_timer_cb(void *arg);
41 #ifdef NKRO_ENABLE
42 extern bool keyboard_nkro;
43 #endif /* NKRO_ENABLE */
44
45 report_keyboard_t keyboard_report_sent = {{0}};
46 #ifdef MOUSE_ENABLE
47 report_mouse_t mouse_report_blank = {0};
48 #endif /* MOUSE_ENABLE */
49 #ifdef EXTRAKEY_ENABLE
50 uint8_t extra_report_blank[3] = {0};
51 #endif /* EXTRAKEY_ENABLE */
52
53 #ifdef CONSOLE_ENABLE
54 /* The emission queue */
55 output_queue_t console_queue;
56 static uint8_t console_queue_buffer[CONSOLE_QUEUE_BUFFER_SIZE];
57 static virtual_timer_t console_flush_timer;
58 void console_queue_onotify(io_queue_t *qp);
59 static void console_flush_cb(void *arg);
60 #endif /* CONSOLE_ENABLE */
61
62 /* ---------------------------------------------------------
63  *            Descriptors and USB driver objects
64  * ---------------------------------------------------------
65  */
66
67 /* HID specific constants */
68 #define USB_DESCRIPTOR_HID 0x21
69 #define USB_DESCRIPTOR_HID_REPORT 0x22
70 #define HID_GET_REPORT 0x01
71 #define HID_GET_IDLE 0x02
72 #define HID_GET_PROTOCOL 0x03
73 #define HID_SET_REPORT 0x09
74 #define HID_SET_IDLE 0x0A
75 #define HID_SET_PROTOCOL 0x0B
76
77 /* USB Device Descriptor */
78 static const uint8_t usb_device_descriptor_data[] = {
79   USB_DESC_DEVICE(0x0200,      // bcdUSB (1.1)
80                   0,           // bDeviceClass (defined in later in interface)
81                   0,           // bDeviceSubClass
82                   0,           // bDeviceProtocol
83                   64,          // bMaxPacketSize (64 bytes) (the driver didn't work with 32)
84                   VENDOR_ID,   // idVendor
85                   PRODUCT_ID,  // idProduct
86                   DEVICE_VER,      // bcdDevice
87                   1,           // iManufacturer
88                   2,           // iProduct
89                   3,           // iSerialNumber
90                   1)           // bNumConfigurations
91 };
92
93 /* Device Descriptor wrapper */
94 static const USBDescriptor usb_device_descriptor = {
95   sizeof usb_device_descriptor_data,
96   usb_device_descriptor_data
97 };
98
99 /*
100  * HID Report Descriptor
101  *
102  * See "Device Class Definition for Human Interface Devices (HID)"
103  * (http://www.usb.org/developers/hidpage/HID1_11.pdf) for the
104  * detailed descrition of all the fields
105  */
106
107 /* Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 */
108 static const uint8_t keyboard_hid_report_desc_data[] = {
109   0x05, 0x01,                // Usage Page (Generic Desktop),
110   0x09, 0x06,                // Usage (Keyboard),
111   0xA1, 0x01,                // Collection (Application),
112   0x75, 0x01,                //   Report Size (1),
113   0x95, 0x08,                //   Report Count (8),
114   0x05, 0x07,                //   Usage Page (Key Codes),
115   0x19, 0xE0,                //   Usage Minimum (224),
116   0x29, 0xE7,                //   Usage Maximum (231),
117   0x15, 0x00,                //   Logical Minimum (0),
118   0x25, 0x01,                //   Logical Maximum (1),
119   0x81, 0x02,                //   Input (Data, Variable, Absolute), ;Modifier byte
120   0x95, 0x01,                //   Report Count (1),
121   0x75, 0x08,                //   Report Size (8),
122   0x81, 0x03,                //   Input (Constant),                 ;Reserved byte
123   0x95, 0x05,                //   Report Count (5),
124   0x75, 0x01,                //   Report Size (1),
125   0x05, 0x08,                //   Usage Page (LEDs),
126   0x19, 0x01,                //   Usage Minimum (1),
127   0x29, 0x05,                //   Usage Maximum (5),
128   0x91, 0x02,                //   Output (Data, Variable, Absolute), ;LED report
129   0x95, 0x01,                //   Report Count (1),
130   0x75, 0x03,                //   Report Size (3),
131   0x91, 0x03,                //   Output (Constant),                 ;LED report padding
132   0x95, KBD_REPORT_KEYS,          //   Report Count (),
133   0x75, 0x08,                //   Report Size (8),
134   0x15, 0x00,                //   Logical Minimum (0),
135   0x25, 0xFF,                //   Logical Maximum(255),
136   0x05, 0x07,                //   Usage Page (Key Codes),
137   0x19, 0x00,                //   Usage Minimum (0),
138   0x29, 0xFF,                //   Usage Maximum (255),
139   0x81, 0x00,                //   Input (Data, Array),
140   0xc0                       // End Collection
141 };
142 /* wrapper */
143 static const USBDescriptor keyboard_hid_report_descriptor = {
144   sizeof keyboard_hid_report_desc_data,
145   keyboard_hid_report_desc_data
146 };
147
148 #ifdef NKRO_ENABLE
149 static const uint8_t nkro_hid_report_desc_data[] = {
150   0x05, 0x01,                           // Usage Page (Generic Desktop),
151   0x09, 0x06,                           // Usage (Keyboard),
152   0xA1, 0x01,                           // Collection (Application),
153   // bitmap of modifiers
154   0x75, 0x01,                           //   Report Size (1),
155   0x95, 0x08,                           //   Report Count (8),
156   0x05, 0x07,                           //   Usage Page (Key Codes),
157   0x19, 0xE0,                           //   Usage Minimum (224),
158   0x29, 0xE7,                           //   Usage Maximum (231),
159   0x15, 0x00,                           //   Logical Minimum (0),
160   0x25, 0x01,                           //   Logical Maximum (1),
161   0x81, 0x02,                           //   Input (Data, Variable, Absolute), ;Modifier byte
162   // LED output report
163   0x95, 0x05,                           //   Report Count (5),
164   0x75, 0x01,                           //   Report Size (1),
165   0x05, 0x08,                           //   Usage Page (LEDs),
166   0x19, 0x01,                           //   Usage Minimum (1),
167   0x29, 0x05,                           //   Usage Maximum (5),
168   0x91, 0x02,                           //   Output (Data, Variable, Absolute),
169   0x95, 0x01,                           //   Report Count (1),
170   0x75, 0x03,                           //   Report Size (3),
171   0x91, 0x03,                           //   Output (Constant),
172   // bitmap of keys
173   0x95, NKRO_REPORT_KEYS * 8,           //   Report Count (),
174   0x75, 0x01,                           //   Report Size (1),
175   0x15, 0x00,                           //   Logical Minimum (0),
176   0x25, 0x01,                           //   Logical Maximum(1),
177   0x05, 0x07,                           //   Usage Page (Key Codes),
178   0x19, 0x00,                           //   Usage Minimum (0),
179   0x29, NKRO_REPORT_KEYS * 8 - 1,       //   Usage Maximum (),
180   0x81, 0x02,                           //   Input (Data, Variable, Absolute),
181   0xc0                                  // End Collection
182 };
183 /* wrapper */
184 static const USBDescriptor nkro_hid_report_descriptor = {
185   sizeof nkro_hid_report_desc_data,
186   nkro_hid_report_desc_data
187 };
188 #endif /* NKRO_ENABLE */
189
190 #ifdef MOUSE_ENABLE
191 /* Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
192  * http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
193  * http://www.keil.com/forum/15671/
194  * http://www.microsoft.com/whdc/device/input/wheel.mspx */
195 static const uint8_t mouse_hid_report_desc_data[] = {
196   /* mouse */
197   0x05, 0x01,                      // USAGE_PAGE (Generic Desktop)
198   0x09, 0x02,                      // USAGE (Mouse)
199   0xa1, 0x01,                      // COLLECTION (Application)
200   //0x85, REPORT_ID_MOUSE,         //   REPORT_ID (1)
201   0x09, 0x01,                      //   USAGE (Pointer)
202   0xa1, 0x00,                      //   COLLECTION (Physical)
203                                    // ----------------------------  Buttons
204   0x05, 0x09,                      //     USAGE_PAGE (Button)
205   0x19, 0x01,                      //     USAGE_MINIMUM (Button 1)
206   0x29, 0x05,                      //     USAGE_MAXIMUM (Button 5)
207   0x15, 0x00,                      //     LOGICAL_MINIMUM (0)
208   0x25, 0x01,                      //     LOGICAL_MAXIMUM (1)
209   0x75, 0x01,                      //     REPORT_SIZE (1)
210   0x95, 0x05,                      //     REPORT_COUNT (5)
211   0x81, 0x02,                      //     INPUT (Data,Var,Abs)
212   0x75, 0x03,                      //     REPORT_SIZE (3)
213   0x95, 0x01,                      //     REPORT_COUNT (1)
214   0x81, 0x03,                      //     INPUT (Cnst,Var,Abs)
215                                    // ----------------------------  X,Y position
216   0x05, 0x01,                      //     USAGE_PAGE (Generic Desktop)
217   0x09, 0x30,                      //     USAGE (X)
218   0x09, 0x31,                      //     USAGE (Y)
219   0x15, 0x81,                      //     LOGICAL_MINIMUM (-127)
220   0x25, 0x7f,                      //     LOGICAL_MAXIMUM (127)
221   0x75, 0x08,                      //     REPORT_SIZE (8)
222   0x95, 0x02,                      //     REPORT_COUNT (2)
223   0x81, 0x06,                      //     INPUT (Data,Var,Rel)
224                                    // ----------------------------  Vertical wheel
225   0x09, 0x38,                      //     USAGE (Wheel)
226   0x15, 0x81,                      //     LOGICAL_MINIMUM (-127)
227   0x25, 0x7f,                      //     LOGICAL_MAXIMUM (127)
228   0x35, 0x00,                      //     PHYSICAL_MINIMUM (0)        - reset physical
229   0x45, 0x00,                      //     PHYSICAL_MAXIMUM (0)
230   0x75, 0x08,                      //     REPORT_SIZE (8)
231   0x95, 0x01,                      //     REPORT_COUNT (1)
232   0x81, 0x06,                      //     INPUT (Data,Var,Rel)
233                                    // ----------------------------  Horizontal wheel
234   0x05, 0x0c,                      //     USAGE_PAGE (Consumer Devices)
235   0x0a, 0x38, 0x02,                //     USAGE (AC Pan)
236   0x15, 0x81,                      //     LOGICAL_MINIMUM (-127)
237   0x25, 0x7f,                      //     LOGICAL_MAXIMUM (127)
238   0x75, 0x08,                      //     REPORT_SIZE (8)
239   0x95, 0x01,                      //     REPORT_COUNT (1)
240   0x81, 0x06,                      //     INPUT (Data,Var,Rel)
241   0xc0,                            //   END_COLLECTION
242   0xc0,                            // END_COLLECTION
243 };
244 /* wrapper */
245 static const USBDescriptor mouse_hid_report_descriptor = {
246   sizeof mouse_hid_report_desc_data,
247   mouse_hid_report_desc_data
248 };
249 #endif /* MOUSE_ENABLE */
250
251 #ifdef CONSOLE_ENABLE
252 static const uint8_t console_hid_report_desc_data[] = {
253   0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined)
254   0x09, 0x74,       // Usage 0x74
255   0xA1, 0x53,       // Collection 0x53
256   0x75, 0x08,       // report size = 8 bits
257   0x15, 0x00,       // logical minimum = 0
258   0x26, 0xFF, 0x00, // logical maximum = 255
259   0x95, CONSOLE_EPSIZE, // report count
260   0x09, 0x75,       // usage
261   0x81, 0x02,       // Input (array)
262   0xC0              // end collection
263 };
264 /* wrapper */
265 static const USBDescriptor console_hid_report_descriptor = {
266   sizeof console_hid_report_desc_data,
267   console_hid_report_desc_data
268 };
269 #endif /* CONSOLE_ENABLE */
270
271 #ifdef EXTRAKEY_ENABLE
272 /* audio controls & system controls
273  * http://www.microsoft.com/whdc/archive/w2kbd.mspx */
274 static const uint8_t extra_hid_report_desc_data[] = {
275   /* system control */
276   0x05, 0x01,                      // USAGE_PAGE (Generic Desktop)
277   0x09, 0x80,                      // USAGE (System Control)
278   0xa1, 0x01,                      // COLLECTION (Application)
279   0x85, REPORT_ID_SYSTEM,          //   REPORT_ID (2)
280   0x15, 0x01,                      //   LOGICAL_MINIMUM (0x1)
281   0x25, 0xb7,                      //   LOGICAL_MAXIMUM (0xb7)
282   0x19, 0x01,                      //   USAGE_MINIMUM (0x1)
283   0x29, 0xb7,                      //   USAGE_MAXIMUM (0xb7)
284   0x75, 0x10,                      //   REPORT_SIZE (16)
285   0x95, 0x01,                      //   REPORT_COUNT (1)
286   0x81, 0x00,                      //   INPUT (Data,Array,Abs)
287   0xc0,                            // END_COLLECTION
288   /* consumer */
289   0x05, 0x0c,                      // USAGE_PAGE (Consumer Devices)
290   0x09, 0x01,                      // USAGE (Consumer Control)
291   0xa1, 0x01,                      // COLLECTION (Application)
292   0x85, REPORT_ID_CONSUMER,        //   REPORT_ID (3)
293   0x15, 0x01,                      //   LOGICAL_MINIMUM (0x1)
294   0x26, 0x9c, 0x02,                //   LOGICAL_MAXIMUM (0x29c)
295   0x19, 0x01,                      //   USAGE_MINIMUM (0x1)
296   0x2a, 0x9c, 0x02,                //   USAGE_MAXIMUM (0x29c)
297   0x75, 0x10,                      //   REPORT_SIZE (16)
298   0x95, 0x01,                      //   REPORT_COUNT (1)
299   0x81, 0x00,                      //   INPUT (Data,Array,Abs)
300   0xc0,                            // END_COLLECTION
301 };
302 /* wrapper */
303 static const USBDescriptor extra_hid_report_descriptor = {
304   sizeof extra_hid_report_desc_data,
305   extra_hid_report_desc_data
306 };
307 #endif /* EXTRAKEY_ENABLE */
308
309
310 /*
311  * Configuration Descriptor tree for a HID device
312  *
313  * The HID Specifications version 1.11 require the following order:
314  * - Configuration Descriptor
315  * - Interface Descriptor
316  * - HID Descriptor
317  * - Endpoints Descriptors
318  */
319 #define KBD_HID_DESC_NUM                0
320 #define KBD_HID_DESC_OFFSET             (9 + (9 + 9 + 7) * KBD_HID_DESC_NUM + 9)
321
322 #ifdef MOUSE_ENABLE
323 #   define MOUSE_HID_DESC_NUM           (KBD_HID_DESC_NUM + 1)
324 #   define MOUSE_HID_DESC_OFFSET        (9 + (9 + 9 + 7) * MOUSE_HID_DESC_NUM + 9)
325 #else /* MOUSE_ENABLE */
326 #   define MOUSE_HID_DESC_NUM           (KBD_HID_DESC_NUM + 0)
327 #endif /* MOUSE_ENABLE */
328
329 #ifdef CONSOLE_ENABLE
330 #define CONSOLE_HID_DESC_NUM            (MOUSE_HID_DESC_NUM + 1)
331 #define CONSOLE_HID_DESC_OFFSET         (9 + (9 + 9 + 7) * CONSOLE_HID_DESC_NUM + 9)
332 #else /* CONSOLE_ENABLE */
333 #   define CONSOLE_HID_DESC_NUM         (MOUSE_HID_DESC_NUM + 0)
334 #endif /* CONSOLE_ENABLE */
335
336 #ifdef EXTRAKEY_ENABLE
337 #   define EXTRA_HID_DESC_NUM           (CONSOLE_HID_DESC_NUM + 1)
338 #   define EXTRA_HID_DESC_OFFSET        (9 + (9 + 9 + 7) * EXTRA_HID_DESC_NUM + 9)
339 #else /* EXTRAKEY_ENABLE */
340 #   define EXTRA_HID_DESC_NUM           (CONSOLE_HID_DESC_NUM + 0)
341 #endif /* EXTRAKEY_ENABLE */
342
343 #ifdef NKRO_ENABLE
344 #   define NKRO_HID_DESC_NUM            (EXTRA_HID_DESC_NUM + 1)
345 #   define NKRO_HID_DESC_OFFSET         (9 + (9 + 9 + 7) * EXTRA_HID_DESC_NUM + 9)
346 #else /* NKRO_ENABLE */
347 #   define NKRO_HID_DESC_NUM            (EXTRA_HID_DESC_NUM + 0)
348 #endif /* NKRO_ENABLE */
349
350 #define NUM_INTERFACES                  (NKRO_HID_DESC_NUM + 1)
351 #define CONFIG1_DESC_SIZE               (9 + (9 + 9 + 7) * NUM_INTERFACES)
352
353 static const uint8_t hid_configuration_descriptor_data[] = {
354   /* Configuration Descriptor (9 bytes) USB spec 9.6.3, page 264-266, Table 9-10 */
355   USB_DESC_CONFIGURATION(CONFIG1_DESC_SIZE, // wTotalLength
356                          NUM_INTERFACES,    // bNumInterfaces
357                          1,    // bConfigurationValue
358                          0,    // iConfiguration
359                          0xA0, // bmAttributes
360                          50),  // bMaxPower (100mA)
361
362   /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
363   USB_DESC_INTERFACE(KBD_INTERFACE,        // bInterfaceNumber
364                      0,        // bAlternateSetting
365                      1,        // bNumEndpoints
366                      0x03,     // bInterfaceClass: HID
367                      0x01,     // bInterfaceSubClass: Boot
368                      0x01,     // bInterfaceProtocol: Keyboard
369                      0),       // iInterface
370
371   /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
372   USB_DESC_BYTE(9),            // bLength
373   USB_DESC_BYTE(0x21),         // bDescriptorType (HID class)
374   USB_DESC_BCD(0x0111),        // bcdHID: HID version 1.11
375   USB_DESC_BYTE(0),            // bCountryCode
376   USB_DESC_BYTE(1),            // bNumDescriptors
377   USB_DESC_BYTE(0x22),         // bDescriptorType (report desc)
378   USB_DESC_WORD(sizeof(keyboard_hid_report_desc_data)), // wDescriptorLength
379
380   /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
381   USB_DESC_ENDPOINT(KBD_ENDPOINT | 0x80,  // bEndpointAddress
382                     0x03,      // bmAttributes (Interrupt)
383                     KBD_EPSIZE,// wMaxPacketSize
384                     10),       // bInterval
385
386   #ifdef MOUSE_ENABLE
387   /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
388   USB_DESC_INTERFACE(MOUSE_INTERFACE,   // bInterfaceNumber
389                      0,        // bAlternateSetting
390                      1,        // bNumEndpoints
391                      0x03,     // bInterfaceClass (0x03 = HID)
392                      // ThinkPad T23 BIOS doesn't work with boot mouse.
393                      0x00,     // bInterfaceSubClass (0x01 = Boot)
394                      0x00,     // bInterfaceProtocol (0x02 = Mouse)
395                      /*
396                         0x01,      // bInterfaceSubClass (0x01 = Boot)
397                         0x02,      // bInterfaceProtocol (0x02 = Mouse)
398                       */
399                      0),        // iInterface
400
401   /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
402   USB_DESC_BYTE(9),            // bLength
403   USB_DESC_BYTE(0x21),         // bDescriptorType (HID class)
404   USB_DESC_BCD(0x0111),        // bcdHID: HID version 1.11
405   USB_DESC_BYTE(0),            // bCountryCode
406   USB_DESC_BYTE(1),            // bNumDescriptors
407   USB_DESC_BYTE(0x22),         // bDescriptorType (report desc)
408   USB_DESC_WORD(sizeof(mouse_hid_report_desc_data)), // wDescriptorLength
409
410   /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
411   USB_DESC_ENDPOINT(MOUSE_ENDPOINT | 0x80,  // bEndpointAddress
412                     0x03,      // bmAttributes (Interrupt)
413                     MOUSE_EPSIZE,  // wMaxPacketSize
414                     1),        // bInterval
415   #endif /* MOUSE_ENABLE */
416
417   #ifdef CONSOLE_ENABLE
418   /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
419   USB_DESC_INTERFACE(CONSOLE_INTERFACE, // bInterfaceNumber
420                      0,        // bAlternateSetting
421                      1,        // bNumEndpoints
422                      0x03,     // bInterfaceClass: HID
423                      0x00,     // bInterfaceSubClass: None
424                      0x00,     // bInterfaceProtocol: None
425                      0),       // iInterface
426
427   /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
428   USB_DESC_BYTE(9),            // bLength
429   USB_DESC_BYTE(0x21),         // bDescriptorType (HID class)
430   USB_DESC_BCD(0x0111),        // bcdHID: HID version 1.11
431   USB_DESC_BYTE(0),            // bCountryCode
432   USB_DESC_BYTE(1),            // bNumDescriptors
433   USB_DESC_BYTE(0x22),         // bDescriptorType (report desc)
434   USB_DESC_WORD(sizeof(console_hid_report_desc_data)), // wDescriptorLength
435
436   /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
437   USB_DESC_ENDPOINT(CONSOLE_ENDPOINT | 0x80,  // bEndpointAddress
438                     0x03,      // bmAttributes (Interrupt)
439                     CONSOLE_EPSIZE, // wMaxPacketSize
440                     1),        // bInterval
441   #endif /* CONSOLE_ENABLE */
442
443   #ifdef EXTRAKEY_ENABLE
444   /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
445   USB_DESC_INTERFACE(EXTRA_INTERFACE, // bInterfaceNumber
446                      0,        // bAlternateSetting
447                      1,        // bNumEndpoints
448                      0x03,     // bInterfaceClass: HID
449                      0x00,     // bInterfaceSubClass: None
450                      0x00,     // bInterfaceProtocol: None
451                      0),       // iInterface
452
453   /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
454   USB_DESC_BYTE(9),            // bLength
455   USB_DESC_BYTE(0x21),         // bDescriptorType (HID class)
456   USB_DESC_BCD(0x0111),        // bcdHID: HID version 1.11
457   USB_DESC_BYTE(0),            // bCountryCode
458   USB_DESC_BYTE(1),            // bNumDescriptors
459   USB_DESC_BYTE(0x22),         // bDescriptorType (report desc)
460   USB_DESC_WORD(sizeof(extra_hid_report_desc_data)), // wDescriptorLength
461
462   /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
463   USB_DESC_ENDPOINT(EXTRA_ENDPOINT | 0x80,  // bEndpointAddress
464                     0x03,      // bmAttributes (Interrupt)
465                     EXTRA_EPSIZE, // wMaxPacketSize
466                     10),       // bInterval
467   #endif /* EXTRAKEY_ENABLE */
468
469   #ifdef NKRO_ENABLE
470   /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
471   USB_DESC_INTERFACE(NKRO_INTERFACE, // bInterfaceNumber
472                      0,        // bAlternateSetting
473                      1,        // bNumEndpoints
474                      0x03,     // bInterfaceClass: HID
475                      0x00,     // bInterfaceSubClass: None
476                      0x00,     // bInterfaceProtocol: None
477                      0),       // iInterface
478
479   /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
480   USB_DESC_BYTE(9),            // bLength
481   USB_DESC_BYTE(0x21),         // bDescriptorType (HID class)
482   USB_DESC_BCD(0x0111),        // bcdHID: HID version 1.11
483   USB_DESC_BYTE(0),            // bCountryCode
484   USB_DESC_BYTE(1),            // bNumDescriptors
485   USB_DESC_BYTE(0x22),         // bDescriptorType (report desc)
486   USB_DESC_WORD(sizeof(nkro_hid_report_desc_data)), // wDescriptorLength
487
488   /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
489   USB_DESC_ENDPOINT(NKRO_ENDPOINT | 0x80,  // bEndpointAddress
490                     0x03,      // bmAttributes (Interrupt)
491                     NKRO_EPSIZE, // wMaxPacketSize
492                     1),       // bInterval
493   #endif /* NKRO_ENABLE */
494 };
495
496 /* Configuration Descriptor wrapper */
497 static const USBDescriptor hid_configuration_descriptor = {
498   sizeof hid_configuration_descriptor_data,
499   hid_configuration_descriptor_data
500 };
501
502 /* wrappers */
503 #define HID_DESCRIPTOR_SIZE 9
504 static const USBDescriptor keyboard_hid_descriptor = {
505   HID_DESCRIPTOR_SIZE,
506   &hid_configuration_descriptor_data[KBD_HID_DESC_OFFSET]
507 };
508 #ifdef MOUSE_ENABLE
509 static const USBDescriptor mouse_hid_descriptor = {
510   HID_DESCRIPTOR_SIZE,
511   &hid_configuration_descriptor_data[MOUSE_HID_DESC_OFFSET]
512 };
513 #endif /* MOUSE_ENABLE */
514 #ifdef CONSOLE_ENABLE
515 static const USBDescriptor console_hid_descriptor = {
516   HID_DESCRIPTOR_SIZE,
517   &hid_configuration_descriptor_data[CONSOLE_HID_DESC_OFFSET]
518 };
519 #endif /* CONSOLE_ENABLE */
520 #ifdef EXTRAKEY_ENABLE
521 static const USBDescriptor extra_hid_descriptor = {
522   HID_DESCRIPTOR_SIZE,
523   &hid_configuration_descriptor_data[EXTRA_HID_DESC_OFFSET]
524 };
525 #endif /* EXTRAKEY_ENABLE */
526 #ifdef NKRO_ENABLE
527 static const USBDescriptor nkro_hid_descriptor = {
528   HID_DESCRIPTOR_SIZE,
529   &hid_configuration_descriptor_data[NKRO_HID_DESC_OFFSET]
530 };
531 #endif /* NKRO_ENABLE */
532
533
534 /* U.S. English language identifier */
535 static const uint8_t usb_string_langid[] = {
536   USB_DESC_BYTE(4),                        // bLength
537   USB_DESC_BYTE(USB_DESCRIPTOR_STRING),    // bDescriptorType
538   USB_DESC_WORD(0x0409)                    // wLANGID (U.S. English)
539 };
540
541 /* ugly ugly hack */
542 #define PP_NARG(...) \
543          PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
544 #define PP_NARG_(...) \
545          PP_ARG_N(__VA_ARGS__)
546 #define PP_ARG_N( \
547           _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
548          _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
549          _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
550          _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
551          _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
552          _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
553          _61,_62,_63,N,...) N
554 #define PP_RSEQ_N() \
555          63,62,61,60,                   \
556          59,58,57,56,55,54,53,52,51,50, \
557          49,48,47,46,45,44,43,42,41,40, \
558          39,38,37,36,35,34,33,32,31,30, \
559          29,28,27,26,25,24,23,22,21,20, \
560          19,18,17,16,15,14,13,12,11,10, \
561          9,8,7,6,5,4,3,2,1,0
562
563 /* Vendor string = manufacturer */
564 static const uint8_t usb_string_vendor[] = {
565   USB_DESC_BYTE(PP_NARG(USBSTR_MANUFACTURER)+2),                       // bLength
566   USB_DESC_BYTE(USB_DESCRIPTOR_STRING),    // bDescriptorType
567   USBSTR_MANUFACTURER
568 };
569
570 /* Device Description string = product */
571 static const uint8_t usb_string_description[] = {
572   USB_DESC_BYTE(PP_NARG(USBSTR_PRODUCT)+2),           // bLength
573   USB_DESC_BYTE(USB_DESCRIPTOR_STRING),    // bDescriptorType
574   USBSTR_PRODUCT
575 };
576
577 /* Serial Number string (will be filled by the function init_usb_serial_string) */
578 static uint8_t usb_string_serial[] = {
579   USB_DESC_BYTE(22),                       // bLength
580   USB_DESC_BYTE(USB_DESCRIPTOR_STRING),    // bDescriptorType
581   '0', 0, 'x', 0, 'D', 0, 'E', 0, 'A', 0, 'D', 0, 'B', 0, 'E', 0, 'E', 0, 'F', 0
582 };
583
584 /* Strings wrappers array */
585 static const USBDescriptor usb_strings[] = {
586   { sizeof usb_string_langid, usb_string_langid }
587   ,
588   { sizeof usb_string_vendor, usb_string_vendor }
589   ,
590   { sizeof usb_string_description, usb_string_description }
591   ,
592   { sizeof usb_string_serial, usb_string_serial }
593 };
594
595 /*
596  * Handles the GET_DESCRIPTOR callback
597  *
598  * Returns the proper descriptor
599  */
600 static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t lang) {
601   (void)usbp;
602   (void)lang;
603   switch(dtype) {
604   /* Generic descriptors */
605   case USB_DESCRIPTOR_DEVICE:   /* Device Descriptor */
606     return &usb_device_descriptor;
607
608   case USB_DESCRIPTOR_CONFIGURATION:    /* Configuration Descriptor */
609     return &hid_configuration_descriptor;
610
611   case USB_DESCRIPTOR_STRING:   /* Strings */
612     if(dindex < 4)
613       return &usb_strings[dindex];
614     break;
615
616   /* HID specific descriptors */
617   case USB_DESCRIPTOR_HID:      /* HID Descriptors */
618     switch(lang) {    /* yea, poor label, it's actually wIndex from the setup packet */
619     case KBD_INTERFACE:
620       return &keyboard_hid_descriptor;
621
622 #ifdef MOUSE_ENABLE
623     case MOUSE_INTERFACE:
624       return &mouse_hid_descriptor;
625 #endif /* MOUSE_ENABLE */
626 #ifdef CONSOLE_ENABLE
627     case CONSOLE_INTERFACE:
628       return &console_hid_descriptor;
629 #endif /* CONSOLE_ENABLE */
630 #ifdef EXTRAKEY_ENABLE
631     case EXTRA_INTERFACE:
632       return &extra_hid_descriptor;
633 #endif /* EXTRAKEY_ENABLE */
634 #ifdef NKRO_ENABLE
635     case NKRO_INTERFACE:
636       return &nkro_hid_descriptor;
637 #endif /* NKRO_ENABLE */
638     }
639
640   case USB_DESCRIPTOR_HID_REPORT:       /* HID Report Descriptor */
641     switch(lang) {
642     case KBD_INTERFACE:
643       return &keyboard_hid_report_descriptor;
644
645 #ifdef MOUSE_ENABLE
646     case MOUSE_INTERFACE:
647       return &mouse_hid_report_descriptor;
648 #endif /* MOUSE_ENABLE */
649 #ifdef CONSOLE_ENABLE
650     case CONSOLE_INTERFACE:
651       return &console_hid_report_descriptor;
652 #endif /* CONSOLE_ENABLE */
653 #ifdef EXTRAKEY_ENABLE
654     case EXTRA_INTERFACE:
655       return &extra_hid_report_descriptor;
656 #endif /* EXTRAKEY_ENABLE */
657 #ifdef NKRO_ENABLE
658     case NKRO_INTERFACE:
659       return &nkro_hid_report_descriptor;
660 #endif /* NKRO_ENABLE */
661     }
662   }
663   return NULL;
664 }
665
666 /* keyboard endpoint state structure */
667 static USBInEndpointState kbd_ep_state;
668 /* keyboard endpoint initialization structure (IN) */
669 static const USBEndpointConfig kbd_ep_config = {
670   USB_EP_MODE_TYPE_INTR,        /* Interrupt EP */
671   NULL,                         /* SETUP packet notification callback */
672   kbd_in_cb,                    /* IN notification callback */
673   NULL,                         /* OUT notification callback */
674   KBD_EPSIZE,                   /* IN maximum packet size */
675   0,                            /* OUT maximum packet size */
676   &kbd_ep_state,                /* IN Endpoint state */
677   NULL,                         /* OUT endpoint state */
678   2,                            /* IN multiplier */
679   NULL                          /* SETUP buffer (not a SETUP endpoint) */
680 };
681
682 #ifdef MOUSE_ENABLE
683 /* mouse endpoint state structure */
684 static USBInEndpointState mouse_ep_state;
685
686 /* mouse endpoint initialization structure (IN) */
687 static const USBEndpointConfig mouse_ep_config = {
688   USB_EP_MODE_TYPE_INTR,        /* Interrupt EP */
689   NULL,                         /* SETUP packet notification callback */
690   mouse_in_cb,                  /* IN notification callback */
691   NULL,                         /* OUT notification callback */
692   MOUSE_EPSIZE,                 /* IN maximum packet size */
693   0,                            /* OUT maximum packet size */
694   &mouse_ep_state,              /* IN Endpoint state */
695   NULL,                         /* OUT endpoint state */
696   2,                            /* IN multiplier */
697   NULL                          /* SETUP buffer (not a SETUP endpoint) */
698 };
699 #endif /* MOUSE_ENABLE */
700
701 #ifdef CONSOLE_ENABLE
702 /* console endpoint state structure */
703 static USBInEndpointState console_ep_state;
704
705 /* console endpoint initialization structure (IN) */
706 static const USBEndpointConfig console_ep_config = {
707   USB_EP_MODE_TYPE_INTR,        /* Interrupt EP */
708   NULL,                         /* SETUP packet notification callback */
709   console_in_cb,                /* IN notification callback */
710   NULL,                         /* OUT notification callback */
711   CONSOLE_EPSIZE,               /* IN maximum packet size */
712   0,                            /* OUT maximum packet size */
713   &console_ep_state,            /* IN Endpoint state */
714   NULL,                         /* OUT endpoint state */
715   2,                            /* IN multiplier */
716   NULL                          /* SETUP buffer (not a SETUP endpoint) */
717 };
718 #endif /* CONSOLE_ENABLE */
719
720 #ifdef EXTRAKEY_ENABLE
721 /* extrakey endpoint state structure */
722 static USBInEndpointState extra_ep_state;
723
724 /* extrakey endpoint initialization structure (IN) */
725 static const USBEndpointConfig extra_ep_config = {
726   USB_EP_MODE_TYPE_INTR,        /* Interrupt EP */
727   NULL,                         /* SETUP packet notification callback */
728   extra_in_cb,                  /* IN notification callback */
729   NULL,                         /* OUT notification callback */
730   EXTRA_EPSIZE,                 /* IN maximum packet size */
731   0,                            /* OUT maximum packet size */
732   &extra_ep_state,              /* IN Endpoint state */
733   NULL,                         /* OUT endpoint state */
734   2,                            /* IN multiplier */
735   NULL                          /* SETUP buffer (not a SETUP endpoint) */
736 };
737 #endif /* EXTRAKEY_ENABLE */
738
739 #ifdef NKRO_ENABLE
740 /* nkro endpoint state structure */
741 static USBInEndpointState nkro_ep_state;
742
743 /* nkro endpoint initialization structure (IN) */
744 static const USBEndpointConfig nkro_ep_config = {
745   USB_EP_MODE_TYPE_INTR,        /* Interrupt EP */
746   NULL,                         /* SETUP packet notification callback */
747   nkro_in_cb,                   /* IN notification callback */
748   NULL,                         /* OUT notification callback */
749   NKRO_EPSIZE,                  /* IN maximum packet size */
750   0,                            /* OUT maximum packet size */
751   &nkro_ep_state,               /* IN Endpoint state */
752   NULL,                         /* OUT endpoint state */
753   2,                            /* IN multiplier */
754   NULL                          /* SETUP buffer (not a SETUP endpoint) */
755 };
756 #endif /* NKRO_ENABLE */
757
758 /* ---------------------------------------------------------
759  *                  USB driver functions
760  * ---------------------------------------------------------
761  */
762
763 /* Handles the USB driver global events
764  * TODO: maybe disable some things when connection is lost? */
765 static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
766   switch(event) {
767   case USB_EVENT_RESET:
768     //TODO: from ISR! print("[R]");
769     return;
770
771   case USB_EVENT_ADDRESS:
772     return;
773
774   case USB_EVENT_CONFIGURED:
775     osalSysLockFromISR();
776     /* Enable the endpoints specified into the configuration. */
777     usbInitEndpointI(usbp, KBD_ENDPOINT, &kbd_ep_config);
778 #ifdef MOUSE_ENABLE
779     usbInitEndpointI(usbp, MOUSE_ENDPOINT, &mouse_ep_config);
780 #endif /* MOUSE_ENABLE */
781 #ifdef CONSOLE_ENABLE
782     usbInitEndpointI(usbp, CONSOLE_ENDPOINT, &console_ep_config);
783     /* don't need to start the flush timer, it starts from console_in_cb automatically */
784 #endif /* CONSOLE_ENABLE */
785 #ifdef EXTRAKEY_ENABLE
786     usbInitEndpointI(usbp, EXTRA_ENDPOINT, &extra_ep_config);
787 #endif /* EXTRAKEY_ENABLE */
788 #ifdef NKRO_ENABLE
789     usbInitEndpointI(usbp, NKRO_ENDPOINT, &nkro_ep_config);
790 #endif /* NKRO_ENABLE */
791     osalSysUnlockFromISR();
792     return;
793
794   case USB_EVENT_SUSPEND:
795     //TODO: from ISR! print("[S]");
796     //TODO: signal suspend?
797 #ifdef SLEEP_LED_ENABLE
798     sleep_led_enable();
799 #endif /* SLEEP_LED_ENABLE */
800     return;
801
802   case USB_EVENT_WAKEUP:
803     //TODO: from ISR! print("[W]");
804     //TODO: suspend_wakeup_init();
805 #ifdef SLEEP_LED_ENABLE
806     sleep_led_disable();
807     // NOTE: converters may not accept this
808     led_set(host_keyboard_leds());
809 #endif /* SLEEP_LED_ENABLE */
810     return;
811
812   case USB_EVENT_STALLED:
813     return;
814   }
815 }
816
817 /* Function used locally in os/hal/src/usb.c for getting descriptors
818  * need it here for HID descriptor */
819 static uint16_t get_hword(uint8_t *p) {
820   uint16_t hw;
821
822   hw = (uint16_t)*p++;
823   hw |= (uint16_t)*p << 8U;
824   return hw;
825 }
826
827 /*
828  * Appendix G: HID Request Support Requirements
829  *
830  * The following table enumerates the requests that need to be supported by various types of HID class devices.
831  * Device type     GetReport   SetReport   GetIdle     SetIdle     GetProtocol SetProtocol
832  * ------------------------------------------------------------------------------------------
833  * Boot Mouse      Required    Optional    Optional    Optional    Required    Required
834  * Non-Boot Mouse  Required    Optional    Optional    Optional    Optional    Optional
835  * Boot Keyboard   Required    Optional    Required    Required    Required    Required
836  * Non-Boot Keybrd Required    Optional    Required    Required    Optional    Optional
837  * Other Device    Required    Optional    Optional    Optional    Optional    Optional
838  */
839
840 /* Callback for SETUP request on the endpoint 0 (control) */
841 static bool usb_request_hook_cb(USBDriver *usbp) {
842   const USBDescriptor *dp;
843
844   /* usbp->setup fields:
845    *  0:   bmRequestType (bitmask)
846    *  1:   bRequest
847    *  2,3: (LSB,MSB) wValue
848    *  4,5: (LSB,MSB) wIndex
849    *  6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */
850
851   /* Handle HID class specific requests */
852   if(((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) &&
853      ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
854     switch(usbp->setup[0] & USB_RTYPE_DIR_MASK) {
855     case USB_RTYPE_DIR_DEV2HOST:
856       switch(usbp->setup[1]) {   /* bRequest */
857       case HID_GET_REPORT:
858         switch(usbp->setup[4]) {     /* LSB(wIndex) (check MSB==0?) */
859         case KBD_INTERFACE:
860 #ifdef NKRO_ENABLE
861         case NKRO_INTERFACE:
862 #endif /* NKRO_ENABLE */
863           usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
864           return TRUE;
865           break;
866
867 #ifdef MOUSE_ENABLE
868         case MOUSE_INTERFACE:
869           usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
870           return TRUE;
871           break;
872 #endif /* MOUSE_ENABLE */
873
874 #ifdef CONSOLE_ENABLE
875         case CONSOLE_INTERFACE:
876           usbSetupTransfer(usbp, console_queue_buffer, CONSOLE_EPSIZE, NULL);
877           return TRUE;
878           break;
879 #endif /* CONSOLE_ENABLE */
880
881 #ifdef EXTRAKEY_ENABLE
882         case EXTRA_INTERFACE:
883           if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
884             switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
885               case REPORT_ID_SYSTEM:
886                 extra_report_blank[0] = REPORT_ID_SYSTEM;
887                 usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
888                 return TRUE;
889                 break;
890               case REPORT_ID_CONSUMER:
891                 extra_report_blank[0] = REPORT_ID_CONSUMER;
892                 usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
893                 return TRUE;
894                 break;
895               default:
896                 return FALSE;
897             }
898           } else {
899             return FALSE;
900           }
901           break;
902 #endif /* EXTRAKEY_ENABLE */
903
904         default:
905           usbSetupTransfer(usbp, NULL, 0, NULL);
906           return TRUE;
907           break;
908         }
909         break;
910
911       case HID_GET_PROTOCOL:
912         if((usbp->setup[4] == KBD_INTERFACE) && (usbp->setup[5] == 0)) {   /* wIndex */
913           usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
914           return TRUE;
915         }
916         break;
917
918       case HID_GET_IDLE:
919         usbSetupTransfer(usbp, &keyboard_idle, 1, NULL);
920         return TRUE;
921         break;
922       }
923       break;
924
925     case USB_RTYPE_DIR_HOST2DEV:
926       switch(usbp->setup[1]) {   /* bRequest */
927       case HID_SET_REPORT:
928         switch(usbp->setup[4]) {       /* LSB(wIndex) (check MSB==0 and wLength==1?) */
929         case KBD_INTERFACE:
930 #ifdef NKRO_ENABLE
931         case NKRO_INTERFACE:
932 #endif  /* NKRO_ENABLE */
933         /* keyboard_led_stats = <read byte from next OUT report>
934          * keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */
935           usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
936           return TRUE;
937           break;
938         }
939         break;
940
941       case HID_SET_PROTOCOL:
942         if((usbp->setup[4] == KBD_INTERFACE) && (usbp->setup[5] == 0)) {   /* wIndex */
943           keyboard_protocol = ((usbp->setup[2]) != 0x00);   /* LSB(wValue) */
944 #ifdef NKRO_ENABLE
945           keyboard_nkro = !!keyboard_protocol;
946           if(!keyboard_nkro && keyboard_idle) {
947 #else /* NKRO_ENABLE */
948           if(keyboard_idle) {
949 #endif /* NKRO_ENABLE */
950           /* arm the idle timer if boot protocol & idle */
951             osalSysLockFromISR();
952             chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
953             osalSysUnlockFromISR();
954           }
955         }
956         usbSetupTransfer(usbp, NULL, 0, NULL);
957         return TRUE;
958         break;
959
960       case HID_SET_IDLE:
961         keyboard_idle = usbp->setup[3];     /* MSB(wValue) */
962         /* arm the timer */
963 #ifdef NKRO_ENABLE
964         if(!keyboard_nkro && keyboard_idle) {
965 #else /* NKRO_ENABLE */
966         if(keyboard_idle) {
967 #endif /* NKRO_ENABLE */
968           osalSysLockFromISR();
969           chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
970           osalSysUnlockFromISR();
971         }
972         usbSetupTransfer(usbp, NULL, 0, NULL);
973         return TRUE;
974         break;
975       }
976       break;
977     }
978   }
979
980   /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */
981   if((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) {
982     dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4]));
983     if(dp == NULL)
984       return FALSE;
985     usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
986     return TRUE;
987   }
988
989   return FALSE;
990 }
991
992 /* Start-of-frame callback */
993 static void usb_sof_cb(USBDriver *usbp) {
994   kbd_sof_cb(usbp);
995 }
996
997
998 /* USB driver configuration */
999 static const USBConfig usbcfg = {
1000   usb_event_cb,                 /* USB events callback */
1001   usb_get_descriptor_cb,        /* Device GET_DESCRIPTOR request callback */
1002   usb_request_hook_cb,          /* Requests hook callback */
1003   usb_sof_cb                    /* Start Of Frame callback */
1004 };
1005
1006 /*
1007  * Initialize the USB driver
1008  */
1009 void init_usb_driver(USBDriver *usbp) {
1010   /*
1011    * Activates the USB driver and then the USB bus pull-up on D+.
1012    * Note, a delay is inserted in order to not have to disconnect the cable
1013    * after a reset.
1014    */
1015   usbDisconnectBus(usbp);
1016   chThdSleepMilliseconds(1500);
1017   usbStart(usbp, &usbcfg);
1018   usbConnectBus(usbp);
1019
1020   chVTObjectInit(&keyboard_idle_timer);
1021 #ifdef CONSOLE_ENABLE
1022   oqObjectInit(&console_queue, console_queue_buffer, sizeof(console_queue_buffer), console_queue_onotify, (void *)usbp);
1023   chVTObjectInit(&console_flush_timer);
1024 #endif
1025 }
1026
1027 /* ---------------------------------------------------------
1028  *                  Keyboard functions
1029  * ---------------------------------------------------------
1030  */
1031
1032 /* keyboard IN callback hander (a kbd report has made it IN) */
1033 void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
1034   /* STUB */
1035   (void)usbp;
1036   (void)ep;
1037 }
1038
1039 #ifdef NKRO_ENABLE
1040 /* nkro IN callback hander (a nkro report has made it IN) */
1041 void nkro_in_cb(USBDriver *usbp, usbep_t ep) {
1042   /* STUB */
1043   (void)usbp;
1044   (void)ep;
1045 }
1046 #endif /* NKRO_ENABLE */
1047
1048 /* start-of-frame handler
1049  * TODO: i guess it would be better to re-implement using timers,
1050  *  so that this is not going to have to be checked every 1ms */
1051 void kbd_sof_cb(USBDriver *usbp) {
1052   (void)usbp;
1053 }
1054
1055 /* Idle requests timer code
1056  * callback (called from ISR, unlocked state) */
1057 static void keyboard_idle_timer_cb(void *arg) {
1058   USBDriver *usbp = (USBDriver *)arg;
1059
1060   osalSysLockFromISR();
1061
1062   /* check that the states of things are as they're supposed to */
1063   if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
1064     /* do not rearm the timer, should be enabled on IDLE request */
1065     osalSysUnlockFromISR();
1066     return;
1067   }
1068
1069 #ifdef NKRO_ENABLE
1070   if(!keyboard_nkro && keyboard_idle) {
1071 #else /* NKRO_ENABLE */
1072   if(keyboard_idle) {
1073 #endif /* NKRO_ENABLE */
1074     /* TODO: are we sure we want the KBD_ENDPOINT? */
1075     osalSysUnlockFromISR();
1076     usbPrepareTransmit(usbp, KBD_ENDPOINT, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent));
1077     osalSysLockFromISR();
1078     usbStartTransmitI(usbp, KBD_ENDPOINT);
1079     /* rearm the timer */
1080     chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
1081   }
1082
1083   /* do not rearm the timer if the condition above fails
1084    * it should be enabled again on either IDLE or SET_PROTOCOL requests */
1085   osalSysUnlockFromISR();
1086 }
1087
1088 /* LED status */
1089 uint8_t keyboard_leds(void) {
1090   return (uint8_t)(keyboard_led_stats & 0xFF);
1091 }
1092
1093 /* prepare and start sending a report IN
1094  * not callable from ISR or locked state */
1095 void send_keyboard(report_keyboard_t *report) {
1096   osalSysLock();
1097   if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
1098     osalSysUnlock();
1099     return;
1100   }
1101   osalSysUnlock();
1102
1103 #ifdef NKRO_ENABLE
1104   if(keyboard_nkro) {  /* NKRO protocol */
1105     usbPrepareTransmit(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
1106     osalSysLock();
1107     usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT);
1108     osalSysUnlock();
1109   } else
1110 #endif /* NKRO_ENABLE */
1111   { /* boot protocol */
1112     usbPrepareTransmit(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
1113     osalSysLock();
1114     usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT);
1115     osalSysUnlock();
1116   }
1117   keyboard_report_sent = *report;
1118 }
1119
1120 /* ---------------------------------------------------------
1121  *                     Mouse functions
1122  * ---------------------------------------------------------
1123  */
1124
1125 #ifdef MOUSE_ENABLE
1126
1127 /* mouse IN callback hander (a mouse report has made it IN) */
1128 void mouse_in_cb(USBDriver *usbp, usbep_t ep) {
1129   (void)usbp;
1130   (void)ep;
1131 }
1132
1133 void send_mouse(report_mouse_t *report) {
1134   osalSysLock();
1135   if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
1136     osalSysUnlock();
1137     return;
1138   }
1139   osalSysUnlock();
1140
1141   /* TODO: LUFA manually waits for the endpoint to become ready
1142    * for about 10ms for mouse, kbd, system; 1ms for nkro
1143    * is this really needed?
1144    */
1145
1146   usbPrepareTransmit(&USB_DRIVER, MOUSE_ENDPOINT, (uint8_t *)report, sizeof(report_mouse_t));
1147   osalSysLock();
1148   usbStartTransmitI(&USB_DRIVER, MOUSE_ENDPOINT);
1149   osalSysUnlock();
1150 }
1151
1152 #else /* MOUSE_ENABLE */
1153 void send_mouse(report_mouse_t *report) {
1154   (void)report;
1155 }
1156 #endif /* MOUSE_ENABLE */
1157
1158 /* ---------------------------------------------------------
1159  *                   Extrakey functions
1160  * ---------------------------------------------------------
1161  */
1162
1163 #ifdef EXTRAKEY_ENABLE
1164
1165 /* extrakey IN callback hander */
1166 void extra_in_cb(USBDriver *usbp, usbep_t ep) {
1167   /* STUB */
1168   (void)usbp;
1169   (void)ep;
1170 }
1171
1172 static void send_extra_report(uint8_t report_id, uint16_t data) {
1173   osalSysLock();
1174   if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
1175     osalSysUnlock();
1176     return;
1177   }
1178
1179   report_extra_t report = {
1180     .report_id = report_id,
1181     .usage = data
1182   };
1183
1184   osalSysUnlock();
1185   usbPrepareTransmit(&USB_DRIVER, EXTRA_ENDPOINT, (uint8_t *)&report, sizeof(report_extra_t));
1186   osalSysLock();
1187   usbStartTransmitI(&USB_DRIVER, EXTRA_ENDPOINT);
1188   osalSysUnlock();
1189 }
1190
1191 void send_system(uint16_t data) {
1192   send_extra_report(REPORT_ID_SYSTEM, data);
1193 }
1194
1195 void send_consumer(uint16_t data) {
1196   send_extra_report(REPORT_ID_CONSUMER, data);
1197 }
1198
1199 #else /* EXTRAKEY_ENABLE */
1200 void send_system(uint16_t data) {
1201   (void)data;
1202 }
1203 void send_consumer(uint16_t data) {
1204   (void)data;
1205 }
1206 #endif /* EXTRAKEY_ENABLE */
1207
1208 /* ---------------------------------------------------------
1209  *                   Console functions
1210  * ---------------------------------------------------------
1211  */
1212
1213 #ifdef CONSOLE_ENABLE
1214
1215 /* debug IN callback hander */
1216 void console_in_cb(USBDriver *usbp, usbep_t ep) {
1217   (void)ep;
1218   osalSysLockFromISR();
1219
1220   /* rearm the timer */
1221   chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
1222
1223   /* Check if there is data to send left in the output queue */
1224   if(chOQGetFullI(&console_queue) >= CONSOLE_EPSIZE) {
1225     osalSysUnlockFromISR();
1226     usbPrepareQueuedTransmit(usbp, CONSOLE_ENDPOINT, &console_queue, CONSOLE_EPSIZE);
1227     osalSysLockFromISR();
1228     usbStartTransmitI(usbp, CONSOLE_ENDPOINT);
1229   }
1230
1231   osalSysUnlockFromISR();
1232 }
1233
1234 /* Callback when data is inserted into the output queue
1235  * Called from a locked state */
1236 void console_queue_onotify(io_queue_t *qp) {
1237   USBDriver *usbp = qGetLink(qp);
1238
1239   if(usbGetDriverStateI(usbp) != USB_ACTIVE)
1240     return;
1241
1242   if(!usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)
1243      && (chOQGetFullI(&console_queue) >= CONSOLE_EPSIZE)) {
1244     osalSysUnlock();
1245     usbPrepareQueuedTransmit(usbp, CONSOLE_ENDPOINT, &console_queue, CONSOLE_EPSIZE);
1246     osalSysLock();
1247     usbStartTransmitI(usbp, CONSOLE_ENDPOINT);
1248   }
1249 }
1250
1251 /* Flush timer code
1252  * callback (called from ISR, unlocked state) */
1253 static void console_flush_cb(void *arg) {
1254   USBDriver *usbp = (USBDriver *)arg;
1255   size_t i, n;
1256   uint8_t buf[CONSOLE_EPSIZE]; /* TODO: a solution without extra buffer? */
1257   osalSysLockFromISR();
1258
1259   /* check that the states of things are as they're supposed to */
1260   if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
1261     /* rearm the timer */
1262     chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
1263     osalSysUnlockFromISR();
1264     return;
1265   }
1266
1267   /* don't do anything if the queue is empty or has enough stuff in it */
1268   if(((n = oqGetFullI(&console_queue)) == 0) || (n >= CONSOLE_EPSIZE)) {
1269     /* rearm the timer */
1270     chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
1271     osalSysUnlockFromISR();
1272     return;
1273   }
1274
1275   /* there's stuff hanging in the queue - so dequeue and send */
1276   for(i = 0; i < n; i++)
1277     buf[i] = (uint8_t)oqGetI(&console_queue);
1278   for(i = n; i < CONSOLE_EPSIZE; i++)
1279     buf[i] = 0;
1280   osalSysUnlockFromISR();
1281   usbPrepareTransmit(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
1282   osalSysLockFromISR();
1283   (void)usbStartTransmitI(usbp, CONSOLE_ENDPOINT);
1284
1285   /* rearm the timer */
1286   chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
1287   osalSysUnlockFromISR();
1288 }
1289
1290
1291 int8_t sendchar(uint8_t c) {
1292   osalSysLock();
1293   if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
1294     osalSysUnlock();
1295     return 0;
1296   }
1297   osalSysUnlock();
1298   /* should get suspended and wait if the queue is full
1299    * but it's not blocking even if noone is listening,
1300    *  because the USB packets are sent anyway */
1301   return(chOQPut(&console_queue, c));
1302 }
1303
1304 #else /* CONSOLE_ENABLE */
1305 int8_t sendchar(uint8_t c) {
1306   (void)c;
1307   return 0;
1308 }
1309 #endif /* CONSOLE_ENABLE */
1310
1311 void sendchar_pf(void *p, char c) {
1312   (void)p;
1313   sendchar((uint8_t)c);
1314 }