Attempting to write a device driver for the macbook's USB trackpad

Rohit Grover rgrover1 at gmail.com
Fri Dec 26 13:25:20 PST 2008


Hello People,

I'm attempting to write a FreeBSD device driver for the USB trackpad on my
macbook.

The trackpad is an HID class device. Parsing the HID report descriptor
(fetched from an invocation of usbd_read_report_desc()) for this device
results in the following information:

Legend: <descriptor_kind>: <page> <usage> <reportID>
      <hid_location>

input: page: 0x9; usage: 0x1; reportID: 2
        size: 1, count: 1, loc: 0
input: page: 0x9; usage: 0x2; reportID: 2
        size: 1, count: 1, loc: 1
input: page: 0x9; usage: 0x3; reportID: 2
        size: 1, count: 1, loc: 2
input: page: 0x0; usage: 0x0; reportID: 2
        size: 5, count: 1, loc: 3
input: page: 0x1; usage: 0x30; reportID: 2
        size: 8, count: 1, loc: 8
input: page: 0x1; usage: 0x31; reportID: 2
        size: 8, count: 1, loc: 16
input: page: 0xffff; usage: 0x2; reportID: 5
        size: 8, count: 63, loc: 24
collection: page: 0x1; usage: 0x2; collection: 1; collevel: 1, reportID: 0
        size: 0, count: 0, loc: 0
collection: page: 0x1; usage: 0x1; collection: 0; collevel: 2, reportID: 0
        size: 0, count: 0, loc: 0
collection: page: 0xffff; usage: 0x1; collection: 0; collevel: 1, reportID:
2
        size: 8, count: 2, loc: 0
feature: page: 0xffff; usage: 0x4, reportID: 5
        size: 8, count: 1, loc: 0
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 8
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 16
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 24
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 32
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 40
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 48
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 56
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 64
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 72
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 80
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 88
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 96
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 104
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 112
feature: page: 0x0; usage: 0x0, reportID: 5
        size: 8, count: 1, loc: 120
end_collection: page: 0x1; usage: 0x31, reportID: 2
        size: 8, count: 2, loc: 0
end_collection: page: 0x0; usage: 0x0, reportID: 2
        size: 8, count: 2, loc: 0
end_collection: page: 0xffff; usage: 0x4, reportID: 5
        size: 8, count: 16, loc: 0

As can be seen, there are two distinct report IDs being used. Report ID 2
describes the mouse-buttons and XY deltas; and since the generic UMS driver
in Freebsd is able to parse these values, the macbook's trackpad is usable.
I would like to enhance the ums driver to report information from the
pressure sensors--with the hope that this will allow the detection of tap
events.
I suspect that the reports with ID == 5 will contain this information. Of
particular interest to me is the following (from the previous table):

input: page: 0xffff; usage: 0x2; reportID: 5
        size: 8, count: 63, loc: 24

Unfortunately, this report uses a vendor specific page (0xffff), and
therefore will require some reverse engineering before it can be deciphered.

I need help with receiving HID reports for both ID == 2 and ID == 5.
Currently, the interrupt handler (ums_intr) only parses reports with ID==2.
Based on my reading of the code, ums_attach() needs to setup sc->sc_iid and
sc->sc_isize based on the report-descriptors fetched from the device; but in
the case where there are multiple reportIDs supported by the device, the
current setup code uses values from only the first reportID.

In order to parse reportID 2, sc->sc_isize is set to a value of 4 bytes: 1
byte for the reportID header, together with 3 bytes for the button/XY-delta
values.
To accommodate an additional 63 bytes for the input in reportID 5, I am
guessing that I should set sc->sc_isize to 68:  for the 63 bytes starting at
bit offset 24; with allowance for one additional byte which may be necessary
to accommodate a reportID header. I still don't know how to initialize
sc->sc_iid to handle both report IDs.

Can someone please help me with setting up the device to receive reports
with both IDs so that I can begin reverse-engineering the vendor-specific
content of reportID 5?

regards,
Rohit.


More information about the freebsd-drivers mailing list