]> git.donarmstrong.com Git - tmk_firmware.git/blob - protocol/lufa/descriptor.c
Make console compatible with PJRC hid_listen.
[tmk_firmware.git] / protocol / lufa / descriptor.c
1 /* 
2  * Copyright 2012 Jun Wako <wakojun@gmail.com>
3  * This file is based on:
4  *     LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
5  *     LUFA-120219/Demos/Device/Lowlevel/GenericHID
6  */
7
8 /*
9              LUFA Library
10      Copyright (C) Dean Camera, 2012.
11
12   dean [at] fourwalledcubicle [dot] com
13            www.lufa-lib.org
14 */
15
16 /*
17   Copyright 2012  Dean Camera (dean [at] fourwalledcubicle [dot] com)
18   Copyright 2010  Denver Gingerich (denver [at] ossguy [dot] com)
19
20   Permission to use, copy, modify, distribute, and sell this
21   software and its documentation for any purpose is hereby granted
22   without fee, provided that the above copyright notice appear in
23   all copies and that both that the copyright notice and this
24   permission notice and warranty disclaimer appear in supporting
25   documentation, and that the name of the author not be used in
26   advertising or publicity pertaining to distribution of the
27   software without specific, written prior permission.
28
29   The author disclaim all warranties with regard to this
30   software, including all implied warranties of merchantability
31   and fitness.  In no event shall the author be liable for any
32   special, indirect or consequential damages or any damages
33   whatsoever resulting from loss of use, data or profits, whether
34   in an action of contract, negligence or other tortious action,
35   arising out of or in connection with the use or performance of
36   this software.
37 */
38
39 #include "util.h"
40 #include "report.h"
41 #include "descriptor.h"
42
43
44 /*******************************************************************************
45  * HID Report Descriptors
46  ******************************************************************************/
47 const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
48 {
49     HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
50     HID_RI_USAGE(8, 0x06), /* Keyboard */
51     HID_RI_COLLECTION(8, 0x01), /* Application */
52         HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
53         HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
54         HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
55         HID_RI_LOGICAL_MINIMUM(8, 0x00),
56         HID_RI_LOGICAL_MAXIMUM(8, 0x01),
57         HID_RI_REPORT_SIZE(8, 0x01),
58         HID_RI_REPORT_COUNT(8, 0x08),
59         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
60         HID_RI_REPORT_COUNT(8, 0x01),
61         HID_RI_REPORT_SIZE(8, 0x08),
62         HID_RI_INPUT(8, HID_IOF_CONSTANT),
63         HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
64         HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
65         HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
66         HID_RI_REPORT_COUNT(8, 0x05),
67         HID_RI_REPORT_SIZE(8, 0x01),
68         HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
69         HID_RI_REPORT_COUNT(8, 0x01),
70         HID_RI_REPORT_SIZE(8, 0x03),
71         HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
72         HID_RI_LOGICAL_MINIMUM(8, 0x00),
73         HID_RI_LOGICAL_MAXIMUM(8, 0x65),
74         HID_RI_USAGE_PAGE(8, 0x07), /* Keyboard */
75         HID_RI_USAGE_MINIMUM(8, 0x00), /* Reserved (no event indicated) */
76         HID_RI_USAGE_MAXIMUM(8, 0x65), /* Keyboard Application */
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     HID_RI_END_COLLECTION(0),
81 };
82
83 const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
84 {
85     HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
86     HID_RI_USAGE(8, 0x02), /* Mouse */
87     HID_RI_COLLECTION(8, 0x01), /* Application */
88         HID_RI_USAGE(8, 0x01), /* Pointer */
89         HID_RI_COLLECTION(8, 0x00), /* Physical */
90
91             HID_RI_USAGE_PAGE(8, 0x09), /* Button */
92             HID_RI_USAGE_MINIMUM(8, 0x01),  /* Button 1 */
93             HID_RI_USAGE_MAXIMUM(8, 0x05),  /* Button 5 */
94             HID_RI_LOGICAL_MINIMUM(8, 0x00),
95             HID_RI_LOGICAL_MAXIMUM(8, 0x01),
96             HID_RI_REPORT_COUNT(8, 0x05),
97             HID_RI_REPORT_SIZE(8, 0x01),
98             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
99             HID_RI_REPORT_COUNT(8, 0x01),
100             HID_RI_REPORT_SIZE(8, 0x03),
101             HID_RI_INPUT(8, HID_IOF_CONSTANT),
102
103             HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
104             HID_RI_USAGE(8, 0x30), /* Usage X */
105             HID_RI_USAGE(8, 0x31), /* Usage Y */
106             HID_RI_LOGICAL_MINIMUM(8, -127),
107             HID_RI_LOGICAL_MAXIMUM(8, 127),
108             HID_RI_REPORT_COUNT(8, 0x02),
109             HID_RI_REPORT_SIZE(8, 0x08),
110             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
111
112             HID_RI_USAGE(8, 0x38), /* Wheel */
113             HID_RI_LOGICAL_MINIMUM(8, -127),
114             HID_RI_LOGICAL_MAXIMUM(8, 127),
115             HID_RI_REPORT_COUNT(8, 0x01),
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_PAGE(8, 0x0C), /* Consumer */
120             HID_RI_USAGE(16, 0x0238), /* AC Pan (Horizontal wheel) */
121             HID_RI_LOGICAL_MINIMUM(8, -127),
122             HID_RI_LOGICAL_MAXIMUM(8, 127),
123             HID_RI_REPORT_COUNT(8, 0x01),
124             HID_RI_REPORT_SIZE(8, 0x08),
125             HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
126
127         HID_RI_END_COLLECTION(0),
128     HID_RI_END_COLLECTION(0),
129 };
130
131 const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] =
132 {
133     HID_RI_USAGE_PAGE(16, 0xFF31), /* Vendor Page(PJRC Teensy compatible) */
134     HID_RI_USAGE(8, 0x74), /* Vendor Usage(PJRC Teensy compatible) */
135     HID_RI_COLLECTION(8, 0x01), /* Application */
136         HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */
137         HID_RI_LOGICAL_MINIMUM(8, 0x00),
138         HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
139         HID_RI_REPORT_SIZE(8, 0x08),
140         HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE),
141         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
142         HID_RI_USAGE(8, 0x03), /* Vendor Usage 3 */
143         HID_RI_LOGICAL_MINIMUM(8, 0x00),
144         HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
145         HID_RI_REPORT_SIZE(8, 0x08),
146         HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE),
147         HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
148     HID_RI_END_COLLECTION(0),
149 };
150
151 const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtraReport[] =
152 {
153     HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
154     HID_RI_USAGE(8, 0x80), /* System Control */
155     HID_RI_COLLECTION(8, 0x01), /* Application */
156         HID_RI_REPORT_ID(8, REPORT_ID_SYSTEM),
157         HID_RI_LOGICAL_MINIMUM(16, 0x0081),
158         HID_RI_LOGICAL_MAXIMUM(16, 0x00B7),
159         HID_RI_USAGE_MINIMUM(16, 0x0081), /* System Power Down */
160         HID_RI_USAGE_MAXIMUM(16, 0x00B7), /* System Display LCD Autoscale */
161         HID_RI_REPORT_SIZE(8, 16),
162         HID_RI_REPORT_COUNT(8, 1),
163         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
164     HID_RI_END_COLLECTION(0),
165
166     HID_RI_USAGE_PAGE(8, 0x0C), /* Consumer */
167     HID_RI_USAGE(8, 0x01), /* Consumer Control */
168     HID_RI_COLLECTION(8, 0x01), /* Application */
169         HID_RI_REPORT_ID(8, REPORT_ID_CONSUMER),
170         HID_RI_LOGICAL_MINIMUM(16, 0x0010),
171         HID_RI_LOGICAL_MAXIMUM(16, 0x029C),
172         HID_RI_USAGE_MINIMUM(16, 0x0010), /* +10 */
173         HID_RI_USAGE_MAXIMUM(16, 0x029C), /* AC Distribute Vertically */
174         HID_RI_REPORT_SIZE(8, 16),
175         HID_RI_REPORT_COUNT(8, 1),
176         HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
177     HID_RI_END_COLLECTION(0),
178 };
179
180 /*******************************************************************************
181  * Device Descriptors
182  ******************************************************************************/
183 const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
184 {
185     .Header                 = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
186
187     .USBSpecification       = VERSION_BCD(01.10),
188     .Class                  = USB_CSCP_NoDeviceClass,
189     .SubClass               = USB_CSCP_NoDeviceSubclass,
190     .Protocol               = USB_CSCP_NoDeviceProtocol,
191
192     .Endpoint0Size          = FIXED_CONTROL_ENDPOINT_SIZE,
193
194     .VendorID               = VENDOR_ID,
195     .ProductID              = PRODUCT_ID,
196     .ReleaseNumber          = DEVICE_VER,
197
198     .ManufacturerStrIndex   = 0x01,
199     .ProductStrIndex        = 0x02,
200     .SerialNumStrIndex      = NO_DESCRIPTOR,
201
202     .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
203 };
204
205 /*******************************************************************************
206  * Configuration Descriptors
207  ******************************************************************************/
208 const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
209 {
210     .Config =
211         {
212             .Header                 = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
213
214             .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
215             .TotalInterfaces        = TOTAL_INTERFACES,
216
217             .ConfigurationNumber    = 1,
218             .ConfigurationStrIndex  = NO_DESCRIPTOR,
219
220             .ConfigAttributes       = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP),
221
222             .MaxPowerConsumption    = USB_CONFIG_POWER_MA(100)
223         },
224
225     /*
226      * Keyboard
227      */
228     .Keyboard_Interface =
229         {
230             .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
231
232             .InterfaceNumber        = KEYBOARD_INTERFACE,
233             .AlternateSetting       = 0x00,
234
235             .TotalEndpoints         = 1,
236
237             .Class                  = HID_CSCP_HIDClass,
238             .SubClass               = HID_CSCP_BootSubclass,
239             .Protocol               = HID_CSCP_KeyboardBootProtocol,
240
241             .InterfaceStrIndex      = NO_DESCRIPTOR
242         },
243
244     .Keyboard_HID =
245         {
246             .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
247
248             .HIDSpec                = VERSION_BCD(01.11),
249             .CountryCode            = 0x00,
250             .TotalReportDescriptors = 1,
251             .HIDReportType          = HID_DTYPE_Report,
252             .HIDReportLength        = sizeof(KeyboardReport)
253         },
254
255     .Keyboard_INEndpoint =
256         {
257             .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
258
259             .EndpointAddress        = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM),
260             .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
261             .EndpointSize           = KEYBOARD_EPSIZE,
262             .PollingIntervalMS      = 0x01
263         },
264
265     /*
266      * Mouse
267      */
268     .Mouse_Interface =
269         {
270             .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
271
272             .InterfaceNumber        = MOUSE_INTERFACE,
273             .AlternateSetting       = 0x00,
274
275             .TotalEndpoints         = 1,
276
277             .Class                  = HID_CSCP_HIDClass,
278             .SubClass               = HID_CSCP_BootSubclass,
279             .Protocol               = HID_CSCP_MouseBootProtocol,
280
281             .InterfaceStrIndex      = NO_DESCRIPTOR
282         },
283
284     .Mouse_HID =
285         {
286             .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
287
288             .HIDSpec                = VERSION_BCD(01.11),
289             .CountryCode            = 0x00,
290             .TotalReportDescriptors = 1,
291             .HIDReportType          = HID_DTYPE_Report,
292             .HIDReportLength        = sizeof(MouseReport)
293         },
294
295     .Mouse_INEndpoint =
296         {
297             .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
298
299             .EndpointAddress        = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM),
300             .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
301             .EndpointSize           = MOUSE_EPSIZE,
302             .PollingIntervalMS      = 0x01
303         },
304
305     /*
306      * Console
307      */
308     .Console_Interface =
309         {
310             .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
311
312             .InterfaceNumber        = CONSOLE_INTERFACE,
313             .AlternateSetting       = 0x00,
314
315             .TotalEndpoints         = 2,
316
317             .Class                  = HID_CSCP_HIDClass,
318             .SubClass               = HID_CSCP_NonBootSubclass,
319             .Protocol               = HID_CSCP_NonBootProtocol,
320
321             .InterfaceStrIndex      = NO_DESCRIPTOR
322         },
323
324     .Console_HID =
325         {
326             .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
327
328             .HIDSpec                = VERSION_BCD(01.11),
329             .CountryCode            = 0x00,
330             .TotalReportDescriptors = 1,
331             .HIDReportType          = HID_DTYPE_Report,
332             .HIDReportLength        = sizeof(ConsoleReport)
333         },
334
335     .Console_INEndpoint =
336         {
337             .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
338
339             .EndpointAddress        = (ENDPOINT_DIR_IN | CONSOLE_IN_EPNUM),
340             .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
341             .EndpointSize           = CONSOLE_EPSIZE,
342             .PollingIntervalMS      = 0x01
343         },
344
345     .Console_OUTEndpoint =
346         {
347             .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
348
349             .EndpointAddress        = (ENDPOINT_DIR_OUT | CONSOLE_OUT_EPNUM),
350             .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
351             .EndpointSize           = CONSOLE_EPSIZE,
352             .PollingIntervalMS      = 0x01
353         },
354
355     /*
356      * Extra
357      */
358     .Extra_Interface =
359         {
360             .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
361
362             .InterfaceNumber        = EXTRA_INTERFACE,
363             .AlternateSetting       = 0x00,
364
365             .TotalEndpoints         = 1,
366
367             .Class                  = HID_CSCP_HIDClass,
368             .SubClass               = HID_CSCP_NonBootSubclass,
369             .Protocol               = HID_CSCP_NonBootProtocol,
370
371             .InterfaceStrIndex      = NO_DESCRIPTOR
372         },
373
374     .Extra_HID =
375         {
376             .Header                 = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
377
378             .HIDSpec                = VERSION_BCD(01.11),
379             .CountryCode            = 0x00,
380             .TotalReportDescriptors = 1,
381             .HIDReportType          = HID_DTYPE_Report,
382             .HIDReportLength        = sizeof(ExtraReport)
383         },
384
385     .Extra_INEndpoint =
386         {
387             .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
388
389             .EndpointAddress        = (ENDPOINT_DIR_IN | EXTRA_IN_EPNUM),
390             .Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
391             .EndpointSize           = EXTRA_EPSIZE,
392             .PollingIntervalMS      = 0x01
393         },
394 };
395
396
397 /*******************************************************************************
398  * String Descriptors
399  ******************************************************************************/
400 const USB_Descriptor_String_t PROGMEM LanguageString =
401 {
402     .Header                 = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
403
404     .UnicodeString          = {LANGUAGE_ID_ENG}
405 };
406
407 const USB_Descriptor_String_t PROGMEM ManufacturerString =
408 {
409     .Header                 = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
410
411     .UnicodeString          = LSTR(MANUFACTURER)
412 };
413
414 const USB_Descriptor_String_t PROGMEM ProductString =
415 {
416     .Header                 = {.Size = USB_STRING_LEN(28), .Type = DTYPE_String},
417
418     .UnicodeString          = LSTR(PRODUCT)
419 };
420
421
422 /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
423  *  documentation) by the application code so that the address and size of a requested descriptor can be given
424  *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
425  *  is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
426  *  USB host.
427  */
428 uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
429                                     const uint8_t wIndex,
430                                     const void** const DescriptorAddress)
431 {
432     const uint8_t  DescriptorType   = (wValue >> 8);
433     const uint8_t  DescriptorIndex  = (wValue & 0xFF);
434
435     const void* Address = NULL;
436     uint16_t    Size    = NO_DESCRIPTOR;
437
438     switch (DescriptorType)
439     {
440         case DTYPE_Device:
441             Address = &DeviceDescriptor;
442             Size    = sizeof(USB_Descriptor_Device_t);
443             break;
444         case DTYPE_Configuration:
445             Address = &ConfigurationDescriptor;
446             Size    = sizeof(USB_Descriptor_Configuration_t);
447             break;
448         case DTYPE_String:
449             switch (DescriptorIndex )
450             {
451                 case 0x00:
452                     Address = &LanguageString;
453                     Size    = pgm_read_byte(&LanguageString.Header.Size);
454                     break;
455                 case 0x01:
456                     Address = &ManufacturerString;
457                     Size    = pgm_read_byte(&ManufacturerString.Header.Size);
458                     break;
459                 case 0x02:
460                     Address = &ProductString;
461                     Size    = pgm_read_byte(&ProductString.Header.Size);
462                     break;
463             }
464             break;
465         case HID_DTYPE_HID:
466             switch (wIndex) {
467             case KEYBOARD_INTERFACE:
468                 Address = &ConfigurationDescriptor.Keyboard_HID;
469                 Size    = sizeof(USB_HID_Descriptor_HID_t);
470                 break;
471             case MOUSE_INTERFACE:
472                 Address = &ConfigurationDescriptor.Mouse_HID;
473                 Size    = sizeof(USB_HID_Descriptor_HID_t);
474                 break;
475             case CONSOLE_INTERFACE:
476                 Address = &ConfigurationDescriptor.Console_HID;
477                 Size    = sizeof(USB_HID_Descriptor_HID_t);
478                 break;
479             case EXTRA_INTERFACE:
480                 Address = &ConfigurationDescriptor.Extra_HID;
481                 Size    = sizeof(USB_HID_Descriptor_HID_t);
482                 break;
483             }
484             break;
485         case HID_DTYPE_Report:
486             switch (wIndex) {
487             case KEYBOARD_INTERFACE:
488                 Address = &KeyboardReport;
489                 Size    = sizeof(KeyboardReport);
490                 break;
491             case MOUSE_INTERFACE:
492                 Address = &MouseReport;
493                 Size    = sizeof(MouseReport);
494                 break;
495             case CONSOLE_INTERFACE:
496                 Address = &ConsoleReport;
497                 Size    = sizeof(ConsoleReport);
498                 break;
499             case EXTRA_INTERFACE:
500                 Address = &ExtraReport;
501                 Size    = sizeof(ExtraReport);
502                 break;
503             }
504             break;
505     }
506
507     *DescriptorAddress = Address;
508     return Size;
509 }