]> git.donarmstrong.com Git - tmk_firmware.git/blob - protocol/pjrc/usb.c
Fix USB Descriptors
[tmk_firmware.git] / protocol / pjrc / usb.c
1 /* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
2  * http://www.pjrc.com/teensy/usb_keyboard.html
3  * Copyright (c) 2009 PJRC.COM, LLC
4  * 
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  * 
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  * 
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21  * THE SOFTWARE.
22  */
23
24 #include <stdint.h>
25 #include <stdbool.h>
26 #include <avr/io.h>
27 #include <avr/pgmspace.h>
28 #include <avr/interrupt.h>
29 #include "usb.h"
30 #include "usb_keyboard.h"
31 #include "usb_mouse.h"
32 #include "usb_debug.h"
33 #include "usb_extra.h"
34 #include "led.h"
35 #include "print.h"
36 #include "util.h"
37 #include "sleep_led.h"
38 #include "suspend.h"
39
40
41 /**************************************************************************
42  *
43  *  Configurable Options
44  *
45  **************************************************************************/
46
47 // You can change these to give your code its own name.
48 #ifndef MANUFACTURER
49 #   define STR_MANUFACTURER     L"t.m.k."
50 #else
51 #   define STR_MANUFACTURER     LSTR(MANUFACTURER)
52 #endif
53 #ifndef PRODUCT
54 #   define STR_PRODUCT          L"t.m.k. keyboard"
55 #else
56 #   define STR_PRODUCT          LSTR(PRODUCT)
57 #endif
58
59
60 // Mac OS-X and Linux automatically load the correct drivers.  On
61 // Windows, even though the driver is supplied by Microsoft, an
62 // INF file is needed to load the driver.  These numbers need to
63 // match the INF file.
64 #ifndef VENDOR_ID
65 #   define VENDOR_ID            0xFEED
66 #endif
67
68 #ifndef PRODUCT_ID
69 #   define PRODUCT_ID           0xBABE
70 #endif
71
72 #ifndef DEVICE_VER
73 #   define DEVICE_VER           0x0100
74 #endif
75
76
77 // USB devices are supposed to implment a halt feature, which is
78 // rarely (if ever) used.  If you comment this line out, the halt
79 // code will be removed, saving 102 bytes of space (gcc 4.3.0).
80 // This is not strictly USB compliant, but works with all major
81 // operating systems.
82 #define SUPPORT_ENDPOINT_HALT
83
84
85
86 /**************************************************************************
87  *
88  *  Endpoint Buffer Configuration
89  *
90  **************************************************************************/
91
92 #define ENDPOINT0_SIZE          32
93
94 bool remote_wakeup = false;
95 bool suspend = false;
96
97 // 0:control endpoint is enabled automatically by controller.
98 static const uint8_t PROGMEM endpoint_config_table[] = {
99         // enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation)
100         1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(KBD_SIZE)      | KBD_BUFFER,      // 1
101 #ifdef MOUSE_ENABLE
102         1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(MOUSE_SIZE)    | MOUSE_BUFFER,    // 2
103 #else
104         0,                                                                  // 2
105 #endif
106 #ifdef CONSOLE_ENABLE
107         1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3
108 #else
109         0,
110 #endif
111 #ifdef EXTRAKEY_ENABLE
112         1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(EXTRA_SIZE)    | EXTRA_BUFFER,    // 4
113 #else
114         0,                                                                  // 4
115 #endif
116 #ifdef NKRO_ENABLE
117         1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(KBD2_SIZE)     | KBD2_BUFFER,     // 5
118 #else
119         0,                                                                  // 5
120 #endif
121         0,                                                                  // 6
122 };
123
124
125 /**************************************************************************
126  *
127  *  Descriptor Data
128  *
129  **************************************************************************/
130
131 // Descriptors are the data that your computer reads when it auto-detects
132 // this USB device (called "enumeration" in USB lingo).  The most commonly
133 // changed items are editable at the top of this file.  Changing things
134 // in here should only be done by those who've read chapter 9 of the USB
135 // spec and relevant portions of any USB class specifications!
136
137
138 static const uint8_t PROGMEM device_descriptor[] = {
139         18,                                     // bLength
140         1,                                      // bDescriptorType
141         0x00, 0x02,                             // bcdUSB
142         0,                                      // bDeviceClass
143         0,                                      // bDeviceSubClass
144         0,                                      // bDeviceProtocol
145         ENDPOINT0_SIZE,                         // bMaxPacketSize0
146         LSB(VENDOR_ID), MSB(VENDOR_ID),         // idVendor
147         LSB(PRODUCT_ID), MSB(PRODUCT_ID),       // idProduct
148         LSB(DEVICE_VER), MSB(DEVICE_VER),       // bcdDevice
149         1,                                      // iManufacturer
150         2,                                      // iProduct
151         0,                                      // iSerialNumber
152         1                                       // bNumConfigurations
153 };
154
155 // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
156 static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
157         0x05, 0x01,          // Usage Page (Generic Desktop),
158         0x09, 0x06,          // Usage (Keyboard),
159         0xA1, 0x01,          // Collection (Application),
160         0x75, 0x01,          //   Report Size (1),
161         0x95, 0x08,          //   Report Count (8),
162         0x05, 0x07,          //   Usage Page (Key Codes),
163         0x19, 0xE0,          //   Usage Minimum (224),
164         0x29, 0xE7,          //   Usage Maximum (231),
165         0x15, 0x00,          //   Logical Minimum (0),
166         0x25, 0x01,          //   Logical Maximum (1),
167         0x81, 0x02,          //   Input (Data, Variable, Absolute), ;Modifier byte
168         0x95, 0x01,          //   Report Count (1),
169         0x75, 0x08,          //   Report Size (8),
170         0x81, 0x03,          //   Input (Constant),                 ;Reserved byte
171         0x95, 0x05,          //   Report Count (5),
172         0x75, 0x01,          //   Report Size (1),
173         0x05, 0x08,          //   Usage Page (LEDs),
174         0x19, 0x01,          //   Usage Minimum (1),
175         0x29, 0x05,          //   Usage Maximum (5),
176         0x91, 0x02,          //   Output (Data, Variable, Absolute), ;LED report
177         0x95, 0x01,          //   Report Count (1),
178         0x75, 0x03,          //   Report Size (3),
179         0x91, 0x03,          //   Output (Constant),                 ;LED report padding
180         0x95, KBD_REPORT_KEYS,    //   Report Count (),
181         0x75, 0x08,          //   Report Size (8),
182         0x15, 0x00,          //   Logical Minimum (0),
183         0x25, 0xFF,          //   Logical Maximum(255),
184         0x05, 0x07,          //   Usage Page (Key Codes),
185         0x19, 0x00,          //   Usage Minimum (0),
186         0x29, 0xFF,          //   Usage Maximum (255),
187         0x81, 0x00,          //   Input (Data, Array),
188         0xc0                 // End Collection
189 };
190 #ifdef NKRO_ENABLE
191 static const uint8_t PROGMEM keyboard2_hid_report_desc[] = {
192         0x05, 0x01,                     // Usage Page (Generic Desktop),
193         0x09, 0x06,                     // Usage (Keyboard),
194         0xA1, 0x01,                     // Collection (Application),
195         // bitmap of modifiers
196         0x75, 0x01,                     //   Report Size (1),
197         0x95, 0x08,                     //   Report Count (8),
198         0x05, 0x07,                     //   Usage Page (Key Codes),
199         0x19, 0xE0,                     //   Usage Minimum (224),
200         0x29, 0xE7,                     //   Usage Maximum (231),
201         0x15, 0x00,                     //   Logical Minimum (0),
202         0x25, 0x01,                     //   Logical Maximum (1),
203         0x81, 0x02,                     //   Input (Data, Variable, Absolute), ;Modifier byte
204         // LED output report
205         0x95, 0x05,                     //   Report Count (5),
206         0x75, 0x01,                     //   Report Size (1),
207         0x05, 0x08,                     //   Usage Page (LEDs),
208         0x19, 0x01,                     //   Usage Minimum (1),
209         0x29, 0x05,                     //   Usage Maximum (5),
210         0x91, 0x02,                     //   Output (Data, Variable, Absolute),
211         0x95, 0x01,                     //   Report Count (1),
212         0x75, 0x03,                     //   Report Size (3),
213         0x91, 0x03,                     //   Output (Constant),
214         // bitmap of keys
215         0x95, KBD2_REPORT_KEYS*8,       //   Report Count (),
216         0x75, 0x01,                     //   Report Size (1),
217         0x15, 0x00,                     //   Logical Minimum (0),
218         0x25, 0x01,                     //   Logical Maximum(1),
219         0x05, 0x07,                     //   Usage Page (Key Codes),
220         0x19, 0x00,                     //   Usage Minimum (0),
221         0x29, KBD2_REPORT_KEYS*8-1,     //   Usage Maximum (),
222         0x81, 0x02,                     //   Input (Data, Variable, Absolute),
223         0xc0                            // End Collection
224 };
225 #endif
226
227 #ifdef MOUSE_ENABLE
228 // Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
229 // http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
230 // http://www.keil.com/forum/15671/
231 // http://www.microsoft.com/whdc/device/input/wheel.mspx
232 static const uint8_t PROGMEM mouse_hid_report_desc[] = {
233     /* mouse */
234     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
235     0x09, 0x02,                    // USAGE (Mouse)
236     0xa1, 0x01,                    // COLLECTION (Application)
237     //0x85, REPORT_ID_MOUSE,         //   REPORT_ID (1)
238     0x09, 0x01,                    //   USAGE (Pointer)
239     0xa1, 0x00,                    //   COLLECTION (Physical)
240                                    // ----------------------------  Buttons
241     0x05, 0x09,                    //     USAGE_PAGE (Button)
242     0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
243     0x29, 0x05,                    //     USAGE_MAXIMUM (Button 5)
244     0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
245     0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
246     0x75, 0x01,                    //     REPORT_SIZE (1)
247     0x95, 0x05,                    //     REPORT_COUNT (5)
248     0x81, 0x02,                    //     INPUT (Data,Var,Abs)
249     0x75, 0x03,                    //     REPORT_SIZE (3)
250     0x95, 0x01,                    //     REPORT_COUNT (1)
251     0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
252                                    // ----------------------------  X,Y position
253     0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
254     0x09, 0x30,                    //     USAGE (X)
255     0x09, 0x31,                    //     USAGE (Y)
256     0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
257     0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
258     0x75, 0x08,                    //     REPORT_SIZE (8)
259     0x95, 0x02,                    //     REPORT_COUNT (2)
260     0x81, 0x06,                    //     INPUT (Data,Var,Rel)
261                                    // ----------------------------  Vertical wheel
262     0x09, 0x38,                    //     USAGE (Wheel)
263     0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
264     0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
265     0x35, 0x00,                    //     PHYSICAL_MINIMUM (0)        - reset physical
266     0x45, 0x00,                    //     PHYSICAL_MAXIMUM (0)
267     0x75, 0x08,                    //     REPORT_SIZE (8)
268     0x95, 0x01,                    //     REPORT_COUNT (1)
269     0x81, 0x06,                    //     INPUT (Data,Var,Rel)
270                                    // ----------------------------  Horizontal wheel
271     0x05, 0x0c,                    //     USAGE_PAGE (Consumer Devices)
272     0x0a, 0x38, 0x02,              //     USAGE (AC Pan)
273     0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
274     0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
275     0x75, 0x08,                    //     REPORT_SIZE (8)
276     0x95, 0x01,                    //     REPORT_COUNT (1)
277     0x81, 0x06,                    //     INPUT (Data,Var,Rel)
278     0xc0,                          //   END_COLLECTION
279     0xc0,                          // END_COLLECTION
280 };
281 #endif
282
283 static const uint8_t PROGMEM debug_hid_report_desc[] = {
284         0x06, 0x31, 0xFF,                       // Usage Page 0xFF31 (vendor defined)
285         0x09, 0x74,                             // Usage 0x74
286         0xA1, 0x53,                             // Collection 0x53
287         0x75, 0x08,                             // report size = 8 bits
288         0x15, 0x00,                             // logical minimum = 0
289         0x26, 0xFF, 0x00,                       // logical maximum = 255
290         0x95, DEBUG_TX_SIZE,                    // report count
291         0x09, 0x75,                             // usage
292         0x81, 0x02,                             // Input (array)
293         0xC0                                    // end collection
294 };
295
296 #ifdef EXTRAKEY_ENABLE
297 // audio controls & system controls
298 // http://www.microsoft.com/whdc/archive/w2kbd.mspx
299 static const uint8_t PROGMEM extra_hid_report_desc[] = {
300     /* system control */
301     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
302     0x09, 0x80,                    // USAGE (System Control)
303     0xa1, 0x01,                    // COLLECTION (Application)
304     0x85, REPORT_ID_SYSTEM,        //   REPORT_ID (2)
305     0x15, 0x01,                    //   LOGICAL_MINIMUM (0x1)
306     0x25, 0xb7,                    //   LOGICAL_MAXIMUM (0xb7)
307     0x19, 0x01,                    //   USAGE_MINIMUM (0x1)
308     0x29, 0xb7,                    //   USAGE_MAXIMUM (0xb7)
309     0x75, 0x10,                    //   REPORT_SIZE (16)
310     0x95, 0x01,                    //   REPORT_COUNT (1)
311     0x81, 0x00,                    //   INPUT (Data,Array,Abs)
312     0xc0,                          // END_COLLECTION
313     /* consumer */
314     0x05, 0x0c,                    // USAGE_PAGE (Consumer Devices)
315     0x09, 0x01,                    // USAGE (Consumer Control)
316     0xa1, 0x01,                    // COLLECTION (Application)
317     0x85, REPORT_ID_CONSUMER,      //   REPORT_ID (3)
318     0x15, 0x01,                    //   LOGICAL_MINIMUM (0x1)
319     0x26, 0x9c, 0x02,              //   LOGICAL_MAXIMUM (0x29c)
320     0x19, 0x01,                    //   USAGE_MINIMUM (0x1)
321     0x2a, 0x9c, 0x02,              //   USAGE_MAXIMUM (0x29c)
322     0x75, 0x10,                    //   REPORT_SIZE (16)
323     0x95, 0x01,                    //   REPORT_COUNT (1)
324     0x81, 0x00,                    //   INPUT (Data,Array,Abs)
325     0xc0,                          // END_COLLECTION
326 };
327 #endif
328
329 #define KBD_HID_DESC_NUM                0
330 #define KBD_HID_DESC_OFFSET             (9+(9+9+7)*KBD_HID_DESC_NUM+9)
331
332 #ifdef MOUSE_ENABLE
333 #   define MOUSE_HID_DESC_NUM           (KBD_HID_DESC_NUM + 1)
334 #   define MOUSE_HID_DESC_OFFSET        (9+(9+9+7)*MOUSE_HID_DESC_NUM+9)
335 #else
336 #   define MOUSE_HID_DESC_NUM           (KBD_HID_DESC_NUM + 0)
337 #endif
338
339 #ifdef CONSOLE_ENABLE
340 #define DEBUG_HID_DESC_NUM              (MOUSE_HID_DESC_NUM + 1)
341 #define DEBUG_HID_DESC_OFFSET           (9+(9+9+7)*DEBUG_HID_DESC_NUM+9)
342 #else
343 #   define DEBUG_HID_DESC_NUM           (MOUSE_HID_DESC_NUM + 0)
344 #endif
345
346 #ifdef EXTRAKEY_ENABLE
347 #   define EXTRA_HID_DESC_NUM           (DEBUG_HID_DESC_NUM + 1)
348 #   define EXTRA_HID_DESC_OFFSET        (9+(9+9+7)*EXTRA_HID_DESC_NUM+9)
349 #else
350 #   define EXTRA_HID_DESC_NUM           (DEBUG_HID_DESC_NUM + 0)
351 #endif
352
353 #ifdef NKRO_ENABLE
354 #   define KBD2_HID_DESC_NUM            (EXTRA_HID_DESC_NUM + 1)
355 #   define KBD2_HID_DESC_OFFSET         (9+(9+9+7)*EXTRA_HID_DESC_NUM+9)
356 #else
357 #   define KBD2_HID_DESC_NUM            (EXTRA_HID_DESC_NUM + 0)
358 #endif
359
360 #define NUM_INTERFACES                  (KBD2_HID_DESC_NUM + 1)
361 #define CONFIG1_DESC_SIZE               (9+(9+9+7)*NUM_INTERFACES)
362 static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
363         // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
364         9,                                      // bLength;
365         2,                                      // bDescriptorType;
366         LSB(CONFIG1_DESC_SIZE),                 // wTotalLength
367         MSB(CONFIG1_DESC_SIZE),
368         NUM_INTERFACES,                         // bNumInterfaces
369         1,                                      // bConfigurationValue
370         0,                                      // iConfiguration
371         0xA0,                                   // bmAttributes
372         50,                                     // bMaxPower
373
374         // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
375         9,                                      // bLength
376         4,                                      // bDescriptorType
377         KBD_INTERFACE,                          // bInterfaceNumber
378         0,                                      // bAlternateSetting
379         1,                                      // bNumEndpoints
380         0x03,                                   // bInterfaceClass (0x03 = HID)
381         0x01,                                   // bInterfaceSubClass (0x01 = Boot)
382         0x01,                                   // bInterfaceProtocol (0x01 = Keyboard)
383         0,                                      // iInterface
384         // HID descriptor, HID 1.11 spec, section 6.2.1
385         9,                                      // bLength
386         0x21,                                   // bDescriptorType
387         0x11, 0x01,                             // bcdHID
388         0,                                      // bCountryCode
389         1,                                      // bNumDescriptors
390         0x22,                                   // bDescriptorType
391         sizeof(keyboard_hid_report_desc),       // wDescriptorLength
392         0,
393         // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
394         7,                                      // bLength
395         5,                                      // bDescriptorType
396         KBD_ENDPOINT | 0x80,                    // bEndpointAddress
397         0x03,                                   // bmAttributes (0x03=intr)
398         KBD_SIZE, 0,                            // wMaxPacketSize
399         10,                                     // bInterval
400
401 #ifdef MOUSE_ENABLE
402         // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
403         9,                                      // bLength
404         4,                                      // bDescriptorType
405         MOUSE_INTERFACE,                        // bInterfaceNumber
406         0,                                      // bAlternateSetting
407         1,                                      // bNumEndpoints
408         0x03,                                   // bInterfaceClass (0x03 = HID)
409         // ThinkPad T23 BIOS doesn't work with boot mouse.
410         0x00,                                   // bInterfaceSubClass (0x01 = Boot)
411         0x00,                                   // bInterfaceProtocol (0x02 = Mouse)
412 /*
413         0x01,                                   // bInterfaceSubClass (0x01 = Boot)
414         0x02,                                   // bInterfaceProtocol (0x02 = Mouse)
415 */
416         0,                                      // iInterface
417         // HID descriptor, HID 1.11 spec, section 6.2.1
418         9,                                      // bLength
419         0x21,                                   // bDescriptorType
420         0x11, 0x01,                             // bcdHID
421         0,                                      // bCountryCode
422         1,                                      // bNumDescriptors
423         0x22,                                   // bDescriptorType
424         sizeof(mouse_hid_report_desc),          // wDescriptorLength
425         0,
426         // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
427         7,                                      // bLength
428         5,                                      // bDescriptorType
429         MOUSE_ENDPOINT | 0x80,                  // bEndpointAddress
430         0x03,                                   // bmAttributes (0x03=intr)
431         MOUSE_SIZE, 0,                          // wMaxPacketSize
432         1,                                      // bInterval
433 #endif
434
435 #ifdef CONSOLE_ENABLE
436         // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
437         9,                                      // bLength
438         4,                                      // bDescriptorType
439         DEBUG_INTERFACE,                        // bInterfaceNumber
440         0,                                      // bAlternateSetting
441         1,                                      // bNumEndpoints
442         0x03,                                   // bInterfaceClass (0x03 = HID)
443         0x00,                                   // bInterfaceSubClass
444         0x00,                                   // bInterfaceProtocol
445         0,                                      // iInterface
446         // HID descriptor, HID 1.11 spec, section 6.2.1
447         9,                                      // bLength
448         0x21,                                   // bDescriptorType
449         0x11, 0x01,                             // bcdHID
450         0,                                      // bCountryCode
451         1,                                      // bNumDescriptors
452         0x22,                                   // bDescriptorType
453         sizeof(debug_hid_report_desc),          // wDescriptorLength
454         0,
455         // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
456         7,                                      // bLength
457         5,                                      // bDescriptorType
458         DEBUG_TX_ENDPOINT | 0x80,               // bEndpointAddress
459         0x03,                                   // bmAttributes (0x03=intr)
460         DEBUG_TX_SIZE, 0,                       // wMaxPacketSize
461         1,                                      // bInterval
462 #endif
463
464 #ifdef EXTRAKEY_ENABLE
465         // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
466         9,                                      // bLength
467         4,                                      // bDescriptorType
468         EXTRA_INTERFACE,                        // bInterfaceNumber
469         0,                                      // bAlternateSetting
470         1,                                      // bNumEndpoints
471         0x03,                                   // bInterfaceClass (0x03 = HID)
472         0x00,                                   // bInterfaceSubClass
473         0x00,                                   // bInterfaceProtocol
474         0,                                      // iInterface
475         // HID descriptor, HID 1.11 spec, section 6.2.1
476         9,                                      // bLength
477         0x21,                                   // bDescriptorType
478         0x11, 0x01,                             // bcdHID
479         0,                                      // bCountryCode
480         1,                                      // bNumDescriptors
481         0x22,                                   // bDescriptorType
482         sizeof(extra_hid_report_desc),          // wDescriptorLength
483         0,
484         // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
485         7,                                      // bLength
486         5,                                      // bDescriptorType
487         EXTRA_ENDPOINT | 0x80,                  // bEndpointAddress
488         0x03,                                   // bmAttributes (0x03=intr)
489         EXTRA_SIZE, 0,                          // wMaxPacketSize
490         10,                                     // bInterval
491 #endif
492
493 #ifdef NKRO_ENABLE
494         // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
495         9,                                      // bLength
496         4,                                      // bDescriptorType
497         KBD2_INTERFACE,                         // bInterfaceNumber
498         0,                                      // bAlternateSetting
499         1,                                      // bNumEndpoints
500         0x03,                                   // bInterfaceClass (0x03 = HID)
501         0x00,                                   // bInterfaceSubClass (0x01 = Boot)
502         0x00,                                   // bInterfaceProtocol (0x01 = Keyboard)
503         0,                                      // iInterface
504         // HID descriptor, HID 1.11 spec, section 6.2.1
505         9,                                      // bLength
506         0x21,                                   // bDescriptorType
507         0x11, 0x01,                             // bcdHID
508         0,                                      // bCountryCode
509         1,                                      // bNumDescriptors
510         0x22,                                   // bDescriptorType
511         sizeof(keyboard2_hid_report_desc),      // wDescriptorLength
512         0,
513         // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
514         7,                                      // bLength
515         5,                                      // bDescriptorType
516         KBD2_ENDPOINT | 0x80,                   // bEndpointAddress
517         0x03,                                   // bmAttributes (0x03=intr)
518         KBD2_SIZE, 0,                           // wMaxPacketSize
519         1,                                      // bInterval
520 #endif
521 };
522
523 // If you're desperate for a little extra code memory, these strings
524 // can be completely removed if iManufacturer, iProduct, iSerialNumber
525 // in the device desciptor are changed to zeros.
526 struct usb_string_descriptor_struct {
527         uint8_t bLength;
528         uint8_t bDescriptorType;
529         int16_t wString[];
530 };
531 static const struct usb_string_descriptor_struct PROGMEM string0 = {
532         4,
533         3,
534         {0x0409}
535 };
536 static const struct usb_string_descriptor_struct PROGMEM string1 = {
537         sizeof(STR_MANUFACTURER),
538         3,
539         STR_MANUFACTURER
540 };
541 static const struct usb_string_descriptor_struct PROGMEM string2 = {
542         sizeof(STR_PRODUCT),
543         3,
544         STR_PRODUCT
545 };
546
547 // This table defines which descriptor data is sent for each specific
548 // request from the host (in wValue and wIndex).
549 static const struct descriptor_list_struct {
550         uint16_t        wValue;     // descriptor type
551         uint16_t        wIndex;
552         const uint8_t   *addr;
553         uint8_t         length;
554 } PROGMEM descriptor_list[] = {
555         // DEVICE descriptor
556         {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
557         // CONFIGURATION descriptor
558         {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
559         // HID/REPORT descriptors
560         {0x2100, KBD_INTERFACE, config1_descriptor+KBD_HID_DESC_OFFSET, 9},
561         {0x2200, KBD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
562 #ifdef MOUSE_ENABLE
563         {0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9},
564         {0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)},
565 #endif
566 #ifdef CONSOLE_ENABLE
567         {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
568         {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
569 #endif
570 #ifdef EXTRAKEY_ENABLE
571         {0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9},
572         {0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)},
573 #endif
574 #ifdef NKRO_ENABLE
575         {0x2100, KBD2_INTERFACE, config1_descriptor+KBD2_HID_DESC_OFFSET, 9},
576         {0x2200, KBD2_INTERFACE, keyboard2_hid_report_desc, sizeof(keyboard2_hid_report_desc)},
577 #endif
578         // STRING descriptors
579         {0x0300, 0x0000, (const uint8_t *)&string0, 4},
580         {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
581         {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}
582 };
583 #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
584
585
586 /**************************************************************************
587  *
588  *  Variables - these are the only non-stack RAM usage
589  *
590  **************************************************************************/
591
592 // zero when we are not configured, non-zero when enumerated
593 static volatile uint8_t usb_configuration=0;
594
595
596 /**************************************************************************
597  *
598  *  Public Functions - these are the API intended for the user
599  *
600  **************************************************************************/
601
602
603 // initialize USB
604 void usb_init(void)
605 {
606         HW_CONFIG();
607         USB_FREEZE();                           // enable USB
608         PLL_CONFIG();                           // config PLL
609         while (!(PLLCSR & (1<<PLOCK))) ;        // wait for PLL lock
610         USB_CONFIG();                           // start USB clock
611         UDCON = 0;                              // enable attach resistor
612         usb_configuration = 0;
613         suspend = false;
614         UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE)|(1<<WAKEUPE);
615         sei();
616 }
617
618 // return 0 if the USB is not configured, or the configuration
619 // number selected by the HOST
620 uint8_t usb_configured(void)
621 {
622         return usb_configuration && !suspend;
623 }
624
625 void usb_remote_wakeup(void)
626 {
627     UDCON |= (1<<RMWKUP);
628 }
629
630
631
632 /**************************************************************************
633  *
634  *  Private Functions - not intended for general user consumption....
635  *
636  **************************************************************************/
637
638
639
640 // USB Device Interrupt - handle all device-level events
641 // the transmit buffer flushing is triggered by the start of frame
642 //
643 ISR(USB_GEN_vect)
644 {
645         uint8_t intbits, t;
646         static uint8_t div4=0;
647
648         intbits = UDINT;
649         UDINT = 0;
650         if ((intbits & (1<<SUSPI)) && (UDIEN & (1<<SUSPE)) && usb_configuration) {
651 #ifdef SLEEP_LED_ENABLE
652             sleep_led_enable();
653 #endif
654             UDIEN &= ~(1<<SUSPE);
655             UDIEN |= (1<<WAKEUPE);
656             suspend = true;
657         }
658         if ((intbits & (1<<WAKEUPI)) && (UDIEN & (1<<WAKEUPE)) && usb_configuration) {
659             suspend_wakeup_init();
660 #ifdef SLEEP_LED_ENABLE
661             sleep_led_disable();
662 #endif
663             led_set(host_keyboard_leds());
664
665             UDIEN |= (1<<SUSPE);
666             UDIEN &= ~(1<<WAKEUPE);
667             suspend = false;
668         }
669         if (intbits & (1<<EORSTI)) {
670                 UENUM = 0;
671                 UECONX = 1;
672                 UECFG0X = EP_TYPE_CONTROL;
673                 UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
674                 UEIENX = (1<<RXSTPE);
675                 usb_configuration = 0;
676         }
677         if ((intbits & (1<<SOFI)) && usb_configuration) {
678                 t = debug_flush_timer;
679                 if (t) {
680                         debug_flush_timer = -- t;
681                         if (!t) {
682                                 UENUM = DEBUG_TX_ENDPOINT;
683                                 while ((UEINTX & (1<<RWAL))) {
684                                         UEDATX = 0;
685                                 }
686                                 UEINTX = 0x3A;
687                         }
688                 }
689                 /* TODO: should keep IDLE rate on each keyboard interface */
690 #ifdef NKRO_ENABLE
691                 if (!keyboard_nkro && usb_keyboard_idle_config && (++div4 & 3) == 0) {
692 #else
693                 if (usb_keyboard_idle_config && (++div4 & 3) == 0) {
694 #endif
695                         UENUM = KBD_ENDPOINT;
696                         if (UEINTX & (1<<RWAL)) {
697                                 usb_keyboard_idle_count++;
698                                 if (usb_keyboard_idle_count == usb_keyboard_idle_config) {
699                                         usb_keyboard_idle_count = 0;
700                                         /* TODO: fix keyboard_report inconsistency */
701 /* To avoid Mac SET_IDLE behaviour.
702                                         UEDATX = keyboard_report_prev->mods;
703                                         UEDATX = 0;
704                                         uint8_t keys = usb_keyboard_protocol ? KBD_REPORT_KEYS : 6;
705                                         for (uint8_t i=0; i<keys; i++) {
706                                                 UEDATX = keyboard_report_prev->keys[i];
707                                         }
708                                         UEINTX = 0x3A;
709 */
710                                 }
711                         }
712                 }
713         }
714 }
715
716
717
718 // Misc functions to wait for ready and send/receive packets
719 static inline void usb_wait_in_ready(void)
720 {
721         while (!(UEINTX & (1<<TXINI))) ;
722 }
723 static inline void usb_send_in(void)
724 {
725         UEINTX = ~(1<<TXINI);
726 }
727 static inline void usb_wait_receive_out(void)
728 {
729         while (!(UEINTX & (1<<RXOUTI))) ;
730 }
731 static inline void usb_ack_out(void)
732 {
733         UEINTX = ~(1<<RXOUTI);
734 }
735
736
737
738 // USB Endpoint Interrupt - endpoint 0 is handled here.  The
739 // other endpoints are manipulated by the user-callable
740 // functions, and the start-of-frame interrupt.
741 //
742 ISR(USB_COM_vect)
743 {
744         uint8_t intbits;
745         const uint8_t *list;
746         const uint8_t *cfg;
747         uint8_t i, n, len, en;
748         uint8_t bmRequestType;
749         uint8_t bRequest;
750         uint16_t wValue;
751         uint16_t wIndex;
752         uint16_t wLength;
753         uint16_t desc_val;
754         const uint8_t *desc_addr;
755         uint8_t desc_length;
756
757         UENUM = 0;
758         intbits = UEINTX;
759         if (intbits & (1<<RXSTPI)) {
760                 bmRequestType = UEDATX;
761                 bRequest = UEDATX;
762                 wValue = UEDATX;
763                 wValue |= (UEDATX << 8);
764                 wIndex = UEDATX;
765                 wIndex |= (UEDATX << 8);
766                 wLength = UEDATX;
767                 wLength |= (UEDATX << 8);
768                 UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
769                 if (bRequest == GET_DESCRIPTOR) {
770                         list = (const uint8_t *)descriptor_list;
771                         for (i=0; ; i++) {
772                                 if (i >= NUM_DESC_LIST) {
773                                         UECONX = (1<<STALLRQ)|(1<<EPEN);  //stall
774                                         return;
775                                 }
776                                 desc_val = pgm_read_word(list);
777                                 if (desc_val != wValue) {
778                                         list += sizeof(struct descriptor_list_struct);
779                                         continue;
780                                 }
781                                 list += 2;
782                                 desc_val = pgm_read_word(list);
783                                 if (desc_val != wIndex) {
784                                         list += sizeof(struct descriptor_list_struct)-2;
785                                         continue;
786                                 }
787                                 list += 2;
788                                 desc_addr = (const uint8_t *)pgm_read_word(list);
789                                 list += 2;
790                                 desc_length = pgm_read_byte(list);
791                                 break;
792                         }
793                         len = (wLength < 256) ? wLength : 255;
794                         if (len > desc_length) len = desc_length;
795                         do {
796                                 // wait for host ready for IN packet
797                                 do {
798                                         i = UEINTX;
799                                 } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
800                                 if (i & (1<<RXOUTI)) return;    // abort
801                                 // send IN packet
802                                 n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
803                                 for (i = n; i; i--) {
804                                         UEDATX = pgm_read_byte(desc_addr++);
805                                 }
806                                 len -= n;
807                                 usb_send_in();
808                         } while (len || n == ENDPOINT0_SIZE);
809                         return;
810                 }
811                 if (bRequest == SET_ADDRESS) {
812                         usb_send_in();
813                         usb_wait_in_ready();
814                         UDADDR = wValue | (1<<ADDEN);
815                         return;
816                 }
817                 if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
818                         usb_configuration = wValue;
819                         usb_send_in();
820                         cfg = endpoint_config_table;
821                         for (i=1; i<=MAX_ENDPOINT; i++) {
822                                 UENUM = i;
823                                 en = pgm_read_byte(cfg++);
824                                 if (en) {
825                                     UECONX = (1<<EPEN);
826                                     UECFG0X = pgm_read_byte(cfg++);
827                                     UECFG1X = pgm_read_byte(cfg++);
828                                 } else {
829                                     UECONX = 0;
830                                 }
831                         }
832                         UERST = UERST_MASK;
833                         UERST = 0;
834                         return;
835                 }
836                 if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
837                         usb_wait_in_ready();
838                         UEDATX = usb_configuration;
839                         usb_send_in();
840                         return;
841                 }
842
843                 if (bRequest == GET_STATUS) {
844                         usb_wait_in_ready();
845                         i = 0;
846                         #ifdef SUPPORT_ENDPOINT_HALT
847                         if (bmRequestType == 0x82) {
848                                 UENUM = wIndex;
849                                 if (UECONX & (1<<STALLRQ)) i = 1;
850                                 UENUM = 0;
851                         }
852                         #endif
853                         UEDATX = i;
854                         UEDATX = 0;
855                         usb_send_in();
856                         return;
857                 }
858                 if (bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE) {
859 #ifdef SUPPORT_ENDPOINT_HALT
860                     if (bmRequestType == 0x02 && wValue == ENDPOINT_HALT) {
861                         i = wIndex & 0x7F;
862                         if (i >= 1 && i <= MAX_ENDPOINT) {
863                                 usb_send_in();
864                                 UENUM = i;
865                                 if (bRequest == SET_FEATURE) {
866                                         UECONX = (1<<STALLRQ)|(1<<EPEN);
867                                 } else {
868                                         UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
869                                         UERST = (1 << i);
870                                         UERST = 0;
871                                 }
872                                 return;
873                         }
874                     }
875 #endif
876                     if (bmRequestType == 0x00 && wValue == DEVICE_REMOTE_WAKEUP) {
877                         if (bRequest == SET_FEATURE) {
878                             remote_wakeup = true;   
879                         } else {
880                             remote_wakeup = false;
881                         }
882                         usb_send_in();
883                         return;
884                     }
885                 }
886                 if (wIndex == KBD_INTERFACE) {
887                         if (bmRequestType == 0xA1) {
888                                 if (bRequest == HID_GET_REPORT) {
889                                         usb_wait_in_ready();
890                                         UEDATX = keyboard_report->mods;
891                                         UEDATX = 0;
892                                         for (i=0; i<6; i++) {
893                                                 UEDATX = keyboard_report->keys[i];
894                                         }
895                                         usb_send_in();
896                                         return;
897                                 }
898                                 if (bRequest == HID_GET_IDLE) {
899                                         usb_wait_in_ready();
900                                         UEDATX = usb_keyboard_idle_config;
901                                         usb_send_in();
902                                         return;
903                                 }
904                                 if (bRequest == HID_GET_PROTOCOL) {
905                                         usb_wait_in_ready();
906                                         UEDATX = usb_keyboard_protocol;
907                                         usb_send_in();
908                                         return;
909                                 }
910                         }
911                         if (bmRequestType == 0x21) {
912                                 if (bRequest == HID_SET_REPORT) {
913                                         usb_wait_receive_out();
914                                         usb_keyboard_leds = UEDATX;
915                                         usb_ack_out();
916                                         usb_send_in();
917                                         return;
918                                 }
919                                 if (bRequest == HID_SET_IDLE) {
920                                         usb_keyboard_idle_config = (wValue >> 8);
921                                         usb_keyboard_idle_count = 0;
922                                         //usb_wait_in_ready();
923                                         usb_send_in();
924                                         return;
925                                 }
926                                 if (bRequest == HID_SET_PROTOCOL) {
927                                         usb_keyboard_protocol = wValue;
928                                         //usb_wait_in_ready();
929                                         usb_send_in();
930                                         return;
931                                 }
932                         }
933                 }
934 #ifdef MOUSE_ENABLE
935                 if (wIndex == MOUSE_INTERFACE) {
936                         if (bmRequestType == 0xA1) {
937                                 if (bRequest == HID_GET_REPORT) {
938                                     if (wValue == HID_REPORT_INPUT) {
939                                         usb_wait_in_ready();
940                                         UEDATX = 0;
941                                         UEDATX = 0;
942                                         UEDATX = 0;
943                                         UEDATX = 0;
944                                         usb_send_in();
945                                         return;
946                                     }
947                                     if (wValue == HID_REPORT_FEATURE) {
948                                         usb_wait_in_ready();
949                                         UEDATX = 0x05;
950                                         usb_send_in();
951                                         return;
952                                     }
953                                 }
954                                 if (bRequest == HID_GET_PROTOCOL) {
955                                         usb_wait_in_ready();
956                                         UEDATX = usb_mouse_protocol;
957                                         usb_send_in();
958                                         return;
959                                 }
960                         }
961                         if (bmRequestType == 0x21) {
962                                 if (bRequest == HID_SET_PROTOCOL) {
963                                         usb_mouse_protocol = wValue;
964                                         usb_send_in();
965                                         return;
966                                 }
967                         }
968                 }
969 #endif
970                 if (wIndex == DEBUG_INTERFACE) {
971                         if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
972                                 len = wLength;
973                                 do {
974                                         // wait for host ready for IN packet
975                                         do {
976                                                 i = UEINTX;
977                                         } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
978                                         if (i & (1<<RXOUTI)) return;    // abort
979                                         // send IN packet
980                                         n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
981                                         for (i = n; i; i--) {
982                                                 UEDATX = 0;
983                                         }
984                                         len -= n;
985                                         usb_send_in();
986                                 } while (len || n == ENDPOINT0_SIZE);
987                                 return;
988                         }
989                 }
990         }
991         UECONX = (1<<STALLRQ) | (1<<EPEN);      // stall
992 }