Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 17 Feb 2008 16:41:59 +0100
From:      Markus Brueffer <markus@FreeBSD.org>
To:        freebsd-current@freebsd.org
Cc:        Chuck Robey <chuckr@chuckr.org>, Alexander Leidinger <Alexander@leidinger.net>
Subject:   Re: about usb
Message-ID:  <200802171642.04403.markus@FreeBSD.org>
In-Reply-To: <47B79A48.1030406@chuckr.org>
References:  <47B20739.1050602@chuckr.org> <20080216121241.450ff175@deskjail> <47B79A48.1030406@chuckr.org>

next in thread | previous in thread | raw e-mail | index | archive | help
--nextPart5572139.TovlfbE5Tt
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

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=
=20
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=20
binary representation):

bTag=3D0000
bType=3D01
bSize=3D01

=46irst, as bTag is not 1111, we know that this is not a long item (see=20
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 specifie=
s=20
the number of following bytes that belong to this item which is 1 in this=20
case. So, looking back at the raw descriptor we know now that the sequence=
=20
0x05 0x01 forms one item. We also know that it is a short item and that it =
is=20
a global item. What we don't know yet is, what global item this is. For thi=
s,=20
we have to look at bTag again. As we know that this is a global item, we ta=
ke=20
a look at chapter 6.2.2.7 "Global Items". It tells us that 0000 stands for=
=20
Usage Page. Which usage page is meant is encoded in the data part of the=20
item, which is 0x01. From the HID Usage Tables document Chapter 3 we learn=
=20
that 0x01 stands for "Generic Desktop Controls". This gives us the followin=
g=20
for the first item:

0x05 0x01	USAGE_PAGE (Generic Desktop)

Now the second item beginning with 0x09: Binary representation is 00001001.=
=20
Splitting this up yields:

bTag=3D0000
bType=3D10
bSize=3D01

Again this is a short item as bTag !=3D 1111. bType is a decimal 2 and chap=
ter=20
6.2.2.2 tells us that this is a local item. Advancing to chapter=20
6.2.2.7 "Local Items" gives us the meaning for bTag, which is "Usage". As=20
bSize is 1, only the next byte in the report descriptor is considered for t=
he=20
data of the item, so the usage is 0x02. Looking at the HID Usage Tables=20
document again, this time chapter 4, as we already learned that this usage=
=20
belongs to the usage page Generic Desktop, we see that 0x02 is equivalent=20
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=3D1010
bType=3D00
bSize=3D01

Again this is a short item as bTag !=3D 1111. bType is 0, which stands for =
Main=20
Item, according to chapter 6.2.2.2. Looking at chapter 6.2.2.4, we learn th=
at=20
the bTag of 1010 actually means "Collection". The data part of 1 byte (see=
=20
bSize), which is in this case 0x01 tells us that this is an "Application=20
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=20
local, global and main items relate to each other. Main items are actually=
=20
the most important ones, as they directly correlate to physical controls of=
=20
your device (apart from the collection items). Global and local items=20
describe the different main items, whereas local items only describe the ne=
xt=20
main item. Global items instead keep their state accross main items until=20
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 o=
ne

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 contex=
t=20
of the items that are within it, so we have:

Collection page=3DGeneric_Desktop usage=3DMouse

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=20
controls is specified by the usage page and usage min/max. In this case=20
Button 1 - Button 4. Logical min/max are 0 and 1 and mean that the range of=
=20
the data in the data stream, that is submitted by the device, is between 0=
=20
and 1, which is actually only 0 and 1 in this case. Report size finally giv=
es=20
the size in the data stream for each button state that is submitted by the=
=20
device in number of bits. Now we have:

Collection page=3DGeneric_Desktop usage=3DMouse
Input   size=3D1 count=3D1 page=3DButton usage=3DButton_1, logical range 0.=
=2E1
Input   size=3D1 count=3D1 page=3DButton usage=3DButton_2, logical range 0.=
=2E1
Input   size=3D1 count=3D1 page=3DButton usage=3DButton_3, logical range 0.=
=2E1
Input   size=3D1 count=3D1 page=3DButton usage=3DButton_4, logical range 0.=
=2E1

The next input item is a const item, which is being used for padding in thi=
s=20
case. It can be ignored. In the end we get the following:

Collection page=3DGeneric_Desktop usage=3DMouse
Input   size=3D1 count=3D1 page=3DButton usage=3DButton_1, logical range 0.=
=2E1
Input   size=3D1 count=3D1 page=3DButton usage=3DButton_2, logical range 0.=
=2E1
Input   size=3D1 count=3D1 page=3DButton usage=3DButton_3, logical range 0.=
=2E1
Input   size=3D1 count=3D1 page=3DButton usage=3DButton_4, logical range 0.=
=2E1
Input   size=3D4 count=3D1 page=3D0x0000 usage=3D0x0000 Const, logical rang=
e 0..1
Collection page=3DGeneric_Desktop usage=3DPointer
Input   size=3D8 count=3D1 page=3DGeneric_Desktop usage=3DX, logical range =
=2D127..127
Input   size=3D8 count=3D1 page=3DGeneric_Desktop usage=3DY, logical range =
=2D127..127
Input   size=3D8 count=3D1 page=3DGeneric_Desktop usage=3DZ, logical range =
=2D127..127
Input   size=3D8 count=3D1 page=3DGeneric_Desktop usage=3DWheel, logical=20
range -127..127
End collection
Input   size=3D8 count=3D1 page=3D0x00ff usage=3D0x00c0, logical range -127=
=2E.127
End collection

This actually means, that the mouse reports 6 bytes of data in each=20
transmission. The first 4 bits indicate the button states, the next 4 bits=
=20
can be ignored. Byte 2 reports the X axis state, byte 3, 4 and 5 data for Y=
,=20
Z and the wheel. The last byte reports vendor specific data (usage page=20
0x00ff).

That's it in short. There is of course much to learn regarding the details,=
=20
but it should give you a general overview of how this works.

Markus

--nextPart5572139.TovlfbE5Tt
Content-Type: application/pgp-signature; name=signature.asc 
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.4 (FreeBSD)

iD8DBQBHuFXM1I0Qcnj4qNQRAg9bAKCWK1PRol2EAVAgTUpfU/AhJmKzNwCg/yXZ
yW806VV205ScIpHVm/gMAag=
=MhWu
-----END PGP SIGNATURE-----

--nextPart5572139.TovlfbE5Tt--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200802171642.04403.markus>