|
@@ -0,0 +1,169 @@
|
|
|
+ UHID - User-space I/O driver support for HID subsystem
|
|
|
+ ========================================================
|
|
|
+
|
|
|
+The HID subsystem needs two kinds of drivers. In this document we call them:
|
|
|
+
|
|
|
+ 1. The "HID I/O Driver" is the driver that performs raw data I/O to the
|
|
|
+ low-level device. Internally, they register an hid_ll_driver structure with
|
|
|
+ the HID core. They perform device setup, read raw data from the device and
|
|
|
+ push it into the HID subsystem and they provide a callback so the HID
|
|
|
+ subsystem can send data to the device.
|
|
|
+
|
|
|
+ 2. The "HID Device Driver" is the driver that parses HID reports and reacts on
|
|
|
+ them. There are generic drivers like "generic-usb" and "generic-bluetooth"
|
|
|
+ which adhere to the HID specification and provide the standardizes features.
|
|
|
+ But there may be special drivers and quirks for each non-standard device out
|
|
|
+ there. Internally, they use the hid_driver structure.
|
|
|
+
|
|
|
+Historically, the USB stack was the first subsystem to provide an HID I/O
|
|
|
+Driver. However, other standards like Bluetooth have adopted the HID specs and
|
|
|
+may provide HID I/O Drivers, too. The UHID driver allows to implement HID I/O
|
|
|
+Drivers in user-space and feed the data into the kernel HID-subsystem.
|
|
|
+
|
|
|
+This allows user-space to operate on the same level as USB-HID, Bluetooth-HID
|
|
|
+and similar. It does not provide a way to write HID Device Drivers, though. Use
|
|
|
+hidraw for this purpose.
|
|
|
+
|
|
|
+There is an example user-space application in ./samples/uhid/uhid-example.c
|
|
|
+
|
|
|
+The UHID API
|
|
|
+------------
|
|
|
+
|
|
|
+UHID is accessed through a character misc-device. The minor-number is allocated
|
|
|
+dynamically so you need to rely on udev (or similar) to create the device node.
|
|
|
+This is /dev/uhid by default.
|
|
|
+
|
|
|
+If a new device is detected by your HID I/O Driver and you want to register this
|
|
|
+device with the HID subsystem, then you need to open /dev/uhid once for each
|
|
|
+device you want to register. All further communication is done by read()'ing or
|
|
|
+write()'ing "struct uhid_event" objects. Non-blocking operations are supported
|
|
|
+by setting O_NONBLOCK.
|
|
|
+
|
|
|
+struct uhid_event {
|
|
|
+ __u32 type;
|
|
|
+ union {
|
|
|
+ struct uhid_create_req create;
|
|
|
+ struct uhid_data_req data;
|
|
|
+ ...
|
|
|
+ } u;
|
|
|
+};
|
|
|
+
|
|
|
+The "type" field contains the ID of the event. Depending on the ID different
|
|
|
+payloads are sent. You must not split a single event across multiple read()'s or
|
|
|
+multiple write()'s. A single event must always be sent as a whole. Furthermore,
|
|
|
+only a single event can be sent per read() or write(). Pending data is ignored.
|
|
|
+If you want to handle multiple events in a single syscall, then use vectored
|
|
|
+I/O with readv()/writev().
|
|
|
+
|
|
|
+The first thing you should do is sending an UHID_CREATE event. This will
|
|
|
+register the device. UHID will respond with an UHID_START event. You can now
|
|
|
+start sending data to and reading data from UHID. However, unless UHID sends the
|
|
|
+UHID_OPEN event, the internally attached HID Device Driver has no user attached.
|
|
|
+That is, you might put your device asleep unless you receive the UHID_OPEN
|
|
|
+event. If you receive the UHID_OPEN event, you should start I/O. If the last
|
|
|
+user closes the HID device, you will receive an UHID_CLOSE event. This may be
|
|
|
+followed by an UHID_OPEN event again and so on. There is no need to perform
|
|
|
+reference-counting in user-space. That is, you will never receive multiple
|
|
|
+UHID_OPEN events without an UHID_CLOSE event. The HID subsystem performs
|
|
|
+ref-counting for you.
|
|
|
+You may decide to ignore UHID_OPEN/UHID_CLOSE, though. I/O is allowed even
|
|
|
+though the device may have no users.
|
|
|
+
|
|
|
+If you want to send data to the HID subsystem, you send an HID_INPUT event with
|
|
|
+your raw data payload. If the kernel wants to send data to the device, you will
|
|
|
+read an UHID_OUTPUT or UHID_OUTPUT_EV event.
|
|
|
+
|
|
|
+If your device disconnects, you should send an UHID_DESTROY event. This will
|
|
|
+unregister the device. You can now send UHID_CREATE again to register a new
|
|
|
+device.
|
|
|
+If you close() the fd, the device is automatically unregistered and destroyed
|
|
|
+internally.
|
|
|
+
|
|
|
+write()
|
|
|
+-------
|
|
|
+write() allows you to modify the state of the device and feed input data into
|
|
|
+the kernel. The following types are supported: UHID_CREATE, UHID_DESTROY and
|
|
|
+UHID_INPUT. The kernel will parse the event immediately and if the event ID is
|
|
|
+not supported, it will return -EOPNOTSUPP. If the payload is invalid, then
|
|
|
+-EINVAL is returned, otherwise, the amount of data that was read is returned and
|
|
|
+the request was handled successfully.
|
|
|
+
|
|
|
+ UHID_CREATE:
|
|
|
+ This creates the internal HID device. No I/O is possible until you send this
|
|
|
+ event to the kernel. The payload is of type struct uhid_create_req and
|
|
|
+ contains information about your device. You can start I/O now.
|
|
|
+
|
|
|
+ UHID_DESTROY:
|
|
|
+ This destroys the internal HID device. No further I/O will be accepted. There
|
|
|
+ may still be pending messages that you can receive with read() but no further
|
|
|
+ UHID_INPUT events can be sent to the kernel.
|
|
|
+ You can create a new device by sending UHID_CREATE again. There is no need to
|
|
|
+ reopen the character device.
|
|
|
+
|
|
|
+ UHID_INPUT:
|
|
|
+ You must send UHID_CREATE before sending input to the kernel! This event
|
|
|
+ contains a data-payload. This is the raw data that you read from your device.
|
|
|
+ The kernel will parse the HID reports and react on it.
|
|
|
+
|
|
|
+ UHID_FEATURE_ANSWER:
|
|
|
+ If you receive a UHID_FEATURE request you must answer with this request. You
|
|
|
+ must copy the "id" field from the request into the answer. Set the "err" field
|
|
|
+ to 0 if no error occured or to EIO if an I/O error occurred.
|
|
|
+ If "err" is 0 then you should fill the buffer of the answer with the results
|
|
|
+ of the feature request and set "size" correspondingly.
|
|
|
+
|
|
|
+read()
|
|
|
+------
|
|
|
+read() will return a queued ouput report. These output reports can be of type
|
|
|
+UHID_START, UHID_STOP, UHID_OPEN, UHID_CLOSE, UHID_OUTPUT or UHID_OUTPUT_EV. No
|
|
|
+reaction is required to any of them but you should handle them according to your
|
|
|
+needs. Only UHID_OUTPUT and UHID_OUTPUT_EV have payloads.
|
|
|
+
|
|
|
+ UHID_START:
|
|
|
+ This is sent when the HID device is started. Consider this as an answer to
|
|
|
+ UHID_CREATE. This is always the first event that is sent.
|
|
|
+
|
|
|
+ UHID_STOP:
|
|
|
+ This is sent when the HID device is stopped. Consider this as an answer to
|
|
|
+ UHID_DESTROY.
|
|
|
+ If the kernel HID device driver closes the device manually (that is, you
|
|
|
+ didn't send UHID_DESTROY) then you should consider this device closed and send
|
|
|
+ an UHID_DESTROY event. You may want to reregister your device, though. This is
|
|
|
+ always the last message that is sent to you unless you reopen the device with
|
|
|
+ UHID_CREATE.
|
|
|
+
|
|
|
+ UHID_OPEN:
|
|
|
+ This is sent when the HID device is opened. That is, the data that the HID
|
|
|
+ device provides is read by some other process. You may ignore this event but
|
|
|
+ it is useful for power-management. As long as you haven't received this event
|
|
|
+ there is actually no other process that reads your data so there is no need to
|
|
|
+ send UHID_INPUT events to the kernel.
|
|
|
+
|
|
|
+ UHID_CLOSE:
|
|
|
+ This is sent when there are no more processes which read the HID data. It is
|
|
|
+ the counterpart of UHID_OPEN and you may as well ignore this event.
|
|
|
+
|
|
|
+ UHID_OUTPUT:
|
|
|
+ This is sent if the HID device driver wants to send raw data to the I/O
|
|
|
+ device. You should read the payload and forward it to the device. The payload
|
|
|
+ is of type "struct uhid_data_req".
|
|
|
+ This may be received even though you haven't received UHID_OPEN, yet.
|
|
|
+
|
|
|
+ UHID_OUTPUT_EV:
|
|
|
+ Same as UHID_OUTPUT but this contains a "struct input_event" as payload. This
|
|
|
+ is called for force-feedback, LED or similar events which are received through
|
|
|
+ an input device by the HID subsystem. You should convert this into raw reports
|
|
|
+ and send them to your device similar to events of type UHID_OUTPUT.
|
|
|
+
|
|
|
+ UHID_FEATURE:
|
|
|
+ This event is sent if the kernel driver wants to perform a feature request as
|
|
|
+ described in the HID specs. The report-type and report-number are available in
|
|
|
+ the payload.
|
|
|
+ The kernel serializes feature requests so there will never be two in parallel.
|
|
|
+ However, if you fail to respond with a UHID_FEATURE_ANSWER in a time-span of 5
|
|
|
+ seconds, then the requests will be dropped and a new one might be sent.
|
|
|
+ Therefore, the payload also contains an "id" field that identifies every
|
|
|
+ request.
|
|
|
+
|
|
|
+Document by:
|
|
|
+ David Herrmann <dh.herrmann@googlemail.com>
|