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