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