]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/usb_descriptor.c
cab344675245de8d1954409155ca975f60c02d6b
[qmk_firmware.git] / tmk_core / protocol / usb_descriptor.c
1 /*
2  * Copyright 2012 Jun Wako <wakojun@gmail.com>
3  * This file is based on:
4  *     LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
5  *     LUFA-120219/Demos/Device/Lowlevel/GenericHID
6  */
7
8 /*
9              LUFA Library
10      Copyright (C) Dean Camera, 2012.
11
12   dean [at] fourwalledcubicle [dot] com
13            www.lufa-lib.org
14 */
15
16 /*
17   Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com)
18   Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)
19
20   Permission to use, copy, modify, distribute, and sell this
21   software and its documentation for any purpose is hereby granted
22   without fee, provided that the above copyright notice appear in
23   all copies and that both that the copyright notice and this
24   permission notice and warranty disclaimer appear in supporting
25   documentation, and that the name of the author not be used in
26   advertising or publicity pertaining to distribution of the
27   software without specific, written prior permission.
28
29   The author disclaim all warranties with regard to this
30   software, including all implied warranties of merchantability
31   and fitness.  In no event shall the author be liable for any
32   special, indirect or consequential damages or any damages
33   whatsoever resulting from loss of use, data or profits, whether
34   in an action of contract, negligence or other tortious action,
35   arising out of or in connection with the use or performance of
36   this software.
37 */
38
39 #include "util.h"
40 #include "report.h"
41 #include "usb_descriptor.h"
42
43 #ifndef USB_MAX_POWER_CONSUMPTION
44 #define USB_MAX_POWER_CONSUMPTION 500
45 #endif
46
47 /*******************************************************************************
48  * HID Report Descriptors
49  ******************************************************************************/
50 const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
51 {
52     HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
53     HID_RI_USAGE(8, 0x06), /* Keyboard */
54     HID_RI_COLLECTION(8, 0x01), /* Application */
55         HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
56         HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
57         HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
58         HID_RI_LOGICAL_MINIMUM(8, 0x00),
59         HID_RI_LOGICAL_MAXIMUM(8, 0x01),
60         HID_RI_REPORT_COUNT(8, 0x08),
61         HID_RI_REPORT_SIZE(8, 0x01),
62         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
63
64         HID_RI_REPORT_COUNT(8, 0x01),
65         HID_RI_REPORT_SIZE(8, 0x08),
66         HID_RI_INPUT(8, HID_IOF_CONSTANT),  /* reserved */
67
68         HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
69         HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
70         HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
71         HID_RI_REPORT_COUNT(8, 0x05),
72         HID_RI_REPORT_SIZE(8, 0x01),
73         HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
74         HID_RI_REPORT_COUNT(8, 0x01),
75         HID_RI_REPORT_SIZE(8, 0x03),
76         HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
77
78         HID_RI_USAGE_PAGE(8, 0x07), /* Keyboard */
79         HID_RI_USAGE_MINIMUM(8, 0x00), /* Reserved (no event indicated) */
80         HID_RI_USAGE_MAXIMUM(8, 0xFF), /* Keyboard Application */
81         HID_RI_LOGICAL_MINIMUM(8, 0x00),
82         HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
83         HID_RI_REPORT_COUNT(8, 0x06),
84         HID_RI_REPORT_SIZE(8, 0x08),
85         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
86     HID_RI_END_COLLECTION(0),
87 };
88
89 #ifdef MOUSE_ENABLE
90 const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
91 {
92     HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
93     HID_RI_USAGE(8, 0x02), /* Mouse */
94     HID_RI_COLLECTION(8, 0x01), /* Application */
95         HID_RI_USAGE(8, 0x01), /* Pointer */
96         HID_RI_COLLECTION(8, 0x00), /* Physical */
97
98             HID_RI_USAGE_PAGE(8, 0x09), /* Button */
99             HID_RI_USAGE_MINIMUM(8, 0x01),  /* Button 1 */
100             HID_RI_USAGE_MAXIMUM(8, 0x05),  /* Button 5 */
101             HID_RI_LOGICAL_MINIMUM(8, 0x00),
102             HID_RI_LOGICAL_MAXIMUM(8, 0x01),
103             HID_RI_REPORT_COUNT(8, 0x05),
104             HID_RI_REPORT_SIZE(8, 0x01),
105             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
106             HID_RI_REPORT_COUNT(8, 0x01),
107             HID_RI_REPORT_SIZE(8, 0x03),
108             HID_RI_INPUT(8, HID_IOF_CONSTANT),
109
110             HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
111             HID_RI_USAGE(8, 0x30), /* Usage X */
112             HID_RI_USAGE(8, 0x31), /* Usage Y */
113             HID_RI_LOGICAL_MINIMUM(8, -127),
114             HID_RI_LOGICAL_MAXIMUM(8, 127),
115             HID_RI_REPORT_COUNT(8, 0x02),
116             HID_RI_REPORT_SIZE(8, 0x08),
117             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
118
119             HID_RI_USAGE(8, 0x38), /* Wheel */
120             HID_RI_LOGICAL_MINIMUM(8, -127),
121             HID_RI_LOGICAL_MAXIMUM(8, 127),
122             HID_RI_REPORT_COUNT(8, 0x01),
123             HID_RI_REPORT_SIZE(8, 0x08),
124             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
125
126             HID_RI_USAGE_PAGE(8, 0x0C), /* Consumer */
127             HID_RI_USAGE(16, 0x0238), /* AC Pan (Horizontal wheel) */
128             HID_RI_LOGICAL_MINIMUM(8, -127),
129             HID_RI_LOGICAL_MAXIMUM(8, 127),
130             HID_RI_REPORT_COUNT(8, 0x01),
131             HID_RI_REPORT_SIZE(8, 0x08),
132             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
133
134         HID_RI_END_COLLECTION(0),
135     HID_RI_END_COLLECTION(0),
136 };
137 #endif
138
139 #ifdef EXTRAKEY_ENABLE
140 const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] =
141 {
142     HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
143     HID_RI_USAGE(8, 0x80), /* System Control */
144     HID_RI_COLLECTION(8, 0x01), /* Application */
145         HID_RI_REPORT_ID(8, REPORT_ID_SYSTEM),
146         HID_RI_LOGICAL_MINIMUM(16, 0x0001),
147         HID_RI_LOGICAL_MAXIMUM(16, 0x0003),
148         HID_RI_USAGE_MINIMUM(16, 0x0081), /* System Power Down */
149         HID_RI_USAGE_MAXIMUM(16, 0x0083), /* System Wake Up */
150         HID_RI_REPORT_SIZE(8, 16),
151         HID_RI_REPORT_COUNT(8, 1),
152         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
153     HID_RI_END_COLLECTION(0),
154
155     HID_RI_USAGE_PAGE(8, 0x0C), /* Consumer */
156     HID_RI_USAGE(8, 0x01), /* Consumer Control */
157     HID_RI_COLLECTION(8, 0x01), /* Application */
158         HID_RI_REPORT_ID(8, REPORT_ID_CONSUMER),
159         HID_RI_LOGICAL_MINIMUM(16, 0x0001),
160         HID_RI_LOGICAL_MAXIMUM(16, 0x029C),
161         HID_RI_USAGE_MINIMUM(16, 0x0001), /* +10 */
162         HID_RI_USAGE_MAXIMUM(16, 0x029C), /* AC Distribute Vertically */
163         HID_RI_REPORT_SIZE(8, 16),
164         HID_RI_REPORT_COUNT(8, 1),
165         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
166     HID_RI_END_COLLECTION(0),
167 };
168 #endif
169
170 #ifdef RAW_ENABLE
171 const USB_Descriptor_HIDReport_Datatype_t PROGMEM RawReport[] =
172 {
173     HID_RI_USAGE_PAGE(16, 0xFF60), /* Vendor Page 0xFF60 */
174     HID_RI_USAGE(8, 0x61), /* Vendor Usage 0x61 */
175     HID_RI_COLLECTION(8, 0x01), /* Application */
176         HID_RI_USAGE(8, 0x62), /* Vendor Usage 0x62 */
177         HID_RI_LOGICAL_MINIMUM(8, 0x00),
178         HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
179         HID_RI_REPORT_COUNT(8, RAW_EPSIZE),
180         HID_RI_REPORT_SIZE(8, 0x08),
181         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
182         HID_RI_USAGE(8, 0x63), /* Vendor Usage 0x63 */
183         HID_RI_LOGICAL_MINIMUM(8, 0x00),
184         HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
185         HID_RI_REPORT_COUNT(8, RAW_EPSIZE),
186         HID_RI_REPORT_SIZE(8, 0x08),
187         HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
188     HID_RI_END_COLLECTION(0),
189 };
190 #endif
191
192 #ifdef CONSOLE_ENABLE
193 const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] =
194 {
195     HID_RI_USAGE_PAGE(16, 0xFF31), /* Vendor Page(PJRC Teensy compatible) */
196     HID_RI_USAGE(8, 0x74), /* Vendor Usage(PJRC Teensy compatible) */
197     HID_RI_COLLECTION(8, 0x01), /* Application */
198         HID_RI_USAGE(8, 0x75), /* Vendor Usage 0x75 */
199         HID_RI_LOGICAL_MINIMUM(8, 0x00),
200         HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
201         HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE),
202         HID_RI_REPORT_SIZE(8, 0x08),
203         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
204         HID_RI_USAGE(8, 0x76), /* Vendor Usage 0x76 */
205         HID_RI_LOGICAL_MINIMUM(8, 0x00),
206         HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
207         HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE),
208         HID_RI_REPORT_SIZE(8, 0x08),
209         HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
210     HID_RI_END_COLLECTION(0),
211 };
212 #endif
213
214 #ifdef NKRO_ENABLE
215 const USB_Descriptor_HIDReport_Datatype_t PROGMEM NKROReport[] =
216 {
217     HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
218     HID_RI_USAGE(8, 0x06), /* Keyboard */
219     HID_RI_COLLECTION(8, 0x01), /* Application */
220         HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
221         HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
222         HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
223         HID_RI_LOGICAL_MINIMUM(8, 0x00),
224         HID_RI_LOGICAL_MAXIMUM(8, 0x01),
225         HID_RI_REPORT_COUNT(8, 0x08),
226         HID_RI_REPORT_SIZE(8, 0x01),
227         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
228
229         HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
230         HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
231         HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
232         HID_RI_REPORT_COUNT(8, 0x05),
233         HID_RI_REPORT_SIZE(8, 0x01),
234         HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
235         HID_RI_REPORT_COUNT(8, 0x01),
236         HID_RI_REPORT_SIZE(8, 0x03),
237         HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
238
239         HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
240         HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
241         HID_RI_USAGE_MAXIMUM(8, (NKRO_EPSIZE-1)*8-1), /* Keyboard Right GUI */
242         HID_RI_LOGICAL_MINIMUM(8, 0x00),
243         HID_RI_LOGICAL_MAXIMUM(8, 0x01),
244         HID_RI_REPORT_COUNT(8, (NKRO_EPSIZE-1)*8),
245         HID_RI_REPORT_SIZE(8, 0x01),
246         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
247     HID_RI_END_COLLECTION(0),
248 };
249 #endif
250
251 /*******************************************************************************
252  * Device Descriptors
253  ******************************************************************************/
254 const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
255 {
256     .Header                 = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
257
258     .USBSpecification       = VERSION_BCD(1,1,0),
259 #if VIRTSER_ENABLE
260     .Class                  = USB_CSCP_IADDeviceClass,
261     .SubClass               = USB_CSCP_IADDeviceSubclass,
262     .Protocol               = USB_CSCP_IADDeviceProtocol,
263 #else
264     .Class                  = USB_CSCP_NoDeviceClass,
265     .SubClass               = USB_CSCP_NoDeviceSubclass,
266     .Protocol               = USB_CSCP_NoDeviceProtocol,
267 #endif
268
269     .Endpoint0Size          = FIXED_CONTROL_ENDPOINT_SIZE,
270
271     /* specified in config.h */
272     .VendorID               = VENDOR_ID,
273     .ProductID              = PRODUCT_ID,
274     .ReleaseNumber          = DEVICE_VER,
275
276     .ManufacturerStrIndex   = 0x01,
277     .ProductStrIndex        = 0x02,
278     .SerialNumStrIndex      = 0x03,
279
280     .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
281 };
282
283 /*******************************************************************************
284  * Configuration Descriptors
285  ******************************************************************************/
286 const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
287 {
288     .Config =
289         {
290             .Header                 = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
291
292             .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
293             .TotalInterfaces        = TOTAL_INTERFACES,
294
295             .ConfigurationNumber    = 1,
296             .ConfigurationStrIndex  = NO_DESCRIPTOR,
297
298             .ConfigAttributes       = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP),
299
300             .MaxPowerConsumption    = USB_CONFIG_POWER_MA(USB_MAX_POWER_CONSUMPTION)
301         },
302
303     /*
304      * Keyboard
305      */
306     .Keyboard_Interface =
307         {
308             .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
309
310             .InterfaceNumber        = KEYBOARD_INTERFACE,
311             .AlternateSetting       = 0x00,
312
313             .TotalEndpoints         = 1,
314
315             .Class                  = HID_CSCP_HIDClass,
316             .SubClass               = HID_CSCP_BootSubclass,
317             .Protocol               = HID_CSCP_KeyboardBootProtocol,
318
319             .InterfaceStrIndex      = NO_DESCRIPTOR
320         },
321
322     .Keyboard_HID =
323         {
324             .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
325
326             .HIDSpec                = VERSION_BCD(1,1,1),
327             .CountryCode            = 0x00,
328             .TotalReportDescriptors = 1,
329             .HIDReportType          = HID_DTYPE_Report,
330             .HIDReportLength        = sizeof(KeyboardReport)
331         },
332
333     .Keyboard_INEndpoint =
334         {
335             .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
336
337             .EndpointAddress        = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM),
338             .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
339             .EndpointSize           = KEYBOARD_EPSIZE,
340             .PollingIntervalMS      = 0x0A
341         },
342
343     /*
344      * Mouse
345      */
346 #ifdef MOUSE_ENABLE
347     .Mouse_Interface =
348         {
349             .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
350
351             .InterfaceNumber        = MOUSE_INTERFACE,
352             .AlternateSetting       = 0x00,
353
354             .TotalEndpoints         = 1,
355
356             .Class                  = HID_CSCP_HIDClass,
357             .SubClass               = HID_CSCP_BootSubclass,
358             .Protocol               = HID_CSCP_MouseBootProtocol,
359
360             .InterfaceStrIndex      = NO_DESCRIPTOR
361         },
362
363     .Mouse_HID =
364         {
365             .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
366
367             .HIDSpec                = VERSION_BCD(1,1,1),
368             .CountryCode            = 0x00,
369             .TotalReportDescriptors = 1,
370             .HIDReportType          = HID_DTYPE_Report,
371             .HIDReportLength        = sizeof(MouseReport)
372         },
373
374     .Mouse_INEndpoint =
375         {
376             .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
377
378             .EndpointAddress        = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM),
379             .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
380             .EndpointSize           = MOUSE_EPSIZE,
381             .PollingIntervalMS      = 0x0A
382         },
383 #endif
384
385     /*
386      * Extra
387      */
388 #ifdef EXTRAKEY_ENABLE
389     .Extrakey_Interface =
390         {
391             .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
392
393             .InterfaceNumber        = EXTRAKEY_INTERFACE,
394             .AlternateSetting       = 0x00,
395
396             .TotalEndpoints         = 1,
397
398             .Class                  = HID_CSCP_HIDClass,
399             .SubClass               = HID_CSCP_NonBootSubclass,
400             .Protocol               = HID_CSCP_NonBootProtocol,
401
402             .InterfaceStrIndex      = NO_DESCRIPTOR
403         },
404
405     .Extrakey_HID =
406         {
407             .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
408
409             .HIDSpec                = VERSION_BCD(1,1,1),
410             .CountryCode            = 0x00,
411             .TotalReportDescriptors = 1,
412             .HIDReportType          = HID_DTYPE_Report,
413             .HIDReportLength        = sizeof(ExtrakeyReport)
414         },
415
416     .Extrakey_INEndpoint =
417         {
418             .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
419
420             .EndpointAddress        = (ENDPOINT_DIR_IN | EXTRAKEY_IN_EPNUM),
421             .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
422             .EndpointSize           = EXTRAKEY_EPSIZE,
423             .PollingIntervalMS      = 0x0A
424         },
425 #endif
426
427                 /*
428              * Raw
429              */
430         #ifdef RAW_ENABLE
431             .Raw_Interface =
432                 {
433                     .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
434
435                     .InterfaceNumber        = RAW_INTERFACE,
436                     .AlternateSetting       = 0x00,
437
438                     .TotalEndpoints         = 2,
439
440                     .Class                  = HID_CSCP_HIDClass,
441                     .SubClass               = HID_CSCP_NonBootSubclass,
442                     .Protocol               = HID_CSCP_NonBootProtocol,
443
444                     .InterfaceStrIndex      = NO_DESCRIPTOR
445                 },
446
447             .Raw_HID =
448                 {
449                     .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
450
451                     .HIDSpec                = VERSION_BCD(1,1,1),
452                     .CountryCode            = 0x00,
453                     .TotalReportDescriptors = 1,
454                     .HIDReportType          = HID_DTYPE_Report,
455                     .HIDReportLength        = sizeof(RawReport)
456                 },
457
458             .Raw_INEndpoint =
459                 {
460                     .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
461
462                     .EndpointAddress        = (ENDPOINT_DIR_IN | RAW_IN_EPNUM),
463                     .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
464                     .EndpointSize           = RAW_EPSIZE,
465                     .PollingIntervalMS      = 0x01
466                 },
467
468             .Raw_OUTEndpoint =
469                 {
470                     .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
471
472                     .EndpointAddress        = (ENDPOINT_DIR_OUT | RAW_OUT_EPNUM),
473                     .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
474                     .EndpointSize           = RAW_EPSIZE,
475                     .PollingIntervalMS      = 0x01
476                 },
477         #endif
478
479     /*
480      * Console
481      */
482 #ifdef CONSOLE_ENABLE
483     .Console_Interface =
484         {
485             .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
486
487             .InterfaceNumber        = CONSOLE_INTERFACE,
488             .AlternateSetting       = 0x00,
489
490             .TotalEndpoints         = 2,
491
492             .Class                  = HID_CSCP_HIDClass,
493             .SubClass               = HID_CSCP_NonBootSubclass,
494             .Protocol               = HID_CSCP_NonBootProtocol,
495
496             .InterfaceStrIndex      = NO_DESCRIPTOR
497         },
498
499     .Console_HID =
500         {
501             .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
502
503             .HIDSpec                = VERSION_BCD(1,1,1),
504             .CountryCode            = 0x00,
505             .TotalReportDescriptors = 1,
506             .HIDReportType          = HID_DTYPE_Report,
507             .HIDReportLength        = sizeof(ConsoleReport)
508         },
509
510     .Console_INEndpoint =
511         {
512             .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
513
514             .EndpointAddress        = (ENDPOINT_DIR_IN | CONSOLE_IN_EPNUM),
515             .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
516             .EndpointSize           = CONSOLE_EPSIZE,
517             .PollingIntervalMS      = 0x01
518         },
519
520     .Console_OUTEndpoint =
521         {
522             .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
523
524             .EndpointAddress        = (ENDPOINT_DIR_OUT | CONSOLE_OUT_EPNUM),
525             .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
526             .EndpointSize           = CONSOLE_EPSIZE,
527             .PollingIntervalMS      = 0x01
528         },
529 #endif
530
531     /*
532      * NKRO
533      */
534 #ifdef NKRO_ENABLE
535     .NKRO_Interface =
536         {
537             .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
538
539             .InterfaceNumber        = NKRO_INTERFACE,
540             .AlternateSetting       = 0x00,
541
542             .TotalEndpoints         = 1,
543
544             .Class                  = HID_CSCP_HIDClass,
545             .SubClass               = HID_CSCP_NonBootSubclass,
546             .Protocol               = HID_CSCP_NonBootProtocol,
547
548             .InterfaceStrIndex      = NO_DESCRIPTOR
549         },
550
551     .NKRO_HID =
552         {
553             .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
554
555             .HIDSpec                = VERSION_BCD(1,1,1),
556             .CountryCode            = 0x00,
557             .TotalReportDescriptors = 1,
558             .HIDReportType          = HID_DTYPE_Report,
559             .HIDReportLength        = sizeof(NKROReport)
560         },
561
562     .NKRO_INEndpoint =
563         {
564             .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
565
566             .EndpointAddress        = (ENDPOINT_DIR_IN | NKRO_IN_EPNUM),
567             .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
568             .EndpointSize           = NKRO_EPSIZE,
569             .PollingIntervalMS      = 0x01
570         },
571 #endif
572
573 #ifdef MIDI_ENABLE
574     .Audio_Interface_Association =
575         {
576             .Header                   = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
577
578             .FirstInterfaceIndex      = AC_INTERFACE,
579             .TotalInterfaces          = 2,
580
581             .Class                    = AUDIO_CSCP_AudioClass,
582             .SubClass                 = AUDIO_CSCP_ControlSubclass,
583             .Protocol                 = AUDIO_CSCP_ControlProtocol,
584
585             .IADStrIndex              = NO_DESCRIPTOR,
586         },
587     .Audio_ControlInterface =
588         {
589             .Header                   = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
590
591             .InterfaceNumber          = AC_INTERFACE,
592             .AlternateSetting         = 0,
593
594             .TotalEndpoints           = 0,
595
596             .Class                    = AUDIO_CSCP_AudioClass,
597             .SubClass                 = AUDIO_CSCP_ControlSubclass,
598             .Protocol                 = AUDIO_CSCP_ControlProtocol,
599
600             .InterfaceStrIndex        = NO_DESCRIPTOR
601         },
602
603     .Audio_ControlInterface_SPC =
604         {
605             .Header                   = {.Size = sizeof(USB_Audio_Descriptor_Interface_AC_t), .Type = DTYPE_CSInterface},
606             .Subtype                  = AUDIO_DSUBTYPE_CSInterface_Header,
607
608             .ACSpecification          = VERSION_BCD(1,0,0),
609             .TotalLength              = sizeof(USB_Audio_Descriptor_Interface_AC_t),
610
611             .InCollection             = 1,
612             .InterfaceNumber          = AS_INTERFACE,
613         },
614
615     .Audio_StreamInterface =
616         {
617             .Header                   = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
618
619             .InterfaceNumber          = AS_INTERFACE,
620             .AlternateSetting         = 0,
621
622             .TotalEndpoints           = 2,
623
624             .Class                    = AUDIO_CSCP_AudioClass,
625             .SubClass                 = AUDIO_CSCP_MIDIStreamingSubclass,
626             .Protocol                 = AUDIO_CSCP_StreamingProtocol,
627
628             .InterfaceStrIndex        = NO_DESCRIPTOR
629         },
630
631     .Audio_StreamInterface_SPC =
632         {
633             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_AudioInterface_AS_t), .Type = DTYPE_CSInterface},
634             .Subtype                  = AUDIO_DSUBTYPE_CSInterface_General,
635
636             .AudioSpecification       = VERSION_BCD(1,0,0),
637
638             .TotalLength              = offsetof(USB_Descriptor_Configuration_t, MIDI_Out_Jack_Endpoint_SPC)
639                                         + sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t)
640                                         - offsetof(USB_Descriptor_Configuration_t, Audio_StreamInterface_SPC)
641         },
642
643     .MIDI_In_Jack_Emb =
644         {
645             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = DTYPE_CSInterface},
646             .Subtype                  = AUDIO_DSUBTYPE_CSInterface_InputTerminal,
647
648             .JackType                 = MIDI_JACKTYPE_Embedded,
649             .JackID                   = 0x01,
650
651             .JackStrIndex             = NO_DESCRIPTOR
652         },
653
654     .MIDI_In_Jack_Ext =
655         {
656             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = DTYPE_CSInterface},
657             .Subtype                  = AUDIO_DSUBTYPE_CSInterface_InputTerminal,
658
659             .JackType                 = MIDI_JACKTYPE_External,
660             .JackID                   = 0x02,
661
662             .JackStrIndex             = NO_DESCRIPTOR
663         },
664
665     .MIDI_Out_Jack_Emb =
666         {
667             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = DTYPE_CSInterface},
668             .Subtype                  = AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
669
670             .JackType                 = MIDI_JACKTYPE_Embedded,
671             .JackID                   = 0x03,
672
673             .NumberOfPins             = 1,
674             .SourceJackID             = {0x02},
675             .SourcePinID              = {0x01},
676
677             .JackStrIndex             = NO_DESCRIPTOR
678         },
679
680     .MIDI_Out_Jack_Ext =
681         {
682             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = DTYPE_CSInterface},
683             .Subtype                  = AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
684
685             .JackType                 = MIDI_JACKTYPE_External,
686             .JackID                   = 0x04,
687
688             .NumberOfPins             = 1,
689             .SourceJackID             = {0x01},
690             .SourcePinID              = {0x01},
691
692             .JackStrIndex             = NO_DESCRIPTOR
693         },
694
695     .MIDI_In_Jack_Endpoint =
696         {
697             .Endpoint =
698                 {
699                     .Header              = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint},
700
701                     .EndpointAddress     = MIDI_STREAM_OUT_EPADDR,
702                     .Attributes          = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
703                     .EndpointSize        = MIDI_STREAM_EPSIZE,
704                     .PollingIntervalMS   = 0x05
705                 },
706
707             .Refresh                  = 0,
708             .SyncEndpointNumber       = 0
709         },
710
711     .MIDI_In_Jack_Endpoint_SPC =
712         {
713             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = DTYPE_CSEndpoint},
714             .Subtype                  = AUDIO_DSUBTYPE_CSEndpoint_General,
715
716             .TotalEmbeddedJacks       = 0x01,
717             .AssociatedJackID         = {0x01}
718         },
719
720     .MIDI_Out_Jack_Endpoint =
721         {
722             .Endpoint =
723                 {
724                     .Header              = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint},
725
726                     .EndpointAddress     = MIDI_STREAM_IN_EPADDR,
727                     .Attributes          = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
728                     .EndpointSize        = MIDI_STREAM_EPSIZE,
729                     .PollingIntervalMS   = 0x05
730                 },
731
732             .Refresh                  = 0,
733             .SyncEndpointNumber       = 0
734         },
735
736     .MIDI_Out_Jack_Endpoint_SPC =
737         {
738             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = DTYPE_CSEndpoint},
739             .Subtype                  = AUDIO_DSUBTYPE_CSEndpoint_General,
740
741             .TotalEmbeddedJacks       = 0x01,
742             .AssociatedJackID         = {0x03}
743         },
744 #endif
745
746 #ifdef VIRTSER_ENABLE
747     .CDC_Interface_Association =
748             {
749                     .Header                 = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
750
751                     .FirstInterfaceIndex    = CCI_INTERFACE,
752                     .TotalInterfaces        = 2,
753
754                     .Class                  = CDC_CSCP_CDCClass,
755                     .SubClass               = CDC_CSCP_ACMSubclass,
756                     .Protocol               = CDC_CSCP_ATCommandProtocol,
757
758                     .IADStrIndex            = NO_DESCRIPTOR,
759             },
760
761     .CDC_CCI_Interface =
762             {
763                     .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
764
765                     .InterfaceNumber        = CCI_INTERFACE,
766                     .AlternateSetting       = 0,
767
768                     .TotalEndpoints         = 1,
769
770                     .Class                  = CDC_CSCP_CDCClass,
771                     .SubClass               = CDC_CSCP_ACMSubclass,
772                     .Protocol               = CDC_CSCP_ATCommandProtocol,
773
774                     .InterfaceStrIndex      = NO_DESCRIPTOR
775             },
776
777     .CDC_Functional_Header =
778             {
779                     .Header                 = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = DTYPE_CSInterface},
780                     .Subtype                = 0x00,
781
782                     .CDCSpecification       = VERSION_BCD(1,1,0),
783             },
784
785     .CDC_Functional_ACM =
786             {
787                     .Header                 = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface},
788                     .Subtype                = 0x02,
789
790                     .Capabilities           = 0x02,
791             },
792
793     .CDC_Functional_Union =
794             {
795                     .Header                 = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface},
796                     .Subtype                = 0x06,
797
798                     .MasterInterfaceNumber  = CCI_INTERFACE,
799                     .SlaveInterfaceNumber   = CDI_INTERFACE,
800             },
801
802     .CDC_NotificationEndpoint =
803             {
804                     .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
805
806                     .EndpointAddress        = CDC_NOTIFICATION_EPADDR,
807                     .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
808                     .EndpointSize           = CDC_NOTIFICATION_EPSIZE,
809                     .PollingIntervalMS      = 0xFF
810             },
811
812     .CDC_DCI_Interface =
813             {
814                     .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
815
816                     .InterfaceNumber        = CDI_INTERFACE,
817                     .AlternateSetting       = 0,
818
819                     .TotalEndpoints         = 2,
820
821                     .Class                  = CDC_CSCP_CDCDataClass,
822                     .SubClass               = CDC_CSCP_NoDataSubclass,
823                     .Protocol               = CDC_CSCP_NoDataProtocol,
824
825                     .InterfaceStrIndex      = NO_DESCRIPTOR
826             },
827
828     .CDC_DataOutEndpoint =
829             {
830                     .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
831
832                     .EndpointAddress        = CDC_OUT_EPADDR,
833                     .Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
834                     .EndpointSize           = CDC_EPSIZE,
835                     .PollingIntervalMS      = 0x05
836             },
837
838     .CDC_DataInEndpoint =
839             {
840                     .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
841
842                     .EndpointAddress        = CDC_IN_EPADDR,
843                     .Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
844                     .EndpointSize           = CDC_EPSIZE,
845                     .PollingIntervalMS      = 0x05
846             },
847 #endif
848 };
849
850
851 /*******************************************************************************
852  * String Descriptors
853  ******************************************************************************/
854 const USB_Descriptor_String_t PROGMEM LanguageString =
855 {
856     .Header                 = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
857
858     .UnicodeString          = {LANGUAGE_ID_ENG}
859 };
860
861 const USB_Descriptor_String_t PROGMEM ManufacturerString =
862 {
863     /* subtract 1 for null terminator */
864     .Header                 = {.Size = USB_STRING_LEN(sizeof(STR(MANUFACTURER))-1), .Type = DTYPE_String},
865
866     .UnicodeString          = LSTR(MANUFACTURER)
867 };
868
869 const USB_Descriptor_String_t PROGMEM ProductString =
870 {
871     /* subtract 1 for null terminator */
872     .Header                 = {.Size = USB_STRING_LEN(sizeof(STR(PRODUCT))-1), .Type = DTYPE_String},
873
874     .UnicodeString          = LSTR(PRODUCT)
875 };
876
877 #ifndef SERIAL_NUMBER
878     #define SERIAL_NUMBER 0
879 #endif
880
881 const USB_Descriptor_String_t PROGMEM SerialNumberString =
882 {
883     /* subtract 1 for null terminator */
884     .Header                 = {.Size = USB_STRING_LEN(sizeof(STR(SERIAL_NUMBER))-1), .Type = DTYPE_String},
885
886     .UnicodeString          = LSTR(SERIAL_NUMBER)
887 };
888
889
890 /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
891  *  documentation) by the application code so that the address and size of a requested descriptor can be given
892  *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
893  *  is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
894  *  USB host.
895  */
896 uint16_t get_usb_descriptor(const uint16_t wValue,
897                             const uint16_t wIndex,
898                             const void** const DescriptorAddress)
899 {
900     const uint8_t  DescriptorType   = (wValue >> 8);
901     const uint8_t  DescriptorIndex  = (wValue & 0xFF);
902
903     const void* Address = NULL;
904     uint16_t    Size    = NO_DESCRIPTOR;
905
906     switch (DescriptorType)
907     {
908         case DTYPE_Device:
909             Address = &DeviceDescriptor;
910             Size    = sizeof(USB_Descriptor_Device_t);
911             break;
912         case DTYPE_Configuration:
913             Address = &ConfigurationDescriptor;
914             Size    = sizeof(USB_Descriptor_Configuration_t);
915             break;
916         case DTYPE_String:
917             switch (DescriptorIndex )
918             {
919                 case 0x00:
920                     Address = &LanguageString;
921                     Size    = pgm_read_byte(&LanguageString.Header.Size);
922                     break;
923                 case 0x01:
924                     Address = &ManufacturerString;
925                     Size    = pgm_read_byte(&ManufacturerString.Header.Size);
926                     break;
927                 case 0x02:
928                     Address = &ProductString;
929                     Size    = pgm_read_byte(&ProductString.Header.Size);
930                     break;
931                 case 0x03:
932                     Address = &SerialNumberString;
933                     Size    = pgm_read_byte(&SerialNumberString.Header.Size);
934                     break;
935             }
936             break;
937         case HID_DTYPE_HID:
938             switch (wIndex) {
939             case KEYBOARD_INTERFACE:
940                 Address = &ConfigurationDescriptor.Keyboard_HID;
941                 Size    = sizeof(USB_HID_Descriptor_HID_t);
942                 break;
943 #ifdef MOUSE_ENABLE
944             case MOUSE_INTERFACE:
945                 Address = &ConfigurationDescriptor.Mouse_HID;
946                 Size    = sizeof(USB_HID_Descriptor_HID_t);
947                 break;
948 #endif
949 #ifdef EXTRAKEY_ENABLE
950             case EXTRAKEY_INTERFACE:
951                 Address = &ConfigurationDescriptor.Extrakey_HID;
952                 Size    = sizeof(USB_HID_Descriptor_HID_t);
953                 break;
954 #endif
955 #ifdef RAW_ENABLE
956             case RAW_INTERFACE:
957                 Address = &ConfigurationDescriptor.Raw_HID;
958                 Size    = sizeof(USB_HID_Descriptor_HID_t);
959                 break;
960 #endif
961 #ifdef CONSOLE_ENABLE
962             case CONSOLE_INTERFACE:
963                 Address = &ConfigurationDescriptor.Console_HID;
964                 Size    = sizeof(USB_HID_Descriptor_HID_t);
965                 break;
966 #endif
967 #ifdef NKRO_ENABLE
968             case NKRO_INTERFACE:
969                 Address = &ConfigurationDescriptor.NKRO_HID;
970                 Size    = sizeof(USB_HID_Descriptor_HID_t);
971                 break;
972 #endif
973             }
974             break;
975         case HID_DTYPE_Report:
976             switch (wIndex) {
977             case KEYBOARD_INTERFACE:
978                 Address = &KeyboardReport;
979                 Size    = sizeof(KeyboardReport);
980                 break;
981 #ifdef MOUSE_ENABLE
982             case MOUSE_INTERFACE:
983                 Address = &MouseReport;
984                 Size    = sizeof(MouseReport);
985                 break;
986 #endif
987 #ifdef EXTRAKEY_ENABLE
988             case EXTRAKEY_INTERFACE:
989                 Address = &ExtrakeyReport;
990                 Size    = sizeof(ExtrakeyReport);
991                 break;
992 #endif
993 #ifdef RAW_ENABLE
994             case RAW_INTERFACE:
995                 Address = &RawReport;
996                 Size    = sizeof(RawReport);
997                 break;
998 #endif
999 #ifdef CONSOLE_ENABLE
1000             case CONSOLE_INTERFACE:
1001                 Address = &ConsoleReport;
1002                 Size    = sizeof(ConsoleReport);
1003                 break;
1004 #endif
1005 #ifdef NKRO_ENABLE
1006             case NKRO_INTERFACE:
1007                 Address = &NKROReport;
1008                 Size    = sizeof(NKROReport);
1009                 break;
1010 #endif
1011             }
1012             break;
1013     }
1014
1015     *DescriptorAddress = Address;
1016     return Size;
1017 }