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