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