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
10 Copyright (C) Dean Camera, 2012.
12 dean [at] fourwalledcubicle [dot] com
17 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
18 Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com)
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.
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
41 #include "usb_descriptor.h"
43 #ifndef USB_MAX_POWER_CONSUMPTION
44 #define USB_MAX_POWER_CONSUMPTION 500
47 /*******************************************************************************
48 * HID Report Descriptors
49 ******************************************************************************/
50 const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
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),
64 HID_RI_REPORT_COUNT(8, 0x01),
65 HID_RI_REPORT_SIZE(8, 0x08),
66 HID_RI_INPUT(8, HID_IOF_CONSTANT), /* reserved */
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),
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),
90 const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
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 */
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),
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),
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),
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),
134 HID_RI_END_COLLECTION(0),
135 HID_RI_END_COLLECTION(0),
139 #ifdef EXTRAKEY_ENABLE
140 const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] =
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),
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),
171 const USB_Descriptor_HIDReport_Datatype_t PROGMEM RawReport[] =
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),
192 #ifdef CONSOLE_ENABLE
193 const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] =
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),
215 const USB_Descriptor_HIDReport_Datatype_t PROGMEM NKROReport[] =
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),
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),
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),
251 /*******************************************************************************
253 ******************************************************************************/
254 const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
256 .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
258 .USBSpecification = VERSION_BCD(1,1,0),
260 .Class = USB_CSCP_IADDeviceClass,
261 .SubClass = USB_CSCP_IADDeviceSubclass,
262 .Protocol = USB_CSCP_IADDeviceProtocol,
264 .Class = USB_CSCP_NoDeviceClass,
265 .SubClass = USB_CSCP_NoDeviceSubclass,
266 .Protocol = USB_CSCP_NoDeviceProtocol,
269 .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
271 /* specified in config.h */
272 .VendorID = VENDOR_ID,
273 .ProductID = PRODUCT_ID,
274 .ReleaseNumber = DEVICE_VER,
276 .ManufacturerStrIndex = 0x01,
277 .ProductStrIndex = 0x02,
278 .SerialNumStrIndex = 0x03,
280 .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
283 /*******************************************************************************
284 * Configuration Descriptors
285 ******************************************************************************/
286 const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
290 .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
292 .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
293 .TotalInterfaces = TOTAL_INTERFACES,
295 .ConfigurationNumber = 1,
296 .ConfigurationStrIndex = NO_DESCRIPTOR,
298 .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP),
300 .MaxPowerConsumption = USB_CONFIG_POWER_MA(USB_MAX_POWER_CONSUMPTION)
306 .Keyboard_Interface =
308 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
310 .InterfaceNumber = KEYBOARD_INTERFACE,
311 .AlternateSetting = 0x00,
315 .Class = HID_CSCP_HIDClass,
316 .SubClass = HID_CSCP_BootSubclass,
317 .Protocol = HID_CSCP_KeyboardBootProtocol,
319 .InterfaceStrIndex = NO_DESCRIPTOR
324 .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
326 .HIDSpec = VERSION_BCD(1,1,1),
328 .TotalReportDescriptors = 1,
329 .HIDReportType = HID_DTYPE_Report,
330 .HIDReportLength = sizeof(KeyboardReport)
333 .Keyboard_INEndpoint =
335 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
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
349 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
351 .InterfaceNumber = MOUSE_INTERFACE,
352 .AlternateSetting = 0x00,
356 .Class = HID_CSCP_HIDClass,
357 .SubClass = HID_CSCP_BootSubclass,
358 .Protocol = HID_CSCP_MouseBootProtocol,
360 .InterfaceStrIndex = NO_DESCRIPTOR
365 .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
367 .HIDSpec = VERSION_BCD(1,1,1),
369 .TotalReportDescriptors = 1,
370 .HIDReportType = HID_DTYPE_Report,
371 .HIDReportLength = sizeof(MouseReport)
376 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
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
388 #ifdef EXTRAKEY_ENABLE
389 .Extrakey_Interface =
391 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
393 .InterfaceNumber = EXTRAKEY_INTERFACE,
394 .AlternateSetting = 0x00,
398 .Class = HID_CSCP_HIDClass,
399 .SubClass = HID_CSCP_NonBootSubclass,
400 .Protocol = HID_CSCP_NonBootProtocol,
402 .InterfaceStrIndex = NO_DESCRIPTOR
407 .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
409 .HIDSpec = VERSION_BCD(1,1,1),
411 .TotalReportDescriptors = 1,
412 .HIDReportType = HID_DTYPE_Report,
413 .HIDReportLength = sizeof(ExtrakeyReport)
416 .Extrakey_INEndpoint =
418 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
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
433 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
435 .InterfaceNumber = RAW_INTERFACE,
436 .AlternateSetting = 0x00,
440 .Class = HID_CSCP_HIDClass,
441 .SubClass = HID_CSCP_NonBootSubclass,
442 .Protocol = HID_CSCP_NonBootProtocol,
444 .InterfaceStrIndex = NO_DESCRIPTOR
449 .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
451 .HIDSpec = VERSION_BCD(1,1,1),
453 .TotalReportDescriptors = 1,
454 .HIDReportType = HID_DTYPE_Report,
455 .HIDReportLength = sizeof(RawReport)
460 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
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
470 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
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
482 #ifdef CONSOLE_ENABLE
485 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
487 .InterfaceNumber = CONSOLE_INTERFACE,
488 .AlternateSetting = 0x00,
492 .Class = HID_CSCP_HIDClass,
493 .SubClass = HID_CSCP_NonBootSubclass,
494 .Protocol = HID_CSCP_NonBootProtocol,
496 .InterfaceStrIndex = NO_DESCRIPTOR
501 .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
503 .HIDSpec = VERSION_BCD(1,1,1),
505 .TotalReportDescriptors = 1,
506 .HIDReportType = HID_DTYPE_Report,
507 .HIDReportLength = sizeof(ConsoleReport)
510 .Console_INEndpoint =
512 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
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
520 .Console_OUTEndpoint =
522 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
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
537 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
539 .InterfaceNumber = NKRO_INTERFACE,
540 .AlternateSetting = 0x00,
544 .Class = HID_CSCP_HIDClass,
545 .SubClass = HID_CSCP_NonBootSubclass,
546 .Protocol = HID_CSCP_NonBootProtocol,
548 .InterfaceStrIndex = NO_DESCRIPTOR
553 .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
555 .HIDSpec = VERSION_BCD(1,1,1),
557 .TotalReportDescriptors = 1,
558 .HIDReportType = HID_DTYPE_Report,
559 .HIDReportLength = sizeof(NKROReport)
564 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
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
574 .Audio_Interface_Association =
576 .Header = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
578 .FirstInterfaceIndex = AC_INTERFACE,
579 .TotalInterfaces = 2,
581 .Class = AUDIO_CSCP_AudioClass,
582 .SubClass = AUDIO_CSCP_ControlSubclass,
583 .Protocol = AUDIO_CSCP_ControlProtocol,
585 .IADStrIndex = NO_DESCRIPTOR,
587 .Audio_ControlInterface =
589 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
591 .InterfaceNumber = AC_INTERFACE,
592 .AlternateSetting = 0,
596 .Class = AUDIO_CSCP_AudioClass,
597 .SubClass = AUDIO_CSCP_ControlSubclass,
598 .Protocol = AUDIO_CSCP_ControlProtocol,
600 .InterfaceStrIndex = NO_DESCRIPTOR
603 .Audio_ControlInterface_SPC =
605 .Header = {.Size = sizeof(USB_Audio_Descriptor_Interface_AC_t), .Type = DTYPE_CSInterface},
606 .Subtype = AUDIO_DSUBTYPE_CSInterface_Header,
608 .ACSpecification = VERSION_BCD(1,0,0),
609 .TotalLength = sizeof(USB_Audio_Descriptor_Interface_AC_t),
612 .InterfaceNumber = AS_INTERFACE,
615 .Audio_StreamInterface =
617 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
619 .InterfaceNumber = AS_INTERFACE,
620 .AlternateSetting = 0,
624 .Class = AUDIO_CSCP_AudioClass,
625 .SubClass = AUDIO_CSCP_MIDIStreamingSubclass,
626 .Protocol = AUDIO_CSCP_StreamingProtocol,
628 .InterfaceStrIndex = NO_DESCRIPTOR
631 .Audio_StreamInterface_SPC =
633 .Header = {.Size = sizeof(USB_MIDI_Descriptor_AudioInterface_AS_t), .Type = DTYPE_CSInterface},
634 .Subtype = AUDIO_DSUBTYPE_CSInterface_General,
636 .AudioSpecification = VERSION_BCD(1,0,0),
638 .TotalLength = offsetof(USB_Descriptor_Configuration_t, MIDI_Out_Jack_Endpoint_SPC)
639 + sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t)
640 - offsetof(USB_Descriptor_Configuration_t, Audio_StreamInterface_SPC)
645 .Header = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = DTYPE_CSInterface},
646 .Subtype = AUDIO_DSUBTYPE_CSInterface_InputTerminal,
648 .JackType = MIDI_JACKTYPE_Embedded,
651 .JackStrIndex = NO_DESCRIPTOR
656 .Header = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = DTYPE_CSInterface},
657 .Subtype = AUDIO_DSUBTYPE_CSInterface_InputTerminal,
659 .JackType = MIDI_JACKTYPE_External,
662 .JackStrIndex = NO_DESCRIPTOR
667 .Header = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = DTYPE_CSInterface},
668 .Subtype = AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
670 .JackType = MIDI_JACKTYPE_Embedded,
674 .SourceJackID = {0x02},
675 .SourcePinID = {0x01},
677 .JackStrIndex = NO_DESCRIPTOR
682 .Header = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = DTYPE_CSInterface},
683 .Subtype = AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
685 .JackType = MIDI_JACKTYPE_External,
689 .SourceJackID = {0x01},
690 .SourcePinID = {0x01},
692 .JackStrIndex = NO_DESCRIPTOR
695 .MIDI_In_Jack_Endpoint =
699 .Header = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint},
701 .EndpointAddress = MIDI_STREAM_OUT_EPADDR,
702 .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
703 .EndpointSize = MIDI_STREAM_EPSIZE,
704 .PollingIntervalMS = 0x05
708 .SyncEndpointNumber = 0
711 .MIDI_In_Jack_Endpoint_SPC =
713 .Header = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = DTYPE_CSEndpoint},
714 .Subtype = AUDIO_DSUBTYPE_CSEndpoint_General,
716 .TotalEmbeddedJacks = 0x01,
717 .AssociatedJackID = {0x01}
720 .MIDI_Out_Jack_Endpoint =
724 .Header = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint},
726 .EndpointAddress = MIDI_STREAM_IN_EPADDR,
727 .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
728 .EndpointSize = MIDI_STREAM_EPSIZE,
729 .PollingIntervalMS = 0x05
733 .SyncEndpointNumber = 0
736 .MIDI_Out_Jack_Endpoint_SPC =
738 .Header = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = DTYPE_CSEndpoint},
739 .Subtype = AUDIO_DSUBTYPE_CSEndpoint_General,
741 .TotalEmbeddedJacks = 0x01,
742 .AssociatedJackID = {0x03}
746 #ifdef VIRTSER_ENABLE
747 .CDC_Interface_Association =
749 .Header = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
751 .FirstInterfaceIndex = CCI_INTERFACE,
752 .TotalInterfaces = 2,
754 .Class = CDC_CSCP_CDCClass,
755 .SubClass = CDC_CSCP_ACMSubclass,
756 .Protocol = CDC_CSCP_ATCommandProtocol,
758 .IADStrIndex = NO_DESCRIPTOR,
763 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
765 .InterfaceNumber = CCI_INTERFACE,
766 .AlternateSetting = 0,
770 .Class = CDC_CSCP_CDCClass,
771 .SubClass = CDC_CSCP_ACMSubclass,
772 .Protocol = CDC_CSCP_ATCommandProtocol,
774 .InterfaceStrIndex = NO_DESCRIPTOR
777 .CDC_Functional_Header =
779 .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = DTYPE_CSInterface},
782 .CDCSpecification = VERSION_BCD(1,1,0),
785 .CDC_Functional_ACM =
787 .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface},
790 .Capabilities = 0x02,
793 .CDC_Functional_Union =
795 .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface},
798 .MasterInterfaceNumber = CCI_INTERFACE,
799 .SlaveInterfaceNumber = CDI_INTERFACE,
802 .CDC_NotificationEndpoint =
804 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
806 .EndpointAddress = CDC_NOTIFICATION_EPADDR,
807 .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
808 .EndpointSize = CDC_NOTIFICATION_EPSIZE,
809 .PollingIntervalMS = 0xFF
814 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
816 .InterfaceNumber = CDI_INTERFACE,
817 .AlternateSetting = 0,
821 .Class = CDC_CSCP_CDCDataClass,
822 .SubClass = CDC_CSCP_NoDataSubclass,
823 .Protocol = CDC_CSCP_NoDataProtocol,
825 .InterfaceStrIndex = NO_DESCRIPTOR
828 .CDC_DataOutEndpoint =
830 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
832 .EndpointAddress = CDC_OUT_EPADDR,
833 .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
834 .EndpointSize = CDC_EPSIZE,
835 .PollingIntervalMS = 0x05
838 .CDC_DataInEndpoint =
840 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
842 .EndpointAddress = CDC_IN_EPADDR,
843 .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
844 .EndpointSize = CDC_EPSIZE,
845 .PollingIntervalMS = 0x05
851 /*******************************************************************************
853 ******************************************************************************/
854 const USB_Descriptor_String_t PROGMEM LanguageString =
856 .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
858 .UnicodeString = {LANGUAGE_ID_ENG}
861 const USB_Descriptor_String_t PROGMEM ManufacturerString =
863 /* subtract 1 for null terminator */
864 .Header = {.Size = USB_STRING_LEN(sizeof(STR(MANUFACTURER))-1), .Type = DTYPE_String},
866 .UnicodeString = LSTR(MANUFACTURER)
869 const USB_Descriptor_String_t PROGMEM ProductString =
871 /* subtract 1 for null terminator */
872 .Header = {.Size = USB_STRING_LEN(sizeof(STR(PRODUCT))-1), .Type = DTYPE_String},
874 .UnicodeString = LSTR(PRODUCT)
877 #ifndef SERIAL_NUMBER
878 #define SERIAL_NUMBER 0
881 const USB_Descriptor_String_t PROGMEM SerialNumberString =
883 /* subtract 1 for null terminator */
884 .Header = {.Size = USB_STRING_LEN(sizeof(STR(SERIAL_NUMBER))-1), .Type = DTYPE_String},
886 .UnicodeString = LSTR(SERIAL_NUMBER)
890 /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
891 * documentation) by the application code so that the address and size of a requested descriptor can be given
892 * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
893 * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
896 uint16_t get_usb_descriptor(const uint16_t wValue,
897 const uint16_t wIndex,
898 const void** const DescriptorAddress)
900 const uint8_t DescriptorType = (wValue >> 8);
901 const uint8_t DescriptorIndex = (wValue & 0xFF);
903 const void* Address = NULL;
904 uint16_t Size = NO_DESCRIPTOR;
906 switch (DescriptorType)
909 Address = &DeviceDescriptor;
910 Size = sizeof(USB_Descriptor_Device_t);
912 case DTYPE_Configuration:
913 Address = &ConfigurationDescriptor;
914 Size = sizeof(USB_Descriptor_Configuration_t);
917 switch (DescriptorIndex )
920 Address = &LanguageString;
921 Size = pgm_read_byte(&LanguageString.Header.Size);
924 Address = &ManufacturerString;
925 Size = pgm_read_byte(&ManufacturerString.Header.Size);
928 Address = &ProductString;
929 Size = pgm_read_byte(&ProductString.Header.Size);
932 Address = &SerialNumberString;
933 Size = pgm_read_byte(&SerialNumberString.Header.Size);
939 case KEYBOARD_INTERFACE:
940 Address = &ConfigurationDescriptor.Keyboard_HID;
941 Size = sizeof(USB_HID_Descriptor_HID_t);
944 case MOUSE_INTERFACE:
945 Address = &ConfigurationDescriptor.Mouse_HID;
946 Size = sizeof(USB_HID_Descriptor_HID_t);
949 #ifdef EXTRAKEY_ENABLE
950 case EXTRAKEY_INTERFACE:
951 Address = &ConfigurationDescriptor.Extrakey_HID;
952 Size = sizeof(USB_HID_Descriptor_HID_t);
957 Address = &ConfigurationDescriptor.Raw_HID;
958 Size = sizeof(USB_HID_Descriptor_HID_t);
961 #ifdef CONSOLE_ENABLE
962 case CONSOLE_INTERFACE:
963 Address = &ConfigurationDescriptor.Console_HID;
964 Size = sizeof(USB_HID_Descriptor_HID_t);
969 Address = &ConfigurationDescriptor.NKRO_HID;
970 Size = sizeof(USB_HID_Descriptor_HID_t);
975 case HID_DTYPE_Report:
977 case KEYBOARD_INTERFACE:
978 Address = &KeyboardReport;
979 Size = sizeof(KeyboardReport);
982 case MOUSE_INTERFACE:
983 Address = &MouseReport;
984 Size = sizeof(MouseReport);
987 #ifdef EXTRAKEY_ENABLE
988 case EXTRAKEY_INTERFACE:
989 Address = &ExtrakeyReport;
990 Size = sizeof(ExtrakeyReport);
995 Address = &RawReport;
996 Size = sizeof(RawReport);
999 #ifdef CONSOLE_ENABLE
1000 case CONSOLE_INTERFACE:
1001 Address = &ConsoleReport;
1002 Size = sizeof(ConsoleReport);
1006 case NKRO_INTERFACE:
1007 Address = &NKROReport;
1008 Size = sizeof(NKROReport);
1015 *DescriptorAddress = Address;