]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/chibios/usb_main.c
fix Logical Maximum to be recognized as 255 instead of -1
[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_RESET:
782     //TODO: from ISR! print("[R]");
783     return;
784
785   case USB_EVENT_ADDRESS:
786     return;
787
788   case USB_EVENT_CONFIGURED:
789     osalSysLockFromISR();
790     /* Enable the endpoints specified into the configuration. */
791     usbInitEndpointI(usbp, KBD_ENDPOINT, &kbd_ep_config);
792 #ifdef MOUSE_ENABLE
793     usbInitEndpointI(usbp, MOUSE_ENDPOINT, &mouse_ep_config);
794 #endif /* MOUSE_ENABLE */
795 #ifdef CONSOLE_ENABLE
796     usbInitEndpointI(usbp, CONSOLE_ENDPOINT, &console_ep_config);
797     /* don't need to start the flush timer, it starts from console_in_cb automatically */
798 #endif /* CONSOLE_ENABLE */
799 #ifdef EXTRAKEY_ENABLE
800     usbInitEndpointI(usbp, EXTRA_ENDPOINT, &extra_ep_config);
801 #endif /* EXTRAKEY_ENABLE */
802 #ifdef NKRO_ENABLE
803     usbInitEndpointI(usbp, NKRO_ENDPOINT, &nkro_ep_config);
804 #endif /* NKRO_ENABLE */
805     osalSysUnlockFromISR();
806     return;
807
808   case USB_EVENT_SUSPEND:
809     //TODO: from ISR! print("[S]");
810 #ifdef SLEEP_LED_ENABLE
811     sleep_led_enable();
812 #endif /* SLEEP_LED_ENABLE */
813     return;
814
815   case USB_EVENT_WAKEUP:
816     //TODO: from ISR! print("[W]");
817     suspend_wakeup_init();
818 #ifdef SLEEP_LED_ENABLE
819     sleep_led_disable();
820     // NOTE: converters may not accept this
821     led_set(host_keyboard_leds());
822 #endif /* SLEEP_LED_ENABLE */
823     return;
824
825   case USB_EVENT_STALLED:
826     return;
827   }
828 }
829
830 /* Function used locally in os/hal/src/usb.c for getting descriptors
831  * need it here for HID descriptor */
832 static uint16_t get_hword(uint8_t *p) {
833   uint16_t hw;
834
835   hw = (uint16_t)*p++;
836   hw |= (uint16_t)*p << 8U;
837   return hw;
838 }
839
840 /*
841  * Appendix G: HID Request Support Requirements
842  *
843  * The following table enumerates the requests that need to be supported by various types of HID class devices.
844  * Device type     GetReport   SetReport   GetIdle     SetIdle     GetProtocol SetProtocol
845  * ------------------------------------------------------------------------------------------
846  * Boot Mouse      Required    Optional    Optional    Optional    Required    Required
847  * Non-Boot Mouse  Required    Optional    Optional    Optional    Optional    Optional
848  * Boot Keyboard   Required    Optional    Required    Required    Required    Required
849  * Non-Boot Keybrd Required    Optional    Required    Required    Optional    Optional
850  * Other Device    Required    Optional    Optional    Optional    Optional    Optional
851  */
852
853 /* Callback for SETUP request on the endpoint 0 (control) */
854 static bool usb_request_hook_cb(USBDriver *usbp) {
855   const USBDescriptor *dp;
856
857   /* usbp->setup fields:
858    *  0:   bmRequestType (bitmask)
859    *  1:   bRequest
860    *  2,3: (LSB,MSB) wValue
861    *  4,5: (LSB,MSB) wIndex
862    *  6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */
863
864   /* Handle HID class specific requests */
865   if(((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) &&
866      ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
867     switch(usbp->setup[0] & USB_RTYPE_DIR_MASK) {
868     case USB_RTYPE_DIR_DEV2HOST:
869       switch(usbp->setup[1]) {   /* bRequest */
870       case HID_GET_REPORT:
871         switch(usbp->setup[4]) {     /* LSB(wIndex) (check MSB==0?) */
872         case KBD_INTERFACE:
873 #ifdef NKRO_ENABLE
874         case NKRO_INTERFACE:
875 #endif /* NKRO_ENABLE */
876           usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
877           return TRUE;
878           break;
879
880 #ifdef MOUSE_ENABLE
881         case MOUSE_INTERFACE:
882           usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
883           return TRUE;
884           break;
885 #endif /* MOUSE_ENABLE */
886
887 #ifdef CONSOLE_ENABLE
888         case CONSOLE_INTERFACE:
889           usbSetupTransfer(usbp, console_queue_buffer, CONSOLE_EPSIZE, NULL);
890           return TRUE;
891           break;
892 #endif /* CONSOLE_ENABLE */
893
894 #ifdef EXTRAKEY_ENABLE
895         case EXTRA_INTERFACE:
896           if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
897             switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
898               case REPORT_ID_SYSTEM:
899                 extra_report_blank[0] = REPORT_ID_SYSTEM;
900                 usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
901                 return TRUE;
902                 break;
903               case REPORT_ID_CONSUMER:
904                 extra_report_blank[0] = REPORT_ID_CONSUMER;
905                 usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
906                 return TRUE;
907                 break;
908               default:
909                 return FALSE;
910             }
911           } else {
912             return FALSE;
913           }
914           break;
915 #endif /* EXTRAKEY_ENABLE */
916
917         default:
918           usbSetupTransfer(usbp, NULL, 0, NULL);
919           return TRUE;
920           break;
921         }
922         break;
923
924       case HID_GET_PROTOCOL:
925         if((usbp->setup[4] == KBD_INTERFACE) && (usbp->setup[5] == 0)) {   /* wIndex */
926           usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
927           return TRUE;
928         }
929         break;
930
931       case HID_GET_IDLE:
932         usbSetupTransfer(usbp, &keyboard_idle, 1, NULL);
933         return TRUE;
934         break;
935       }
936       break;
937
938     case USB_RTYPE_DIR_HOST2DEV:
939       switch(usbp->setup[1]) {   /* bRequest */
940       case HID_SET_REPORT:
941         switch(usbp->setup[4]) {       /* LSB(wIndex) (check MSB==0 and wLength==1?) */
942         case KBD_INTERFACE:
943 #ifdef NKRO_ENABLE
944         case NKRO_INTERFACE:
945 #endif  /* NKRO_ENABLE */
946         /* keyboard_led_stats = <read byte from next OUT report>
947          * keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */
948           usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
949           return TRUE;
950           break;
951         }
952         break;
953
954       case HID_SET_PROTOCOL:
955         if((usbp->setup[4] == KBD_INTERFACE) && (usbp->setup[5] == 0)) {   /* wIndex */
956           keyboard_protocol = ((usbp->setup[2]) != 0x00);   /* LSB(wValue) */
957 #ifdef NKRO_ENABLE
958           keymap_config.nkro = !!keyboard_protocol;
959           if(!keymap_config.nkro && keyboard_idle) {
960 #else /* NKRO_ENABLE */
961           if(keyboard_idle) {
962 #endif /* NKRO_ENABLE */
963           /* arm the idle timer if boot protocol & idle */
964             osalSysLockFromISR();
965             chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
966             osalSysUnlockFromISR();
967           }
968         }
969         usbSetupTransfer(usbp, NULL, 0, NULL);
970         return TRUE;
971         break;
972
973       case HID_SET_IDLE:
974         keyboard_idle = usbp->setup[3];     /* MSB(wValue) */
975         /* arm the timer */
976 #ifdef NKRO_ENABLE
977         if(!keymap_config.nkro && keyboard_idle) {
978 #else /* NKRO_ENABLE */
979         if(keyboard_idle) {
980 #endif /* NKRO_ENABLE */
981           osalSysLockFromISR();
982           chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
983           osalSysUnlockFromISR();
984         }
985         usbSetupTransfer(usbp, NULL, 0, NULL);
986         return TRUE;
987         break;
988       }
989       break;
990     }
991   }
992
993   /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */
994   if((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) {
995     dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4]));
996     if(dp == NULL)
997       return FALSE;
998     usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
999     return TRUE;
1000   }
1001
1002   return FALSE;
1003 }
1004
1005 /* Start-of-frame callback */
1006 static void usb_sof_cb(USBDriver *usbp) {
1007   kbd_sof_cb(usbp);
1008 }
1009
1010
1011 /* USB driver configuration */
1012 static const USBConfig usbcfg = {
1013   usb_event_cb,                 /* USB events callback */
1014   usb_get_descriptor_cb,        /* Device GET_DESCRIPTOR request callback */
1015   usb_request_hook_cb,          /* Requests hook callback */
1016   usb_sof_cb                    /* Start Of Frame callback */
1017 };
1018
1019 /*
1020  * Initialize the USB driver
1021  */
1022 void init_usb_driver(USBDriver *usbp) {
1023   /*
1024    * Activates the USB driver and then the USB bus pull-up on D+.
1025    * Note, a delay is inserted in order to not have to disconnect the cable
1026    * after a reset.
1027    */
1028   usbDisconnectBus(usbp);
1029   wait_ms(1500);
1030   usbStart(usbp, &usbcfg);
1031   usbConnectBus(usbp);
1032
1033   chVTObjectInit(&keyboard_idle_timer);
1034 #ifdef CONSOLE_ENABLE
1035   obqObjectInit(&console_buf_queue, console_queue_buffer, CONSOLE_EPSIZE, CONSOLE_QUEUE_CAPACITY, console_queue_onotify, (void*)usbp);
1036   chVTObjectInit(&console_flush_timer);
1037 #endif
1038 }
1039
1040 /*
1041  * Send remote wakeup packet
1042  * Note: should not be called from ISR
1043  */
1044 void send_remote_wakeup(USBDriver *usbp) {
1045   (void)usbp;
1046 #if defined(K20x) || defined(KL2x)
1047 #if KINETIS_USB_USE_USB0
1048   USB0->CTL |= USBx_CTL_RESUME;
1049   wait_ms(15);
1050   USB0->CTL &= ~USBx_CTL_RESUME;
1051 #endif /* KINETIS_USB_USE_USB0 */
1052 #elif defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) /* End K20x || KL2x */
1053   STM32_USB->CNTR |= CNTR_RESUME;
1054   wait_ms(15);
1055   STM32_USB->CNTR &= ~CNTR_RESUME;
1056 #else /* End STM32F0XX || STM32F1XX || STM32F3XX */
1057 #warning Sending remote wakeup packet not implemented for your platform.
1058 #endif
1059 }
1060
1061 /* ---------------------------------------------------------
1062  *                  Keyboard functions
1063  * ---------------------------------------------------------
1064  */
1065
1066 /* keyboard IN callback hander (a kbd report has made it IN) */
1067 void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
1068   /* STUB */
1069   (void)usbp;
1070   (void)ep;
1071 }
1072
1073 #ifdef NKRO_ENABLE
1074 /* nkro IN callback hander (a nkro report has made it IN) */
1075 void nkro_in_cb(USBDriver *usbp, usbep_t ep) {
1076   /* STUB */
1077   (void)usbp;
1078   (void)ep;
1079 }
1080 #endif /* NKRO_ENABLE */
1081
1082 /* start-of-frame handler
1083  * TODO: i guess it would be better to re-implement using timers,
1084  *  so that this is not going to have to be checked every 1ms */
1085 void kbd_sof_cb(USBDriver *usbp) {
1086   (void)usbp;
1087 }
1088
1089 /* Idle requests timer code
1090  * callback (called from ISR, unlocked state) */
1091 static void keyboard_idle_timer_cb(void *arg) {
1092   USBDriver *usbp = (USBDriver *)arg;
1093
1094   osalSysLockFromISR();
1095
1096   /* check that the states of things are as they're supposed to */
1097   if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
1098     /* do not rearm the timer, should be enabled on IDLE request */
1099     osalSysUnlockFromISR();
1100     return;
1101   }
1102
1103 #ifdef NKRO_ENABLE
1104   if(!keymap_config.nkro && keyboard_idle) {
1105 #else /* NKRO_ENABLE */
1106   if(keyboard_idle) {
1107 #endif /* NKRO_ENABLE */
1108     /* TODO: are we sure we want the KBD_ENDPOINT? */
1109     if(!usbGetTransmitStatusI(usbp, KBD_ENDPOINT)) {
1110       usbStartTransmitI(usbp, KBD_ENDPOINT, (uint8_t *)&keyboard_report_sent, KBD_EPSIZE);
1111     }
1112     /* rearm the timer */
1113     chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
1114   }
1115
1116   /* do not rearm the timer if the condition above fails
1117    * it should be enabled again on either IDLE or SET_PROTOCOL requests */
1118   osalSysUnlockFromISR();
1119 }
1120
1121 /* LED status */
1122 uint8_t keyboard_leds(void) {
1123   return (uint8_t)(keyboard_led_stats & 0xFF);
1124 }
1125
1126 /* prepare and start sending a report IN
1127  * not callable from ISR or locked state */
1128 void send_keyboard(report_keyboard_t *report) {
1129   osalSysLock();
1130   if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
1131     osalSysUnlock();
1132     return;
1133   }
1134   osalSysUnlock();
1135
1136 #ifdef NKRO_ENABLE
1137   if(keymap_config.nkro) {  /* NKRO protocol */
1138     /* need to wait until the previous packet has made it through */
1139     /* can rewrite this using the synchronous API, then would wait
1140      * until *after* the packet has been transmitted. I think
1141      * this is more efficient */
1142     /* busy wait, should be short and not very common */
1143     osalSysLock();
1144     if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_ENDPOINT)) {
1145       /* Need to either suspend, or loop and call unlock/lock during
1146        * every iteration - otherwise the system will remain locked,
1147        * no interrupts served, so USB not going through as well.
1148        * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
1149       osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_ENDPOINT]->in_state->thread);
1150     }
1151     usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
1152     osalSysUnlock();
1153   } else
1154 #endif /* NKRO_ENABLE */
1155   { /* boot protocol */
1156     /* need to wait until the previous packet has made it through */
1157     /* busy wait, should be short and not very common */
1158     osalSysLock();
1159     if(usbGetTransmitStatusI(&USB_DRIVER, KBD_ENDPOINT)) {
1160       /* Need to either suspend, or loop and call unlock/lock during
1161        * every iteration - otherwise the system will remain locked,
1162        * no interrupts served, so USB not going through as well.
1163        * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
1164       osalThreadSuspendS(&(&USB_DRIVER)->epc[KBD_ENDPOINT]->in_state->thread);
1165     }
1166     usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE);
1167     osalSysUnlock();
1168   }
1169   keyboard_report_sent = *report;
1170 }
1171
1172 /* ---------------------------------------------------------
1173  *                     Mouse functions
1174  * ---------------------------------------------------------
1175  */
1176
1177 #ifdef MOUSE_ENABLE
1178
1179 /* mouse IN callback hander (a mouse report has made it IN) */
1180 void mouse_in_cb(USBDriver *usbp, usbep_t ep) {
1181   (void)usbp;
1182   (void)ep;
1183 }
1184
1185 void send_mouse(report_mouse_t *report) {
1186   osalSysLock();
1187   if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
1188     osalSysUnlock();
1189     return;
1190   }
1191   osalSysUnlock();
1192
1193   /* TODO: LUFA manually waits for the endpoint to become ready
1194    * for about 10ms for mouse, kbd, system; 1ms for nkro
1195    * is this really needed?
1196    */
1197
1198   osalSysLock();
1199   usbStartTransmitI(&USB_DRIVER, MOUSE_ENDPOINT, (uint8_t *)report, sizeof(report_mouse_t));
1200   osalSysUnlock();
1201 }
1202
1203 #else /* MOUSE_ENABLE */
1204 void send_mouse(report_mouse_t *report) {
1205   (void)report;
1206 }
1207 #endif /* MOUSE_ENABLE */
1208
1209 /* ---------------------------------------------------------
1210  *                   Extrakey functions
1211  * ---------------------------------------------------------
1212  */
1213
1214 #ifdef EXTRAKEY_ENABLE
1215
1216 /* extrakey IN callback hander */
1217 void extra_in_cb(USBDriver *usbp, usbep_t ep) {
1218   /* STUB */
1219   (void)usbp;
1220   (void)ep;
1221 }
1222
1223 static void send_extra_report(uint8_t report_id, uint16_t data) {
1224   osalSysLock();
1225   if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
1226     osalSysUnlock();
1227     return;
1228   }
1229
1230   report_extra_t report = {
1231     .report_id = report_id,
1232     .usage = data
1233   };
1234
1235   usbStartTransmitI(&USB_DRIVER, EXTRA_ENDPOINT, (uint8_t *)&report, sizeof(report_extra_t));
1236   osalSysUnlock();
1237 }
1238
1239 void send_system(uint16_t data) {
1240   send_extra_report(REPORT_ID_SYSTEM, data);
1241 }
1242
1243 void send_consumer(uint16_t data) {
1244   send_extra_report(REPORT_ID_CONSUMER, data);
1245 }
1246
1247 #else /* EXTRAKEY_ENABLE */
1248 void send_system(uint16_t data) {
1249   (void)data;
1250 }
1251 void send_consumer(uint16_t data) {
1252   (void)data;
1253 }
1254 #endif /* EXTRAKEY_ENABLE */
1255
1256 /* ---------------------------------------------------------
1257  *                   Console functions
1258  * ---------------------------------------------------------
1259  */
1260
1261 #ifdef CONSOLE_ENABLE
1262
1263 /* console IN callback hander */
1264 void console_in_cb(USBDriver *usbp, usbep_t ep) {
1265   (void)ep; /* should have ep == CONSOLE_ENDPOINT, so use that to save time/space */
1266   uint8_t *buf;
1267   size_t n;
1268
1269   osalSysLockFromISR();
1270
1271   /* rearm the timer */
1272   chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
1273
1274   /* Freeing the buffer just transmitted, if it was not a zero size packet.*/
1275   if (usbp->epc[CONSOLE_ENDPOINT]->in_state->txsize > 0U) {
1276     obqReleaseEmptyBufferI(&console_buf_queue);
1277   }
1278
1279   /* Checking if there is a buffer ready for transmission.*/
1280   buf = obqGetFullBufferI(&console_buf_queue, &n);
1281
1282   if (buf != NULL) {
1283     /* The endpoint cannot be busy, we are in the context of the callback,
1284        so it is safe to transmit without a check.*/
1285     /* Should have n == CONSOLE_EPSIZE; check it? */
1286     usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
1287   } else {
1288     /* Nothing to transmit.*/
1289   }
1290
1291   osalSysUnlockFromISR();
1292 }
1293
1294 /* Callback when data is inserted into the output queue
1295  * Called from a locked state */
1296 void console_queue_onotify(io_buffers_queue_t *bqp) {
1297   size_t n;
1298   USBDriver *usbp = bqGetLinkX(bqp);
1299
1300   if(usbGetDriverStateI(usbp) != USB_ACTIVE)
1301     return;
1302
1303   /* Checking if there is already a transaction ongoing on the endpoint.*/
1304   if (!usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) {
1305     /* Trying to get a full buffer.*/
1306     uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n);
1307     if (buf != NULL) {
1308       /* Buffer found, starting a new transaction.*/
1309       /* Should have n == CONSOLE_EPSIZE; check this? */
1310       usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
1311     }
1312   }
1313 }
1314
1315 /* Flush timer code
1316  * callback (called from ISR, unlocked state) */
1317 static void console_flush_cb(void *arg) {
1318   USBDriver *usbp = (USBDriver *)arg;
1319   osalSysLockFromISR();
1320
1321   /* check that the states of things are as they're supposed to */
1322   if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
1323     /* rearm the timer */
1324     chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
1325     osalSysUnlockFromISR();
1326     return;
1327   }
1328
1329   /* If there is already a transaction ongoing then another one cannot be
1330      started.*/
1331   if (usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) {
1332     /* rearm the timer */
1333     chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
1334     osalSysUnlockFromISR();
1335     return;
1336   }
1337
1338   /* Checking if there only a buffer partially filled, if so then it is
1339      enforced in the queue and transmitted.*/
1340   if(obqTryFlushI(&console_buf_queue)) {
1341     size_t n,i;
1342     uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n);
1343
1344     osalDbgAssert(buf != NULL, "queue is empty");
1345
1346     /* zero the rest of the buffer (buf should point to allocated space) */
1347     for(i=n; i<CONSOLE_EPSIZE; i++)
1348       buf[i]=0;
1349     usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
1350   }
1351
1352   /* rearm the timer */
1353   chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
1354   osalSysUnlockFromISR();
1355 }
1356
1357
1358 int8_t sendchar(uint8_t c) {
1359   osalSysLock();
1360   if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
1361     osalSysUnlock();
1362     return 0;
1363   }
1364   osalSysUnlock();
1365   /* Timeout after 100us if the queue is full.
1366    * Increase this timeout if too much stuff is getting
1367    * dropped (i.e. the buffer is getting full too fast
1368    * for USB/HIDRAW to dequeue). Another possibility
1369    * for fixing this kind of thing is to increase
1370    * CONSOLE_QUEUE_CAPACITY. */
1371   return(obqPutTimeout(&console_buf_queue, c, US2ST(100)));
1372 }
1373
1374 #else /* CONSOLE_ENABLE */
1375 int8_t sendchar(uint8_t c) {
1376   (void)c;
1377   return 0;
1378 }
1379 #endif /* CONSOLE_ENABLE */
1380
1381 void sendchar_pf(void *p, char c) {
1382   (void)p;
1383   sendchar((uint8_t)c);
1384 }