linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] HID: Add HID transport driver documentation
@ 2014-01-29 15:28 Frank Praznik
  2014-01-29 15:35 ` David Herrmann
  0 siblings, 1 reply; 6+ messages in thread
From: Frank Praznik @ 2014-01-29 15:28 UTC (permalink / raw)
  To: linux-input; +Cc: jkosina, dh.herrmann, Frank Praznik

Add David Herrmann's documentation for the new low-level HID transport driver
functions. 

Signed-off-by: Frank Praznik <frank.praznik@oh.rr.com>

---
 
 Sorry, I forgot to include this in the original patch set.

 Documentation/hid/hid-transport.txt | 324 ++++++++++++++++++++++++++++++++++++
 1 file changed, 324 insertions(+)
 create mode 100644 Documentation/hid/hid-transport.txt

diff --git a/Documentation/hid/hid-transport.txt b/Documentation/hid/hid-transport.txt
new file mode 100644
index 0000000..14b1c18
--- /dev/null
+++ b/Documentation/hid/hid-transport.txt
@@ -0,0 +1,324 @@
+                          HID I/O Transport Drivers
+                         ===========================
+
+The HID subsystem is independent of the underlying transport driver. Initially,
+only USB was supported, but other specifications adopted the HID design and
+provided new transport drivers. The kernel includes at least support for USB,
+Bluetooth, I2C and user-space I/O drivers.
+
+1) HID Bus
+==========
+
+The HID subsystem is designed as a bus. Any I/O subsystem may provide HID
+devices and register them with the HID bus. HID core then loads generic device
+drivers on top of it. The transport drivers are responsible of raw data
+transport and device setup/management. HID core is responsible of
+report-parsing, report interpretation and the user-space API. Device specifics
+and quirks are handled by all layers depending on the quirk.
+
+ +-----------+  +-----------+            +-----------+  +-----------+
+ | Device #1 |  | Device #i |            | Device #j |  | Device #k |
+ +-----------+  +-----------+            +-----------+  +-----------+
+          \\      //                              \\      //
+        +------------+                          +------------+
+        | I/O Driver |                          | I/O Driver |
+        +------------+                          +------------+
+              ||                                      ||
+     +------------------+                    +------------------+
+     | Transport Driver |                    | Transport Driver |
+     +------------------+                    +------------------+
+                       \___                ___/
+                           \              /
+                          +----------------+
+                          |    HID Core    |
+                          +----------------+
+                           /  |        |  \
+                          /   |        |   \
+             ____________/    |        |    \_________________
+            /                 |        |                      \
+           /                  |        |                       \
+ +----------------+  +-----------+  +------------------+  +------------------+
+ | Generic Driver |  | MT Driver |  | Custom Driver #1 |  | Custom Driver #2 |
+ +----------------+  +-----------+  +------------------+  +------------------+
+
+Example Drivers:
+  I/O: USB, I2C, Bluetooth-l2cap
+  Transport: USB-HID, I2C-HID, BT-HIDP
+
+Everything below "HID Core" is simplified in this graph as it is only of
+interest to HID device drivers. Transport drivers do not need to know the
+specifics.
+
+1.1) Device Setup
+-----------------
+
+I/O drivers normally provide hotplug detection or device enumeration APIs to the
+transport drivers. Transport drivers use this to find any suitable HID device.
+They allocate HID device objects and register them with HID core. Transport
+drivers are not required to register themselves with HID core. HID core is never
+aware of which transport drivers are available and is not interested in it. It
+is only interested in devices.
+
+Transport drivers attach a constant "struct hid_ll_driver" object with each
+device. Once a device is registered with HID core, the callbacks provided via
+this struct are used by HID core to communicate with the device.
+
+Transport drivers are responsible of detecting device failures and unplugging.
+HID core will operate a device as long as it is registered regardless of any
+device failures. Once transport drivers detect unplug or failure events, they
+must unregister the device from HID core and HID core will stop using the
+provided callbacks.
+
+1.2) Transport Driver Requirements
+----------------------------------
+
+The terms "asynchronous" and "synchronous" in this document describe the
+transmission behavior regarding acknowledgements. An asynchronous channel must
+not perform any synchronous operations like waiting for acknowledgements or
+verifications. Generally, HID calls operating on asynchronous channels must be
+running in atomic-context just fine.
+On the other hand, synchronous channels can be implemented by the transport
+driver in whatever way they like. They might just be the same as asynchronous
+channels, but they can also provide acknowledgement reports, automatic
+retransmission on failure, etc. in a blocking manner. If such functionality is
+required on asynchronous channels, a transport-driver must implement that via
+its own worker threads.
+
+HID core requires transport drivers to follow a given design. A Transport
+driver must provide two bi-directional I/O channels to each HID device. These
+channels must not necessarily be bi-directional in the hardware itself. A
+transport driver might just provide 4 uni-directional channels. Or it might
+multiplex all four on a single physical channel. However, in this document we
+will describe them as two bi-directional channels as they have several
+properties in common.
+
+ - Interrupt Channel (intr): The intr channel is used for asynchronous data
+   reports. No management commands or data acknowledgements are sent on this
+   channel. Any unrequested incoming or outgoing data report must be sent on
+   this channel and is never acknowledged by the remote side. Devices usually
+   send their input events on this channel. Outgoing events are normally
+   not send via intr, except if high throughput is required.
+ - Control Channel (ctrl): The ctrl channel is used for synchronous requests and
+   device management. Unrequested data input events must not be sent on this
+   channel and are normally ignored. Instead, devices only send management
+   events or answers to host requests on this channel.
+   The control-channel is used for direct blocking queries to the device
+   independent of any events on the intr-channel.
+   Outgoing reports are usually sent on the ctrl channel via synchronous
+   SET_REPORT requests.
+
+Communication between devices and HID core is mostly done via HID reports. A
+report can be of one of three types:
+
+ - INPUT Report: Input reports provide data from device to host. This
+   data may include button events, axis events, battery status or more. This
+   data is generated by the device and sent to the host with or without
+   requiring explicit requests. Devices can choose to send data continuously or
+   only on change.
+ - OUTPUT Report: Output reports change device states. They are sent from host
+   to device and may include LED requests, rumble requests or more. Output
+   reports are never sent from device to host, but a host can retrieve their
+   current state.
+   Hosts may choose to send output reports either continuously or only on
+   change.
+ - FEATURE Report: Feature reports are used for specific static device features
+   and never reported spontaneously. A host can read and/or write them to access
+   data like battery-state or device-settings.
+   Feature reports are never sent without requests. A host must explicitly set
+   or retrieve a feature report. This also means, feature reports are never sent
+   on the intr channel as this channel is asynchronous.
+
+INPUT and OUTPUT reports can be sent as pure data reports on the intr channel.
+For INPUT reports this is the usual operational mode. But for OUTPUT reports,
+this is rarely done as OUTPUT reports are normally quite scarce. But devices are
+free to make excessive use of asynchronous OUTPUT reports (for instance, custom
+HID audio speakers make great use of it).
+
+Plain reports must not be sent on the ctrl channel, though. Instead, the ctrl
+channel provides synchronous GET/SET_REPORT requests. Plain reports are only
+allowed on the intr channel and are the only means of data there.
+
+ - GET_REPORT: A GET_REPORT request has a report ID as payload and is sent
+   from host to device. The device must answer with a data report for the
+   requested report ID on the ctrl channel as a synchronous acknowledgement.
+   Only one GET_REPORT request can be pending for each device. This restriction
+   is enforced by HID core as several transport drivers don't allow multiple
+   simultaneous GET_REPORT requests.
+   Note that data reports which are sent as answer to a GET_REPORT request are
+   not handled as generic device events. That is, if a device does not operate
+   in continuous data reporting mode, an answer to GET_REPORT does not replace
+   the raw data report on the intr channel on state change.
+   GET_REPORT is only used by custom HID device drivers to query device state.
+   Normally, HID core caches any device state so this request is not necessary
+   on devices that follow the HID specs except during device initialization to
+   retrieve the current state.
+   GET_REPORT requests can be sent for any of the 3 report types and shall
+   return the current report state of the device. However, OUTPUT reports as
+   payload may be blocked by the underlying transport driver if the
+   specification does not allow them.
+ - SET_REPORT: A SET_REPORT request has a report ID plus data as payload. It is
+   sent from host to device and a device must update it's current report state
+   according to the given data. Any of the 3 report types can be used. However,
+   INPUT reports as payload might be blocked by the underlying transport driver
+   if the specification does not allow them.
+   A device must answer with a synchronous acknowledgement. However, HID core
+   does not require transport drivers to forward this acknowledgement to HID
+   core.
+   Same as for GET_REPORT, only one SET_REPORT can be pending at a time. This
+   restriction is enforced by HID core as some transport drivers do not support
+   multiple synchronous SET_REPORT requests.
+
+Other ctrl-channel requests are supported by USB-HID but are not available
+(or deprecated) in most other transport level specifications:
+
+ - GET/SET_IDLE: Only used by USB-HID and I2C-HID.
+ - GET/SET_PROTOCOL: Not used by HID core.
+ - RESET: Used by I2C-HID, not hooked up in HID core.
+ - SET_POWER: Used by I2C-HID, not hooked up in HID core.
+
+2) HID API
+==========
+
+2.1) Initialization
+-------------------
+
+Transport drivers normally use the following procedure to register a new device
+with HID core:
+
+	struct hid_device *hid;
+	int ret;
+
+	hid = hid_allocate_device();
+	if (IS_ERR(hid)) {
+		ret = PTR_ERR(hid);
+		goto err_<...>;
+	}
+
+	strlcpy(hid->name, <device-name-src>, 127);
+	strlcpy(hid->phys, <device-phys-src>, 63);
+	strlcpy(hid->uniq, <device-uniq-src>, 63);
+
+	hid->ll_driver = &custom_ll_driver;
+	hid->bus = <device-bus>;
+	hid->vendor = <device-vendor>;
+	hid->product = <device-product>;
+	hid->version = <device-version>;
+	hid->country = <device-country>;
+	hid->dev.parent = <pointer-to-parent-device>;
+	hid->driver_data = <transport-driver-data-field>;
+
+	ret = hid_add_device(hid);
+	if (ret)
+		goto err_<...>;
+
+Once hid_add_device() is entered, HID core might use the callbacks provided in
+"custom_ll_driver". Note that fields like "country" can be ignored by underlying
+transport-drivers if not supported.
+
+To unregister a device, use:
+
+	hid_destroy_device(hid);
+
+Once hid_destroy_device() returns, HID core will no longer make use of any
+driver callbacks.
+
+2.2) hid_ll_driver operations
+-----------------------------
+
+The available HID callbacks are:
+ - int (*start) (struct hid_device *hdev)
+   Called from HID device drivers once they want to use the device. Transport
+   drivers can choose to setup their device in this callback. However, normally
+   devices are already set up before transport drivers register them to HID core
+   so this is mostly only used by USB-HID.
+
+ - void (*stop) (struct hid_device *hdev)
+   Called from HID device drivers once they are done with a device. Transport
+   drivers can free any buffers and deinitialize the device. But note that
+   ->start() might be called again if another HID device driver is loaded on the
+   device.
+   Transport drivers are free to ignore it and deinitialize devices after they
+   destroyed them via hid_destroy_device().
+
+ - int (*open) (struct hid_device *hdev)
+   Called from HID device drivers once they are interested in data reports.
+   Usually, while user-space didn't open any input API/etc., device drivers are
+   not interested in device data and transport drivers can put devices asleep.
+   However, once ->open() is called, transport drivers must be ready for I/O.
+   ->open() calls are nested for each client that opens the HID device.
+
+ - void (*close) (struct hid_device *hdev)
+   Called from HID device drivers after ->open() was called but they are no
+   longer interested in device reports. (Usually if user-space closed any input
+   devices of the driver).
+   Transport drivers can put devices asleep and terminate any I/O of all
+   ->open() calls have been followed by a ->close() call. However, ->start() may
+   be called again if the device driver is interested in input reports again.
+
+ - int (*parse) (struct hid_device *hdev)
+   Called once during device setup after ->start() has been called. Transport
+   drivers must read the HID report-descriptor from the device and tell HID core
+   about it via hid_parse_report().
+
+ - int (*power) (struct hid_device *hdev, int level)
+   Called by HID core to give PM hints to transport drivers. Usually this is
+   analogical to the ->open() and ->close() hints and redundant.
+
+ - void (*request) (struct hid_device *hdev, struct hid_report *report,
+                    int reqtype)
+   Send an HID request on the ctrl channel. "report" contains the report that
+   should be sent and "reqtype" the request type. Request-type can be
+   HID_REQ_SET_REPORT or HID_REQ_GET_REPORT.
+   This callback is optional. If not provided, HID core will assemble a raw
+   report following the HID specs and send it via the ->raw_request() callback.
+   The transport driver is free to implement this asynchronously.
+
+ - int (*wait) (struct hid_device *hdev)
+   Used by HID core before calling ->request() again. A transport driver can use
+   it to wait for any pending requests to complete if only one request is
+   allowed at a time.
+
+ - int (*raw_request) (struct hid_device *hdev, unsigned char reportnum,
+                       __u8 *buf, size_t count, unsigned char rtype,
+                       int reqtype)
+   Same as ->request() but provides the report as raw buffer. This request shall
+   be synchronous. A transport driver must not use ->wait() to complete such
+   requests.
+
+ - int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len)
+   Send raw output report via intr channel. Used by some HID device drivers
+   which require high throughput for outgoing requests on the intr channel. This
+   must not cause SET_REPORT calls! This must be implemented as asynchronous
+   output report on the intr channel!
+
+ - int (*hidinput_input_event) (struct input_dev *idev, unsigned int type,
+                                unsigned int code, int value)
+   Obsolete callback used by logitech converters. It is called when userspace
+   writes input events to the input device (eg., EV_LED). A driver can use this
+   callback to convert it into an output report and send it to the device. If
+   this callback is not provided, HID core will use ->request() or
+   ->raw_request() respectively.
+
+ - int (*idle) (struct hid_device *hdev, int report, int idle, int reqtype)
+   Perform SET/GET_IDLE request. Only used by USB-HID, do not implement!
+
+2.3) Data Path
+--------------
+
+Transport drivers are responsible of reading data from I/O devices. They must
+handle any I/O-related state-tracking themselves. HID core does not implement
+protocol handshakes or other management commands which can be required by the
+given HID transport specification.
+
+Every raw data packet read from a device must be fed into HID core via
+hid_input_report(). You must specify the channel-type (intr or ctrl) and report
+type (input/output/feature). Under normal conditions, only input reports are
+provided via this API.
+
+Responses to GET_REPORT requests via ->request() must also be provided via this
+API. Responses to ->raw_request() are synchronous and must be intercepted by the
+transport driver and not passed to hid_input_report().
+Acknowledgements to SET_REPORT requests are not of interest to HID core.
+
+----------------------------------------------------
+Written 2013, David Herrmann <dh.herrmann@gmail.com>
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] HID: Add HID transport driver documentation
  2014-01-29 15:28 [PATCH] HID: Add HID transport driver documentation Frank Praznik
@ 2014-01-29 15:35 ` David Herrmann
  2014-01-31 23:18   ` Benjamin Tissoires
  0 siblings, 1 reply; 6+ messages in thread
From: David Herrmann @ 2014-01-29 15:35 UTC (permalink / raw)
  To: Frank Praznik, Benjamin Tissoires; +Cc: open list:HID CORE LAYER, Jiri Kosina

Hi

On Wed, Jan 29, 2014 at 4:28 PM, Frank Praznik <frank.praznik@oh.rr.com> wrote:
> Add David Herrmann's documentation for the new low-level HID transport driver
> functions.
>
> Signed-off-by: Frank Praznik <frank.praznik@oh.rr.com>

If you copy code, you really should keep the signed-off-by chain. A
signed-off-by in kernel context means that you either wrote the code
or have permission to copy it. See here:
http://developercertificate.org/ (which is a public copy of the
kernel's signed-off-by practice).
If you copy code unchanged, it's common practice to even keep the
"Author" field via "git commit --author", but that's optional.

Anyhow, patch is good, thanks for picking it up!

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>

Putting Benjamin on CC as he reviewed the patch last time and might
have some more comments (or his final reviewed-by).

Thanks!
David

> ---
>
>  Sorry, I forgot to include this in the original patch set.
>
>  Documentation/hid/hid-transport.txt | 324 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 324 insertions(+)
>  create mode 100644 Documentation/hid/hid-transport.txt
>
> diff --git a/Documentation/hid/hid-transport.txt b/Documentation/hid/hid-transport.txt
> new file mode 100644
> index 0000000..14b1c18
> --- /dev/null
> +++ b/Documentation/hid/hid-transport.txt
> @@ -0,0 +1,324 @@
> +                          HID I/O Transport Drivers
> +                         ===========================
> +
> +The HID subsystem is independent of the underlying transport driver. Initially,
> +only USB was supported, but other specifications adopted the HID design and
> +provided new transport drivers. The kernel includes at least support for USB,
> +Bluetooth, I2C and user-space I/O drivers.
> +
> +1) HID Bus
> +==========
> +
> +The HID subsystem is designed as a bus. Any I/O subsystem may provide HID
> +devices and register them with the HID bus. HID core then loads generic device
> +drivers on top of it. The transport drivers are responsible of raw data
> +transport and device setup/management. HID core is responsible of
> +report-parsing, report interpretation and the user-space API. Device specifics
> +and quirks are handled by all layers depending on the quirk.
> +
> + +-----------+  +-----------+            +-----------+  +-----------+
> + | Device #1 |  | Device #i |            | Device #j |  | Device #k |
> + +-----------+  +-----------+            +-----------+  +-----------+
> +          \\      //                              \\      //
> +        +------------+                          +------------+
> +        | I/O Driver |                          | I/O Driver |
> +        +------------+                          +------------+
> +              ||                                      ||
> +     +------------------+                    +------------------+
> +     | Transport Driver |                    | Transport Driver |
> +     +------------------+                    +------------------+
> +                       \___                ___/
> +                           \              /
> +                          +----------------+
> +                          |    HID Core    |
> +                          +----------------+
> +                           /  |        |  \
> +                          /   |        |   \
> +             ____________/    |        |    \_________________
> +            /                 |        |                      \
> +           /                  |        |                       \
> + +----------------+  +-----------+  +------------------+  +------------------+
> + | Generic Driver |  | MT Driver |  | Custom Driver #1 |  | Custom Driver #2 |
> + +----------------+  +-----------+  +------------------+  +------------------+
> +
> +Example Drivers:
> +  I/O: USB, I2C, Bluetooth-l2cap
> +  Transport: USB-HID, I2C-HID, BT-HIDP
> +
> +Everything below "HID Core" is simplified in this graph as it is only of
> +interest to HID device drivers. Transport drivers do not need to know the
> +specifics.
> +
> +1.1) Device Setup
> +-----------------
> +
> +I/O drivers normally provide hotplug detection or device enumeration APIs to the
> +transport drivers. Transport drivers use this to find any suitable HID device.
> +They allocate HID device objects and register them with HID core. Transport
> +drivers are not required to register themselves with HID core. HID core is never
> +aware of which transport drivers are available and is not interested in it. It
> +is only interested in devices.
> +
> +Transport drivers attach a constant "struct hid_ll_driver" object with each
> +device. Once a device is registered with HID core, the callbacks provided via
> +this struct are used by HID core to communicate with the device.
> +
> +Transport drivers are responsible of detecting device failures and unplugging.
> +HID core will operate a device as long as it is registered regardless of any
> +device failures. Once transport drivers detect unplug or failure events, they
> +must unregister the device from HID core and HID core will stop using the
> +provided callbacks.
> +
> +1.2) Transport Driver Requirements
> +----------------------------------
> +
> +The terms "asynchronous" and "synchronous" in this document describe the
> +transmission behavior regarding acknowledgements. An asynchronous channel must
> +not perform any synchronous operations like waiting for acknowledgements or
> +verifications. Generally, HID calls operating on asynchronous channels must be
> +running in atomic-context just fine.
> +On the other hand, synchronous channels can be implemented by the transport
> +driver in whatever way they like. They might just be the same as asynchronous
> +channels, but they can also provide acknowledgement reports, automatic
> +retransmission on failure, etc. in a blocking manner. If such functionality is
> +required on asynchronous channels, a transport-driver must implement that via
> +its own worker threads.
> +
> +HID core requires transport drivers to follow a given design. A Transport
> +driver must provide two bi-directional I/O channels to each HID device. These
> +channels must not necessarily be bi-directional in the hardware itself. A
> +transport driver might just provide 4 uni-directional channels. Or it might
> +multiplex all four on a single physical channel. However, in this document we
> +will describe them as two bi-directional channels as they have several
> +properties in common.
> +
> + - Interrupt Channel (intr): The intr channel is used for asynchronous data
> +   reports. No management commands or data acknowledgements are sent on this
> +   channel. Any unrequested incoming or outgoing data report must be sent on
> +   this channel and is never acknowledged by the remote side. Devices usually
> +   send their input events on this channel. Outgoing events are normally
> +   not send via intr, except if high throughput is required.
> + - Control Channel (ctrl): The ctrl channel is used for synchronous requests and
> +   device management. Unrequested data input events must not be sent on this
> +   channel and are normally ignored. Instead, devices only send management
> +   events or answers to host requests on this channel.
> +   The control-channel is used for direct blocking queries to the device
> +   independent of any events on the intr-channel.
> +   Outgoing reports are usually sent on the ctrl channel via synchronous
> +   SET_REPORT requests.
> +
> +Communication between devices and HID core is mostly done via HID reports. A
> +report can be of one of three types:
> +
> + - INPUT Report: Input reports provide data from device to host. This
> +   data may include button events, axis events, battery status or more. This
> +   data is generated by the device and sent to the host with or without
> +   requiring explicit requests. Devices can choose to send data continuously or
> +   only on change.
> + - OUTPUT Report: Output reports change device states. They are sent from host
> +   to device and may include LED requests, rumble requests or more. Output
> +   reports are never sent from device to host, but a host can retrieve their
> +   current state.
> +   Hosts may choose to send output reports either continuously or only on
> +   change.
> + - FEATURE Report: Feature reports are used for specific static device features
> +   and never reported spontaneously. A host can read and/or write them to access
> +   data like battery-state or device-settings.
> +   Feature reports are never sent without requests. A host must explicitly set
> +   or retrieve a feature report. This also means, feature reports are never sent
> +   on the intr channel as this channel is asynchronous.
> +
> +INPUT and OUTPUT reports can be sent as pure data reports on the intr channel.
> +For INPUT reports this is the usual operational mode. But for OUTPUT reports,
> +this is rarely done as OUTPUT reports are normally quite scarce. But devices are
> +free to make excessive use of asynchronous OUTPUT reports (for instance, custom
> +HID audio speakers make great use of it).
> +
> +Plain reports must not be sent on the ctrl channel, though. Instead, the ctrl
> +channel provides synchronous GET/SET_REPORT requests. Plain reports are only
> +allowed on the intr channel and are the only means of data there.
> +
> + - GET_REPORT: A GET_REPORT request has a report ID as payload and is sent
> +   from host to device. The device must answer with a data report for the
> +   requested report ID on the ctrl channel as a synchronous acknowledgement.
> +   Only one GET_REPORT request can be pending for each device. This restriction
> +   is enforced by HID core as several transport drivers don't allow multiple
> +   simultaneous GET_REPORT requests.
> +   Note that data reports which are sent as answer to a GET_REPORT request are
> +   not handled as generic device events. That is, if a device does not operate
> +   in continuous data reporting mode, an answer to GET_REPORT does not replace
> +   the raw data report on the intr channel on state change.
> +   GET_REPORT is only used by custom HID device drivers to query device state.
> +   Normally, HID core caches any device state so this request is not necessary
> +   on devices that follow the HID specs except during device initialization to
> +   retrieve the current state.
> +   GET_REPORT requests can be sent for any of the 3 report types and shall
> +   return the current report state of the device. However, OUTPUT reports as
> +   payload may be blocked by the underlying transport driver if the
> +   specification does not allow them.
> + - SET_REPORT: A SET_REPORT request has a report ID plus data as payload. It is
> +   sent from host to device and a device must update it's current report state
> +   according to the given data. Any of the 3 report types can be used. However,
> +   INPUT reports as payload might be blocked by the underlying transport driver
> +   if the specification does not allow them.
> +   A device must answer with a synchronous acknowledgement. However, HID core
> +   does not require transport drivers to forward this acknowledgement to HID
> +   core.
> +   Same as for GET_REPORT, only one SET_REPORT can be pending at a time. This
> +   restriction is enforced by HID core as some transport drivers do not support
> +   multiple synchronous SET_REPORT requests.
> +
> +Other ctrl-channel requests are supported by USB-HID but are not available
> +(or deprecated) in most other transport level specifications:
> +
> + - GET/SET_IDLE: Only used by USB-HID and I2C-HID.
> + - GET/SET_PROTOCOL: Not used by HID core.
> + - RESET: Used by I2C-HID, not hooked up in HID core.
> + - SET_POWER: Used by I2C-HID, not hooked up in HID core.
> +
> +2) HID API
> +==========
> +
> +2.1) Initialization
> +-------------------
> +
> +Transport drivers normally use the following procedure to register a new device
> +with HID core:
> +
> +       struct hid_device *hid;
> +       int ret;
> +
> +       hid = hid_allocate_device();
> +       if (IS_ERR(hid)) {
> +               ret = PTR_ERR(hid);
> +               goto err_<...>;
> +       }
> +
> +       strlcpy(hid->name, <device-name-src>, 127);
> +       strlcpy(hid->phys, <device-phys-src>, 63);
> +       strlcpy(hid->uniq, <device-uniq-src>, 63);
> +
> +       hid->ll_driver = &custom_ll_driver;
> +       hid->bus = <device-bus>;
> +       hid->vendor = <device-vendor>;
> +       hid->product = <device-product>;
> +       hid->version = <device-version>;
> +       hid->country = <device-country>;
> +       hid->dev.parent = <pointer-to-parent-device>;
> +       hid->driver_data = <transport-driver-data-field>;
> +
> +       ret = hid_add_device(hid);
> +       if (ret)
> +               goto err_<...>;
> +
> +Once hid_add_device() is entered, HID core might use the callbacks provided in
> +"custom_ll_driver". Note that fields like "country" can be ignored by underlying
> +transport-drivers if not supported.
> +
> +To unregister a device, use:
> +
> +       hid_destroy_device(hid);
> +
> +Once hid_destroy_device() returns, HID core will no longer make use of any
> +driver callbacks.
> +
> +2.2) hid_ll_driver operations
> +-----------------------------
> +
> +The available HID callbacks are:
> + - int (*start) (struct hid_device *hdev)
> +   Called from HID device drivers once they want to use the device. Transport
> +   drivers can choose to setup their device in this callback. However, normally
> +   devices are already set up before transport drivers register them to HID core
> +   so this is mostly only used by USB-HID.
> +
> + - void (*stop) (struct hid_device *hdev)
> +   Called from HID device drivers once they are done with a device. Transport
> +   drivers can free any buffers and deinitialize the device. But note that
> +   ->start() might be called again if another HID device driver is loaded on the
> +   device.
> +   Transport drivers are free to ignore it and deinitialize devices after they
> +   destroyed them via hid_destroy_device().
> +
> + - int (*open) (struct hid_device *hdev)
> +   Called from HID device drivers once they are interested in data reports.
> +   Usually, while user-space didn't open any input API/etc., device drivers are
> +   not interested in device data and transport drivers can put devices asleep.
> +   However, once ->open() is called, transport drivers must be ready for I/O.
> +   ->open() calls are nested for each client that opens the HID device.
> +
> + - void (*close) (struct hid_device *hdev)
> +   Called from HID device drivers after ->open() was called but they are no
> +   longer interested in device reports. (Usually if user-space closed any input
> +   devices of the driver).
> +   Transport drivers can put devices asleep and terminate any I/O of all
> +   ->open() calls have been followed by a ->close() call. However, ->start() may
> +   be called again if the device driver is interested in input reports again.
> +
> + - int (*parse) (struct hid_device *hdev)
> +   Called once during device setup after ->start() has been called. Transport
> +   drivers must read the HID report-descriptor from the device and tell HID core
> +   about it via hid_parse_report().
> +
> + - int (*power) (struct hid_device *hdev, int level)
> +   Called by HID core to give PM hints to transport drivers. Usually this is
> +   analogical to the ->open() and ->close() hints and redundant.
> +
> + - void (*request) (struct hid_device *hdev, struct hid_report *report,
> +                    int reqtype)
> +   Send an HID request on the ctrl channel. "report" contains the report that
> +   should be sent and "reqtype" the request type. Request-type can be
> +   HID_REQ_SET_REPORT or HID_REQ_GET_REPORT.
> +   This callback is optional. If not provided, HID core will assemble a raw
> +   report following the HID specs and send it via the ->raw_request() callback.
> +   The transport driver is free to implement this asynchronously.
> +
> + - int (*wait) (struct hid_device *hdev)
> +   Used by HID core before calling ->request() again. A transport driver can use
> +   it to wait for any pending requests to complete if only one request is
> +   allowed at a time.
> +
> + - int (*raw_request) (struct hid_device *hdev, unsigned char reportnum,
> +                       __u8 *buf, size_t count, unsigned char rtype,
> +                       int reqtype)
> +   Same as ->request() but provides the report as raw buffer. This request shall
> +   be synchronous. A transport driver must not use ->wait() to complete such
> +   requests.
> +
> + - int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len)
> +   Send raw output report via intr channel. Used by some HID device drivers
> +   which require high throughput for outgoing requests on the intr channel. This
> +   must not cause SET_REPORT calls! This must be implemented as asynchronous
> +   output report on the intr channel!
> +
> + - int (*hidinput_input_event) (struct input_dev *idev, unsigned int type,
> +                                unsigned int code, int value)
> +   Obsolete callback used by logitech converters. It is called when userspace
> +   writes input events to the input device (eg., EV_LED). A driver can use this
> +   callback to convert it into an output report and send it to the device. If
> +   this callback is not provided, HID core will use ->request() or
> +   ->raw_request() respectively.
> +
> + - int (*idle) (struct hid_device *hdev, int report, int idle, int reqtype)
> +   Perform SET/GET_IDLE request. Only used by USB-HID, do not implement!
> +
> +2.3) Data Path
> +--------------
> +
> +Transport drivers are responsible of reading data from I/O devices. They must
> +handle any I/O-related state-tracking themselves. HID core does not implement
> +protocol handshakes or other management commands which can be required by the
> +given HID transport specification.
> +
> +Every raw data packet read from a device must be fed into HID core via
> +hid_input_report(). You must specify the channel-type (intr or ctrl) and report
> +type (input/output/feature). Under normal conditions, only input reports are
> +provided via this API.
> +
> +Responses to GET_REPORT requests via ->request() must also be provided via this
> +API. Responses to ->raw_request() are synchronous and must be intercepted by the
> +transport driver and not passed to hid_input_report().
> +Acknowledgements to SET_REPORT requests are not of interest to HID core.
> +
> +----------------------------------------------------
> +Written 2013, David Herrmann <dh.herrmann@gmail.com>
> --
> 1.8.3.2
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] HID: Add HID transport driver documentation
  2014-01-29 15:35 ` David Herrmann
@ 2014-01-31 23:18   ` Benjamin Tissoires
  2014-02-03 16:50     ` David Herrmann
  0 siblings, 1 reply; 6+ messages in thread
From: Benjamin Tissoires @ 2014-01-31 23:18 UTC (permalink / raw)
  To: David Herrmann; +Cc: Frank Praznik, open list:HID CORE LAYER, Jiri Kosina

On Wed, Jan 29, 2014 at 10:35 AM, David Herrmann <dh.herrmann@gmail.com> wrote:
> Hi
>
> On Wed, Jan 29, 2014 at 4:28 PM, Frank Praznik <frank.praznik@oh.rr.com> wrote:
>> Add David Herrmann's documentation for the new low-level HID transport driver
>> functions.
>>
>> Signed-off-by: Frank Praznik <frank.praznik@oh.rr.com>
>
> If you copy code, you really should keep the signed-off-by chain. A
> signed-off-by in kernel context means that you either wrote the code
> or have permission to copy it. See here:
> http://developercertificate.org/ (which is a public copy of the
> kernel's signed-off-by practice).
> If you copy code unchanged, it's common practice to even keep the
> "Author" field via "git commit --author", but that's optional.
>
> Anyhow, patch is good, thanks for picking it up!
>
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
>
> Putting Benjamin on CC as he reviewed the patch last time and might
> have some more comments (or his final reviewed-by).
>

Thanks David. I am globally happy with it, but I have a little remark:

> Thanks!
> David
>
>> ---
>>
>>  Sorry, I forgot to include this in the original patch set.
>>
>>  Documentation/hid/hid-transport.txt | 324 ++++++++++++++++++++++++++++++++++++
>>  1 file changed, 324 insertions(+)
>>  create mode 100644 Documentation/hid/hid-transport.txt
>>
>> diff --git a/Documentation/hid/hid-transport.txt b/Documentation/hid/hid-transport.txt
>> new file mode 100644
>> index 0000000..14b1c18
>> --- /dev/null
>> +++ b/Documentation/hid/hid-transport.txt
>> @@ -0,0 +1,324 @@
>> +                          HID I/O Transport Drivers
>> +                         ===========================
>> +
>> +The HID subsystem is independent of the underlying transport driver. Initially,
>> +only USB was supported, but other specifications adopted the HID design and
>> +provided new transport drivers. The kernel includes at least support for USB,
>> +Bluetooth, I2C and user-space I/O drivers.
>> +
>> +1) HID Bus
>> +==========
>> +
>> +The HID subsystem is designed as a bus. Any I/O subsystem may provide HID
>> +devices and register them with the HID bus. HID core then loads generic device
>> +drivers on top of it. The transport drivers are responsible of raw data
>> +transport and device setup/management. HID core is responsible of
>> +report-parsing, report interpretation and the user-space API. Device specifics
>> +and quirks are handled by all layers depending on the quirk.
>> +
>> + +-----------+  +-----------+            +-----------+  +-----------+
>> + | Device #1 |  | Device #i |            | Device #j |  | Device #k |
>> + +-----------+  +-----------+            +-----------+  +-----------+
>> +          \\      //                              \\      //
>> +        +------------+                          +------------+
>> +        | I/O Driver |                          | I/O Driver |
>> +        +------------+                          +------------+
>> +              ||                                      ||
>> +     +------------------+                    +------------------+
>> +     | Transport Driver |                    | Transport Driver |
>> +     +------------------+                    +------------------+
>> +                       \___                ___/
>> +                           \              /
>> +                          +----------------+
>> +                          |    HID Core    |
>> +                          +----------------+
>> +                           /  |        |  \
>> +                          /   |        |   \
>> +             ____________/    |        |    \_________________
>> +            /                 |        |                      \
>> +           /                  |        |                       \
>> + +----------------+  +-----------+  +------------------+  +------------------+
>> + | Generic Driver |  | MT Driver |  | Custom Driver #1 |  | Custom Driver #2 |
>> + +----------------+  +-----------+  +------------------+  +------------------+
>> +
>> +Example Drivers:
>> +  I/O: USB, I2C, Bluetooth-l2cap
>> +  Transport: USB-HID, I2C-HID, BT-HIDP
>> +
>> +Everything below "HID Core" is simplified in this graph as it is only of
>> +interest to HID device drivers. Transport drivers do not need to know the
>> +specifics.
>> +
>> +1.1) Device Setup
>> +-----------------
>> +
>> +I/O drivers normally provide hotplug detection or device enumeration APIs to the
>> +transport drivers. Transport drivers use this to find any suitable HID device.
>> +They allocate HID device objects and register them with HID core. Transport
>> +drivers are not required to register themselves with HID core. HID core is never
>> +aware of which transport drivers are available and is not interested in it. It
>> +is only interested in devices.
>> +
>> +Transport drivers attach a constant "struct hid_ll_driver" object with each
>> +device. Once a device is registered with HID core, the callbacks provided via
>> +this struct are used by HID core to communicate with the device.
>> +
>> +Transport drivers are responsible of detecting device failures and unplugging.
>> +HID core will operate a device as long as it is registered regardless of any
>> +device failures. Once transport drivers detect unplug or failure events, they
>> +must unregister the device from HID core and HID core will stop using the
>> +provided callbacks.
>> +
>> +1.2) Transport Driver Requirements
>> +----------------------------------
>> +
>> +The terms "asynchronous" and "synchronous" in this document describe the
>> +transmission behavior regarding acknowledgements. An asynchronous channel must
>> +not perform any synchronous operations like waiting for acknowledgements or
>> +verifications. Generally, HID calls operating on asynchronous channels must be
>> +running in atomic-context just fine.
>> +On the other hand, synchronous channels can be implemented by the transport
>> +driver in whatever way they like. They might just be the same as asynchronous
>> +channels, but they can also provide acknowledgement reports, automatic
>> +retransmission on failure, etc. in a blocking manner. If such functionality is
>> +required on asynchronous channels, a transport-driver must implement that via
>> +its own worker threads.
>> +
>> +HID core requires transport drivers to follow a given design. A Transport
>> +driver must provide two bi-directional I/O channels to each HID device. These
>> +channels must not necessarily be bi-directional in the hardware itself. A
>> +transport driver might just provide 4 uni-directional channels. Or it might
>> +multiplex all four on a single physical channel. However, in this document we
>> +will describe them as two bi-directional channels as they have several
>> +properties in common.
>> +
>> + - Interrupt Channel (intr): The intr channel is used for asynchronous data
>> +   reports. No management commands or data acknowledgements are sent on this
>> +   channel. Any unrequested incoming or outgoing data report must be sent on
>> +   this channel and is never acknowledged by the remote side. Devices usually
>> +   send their input events on this channel. Outgoing events are normally
>> +   not send via intr, except if high throughput is required.
>> + - Control Channel (ctrl): The ctrl channel is used for synchronous requests and
>> +   device management. Unrequested data input events must not be sent on this
>> +   channel and are normally ignored. Instead, devices only send management
>> +   events or answers to host requests on this channel.
>> +   The control-channel is used for direct blocking queries to the device
>> +   independent of any events on the intr-channel.
>> +   Outgoing reports are usually sent on the ctrl channel via synchronous
>> +   SET_REPORT requests.
>> +
>> +Communication between devices and HID core is mostly done via HID reports. A
>> +report can be of one of three types:
>> +
>> + - INPUT Report: Input reports provide data from device to host. This
>> +   data may include button events, axis events, battery status or more. This
>> +   data is generated by the device and sent to the host with or without
>> +   requiring explicit requests. Devices can choose to send data continuously or
>> +   only on change.
>> + - OUTPUT Report: Output reports change device states. They are sent from host
>> +   to device and may include LED requests, rumble requests or more. Output
>> +   reports are never sent from device to host, but a host can retrieve their
>> +   current state.
>> +   Hosts may choose to send output reports either continuously or only on
>> +   change.
>> + - FEATURE Report: Feature reports are used for specific static device features
>> +   and never reported spontaneously. A host can read and/or write them to access
>> +   data like battery-state or device-settings.
>> +   Feature reports are never sent without requests. A host must explicitly set
>> +   or retrieve a feature report. This also means, feature reports are never sent
>> +   on the intr channel as this channel is asynchronous.
>> +
>> +INPUT and OUTPUT reports can be sent as pure data reports on the intr channel.
>> +For INPUT reports this is the usual operational mode. But for OUTPUT reports,
>> +this is rarely done as OUTPUT reports are normally quite scarce. But devices are
>> +free to make excessive use of asynchronous OUTPUT reports (for instance, custom
>> +HID audio speakers make great use of it).
>> +
>> +Plain reports must not be sent on the ctrl channel, though. Instead, the ctrl
>> +channel provides synchronous GET/SET_REPORT requests. Plain reports are only
>> +allowed on the intr channel and are the only means of data there.
>> +
>> + - GET_REPORT: A GET_REPORT request has a report ID as payload and is sent
>> +   from host to device. The device must answer with a data report for the
>> +   requested report ID on the ctrl channel as a synchronous acknowledgement.
>> +   Only one GET_REPORT request can be pending for each device. This restriction
>> +   is enforced by HID core as several transport drivers don't allow multiple
>> +   simultaneous GET_REPORT requests.
>> +   Note that data reports which are sent as answer to a GET_REPORT request are
>> +   not handled as generic device events. That is, if a device does not operate
>> +   in continuous data reporting mode, an answer to GET_REPORT does not replace
>> +   the raw data report on the intr channel on state change.
>> +   GET_REPORT is only used by custom HID device drivers to query device state.
>> +   Normally, HID core caches any device state so this request is not necessary
>> +   on devices that follow the HID specs except during device initialization to
>> +   retrieve the current state.
>> +   GET_REPORT requests can be sent for any of the 3 report types and shall
>> +   return the current report state of the device. However, OUTPUT reports as
>> +   payload may be blocked by the underlying transport driver if the
>> +   specification does not allow them.
>> + - SET_REPORT: A SET_REPORT request has a report ID plus data as payload. It is
>> +   sent from host to device and a device must update it's current report state
>> +   according to the given data. Any of the 3 report types can be used. However,
>> +   INPUT reports as payload might be blocked by the underlying transport driver
>> +   if the specification does not allow them.
>> +   A device must answer with a synchronous acknowledgement. However, HID core
>> +   does not require transport drivers to forward this acknowledgement to HID
>> +   core.
>> +   Same as for GET_REPORT, only one SET_REPORT can be pending at a time. This
>> +   restriction is enforced by HID core as some transport drivers do not support
>> +   multiple synchronous SET_REPORT requests.
>> +
>> +Other ctrl-channel requests are supported by USB-HID but are not available
>> +(or deprecated) in most other transport level specifications:
>> +
>> + - GET/SET_IDLE: Only used by USB-HID and I2C-HID.
>> + - GET/SET_PROTOCOL: Not used by HID core.
>> + - RESET: Used by I2C-HID, not hooked up in HID core.
>> + - SET_POWER: Used by I2C-HID, not hooked up in HID core.
>> +
>> +2) HID API
>> +==========
>> +
>> +2.1) Initialization
>> +-------------------
>> +
>> +Transport drivers normally use the following procedure to register a new device
>> +with HID core:
>> +
>> +       struct hid_device *hid;
>> +       int ret;
>> +
>> +       hid = hid_allocate_device();
>> +       if (IS_ERR(hid)) {
>> +               ret = PTR_ERR(hid);
>> +               goto err_<...>;
>> +       }
>> +
>> +       strlcpy(hid->name, <device-name-src>, 127);
>> +       strlcpy(hid->phys, <device-phys-src>, 63);
>> +       strlcpy(hid->uniq, <device-uniq-src>, 63);
>> +
>> +       hid->ll_driver = &custom_ll_driver;
>> +       hid->bus = <device-bus>;
>> +       hid->vendor = <device-vendor>;
>> +       hid->product = <device-product>;
>> +       hid->version = <device-version>;
>> +       hid->country = <device-country>;
>> +       hid->dev.parent = <pointer-to-parent-device>;
>> +       hid->driver_data = <transport-driver-data-field>;
>> +
>> +       ret = hid_add_device(hid);
>> +       if (ret)
>> +               goto err_<...>;
>> +
>> +Once hid_add_device() is entered, HID core might use the callbacks provided in
>> +"custom_ll_driver". Note that fields like "country" can be ignored by underlying
>> +transport-drivers if not supported.
>> +
>> +To unregister a device, use:
>> +
>> +       hid_destroy_device(hid);
>> +
>> +Once hid_destroy_device() returns, HID core will no longer make use of any
>> +driver callbacks.
>> +
>> +2.2) hid_ll_driver operations
>> +-----------------------------
>> +
>> +The available HID callbacks are:
>> + - int (*start) (struct hid_device *hdev)
>> +   Called from HID device drivers once they want to use the device. Transport
>> +   drivers can choose to setup their device in this callback. However, normally
>> +   devices are already set up before transport drivers register them to HID core
>> +   so this is mostly only used by USB-HID.
>> +
>> + - void (*stop) (struct hid_device *hdev)
>> +   Called from HID device drivers once they are done with a device. Transport
>> +   drivers can free any buffers and deinitialize the device. But note that
>> +   ->start() might be called again if another HID device driver is loaded on the
>> +   device.
>> +   Transport drivers are free to ignore it and deinitialize devices after they
>> +   destroyed them via hid_destroy_device().
>> +
>> + - int (*open) (struct hid_device *hdev)
>> +   Called from HID device drivers once they are interested in data reports.
>> +   Usually, while user-space didn't open any input API/etc., device drivers are
>> +   not interested in device data and transport drivers can put devices asleep.
>> +   However, once ->open() is called, transport drivers must be ready for I/O.
>> +   ->open() calls are nested for each client that opens the HID device.
>> +
>> + - void (*close) (struct hid_device *hdev)
>> +   Called from HID device drivers after ->open() was called but they are no
>> +   longer interested in device reports. (Usually if user-space closed any input
>> +   devices of the driver).
>> +   Transport drivers can put devices asleep and terminate any I/O of all
>> +   ->open() calls have been followed by a ->close() call. However, ->start() may
>> +   be called again if the device driver is interested in input reports again.
>> +
>> + - int (*parse) (struct hid_device *hdev)
>> +   Called once during device setup after ->start() has been called. Transport
>> +   drivers must read the HID report-descriptor from the device and tell HID core
>> +   about it via hid_parse_report().
>> +
>> + - int (*power) (struct hid_device *hdev, int level)
>> +   Called by HID core to give PM hints to transport drivers. Usually this is
>> +   analogical to the ->open() and ->close() hints and redundant.
>> +
>> + - void (*request) (struct hid_device *hdev, struct hid_report *report,
>> +                    int reqtype)
>> +   Send an HID request on the ctrl channel. "report" contains the report that
>> +   should be sent and "reqtype" the request type. Request-type can be
>> +   HID_REQ_SET_REPORT or HID_REQ_GET_REPORT.
>> +   This callback is optional. If not provided, HID core will assemble a raw
>> +   report following the HID specs and send it via the ->raw_request() callback.

This is not true currently. Aren't we missing a commit in the original series?
But I would love seeing this come true.

Cheers,
Benjamin

>> +   The transport driver is free to implement this asynchronously.
>> +
>> + - int (*wait) (struct hid_device *hdev)
>> +   Used by HID core before calling ->request() again. A transport driver can use
>> +   it to wait for any pending requests to complete if only one request is
>> +   allowed at a time.
>> +
>> + - int (*raw_request) (struct hid_device *hdev, unsigned char reportnum,
>> +                       __u8 *buf, size_t count, unsigned char rtype,
>> +                       int reqtype)
>> +   Same as ->request() but provides the report as raw buffer. This request shall
>> +   be synchronous. A transport driver must not use ->wait() to complete such
>> +   requests.
>> +
>> + - int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len)
>> +   Send raw output report via intr channel. Used by some HID device drivers
>> +   which require high throughput for outgoing requests on the intr channel. This
>> +   must not cause SET_REPORT calls! This must be implemented as asynchronous
>> +   output report on the intr channel!
>> +
>> + - int (*hidinput_input_event) (struct input_dev *idev, unsigned int type,
>> +                                unsigned int code, int value)
>> +   Obsolete callback used by logitech converters. It is called when userspace
>> +   writes input events to the input device (eg., EV_LED). A driver can use this
>> +   callback to convert it into an output report and send it to the device. If
>> +   this callback is not provided, HID core will use ->request() or
>> +   ->raw_request() respectively.
>> +
>> + - int (*idle) (struct hid_device *hdev, int report, int idle, int reqtype)
>> +   Perform SET/GET_IDLE request. Only used by USB-HID, do not implement!
>> +
>> +2.3) Data Path
>> +--------------
>> +
>> +Transport drivers are responsible of reading data from I/O devices. They must
>> +handle any I/O-related state-tracking themselves. HID core does not implement
>> +protocol handshakes or other management commands which can be required by the
>> +given HID transport specification.
>> +
>> +Every raw data packet read from a device must be fed into HID core via
>> +hid_input_report(). You must specify the channel-type (intr or ctrl) and report
>> +type (input/output/feature). Under normal conditions, only input reports are
>> +provided via this API.
>> +
>> +Responses to GET_REPORT requests via ->request() must also be provided via this
>> +API. Responses to ->raw_request() are synchronous and must be intercepted by the
>> +transport driver and not passed to hid_input_report().
>> +Acknowledgements to SET_REPORT requests are not of interest to HID core.
>> +
>> +----------------------------------------------------
>> +Written 2013, David Herrmann <dh.herrmann@gmail.com>
>> --
>> 1.8.3.2
>>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] HID: Add HID transport driver documentation
  2014-01-31 23:18   ` Benjamin Tissoires
@ 2014-02-03 16:50     ` David Herrmann
  2014-02-03 16:52       ` Benjamin Tissoires
  0 siblings, 1 reply; 6+ messages in thread
From: David Herrmann @ 2014-02-03 16:50 UTC (permalink / raw)
  To: Benjamin Tissoires; +Cc: Frank Praznik, open list:HID CORE LAYER, Jiri Kosina

Hi

On Sat, Feb 1, 2014 at 12:18 AM, Benjamin Tissoires
<benjamin.tissoires@gmail.com> wrote:
> On Wed, Jan 29, 2014 at 10:35 AM, David Herrmann <dh.herrmann@gmail.com> wrote:
>> Hi
>>
>> On Wed, Jan 29, 2014 at 4:28 PM, Frank Praznik <frank.praznik@oh.rr.com> wrote:
>>> Add David Herrmann's documentation for the new low-level HID transport driver
>>> functions.
>>>
>>> Signed-off-by: Frank Praznik <frank.praznik@oh.rr.com>
>>
>> If you copy code, you really should keep the signed-off-by chain. A
>> signed-off-by in kernel context means that you either wrote the code
>> or have permission to copy it. See here:
>> http://developercertificate.org/ (which is a public copy of the
>> kernel's signed-off-by practice).
>> If you copy code unchanged, it's common practice to even keep the
>> "Author" field via "git commit --author", but that's optional.
>>
>> Anyhow, patch is good, thanks for picking it up!
>>
>> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
>>
>> Putting Benjamin on CC as he reviewed the patch last time and might
>> have some more comments (or his final reviewed-by).
>>
>
> Thanks David. I am globally happy with it, but I have a little remark:
>
>> Thanks!
>> David
>>
>>> ---
>>>
>>>  Sorry, I forgot to include this in the original patch set.
>>>
>>>  Documentation/hid/hid-transport.txt | 324 ++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 324 insertions(+)
>>>  create mode 100644 Documentation/hid/hid-transport.txt
>>>
>>> diff --git a/Documentation/hid/hid-transport.txt b/Documentation/hid/hid-transport.txt
>>> new file mode 100644
>>> index 0000000..14b1c18
>>> --- /dev/null
>>> +++ b/Documentation/hid/hid-transport.txt
>>> @@ -0,0 +1,324 @@
>>> +                          HID I/O Transport Drivers
>>> +                         ===========================
>>> +
>>> +The HID subsystem is independent of the underlying transport driver. Initially,
>>> +only USB was supported, but other specifications adopted the HID design and
>>> +provided new transport drivers. The kernel includes at least support for USB,
>>> +Bluetooth, I2C and user-space I/O drivers.
>>> +
>>> +1) HID Bus
>>> +==========
>>> +
>>> +The HID subsystem is designed as a bus. Any I/O subsystem may provide HID
>>> +devices and register them with the HID bus. HID core then loads generic device
>>> +drivers on top of it. The transport drivers are responsible of raw data
>>> +transport and device setup/management. HID core is responsible of
>>> +report-parsing, report interpretation and the user-space API. Device specifics
>>> +and quirks are handled by all layers depending on the quirk.
>>> +
>>> + +-----------+  +-----------+            +-----------+  +-----------+
>>> + | Device #1 |  | Device #i |            | Device #j |  | Device #k |
>>> + +-----------+  +-----------+            +-----------+  +-----------+
>>> +          \\      //                              \\      //
>>> +        +------------+                          +------------+
>>> +        | I/O Driver |                          | I/O Driver |
>>> +        +------------+                          +------------+
>>> +              ||                                      ||
>>> +     +------------------+                    +------------------+
>>> +     | Transport Driver |                    | Transport Driver |
>>> +     +------------------+                    +------------------+
>>> +                       \___                ___/
>>> +                           \              /
>>> +                          +----------------+
>>> +                          |    HID Core    |
>>> +                          +----------------+
>>> +                           /  |        |  \
>>> +                          /   |        |   \
>>> +             ____________/    |        |    \_________________
>>> +            /                 |        |                      \
>>> +           /                  |        |                       \
>>> + +----------------+  +-----------+  +------------------+  +------------------+
>>> + | Generic Driver |  | MT Driver |  | Custom Driver #1 |  | Custom Driver #2 |
>>> + +----------------+  +-----------+  +------------------+  +------------------+
>>> +
>>> +Example Drivers:
>>> +  I/O: USB, I2C, Bluetooth-l2cap
>>> +  Transport: USB-HID, I2C-HID, BT-HIDP
>>> +
>>> +Everything below "HID Core" is simplified in this graph as it is only of
>>> +interest to HID device drivers. Transport drivers do not need to know the
>>> +specifics.
>>> +
>>> +1.1) Device Setup
>>> +-----------------
>>> +
>>> +I/O drivers normally provide hotplug detection or device enumeration APIs to the
>>> +transport drivers. Transport drivers use this to find any suitable HID device.
>>> +They allocate HID device objects and register them with HID core. Transport
>>> +drivers are not required to register themselves with HID core. HID core is never
>>> +aware of which transport drivers are available and is not interested in it. It
>>> +is only interested in devices.
>>> +
>>> +Transport drivers attach a constant "struct hid_ll_driver" object with each
>>> +device. Once a device is registered with HID core, the callbacks provided via
>>> +this struct are used by HID core to communicate with the device.
>>> +
>>> +Transport drivers are responsible of detecting device failures and unplugging.
>>> +HID core will operate a device as long as it is registered regardless of any
>>> +device failures. Once transport drivers detect unplug or failure events, they
>>> +must unregister the device from HID core and HID core will stop using the
>>> +provided callbacks.
>>> +
>>> +1.2) Transport Driver Requirements
>>> +----------------------------------
>>> +
>>> +The terms "asynchronous" and "synchronous" in this document describe the
>>> +transmission behavior regarding acknowledgements. An asynchronous channel must
>>> +not perform any synchronous operations like waiting for acknowledgements or
>>> +verifications. Generally, HID calls operating on asynchronous channels must be
>>> +running in atomic-context just fine.
>>> +On the other hand, synchronous channels can be implemented by the transport
>>> +driver in whatever way they like. They might just be the same as asynchronous
>>> +channels, but they can also provide acknowledgement reports, automatic
>>> +retransmission on failure, etc. in a blocking manner. If such functionality is
>>> +required on asynchronous channels, a transport-driver must implement that via
>>> +its own worker threads.
>>> +
>>> +HID core requires transport drivers to follow a given design. A Transport
>>> +driver must provide two bi-directional I/O channels to each HID device. These
>>> +channels must not necessarily be bi-directional in the hardware itself. A
>>> +transport driver might just provide 4 uni-directional channels. Or it might
>>> +multiplex all four on a single physical channel. However, in this document we
>>> +will describe them as two bi-directional channels as they have several
>>> +properties in common.
>>> +
>>> + - Interrupt Channel (intr): The intr channel is used for asynchronous data
>>> +   reports. No management commands or data acknowledgements are sent on this
>>> +   channel. Any unrequested incoming or outgoing data report must be sent on
>>> +   this channel and is never acknowledged by the remote side. Devices usually
>>> +   send their input events on this channel. Outgoing events are normally
>>> +   not send via intr, except if high throughput is required.
>>> + - Control Channel (ctrl): The ctrl channel is used for synchronous requests and
>>> +   device management. Unrequested data input events must not be sent on this
>>> +   channel and are normally ignored. Instead, devices only send management
>>> +   events or answers to host requests on this channel.
>>> +   The control-channel is used for direct blocking queries to the device
>>> +   independent of any events on the intr-channel.
>>> +   Outgoing reports are usually sent on the ctrl channel via synchronous
>>> +   SET_REPORT requests.
>>> +
>>> +Communication between devices and HID core is mostly done via HID reports. A
>>> +report can be of one of three types:
>>> +
>>> + - INPUT Report: Input reports provide data from device to host. This
>>> +   data may include button events, axis events, battery status or more. This
>>> +   data is generated by the device and sent to the host with or without
>>> +   requiring explicit requests. Devices can choose to send data continuously or
>>> +   only on change.
>>> + - OUTPUT Report: Output reports change device states. They are sent from host
>>> +   to device and may include LED requests, rumble requests or more. Output
>>> +   reports are never sent from device to host, but a host can retrieve their
>>> +   current state.
>>> +   Hosts may choose to send output reports either continuously or only on
>>> +   change.
>>> + - FEATURE Report: Feature reports are used for specific static device features
>>> +   and never reported spontaneously. A host can read and/or write them to access
>>> +   data like battery-state or device-settings.
>>> +   Feature reports are never sent without requests. A host must explicitly set
>>> +   or retrieve a feature report. This also means, feature reports are never sent
>>> +   on the intr channel as this channel is asynchronous.
>>> +
>>> +INPUT and OUTPUT reports can be sent as pure data reports on the intr channel.
>>> +For INPUT reports this is the usual operational mode. But for OUTPUT reports,
>>> +this is rarely done as OUTPUT reports are normally quite scarce. But devices are
>>> +free to make excessive use of asynchronous OUTPUT reports (for instance, custom
>>> +HID audio speakers make great use of it).
>>> +
>>> +Plain reports must not be sent on the ctrl channel, though. Instead, the ctrl
>>> +channel provides synchronous GET/SET_REPORT requests. Plain reports are only
>>> +allowed on the intr channel and are the only means of data there.
>>> +
>>> + - GET_REPORT: A GET_REPORT request has a report ID as payload and is sent
>>> +   from host to device. The device must answer with a data report for the
>>> +   requested report ID on the ctrl channel as a synchronous acknowledgement.
>>> +   Only one GET_REPORT request can be pending for each device. This restriction
>>> +   is enforced by HID core as several transport drivers don't allow multiple
>>> +   simultaneous GET_REPORT requests.
>>> +   Note that data reports which are sent as answer to a GET_REPORT request are
>>> +   not handled as generic device events. That is, if a device does not operate
>>> +   in continuous data reporting mode, an answer to GET_REPORT does not replace
>>> +   the raw data report on the intr channel on state change.
>>> +   GET_REPORT is only used by custom HID device drivers to query device state.
>>> +   Normally, HID core caches any device state so this request is not necessary
>>> +   on devices that follow the HID specs except during device initialization to
>>> +   retrieve the current state.
>>> +   GET_REPORT requests can be sent for any of the 3 report types and shall
>>> +   return the current report state of the device. However, OUTPUT reports as
>>> +   payload may be blocked by the underlying transport driver if the
>>> +   specification does not allow them.
>>> + - SET_REPORT: A SET_REPORT request has a report ID plus data as payload. It is
>>> +   sent from host to device and a device must update it's current report state
>>> +   according to the given data. Any of the 3 report types can be used. However,
>>> +   INPUT reports as payload might be blocked by the underlying transport driver
>>> +   if the specification does not allow them.
>>> +   A device must answer with a synchronous acknowledgement. However, HID core
>>> +   does not require transport drivers to forward this acknowledgement to HID
>>> +   core.
>>> +   Same as for GET_REPORT, only one SET_REPORT can be pending at a time. This
>>> +   restriction is enforced by HID core as some transport drivers do not support
>>> +   multiple synchronous SET_REPORT requests.
>>> +
>>> +Other ctrl-channel requests are supported by USB-HID but are not available
>>> +(or deprecated) in most other transport level specifications:
>>> +
>>> + - GET/SET_IDLE: Only used by USB-HID and I2C-HID.
>>> + - GET/SET_PROTOCOL: Not used by HID core.
>>> + - RESET: Used by I2C-HID, not hooked up in HID core.
>>> + - SET_POWER: Used by I2C-HID, not hooked up in HID core.
>>> +
>>> +2) HID API
>>> +==========
>>> +
>>> +2.1) Initialization
>>> +-------------------
>>> +
>>> +Transport drivers normally use the following procedure to register a new device
>>> +with HID core:
>>> +
>>> +       struct hid_device *hid;
>>> +       int ret;
>>> +
>>> +       hid = hid_allocate_device();
>>> +       if (IS_ERR(hid)) {
>>> +               ret = PTR_ERR(hid);
>>> +               goto err_<...>;
>>> +       }
>>> +
>>> +       strlcpy(hid->name, <device-name-src>, 127);
>>> +       strlcpy(hid->phys, <device-phys-src>, 63);
>>> +       strlcpy(hid->uniq, <device-uniq-src>, 63);
>>> +
>>> +       hid->ll_driver = &custom_ll_driver;
>>> +       hid->bus = <device-bus>;
>>> +       hid->vendor = <device-vendor>;
>>> +       hid->product = <device-product>;
>>> +       hid->version = <device-version>;
>>> +       hid->country = <device-country>;
>>> +       hid->dev.parent = <pointer-to-parent-device>;
>>> +       hid->driver_data = <transport-driver-data-field>;
>>> +
>>> +       ret = hid_add_device(hid);
>>> +       if (ret)
>>> +               goto err_<...>;
>>> +
>>> +Once hid_add_device() is entered, HID core might use the callbacks provided in
>>> +"custom_ll_driver". Note that fields like "country" can be ignored by underlying
>>> +transport-drivers if not supported.
>>> +
>>> +To unregister a device, use:
>>> +
>>> +       hid_destroy_device(hid);
>>> +
>>> +Once hid_destroy_device() returns, HID core will no longer make use of any
>>> +driver callbacks.
>>> +
>>> +2.2) hid_ll_driver operations
>>> +-----------------------------
>>> +
>>> +The available HID callbacks are:
>>> + - int (*start) (struct hid_device *hdev)
>>> +   Called from HID device drivers once they want to use the device. Transport
>>> +   drivers can choose to setup their device in this callback. However, normally
>>> +   devices are already set up before transport drivers register them to HID core
>>> +   so this is mostly only used by USB-HID.
>>> +
>>> + - void (*stop) (struct hid_device *hdev)
>>> +   Called from HID device drivers once they are done with a device. Transport
>>> +   drivers can free any buffers and deinitialize the device. But note that
>>> +   ->start() might be called again if another HID device driver is loaded on the
>>> +   device.
>>> +   Transport drivers are free to ignore it and deinitialize devices after they
>>> +   destroyed them via hid_destroy_device().
>>> +
>>> + - int (*open) (struct hid_device *hdev)
>>> +   Called from HID device drivers once they are interested in data reports.
>>> +   Usually, while user-space didn't open any input API/etc., device drivers are
>>> +   not interested in device data and transport drivers can put devices asleep.
>>> +   However, once ->open() is called, transport drivers must be ready for I/O.
>>> +   ->open() calls are nested for each client that opens the HID device.
>>> +
>>> + - void (*close) (struct hid_device *hdev)
>>> +   Called from HID device drivers after ->open() was called but they are no
>>> +   longer interested in device reports. (Usually if user-space closed any input
>>> +   devices of the driver).
>>> +   Transport drivers can put devices asleep and terminate any I/O of all
>>> +   ->open() calls have been followed by a ->close() call. However, ->start() may
>>> +   be called again if the device driver is interested in input reports again.
>>> +
>>> + - int (*parse) (struct hid_device *hdev)
>>> +   Called once during device setup after ->start() has been called. Transport
>>> +   drivers must read the HID report-descriptor from the device and tell HID core
>>> +   about it via hid_parse_report().
>>> +
>>> + - int (*power) (struct hid_device *hdev, int level)
>>> +   Called by HID core to give PM hints to transport drivers. Usually this is
>>> +   analogical to the ->open() and ->close() hints and redundant.
>>> +
>>> + - void (*request) (struct hid_device *hdev, struct hid_report *report,
>>> +                    int reqtype)
>>> +   Send an HID request on the ctrl channel. "report" contains the report that
>>> +   should be sent and "reqtype" the request type. Request-type can be
>>> +   HID_REQ_SET_REPORT or HID_REQ_GET_REPORT.
>>> +   This callback is optional. If not provided, HID core will assemble a raw
>>> +   report following the HID specs and send it via the ->raw_request() callback.
>
> This is not true currently. Aren't we missing a commit in the original series?
> But I would love seeing this come true.

You're talking about the ->request() to ->raw_request() conversion?
Indeed, that hasn't been implemented. But it should be rather easy to
do, right? I will prepare a patch for that so we can apply this
documentation unchanged.

Thanks
David

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] HID: Add HID transport driver documentation
  2014-02-03 16:50     ` David Herrmann
@ 2014-02-03 16:52       ` Benjamin Tissoires
  2014-02-03 17:02         ` David Herrmann
  0 siblings, 1 reply; 6+ messages in thread
From: Benjamin Tissoires @ 2014-02-03 16:52 UTC (permalink / raw)
  To: David Herrmann; +Cc: Frank Praznik, open list:HID CORE LAYER, Jiri Kosina

On Mon, Feb 3, 2014 at 11:50 AM, David Herrmann <dh.herrmann@gmail.com> wrote:
> Hi
>
> On Sat, Feb 1, 2014 at 12:18 AM, Benjamin Tissoires
> <benjamin.tissoires@gmail.com> wrote:
>> On Wed, Jan 29, 2014 at 10:35 AM, David Herrmann <dh.herrmann@gmail.com> wrote:
>>> Hi
>>>
>>> On Wed, Jan 29, 2014 at 4:28 PM, Frank Praznik <frank.praznik@oh.rr.com> wrote:
>>>> Add David Herrmann's documentation for the new low-level HID transport driver
>>>> functions.
>>>>
>>>> Signed-off-by: Frank Praznik <frank.praznik@oh.rr.com>
>>>
>>> If you copy code, you really should keep the signed-off-by chain. A
>>> signed-off-by in kernel context means that you either wrote the code
>>> or have permission to copy it. See here:
>>> http://developercertificate.org/ (which is a public copy of the
>>> kernel's signed-off-by practice).
>>> If you copy code unchanged, it's common practice to even keep the
>>> "Author" field via "git commit --author", but that's optional.
>>>
>>> Anyhow, patch is good, thanks for picking it up!
>>>
>>> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
>>>
>>> Putting Benjamin on CC as he reviewed the patch last time and might
>>> have some more comments (or his final reviewed-by).
>>>
>>
>> Thanks David. I am globally happy with it, but I have a little remark:
>>
>>> Thanks!
>>> David
>>>
>>>> ---
>>>>
>>>>  Sorry, I forgot to include this in the original patch set.
>>>>
>>>>  Documentation/hid/hid-transport.txt | 324 ++++++++++++++++++++++++++++++++++++
>>>>  1 file changed, 324 insertions(+)
>>>>  create mode 100644 Documentation/hid/hid-transport.txt
>>>>
>>>> diff --git a/Documentation/hid/hid-transport.txt b/Documentation/hid/hid-transport.txt
>>>> new file mode 100644
>>>> index 0000000..14b1c18
>>>> --- /dev/null
>>>> +++ b/Documentation/hid/hid-transport.txt
>>>> @@ -0,0 +1,324 @@
>>>> +                          HID I/O Transport Drivers
>>>> +                         ===========================
>>>> +
>>>> +The HID subsystem is independent of the underlying transport driver. Initially,
>>>> +only USB was supported, but other specifications adopted the HID design and
>>>> +provided new transport drivers. The kernel includes at least support for USB,
>>>> +Bluetooth, I2C and user-space I/O drivers.
>>>> +
>>>> +1) HID Bus
>>>> +==========
>>>> +
>>>> +The HID subsystem is designed as a bus. Any I/O subsystem may provide HID
>>>> +devices and register them with the HID bus. HID core then loads generic device
>>>> +drivers on top of it. The transport drivers are responsible of raw data
>>>> +transport and device setup/management. HID core is responsible of
>>>> +report-parsing, report interpretation and the user-space API. Device specifics
>>>> +and quirks are handled by all layers depending on the quirk.
>>>> +
>>>> + +-----------+  +-----------+            +-----------+  +-----------+
>>>> + | Device #1 |  | Device #i |            | Device #j |  | Device #k |
>>>> + +-----------+  +-----------+            +-----------+  +-----------+
>>>> +          \\      //                              \\      //
>>>> +        +------------+                          +------------+
>>>> +        | I/O Driver |                          | I/O Driver |
>>>> +        +------------+                          +------------+
>>>> +              ||                                      ||
>>>> +     +------------------+                    +------------------+
>>>> +     | Transport Driver |                    | Transport Driver |
>>>> +     +------------------+                    +------------------+
>>>> +                       \___                ___/
>>>> +                           \              /
>>>> +                          +----------------+
>>>> +                          |    HID Core    |
>>>> +                          +----------------+
>>>> +                           /  |        |  \
>>>> +                          /   |        |   \
>>>> +             ____________/    |        |    \_________________
>>>> +            /                 |        |                      \
>>>> +           /                  |        |                       \
>>>> + +----------------+  +-----------+  +------------------+  +------------------+
>>>> + | Generic Driver |  | MT Driver |  | Custom Driver #1 |  | Custom Driver #2 |
>>>> + +----------------+  +-----------+  +------------------+  +------------------+
>>>> +
>>>> +Example Drivers:
>>>> +  I/O: USB, I2C, Bluetooth-l2cap
>>>> +  Transport: USB-HID, I2C-HID, BT-HIDP
>>>> +
>>>> +Everything below "HID Core" is simplified in this graph as it is only of
>>>> +interest to HID device drivers. Transport drivers do not need to know the
>>>> +specifics.
>>>> +
>>>> +1.1) Device Setup
>>>> +-----------------
>>>> +
>>>> +I/O drivers normally provide hotplug detection or device enumeration APIs to the
>>>> +transport drivers. Transport drivers use this to find any suitable HID device.
>>>> +They allocate HID device objects and register them with HID core. Transport
>>>> +drivers are not required to register themselves with HID core. HID core is never
>>>> +aware of which transport drivers are available and is not interested in it. It
>>>> +is only interested in devices.
>>>> +
>>>> +Transport drivers attach a constant "struct hid_ll_driver" object with each
>>>> +device. Once a device is registered with HID core, the callbacks provided via
>>>> +this struct are used by HID core to communicate with the device.
>>>> +
>>>> +Transport drivers are responsible of detecting device failures and unplugging.
>>>> +HID core will operate a device as long as it is registered regardless of any
>>>> +device failures. Once transport drivers detect unplug or failure events, they
>>>> +must unregister the device from HID core and HID core will stop using the
>>>> +provided callbacks.
>>>> +
>>>> +1.2) Transport Driver Requirements
>>>> +----------------------------------
>>>> +
>>>> +The terms "asynchronous" and "synchronous" in this document describe the
>>>> +transmission behavior regarding acknowledgements. An asynchronous channel must
>>>> +not perform any synchronous operations like waiting for acknowledgements or
>>>> +verifications. Generally, HID calls operating on asynchronous channels must be
>>>> +running in atomic-context just fine.
>>>> +On the other hand, synchronous channels can be implemented by the transport
>>>> +driver in whatever way they like. They might just be the same as asynchronous
>>>> +channels, but they can also provide acknowledgement reports, automatic
>>>> +retransmission on failure, etc. in a blocking manner. If such functionality is
>>>> +required on asynchronous channels, a transport-driver must implement that via
>>>> +its own worker threads.
>>>> +
>>>> +HID core requires transport drivers to follow a given design. A Transport
>>>> +driver must provide two bi-directional I/O channels to each HID device. These
>>>> +channels must not necessarily be bi-directional in the hardware itself. A
>>>> +transport driver might just provide 4 uni-directional channels. Or it might
>>>> +multiplex all four on a single physical channel. However, in this document we
>>>> +will describe them as two bi-directional channels as they have several
>>>> +properties in common.
>>>> +
>>>> + - Interrupt Channel (intr): The intr channel is used for asynchronous data
>>>> +   reports. No management commands or data acknowledgements are sent on this
>>>> +   channel. Any unrequested incoming or outgoing data report must be sent on
>>>> +   this channel and is never acknowledged by the remote side. Devices usually
>>>> +   send their input events on this channel. Outgoing events are normally
>>>> +   not send via intr, except if high throughput is required.
>>>> + - Control Channel (ctrl): The ctrl channel is used for synchronous requests and
>>>> +   device management. Unrequested data input events must not be sent on this
>>>> +   channel and are normally ignored. Instead, devices only send management
>>>> +   events or answers to host requests on this channel.
>>>> +   The control-channel is used for direct blocking queries to the device
>>>> +   independent of any events on the intr-channel.
>>>> +   Outgoing reports are usually sent on the ctrl channel via synchronous
>>>> +   SET_REPORT requests.
>>>> +
>>>> +Communication between devices and HID core is mostly done via HID reports. A
>>>> +report can be of one of three types:
>>>> +
>>>> + - INPUT Report: Input reports provide data from device to host. This
>>>> +   data may include button events, axis events, battery status or more. This
>>>> +   data is generated by the device and sent to the host with or without
>>>> +   requiring explicit requests. Devices can choose to send data continuously or
>>>> +   only on change.
>>>> + - OUTPUT Report: Output reports change device states. They are sent from host
>>>> +   to device and may include LED requests, rumble requests or more. Output
>>>> +   reports are never sent from device to host, but a host can retrieve their
>>>> +   current state.
>>>> +   Hosts may choose to send output reports either continuously or only on
>>>> +   change.
>>>> + - FEATURE Report: Feature reports are used for specific static device features
>>>> +   and never reported spontaneously. A host can read and/or write them to access
>>>> +   data like battery-state or device-settings.
>>>> +   Feature reports are never sent without requests. A host must explicitly set
>>>> +   or retrieve a feature report. This also means, feature reports are never sent
>>>> +   on the intr channel as this channel is asynchronous.
>>>> +
>>>> +INPUT and OUTPUT reports can be sent as pure data reports on the intr channel.
>>>> +For INPUT reports this is the usual operational mode. But for OUTPUT reports,
>>>> +this is rarely done as OUTPUT reports are normally quite scarce. But devices are
>>>> +free to make excessive use of asynchronous OUTPUT reports (for instance, custom
>>>> +HID audio speakers make great use of it).
>>>> +
>>>> +Plain reports must not be sent on the ctrl channel, though. Instead, the ctrl
>>>> +channel provides synchronous GET/SET_REPORT requests. Plain reports are only
>>>> +allowed on the intr channel and are the only means of data there.
>>>> +
>>>> + - GET_REPORT: A GET_REPORT request has a report ID as payload and is sent
>>>> +   from host to device. The device must answer with a data report for the
>>>> +   requested report ID on the ctrl channel as a synchronous acknowledgement.
>>>> +   Only one GET_REPORT request can be pending for each device. This restriction
>>>> +   is enforced by HID core as several transport drivers don't allow multiple
>>>> +   simultaneous GET_REPORT requests.
>>>> +   Note that data reports which are sent as answer to a GET_REPORT request are
>>>> +   not handled as generic device events. That is, if a device does not operate
>>>> +   in continuous data reporting mode, an answer to GET_REPORT does not replace
>>>> +   the raw data report on the intr channel on state change.
>>>> +   GET_REPORT is only used by custom HID device drivers to query device state.
>>>> +   Normally, HID core caches any device state so this request is not necessary
>>>> +   on devices that follow the HID specs except during device initialization to
>>>> +   retrieve the current state.
>>>> +   GET_REPORT requests can be sent for any of the 3 report types and shall
>>>> +   return the current report state of the device. However, OUTPUT reports as
>>>> +   payload may be blocked by the underlying transport driver if the
>>>> +   specification does not allow them.
>>>> + - SET_REPORT: A SET_REPORT request has a report ID plus data as payload. It is
>>>> +   sent from host to device and a device must update it's current report state
>>>> +   according to the given data. Any of the 3 report types can be used. However,
>>>> +   INPUT reports as payload might be blocked by the underlying transport driver
>>>> +   if the specification does not allow them.
>>>> +   A device must answer with a synchronous acknowledgement. However, HID core
>>>> +   does not require transport drivers to forward this acknowledgement to HID
>>>> +   core.
>>>> +   Same as for GET_REPORT, only one SET_REPORT can be pending at a time. This
>>>> +   restriction is enforced by HID core as some transport drivers do not support
>>>> +   multiple synchronous SET_REPORT requests.
>>>> +
>>>> +Other ctrl-channel requests are supported by USB-HID but are not available
>>>> +(or deprecated) in most other transport level specifications:
>>>> +
>>>> + - GET/SET_IDLE: Only used by USB-HID and I2C-HID.
>>>> + - GET/SET_PROTOCOL: Not used by HID core.
>>>> + - RESET: Used by I2C-HID, not hooked up in HID core.
>>>> + - SET_POWER: Used by I2C-HID, not hooked up in HID core.
>>>> +
>>>> +2) HID API
>>>> +==========
>>>> +
>>>> +2.1) Initialization
>>>> +-------------------
>>>> +
>>>> +Transport drivers normally use the following procedure to register a new device
>>>> +with HID core:
>>>> +
>>>> +       struct hid_device *hid;
>>>> +       int ret;
>>>> +
>>>> +       hid = hid_allocate_device();
>>>> +       if (IS_ERR(hid)) {
>>>> +               ret = PTR_ERR(hid);
>>>> +               goto err_<...>;
>>>> +       }
>>>> +
>>>> +       strlcpy(hid->name, <device-name-src>, 127);
>>>> +       strlcpy(hid->phys, <device-phys-src>, 63);
>>>> +       strlcpy(hid->uniq, <device-uniq-src>, 63);
>>>> +
>>>> +       hid->ll_driver = &custom_ll_driver;
>>>> +       hid->bus = <device-bus>;
>>>> +       hid->vendor = <device-vendor>;
>>>> +       hid->product = <device-product>;
>>>> +       hid->version = <device-version>;
>>>> +       hid->country = <device-country>;
>>>> +       hid->dev.parent = <pointer-to-parent-device>;
>>>> +       hid->driver_data = <transport-driver-data-field>;
>>>> +
>>>> +       ret = hid_add_device(hid);
>>>> +       if (ret)
>>>> +               goto err_<...>;
>>>> +
>>>> +Once hid_add_device() is entered, HID core might use the callbacks provided in
>>>> +"custom_ll_driver". Note that fields like "country" can be ignored by underlying
>>>> +transport-drivers if not supported.
>>>> +
>>>> +To unregister a device, use:
>>>> +
>>>> +       hid_destroy_device(hid);
>>>> +
>>>> +Once hid_destroy_device() returns, HID core will no longer make use of any
>>>> +driver callbacks.
>>>> +
>>>> +2.2) hid_ll_driver operations
>>>> +-----------------------------
>>>> +
>>>> +The available HID callbacks are:
>>>> + - int (*start) (struct hid_device *hdev)
>>>> +   Called from HID device drivers once they want to use the device. Transport
>>>> +   drivers can choose to setup their device in this callback. However, normally
>>>> +   devices are already set up before transport drivers register them to HID core
>>>> +   so this is mostly only used by USB-HID.
>>>> +
>>>> + - void (*stop) (struct hid_device *hdev)
>>>> +   Called from HID device drivers once they are done with a device. Transport
>>>> +   drivers can free any buffers and deinitialize the device. But note that
>>>> +   ->start() might be called again if another HID device driver is loaded on the
>>>> +   device.
>>>> +   Transport drivers are free to ignore it and deinitialize devices after they
>>>> +   destroyed them via hid_destroy_device().
>>>> +
>>>> + - int (*open) (struct hid_device *hdev)
>>>> +   Called from HID device drivers once they are interested in data reports.
>>>> +   Usually, while user-space didn't open any input API/etc., device drivers are
>>>> +   not interested in device data and transport drivers can put devices asleep.
>>>> +   However, once ->open() is called, transport drivers must be ready for I/O.
>>>> +   ->open() calls are nested for each client that opens the HID device.
>>>> +
>>>> + - void (*close) (struct hid_device *hdev)
>>>> +   Called from HID device drivers after ->open() was called but they are no
>>>> +   longer interested in device reports. (Usually if user-space closed any input
>>>> +   devices of the driver).
>>>> +   Transport drivers can put devices asleep and terminate any I/O of all
>>>> +   ->open() calls have been followed by a ->close() call. However, ->start() may
>>>> +   be called again if the device driver is interested in input reports again.
>>>> +
>>>> + - int (*parse) (struct hid_device *hdev)
>>>> +   Called once during device setup after ->start() has been called. Transport
>>>> +   drivers must read the HID report-descriptor from the device and tell HID core
>>>> +   about it via hid_parse_report().
>>>> +
>>>> + - int (*power) (struct hid_device *hdev, int level)
>>>> +   Called by HID core to give PM hints to transport drivers. Usually this is
>>>> +   analogical to the ->open() and ->close() hints and redundant.
>>>> +
>>>> + - void (*request) (struct hid_device *hdev, struct hid_report *report,
>>>> +                    int reqtype)
>>>> +   Send an HID request on the ctrl channel. "report" contains the report that
>>>> +   should be sent and "reqtype" the request type. Request-type can be
>>>> +   HID_REQ_SET_REPORT or HID_REQ_GET_REPORT.
>>>> +   This callback is optional. If not provided, HID core will assemble a raw
>>>> +   report following the HID specs and send it via the ->raw_request() callback.
>>
>> This is not true currently. Aren't we missing a commit in the original series?
>> But I would love seeing this come true.
>
> You're talking about the ->request() to ->raw_request() conversion?
> Indeed, that hasn't been implemented. But it should be rather easy to
> do, right? I will prepare a patch for that so we can apply this
> documentation unchanged.

Don't bother doing it, I have already made it yesterday :)

The documentation would still need to be cleaned to remove
hid_input_event callback... So I can take it in the next round of
ll_transport cleanup if you are ok too.

CHeers,
Benjamin

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] HID: Add HID transport driver documentation
  2014-02-03 16:52       ` Benjamin Tissoires
@ 2014-02-03 17:02         ` David Herrmann
  0 siblings, 0 replies; 6+ messages in thread
From: David Herrmann @ 2014-02-03 17:02 UTC (permalink / raw)
  To: Benjamin Tissoires; +Cc: Frank Praznik, open list:HID CORE LAYER, Jiri Kosina

Hi

On Mon, Feb 3, 2014 at 5:52 PM, Benjamin Tissoires
<benjamin.tissoires@gmail.com> wrote:
[snip]
>>>>> + - void (*request) (struct hid_device *hdev, struct hid_report *report,
>>>>> +                    int reqtype)
>>>>> +   Send an HID request on the ctrl channel. "report" contains the report that
>>>>> +   should be sent and "reqtype" the request type. Request-type can be
>>>>> +   HID_REQ_SET_REPORT or HID_REQ_GET_REPORT.
>>>>> +   This callback is optional. If not provided, HID core will assemble a raw
>>>>> +   report following the HID specs and send it via the ->raw_request() callback.
>>>
>>> This is not true currently. Aren't we missing a commit in the original series?
>>> But I would love seeing this come true.
>>
>> You're talking about the ->request() to ->raw_request() conversion?
>> Indeed, that hasn't been implemented. But it should be rather easy to
>> do, right? I will prepare a patch for that so we can apply this
>> documentation unchanged.
>
> Don't bother doing it, I have already made it yesterday :)
>
> The documentation would still need to be cleaned to remove
> hid_input_event callback... So I can take it in the next round of
> ll_transport cleanup if you are ok too.

Perfect, all fine with me!

Thanks
David

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-02-03 17:02 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-29 15:28 [PATCH] HID: Add HID transport driver documentation Frank Praznik
2014-01-29 15:35 ` David Herrmann
2014-01-31 23:18   ` Benjamin Tissoires
2014-02-03 16:50     ` David Herrmann
2014-02-03 16:52       ` Benjamin Tissoires
2014-02-03 17:02         ` David Herrmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).