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