Hi On Sat, Feb 1, 2014 at 12:18 AM, Benjamin Tissoires <benjamin.tissoires@xxxxxxxxx> wrote: > On Wed, Jan 29, 2014 at 10:35 AM, David Herrmann <dh.herrmann@xxxxxxxxx> wrote: >> Hi >> >> On Wed, Jan 29, 2014 at 4:28 PM, Frank Praznik <frank.praznik@xxxxxxxxx> wrote: >>> Add David Herrmann's documentation for the new low-level HID transport driver >>> functions. >>> >>> Signed-off-by: Frank Praznik <frank.praznik@xxxxxxxxx> >> >> 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@xxxxxxxxx> >> >> 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 -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html