]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/lufa/descriptor.c
357954368b2696dbd402d25c8f493d96ab584dfa
[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      = NO_DESCRIPTOR,
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
864 /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
865  *  documentation) by the application code so that the address and size of a requested descriptor can be given
866  *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
867  *  is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
868  *  USB host.
869  */
870 uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
871                                     const uint16_t wIndex,
872                                     const void** const DescriptorAddress)
873 {
874     const uint8_t  DescriptorType   = (wValue >> 8);
875     const uint8_t  DescriptorIndex  = (wValue & 0xFF);
876
877     const void* Address = NULL;
878     uint16_t    Size    = NO_DESCRIPTOR;
879
880     switch (DescriptorType)
881     {
882         case DTYPE_Device:
883             Address = &DeviceDescriptor;
884             Size    = sizeof(USB_Descriptor_Device_t);
885             break;
886         case DTYPE_Configuration:
887             Address = &ConfigurationDescriptor;
888             Size    = sizeof(USB_Descriptor_Configuration_t);
889             break;
890         case DTYPE_String:
891             switch (DescriptorIndex )
892             {
893                 case 0x00:
894                     Address = &LanguageString;
895                     Size    = pgm_read_byte(&LanguageString.Header.Size);
896                     break;
897                 case 0x01:
898                     Address = &ManufacturerString;
899                     Size    = pgm_read_byte(&ManufacturerString.Header.Size);
900                     break;
901                 case 0x02:
902                     Address = &ProductString;
903                     Size    = pgm_read_byte(&ProductString.Header.Size);
904                     break;
905             }
906             break;
907         case HID_DTYPE_HID:
908             switch (wIndex) {
909             case KEYBOARD_INTERFACE:
910                 Address = &ConfigurationDescriptor.Keyboard_HID;
911                 Size    = sizeof(USB_HID_Descriptor_HID_t);
912                 break;
913 #ifdef MOUSE_ENABLE
914             case MOUSE_INTERFACE:
915                 Address = &ConfigurationDescriptor.Mouse_HID;
916                 Size    = sizeof(USB_HID_Descriptor_HID_t);
917                 break;
918 #endif
919 #ifdef EXTRAKEY_ENABLE
920             case EXTRAKEY_INTERFACE:
921                 Address = &ConfigurationDescriptor.Extrakey_HID;
922                 Size    = sizeof(USB_HID_Descriptor_HID_t);
923                 break;
924 #endif
925 #ifdef RAW_ENABLE
926             case RAW_INTERFACE:
927                 Address = &ConfigurationDescriptor.Raw_HID;
928                 Size    = sizeof(USB_HID_Descriptor_HID_t);
929                 break;
930 #endif
931 #ifdef CONSOLE_ENABLE
932             case CONSOLE_INTERFACE:
933                 Address = &ConfigurationDescriptor.Console_HID;
934                 Size    = sizeof(USB_HID_Descriptor_HID_t);
935                 break;
936 #endif
937 #ifdef NKRO_ENABLE
938             case NKRO_INTERFACE:
939                 Address = &ConfigurationDescriptor.NKRO_HID;
940                 Size    = sizeof(USB_HID_Descriptor_HID_t);
941                 break;
942 #endif
943             }
944             break;
945         case HID_DTYPE_Report:
946             switch (wIndex) {
947             case KEYBOARD_INTERFACE:
948                 Address = &KeyboardReport;
949                 Size    = sizeof(KeyboardReport);
950                 break;
951 #ifdef MOUSE_ENABLE
952             case MOUSE_INTERFACE:
953                 Address = &MouseReport;
954                 Size    = sizeof(MouseReport);
955                 break;
956 #endif
957 #ifdef EXTRAKEY_ENABLE
958             case EXTRAKEY_INTERFACE:
959                 Address = &ExtrakeyReport;
960                 Size    = sizeof(ExtrakeyReport);
961                 break;
962 #endif
963 #ifdef RAW_ENABLE
964             case RAW_INTERFACE:
965                 Address = &RawReport;
966                 Size    = sizeof(RawReport);
967                 break;
968 #endif
969 #ifdef CONSOLE_ENABLE
970             case CONSOLE_INTERFACE:
971                 Address = &ConsoleReport;
972                 Size    = sizeof(ConsoleReport);
973                 break;
974 #endif
975 #ifdef NKRO_ENABLE
976             case NKRO_INTERFACE:
977                 Address = &NKROReport;
978                 Size    = sizeof(NKROReport);
979                 break;
980 #endif
981             }
982             break;
983     }
984
985     *DescriptorAddress = Address;
986     return Size;
987 }