descriptors.c (10494B)
1 /* 2 MNT Reform 2.0 Keyboard Firmware 3 See keyboard.c for Copyright 4 SPDX-License-Identifier: MIT 5 */ 6 7 /** \file 8 * 9 * USB Device Descriptors, for library use when in USB device mode. Descriptors are special 10 * computer-readable structures which the host requests upon device enumeration, to determine 11 * the device's capabilities and functions. 12 */ 13 14 #include "Config/LUFAConfig.h" 15 #include "descriptors.h" 16 17 18 /** HID class report descriptor. This is a special descriptor constructed with values from the 19 * USBIF HID class specification to describe the reports and capabilities of the HID device. This 20 * descriptor is parsed by the host and its contents used to determine what data (and in what encoding) 21 * the device will send, and what it may be sent back from the host. Refer to the HID specification for 22 * more details on HID report descriptors. 23 */ 24 const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = 25 { 26 /* Use the HID class driver's standard Keyboard report. 27 * Max simultaneous keys: 6 28 */ 29 HID_DESCRIPTOR_KEYBOARD(6) 30 }; 31 32 /** HID class report descriptor. This is a special descriptor constructed with values from the 33 * USBIF HID class specification to describe the reports and capabilities of the HID device. This 34 * descriptor is parsed by the host and its contents used to determine what data (and in what encoding) 35 * the device will send, and what it may be sent back from the host. Refer to the HID specification for 36 * more details on HID report descriptors. 37 */ 38 const USB_Descriptor_HIDReport_Datatype_t PROGMEM MediaControlReport[] = 39 { 40 HID_RI_USAGE_PAGE(8, 0x0C), /* Consumer Page */ 41 HID_RI_USAGE(8, 0x01), /* Consumer Controls */ 42 HID_RI_COLLECTION(8, 0x01), /* Application */ 43 HID_RI_USAGE(8, 0x70), /* Display Brightness Decrement */ 44 HID_RI_USAGE(8, 0x6F), /* Display Brightness Increment */ 45 HID_RI_USAGE(8, 0xB6), /* Previous Track */ 46 HID_RI_USAGE(8, 0xCD), /* Play/Pause (toggle) */ 47 HID_RI_USAGE(8, 0xB5), /* Next Track */ 48 HID_RI_USAGE(8, 0xE2), /* Mute */ 49 HID_RI_USAGE(8, 0xEA), /* Volume Down */ 50 HID_RI_USAGE(8, 0xE9), /* Volume Up */ 51 HID_RI_REPORT_SIZE(8, 0x01), 52 HID_RI_REPORT_COUNT(8, 0x08), 53 HID_RI_LOGICAL_MINIMUM(8, 0), 54 HID_RI_LOGICAL_MAXIMUM(8, 1), 55 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), 56 HID_RI_END_COLLECTION(0), 57 }; 58 59 /** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall 60 * device characteristics, including the supported USB version, control endpoint size and the 61 * number of device configurations. The descriptor is read out by the USB host when the enumeration 62 * process begins. 63 */ 64 const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = 65 { 66 .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device}, 67 68 .USBSpecification = VERSION_BCD(1,1,0), 69 .Class = USB_CSCP_NoDeviceClass, 70 .SubClass = USB_CSCP_NoDeviceSubclass, 71 .Protocol = USB_CSCP_NoDeviceProtocol, 72 73 .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, 74 75 .VendorID = 0x03EB, 76 .ProductID = 0x2042, 77 .ReleaseNumber = VERSION_BCD(0,0,1), 78 79 .ManufacturerStrIndex = STRING_ID_Manufacturer, 80 .ProductStrIndex = STRING_ID_Product, 81 .SerialNumStrIndex = NO_DESCRIPTOR, 82 83 .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS 84 }; 85 86 /** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage 87 * of the device in one of its supported configurations, including information about any device interfaces 88 * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting 89 * a configuration so that the host may correctly communicate with the USB device. 90 */ 91 const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = 92 { 93 .Config = 94 { 95 .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration}, 96 97 .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), 98 .TotalInterfaces = 2, 99 100 .ConfigurationNumber = 1, 101 .ConfigurationStrIndex = NO_DESCRIPTOR, 102 103 .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED), 104 105 .MaxPowerConsumption = USB_CONFIG_POWER_MA(100) 106 }, 107 108 .HID1_KeyboardInterface = 109 { 110 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, 111 112 .InterfaceNumber = INTERFACE_ID_Keyboard, 113 .AlternateSetting = 0x00, 114 115 .TotalEndpoints = 1, 116 117 .Class = HID_CSCP_HIDClass, 118 .SubClass = HID_CSCP_BootSubclass, 119 .Protocol = HID_CSCP_KeyboardBootProtocol, 120 121 .InterfaceStrIndex = NO_DESCRIPTOR 122 }, 123 124 .HID1_KeyboardHID = 125 { 126 .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, 127 128 .HIDSpec = VERSION_BCD(1,1,1), 129 .CountryCode = 0x00, 130 .TotalReportDescriptors = 1, 131 .HIDReportType = HID_DTYPE_Report, 132 .HIDReportLength = sizeof(KeyboardReport) 133 }, 134 135 .HID1_ReportINEndpoint = 136 { 137 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, 138 139 .EndpointAddress = KEYBOARD_EPADDR, 140 .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), 141 .EndpointSize = HID_EPSIZE, 142 .PollingIntervalMS = 10 143 }, 144 145 .HID2_MediaControlInterface = 146 { 147 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, 148 149 .InterfaceNumber = INTERFACE_ID_MediaControl, 150 .AlternateSetting = 0x00, 151 152 .TotalEndpoints = 1, 153 154 .Class = HID_CSCP_HIDClass, 155 .SubClass = HID_CSCP_NonBootSubclass, 156 .Protocol = HID_CSCP_NonBootProtocol, 157 158 .InterfaceStrIndex = NO_DESCRIPTOR 159 }, 160 161 .HID2_MediaControlHID = 162 { 163 .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, 164 165 .HIDSpec = VERSION_BCD(1,1,1), 166 .CountryCode = 0x00, 167 .TotalReportDescriptors = 1, 168 .HIDReportType = HID_DTYPE_Report, 169 .HIDReportLength = sizeof(MediaControlReport) 170 }, 171 172 .HID2_ReportINEndpoint = 173 { 174 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, 175 176 .EndpointAddress = MEDIACONTROL_EPADDR, 177 .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), 178 .EndpointSize = HID_EPSIZE, 179 .PollingIntervalMS = 100 180 }, 181 }; 182 183 /** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests 184 * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate 185 * via the language ID table available at USB.org what languages the device supports for its string descriptors. 186 */ 187 const USB_Descriptor_String_t PROGMEM LanguageString = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG); 188 189 /** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable 190 * form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device 191 * Descriptor. 192 */ 193 const USB_Descriptor_String_t PROGMEM ManufacturerString = USB_STRING_DESCRIPTOR(L"MNT"); 194 195 /** Product descriptor string. This is a Unicode string containing the product's details in human readable form, 196 * and is read out upon request by the host when the appropriate string ID is requested, listed in the Device 197 * Descriptor. 198 */ 199 const USB_Descriptor_String_t PROGMEM ProductString = USB_STRING_DESCRIPTOR(L"Reform Keyboard"); 200 201 /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors" 202 * documentation) by the application code so that the address and size of a requested descriptor can be given 203 * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function 204 * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the 205 * USB host. 206 */ 207 uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, 208 const uint16_t wIndex, 209 const void** const DescriptorAddress) 210 { 211 const uint8_t DescriptorType = (wValue >> 8); 212 const uint8_t DescriptorNumber = (wValue & 0xFF); 213 214 const void* Address = NULL; 215 uint16_t Size = NO_DESCRIPTOR; 216 217 switch (DescriptorType) 218 { 219 case DTYPE_Device: 220 Address = &DeviceDescriptor; 221 Size = sizeof(USB_Descriptor_Device_t); 222 break; 223 case DTYPE_Configuration: 224 Address = &ConfigurationDescriptor; 225 Size = sizeof(USB_Descriptor_Configuration_t); 226 break; 227 case DTYPE_String: 228 switch (DescriptorNumber) 229 { 230 case STRING_ID_Language: 231 Address = &LanguageString; 232 Size = pgm_read_byte(&LanguageString.Header.Size); 233 break; 234 case STRING_ID_Manufacturer: 235 Address = &ManufacturerString; 236 Size = pgm_read_byte(&ManufacturerString.Header.Size); 237 break; 238 case STRING_ID_Product: 239 Address = &ProductString; 240 Size = pgm_read_byte(&ProductString.Header.Size); 241 break; 242 } 243 break; 244 case HID_DTYPE_HID: 245 switch (wIndex) 246 { 247 case INTERFACE_ID_Keyboard: 248 Address = &ConfigurationDescriptor.HID1_KeyboardHID; 249 Size = sizeof(USB_HID_Descriptor_HID_t); 250 break; 251 case INTERFACE_ID_MediaControl: 252 Address = &ConfigurationDescriptor.HID2_MediaControlHID; 253 Size = sizeof(USB_HID_Descriptor_HID_t); 254 break; 255 } 256 break; 257 case HID_DTYPE_Report: 258 switch (wIndex) 259 { 260 case INTERFACE_ID_Keyboard: 261 Address = &KeyboardReport; 262 Size = sizeof(KeyboardReport); 263 break; 264 case INTERFACE_ID_MediaControl: 265 Address = &MediaControlReport; 266 Size = sizeof(MediaControlReport); 267 break; 268 } 269 break; 270 } 271 272 *DescriptorAddress = Address; 273 return Size; 274 }