Modifying the Joystick HID Descriptor
Introduction
The HID Tool comes with several example descriptors which you can use as the
basis for your own custom HID descriptors. This article will demonstrate how to
modify the descriptors to suit your specifications.
Many thanks to Glen Alexis for explaining this to me!
Basic Principles
When modifying the HID descriptors, there is one important rule that must be
followed in order for the modifications to be accepted: the total number of
data bits specified in the descriptor must be a multiple of 8 bits. For
example, let's have a look at the default joystick descriptor:
USAGE_PAGE (Generic Desktop)
LOGICAL_MINIMUM (0)
USAGE (Joystick)
COLLECTION (Application)
USAGE_PAGE
(Simulation Controls)
USAGE
(Throttle)
LOGICAL_MINIMUM (-127)
LOGICAL_MAXIMUM (127)
REPORT_SIZE
(8)
REPORT_COUNT
(1)
INPUT
(Data,Var,Abs)
USAGE_PAGE
(Generic Desktop)
USAGE
(Pointer)
COLLECTION
(Physical)
USAGE (X)
USAGE (Y)
REPORT_COUNT (2)
INPUT (Data,Var,Abs)
END_COLLECTION
USAGE (Hat
switch)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (3)
PHYSICAL_MINIMUM (0)
PHYSICAL_MAXIMUM (270)
UNIT (Eng
Rot:Angular Pos)
REPORT_SIZE
(4)
REPORT_COUNT
(1)
INPUT
(Data,Var,Abs)
USAGE_PAGE
(Button)
USAGE_MINIMUM
(Button 1)
USAGE_MAXIMUM
(Button 4)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1)
REPORT_SIZE
(1)
REPORT_COUNT
(4)
UNIT_EXPONENT
(0)
UNIT (None) 65 00
INPUT
(Data,Var,Abs)
END_COLLECTION
From the descriptor, we can see that the data is defined as follows:
|
Value
|
Size (bits)
|
|
Throttle
|
8
|
|
X axis
|
8
|
|
Y axis
|
8
|
|
POV Hat
|
4
|
|
Buttons
|
4
|
|
Total
|
32 bits = 4 bytes
|
The data bits form a whole number of bytes and so is accepted by the host PC. Let's
say, however, that we didn't want the POV Hat in our joystick and we removed
it's section from the descriptor. We would end up with the following descriptor:
USAGE_PAGE (Generic Desktop)
LOGICAL_MINIMUM (0)
USAGE (Joystick)
COLLECTION (Application)
USAGE_PAGE
(Simulation Controls)
USAGE
(Throttle)
LOGICAL_MINIMUM (-127)
LOGICAL_MAXIMUM (127)
REPORT_SIZE
(8)
REPORT_COUNT
(1)
INPUT
(Data,Var,Abs)
USAGE_PAGE
(Generic Desktop)
USAGE
(Pointer)
COLLECTION
(Physical)
USAGE (X)
USAGE (Y)
REPORT_COUNT (2)
INPUT (Data,Var,Abs)
END_COLLECTION
USAGE_PAGE
(Button)
USAGE_MINIMUM
(Button 1)
USAGE_MAXIMUM
(Button 4)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1)
REPORT_SIZE
(1)
REPORT_COUNT
(4)
UNIT_EXPONENT
(0)
UNIT (None) 65 00
INPUT
(Data,Var,Abs)
END_COLLECTION
Our data would look like this:
|
Value
|
Size (bits)
|
|
Throttle
|
8
|
|
X axis
|
8
|
|
Y axis
|
8
|
|
Buttons
|
4
|
|
Total
|
28 bits = 3.5 bytes
|
What's immediately noticeable is that the total number of data bits does not come
to a whole number of bytes and this is why the above descriptor would fail. In
order to fix this problem, some padding needs to be added at the end of the
descriptor to fill up the extra 4 bits. The necessary modification is
highlighted below:
USAGE_PAGE (Generic Desktop)
LOGICAL_MINIMUM (0)
USAGE (Joystick)
COLLECTION (Application)
USAGE_PAGE
(Simulation Controls)
USAGE
(Throttle)
LOGICAL_MINIMUM (-127)
LOGICAL_MAXIMUM (127)
REPORT_SIZE
(8)
REPORT_COUNT
(1)
INPUT
(Data,Var,Abs)
USAGE_PAGE
(Generic Desktop)
USAGE
(Pointer)
COLLECTION
(Physical)
USAGE (X)
USAGE (Y)
REPORT_COUNT (2)
INPUT (Data,Var,Abs)
END_COLLECTION
USAGE_PAGE
(Button)
USAGE_MINIMUM
(Button 1)
USAGE_MAXIMUM
(Button 4)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1)
REPORT_SIZE
(1)
REPORT_COUNT
(4)
UNIT_EXPONENT
(0)
UNIT (None) 65 00
INPUT
(Data,Var,Abs)
REPORT_COUNT (4) <-Adds 4
extra padding bits to the descriptor
INPUT (Constant,Var,Abs)
END_COLLECTION
The two lines above the
END_COLLECTION statement declares a constant
that is 4 bits in size. This brings the total data bits to 32 bits which forms 4
complete bytes.
Conclusion
That's pretty much the key to any modifications you make to the HID descriptors -
as long as you make sure that you add the correct amount of padding to your
descriptor, you should be able to modify to your heart's content.
|