-
Notifications
You must be signed in to change notification settings - Fork 0
Report Descriptor
The device reports a 936-byte HID report descriptor (RPT_DESC, wire type 8) describing 8
top-level collections: a standard Digitizer Pen collection (Report ID 0x01), a standard
TouchScreen collection (Report ID 0x40), and several vendor/raw collections used for the
experimental raw heatmap mode (see Multi-touch Experimental).
Earlier iterations of this driver just used a hardcoded copy of the descriptor as a fallback
of last resort. The current driver prefers reading it live from the device every boot —
spi_hid_ll_parse() tries shid->wire_report_descriptor (populated by the RPT_DESC handling
in spi_hid_seq_thread()) first, and only falls back to the hardcoded copy
(driver/hardcoded_rd.h) if the live one fails hid_parse_report() — this also picks up
firmware updates or descriptor differences across SKUs automatically.
hid_parse_report()'s return code is not a reliable validity signal — it can return success
with just a non-fatal "unexpected long global item" warning even for a structurally corrupted
descriptor. The real failure only surfaces later, inside hid_add_device(), when the kernel's
own driver-matching machinery tries (and synchronously fails) to bind hid-generic against
the malformed parsed structure — and hid_add_device() itself still returns success in that
case. The actual reliable signal implemented here is checking hid->driver == NULL after
a "successful" hid_add_device() call; if that's true, the driver retries once with the
hardcoded descriptor.
As covered in Wire Protocol, fetching the descriptor in 64-byte chunks
reveals a hardware quirk: byte n·64+58 of every chunk (14 positions across the 936-byte
descriptor) reads back as a spurious 0xFF, reproducibly, independent of SPI clock speed and
of the host's own chunk boundaries — i.e. it's tied to the device's own internal page
structure, not to anything the driver controls.
Since these are the only 14 bytes ever wrong, and always the same ones, the driver applies a
targeted, minimal patch: only those 14 byte positions are overwritten from
hardcoded_report_descriptor (used purely as ground truth for those positions, cross-checked
against a real Windows ETW capture), while the other 922/936 bytes (98.5%) come from the
live wire read on every boot.
/* driver/spi-hid-core.c, inside the RPT_DESC handling */
for (k = 55; k < len; k += 64) {
if (shid->wire_report_descriptor[k] == 0xFF &&
k < HARDCODED_RD_SIZE &&
hardcoded_report_descriptor[k] != 0xFF) {
shid->wire_report_descriptor[k] = hardcoded_report_descriptor[k];
}
}(The patch loop's phase is 55, not the raw 58 measured against the wire capture, because
by the time the descriptor bytes reach this buffer the 3-byte [len16][ContentID] prefix has
already been stripped — an off-by-3 bug that was caught and fixed during development, worth
remembering if this code is touched again.)
With the patch applied, the live-read descriptor parses successfully and binds hid-generic
on the first attempt essentially every time.