Files
mon_PocketVoltex/Firmware/Keyboard/Descriptors.c
T
2016-10-30 02:09:42 +10:00

454 lines
17 KiB
C

/** \file
*
* USB Device Descriptors, for library use when in USB device mode. Descriptors are special
* computer-readable structures which the host requests upon device enumeration, to determine
* the device's capabilities and functions.
*/
#include "Descriptors.h"
/** HID class report descriptor. This is a special descriptor constructed with values from the
* USBIF HID class specification to describe the reports and capabilities of the HID device. This
* descriptor is parsed by the host and its contents used to determine what data (and in what encoding)
* the device will send, and what it may be sent back from the host. Refer to the HID specification for
* more details on HID report descriptors.
*/
const USB_Descriptor_HIDReport_Datatype_t PROGMEM GenericReport[] =
{
HID_RI_USAGE_PAGE(16, 0xFFDC), /* Vendor Page 0xDC */
HID_RI_USAGE(8, 0xFB), /* Vendor Usage 0xFB */
HID_RI_COLLECTION(8, 0x01), /* Vendor Usage 1 */
// Global Items
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
HID_RI_REPORT_SIZE(8, 8),
HID_RI_REPORT_COUNT(8, CONFIG_BYTES),
// Write config
HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
// Read config
HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
HID_RI_END_COLLECTION(0),
};
const USB_Descriptor_HIDReport_Datatype_t PROGMEM LEDReport[] =
{
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
HID_RI_USAGE(8, 0x00), /* Undefined */
HID_RI_COLLECTION(8, 0x01), /* Application */
// Global Items
HID_RI_REPORT_COUNT(8, LED_TOTAL_COUNT),
HID_RI_REPORT_SIZE(8, 8),
HID_RI_LOGICAL_MINIMUM(8, 0),
HID_RI_LOGICAL_MAXIMUM(8, BRIGHTNESS_LEVELS-1),
HID_RI_USAGE_PAGE(8, 0x0A), // Ordinals
// Locals repeated for INPUT/OUTPUT
0x79, STRING_ID_LED_INDIV, //HID_RI_STRING_MINIMUM(8, STRING_ID_LED_INDIV),
0x89, STRING_ID_LED_INDIV + LED_TOTAL_COUNT, //HID_RI_STRING_MAXIMUM(8, STRING_ID_LED_INDIV + LED_COUNT),
HID_RI_USAGE_MINIMUM(8, 1), // LED 1
HID_RI_USAGE_MAXIMUM(8, LED_TOTAL_COUNT), // LED 8
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
// INPUT is also needed to be recognised by Bemanitools
0x79, STRING_ID_LED_INDIV, //HID_RI_STRING_MINIMUM(8, STRING_ID_LED_INDIV),
0x89, STRING_ID_LED_INDIV + LED_TOTAL_COUNT, //HID_RI_STRING_MAXIMUM(8, STRING_ID_LED_INDIV + LED_COUNT),
HID_RI_USAGE_MINIMUM(8, 1), // LED 1
HID_RI_USAGE_MAXIMUM(8, LED_TOTAL_COUNT), // LED 8
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
HID_RI_END_COLLECTION(0),
};
/** HID class report descriptor. This is a special descriptor constructed with values from the
* USBIF HID class specification to describe the reports and capabilities of the HID device. This
* descriptor is parsed by the host and its contents used to determine what data (and in what encoding)
* the device will send, and what it may be sent back from the host. Refer to the HID specification for
* more details on HID report descriptors.
*/
const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
{
// Use the HID class driver's standard Keyboard report
HID_DESCRIPTOR_KEYBOARD(SWITCH_COUNT)
};
/** HID class report descriptor. This is a special descriptor constructed with values from the
* USBIF HID class specification to describe the reports and capabilities of the HID device. This
* descriptor is parsed by the host and its contents used to determine what data (and in what encoding)
* the device will send, and what it may be sent back from the host. Refer to the HID specification for
* more details on HID report descriptors.
*
* This descriptor describes the mouse HID interface's report structure.
*/
const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
{
/* Use the HID class driver's standard Mouse report.
* Min X/Y Axis values: -128
* Max X/Y Axis values: 127
* Min physical X/Y Axis values (used to determine resolution): -128
* Max physical X/Y Axis values (used to determine resolution): 127
* NOTE: need at least 1 button or report does not work
* Buttons: 1
* Absolute screen coordinates: false
*/
HID_DESCRIPTOR_MOUSE(-128, 127, -128, 127, 1, false)
};
/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
* device characteristics, including the supported USB version, control endpoint size and the
* number of device configurations. The descriptor is read out by the USB host when the enumeration
* process begins.
*/
const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
{
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
.USBSpecification = VERSION_BCD(1,1,0),
.Class = USB_CSCP_NoDeviceClass,
.SubClass = USB_CSCP_NoDeviceSubclass,
.Protocol = USB_CSCP_NoDeviceProtocol,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
// mon.im VID/PID pair, unique!
.VendorID = 0x16D0,
.ProductID = 0x0A6D,
.ReleaseNumber = VERSION_BCD(0,0,1),
.ManufacturerStrIndex = STRING_ID_Manufacturer,
.ProductStrIndex = STRING_ID_Product,
.SerialNumStrIndex = STRING_ID_Product,
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
};
/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
* of the device in one of its supported configurations, including information about any device interfaces
* and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
* a configuration so that the host may correctly communicate with the USB device.
*/
const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
{
.Config =
{
.Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
.TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
.TotalInterfaces = 4,
.ConfigurationNumber = 1,
.ConfigurationStrIndex = STRING_ID_Product,
.ConfigAttributes = USB_CONFIG_ATTR_RESERVED,
.MaxPowerConsumption = USB_CONFIG_POWER_MA(500)
},
.HID1_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = INTERFACE_ID_Keyboard,
.AlternateSetting = 0x00,
.TotalEndpoints = 1,
.Class = HID_CSCP_HIDClass,
.SubClass = HID_CSCP_NonBootSubclass,
.Protocol = HID_CSCP_NonBootProtocol,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.HID1_KeyboardHID =
{
.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)
},
.HID1_ReportINEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = KEYBOARD_EPADDR,
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = KEYBOARD_EPSIZE,
.PollingIntervalMS = 0x01
},
.HID2_MouseInterface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = INTERFACE_ID_Mouse,
.AlternateSetting = 0x00,
.TotalEndpoints = 1,
.Class = HID_CSCP_HIDClass,
.SubClass = HID_CSCP_BootSubclass,
.Protocol = HID_CSCP_MouseBootProtocol,
.InterfaceStrIndex = STRING_ID_KNOB
},
.HID2_MouseHID =
{
.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)
},
.HID2_ReportINEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = MOUSE_IN_EPADDR,
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = MOUSE_EPSIZE,
.PollingIntervalMS = 0x01
},
.HID3_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = INTERFACE_ID_Generic,
.AlternateSetting = 0x00,
.TotalEndpoints = 1,
.Class = HID_CSCP_HIDClass,
.SubClass = HID_CSCP_NonBootSubclass,
.Protocol = HID_CSCP_NonBootProtocol,
.InterfaceStrIndex = STRING_ID_Config
},
.HID3_VendorHID =
{
.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(GenericReport)
},
.HID3_ReportINEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = GENERIC_EPADDR,
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = GENERIC_EPSIZE,
.PollingIntervalMS = 255
},
.HID4_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = INTERFACE_ID_LED,
.AlternateSetting = 0x00,
.TotalEndpoints = 1,
.Class = HID_CSCP_HIDClass,
.SubClass = HID_CSCP_NonBootSubclass,
.Protocol = HID_CSCP_NonBootProtocol,
.InterfaceStrIndex = STRING_ID_LED
},
.HID4_LEDHID =
{
.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(LEDReport)
},
.HID4_ReportINEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = LED_EPADDR,
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = LED_EPSIZE,
.PollingIntervalMS = 15
},
};
/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
* the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
* via the language ID table available at USB.org what languages the device supports for its string descriptors.
*/
const USB_Descriptor_String_t PROGMEM LanguageString = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG);
/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
* form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
const USB_Descriptor_String_t PROGMEM ManufacturerString = USB_STRING_DESCRIPTOR(L"mon.im");
/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
* and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
const USB_Descriptor_String_t PROGMEM ProductString = USB_STRING_DESCRIPTOR(L"Pocket Voltex");
const USB_Descriptor_String_t PROGMEM ConfigString = USB_STRING_DESCRIPTOR(L"Pocket Voltex Config");
const USB_Descriptor_String_t PROGMEM LEDString = USB_STRING_DESCRIPTOR(L"Pocket Voltex LEDs");
const USB_Descriptor_String_t PROGMEM KnobString = USB_STRING_DESCRIPTOR(L"Pocket Voltex Knobs");
const USB_Descriptor_String_t PROGMEM LEDString_indiv[] = {
USB_STRING_DESCRIPTOR(L"L1-B"),
USB_STRING_DESCRIPTOR(L"L1-G"),
USB_STRING_DESCRIPTOR(L"L1-R"),
USB_STRING_DESCRIPTOR(L"L2-B"),
USB_STRING_DESCRIPTOR(L"L2-G"),
USB_STRING_DESCRIPTOR(L"L2-R"),
USB_STRING_DESCRIPTOR(L"L3-B"),
USB_STRING_DESCRIPTOR(L"L3-G"),
USB_STRING_DESCRIPTOR(L"L3-R"),
USB_STRING_DESCRIPTOR(L"L4-B"),
USB_STRING_DESCRIPTOR(L"L4-G"),
USB_STRING_DESCRIPTOR(L"L4-R"),
USB_STRING_DESCRIPTOR(L"L5-B"),
USB_STRING_DESCRIPTOR(L"L5-G"),
USB_STRING_DESCRIPTOR(L"L5-R"),
USB_STRING_DESCRIPTOR(L"L6-B"),
USB_STRING_DESCRIPTOR(L"L6-G"),
USB_STRING_DESCRIPTOR(L"L6-R"),
USB_STRING_DESCRIPTOR(L"L7-B"),
USB_STRING_DESCRIPTOR(L"L7-G"),
USB_STRING_DESCRIPTOR(L"L7-R"),
USB_STRING_DESCRIPTOR(L"L8-B"),
USB_STRING_DESCRIPTOR(L"L8-G"),
USB_STRING_DESCRIPTOR(L"L8-R"),
USB_STRING_DESCRIPTOR(L"BT-A"),
USB_STRING_DESCRIPTOR(L"BT-B"),
USB_STRING_DESCRIPTOR(L"BT-C"),
USB_STRING_DESCRIPTOR(L"BT-D"),
USB_STRING_DESCRIPTOR(L"FX-L"),
USB_STRING_DESCRIPTOR(L"FX-R"),
};
/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
* documentation) by the application code so that the address and size of a requested descriptor can be given
* to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
* is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
* USB host.
*/
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
const uint8_t wIndex,
const void** const DescriptorAddress)
{
const uint8_t DescriptorType = (wValue >> 8);
const uint8_t DescriptorNumber = (wValue & 0xFF);
const void* Address = NULL;
uint16_t Size = NO_DESCRIPTOR;
switch (DescriptorType)
{
case DTYPE_Device:
Address = &DeviceDescriptor;
Size = sizeof(USB_Descriptor_Device_t);
break;
case DTYPE_Configuration:
Address = &ConfigurationDescriptor;
Size = sizeof(USB_Descriptor_Configuration_t);
break;
case DTYPE_String:
switch (DescriptorNumber)
{
case STRING_ID_Language:
Address = &LanguageString;
Size = pgm_read_byte(&LanguageString.Header.Size);
break;
case STRING_ID_Manufacturer:
Address = &ManufacturerString;
Size = pgm_read_byte(&ManufacturerString.Header.Size);
break;
case STRING_ID_Product:
Address = &ProductString;
Size = pgm_read_byte(&ProductString.Header.Size);
break;
case STRING_ID_Config:
Address = &ConfigString;
Size = pgm_read_byte(&ConfigString.Header.Size);
break;
case STRING_ID_LED:
Address = &LEDString;
Size = pgm_read_byte(&LEDString.Header.Size);
break;
case STRING_ID_KNOB:
Address = &KnobString;
Size = pgm_read_byte(&KnobString.Header.Size);
break;
default:
if(DescriptorNumber >= STRING_ID_LED_INDIV) {
Address = &(LEDString_indiv[STRING_ID_LED_INDIV - DescriptorNumber]);
Size = pgm_read_byte(&LEDString_indiv[STRING_ID_LED_INDIV - DescriptorNumber].Header.Size);
}
}
break;
case HID_DTYPE_HID:
Size = sizeof(USB_HID_Descriptor_HID_t);
switch (wIndex) {
case INTERFACE_ID_Keyboard:
Address = &ConfigurationDescriptor.HID1_KeyboardHID;
break;
case INTERFACE_ID_Mouse:
Address = &ConfigurationDescriptor.HID2_MouseHID;
break;
case INTERFACE_ID_Generic:
Address = &ConfigurationDescriptor.HID3_VendorHID;
break;
case INTERFACE_ID_LED:
Address = &ConfigurationDescriptor.HID4_LEDHID;
break;
}
break;
case HID_DTYPE_Report:
switch (wIndex) {
case INTERFACE_ID_Keyboard:
Address = &KeyboardReport;
Size = sizeof(KeyboardReport);
break;
case INTERFACE_ID_Mouse:
Address = &MouseReport;
Size = sizeof(MouseReport);
break;
case INTERFACE_ID_Generic:
Address = &GenericReport;
Size = sizeof(GenericReport);
break;
case INTERFACE_ID_LED:
Address = &LEDReport;
Size = sizeof(LEDReport);
break;
}
break;
}
*DescriptorAddress = Address;
return Size;
}