Make USB polling rate configurable with a define (#6668)
[jackhill/qmk/firmware.git] / tmk_core / protocol / usb_descriptor.c
... / ...
CommitLineData
1/*
2 * Copyright 2012 Jun Wako <wakojun@gmail.com>
3 * This file is based on:
4 * LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
5 * LUFA-120219/Demos/Device/Lowlevel/GenericHID
6 */
7
8/*
9 LUFA Library
10 Copyright (C) Dean Camera, 2012.
11
12 dean [at] fourwalledcubicle [dot] com
13 www.lufa-lib.org
14*/
15
16/*
17 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
18 Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com)
19
20 Permission to use, copy, modify, distribute, and sell this
21 software and its documentation for any purpose is hereby granted
22 without fee, provided that the above copyright notice appear in
23 all copies and that both that the copyright notice and this
24 permission notice and warranty disclaimer appear in supporting
25 documentation, and that the name of the author not be used in
26 advertising or publicity pertaining to distribution of the
27 software without specific, written prior permission.
28
29 The author disclaim all warranties with regard to this
30 software, including all implied warranties of merchantability
31 and fitness. In no event shall the author be liable for any
32 special, indirect or consequential damages or any damages
33 whatsoever resulting from loss of use, data or profits, whether
34 in an action of contract, negligence or other tortious action,
35 arising out of or in connection with the use or performance of
36 this software.
37*/
38
39#include "util.h"
40#include "report.h"
41#include "usb_descriptor.h"
42
43/*
44 * HID report descriptors
45 */
46#ifdef KEYBOARD_SHARED_EP
47const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
48# define SHARED_REPORT_STARTED
49#else
50const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = {
51#endif
52 HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
53 HID_RI_USAGE(8, 0x06), // Keyboard
54 HID_RI_COLLECTION(8, 0x01), // Application
55#ifdef KEYBOARD_SHARED_EP
56 HID_RI_REPORT_ID(8, REPORT_ID_KEYBOARD),
57#endif
58 // Modifiers (8 bits)
59 HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad
60 HID_RI_USAGE_MINIMUM(8, 0xE0), // Keyboard Left Control
61 HID_RI_USAGE_MAXIMUM(8, 0xE7), // Keyboard Right GUI
62 HID_RI_LOGICAL_MINIMUM(8, 0x00),
63 HID_RI_LOGICAL_MAXIMUM(8, 0x01),
64 HID_RI_REPORT_COUNT(8, 0x08),
65 HID_RI_REPORT_SIZE(8, 0x01),
66 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
67 // Reserved (1 byte)
68 HID_RI_REPORT_COUNT(8, 0x01),
69 HID_RI_REPORT_SIZE(8, 0x08),
70 HID_RI_INPUT(8, HID_IOF_CONSTANT),
71 // Keycodes (6 bytes)
72 HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad
73 HID_RI_USAGE_MINIMUM(8, 0x00),
74 HID_RI_USAGE_MAXIMUM(8, 0xFF),
75 HID_RI_LOGICAL_MINIMUM(8, 0x00),
76 HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
77 HID_RI_REPORT_COUNT(8, 0x06),
78 HID_RI_REPORT_SIZE(8, 0x08),
79 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
80
81 // Status LEDs (5 bits)
82 HID_RI_USAGE_PAGE(8, 0x08), // LED
83 HID_RI_USAGE_MINIMUM(8, 0x01), // Num Lock
84 HID_RI_USAGE_MAXIMUM(8, 0x05), // Kana
85 HID_RI_REPORT_COUNT(8, 0x05),
86 HID_RI_REPORT_SIZE(8, 0x01),
87 HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
88 // LED padding (3 bits)
89 HID_RI_REPORT_COUNT(8, 0x01),
90 HID_RI_REPORT_SIZE(8, 0x03),
91 HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
92 HID_RI_END_COLLECTION(0),
93#ifndef KEYBOARD_SHARED_EP
94};
95#endif
96
97#ifdef MOUSE_ENABLE
98# ifndef MOUSE_SHARED_EP
99const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] = {
100# elif !defined(SHARED_REPORT_STARTED)
101const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
102# define SHARED_REPORT_STARTED
103# endif
104 HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
105 HID_RI_USAGE(8, 0x02), // Mouse
106 HID_RI_COLLECTION(8, 0x01), // Application
107# ifdef MOUSE_SHARED_EP
108 HID_RI_REPORT_ID(8, REPORT_ID_MOUSE),
109# endif
110 HID_RI_USAGE(8, 0x01), // Pointer
111 HID_RI_COLLECTION(8, 0x00), // Physical
112 // Buttons (5 bits)
113 HID_RI_USAGE_PAGE(8, 0x09), // Button
114 HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1
115 HID_RI_USAGE_MAXIMUM(8, 0x05), // Button 5
116 HID_RI_LOGICAL_MINIMUM(8, 0x00),
117 HID_RI_LOGICAL_MAXIMUM(8, 0x01),
118 HID_RI_REPORT_COUNT(8, 0x05),
119 HID_RI_REPORT_SIZE(8, 0x01),
120 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
121 // Button padding (3 bits)
122 HID_RI_REPORT_COUNT(8, 0x01),
123 HID_RI_REPORT_SIZE(8, 0x03),
124 HID_RI_INPUT(8, HID_IOF_CONSTANT),
125
126 // X/Y position (2 bytes)
127 HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
128 HID_RI_USAGE(8, 0x30), // X
129 HID_RI_USAGE(8, 0x31), // Y
130 HID_RI_LOGICAL_MINIMUM(8, -127),
131 HID_RI_LOGICAL_MAXIMUM(8, 127),
132 HID_RI_REPORT_COUNT(8, 0x02),
133 HID_RI_REPORT_SIZE(8, 0x08),
134 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
135
136 // Vertical wheel (1 byte)
137 HID_RI_USAGE(8, 0x38), // Wheel
138 HID_RI_LOGICAL_MINIMUM(8, -127),
139 HID_RI_LOGICAL_MAXIMUM(8, 127),
140 HID_RI_REPORT_COUNT(8, 0x01),
141 HID_RI_REPORT_SIZE(8, 0x08),
142 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
143 // Horizontal wheel (1 byte)
144 HID_RI_USAGE_PAGE(8, 0x0C), // Consumer
145 HID_RI_USAGE(16, 0x0238), // AC Pan
146 HID_RI_LOGICAL_MINIMUM(8, -127),
147 HID_RI_LOGICAL_MAXIMUM(8, 127),
148 HID_RI_REPORT_COUNT(8, 0x01),
149 HID_RI_REPORT_SIZE(8, 0x08),
150 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
151 HID_RI_END_COLLECTION(0),
152 HID_RI_END_COLLECTION(0),
153# ifndef MOUSE_SHARED_EP
154};
155# endif
156#endif
157
158#if defined(SHARED_EP_ENABLE) && !defined(SHARED_REPORT_STARTED)
159const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
160#endif
161
162#ifdef EXTRAKEY_ENABLE
163 HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
164 HID_RI_USAGE(8, 0x80), // System Control
165 HID_RI_COLLECTION(8, 0x01), // Application
166 HID_RI_REPORT_ID(8, REPORT_ID_SYSTEM),
167 HID_RI_USAGE_MINIMUM(16, 0x0081), // System Power Down
168 HID_RI_USAGE_MAXIMUM(16, 0x0083), // System Wake Up
169 HID_RI_LOGICAL_MINIMUM(16, 0x0001),
170 HID_RI_LOGICAL_MAXIMUM(16, 0x0003),
171 HID_RI_REPORT_COUNT(8, 1),
172 HID_RI_REPORT_SIZE(8, 16),
173 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
174 HID_RI_END_COLLECTION(0),
175
176 HID_RI_USAGE_PAGE(8, 0x0C), // Consumer
177 HID_RI_USAGE(8, 0x01), // Consumer Control
178 HID_RI_COLLECTION(8, 0x01), // Application
179 HID_RI_REPORT_ID(8, REPORT_ID_CONSUMER),
180 HID_RI_USAGE_MINIMUM(16, 0x0001), // Consumer Control
181 HID_RI_USAGE_MAXIMUM(16, 0x029C), // AC Distribute Vertically
182 HID_RI_LOGICAL_MINIMUM(16, 0x0001),
183 HID_RI_LOGICAL_MAXIMUM(16, 0x029C),
184 HID_RI_REPORT_COUNT(8, 1),
185 HID_RI_REPORT_SIZE(8, 16),
186 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
187 HID_RI_END_COLLECTION(0),
188#endif
189
190#ifdef NKRO_ENABLE
191 HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
192 HID_RI_USAGE(8, 0x06), // Keyboard
193 HID_RI_COLLECTION(8, 0x01), // Application
194 HID_RI_REPORT_ID(8, REPORT_ID_NKRO),
195 // Modifiers (8 bits)
196 HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad
197 HID_RI_USAGE_MINIMUM(8, 0xE0), // Keyboard Left Control
198 HID_RI_USAGE_MAXIMUM(8, 0xE7), // Keyboard Right GUI
199 HID_RI_LOGICAL_MINIMUM(8, 0x00),
200 HID_RI_LOGICAL_MAXIMUM(8, 0x01),
201 HID_RI_REPORT_COUNT(8, 0x08),
202 HID_RI_REPORT_SIZE(8, 0x01),
203 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
204 // Keycodes
205 HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad
206 HID_RI_USAGE_MINIMUM(8, 0x00),
207 HID_RI_USAGE_MAXIMUM(8, KEYBOARD_REPORT_BITS * 8 - 1),
208 HID_RI_LOGICAL_MINIMUM(8, 0x00),
209 HID_RI_LOGICAL_MAXIMUM(8, 0x01),
210 HID_RI_REPORT_COUNT(8, KEYBOARD_REPORT_BITS * 8),
211 HID_RI_REPORT_SIZE(8, 0x01),
212 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
213
214 // Status LEDs (5 bits)
215 HID_RI_USAGE_PAGE(8, 0x08), // LED
216 HID_RI_USAGE_MINIMUM(8, 0x01), // Num Lock
217 HID_RI_USAGE_MAXIMUM(8, 0x05), // Kana
218 HID_RI_REPORT_COUNT(8, 0x05),
219 HID_RI_REPORT_SIZE(8, 0x01),
220 HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
221 // LED padding (3 bits)
222 HID_RI_REPORT_COUNT(8, 0x01),
223 HID_RI_REPORT_SIZE(8, 0x03),
224 HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
225 HID_RI_END_COLLECTION(0),
226#endif
227#ifdef SHARED_EP_ENABLE
228};
229#endif
230
231#ifdef RAW_ENABLE
232const USB_Descriptor_HIDReport_Datatype_t PROGMEM RawReport[] = {
233 HID_RI_USAGE_PAGE(16, 0xFF60), // Vendor Defined
234 HID_RI_USAGE(8, 0x61), // Vendor Defined
235 HID_RI_COLLECTION(8, 0x01), // Application
236 // Data to host
237 HID_RI_USAGE(8, 0x62), // Vendor Defined
238 HID_RI_LOGICAL_MINIMUM(8, 0x00),
239 HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
240 HID_RI_REPORT_COUNT(8, RAW_EPSIZE),
241 HID_RI_REPORT_SIZE(8, 0x08),
242 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
243 // Data from host
244 HID_RI_USAGE(8, 0x63), // Vendor Defined
245 HID_RI_LOGICAL_MINIMUM(8, 0x00),
246 HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
247 HID_RI_REPORT_COUNT(8, RAW_EPSIZE),
248 HID_RI_REPORT_SIZE(8, 0x08),
249 HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
250 HID_RI_END_COLLECTION(0),
251};
252#endif
253
254#ifdef CONSOLE_ENABLE
255const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = {
256 HID_RI_USAGE_PAGE(16, 0xFF31), // Vendor Defined (PJRC Teensy compatible)
257 HID_RI_USAGE(8, 0x74), // Vendor Defined (PJRC Teensy compatible)
258 HID_RI_COLLECTION(8, 0x01), // Application
259 // Data to host
260 HID_RI_USAGE(8, 0x75), // Vendor Defined
261 HID_RI_LOGICAL_MINIMUM(8, 0x00),
262 HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
263 HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE),
264 HID_RI_REPORT_SIZE(8, 0x08),
265 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
266 // Data from host
267 HID_RI_USAGE(8, 0x76), // Vendor Defined
268 HID_RI_LOGICAL_MINIMUM(8, 0x00),
269 HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
270 HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE),
271 HID_RI_REPORT_SIZE(8, 0x08),
272 HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
273 HID_RI_END_COLLECTION(0),
274};
275#endif
276
277/*
278 * Device descriptor
279 */
280const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = {.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
281 .USBSpecification = VERSION_BCD(1, 1, 0),
282#if VIRTSER_ENABLE
283 .Class = USB_CSCP_IADDeviceClass,
284 .SubClass = USB_CSCP_IADDeviceSubclass,
285 .Protocol = USB_CSCP_IADDeviceProtocol,
286#else
287 .Class = USB_CSCP_NoDeviceClass,
288 .SubClass = USB_CSCP_NoDeviceSubclass,
289 .Protocol = USB_CSCP_NoDeviceProtocol,
290#endif
291 .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
292 // Specified in config.h
293 .VendorID = VENDOR_ID,
294 .ProductID = PRODUCT_ID,
295 .ReleaseNumber = DEVICE_VER,
296 .ManufacturerStrIndex = 0x01,
297 .ProductStrIndex = 0x02,
298 .SerialNumStrIndex = 0x03,
299 .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS};
300
301#ifndef USB_MAX_POWER_CONSUMPTION
302# define USB_MAX_POWER_CONSUMPTION 500
303#endif
304
305#ifndef USB_POLLING_INTERVAL_MS
306# define USB_POLLING_INTERVAL_MS 10
307#endif
308
309/*
310 * Configuration descriptors
311 */
312const USB_Descriptor_Configuration_t PROGMEM
313 ConfigurationDescriptor =
314 {
315 .Config = {.Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration}, .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), .TotalInterfaces = TOTAL_INTERFACES, .ConfigurationNumber = 1, .ConfigurationStrIndex = NO_DESCRIPTOR, .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP), .MaxPowerConsumption = USB_CONFIG_POWER_MA(USB_MAX_POWER_CONSUMPTION)},
316
317#ifndef KEYBOARD_SHARED_EP
318 /*
319 * Keyboard
320 */
321 .Keyboard_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
322 .InterfaceNumber = KEYBOARD_INTERFACE,
323 .AlternateSetting = 0x00,
324 .TotalEndpoints = 1,
325 .Class = HID_CSCP_HIDClass,
326 .SubClass = HID_CSCP_BootSubclass,
327 .Protocol = HID_CSCP_KeyboardBootProtocol,
328
329 .InterfaceStrIndex = NO_DESCRIPTOR},
330 .Keyboard_HID = {.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, .HIDSpec = VERSION_BCD(1, 1, 1), .CountryCode = 0x00, .TotalReportDescriptors = 1, .HIDReportType = HID_DTYPE_Report, .HIDReportLength = sizeof(KeyboardReport)},
331 .Keyboard_INEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = KEYBOARD_EPSIZE, .PollingIntervalMS = USB_POLLING_INTERVAL_MS},
332#endif
333
334#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
335 /*
336 * Mouse
337 */
338 .Mouse_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .InterfaceNumber = MOUSE_INTERFACE, .AlternateSetting = 0x00, .TotalEndpoints = 1, .Class = HID_CSCP_HIDClass, .SubClass = HID_CSCP_BootSubclass, .Protocol = HID_CSCP_MouseBootProtocol, .InterfaceStrIndex = NO_DESCRIPTOR},
339 .Mouse_HID = {.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, .HIDSpec = VERSION_BCD(1, 1, 1), .CountryCode = 0x00, .TotalReportDescriptors = 1, .HIDReportType = HID_DTYPE_Report, .HIDReportLength = sizeof(MouseReport)},
340 .Mouse_INEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = MOUSE_EPSIZE, .PollingIntervalMS = USB_POLLING_INTERVAL_MS},
341#endif
342
343#ifdef SHARED_EP_ENABLE
344 /*
345 * Shared
346 */
347 .Shared_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
348 .InterfaceNumber = SHARED_INTERFACE,
349 .AlternateSetting = 0x00,
350 .TotalEndpoints = 1,
351 .Class = HID_CSCP_HIDClass,
352# ifdef KEYBOARD_SHARED_EP
353 .SubClass = HID_CSCP_BootSubclass,
354 .Protocol = HID_CSCP_KeyboardBootProtocol,
355# else
356 .SubClass = HID_CSCP_NonBootSubclass,
357 .Protocol = HID_CSCP_NonBootProtocol,
358# endif
359 .InterfaceStrIndex = NO_DESCRIPTOR},
360 .Shared_HID = {.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, .HIDSpec = VERSION_BCD(1, 1, 1), .CountryCode = 0x00, .TotalReportDescriptors = 1, .HIDReportType = HID_DTYPE_Report, .HIDReportLength = sizeof(SharedReport)},
361 .Shared_INEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_IN | SHARED_IN_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = SHARED_EPSIZE, .PollingIntervalMS = USB_POLLING_INTERVAL_MS},
362#endif
363
364#ifdef RAW_ENABLE
365 /*
366 * Raw HID
367 */
368 .Raw_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .InterfaceNumber = RAW_INTERFACE, .AlternateSetting = 0x00, .TotalEndpoints = 2, .Class = HID_CSCP_HIDClass, .SubClass = HID_CSCP_NonBootSubclass, .Protocol = HID_CSCP_NonBootProtocol, .InterfaceStrIndex = NO_DESCRIPTOR},
369 .Raw_HID = {.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, .HIDSpec = VERSION_BCD(1, 1, 1), .CountryCode = 0x00, .TotalReportDescriptors = 1, .HIDReportType = HID_DTYPE_Report, .HIDReportLength = sizeof(RawReport)},
370 .Raw_INEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_IN | RAW_IN_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = RAW_EPSIZE, .PollingIntervalMS = 0x01},
371 .Raw_OUTEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_OUT | RAW_OUT_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = RAW_EPSIZE, .PollingIntervalMS = 0x01},
372#endif
373
374#ifdef CONSOLE_ENABLE
375 /*
376 * Console
377 */
378 .Console_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .InterfaceNumber = CONSOLE_INTERFACE, .AlternateSetting = 0x00, .TotalEndpoints = 2, .Class = HID_CSCP_HIDClass, .SubClass = HID_CSCP_NonBootSubclass, .Protocol = HID_CSCP_NonBootProtocol, .InterfaceStrIndex = NO_DESCRIPTOR},
379 .Console_HID = {.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, .HIDSpec = VERSION_BCD(1, 1, 1), .CountryCode = 0x00, .TotalReportDescriptors = 1, .HIDReportType = HID_DTYPE_Report, .HIDReportLength = sizeof(ConsoleReport)},
380 .Console_INEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_IN | CONSOLE_IN_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = CONSOLE_EPSIZE, .PollingIntervalMS = 0x01},
381 .Console_OUTEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = (ENDPOINT_DIR_OUT | CONSOLE_OUT_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = CONSOLE_EPSIZE, .PollingIntervalMS = 0x01},
382#endif
383
384#ifdef MIDI_ENABLE
385 /*
386 * MIDI
387 */
388 .Audio_Interface_Association =
389 {
390 .Header = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
391 .FirstInterfaceIndex = AC_INTERFACE,
392 .TotalInterfaces = 2,
393 .Class = AUDIO_CSCP_AudioClass,
394 .SubClass = AUDIO_CSCP_ControlSubclass,
395 .Protocol = AUDIO_CSCP_ControlProtocol,
396 .IADStrIndex = NO_DESCRIPTOR,
397 },
398 .Audio_ControlInterface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
399
400 .InterfaceNumber = AC_INTERFACE,
401 .AlternateSetting = 0,
402 .TotalEndpoints = 0,
403 .Class = AUDIO_CSCP_AudioClass,
404 .SubClass = AUDIO_CSCP_ControlSubclass,
405 .Protocol = AUDIO_CSCP_ControlProtocol,
406 .InterfaceStrIndex = NO_DESCRIPTOR},
407 .Audio_ControlInterface_SPC =
408 {
409 .Header = {.Size = sizeof(USB_Audio_Descriptor_Interface_AC_t), .Type = AUDIO_DTYPE_CSInterface},
410 .Subtype = AUDIO_DSUBTYPE_CSInterface_Header,
411 .ACSpecification = VERSION_BCD(1, 0, 0),
412 .TotalLength = sizeof(USB_Audio_Descriptor_Interface_AC_t),
413 .InCollection = 1,
414 .InterfaceNumber = AS_INTERFACE,
415 },
416 .Audio_StreamInterface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
417
418 .InterfaceNumber = AS_INTERFACE,
419 .AlternateSetting = 0,
420 .TotalEndpoints = 2,
421 .Class = AUDIO_CSCP_AudioClass,
422 .SubClass = AUDIO_CSCP_MIDIStreamingSubclass,
423 .Protocol = AUDIO_CSCP_StreamingProtocol,
424 .InterfaceStrIndex = NO_DESCRIPTOR},
425 .Audio_StreamInterface_SPC = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_AudioInterface_AS_t), .Type = AUDIO_DTYPE_CSInterface}, .Subtype = AUDIO_DSUBTYPE_CSInterface_General, .AudioSpecification = VERSION_BCD(1, 0, 0), .TotalLength = offsetof(USB_Descriptor_Configuration_t, MIDI_Out_Jack_Endpoint_SPC) + sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t) - offsetof(USB_Descriptor_Configuration_t, Audio_StreamInterface_SPC)},
426 .MIDI_In_Jack_Emb = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = AUDIO_DTYPE_CSInterface}, .Subtype = AUDIO_DSUBTYPE_CSInterface_InputTerminal, .JackType = MIDI_JACKTYPE_Embedded, .JackID = 0x01, .JackStrIndex = NO_DESCRIPTOR},
427 .MIDI_In_Jack_Ext = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = AUDIO_DTYPE_CSInterface}, .Subtype = AUDIO_DSUBTYPE_CSInterface_InputTerminal, .JackType = MIDI_JACKTYPE_External, .JackID = 0x02, .JackStrIndex = NO_DESCRIPTOR},
428 .MIDI_Out_Jack_Emb = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = AUDIO_DTYPE_CSInterface}, .Subtype = AUDIO_DSUBTYPE_CSInterface_OutputTerminal, .JackType = MIDI_JACKTYPE_Embedded, .JackID = 0x03, .NumberOfPins = 1, .SourceJackID = {0x02}, .SourcePinID = {0x01}, .JackStrIndex = NO_DESCRIPTOR},
429 .MIDI_Out_Jack_Ext = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = AUDIO_DTYPE_CSInterface}, .Subtype = AUDIO_DSUBTYPE_CSInterface_OutputTerminal, .JackType = MIDI_JACKTYPE_External, .JackID = 0x04, .NumberOfPins = 1, .SourceJackID = {0x01}, .SourcePinID = {0x01}, .JackStrIndex = NO_DESCRIPTOR},
430 .MIDI_In_Jack_Endpoint = {.Endpoint = {.Header = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint}, .EndpointAddress = MIDI_STREAM_OUT_EPADDR, .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = MIDI_STREAM_EPSIZE, .PollingIntervalMS = 0x05},
431
432 .Refresh = 0,
433 .SyncEndpointNumber = 0},
434 .MIDI_In_Jack_Endpoint_SPC = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = AUDIO_DSUBTYPE_CSEndpoint_General}, .Subtype = AUDIO_DSUBTYPE_CSEndpoint_General, .TotalEmbeddedJacks = 0x01, .AssociatedJackID = {0x01}},
435 .MIDI_Out_Jack_Endpoint = {.Endpoint = {.Header = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint}, .EndpointAddress = MIDI_STREAM_IN_EPADDR, .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = MIDI_STREAM_EPSIZE, .PollingIntervalMS = 0x05},
436
437 .Refresh = 0,
438 .SyncEndpointNumber = 0},
439 .MIDI_Out_Jack_Endpoint_SPC = {.Header = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = AUDIO_DTYPE_CSEndpoint}, .Subtype = AUDIO_DSUBTYPE_CSEndpoint_General, .TotalEmbeddedJacks = 0x01, .AssociatedJackID = {0x03}},
440#endif
441
442#ifdef VIRTSER_ENABLE
443 /*
444 * Virtual Serial
445 */
446 .CDC_Interface_Association =
447 {
448 .Header = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
449 .FirstInterfaceIndex = CCI_INTERFACE,
450 .TotalInterfaces = 2,
451 .Class = CDC_CSCP_CDCClass,
452 .SubClass = CDC_CSCP_ACMSubclass,
453 .Protocol = CDC_CSCP_ATCommandProtocol,
454 .IADStrIndex = NO_DESCRIPTOR,
455 },
456 .CDC_CCI_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .InterfaceNumber = CCI_INTERFACE, .AlternateSetting = 0, .TotalEndpoints = 1, .Class = CDC_CSCP_CDCClass, .SubClass = CDC_CSCP_ACMSubclass, .Protocol = CDC_CSCP_ATCommandProtocol, .InterfaceStrIndex = NO_DESCRIPTOR},
457 .CDC_Functional_Header =
458 {
459 .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = CDC_DTYPE_CSInterface},
460 .Subtype = 0x00,
461 .CDCSpecification = VERSION_BCD(1, 1, 0),
462 },
463 .CDC_Functional_ACM =
464 {
465 .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = CDC_DTYPE_CSInterface},
466 .Subtype = 0x02,
467 .Capabilities = 0x02,
468 },
469 .CDC_Functional_Union =
470 {
471 .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = CDC_DTYPE_CSInterface},
472 .Subtype = 0x06,
473 .MasterInterfaceNumber = CCI_INTERFACE,
474 .SlaveInterfaceNumber = CDI_INTERFACE,
475 },
476 .CDC_NotificationEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = CDC_NOTIFICATION_EPADDR, .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = CDC_NOTIFICATION_EPSIZE, .PollingIntervalMS = 0xFF},
477 .CDC_DCI_Interface = {.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .InterfaceNumber = CDI_INTERFACE, .AlternateSetting = 0, .TotalEndpoints = 2, .Class = CDC_CSCP_CDCDataClass, .SubClass = CDC_CSCP_NoDataSubclass, .Protocol = CDC_CSCP_NoDataProtocol, .InterfaceStrIndex = NO_DESCRIPTOR},
478 .CDC_DataOutEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = CDC_OUT_EPADDR, .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = CDC_EPSIZE, .PollingIntervalMS = 0x05},
479 .CDC_DataInEndpoint = {.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .EndpointAddress = CDC_IN_EPADDR, .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = CDC_EPSIZE, .PollingIntervalMS = 0x05},
480#endif
481};
482
483/*
484 * String descriptors
485 */
486const USB_Descriptor_String_t PROGMEM LanguageString = {.Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String}, .UnicodeString = {LANGUAGE_ID_ENG}};
487
488const USB_Descriptor_String_t PROGMEM ManufacturerString = {.Header = {.Size = USB_STRING_LEN(sizeof(STR(MANUFACTURER)) - 1), // Subtract 1 for null terminator
489 .Type = DTYPE_String},
490 .UnicodeString = LSTR(MANUFACTURER)};
491
492const USB_Descriptor_String_t PROGMEM ProductString = {.Header = {.Size = USB_STRING_LEN(sizeof(STR(PRODUCT)) - 1), // Subtract 1 for null terminator
493 .Type = DTYPE_String},
494 .UnicodeString = LSTR(PRODUCT)};
495
496#ifndef SERIAL_NUMBER
497# define SERIAL_NUMBER 0
498#endif
499
500const USB_Descriptor_String_t PROGMEM SerialNumberString = {.Header = {.Size = USB_STRING_LEN(sizeof(STR(SERIAL_NUMBER)) - 1), // Subtract 1 for null terminator
501 .Type = DTYPE_String},
502 .UnicodeString = LSTR(SERIAL_NUMBER)};
503
504/**
505 * This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
506 * documentation) by the application code so that the address and size of a requested descriptor can be given
507 * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
508 * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
509 * USB host.
510 */
511uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress) {
512 const uint8_t DescriptorType = (wValue >> 8);
513 const uint8_t DescriptorIndex = (wValue & 0xFF);
514 const void* Address = NULL;
515 uint16_t Size = NO_DESCRIPTOR;
516
517 switch (DescriptorType) {
518 case DTYPE_Device:
519 Address = &DeviceDescriptor;
520 Size = sizeof(USB_Descriptor_Device_t);
521
522 break;
523 case DTYPE_Configuration:
524 Address = &ConfigurationDescriptor;
525 Size = sizeof(USB_Descriptor_Configuration_t);
526
527 break;
528 case DTYPE_String:
529 switch (DescriptorIndex) {
530 case 0x00:
531 Address = &LanguageString;
532 Size = pgm_read_byte(&LanguageString.Header.Size);
533
534 break;
535 case 0x01:
536 Address = &ManufacturerString;
537 Size = pgm_read_byte(&ManufacturerString.Header.Size);
538
539 break;
540 case 0x02:
541 Address = &ProductString;
542 Size = pgm_read_byte(&ProductString.Header.Size);
543
544 break;
545 case 0x03:
546 Address = &SerialNumberString;
547 Size = pgm_read_byte(&SerialNumberString.Header.Size);
548
549 break;
550 }
551
552 break;
553 case HID_DTYPE_HID:
554 switch (wIndex) {
555#ifndef KEYBOARD_SHARED_EP
556 case KEYBOARD_INTERFACE:
557 Address = &ConfigurationDescriptor.Keyboard_HID;
558 Size = sizeof(USB_HID_Descriptor_HID_t);
559 break;
560#endif
561
562#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
563 case MOUSE_INTERFACE:
564 Address = &ConfigurationDescriptor.Mouse_HID;
565 Size = sizeof(USB_HID_Descriptor_HID_t);
566
567 break;
568#endif
569
570#ifdef SHARED_EP_ENABLE
571 case SHARED_INTERFACE:
572 Address = &ConfigurationDescriptor.Shared_HID;
573 Size = sizeof(USB_HID_Descriptor_HID_t);
574
575 break;
576#endif
577
578#ifdef RAW_ENABLE
579 case RAW_INTERFACE:
580 Address = &ConfigurationDescriptor.Raw_HID;
581 Size = sizeof(USB_HID_Descriptor_HID_t);
582
583 break;
584#endif
585
586#ifdef CONSOLE_ENABLE
587 case CONSOLE_INTERFACE:
588 Address = &ConfigurationDescriptor.Console_HID;
589 Size = sizeof(USB_HID_Descriptor_HID_t);
590
591 break;
592#endif
593 }
594
595 break;
596 case HID_DTYPE_Report:
597 switch (wIndex) {
598#ifndef KEYBOARD_SHARED_EP
599 case KEYBOARD_INTERFACE:
600 Address = &KeyboardReport;
601 Size = sizeof(KeyboardReport);
602
603 break;
604#endif
605
606#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
607 case MOUSE_INTERFACE:
608 Address = &MouseReport;
609 Size = sizeof(MouseReport);
610
611 break;
612#endif
613
614#ifdef SHARED_EP_ENABLE
615 case SHARED_INTERFACE:
616 Address = &SharedReport;
617 Size = sizeof(SharedReport);
618
619 break;
620#endif
621
622#ifdef RAW_ENABLE
623 case RAW_INTERFACE:
624 Address = &RawReport;
625 Size = sizeof(RawReport);
626
627 break;
628#endif
629
630#ifdef CONSOLE_ENABLE
631 case CONSOLE_INTERFACE:
632 Address = &ConsoleReport;
633 Size = sizeof(ConsoleReport);
634
635 break;
636#endif
637 }
638
639 break;
640 }
641
642 *DescriptorAddress = Address;
643
644 return Size;
645}