potentially a lot of things!). If you would like to reach me, send an email to jeremy (dot) 006 (at) gmail (dot) com. Thanks!

back to posts

an important rule for programming USB HID descriptors

It is very important to remember that when building USB HID device descriptors, you need to make sure the number of bits being sent is divisble by 8. For example, A descriptor for a gamepad with 2 bits for each axis and 4 buttons might look like this:

0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
0x09, 0x05,                    // USAGE (Game Pad)
0xa1, 0x01,                    // COLLECTION (Application)
0x09, 0x01,                    //   USAGE (Pointer)
0xa1, 0x00,                    //   COLLECTION (Physical)
0x09, 0x30,                    //     USAGE (X)
0x09, 0x31,                    //     USAGE (Y)
0x15, 0xff,                    //     LOGICAL_MINIMUM (-1)
0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
0x95, 0x02,                    //     REPORT_COUNT (2)
0x75, 0x02,                    //     REPORT_SIZE (2) ; two bytes to represent each axis
0x81, 0x02,                    //     INPUT (Data,Var,Abs)
0xc0,                          //   END_COLLECTION
0x05, 0x09,                    //   USAGE_PAGE (Button)
0x19, 0x01,                    //   USAGE_MINIMUM (Button 1)
0x29, 0x04,                    //   USAGE_MAXIMUM (Button 4)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
0x95, 0x04,                    //   REPORT_COUNT (4) ; 4 buttons
0x75, 0x01,                    //   REPORT_SIZE (1)
0x81, 0x02,                    //   INPUT (Data,Var,Abs)
0xc0                           // END_COLLECTION

Hopefully you can see the part up the top specifies the joypad and the bottom specifies the buttons. So if we have 2 axis bits and 4 button bits, we have a total of 8 bits (which is perfect!). However, what if we want to use 5 buttons? If you simply change the USAGE_MAXIMUM and REPORT_COUNT parameters, then we are sending 2*2+5*1 = 9 bits! To fix this, we need to add some padding bits to bring our total number of bits up to 16 (in this case, we want to add 7 more). A descriptor with this fix would look something like this:

0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
0x09, 0x05,                    // USAGE (Game Pad)
0xa1, 0x01,                    // COLLECTION (Application)
0x09, 0x01,                    //   USAGE (Pointer)
0xa1, 0x00,                    //   COLLECTION (Physical)
0x09, 0x30,                    //     USAGE (X)
0x09, 0x31,                    //     USAGE (Y)
0x15, 0xff,                    //     LOGICAL_MINIMUM (-1)
0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
0x95, 0x02,                    //     REPORT_COUNT (2)
0x75, 0x02,                    //     REPORT_SIZE (2) ; two bytes to represent each axis
0x81, 0x02,                    //     INPUT (Data,Var,Abs)
0xc0,                          //   END_COLLECTION
0x05, 0x09,                    //   USAGE_PAGE (Button)
0x19, 0x01,                    //   USAGE_MINIMUM (Button 1)
0x29, 0x05,                    //   USAGE_MAXIMUM (Button 5)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
0x95, 0x05,                    //   REPORT_COUNT (5) ; 5 buttons
0x75, 0x01,                    //   REPORT_SIZE (1)
0x81, 0x02,                    //   INPUT (Data,Var,Abs)
0x95, 0x07,                    //	REPORT_COUNT (7) ; to pad out the bits into a number divisible by 8
0x81, 0x03,                    //   INPUT (Const,Var,Abs)
0xc0                           // END_COLLECTION

2010-05-15 22:58:45
CC 2.5 License Support ScienceCommons!
open