Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 1 | ====================================================== |
| 2 | UHID - User-space I/O driver support for HID subsystem |
| 3 | ====================================================== |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 4 | |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 5 | UHID allows user-space to implement HID transport drivers. Please see |
| 6 | hid-transport.txt for an introduction into HID transport drivers. This document |
| 7 | relies heavily on the definitions declared there. |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 8 | |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 9 | With UHID, a user-space transport driver can create kernel hid-devices for each |
| 10 | device connected to the user-space controlled bus. The UHID API defines the I/O |
| 11 | events provided from the kernel to user-space and vice versa. |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 12 | |
| 13 | There is an example user-space application in ./samples/uhid/uhid-example.c |
| 14 | |
| 15 | The UHID API |
| 16 | ------------ |
| 17 | |
| 18 | UHID is accessed through a character misc-device. The minor-number is allocated |
| 19 | dynamically so you need to rely on udev (or similar) to create the device node. |
| 20 | This is /dev/uhid by default. |
| 21 | |
| 22 | If a new device is detected by your HID I/O Driver and you want to register this |
| 23 | device with the HID subsystem, then you need to open /dev/uhid once for each |
| 24 | device you want to register. All further communication is done by read()'ing or |
| 25 | write()'ing "struct uhid_event" objects. Non-blocking operations are supported |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 26 | by setting O_NONBLOCK:: |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 27 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 28 | struct uhid_event { |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 29 | __u32 type; |
| 30 | union { |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 31 | struct uhid_create2_req create2; |
| 32 | struct uhid_output_req output; |
| 33 | struct uhid_input2_req input2; |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 34 | ... |
| 35 | } u; |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 36 | }; |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 37 | |
| 38 | The "type" field contains the ID of the event. Depending on the ID different |
| 39 | payloads are sent. You must not split a single event across multiple read()'s or |
| 40 | multiple write()'s. A single event must always be sent as a whole. Furthermore, |
| 41 | only a single event can be sent per read() or write(). Pending data is ignored. |
| 42 | If you want to handle multiple events in a single syscall, then use vectored |
| 43 | I/O with readv()/writev(). |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 44 | The "type" field defines the payload. For each type, there is a |
| 45 | payload-structure available in the union "u" (except for empty payloads). This |
| 46 | payload contains management and/or device data. |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 47 | |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 48 | The first thing you should do is sending an UHID_CREATE2 event. This will |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 49 | register the device. UHID will respond with an UHID_START event. You can now |
| 50 | start sending data to and reading data from UHID. However, unless UHID sends the |
| 51 | UHID_OPEN event, the internally attached HID Device Driver has no user attached. |
| 52 | That is, you might put your device asleep unless you receive the UHID_OPEN |
| 53 | event. If you receive the UHID_OPEN event, you should start I/O. If the last |
| 54 | user closes the HID device, you will receive an UHID_CLOSE event. This may be |
| 55 | followed by an UHID_OPEN event again and so on. There is no need to perform |
| 56 | reference-counting in user-space. That is, you will never receive multiple |
| 57 | UHID_OPEN events without an UHID_CLOSE event. The HID subsystem performs |
| 58 | ref-counting for you. |
| 59 | You may decide to ignore UHID_OPEN/UHID_CLOSE, though. I/O is allowed even |
| 60 | though the device may have no users. |
| 61 | |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 62 | If you want to send data on the interrupt channel to the HID subsystem, you send |
| 63 | an HID_INPUT2 event with your raw data payload. If the kernel wants to send data |
| 64 | on the interrupt channel to the device, you will read an UHID_OUTPUT event. |
| 65 | Data requests on the control channel are currently limited to GET_REPORT and |
| 66 | SET_REPORT (no other data reports on the control channel are defined so far). |
| 67 | Those requests are always synchronous. That means, the kernel sends |
| 68 | UHID_GET_REPORT and UHID_SET_REPORT events and requires you to forward them to |
| 69 | the device on the control channel. Once the device responds, you must forward |
| 70 | the response via UHID_GET_REPORT_REPLY and UHID_SET_REPORT_REPLY to the kernel. |
| 71 | The kernel blocks internal driver-execution during such round-trips (times out |
| 72 | after a hard-coded period). |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 73 | |
| 74 | If your device disconnects, you should send an UHID_DESTROY event. This will |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 75 | unregister the device. You can now send UHID_CREATE2 again to register a new |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 76 | device. |
| 77 | If you close() the fd, the device is automatically unregistered and destroyed |
| 78 | internally. |
| 79 | |
| 80 | write() |
| 81 | ------- |
| 82 | write() allows you to modify the state of the device and feed input data into |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 83 | the kernel. The kernel will parse the event immediately and if the event ID is |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 84 | not supported, it will return -EOPNOTSUPP. If the payload is invalid, then |
| 85 | -EINVAL is returned, otherwise, the amount of data that was read is returned and |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 86 | the request was handled successfully. O_NONBLOCK does not affect write() as |
| 87 | writes are always handled immediately in a non-blocking fashion. Future requests |
| 88 | might make use of O_NONBLOCK, though. |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 89 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 90 | UHID_CREATE2: |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 91 | This creates the internal HID device. No I/O is possible until you send this |
| 92 | event to the kernel. The payload is of type struct uhid_create2_req and |
| 93 | contains information about your device. You can start I/O now. |
Petri Gynther | 4522643 | 2014-03-24 13:50:01 -0700 | [diff] [blame] | 94 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 95 | UHID_DESTROY: |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 96 | This destroys the internal HID device. No further I/O will be accepted. There |
| 97 | may still be pending messages that you can receive with read() but no further |
| 98 | UHID_INPUT events can be sent to the kernel. |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 99 | You can create a new device by sending UHID_CREATE2 again. There is no need to |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 100 | reopen the character device. |
| 101 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 102 | UHID_INPUT2: |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 103 | You must send UHID_CREATE2 before sending input to the kernel! This event |
| 104 | contains a data-payload. This is the raw data that you read from your device |
| 105 | on the interrupt channel. The kernel will parse the HID reports. |
Petri Gynther | 4522643 | 2014-03-24 13:50:01 -0700 | [diff] [blame] | 106 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 107 | UHID_GET_REPORT_REPLY: |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 108 | If you receive a UHID_GET_REPORT request you must answer with this request. |
| 109 | You must copy the "id" field from the request into the answer. Set the "err" |
| 110 | field to 0 if no error occurred or to EIO if an I/O error occurred. |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 111 | If "err" is 0 then you should fill the buffer of the answer with the results |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 112 | of the GET_REPORT request and set "size" correspondingly. |
| 113 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 114 | UHID_SET_REPORT_REPLY: |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 115 | This is the SET_REPORT equivalent of UHID_GET_REPORT_REPLY. Unlike GET_REPORT, |
| 116 | SET_REPORT never returns a data buffer, therefore, it's sufficient to set the |
| 117 | "id" and "err" fields correctly. |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 118 | |
| 119 | read() |
| 120 | ------ |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 121 | read() will return a queued output report. No reaction is required to any of |
| 122 | them but you should handle them according to your needs. |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 123 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 124 | UHID_START: |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 125 | This is sent when the HID device is started. Consider this as an answer to |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 126 | UHID_CREATE2. This is always the first event that is sent. Note that this |
| 127 | event might not be available immediately after write(UHID_CREATE2) returns. |
| 128 | Device drivers might required delayed setups. |
| 129 | This event contains a payload of type uhid_start_req. The "dev_flags" field |
| 130 | describes special behaviors of a device. The following flags are defined: |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 131 | |
| 132 | - UHID_DEV_NUMBERED_FEATURE_REPORTS |
| 133 | - UHID_DEV_NUMBERED_OUTPUT_REPORTS |
| 134 | - UHID_DEV_NUMBERED_INPUT_REPORTS |
| 135 | |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 136 | Each of these flags defines whether a given report-type uses numbered |
| 137 | reports. If numbered reports are used for a type, all messages from |
| 138 | the kernel already have the report-number as prefix. Otherwise, no |
| 139 | prefix is added by the kernel. |
| 140 | For messages sent by user-space to the kernel, you must adjust the |
| 141 | prefixes according to these flags. |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 142 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 143 | UHID_STOP: |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 144 | This is sent when the HID device is stopped. Consider this as an answer to |
| 145 | UHID_DESTROY. |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 146 | |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 147 | If you didn't destroy your device via UHID_DESTROY, but the kernel sends an |
| 148 | UHID_STOP event, this should usually be ignored. It means that the kernel |
| 149 | reloaded/changed the device driver loaded on your HID device (or some other |
| 150 | maintenance actions happened). |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 151 | |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 152 | You can usually ignored any UHID_STOP events safely. |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 153 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 154 | UHID_OPEN: |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 155 | This is sent when the HID device is opened. That is, the data that the HID |
| 156 | device provides is read by some other process. You may ignore this event but |
| 157 | it is useful for power-management. As long as you haven't received this event |
| 158 | there is actually no other process that reads your data so there is no need to |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 159 | send UHID_INPUT2 events to the kernel. |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 160 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 161 | UHID_CLOSE: |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 162 | This is sent when there are no more processes which read the HID data. It is |
| 163 | the counterpart of UHID_OPEN and you may as well ignore this event. |
| 164 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 165 | UHID_OUTPUT: |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 166 | This is sent if the HID device driver wants to send raw data to the I/O |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 167 | device on the interrupt channel. You should read the payload and forward it to |
Peter Hutterer | 46b14ee | 2018-12-13 11:28:51 +1000 | [diff] [blame] | 168 | the device. The payload is of type "struct uhid_output_req". |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 169 | This may be received even though you haven't received UHID_OPEN, yet. |
| 170 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 171 | UHID_GET_REPORT: |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 172 | This event is sent if the kernel driver wants to perform a GET_REPORT request |
| 173 | on the control channeld as described in the HID specs. The report-type and |
| 174 | report-number are available in the payload. |
| 175 | The kernel serializes GET_REPORT requests so there will never be two in |
| 176 | parallel. However, if you fail to respond with a UHID_GET_REPORT_REPLY, the |
| 177 | request might silently time out. |
| 178 | Once you read a GET_REPORT request, you shall forward it to the hid device and |
| 179 | remember the "id" field in the payload. Once your hid device responds to the |
| 180 | GET_REPORT (or if it fails), you must send a UHID_GET_REPORT_REPLY to the |
| 181 | kernel with the exact same "id" as in the request. If the request already |
| 182 | timed out, the kernel will ignore the response silently. The "id" field is |
| 183 | never re-used, so conflicts cannot happen. |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 184 | |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 185 | UHID_SET_REPORT: |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 186 | This is the SET_REPORT equivalent of UHID_GET_REPORT. On receipt, you shall |
| 187 | send a SET_REPORT request to your hid device. Once it replies, you must tell |
| 188 | the kernel about it via UHID_SET_REPORT_REPLY. |
| 189 | The same restrictions as for UHID_GET_REPORT apply. |
David Herrmann | d99b8ba | 2012-06-10 15:16:26 +0200 | [diff] [blame] | 190 | |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 191 | ---------------------------------------------------- |
Mauro Carvalho Chehab | cca4786 | 2019-06-28 09:19:59 -0300 | [diff] [blame] | 192 | |
David Herrmann | 76c7c49 | 2014-07-29 17:14:26 +0200 | [diff] [blame] | 193 | Written 2012, David Herrmann <dh.herrmann@gmail.com> |