I'm trying to educate myself a bit on creating a USB HID descriptor in C for a PIC32 USB project I want to attempt.

I've downloaded the HID Usage Tables document from http://www.usb.org/developers/hidpage/ and trying to figure out where the actual values are indicated for different elements in the HID descriptor.

Let me explain with an excerpt from the sample I'm looking at:

ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={{
  0x05,0x01,        // USAGE_PAGE (Generic Desktop)
  0x09,0x05,        // USAGE (Game Pad)
  0xA1,0x01,        // COLLECTION (Application)
  0x15,0x00,        //   LOGICAL_MINIMUM(0)
  0x25,0x01,        //   LOGICAL_MAXIMUM(1)
  0x35,0x00,        //   PHYSICAL_MINIMUM(0)
  0x45,0x01,        //   PHYSICAL_MAXIMUM(1)
  // ...

From the above example, it is clear that the BYTE array is constituted of key/value pairs, if I may call it that. For example the 2nd line: 0x05,0x01 indicates the key 0x05, which is the Usage Page, and 0x01 is the value indicating Generic Desktop

I'm trying to figure out where these values are indicated in the HID Usage Table PDF document. For instance, I can find no reference that

USAGE_PAGE == 0x05

and for example


I tried searching the PDF for 0xA1, no result. The only way I am able to find out what the values are, is by either looking at the comments of the example, or by using the USB Descriptor Tool from the link above.

I'm just wondering, am I totally daft for missing this key/value reference documentation?

There are loads of examples online, like for example the following link: http://www.frank-zhao.com/cache/hid_tutorial_1.php

But even this references loads of string values like END_COLLECTION == 0xc0

Where do I find the reference for these values? What am I missing?

  • \$\begingroup\$ Looks like I'm going to have to use the USB Descriptor Tool to build the HID descriptor. :) \$\endgroup\$ May 4, 2013 at 17:52

1 Answer 1


The USB documentation is pretty terrible. It suffers from excessive genericization, where they're trying to make everything so generic and general that it's hard to get from the docs to any specific application.

The descriptor format is located in the document called "Device Class Definition for HID" at the link to usb.org you provide.

The critical thing you're missing is that the various segments (such as 0x05) is not documented with the prefix 0x. In fact, they generally describe them in raw binary.

For example, with regard to the 0xA1: enter image description here

You can see that the binary prefix 1010_00nn indicates that is is a collection, and the postfix nnnn_nn01 indicates it is 1 byte long. Then subsequent byte is then interpreted as the collection type, in this case of type Application. This then sets the context in which the further bytes are interpreted, untill the HID descriptor parser either sees another collection tag, or an end collection marker.

You can see that END COLLECTION is specified as 0b1100_00nn, with nn being ignored. This is where the 0xC0 is coming from.

You can also start to see how the other arguments are constructed. For example, LOGICAL MINIMUM is 0x25, or 0b0010_0101. From that, we can see that we have a data-length of 0bnnnn_nn01, or one byte, and the specifier for LOGICAL MINIMUM is 0b0010_01nn

enter image description here

The structure for the USAGE PAGE descriptor is the same. The command to select the usage page is 0000_01nn, and nnnn_nn01 indicates it is 1 byte long. I would guess that, since the documentation states that usage-pages are 32 bits, the upper bits are assumed to be zero, or inferred from another part of the documentation. I actually don't know how they're specified.

There is a good page of the various HID constants here.

And a more recent version from the BSD sources here (Thanks, @crazysim!) (latest HEAD, may not last).

  • \$\begingroup\$ Just what I needed. Thank you so much for the in depth answer. It really helps a lot! ;) \$\endgroup\$ May 5, 2013 at 16:07
  • 1
    \$\begingroup\$ @josef.van.niekerk - No problem. It's been a while before I dug into the USB standards, and they're as opaque as I remembered. \$\endgroup\$ May 6, 2013 at 0:11
  • \$\begingroup\$ I apologise for gravedigging but the link to USB.org doesn’t work any more. \$\endgroup\$ Aug 5, 2015 at 6:51
  • 1
    \$\begingroup\$ @RobvanderVeer should be fixed now. \$\endgroup\$ Aug 5, 2015 at 20:48
  • 1
    \$\begingroup\$ Should that "good page of various HID constants" be changed to a later version of that file from the FreeBSD sources?? \$\endgroup\$ Dec 1, 2015 at 0:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.