3969ec09 |
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 | /** \file |
40 | * |
41 | * USB Device Descriptors, for library use when in USB device mode. Descriptors are special |
42 | * computer-readable structures which the host requests upon device enumeration, to determine |
43 | * the device's capabilities and functions. |
44 | */ |
45 | |
46 | #include "Descriptors.h" |
47 | |
48 | |
49 | /******************************************************************************* |
50 | * HID Report Descriptors |
51 | ******************************************************************************/ |
52 | const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = |
53 | { |
54 | HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ |
55 | HID_RI_USAGE(8, 0x06), /* Keyboard */ |
56 | HID_RI_COLLECTION(8, 0x01), /* Application */ |
57 | HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */ |
58 | HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */ |
59 | HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */ |
60 | HID_RI_LOGICAL_MINIMUM(8, 0x00), |
61 | HID_RI_LOGICAL_MAXIMUM(8, 0x01), |
62 | HID_RI_REPORT_SIZE(8, 0x01), |
63 | HID_RI_REPORT_COUNT(8, 0x08), |
64 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), |
65 | HID_RI_REPORT_COUNT(8, 0x01), |
66 | HID_RI_REPORT_SIZE(8, 0x08), |
67 | HID_RI_INPUT(8, HID_IOF_CONSTANT), |
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 | HID_RI_LOGICAL_MINIMUM(8, 0x00), |
78 | HID_RI_LOGICAL_MAXIMUM(8, 0x65), |
79 | HID_RI_USAGE_PAGE(8, 0x07), /* Keyboard */ |
80 | HID_RI_USAGE_MINIMUM(8, 0x00), /* Reserved (no event indicated) */ |
81 | HID_RI_USAGE_MAXIMUM(8, 0x65), /* Keyboard Application */ |
82 | HID_RI_REPORT_COUNT(8, 0x06), |
83 | HID_RI_REPORT_SIZE(8, 0x08), |
84 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), |
85 | HID_RI_END_COLLECTION(0), |
86 | }; |
87 | |
88 | const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] = |
89 | { |
90 | HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ |
91 | HID_RI_USAGE(8, 0x02), /* Mouse */ |
92 | HID_RI_COLLECTION(8, 0x01), /* Application */ |
93 | HID_RI_USAGE(8, 0x01), /* Pointer */ |
94 | HID_RI_COLLECTION(8, 0x00), /* Physical */ |
95 | HID_RI_USAGE_PAGE(8, 0x09), /* Button */ |
96 | HID_RI_USAGE_MINIMUM(8, 0x01), |
97 | HID_RI_USAGE_MAXIMUM(8, 0x03), |
98 | HID_RI_LOGICAL_MINIMUM(8, 0x00), |
99 | HID_RI_LOGICAL_MAXIMUM(8, 0x01), |
100 | HID_RI_REPORT_COUNT(8, 0x03), |
101 | HID_RI_REPORT_SIZE(8, 0x01), |
102 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), |
103 | HID_RI_REPORT_COUNT(8, 0x01), |
104 | HID_RI_REPORT_SIZE(8, 0x05), |
105 | HID_RI_INPUT(8, HID_IOF_CONSTANT), |
106 | HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ |
107 | HID_RI_USAGE(8, 0x30), /* Usage X */ |
108 | HID_RI_USAGE(8, 0x31), /* Usage Y */ |
109 | HID_RI_LOGICAL_MINIMUM(8, -1), |
110 | HID_RI_LOGICAL_MAXIMUM(8, 1), |
111 | HID_RI_PHYSICAL_MINIMUM(8, -1), |
112 | HID_RI_PHYSICAL_MAXIMUM(8, 1), |
113 | HID_RI_REPORT_COUNT(8, 0x02), |
114 | HID_RI_REPORT_SIZE(8, 0x08), |
115 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), |
116 | HID_RI_END_COLLECTION(0), |
117 | HID_RI_END_COLLECTION(0), |
118 | }; |
119 | |
120 | const USB_Descriptor_HIDReport_Datatype_t PROGMEM GenericReport[] = |
121 | { |
122 | HID_RI_USAGE_PAGE(16, 0xFF00), /* Vendor Page 0 */ |
123 | HID_RI_USAGE(8, 0x01), /* Vendor Usage 1 */ |
124 | HID_RI_COLLECTION(8, 0x01), /* Vendor Usage 1 */ |
125 | HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */ |
126 | HID_RI_LOGICAL_MINIMUM(8, 0x00), |
127 | HID_RI_LOGICAL_MAXIMUM(8, 0xFF), |
128 | HID_RI_REPORT_SIZE(8, 0x08), |
129 | HID_RI_REPORT_COUNT(8, GENERIC_REPORT_SIZE), |
130 | HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), |
131 | HID_RI_USAGE(8, 0x03), /* Vendor Usage 3 */ |
132 | HID_RI_LOGICAL_MINIMUM(8, 0x00), |
133 | HID_RI_LOGICAL_MAXIMUM(8, 0xFF), |
134 | HID_RI_REPORT_SIZE(8, 0x08), |
135 | HID_RI_REPORT_COUNT(8, GENERIC_REPORT_SIZE), |
136 | HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), |
137 | HID_RI_END_COLLECTION(0), |
138 | }; |
139 | |
140 | |
141 | /******************************************************************************* |
142 | * Device Descriptors |
143 | ******************************************************************************/ |
144 | const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = |
145 | { |
146 | .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device}, |
147 | |
148 | .USBSpecification = VERSION_BCD(01.10), |
149 | .Class = USB_CSCP_NoDeviceClass, |
150 | .SubClass = USB_CSCP_NoDeviceSubclass, |
151 | .Protocol = USB_CSCP_NoDeviceProtocol, |
152 | |
153 | .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, |
154 | |
155 | .VendorID = 0xFEED, |
156 | .ProductID = 0x204D, |
157 | .ReleaseNumber = VERSION_BCD(00.02), |
158 | |
159 | .ManufacturerStrIndex = 0x01, |
160 | .ProductStrIndex = 0x02, |
161 | .SerialNumStrIndex = NO_DESCRIPTOR, |
162 | |
163 | .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS |
164 | }; |
165 | |
166 | /******************************************************************************* |
167 | * Configuration Descriptors |
168 | ******************************************************************************/ |
169 | const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = |
170 | { |
171 | .Config = |
172 | { |
173 | .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration}, |
174 | |
175 | .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), |
176 | .TotalInterfaces = 3, |
177 | |
178 | .ConfigurationNumber = 1, |
179 | .ConfigurationStrIndex = NO_DESCRIPTOR, |
180 | |
181 | .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED), //TODO: bus powered? |
182 | |
183 | .MaxPowerConsumption = USB_CONFIG_POWER_MA(100) |
184 | }, |
185 | |
186 | /* |
187 | * Keyboard |
188 | */ |
189 | .HID1_KeyboardInterface = |
190 | { |
191 | .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, |
192 | |
193 | .InterfaceNumber = 0x00, |
194 | .AlternateSetting = 0x00, |
195 | |
196 | .TotalEndpoints = 2, |
197 | |
198 | .Class = HID_CSCP_HIDClass, |
199 | .SubClass = HID_CSCP_BootSubclass, |
200 | .Protocol = HID_CSCP_KeyboardBootProtocol, |
201 | |
202 | .InterfaceStrIndex = NO_DESCRIPTOR |
203 | }, |
204 | |
205 | .HID1_KeyboardHID = |
206 | { |
207 | .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, |
208 | |
209 | .HIDSpec = VERSION_BCD(01.11), |
210 | .CountryCode = 0x00, |
211 | .TotalReportDescriptors = 1, |
212 | .HIDReportType = HID_DTYPE_Report, |
213 | .HIDReportLength = sizeof(KeyboardReport) |
214 | }, |
215 | |
216 | .HID1_ReportINEndpoint = |
217 | { |
218 | .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, |
219 | |
220 | .EndpointAddress = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM), |
221 | .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), |
222 | .EndpointSize = HID_EPSIZE, |
223 | .PollingIntervalMS = 0x01 |
224 | }, |
225 | |
226 | .HID1_ReportOUTEndpoint = |
227 | { |
228 | .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, |
229 | |
230 | .EndpointAddress = (ENDPOINT_DIR_OUT | KEYBOARD_OUT_EPNUM), |
231 | .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), |
232 | .EndpointSize = HID_EPSIZE, |
233 | .PollingIntervalMS = 0x01 |
234 | }, |
235 | |
236 | /* |
237 | * Mouse |
238 | */ |
239 | .HID2_MouseInterface = |
240 | { |
241 | .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, |
242 | |
243 | .InterfaceNumber = 0x01, |
244 | .AlternateSetting = 0x00, |
245 | |
246 | .TotalEndpoints = 1, |
247 | |
248 | .Class = HID_CSCP_HIDClass, |
249 | .SubClass = HID_CSCP_BootSubclass, |
250 | .Protocol = HID_CSCP_MouseBootProtocol, |
251 | |
252 | .InterfaceStrIndex = NO_DESCRIPTOR |
253 | }, |
254 | |
255 | .HID2_MouseHID = |
256 | { |
257 | .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, |
258 | |
259 | .HIDSpec = VERSION_BCD(01.11), |
260 | .CountryCode = 0x00, |
261 | .TotalReportDescriptors = 1, |
262 | .HIDReportType = HID_DTYPE_Report, |
263 | .HIDReportLength = sizeof(MouseReport) |
264 | }, |
265 | |
266 | .HID2_ReportINEndpoint = |
267 | { |
268 | .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, |
269 | |
270 | .EndpointAddress = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM), |
271 | .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), |
272 | .EndpointSize = HID_EPSIZE, |
273 | .PollingIntervalMS = 0x01 |
274 | }, |
275 | |
276 | /* |
277 | * Generic |
278 | */ |
279 | .HID3_GenericInterface = |
280 | { |
281 | .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, |
282 | |
283 | .InterfaceNumber = 0x02, |
284 | .AlternateSetting = 0x00, |
285 | |
286 | .TotalEndpoints = 2, |
287 | |
288 | .Class = HID_CSCP_HIDClass, |
289 | .SubClass = HID_CSCP_NonBootSubclass, |
290 | .Protocol = HID_CSCP_NonBootProtocol, |
291 | |
292 | .InterfaceStrIndex = NO_DESCRIPTOR |
293 | }, |
294 | |
295 | .HID3_GenericHID = |
296 | { |
297 | .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, |
298 | |
299 | .HIDSpec = VERSION_BCD(01.11), |
300 | .CountryCode = 0x00, |
301 | .TotalReportDescriptors = 1, |
302 | .HIDReportType = HID_DTYPE_Report, |
303 | .HIDReportLength = sizeof(GenericReport) |
304 | }, |
305 | |
306 | .HID3_ReportINEndpoint = |
307 | { |
308 | .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, |
309 | |
310 | .EndpointAddress = (ENDPOINT_DIR_IN | GENERIC_IN_EPNUM), |
311 | .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), |
312 | .EndpointSize = GENERIC_EPSIZE, |
313 | .PollingIntervalMS = 0x01 |
314 | }, |
315 | |
316 | .HID3_ReportOUTEndpoint = |
317 | { |
318 | .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, |
319 | |
320 | .EndpointAddress = (ENDPOINT_DIR_OUT | GENERIC_OUT_EPNUM), |
321 | .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), |
322 | .EndpointSize = GENERIC_EPSIZE, |
323 | .PollingIntervalMS = 0x01 |
324 | } |
325 | }; |
326 | |
327 | |
328 | /******************************************************************************* |
329 | * String Descriptors |
330 | ******************************************************************************/ |
331 | const USB_Descriptor_String_t PROGMEM LanguageString = |
332 | { |
333 | .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String}, |
334 | |
335 | .UnicodeString = {LANGUAGE_ID_ENG} |
336 | }; |
337 | |
338 | const USB_Descriptor_String_t PROGMEM ManufacturerString = |
339 | { |
340 | .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String}, |
341 | |
342 | .UnicodeString = L"Dean Camera" // TODO: |
343 | }; |
344 | |
345 | const USB_Descriptor_String_t PROGMEM ProductString = |
346 | { |
347 | .Header = {.Size = USB_STRING_LEN(28), .Type = DTYPE_String}, |
348 | |
349 | .UnicodeString = L"LUFA Mouse and Keyboard Demo" // TODO: |
350 | }; |
351 | |
352 | |
353 | /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors" |
354 | * documentation) by the application code so that the address and size of a requested descriptor can be given |
355 | * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function |
356 | * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the |
357 | * USB host. |
358 | */ |
359 | uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, |
360 | const uint8_t wIndex, |
361 | const void** const DescriptorAddress) |
362 | { |
363 | const uint8_t DescriptorType = (wValue >> 8); |
364 | const uint8_t DescriptorIndex = (wValue & 0xFF); |
365 | |
366 | const void* Address = NULL; |
367 | uint16_t Size = NO_DESCRIPTOR; |
368 | |
369 | switch (DescriptorType) |
370 | { |
371 | case DTYPE_Device: |
372 | Address = &DeviceDescriptor; |
373 | Size = sizeof(USB_Descriptor_Device_t); |
374 | break; |
375 | case DTYPE_Configuration: |
376 | Address = &ConfigurationDescriptor; |
377 | Size = sizeof(USB_Descriptor_Configuration_t); |
378 | break; |
379 | case DTYPE_String: |
380 | switch (DescriptorIndex ) |
381 | { |
382 | case 0x00: |
383 | Address = &LanguageString; |
384 | Size = pgm_read_byte(&LanguageString.Header.Size); |
385 | break; |
386 | case 0x01: |
387 | Address = &ManufacturerString; |
388 | Size = pgm_read_byte(&ManufacturerString.Header.Size); |
389 | break; |
390 | case 0x02: |
391 | Address = &ProductString; |
392 | Size = pgm_read_byte(&ProductString.Header.Size); |
393 | break; |
394 | } |
395 | break; |
396 | case HID_DTYPE_HID: |
397 | switch (wIndex) { |
398 | case 0: |
399 | Address = &ConfigurationDescriptor.HID1_KeyboardHID; |
400 | Size = sizeof(USB_HID_Descriptor_HID_t); |
401 | break; |
402 | case 1: |
403 | Address = &ConfigurationDescriptor.HID2_MouseHID; |
404 | Size = sizeof(USB_HID_Descriptor_HID_t); |
405 | break; |
406 | case 2: |
407 | Address = &ConfigurationDescriptor.HID3_GenericHID; |
408 | Size = sizeof(USB_HID_Descriptor_HID_t); |
409 | break; |
410 | } |
411 | break; |
412 | case HID_DTYPE_Report: |
413 | switch (wIndex) { |
414 | case 0: |
415 | Address = &KeyboardReport; |
416 | Size = sizeof(KeyboardReport); |
417 | break; |
418 | case 1: |
419 | Address = &MouseReport; |
420 | Size = sizeof(MouseReport); |
421 | break; |
422 | case 2: |
423 | Address = &GenericReport; |
424 | Size = sizeof(GenericReport); |
425 | break; |
426 | } |
427 | break; |
428 | } |
429 | |
430 | *DescriptorAddress = Address; |
431 | return Size; |
432 | } |