reform

MNT Reform: Open Source Portable Computer
Log (Feed) | Files | Refs (Tags) | README

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 }