On Thu, Jun 22, 2023 at 10:39:15PM +0200, Marco Morandini wrote: > Add an introduction about HID > meant for the casual programmers that is trying > either to fix his device or to understand what > is going wrong. > > Signed-off-by: Marco Morandini <marco.morandini@xxxxxxxxx> > --- > v1: https://lore.kernel.org/linux-input/3mbw67akm2xzd2kgzb6sdfh4dly6im5jrz5umuvczjvrgxtf46@q5ooib3zkmfq/T/#m00b625a4d2c605dd7f62a866df7bf97ef2921d63 Thanks for all the fixes, much easier to read and follow already. A few nitpicks like last time but this is coming together! > Documentation/hid/hidintro.rst | 543 ++++++++++++++++++++++++ > Documentation/hid/hidreport-parsing.rst | 52 +++ > Documentation/hid/index.rst | 1 + > include/linux/hid.h | 23 + > 4 files changed, 619 insertions(+) > create mode 100644 Documentation/hid/hidintro.rst > create mode 100644 Documentation/hid/hidreport-parsing.rst > > diff --git a/Documentation/hid/hidintro.rst b/Documentation/hid/hidintro.rst > new file mode 100644 > index 000000000000..cdaa09479147 > --- /dev/null > +++ b/Documentation/hid/hidintro.rst > @@ -0,0 +1,543 @@ > +.. SPDX-License-Identifier: GPL-2.0 > + > +====================================== > +Introduction to HID report descriptors > +====================================== > + > +This chapter is meant to give a broad overview > +of what HID report descriptors are, and of how a casual (non kernel) > +programmer can deal with an HID device that > +is not working well with Linux. > + > +.. contents:: > + :local: > + :depth: 2 > + > +.. toctree:: > + :maxdepth: 2 > + > + hidreport-parsing > + > + > +Introduction > +============ > + > +HID stands for Human Interface Device, and can be whatever device > +you are using to interact with a computer, be it a mouse, > +a touchpad, a tablet, a microphone. > + > +Many HID devices work out the box, even if their hardware is different. > +For example, mice can have any number of buttons; they > +may a wheel; movement sensitivity differs between different > +models, and so on. Nonetheless, > +most of the time everything just works, without the need > +to have specialized code in the kernel for every mouse model > +developed since 1970. A general request - can you reformat the paragraphs please to be roughly the max (or just the same-ish) line lengths. Some of these paragraphs read more like a poem with superfluous linebreaks sprinkled all over it. > + > +This is because modern HID devices do advertise > +their capabilities through the *HID report descriptor*, a > +fixed set of bytes describing exactly what *HID reports* > +may be sent between the device and the host and the meaning of each > +individual bit in those reports. For example, a HID Report Descriptor > +may specify that "in a report with ID 3 the second byte is the delta x > +coordinate of a mouse". staring at this and if you're doing a v3 anyway, I'd say "bits 8 to 15" instead of "second byte" to emphasise that HID reports are usually more bit-y than byte-y. But that's a minor nitpick that doesn't matter too much. > + > +The HID report itself then merely carries the actual data values > +without any extra meta information. Note that HID reports may be sent > +from the device ("Input Reports", i.e. input events), to the device > +("Output Reports" to e.g. change LEDs) or used for device > +configuration ("Feature reports"). A device may support one or more > +HID reports. > + > +The HID subsystem is in charge of parsing the HID report descriptors, > +and converts HID events into normal input > +device interfaces (see Documentation/hid/hid-transport.rst). > +Devices may misbehave because the HID report descriptor > +provided by the device is wrong, > +or because it needs to be dealt with in a special way, > +or because some special device or interaction mode > +is not handled by the default code. > + > +The format of HID report descriptors is described by two documents, > +available from the `USB Implementers Forum <https://www.usb.org/>`_ > +at `this <https://www.usb.org/hid>`_ addresses: > + > + * the `HID USB Device Class Definition > + <https://www.usb.org/document-library/device-class-definition-hid-111>`_ (HID Spec from now on) > + * the `HID Usage Tables <https://usb.org/document-library/hid-usage-tables-14>`_ (HUT from now on) > + > +This does not mean that the HID subsystem can deal with USB devices only; > +rather, different transport drivers, such as I2C or Bluetooth, can be dealt > +with, see Documentation/hid/hid-transport.rst. Simpler wording: "The HID subsystem can deal with different transport drivers (USB, I2C, Bluetooth, etc.). See Documentation/hid/hid-transport.rst." > + > +Parsing HID report descriptors > +============================== > + > +The current list of HID devices can be found at ``/sys/bus/hid/devices/``. > +For each device, say ``/sys/bus/hid/devices/0003\:093A\:2510.0002/``, > +one can read the corresponding report descriptor:: > + > + marco@sun:~> hexdump -C /sys/bus/hid/devices/0003\:093A\:2510.0002/report_descriptor > + 00000000 05 01 09 02 a1 01 09 01 a1 00 05 09 19 01 29 03 |..............).| > + 00000010 15 00 25 01 75 01 95 03 81 02 75 05 95 01 81 01 |..%.u.....u.....| > + 00000020 05 01 09 30 09 31 09 38 15 81 25 7f 75 08 95 03 |...0.1.8..%.u...| > + 00000030 81 06 c0 c0 |....| > + 00000034 > + > +Optional stuff: the HID report descriptor can be read also by > +directly accessing the hidraw driver [#hidraw]_. > + > +The basic structure of HID report descriptors is defined in the HID spec, while > +HUT "defines constants that can be interpreted by an application to > +identify the purpose and meaning of a data > +field in a HID report". Each entry is defined by at least two bytes, > +where the first one defines what type of value is following, > +and is described in the HID spec, no comma before "and" in this case > +while the second one carries the actual value, superfluous comma-man to the rescue! :) > +and is described in the HUT. > + > +HID report descriptors can, in principle, be painstakingly > +parsed by hand, byte by byte. > + > +A short introduction > +on how to do this is sketched in Documentation/hid/hidreport-parsing.rst; > +you need to understand it only if you need to patch HID report descriptors. I think this should be "you only need to ..." (but I'm ESL too) > + > +In practice you should not do parse HID report descriptors by hand; > +rather, you should use an existing parser. > +Among all the available ones > + > + * the online `USB Descriptor and Request Parser > + <http://eleccelerator.com/usbdescreqparser/>`_; > + * `hidrdd <https://github.com/abend0c1/hidrdd>`_, > + that provides very detailed and somewhat verbose descriptions > + (verbosity can be useful if you are not familiar with HID report descriptors); > + * `hid-tools <https://gitlab.freedesktop.org/libevdev/hid-tools>`_, > + a complete utility set that allows, among other things, > + to record and replay the raw HID reports and to debug > + and replay HID devices. > + It is being actively developed by the Linux HID subsystem mantainers. > + > +Parsing the mouse HID report descriptor with `hid-tools <https://gitlab.freedesktop.org/libevdev/hid-tools>`_ leads to > +(explanations interposed):: > + > + marco@sun:~/Programmi/linux/hid-tools (master =)> ./hid-decode /sys/bus/hid/devices/0003\:093A\:2510.0002/report_descriptor shorten the prompt to just "$ hid-decode ..." and it'll fit better on a single line > + # device 0:0 > + # 0x05, 0x01, // Usage Page (Generic Desktop) 0 > + # 0x09, 0x02, // Usage (Mouse) 2 > + # 0xa1, 0x01, // Collection (Application) 4 > + # 0x09, 0x01, // Usage (Pointer) 6 > + # 0xa1, 0x00, // Collection (Physical) 8 > + # 0x05, 0x09, // Usage Page (Button) 10 > + what follows is a button > + > + # 0x19, 0x01, // Usage Minimum (1) 12 > + # 0x29, 0x03, // Usage Maximum (3) 14 > + first button is button number 1, last button is button number 3 > + > + # 0x15, 0x00, // Logical Minimum (0) 16 > + # 0x25, 0x01, // Logical Maximum (1) 18 > + each button can send values from 0 up to including 1 > + (i.e. they are binary buttons) > + > + # 0x75, 0x01, // Report Size (1) 20 > + each button is sent as exactly one bit > + > + # 0x95, 0x03, // Report Count (3) 22 > + and there are three of those bits > + (matching the three buttons) > + > + # 0x81, 0x02, // Input (Data,Var,Abs) 24 > + it's actual Data (not constant padding), they represent > + a single variable (Var) and the value are Absolute (not relative); > + See HID spec Sec. 6.2.2.5 "Input, Output, and Feature Items > + > + # 0x75, 0x05, // Report Size (5) 26 > + five additional padding bits, needed to reach a byte > + > + # 0x95, 0x01, // Report Count (1) 28 > + those five bits are repeated only once > + > + # 0x81, 0x01, // Input (Cnst,Arr,Abs) 30 > + and take Constant (Cnst) values "i.e. they can be ignored" > + > + # 0x05, 0x01, // Usage Page (Generic Desktop) 32 > + # 0x09, 0x30, // Usage (X) 34 > + # 0x09, 0x31, // Usage (Y) 36 > + # 0x09, 0x38, // Usage (Wheel) 38 > + The mouse has also two physical positions (``Usage (X)``, ``Usage (Y)``) too many spaces here > + and a wheel (Usage (Wheel)) > + > + # 0x15, 0x81, // Logical Minimum (-127) 40 > + # 0x25, 0x7f, // Logical Maximum (127) 42 > + each of them can send values ranging from -127 up to including 127 > + > + # 0x75, 0x08, // Report Size (8) 44 > + is represented by eight bits > + > + # 0x95, 0x03, // Report Count (3) 46 > + and there are three of those eight bits, matching X, Y and Wheel > + > + # 0x81, 0x06, // Input (Data,Var,Rel) 48 > + This time the data is Relative (Rel), i.e. it represent > + the change from the previous configuration "the previously sent report (event)" > + > + # 0xc0, // End Collection 50 > + # 0xc0, // End Collection 51 > + # > + R: 52 05 01 09 02 a1 01 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 75 01 95 03 81 02 75 05 95 01 81 01 05 01 09 30 09 31 09 38 15 81 25 7f 75 08 95 03 81 06 c0 c0 > + N: device 0:0 > + I: 3 0001 0001 > + > + > +This Report Descriptor tells us that the mouse input will be > +transmitted using four bytes: > +the first one for the buttons (three bits used, five for padding), > +the last three for the mouse X, Y and wheel changes, respectively. > + > +Indeed, for any event, the mouse will send a *report* of four bytes. > +We can check the values sent by resorting e.g. > +to the `hid-recorder` tool, from `hid-tools > +<https://gitlab.freedesktop.org/libevdev/hid-tools>`_: > +The sequence of bytes sent by clicking and releasing > +button 1, then button 2, then button 3 is:: > + > + marco@sun:~/> sudo ./hid-recorder /dev/hidraw1 for consistency please change the prompt here to `$` as well > + > + .... > + output of hid-decode > + .... > + > + # Button: 1 0 0 | # | X: 0 | Y: 0 | Wheel: 0 > + E: 000000.000000 4 01 00 00 00 > + # Button: 0 0 0 | # | X: 0 | Y: 0 | Wheel: 0 > + E: 000000.183949 4 00 00 00 00 > + # Button: 0 1 0 | # | X: 0 | Y: 0 | Wheel: 0 > + E: 000001.959698 4 02 00 00 00 > + # Button: 0 0 0 | # | X: 0 | Y: 0 | Wheel: 0 > + E: 000002.103899 4 00 00 00 00 > + # Button: 0 0 1 | # | X: 0 | Y: 0 | Wheel: 0 > + E: 000004.855799 4 04 00 00 00 > + # Button: 0 0 0 | # | X: 0 | Y: 0 | Wheel: 0 > + E: 000005.103864 4 00 00 00 00 > + > +This example shows that when button 2 is clicked, > +the bytes ``02 00 00 00`` are sent, and the immediately subsequent > +event (``00 00 00 00``) is the release of button 2 (no buttons are pressed, > +remember that the data is *absolute*). > + > +If instead one clicks and holds button 1, then clicks and holds button 2, > +releases button 1, and finally releases button 2, the reports are:: > + > + # Button: 1 0 0 | # | X: 0 | Y: 0 | Wheel: 0 > + E: 000044.175830 4 01 00 00 00 > + # Button: 1 1 0 | # | X: 0 | Y: 0 | Wheel: 0 > + E: 000045.975997 4 03 00 00 00 > + # Button: 0 1 0 | # | X: 0 | Y: 0 | Wheel: 0 > + E: 000047.407930 4 02 00 00 00 > + # Button: 0 0 0 | # | X: 0 | Y: 0 | Wheel: 0 > + E: 000049.199919 4 00 00 00 00 > + > +where with ``03 00 00 00`` both buttons are pressed, and with the > +subsequent ``02 00 00 00`` button 1 is released while button 2 is still > +active. > + > +Output, Input and Feature Reports > +--------------------------------- > + > +An HID devices can have Input Reports, like > +in the mouse example, Output Reports, and Features Reports. s/Features/Feature/ > +"Output" means that the information is fed s/fed/sent/ > +to the device. For example, > +a joystick with force feedback will have > +some output; the led of a keyboard would > +need an output as well. > +"Input" means that data > +come from the device. s/come/comes/ Not sure, never got the hang of singular vs plural data, whatever is used in the rest of the documentation. > + > +"Feature"s are not meant to be consumed by the end user > +and define configuration options for the device. > +They can be queried from the host; > +when declared as *Volatile* > +they should be changed by the host. > + > + > +Collections, Report IDs and Evdev events > +======================================== > + > +A single device can logically group > +data into different, independent sets, > +called *Collection*. "called a *Collection*" > +Collections can be nested, and there > +are different types of collections > +(see the HID spec 6.2.2.6 > +"Collection, End Collection Items" for details). > + > +Different reports are identified by means > +of different *Report ID* fields, i.e. a number identifying > +the structure of the immediately following report. > +Whenever a Report ID > +is needed it is transmitted as the first byte of any report. "A device with only one supported HID report (like the mouse example above) may omit the report ID." > + > +Consider the following HID report descriptor:: > + > + 05 01 09 02 A1 01 85 01 05 09 19 01 29 05 15 00 > + 25 01 95 05 75 01 81 02 95 01 75 03 81 01 05 01 > + 09 30 09 31 16 00 F8 26 FF 07 75 0C 95 02 81 06 > + 09 38 15 80 25 7F 75 08 95 01 81 06 05 0C 0A 38 > + 02 15 80 25 7F 75 08 95 01 81 06 C0 05 01 09 02 > + A1 01 85 02 05 09 19 01 29 05 15 00 25 01 95 05 > + 75 01 81 02 95 01 75 03 81 01 05 01 09 30 09 31 > + 16 00 F8 26 FF 07 75 0C 95 02 81 06 09 38 15 80 > + 25 7F 75 08 95 01 81 06 05 0C 0A 38 02 15 80 25 > + 7F 75 08 95 01 81 06 C0 05 01 09 07 A1 01 85 05 > + 05 07 15 00 25 01 09 29 09 3E 09 4B 09 4E 09 E3 > + 09 E8 09 E8 09 E8 75 01 95 08 81 02 95 00 81 01 > + C0 05 0C 09 01 A1 01 85 06 15 00 25 01 75 01 95 > + 01 09 3F 81 06 09 3F 81 06 09 3F 81 06 09 3F 81 > + 06 09 3F 81 06 09 3F 81 06 09 3F 81 06 09 3F 81 > + 06 C0 05 0C 09 01 A1 01 85 03 09 05 15 00 26 FF > + 00 75 08 95 02 B1 02 C0 > + > +After parsing it (try to parse it on your own using > +the suggested tools!) > +one can see that the device presents two ``Mouse`` > +Application Collections > +(with reports identified by Reports IDs 1 and 2, respectively), > +a ``Keypad`` Application Collection (whose report is identified > +by the Report ID 5) and two ``Consumer Controls`` > +Application Collections, > +(with Report IDs 6 and 3, respectively). > +Note that, however, that you can have different Report IDs > +for the same Application Collection. > + > +The data sent will begin with the Report ID byte, and will be followed > +by the corresponding information. For example, the > +data transmitted for the last consumer > +control:: > + > + 0x05, 0x0C, // Usage Page (Consumer) > + 0x09, 0x01, // Usage (Consumer Control) > + 0xA1, 0x01, // Collection (Application) > + 0x85, 0x03, // Report ID (3) > + 0x09, 0x05, // Usage (Headphone) > + 0x15, 0x00, // Logical Minimum (0) > + 0x26, 0xFF, 0x00, // Logical Maximum (255) > + 0x75, 0x08, // Report Size (8) > + 0x95, 0x02, // Report Count (2) > + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) > + 0xC0, // End Collection > + > +will be of three bytes: the first for the Report ID (3), the next two > +for the headphone, with two (``Report Count (2)``) bytes > +(``Report Size (8)``), each ranging from 0 (``Logical Minimum (0)`` to 255 > +(``Logical Maximum (255)``). > + > +All the Input data sent by the device should be translated into corresponding > +Evdev events, so that the remaining part of the stack can know what is going on, > +e.g. that a mouse button was pressed, rather > +than a mouse has been moved in the X direction. This example is so obvious that it's actually confusing, a better example may be: "e.g. the bit for the first button translates into the EV_KEY/BTN_LEFT evdev event and relative x movement translates into the EV_REL/REL_X evdev event". > + > +Events > +====== > + > +In Linux, one ``/dev/input/event*`` is created for each > +``Application Collection``. > +Going back to the mouse example, and repeating the sequence where > +one clicks and holds button 1, then clicks and holds button 2, > +releases button 1, and finally releases button 2, one gets:: > + > + marco@sun:~> sudo libinput record /dev/input/event1 $ prompt reminder > + # libinput record > + version: 1 > + ndevices: 1 > + libinput: > + version: "1.23.0" > + git: "unknown" > + system: > + os: "opensuse-tumbleweed:20230619" > + kernel: "6.3.7-1-default" > + dmi: "dmi:bvnHP:bvrU77Ver.01.05.00:bd03/24/2022:br5.0:efr20.29:svnHP:pnHPEliteBook64514inchG9NotebookPC:pvr:rvnHP:rn89D2:rvrKBCVersion14.1D.00:cvnHP:ct10:cvr:sku5Y3J1EA#ABZ:" > + devices: > + - node: /dev/input/event1 > + evdev: > + # Name: PixArt HP USB Optical Mouse > + # ID: bus 0x3 vendor 0x3f0 product 0x94a version 0x111 > + # Supported Events: > + # Event type 0 (EV_SYN) > + # Event type 1 (EV_KEY) > + # Event code 272 (BTN_LEFT) > + # Event code 273 (BTN_RIGHT) > + # Event code 274 (BTN_MIDDLE) > + # Event type 2 (EV_REL) > + # Event code 0 (REL_X) > + # Event code 1 (REL_Y) > + # Event code 8 (REL_WHEEL) > + # Event code 11 (REL_WHEEL_HI_RES) > + # Event type 4 (EV_MSC) > + # Event code 4 (MSC_SCAN) > + # Properties: > + name: "PixArt HP USB Optical Mouse" > + id: [3, 1008, 2378, 273] > + codes: > + 0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] # EV_SYN > + 1: [272, 273, 274] # EV_KEY > + 2: [0, 1, 8, 11] # EV_REL > + 4: [4] # EV_MSC > + properties: [] > + hid: [ > + 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, > + 0x15, 0x00, 0x25, 0x01, 0x95, 0x08, 0x75, 0x01, 0x81, 0x02, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, > + 0x09, 0x38, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x03, 0x81, 0x06, 0xc0, 0xc0 > + ] > + udev: > + properties: > + - ID_INPUT=1 > + - ID_INPUT_MOUSE=1 > + - LIBINPUT_DEVICE_GROUP=3/3f0/94a:usb-0000:05:00.3-2 > + quirks: > + events: > + # Current time is 12:31:56 > + - evdev: > + - [ 0, 0, 4, 4, 30] # EV_MSC / MSC_SCAN 30 (obfuscated) > + - [ 0, 0, 1, 272, 1] # EV_KEY / BTN_LEFT 1 > + - [ 0, 0, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +0ms > + - evdev: > + - [ 1, 207892, 4, 4, 30] # EV_MSC / MSC_SCAN 30 (obfuscated) > + - [ 1, 207892, 1, 273, 1] # EV_KEY / BTN_RIGHT 1 > + - [ 1, 207892, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +1207ms > + - evdev: > + - [ 2, 367823, 4, 4, 30] # EV_MSC / MSC_SCAN 30 (obfuscated) > + - [ 2, 367823, 1, 272, 0] # EV_KEY / BTN_LEFT 0 > + - [ 2, 367823, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +1160ms > + # Current time is 12:32:00 > + - evdev: > + - [ 3, 247617, 4, 4, 30] # EV_MSC / MSC_SCAN 30 (obfuscated) > + - [ 3, 247617, 1, 273, 0] # EV_KEY / BTN_RIGHT 0 > + - [ 3, 247617, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +880ms > + > +Note: if ``libinput`` is not available on your system try using ``evemu-record``. > + > +When something does not work > +============================ > + > +There can be a number of reasons for why a device does not behave > +correctly. For example > + > +* The HID report descriptor provided by the HID device may be wrong > + because e.g. > + > + * it does not follow the standard, so that the kernel > + will not able to make sense of the HID report descriptor; > + * it is possible to verify, by reading the raw HID data, that > + the HID report descriptor *does not match* what is actually > + sent by the device; * the HID report descriptor *does not match* what is actually sent by the device (this can be verified by reading the raw HID data), > + > +or > + skip the or, we're already in an enumeration anyway so this can be a single list > +* the HID report descriptor may need some "quirks" (see later on); > + > +As a consequence, a suitable ``/dev/input/event*`` will not created s/suitable// s/will/may/ > +for each Application Collection, and/or the events > +there will match what you would expect. s/will/may not/ > + > + > +Quirks > +------ > + > +There are some known peculiarities of HID devices that the kernel > +knows how to fix - these are called the HID quirks and a list of those > +are available in `include/linux/hid.h`. > + > +Should this be the case, > +it should be enough to add the required quirk, > +in the kernel, for the HID device at hand. > +This can be done in file `drivers/hid/hid-quirks.c`. s/file/the file/ > +How to do it should be relatively straightforward > +after looking into the file. > + > +The list of currently defined quirks, from > +`include/linux/hid.h`, is > + > +.. kernel-doc:: include/linux/hid.h > + :doc: HID quirks > + > +Quirks for USB devices can be specified > +while loading the usbhid module, > +see ``modinfo usbhid``, although the proper fix > +should go into hid-quirks.c and **submitted upstream**. > +See, again, Documentation/process/submitting-patches.rst s/, again,// (sounds too patronising otherwise) > +for guidelines on how to do submit a patch. > +Quirks for other busses need to go into hid-quirks.c > + > +Fixing HID report descriptors > +----------------------------- > + > +Should you need to patch HID report descriptors > +the easiest way is to resort to eBPF, as described > +in Documentation/hid/hid-bpf.rst. > + > +Basically, you can change any byte of the original HID report descriptor. > +The examples in samples/hid should be a good starting point > +for your code, see e.g. `samples/hid_mouse.bpf.c`:: > + > + SEC("fmod_ret/hid_bpf_rdesc_fixup") > + int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx) > + { > + .... > + data[39] = 0x31; > + data[41] = 0x30; > + return 0; > + } > + > +Of course this can be also done within the kernel source > +code, see e.g. `drivers/hid/hid-aureal.c` or > +`drivers/hid/hid-samsung.c` for a slightly more complex file. > + > +Check Documentation/hid/hidreport-parsing.rst > +if you need an help navigating the HID manuals and > +understanding the exact meaning of > +the HID report descriptor hex numbers. > + > +Whatever solution you come up with, please remember to **submit the > +fix to the HID maintainers**, so that it can be directly > +integrated in the kernel > +and that particular HID device will will start > +working for everyone else. > +See Documentation/process/submitting-patches.rst > +for guidelines on how to do this. > + > + > +Modifying the transmitted data on the fly > +----------------------------------------- > + > +Using eBPF it is also possible to modify the data exchanged > +with the device. See again the examples in `samples/hid`. > + > +Again, **please post your fix**, so that > +it can be integrated in the kernel! > + > +Writing a specialized driver > +---------------------------- > + > +This should really be your last resort. > + > + > +.. rubric:: Footnotes > + > +.. [#hidraw] reading hidraw: see Documentation/hid/hidraw.rst and > + file `samples/hidraw/hid-example.c` for an example. > + The output of ``hid-example`` would be, for the same mouse:: > + > + marco@sun:~> sudo ./hid-example $ prompt reminder > + Report Descriptor Size: 52 > + Report Descriptor: > + 5 1 9 2 a1 1 9 1 a1 0 5 9 19 1 29 3 15 0 25 1 75 1 95 3 81 2 75 5 95 1 81 1 5 1 9 30 9 31 9 38 15 81 25 7f 75 8 95 3 81 6 c0 c0 > + > + Raw Name: PixArt USB Optical Mouse > + Raw Phys: usb-0000:05:00.4-2.3/input0 > + Raw Info: > + bustype: 3 (USB) > + vendor: 0x093a > + product: 0x2510 > + ... > diff --git a/Documentation/hid/hidreport-parsing.rst b/Documentation/hid/hidreport-parsing.rst > new file mode 100644 > index 000000000000..a31a7aec5947 > --- /dev/null > +++ b/Documentation/hid/hidreport-parsing.rst > @@ -0,0 +1,52 @@ > +.. SPDX-License-Identifier: GPL-2.0 > + > +======================================== > +Manual parsing of HID report descriptors > +======================================== > + > +Consider again the mouse HID report descriptor > +introduced in Documentation/hid/hidintro.rst:: > + > + marco@sun:~> hexdump -C /sys/bus/hid/devices/0003\:093A\:2510.0002/report_descriptor > + 00000000 05 01 09 02 a1 01 09 01 a1 00 05 09 19 01 29 03 |..............).| > + 00000010 15 00 25 01 75 01 95 03 81 02 75 05 95 01 81 01 |..%.u.....u.....| > + 00000020 05 01 09 30 09 31 09 38 15 81 25 7f 75 08 95 03 |...0.1.8..%.u...| > + 00000030 81 06 c0 c0 |....| > + 00000034 > + > +and try to parse it by hand. > + > +Start with the first number, 0x05: according to > +the HID spec, Sec. 6.2.2.2, "Short Items" > + > +Start with the first number, 0x05 which carries 2 bits for the > +length of the item, 2 bits for the type of the item and 4 bits for the > +function:: > + > + +----------+ > + | 00000101 | > + +----------+ > + ^^ > + ---- Length of data (see HID spec 6.2.2.2) > + ^^ > + ------ Type of the item (see HID spec 6.2.2.7) > + ^^^^ > + --------- Function of the item (see HUT Sec 3) this is misaligned Cheers, Peter > + > +In our case, the length is 1 byte, the type is ``Global`` and the function > +is ``Usage Page``, thus we need to refer to HUT Sec 3 which indicates that > +the value 0x01 in the second byte stands for ``Generic Desktop Page``. > + > +The second number is the actual data, and its meaning can > +be found in the HUT. > +We have an ``Usage Page``, thus we need to refer to HUT Sec. 3, > +"Usage Pages"; from there, one sees that the ``0x01`` > +stands for ``Generic Desktop Page``. > + > +Moving now to the second two bytes, and following the same scheme, ``0x09`` > +(i.e. ``00001001``) will be followed by one byte (``01``) > +and is a ``Local`` item. > +Thus, the meaning of the remaining four bits (``0000``) > +is given in the HID spec Sec. 6.2.2.8 "Local Items", so that we have an ``Usage``. > + > +The following numbers can be parsed in the same way. > diff --git a/Documentation/hid/index.rst b/Documentation/hid/index.rst > index b2028f382f11..af02cf7cfa82 100644 > --- a/Documentation/hid/index.rst > +++ b/Documentation/hid/index.rst > @@ -7,6 +7,7 @@ Human Interface Devices (HID) > .. toctree:: > :maxdepth: 1 > > + hidintro > hiddev > hidraw > hid-sensor > diff --git a/include/linux/hid.h b/include/linux/hid.h > index 7f2e8ba7d783..ad12a36d9993 100644 > --- a/include/linux/hid.h > +++ b/include/linux/hid.h > @@ -341,6 +341,29 @@ struct hid_item { > */ > #define MAX_USBHID_BOOT_QUIRKS 4 > > +/** > +* DOC: HID quirks > +* | @HID_QUIRK_NOTOUCH: > +* | @HID_QUIRK_IGNORE: ignore this device > +* | @HID_QUIRK_NOGET: > +* | @HID_QUIRK_HIDDEV_FORCE: > +* | @HID_QUIRK_BADPAD: > +* | @HID_QUIRK_MULTI_INPUT: > +* | @HID_QUIRK_HIDINPUT_FORCE: > +* | @HID_QUIRK_ALWAYS_POLL: > +* | @HID_QUIRK_INPUT_PER_APP: > +* | @HID_QUIRK_X_INVERT: > +* | @HID_QUIRK_Y_INVERT: > +* | @HID_QUIRK_SKIP_OUTPUT_REPORTS: > +* | @HID_QUIRK_SKIP_OUTPUT_REPORT_ID: > +* | @HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP: > +* | @HID_QUIRK_HAVE_SPECIAL_DRIVER: > +* | @HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE: > +* | @HID_QUIRK_FULLSPEED_INTERVAL: > +* | @HID_QUIRK_NO_INIT_REPORTS: > +* | @HID_QUIRK_NO_IGNORE: > +* | @HID_QUIRK_NO_INPUT_SYNC: > +*/ > /* BIT(0) reserved for backward compatibility, was HID_QUIRK_INVERT */ > #define HID_QUIRK_NOTOUCH BIT(1) > #define HID_QUIRK_IGNORE BIT(2) > -- > 2.41.0 >