Am Sonntag, 17. Februar 2008 03:22:00 schrieb Chuck Robey: > I am still having a miserable time trying to figure out the HID spec, and > Kai Wang deserves being nominated for Sainthood, for putting up with my > horde of stupid questions. If anyone knows of a HID device which has a > published [HID report in hex, Parsed output, and comments on how it got > from one to the other] I would give nearly anything for such a thing > (anything I happen to have, which doesn't happen to include cash right > now). This is the raw report descriptor of a very simple device: an Apple Mighty Mouse: 0x05 0x01 0x09 0x02 0xa1 0x01 0x05 0x09 0x19 0x01 0x29 0x04 0x15 0x00 0x25 0x01 0x95 0x04 0x75 0x01 0x81 0x02 0x95 0x01 0x75 0x04 0x81 0x01 0x05 0x01 0x09 0x01 0xa1 0x00 0x09 0x30 0x09 0x31 0x09 0x32 0x09 0x38 0x15 0x81 0x25 0x7f 0x75 0x08 0x95 0x04 0x81 0x06 0xc0 0x05 0xff 0x09 0xc0 0x75 0x08 0x95 0x01 0x81 0x02 0xc0 Decoding it works as follows: Let's look at the first byte 0x05. The binary representation is 00000101. Splitting this up as described in chapter 6.2.2.2 gives the following (in binary representation): bTag=0000 bType=01 bSize=01 First, as bTag is not 1111, we know that this is not a long item (see 6.2.2.3). So this must be a short item. bType tells us that this is a global item (6.2.2.2). Finally bSize specifies the number of following bytes that belong to this item which is 1 in this case. So, looking back at the raw descriptor we know now that the sequence 0x05 0x01 forms one item. We also know that it is a short item and that it is a global item. What we don't know yet is, what global item this is. For this, we have to look at bTag again. As we know that this is a global item, we take a look at chapter 6.2.2.7 "Global Items". It tells us that 0000 stands for Usage Page. Which usage page is meant is encoded in the data part of the item, which is 0x01. From the HID Usage Tables document Chapter 3 we learn that 0x01 stands for "Generic Desktop Controls". This gives us the following for the first item: 0x05 0x01 USAGE_PAGE (Generic Desktop) Now the second item beginning with 0x09: Binary representation is 00001001. Splitting this up yields: bTag=0000 bType=10 bSize=01 Again this is a short item as bTag != 1111. bType is a decimal 2 and chapter 6.2.2.2 tells us that this is a local item. Advancing to chapter 6.2.2.7 "Local Items" gives us the meaning for bTag, which is "Usage". As bSize is 1, only the next byte in the report descriptor is considered for the data of the item, so the usage is 0x02. Looking at the HID Usage Tables document again, this time chapter 4, as we already learned that this usage belongs to the usage page Generic Desktop, we see that 0x02 is equivalent to "Mouse". Now we have: 0x05 0x01 USAGE_PAGE (Generic Desktop) 0x09 0x02 USAGE (Mouse) Up to the next item which begins with 0xa1, binary 10100001: bTag=1010 bType=00 bSize=01 Again this is a short item as bTag != 1111. bType is 0, which stands for Main Item, according to chapter 6.2.2.2. Looking at chapter 6.2.2.4, we learn that the bTag of 1010 actually means "Collection". The data part of 1 byte (see bSize), which is in this case 0x01 tells us that this is an "Application Collection". So, now we have: 0x05 0x01 USAGE_PAGE (Generic Desktop) 0x09 0x02 USAGE (Mouse) 0xa1 0x01 COLLECTION (Application) If you continue decoding it this way, you will finally get the following: 0x05 0x01 USAGE_PAGE (Generic Desktop) 0x09 0x02 USAGE (Mouse) 0xa1 0x01 COLLECTION (Application) 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) 0x75 0x01 REPORT_SIZE (1) 0x81 0x02 INPUT (Data, Var, Abs) 0x95 0x01 REPORT_COUNT (1) 0x75 0x04 REPORT_SIZE (4) 0x81 0x01 INPUT (Const, Var, Abs) 0x05 0x01 USAGE_PAGE (Generic Desktop) 0x09 0x01 USAGE (Pointer) 0xa1 0x00 COLLECTION (Physical) 0x09 0x30 USAGE (X) 0x09 0x31 USAGE (Y) 0x09 0x32 USAGE (Z) 0x09 0x38 USAGE (WHEEL) 0x15 0x81 LOGICAL_MINIMUM (0x81) 0x25 0x7f LOGICAL_MAXIMUM (0x7f) 0x75 0x08 REPORT_SIZE (8) 0x95 0x04 REPORT_COUNT (4) 0x81 0x06 INPUT (Data, Var, Rel) 0xc0 END COLLECTION 0x05 0xff USAGE_PAGE (0xff) 0x09 0xc0 USAGE (0xc0) 0x75 0x08 REPORT_SIZE (8) 0x95 0x01 REPORT_COUNT (1) 0x81 0x02 INPUT (Data, Var, Abs) 0xc0 To actually give meaning to the decoded descriptor, you have to learn how local, global and main items relate to each other. Main items are actually the most important ones, as they directly correlate to physical controls of your device (apart from the collection items). Global and local items describe the different main items, whereas local items only describe the next main item. Global items instead keep their state accross main items until they are specified again or are being overrriden by a local item. In this example we have several main items. Lets have a look at the first one 0x05 0x01 USAGE_PAGE (Generic Desktop) 0x09 0x02 USAGE (Mouse) 0xa1 0x01 COLLECTION (Application) This is an application collection. Usage page and usage describe the context of the items that are within it, so we have: Collection page=Generic_Desktop usage=Mouse The next item is a bit more interresting. It's an input item: 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) 0x75 0x01 REPORT_SIZE (1) 0x81 0x02 INPUT (Data, Var, Abs) It actually describes 4 controls (report count). The meaning of these 4 controls is specified by the usage page and usage min/max. In this case Button 1 - Button 4. Logical min/max are 0 and 1 and mean that the range of the data in the data stream, that is submitted by the device, is between 0 and 1, which is actually only 0 and 1 in this case. Report size finally gives the size in the data stream for each button state that is submitted by the device in number of bits. Now we have: Collection page=Generic_Desktop usage=Mouse Input size=1 count=1 page=Button usage=Button_1, logical range 0..1 Input size=1 count=1 page=Button usage=Button_2, logical range 0..1 Input size=1 count=1 page=Button usage=Button_3, logical range 0..1 Input size=1 count=1 page=Button usage=Button_4, logical range 0..1 The next input item is a const item, which is being used for padding in this case. It can be ignored. In the end we get the following: Collection page=Generic_Desktop usage=Mouse Input size=1 count=1 page=Button usage=Button_1, logical range 0..1 Input size=1 count=1 page=Button usage=Button_2, logical range 0..1 Input size=1 count=1 page=Button usage=Button_3, logical range 0..1 Input size=1 count=1 page=Button usage=Button_4, logical range 0..1 Input size=4 count=1 page=0x0000 usage=0x0000 Const, logical range 0..1 Collection page=Generic_Desktop usage=Pointer Input size=8 count=1 page=Generic_Desktop usage=X, logical range -127..127 Input size=8 count=1 page=Generic_Desktop usage=Y, logical range -127..127 Input size=8 count=1 page=Generic_Desktop usage=Z, logical range -127..127 Input size=8 count=1 page=Generic_Desktop usage=Wheel, logical range -127..127 End collection Input size=8 count=1 page=0x00ff usage=0x00c0, logical range -127..127 End collection This actually means, that the mouse reports 6 bytes of data in each transmission. The first 4 bits indicate the button states, the next 4 bits can be ignored. Byte 2 reports the X axis state, byte 3, 4 and 5 data for Y, Z and the wheel. The last byte reports vendor specific data (usage page 0x00ff). That's it in short. There is of course much to learn regarding the details, but it should give you a general overview of how this works. Markus
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:27 UTC