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

