Custom HID device HID report descriptor

后端 未结 5 1849
误落风尘
误落风尘 2020-12-24 04:45

I have a bit of a problem with generating a HID descriptor. I want to use simple reports with ID1 for input and ID2 for output with 64 bytes of data.

I realized that

5条回答
  •  清歌不尽
    2020-12-24 05:15

    1. All the official documentation is available on usb.org. To understand HID Report Descriptors you need to read some of the documents on the HID Information page. In particular, you should try to understand:

      • The "Device Class Definition for HID 1.11" document - which describes the Human Interface Device report format
      • The "HID Usage Tables 1.12" document - which describes the values of many Usage Pages and Usages within those pages that can appear in a Report Descriptor

      Having said that, the documentation is notoriously obtuse and will require considerable effort to digest.

    2. REPORT_SIZE is the size of a report in bits not bytes. Think of REPORT_SIZE as the width of a field (in bits) and the REPORT_COUNT as the number of fields (of that width). This is made clear in the "Device Class Definition for HID 1.11" document, Section 6.2.2.7 "Global Items" as follows:

      Global Item Tag     One-byte Prefix    Description
      Report Size         0111 01 nn         Unsigned integer specifying the size of the report
                                             fields in bits. This allows the parser to build an
                                             item map for the report handler to use. For more
                                             information, see Section 8: Report Protocol.
      
    3. As a guide, a reasonable (i.e I haven't tested it) Report Descriptor that describes a 64-byte input buffer (to the host with a REPORT_ID of 0x01) and a 64-byte output buffer (from the host with a REPORT_ID of 0x02) could be as follows:

        0x06, 0x00, 0xFF,            // (GLOBAL) USAGE_PAGE         0xFF00 Vendor-defined 
        0xA1, 0x01,                  // (MAIN)   COLLECTION         0x01 Application (Usage=0x0: Page=, Usage=, Type=) <-- Warning: USAGE type should be CA (Application)
        0x15, 0x00,                  //   (GLOBAL) LOGICAL_MINIMUM    0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0
        0x26, 0xFF, 0x00,            //   (GLOBAL) LOGICAL_MAXIMUM    0x00FF (255) 
        0x75, 0x08,                  //   (GLOBAL) REPORT_SIZE        0x08 (8) Number of bits per field 
        0x85, 0x01,                  //   (GLOBAL) REPORT_ID          0x01 (1) 
        0x95, 0x40,                  //   (GLOBAL) REPORT_COUNT       0x40 (64) Number of fields 
        0x09, 0x01,                  //   (LOCAL)  USAGE              0xFF000001  
        0x81, 0x02,                  //   (MAIN)   INPUT              0x00000002 (64 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap 
        0x85, 0x02,                  //   (GLOBAL) REPORT_ID          0x02 (2) 
        0x09, 0x01,                  //   (LOCAL)  USAGE              0xFF000001  
        0x91, 0x02,                  //   (MAIN)   OUTPUT             0x00000002 (64 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap 
        0xC0,                        // (MAIN)   END_COLLECTION     Application
      

      Which corresponds to the following C-language structure definitions:

      //--------------------------------------------------------------------------------
      // Vendor-defined inputReport 01 (Device --> Host)
      //--------------------------------------------------------------------------------
      
      typedef struct
      {
        uint8_t  reportId;                                 // Report ID = 0x01 (1)
        uint8_t  VEN_VendorDefined0001[64];                // FF00 0001  Value = 0 to 255
      } inputReport01_t;
      
      //--------------------------------------------------------------------------------
      // Vendor-defined outputReport 02 (Device <-- Host)
      //--------------------------------------------------------------------------------
      
      typedef struct
      {
        uint8_t  reportId;                                 // Report ID = 0x02 (2)
        uint8_t  VEN_VendorDefined0001[64];                // FF00 0001  Value = 0 to 255
      } outputReport02_t;
      
    4. Should you specify LOGICAL_MINIMUM and LOGICAL_MAXIMUM for each report? No.

      Some items are GLOBAL (which means that, as the report descriptor is parsed sequentially, their values remain until they are explicitly changed by another GLOBAL item) and others are LOCAL (which means that their values are reset to defaults whenever a MAIN item is encountered). Both LOGICAL_MINIMUM and LOGICAL_MAXIMUM are GLOBAL items, so you only need to re-specify their values if you want the value to change. In my opinion, the specification would have been clearer if the official names for items were prefixed by GLOBAL_, LOCAL_ and MAIN_ but unfortunately we all have to live with the spec as it stands.

    5. The above example was decoded using a free tool on SourceForge called hidrdd

提交回复
热议问题