]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/lufa/descriptor.c
Adds serial number string to USB descriptors (#1996)
[qmk_firmware.git] / tmk_core / protocol / lufa / 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 "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_ControlInterface =
575         {
576             .Header                   = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
577
578             .InterfaceNumber          = AC_INTERFACE,
579             .AlternateSetting         = 0,
580
581             .TotalEndpoints           = 0,
582
583             .Class                    = AUDIO_CSCP_AudioClass,
584             .SubClass                 = AUDIO_CSCP_ControlSubclass,
585             .Protocol                 = AUDIO_CSCP_ControlProtocol,
586
587             .InterfaceStrIndex        = NO_DESCRIPTOR
588         },
589
590     .Audio_ControlInterface_SPC =
591         {
592             .Header                   = {.Size = sizeof(USB_Audio_Descriptor_Interface_AC_t), .Type = DTYPE_CSInterface},
593             .Subtype                  = AUDIO_DSUBTYPE_CSInterface_Header,
594
595             .ACSpecification          = VERSION_BCD(1,0,0),
596             .TotalLength              = sizeof(USB_Audio_Descriptor_Interface_AC_t),
597
598             .InCollection             = 1,
599             .InterfaceNumber          = AS_INTERFACE,
600         },
601
602     .Audio_StreamInterface =
603         {
604             .Header                   = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
605
606             .InterfaceNumber          = AS_INTERFACE,
607             .AlternateSetting         = 0,
608
609             .TotalEndpoints           = 2,
610
611             .Class                    = AUDIO_CSCP_AudioClass,
612             .SubClass                 = AUDIO_CSCP_MIDIStreamingSubclass,
613             .Protocol                 = AUDIO_CSCP_StreamingProtocol,
614
615             .InterfaceStrIndex        = NO_DESCRIPTOR
616         },
617
618     .Audio_StreamInterface_SPC =
619         {
620             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_AudioInterface_AS_t), .Type = DTYPE_CSInterface},
621             .Subtype                  = AUDIO_DSUBTYPE_CSInterface_General,
622
623             .AudioSpecification       = VERSION_BCD(1,0,0),
624
625             .TotalLength              = (sizeof(USB_Descriptor_Configuration_t) -
626                                          offsetof(USB_Descriptor_Configuration_t, Audio_StreamInterface_SPC))
627         },
628
629     .MIDI_In_Jack_Emb =
630         {
631             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = DTYPE_CSInterface},
632             .Subtype                  = AUDIO_DSUBTYPE_CSInterface_InputTerminal,
633
634             .JackType                 = MIDI_JACKTYPE_Embedded,
635             .JackID                   = 0x01,
636
637             .JackStrIndex             = NO_DESCRIPTOR
638         },
639
640     .MIDI_In_Jack_Ext =
641         {
642             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = DTYPE_CSInterface},
643             .Subtype                  = AUDIO_DSUBTYPE_CSInterface_InputTerminal,
644
645             .JackType                 = MIDI_JACKTYPE_External,
646             .JackID                   = 0x02,
647
648             .JackStrIndex             = NO_DESCRIPTOR
649         },
650
651     .MIDI_Out_Jack_Emb =
652         {
653             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = DTYPE_CSInterface},
654             .Subtype                  = AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
655
656             .JackType                 = MIDI_JACKTYPE_Embedded,
657             .JackID                   = 0x03,
658
659             .NumberOfPins             = 1,
660             .SourceJackID             = {0x02},
661             .SourcePinID              = {0x01},
662
663             .JackStrIndex             = NO_DESCRIPTOR
664         },
665
666     .MIDI_Out_Jack_Ext =
667         {
668             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = DTYPE_CSInterface},
669             .Subtype                  = AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
670
671             .JackType                 = MIDI_JACKTYPE_External,
672             .JackID                   = 0x04,
673
674             .NumberOfPins             = 1,
675             .SourceJackID             = {0x01},
676             .SourcePinID              = {0x01},
677
678             .JackStrIndex             = NO_DESCRIPTOR
679         },
680
681     .MIDI_In_Jack_Endpoint =
682         {
683             .Endpoint =
684                 {
685                     .Header              = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint},
686
687                     .EndpointAddress     = MIDI_STREAM_OUT_EPADDR,
688                     .Attributes          = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
689                     .EndpointSize        = MIDI_STREAM_EPSIZE,
690                     .PollingIntervalMS   = 0x05
691                 },
692
693             .Refresh                  = 0,
694             .SyncEndpointNumber       = 0
695         },
696
697     .MIDI_In_Jack_Endpoint_SPC =
698         {
699             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = DTYPE_CSEndpoint},
700             .Subtype                  = AUDIO_DSUBTYPE_CSEndpoint_General,
701
702             .TotalEmbeddedJacks       = 0x01,
703             .AssociatedJackID         = {0x01}
704         },
705
706     .MIDI_Out_Jack_Endpoint =
707         {
708             .Endpoint =
709                 {
710                     .Header              = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint},
711
712                     .EndpointAddress     = MIDI_STREAM_IN_EPADDR,
713                     .Attributes          = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
714                     .EndpointSize        = MIDI_STREAM_EPSIZE,
715                     .PollingIntervalMS   = 0x05
716                 },
717
718             .Refresh                  = 0,
719             .SyncEndpointNumber       = 0
720         },
721
722     .MIDI_Out_Jack_Endpoint_SPC =
723         {
724             .Header                   = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = DTYPE_CSEndpoint},
725             .Subtype                  = AUDIO_DSUBTYPE_CSEndpoint_General,
726
727             .TotalEmbeddedJacks       = 0x01,
728             .AssociatedJackID         = {0x03}
729         },
730 #endif
731
732 #ifdef VIRTSER_ENABLE
733     .CDC_Interface_Association =
734             {
735                     .Header                 = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
736
737                     .FirstInterfaceIndex    = CCI_INTERFACE,
738                     .TotalInterfaces        = 2,
739
740                     .Class                  = CDC_CSCP_CDCClass,
741                     .SubClass               = CDC_CSCP_ACMSubclass,
742                     .Protocol               = CDC_CSCP_ATCommandProtocol,
743
744                     .IADStrIndex            = NO_DESCRIPTOR,
745             },
746
747     .CDC_CCI_Interface =
748             {
749                     .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
750
751                     .InterfaceNumber        = CCI_INTERFACE,
752                     .AlternateSetting       = 0,
753
754                     .TotalEndpoints         = 1,
755
756                     .Class                  = CDC_CSCP_CDCClass,
757                     .SubClass               = CDC_CSCP_ACMSubclass,
758                     .Protocol               = CDC_CSCP_ATCommandProtocol,
759
760                     .InterfaceStrIndex      = NO_DESCRIPTOR
761             },
762
763     .CDC_Functional_Header =
764             {
765                     .Header                 = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = DTYPE_CSInterface},
766                     .Subtype                = 0x00,
767
768                     .CDCSpecification       = VERSION_BCD(1,1,0),
769             },
770
771     .CDC_Functional_ACM =
772             {
773                     .Header                 = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface},
774                     .Subtype                = 0x02,
775
776                     .Capabilities           = 0x02,
777             },
778
779     .CDC_Functional_Union =
780             {
781                     .Header                 = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface},
782                     .Subtype                = 0x06,
783
784                     .MasterInterfaceNumber  = CCI_INTERFACE,
785                     .SlaveInterfaceNumber   = CDI_INTERFACE,
786             },
787
788     .CDC_NotificationEndpoint =
789             {
790                     .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
791
792                     .EndpointAddress        = CDC_NOTIFICATION_EPADDR,
793                     .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
794                     .EndpointSize           = CDC_NOTIFICATION_EPSIZE,
795                     .PollingIntervalMS      = 0xFF
796             },
797
798     .CDC_DCI_Interface =
799             {
800                     .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
801
802                     .InterfaceNumber        = CDI_INTERFACE,
803                     .AlternateSetting       = 0,
804
805                     .TotalEndpoints         = 2,
806
807                     .Class                  = CDC_CSCP_CDCDataClass,
808                     .SubClass               = CDC_CSCP_NoDataSubclass,
809                     .Protocol               = CDC_CSCP_NoDataProtocol,
810
811                     .InterfaceStrIndex      = NO_DESCRIPTOR
812             },
813
814     .CDC_DataOutEndpoint =
815             {
816                     .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
817
818                     .EndpointAddress        = CDC_OUT_EPADDR,
819                     .Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
820                     .EndpointSize           = CDC_EPSIZE,
821                     .PollingIntervalMS      = 0x05
822             },
823
824     .CDC_DataInEndpoint =
825             {
826                     .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
827
828                     .EndpointAddress        = CDC_IN_EPADDR,
829                     .Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
830                     .EndpointSize           = CDC_EPSIZE,
831                     .PollingIntervalMS      = 0x05
832             },
833 #endif
834 };
835
836
837 /*******************************************************************************
838  * String Descriptors
839  ******************************************************************************/
840 const USB_Descriptor_String_t PROGMEM LanguageString =
841 {
842     .Header                 = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
843
844     .UnicodeString          = {LANGUAGE_ID_ENG}
845 };
846
847 const USB_Descriptor_String_t PROGMEM ManufacturerString =
848 {
849     /* subtract 1 for null terminator */
850     .Header                 = {.Size = USB_STRING_LEN(sizeof(STR(MANUFACTURER))-1), .Type = DTYPE_String},
851
852     .UnicodeString          = LSTR(MANUFACTURER)
853 };
854
855 const USB_Descriptor_String_t PROGMEM ProductString =
856 {
857     /* subtract 1 for null terminator */
858     .Header                 = {.Size = USB_STRING_LEN(sizeof(STR(PRODUCT))-1), .Type = DTYPE_String},
859
860     .UnicodeString          = LSTR(PRODUCT)
861 };
862
863 #ifndef SERIAL_NUMBER
864     #define SERIAL_NUMBER 0
865 #endif
866
867 const USB_Descriptor_String_t PROGMEM SerialNumberString =
868 {
869     /* subtract 1 for null terminator */
870     .Header                 = {.Size = USB_STRING_LEN(sizeof(STR(SERIAL_NUMBER))-1), .Type = DTYPE_String},
871
872     .UnicodeString          = LSTR(SERIAL_NUMBER)
873 };
874
875
876 /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
877  *  documentation) by the application code so that the address and size of a requested descriptor can be given
878  *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
879  *  is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
880  *  USB host.
881  */
882 uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
883                                     const uint16_t wIndex,
884                                     const void** const DescriptorAddress)
885 {
886     const uint8_t  DescriptorType   = (wValue >> 8);
887     const uint8_t  DescriptorIndex  = (wValue & 0xFF);
888
889     const void* Address = NULL;
890     uint16_t    Size    = NO_DESCRIPTOR;
891
892     switch (DescriptorType)
893     {
894         case DTYPE_Device:
895             Address = &DeviceDescriptor;
896             Size    = sizeof(USB_Descriptor_Device_t);
897             break;
898         case DTYPE_Configuration:
899             Address = &ConfigurationDescriptor;
900             Size    = sizeof(USB_Descriptor_Configuration_t);
901             break;
902         case DTYPE_String:
903             switch (DescriptorIndex )
904             {
905                 case 0x00:
906                     Address = &LanguageString;
907                     Size    = pgm_read_byte(&LanguageString.Header.Size);
908                     break;
909                 case 0x01:
910                     Address = &ManufacturerString;
911                     Size    = pgm_read_byte(&ManufacturerString.Header.Size);
912                     break;
913                 case 0x02:
914                     Address = &ProductString;
915                     Size    = pgm_read_byte(&ProductString.Header.Size);
916                     break;
917                 case 0x03:
918                     Address = &SerialNumberString;
919                     Size    = pgm_read_byte(&SerialNumberString.Header.Size);
920                     break;
921             }
922             break;
923         case HID_DTYPE_HID:
924             switch (wIndex) {
925             case KEYBOARD_INTERFACE:
926                 Address = &ConfigurationDescriptor.Keyboard_HID;
927                 Size    = sizeof(USB_HID_Descriptor_HID_t);
928                 break;
929 #ifdef MOUSE_ENABLE
930             case MOUSE_INTERFACE:
931                 Address = &ConfigurationDescriptor.Mouse_HID;
932                 Size    = sizeof(USB_HID_Descriptor_HID_t);
933                 break;
934 #endif
935 #ifdef EXTRAKEY_ENABLE
936             case EXTRAKEY_INTERFACE:
937                 Address = &ConfigurationDescriptor.Extrakey_HID;
938                 Size    = sizeof(USB_HID_Descriptor_HID_t);
939                 break;
940 #endif
941 #ifdef RAW_ENABLE
942             case RAW_INTERFACE:
943                 Address = &ConfigurationDescriptor.Raw_HID;
944                 Size    = sizeof(USB_HID_Descriptor_HID_t);
945                 break;
946 #endif
947 #ifdef CONSOLE_ENABLE
948             case CONSOLE_INTERFACE:
949                 Address = &ConfigurationDescriptor.Console_HID;
950                 Size    = sizeof(USB_HID_Descriptor_HID_t);
951                 break;
952 #endif
953 #ifdef NKRO_ENABLE
954             case NKRO_INTERFACE:
955                 Address = &ConfigurationDescriptor.NKRO_HID;
956                 Size    = sizeof(USB_HID_Descriptor_HID_t);
957                 break;
958 #endif
959             }
960             break;
961         case HID_DTYPE_Report:
962             switch (wIndex) {
963             case KEYBOARD_INTERFACE:
964                 Address = &KeyboardReport;
965                 Size    = sizeof(KeyboardReport);
966                 break;
967 #ifdef MOUSE_ENABLE
968             case MOUSE_INTERFACE:
969                 Address = &MouseReport;
970                 Size    = sizeof(MouseReport);
971                 break;
972 #endif
973 #ifdef EXTRAKEY_ENABLE
974             case EXTRAKEY_INTERFACE:
975                 Address = &ExtrakeyReport;
976                 Size    = sizeof(ExtrakeyReport);
977                 break;
978 #endif
979 #ifdef RAW_ENABLE
980             case RAW_INTERFACE:
981                 Address = &RawReport;
982                 Size    = sizeof(RawReport);
983                 break;
984 #endif
985 #ifdef CONSOLE_ENABLE
986             case CONSOLE_INTERFACE:
987                 Address = &ConsoleReport;
988                 Size    = sizeof(ConsoleReport);
989                 break;
990 #endif
991 #ifdef NKRO_ENABLE
992             case NKRO_INTERFACE:
993                 Address = &NKROReport;
994                 Size    = sizeof(NKROReport);
995                 break;
996 #endif
997             }
998             break;
999     }
1000
1001     *DescriptorAddress = Address;
1002     return Size;
1003 }