← Documents Documentation/hid/hid-transport.rst GitHub 원문 ↗

Linux 6.18.37 · HID

HID I/O Transport Drivers

Transport 독립 HID bus, intr·ctrl channel, report request와 hid_ll_driver callback contract를 설명합니다.

Source pathDocumentation/hid/hid-transport.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

hid-transport.rst:1-359

HID transport driver는 물리 I/O와 HID core를 연결하며 device lifetime, 두 논리 channel, synchronous control request와 raw packet 전달을 책임집니다. HID core는 report parse·해석과 userspace API를 담당합니다.

문서 위치
항목
SourceDocumentation/hid/hid-transport.rst
분량359 source lines
Low-level tablestruct hid_ll_driver
Channelsintr · ctrl
필수 callbackraw_request
Core inputhid_input_report

Source와 핵심 contract입니다.

Transport 핵심 경로
I/O subsystem이 HID device 발견Transport가 hid_device·hid_ll_driver 등록Core가 descriptor parse와 driver bindingintr는 async data, ctrl은 sync request 처리Raw packet을 hid_input_report로 전달Unplug·failure 시 transport가 unregister

Device 발견부터 HID core data 전달까지의 요약입니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 =========================
2 HID I/O Transport Drivers
3 =========================
4
5 The HID subsystem is independent of the underlying transport driver. Initially,
6 only USB was supported, but other specifications adopted the HID design and
7 provided new transport drivers. The kernel includes at least support for USB,
8 Bluetooth, I2C and user-space I/O drivers.
9
10 1) HID Bus
11 ==========
12
13 The HID subsystem is designed as a bus. Any I/O subsystem may provide HID
14 devices and register them with the HID bus. HID core then loads generic device
15 drivers on top of it. The transport drivers are responsible for raw data
16 transport and device setup/management. HID core is responsible for
17 report-parsing, report interpretation and the user-space API. Device specifics
18 and quirks are handled by all layers depending on the quirk.
19
20 ::
21
22 +-----------+ +-----------+ +-----------+ +-----------+
23 | Device #1 | | Device #i | | Device #j | | Device #k |
24 +-----------+ +-----------+ +-----------+ +-----------+
25 \\ // \\ //
26 +------------+ +------------+
27 | I/O Driver | | I/O Driver |
28 +------------+ +------------+
29 || ||
30 +------------------+ +------------------+
31 | Transport Driver | | Transport Driver |
32 +------------------+ +------------------+
33 \___ ___/
34 \ /
35 +----------------+
36 | HID Core |
37 +----------------+
38 / | | \
39 / | | \
40 ____________/ | | \_________________
41 / | | \
42 / | | \
43 +----------------+ +-----------+ +------------------+ +------------------+
44 | Generic Driver | | MT Driver | | Custom Driver #1 | | Custom Driver #2 |
45 +----------------+ +-----------+ +------------------+ +------------------+
46
47 Example Drivers:
48
49 - I/O: USB, I2C, Bluetooth-l2cap
50 - Transport: USB-HID, I2C-HID, BT-HIDP
51
52 Everything below "HID Core" is simplified in this graph as it is only of
53 interest to HID device drivers. Transport drivers do not need to know the
54 specifics.
55
56 1.1) Device Setup
57 -----------------
58
59 I/O drivers normally provide hotplug detection or device enumeration APIs to the
60 transport drivers. Transport drivers use this to find any suitable HID device.
61 They allocate HID device objects and register them with HID core. Transport
62 drivers are not required to register themselves with HID core. HID core is never
63 aware of which transport drivers are available and is not interested in it. It
64 is only interested in devices.
65
66 Transport drivers attach a constant "struct hid_ll_driver" object with each
67 device. Once a device is registered with HID core, the callbacks provided via
68 this struct are used by HID core to communicate with the device.
69
70 Transport drivers are responsible for detecting device failures and unplugging.
71 HID core will operate a device as long as it is registered regardless of any
72 device failures. Once transport drivers detect unplug or failure events, they
73 must unregister the device from HID core and HID core will stop using the
74 provided callbacks.
75
76 1.2) Transport Driver Requirements
77 ----------------------------------
78
79 The terms "asynchronous" and "synchronous" in this document describe the
80 transmission behavior regarding acknowledgements. An asynchronous channel must
81 not perform any synchronous operations like waiting for acknowledgements or
82 verifications. Generally, HID calls operating on asynchronous channels must be
83 running in atomic-context just fine.
84 On the other hand, synchronous channels can be implemented by the transport
85 driver in whatever way they like. They might just be the same as asynchronous
86 channels, but they can also provide acknowledgement reports, automatic
87 retransmission on failure, etc. in a blocking manner. If such functionality is
88 required on asynchronous channels, a transport-driver must implement that via
89 its own worker threads.
90
91 HID core requires transport drivers to follow a given design. A Transport
92 driver must provide two bi-directional I/O channels to each HID device. These
93 channels must not necessarily be bi-directional in the hardware itself. A
94 transport driver might just provide 4 uni-directional channels. Or it might
95 multiplex all four on a single physical channel. However, in this document we
96 will describe them as two bi-directional channels as they have several
97 properties in common.
98
99 - Interrupt Channel (intr): The intr channel is used for asynchronous data
100 reports. No management commands or data acknowledgements are sent on this
101 channel. Any unrequested incoming or outgoing data report must be sent on
102 this channel and is never acknowledged by the remote side. Devices usually
103 send their input events on this channel. Outgoing events are normally
104 not sent via intr, except if high throughput is required.
105 - Control Channel (ctrl): The ctrl channel is used for synchronous requests and
106 device management. Unrequested data input events must not be sent on this
107 channel and are normally ignored. Instead, devices only send management
108 events or answers to host requests on this channel.
109 The control-channel is used for direct blocking queries to the device
110 independent of any events on the intr-channel.
111 Outgoing reports are usually sent on the ctrl channel via synchronous
112 SET_REPORT requests.
113
114 Communication between devices and HID core is mostly done via HID reports. A
115 report can be of one of three types:
116
117 - INPUT Report: Input reports provide data from device to host. This
118 data may include button events, axis events, battery status or more. This
119 data is generated by the device and sent to the host with or without
120 requiring explicit requests. Devices can choose to send data continuously or
121 only on change.
122 - OUTPUT Report: Output reports change device states. They are sent from host
123 to device and may include LED requests, rumble requests or more. Output
124 reports are never sent from device to host, but a host can retrieve their
125 current state.
126 Hosts may choose to send output reports either continuously or only on
127 change.
128 - FEATURE Report: Feature reports are used for specific static device features
129 and never reported spontaneously. A host can read and/or write them to access
130 data like battery-state or device-settings.
131 Feature reports are never sent without requests. A host must explicitly set
132 or retrieve a feature report. This also means, feature reports are never sent
133 on the intr channel as this channel is asynchronous.
134
135 INPUT and OUTPUT reports can be sent as pure data reports on the intr channel.
136 For INPUT reports this is the usual operational mode. But for OUTPUT reports,
137 this is rarely done as OUTPUT reports are normally quite scarce. But devices are
138 free to make excessive use of asynchronous OUTPUT reports (for instance, custom
139 HID audio speakers make great use of it).
140
141 Plain reports must not be sent on the ctrl channel, though. Instead, the ctrl
142 channel provides synchronous GET/SET_REPORT requests. Plain reports are only
143 allowed on the intr channel and are the only means of data there.
144
145 - GET_REPORT: A GET_REPORT request has a report ID as payload and is sent
146 from host to device. The device must answer with a data report for the
147 requested report ID on the ctrl channel as a synchronous acknowledgement.
148 Only one GET_REPORT request can be pending for each device. This restriction
149 is enforced by HID core as several transport drivers don't allow multiple
150 simultaneous GET_REPORT requests.
151 Note that data reports which are sent as answer to a GET_REPORT request are
152 not handled as generic device events. That is, if a device does not operate
153 in continuous data reporting mode, an answer to GET_REPORT does not replace
154 the raw data report on the intr channel on state change.
155 GET_REPORT is only used by custom HID device drivers to query device state.
156 Normally, HID core caches any device state so this request is not necessary
157 on devices that follow the HID specs except during device initialization to
158 retrieve the current state.
159 GET_REPORT requests can be sent for any of the 3 report types and shall
160 return the current report state of the device. However, OUTPUT reports as
161 payload may be blocked by the underlying transport driver if the
162 specification does not allow them.
163 - SET_REPORT: A SET_REPORT request has a report ID plus data as payload. It is
164 sent from host to device and a device must update its current report state
165 according to the given data. Any of the 3 report types can be used. However,
166 INPUT reports as payload might be blocked by the underlying transport driver
167 if the specification does not allow them.
168 A device must answer with a synchronous acknowledgement. However, HID core
169 does not require transport drivers to forward this acknowledgement to HID
170 core.
171 Same as for GET_REPORT, only one SET_REPORT can be pending at a time. This
172 restriction is enforced by HID core as some transport drivers do not support
173 multiple synchronous SET_REPORT requests.
174
175 Other ctrl-channel requests are supported by USB-HID but are not available
176 (or deprecated) in most other transport level specifications:
177
178 - GET/SET_IDLE: Only used by USB-HID and I2C-HID.
179 - GET/SET_PROTOCOL: Not used by HID core.
180 - RESET: Used by I2C-HID, not hooked up in HID core.
181 - SET_POWER: Used by I2C-HID, not hooked up in HID core.
182
183 2) HID API
184 ==========
185
186 2.1) Initialization
187 -------------------
188
189 Transport drivers normally use the following procedure to register a new device
190 with HID core::
191
192 struct hid_device *hid;
193 int ret;
194
195 hid = hid_allocate_device();
196 if (IS_ERR(hid)) {
197 ret = PTR_ERR(hid);
198 goto err_<...>;
199 }
200
201 strscpy(hid->name, <device-name-src>, sizeof(hid->name));
202 strscpy(hid->phys, <device-phys-src>, sizeof(hid->phys));
203 strscpy(hid->uniq, <device-uniq-src>, sizeof(hid->uniq));
204
205 hid->ll_driver = &custom_ll_driver;
206 hid->bus = <device-bus>;
207 hid->vendor = <device-vendor>;
208 hid->product = <device-product>;
209 hid->version = <device-version>;
210 hid->country = <device-country>;
211 hid->dev.parent = <pointer-to-parent-device>;
212 hid->driver_data = <transport-driver-data-field>;
213
214 ret = hid_add_device(hid);
215 if (ret)
216 goto err_<...>;
217
218 Once hid_add_device() is entered, HID core might use the callbacks provided in
219 "custom_ll_driver". Note that fields like "country" can be ignored by underlying
220 transport-drivers if not supported.
221
222 To unregister a device, use::
223
224 hid_destroy_device(hid);
225
226 Once hid_destroy_device() returns, HID core will no longer make use of any
227 driver callbacks.
228
229 2.2) hid_ll_driver operations
230 -----------------------------
231
232 The available HID callbacks are:
233
234 ::
235
236 int (*start) (struct hid_device *hdev)
237
238 Called from HID device drivers once they want to use the device. Transport
239 drivers can choose to setup their device in this callback. However, normally
240 devices are already set up before transport drivers register them to HID core
241 so this is mostly only used by USB-HID.
242
243 ::
244
245 void (*stop) (struct hid_device *hdev)
246
247 Called from HID device drivers once they are done with a device. Transport
248 drivers can free any buffers and deinitialize the device. But note that
249 ->start() might be called again if another HID device driver is loaded on the
250 device.
251
252 Transport drivers are free to ignore it and deinitialize devices after they
253 destroyed them via hid_destroy_device().
254
255 ::
256
257 int (*open) (struct hid_device *hdev)
258
259 Called from HID device drivers once they are interested in data reports.
260 Usually, while user-space didn't open any input API/etc., device drivers are
261 not interested in device data and transport drivers can put devices asleep.
262 However, once ->open() is called, transport drivers must be ready for I/O.
263 ->open() calls are nested for each client that opens the HID device.
264
265 ::
266
267 void (*close) (struct hid_device *hdev)
268
269 Called from HID device drivers after ->open() was called but they are no
270 longer interested in device reports. (Usually if user-space closed any input
271 devices of the driver).
272
273 Transport drivers can put devices asleep and terminate any I/O of all
274 ->open() calls have been followed by a ->close() call. However, ->start() may
275 be called again if the device driver is interested in input reports again.
276
277 ::
278
279 int (*parse) (struct hid_device *hdev)
280
281 Called once during device setup after ->start() has been called. Transport
282 drivers must read the HID report-descriptor from the device and tell HID core
283 about it via hid_parse_report().
284
285 ::
286
287 int (*power) (struct hid_device *hdev, int level)
288
289 Called by HID core to give PM hints to transport drivers. Usually this is
290 analogical to the ->open() and ->close() hints and redundant.
291
292 ::
293
294 void (*request) (struct hid_device *hdev, struct hid_report *report,
295 int reqtype)
296
297 Send a HID request on the ctrl channel. "report" contains the report that
298 should be sent and "reqtype" the request type. Request-type can be
299 HID_REQ_SET_REPORT or HID_REQ_GET_REPORT.
300
301 This callback is optional. If not provided, HID core will assemble a raw
302 report following the HID specs and send it via the ->raw_request() callback.
303 The transport driver is free to implement this asynchronously.
304
305 ::
306
307 int (*wait) (struct hid_device *hdev)
308
309 Used by HID core before calling ->request() again. A transport driver can use
310 it to wait for any pending requests to complete if only one request is
311 allowed at a time.
312
313 ::
314
315 int (*raw_request) (struct hid_device *hdev, unsigned char reportnum,
316 __u8 *buf, size_t count, unsigned char rtype,
317 int reqtype)
318
319 Same as ->request() but provides the report as raw buffer. This request shall
320 be synchronous. A transport driver must not use ->wait() to complete such
321 requests. This request is mandatory and hid core will reject the device if
322 it is missing.
323
324 ::
325
326 int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len)
327
328 Send raw output report via intr channel. Used by some HID device drivers
329 which require high throughput for outgoing requests on the intr channel. This
330 must not cause SET_REPORT calls! This must be implemented as asynchronous
331 output report on the intr channel!
332
333 ::
334
335 int (*idle) (struct hid_device *hdev, int report, int idle, int reqtype)
336
337 Perform SET/GET_IDLE request. Only used by USB-HID, do not implement!
338
339 2.3) Data Path
340 --------------
341
342 Transport drivers are responsible of reading data from I/O devices. They must
343 handle any I/O-related state-tracking themselves. HID core does not implement
344 protocol handshakes or other management commands which can be required by the
345 given HID transport specification.
346
347 Every raw data packet read from a device must be fed into HID core via
348 hid_input_report(). You must specify the channel-type (intr or ctrl) and report
349 type (input/output/feature). Under normal conditions, only input reports are
350 provided via this API.
351
352 Responses to GET_REPORT requests via ->request() must also be provided via this
353 API. Responses to ->raw_request() are synchronous and must be intercepted by the
354 transport driver and not passed to hid_input_report().
355 Acknowledgements to SET_REPORT requests are not of interest to HID core.
356
357 ----------------------------------------------------
358
359 Written 2013, David Herrmann <[email protected]>
360

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Transport 독립 HID bus 구조

1-54

HID subsystem은 아래쪽 transport driver와 독립적입니다. 처음에는 USB만 지원했지만 다른 명세가 HID 설계를 채택하면서 새 transport driver가 추가되었습니다. Kernel은 적어도 USB, Bluetooth, I2C와 userspace I/O driver를 지원합니다.

HID subsystem은 bus로 설계되었습니다. 어떤 I/O subsystem이든 HID device를 제공하고 HID bus에 등록할 수 있으며, HID core는 그 위에 generic device driver를 load합니다.

Transport driver는 raw data 전송과 device 설정·관리를 담당합니다. HID core는 report parsing, report 해석과 userspace API를 담당합니다. Device 고유 동작과 quirk는 quirk의 성격에 따라 모든 계층에서 처리될 수 있습니다.

원문의 구조에서 여러 device는 I/O driver에 연결되고, I/O driver는 USB-HID·I2C-HID·BT-HIDP 같은 transport driver를 거쳐 하나의 HID core에 도달합니다. HID core 위에는 generic driver, MT driver와 여러 custom driver가 놓입니다.

I/O driver의 예는 USB, I2C, Bluetooth L2CAP이고 transport driver의 예는 USB-HID, I2C-HID, BT-HIDP입니다. 원문 그림에서 HID core 아래쪽은 HID device driver에만 중요한 세부이므로 단순화되어 있으며 transport driver가 위쪽 device driver의 구체적인 구현을 알 필요는 없습니다.

HID bus 계층
계층책임
Physical devicesDevice #1..#kHID data 생성·수신
I/O driverUSB · I2C · Bluetooth L2CAP물리 I/O 제공
Transport driverUSB-HID · I2C-HID · BT-HIDPRaw transport·device 관리
HID coreHID busReport parse·해석·userspace API
HID device driverGeneric · MT · Custom기능별 처리와 quirk

원문의 ASCII 계층도를 같은 의미의 구조로 정리했습니다.

Device에서 HID driver까지
HID device 발견I/O driver가 물리 통신 제공Transport driver가 HID packet 운반HID core가 report parse·해석Generic·MT·custom driver가 기능 처리Userspace HID/input API 공개

Transport별 device가 공통 HID core에 합류합니다.

=========================
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 for raw data
transport and device setup/management. HID core is responsible for
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.

Device setup과 비동기·동기 channel

55-89

I/O driver는 보통 transport driver에 hotplug detection 또는 device enumeration API를 제공합니다. Transport driver는 이를 사용해 적합한 HID device를 찾고, `struct hid_device` object를 할당해 HID core에 등록합니다.

Transport driver 자체를 HID core에 등록할 필요는 없습니다. HID core는 어떤 transport driver가 사용 가능한지 알지 못하며 관심도 없습니다. HID core가 보는 대상은 등록된 device뿐입니다.

Transport driver는 각 device에 상수 `struct hid_ll_driver` object를 연결합니다. Device가 HID core에 등록되면 core는 이 구조체의 callback을 사용해 device와 통신합니다.

Device failure와 unplug 감지는 transport driver의 책임입니다. HID core는 device가 등록되어 있는 동안 failure 여부와 관계없이 계속 동작합니다. Transport driver가 unplug 또는 failure event를 감지하면 device를 HID core에서 unregister해야 하며, 그 뒤 core는 제공된 callback 사용을 중단합니다.

이 문서의 asynchronous와 synchronous는 acknowledgement에 대한 전송 동작을 뜻합니다. Asynchronous channel은 acknowledgement나 verification을 기다리는 동기 작업을 해서는 안 됩니다. 일반적으로 asynchronous channel에서 동작하는 HID call은 atomic context에서도 문제없이 실행되어야 합니다.

Synchronous channel의 구현 방식은 transport driver가 선택할 수 있습니다. Asynchronous channel과 같게 만들 수도 있고 acknowledgement report, 실패 시 자동 retransmission 등을 blocking 방식으로 제공할 수도 있습니다. Asynchronous channel에 이런 기능이 필요하면 transport driver가 자체 worker thread로 구현해야 합니다.

Device 등록 책임
주체책임
I/O driverHotplug detection·device enumeration
Transport driverhid_device 할당·등록, hid_ll_driver 연결
Transport driverFailure·unplug 감지 후 unregister
HID core등록된 device와 callback만 사용

I/O, transport와 HID core 사이의 ownership을 정리했습니다.

Device lifetime
I/O subsystem이 device 발견Transport driver가 hid_device 할당상수 hid_ll_driver 연결HID core에 device 등록Core가 low-level callback 사용Failure·unplug 시 transport가 unregisterCore가 callback 사용 중단

발견부터 callback 사용 종료까지의 순서입니다.


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 for 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.

Interrupt·control channel과 report 종류

90-143

HID core는 transport driver가 정해진 설계를 따르도록 요구합니다. 각 HID device에는 양방향 I/O channel 두 개를 제공해야 합니다. Hardware 자체가 양방향일 필요는 없어서 단방향 channel 네 개를 제공하거나 네 방향을 하나의 physical channel에 multiplex할 수도 있지만, 공통 속성에 따라 문서에서는 두 양방향 channel로 설명합니다.

Interrupt channel인 `intr`는 asynchronous data report에 사용됩니다. Management command나 data acknowledgement는 이 channel로 보내지 않습니다. 요청 없이 들어오거나 나가는 data report는 `intr`로 보내며 remote 측이 acknowledge하지 않습니다.

Device는 보통 input event를 `intr`로 전송합니다. 나가는 event는 일반적으로 `intr`로 보내지 않지만 높은 throughput이 필요하면 예외적으로 사용할 수 있습니다.

Control channel인 `ctrl`은 synchronous request와 device management에 사용됩니다. 요청되지 않은 input event를 이 channel로 보내서는 안 되며 보통 무시됩니다. Device는 management event 또는 host request에 대한 answer만 `ctrl`로 보냅니다.

`ctrl`은 `intr` event와 독립적으로 device에 직접 blocking query를 보내는 데 사용됩니다. 나가는 report는 대개 synchronous `SET_REPORT` request로 `ctrl`에 전송됩니다.

Device와 HID core의 통신 대부분은 HID report를 사용합니다. Report는 INPUT, OUTPUT, FEATURE의 세 종류입니다.

INPUT report는 device에서 host로 button, axis, battery status 등의 data를 제공합니다. 명시적 request가 있거나 없어도 device가 생성할 수 있으며 연속해서 보내거나 값이 변할 때만 보낼 수 있습니다.

OUTPUT report는 LED, rumble 같은 device state를 바꾸기 위해 host에서 device로 보냅니다. Device에서 host로 보내지는 않지만 host가 현재 state를 조회할 수 있습니다. Host는 연속으로 또는 변경 시에만 보낼 수 있습니다.

FEATURE report는 특정한 static device feature에 사용되며 spontaneous하게 보고되지 않습니다. Host는 battery state나 device setting 같은 data에 접근하기 위해 읽거나 쓸 수 있습니다. 항상 명시적 request가 필요하므로 asynchronous `intr` channel로 전송되지 않습니다.

INPUT과 OUTPUT report는 `intr` channel에서 순수 data report로 보낼 수 있습니다. INPUT에는 이것이 일반적인 동작입니다. OUTPUT은 빈도가 낮아 드물지만, custom HID audio speaker처럼 asynchronous OUTPUT report를 많이 사용하는 device도 가능합니다.

반대로 plain report는 `ctrl` channel로 보내면 안 됩니다. `ctrl`은 synchronous GET/SET_REPORT request를 제공하며, plain report는 `intr`에서만 허용되고 그 channel의 유일한 data 전달 방식입니다.

HID I/O channel
Channel동기성주요 traffic
intrAsynchronous요청 없는 INPUT·고처리량 OUTPUT data report
ctrlSynchronousGET/SET_REPORT·management·request answer

두 논리 channel의 동기성과 허용 traffic을 비교합니다.

Report 방향과 channel
Device INPUT data 생성Plain INPUT은 intr로 host에 전송Host OUTPUT state 변경 준비보통 ctrl의 SET_REPORT로 전송고처리량 OUTPUT은 intr 사용 가능FEATURE는 반드시 ctrl request로 get/set

Report 종류별 일반적인 전송 경로입니다.


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 sent 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·SET_REPORT와 기타 control request

144-182

`GET_REPORT` request는 report ID를 payload로 하여 host에서 device로 전송됩니다. Device는 요청한 report ID의 data report를 synchronous acknowledgement로 `ctrl` channel에 반환해야 합니다.

Device마다 pending `GET_REPORT`는 하나만 허용됩니다. 여러 transport driver가 동시에 여러 GET_REPORT를 허용하지 않기 때문에 HID core가 이 제한을 강제합니다.

GET_REPORT answer로 전송된 data report는 generic device event로 처리되지 않습니다. 연속 보고 mode가 아닌 device에서는 GET_REPORT answer가 state 변경 때 `intr`로 보내야 하는 raw data report를 대신하지 않습니다.

GET_REPORT는 custom HID device driver가 device state를 query할 때만 사용합니다. 명세를 따르는 device의 state는 보통 HID core가 cache하므로, 초기화 중 현재 state를 읽는 경우를 제외하면 필요하지 않습니다.

GET_REPORT는 세 report type 모두에 보낼 수 있고 device의 현재 report state를 반환해야 합니다. 다만 명세가 허용하지 않으면 transport driver가 OUTPUT report 조회를 차단할 수 있습니다.

`SET_REPORT` request는 report ID와 data를 payload로 host에서 device로 보냅니다. Device는 주어진 data에 따라 현재 report state를 갱신해야 합니다. 세 report type을 모두 사용할 수 있지만 명세가 허용하지 않으면 transport driver가 INPUT report payload를 차단할 수 있습니다.

Device는 synchronous acknowledgement를 반환해야 하지만 HID core는 transport driver가 이 acknowledgement를 core까지 전달하도록 요구하지 않습니다. GET_REPORT와 마찬가지로 pending SET_REPORT는 한 번에 하나뿐이며 HID core가 제한합니다.

USB-HID가 지원하는 다른 `ctrl` request는 대부분 다른 transport 명세에서 사용할 수 없거나 deprecated되었습니다. `GET/SET_IDLE`은 USB-HID와 I2C-HID에서만 사용합니다. `GET/SET_PROTOCOL`은 HID core가 사용하지 않습니다. `RESET`과 `SET_POWER`는 I2C-HID에서 사용하지만 HID core에는 연결되어 있지 않습니다.

Control request contract
RequestPayload응답·제한
GET_REPORTReport ID요청 type의 현재 state · device당 pending 1개
SET_REPORTReport ID + dataState 갱신·sync ack · device당 pending 1개
GET/SET_IDLEIdle parameterUSB-HID·I2C-HID 전용
GET/SET_PROTOCOLProtocolHID core에서 미사용
RESET / SET_POWERTransport-specificI2C-HID 사용, core에 미연결

요청 payload, 응답과 동시성 제한을 비교합니다.

GET_REPORT 처리
Host가 report ID로 GET_REPORT 전송HID core가 pending 1개 제한Device가 ctrl channel로 answerTransport가 synchronous response 완료Answer는 generic device event로 처리하지 않음State 변화 event는 별도 intr raw report로 전달

Synchronous query가 일반 event와 분리되는 경로입니다.


 - 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 its 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.

hid_device 초기화와 등록 해제

183-227

Transport driver는 일반적으로 `hid_allocate_device()`로 새 `struct hid_device`를 할당합니다. Error pointer이면 `PTR_ERR()`를 저장하고 transport 고유 error path로 이동합니다.

할당 후 `name`, `phys`, `uniq`를 `strscpy()`로 채우고 `ll_driver`, bus, vendor, product, version, country, parent device와 transport 전용 `driver_data`를 설정합니다.

struct hid_device *hid;
int ret;

hid = hid_allocate_device();
if (IS_ERR(hid)) {
        ret = PTR_ERR(hid);
        goto err_<...>;
}

strscpy(hid->name, <device-name-src>, sizeof(hid->name));
strscpy(hid->phys, <device-phys-src>, sizeof(hid->phys));
strscpy(hid->uniq, <device-uniq-src>, sizeof(hid->uniq));

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_<...>;

`hid_add_device()`에 진입하는 순간부터 HID core가 `custom_ll_driver`의 callback을 사용할 수 있습니다. `country`처럼 underlying transport가 지원하지 않는 field는 무시할 수 있습니다.

Device 등록 해제에는 `hid_destroy_device(hid)`를 사용합니다. 이 함수가 반환된 뒤 HID core는 어떤 driver callback도 더 이상 사용하지 않습니다.

hid_device 필수 초기화
Field/API내용
hid_allocate_deviceHID object 할당
name · phys · uniqDevice 식별 문자열
ll_driverLow-level callback table
bus · vendor · productMatch 식별자
version · countryDevice metadata
dev.parentI/O parent device
driver_dataTransport-private state

등록 전에 transport driver가 채우는 주요 field입니다.

HID device 등록
hid_allocate_device 호출식별 문자열과 metadata 설정custom_ll_driver 연결Parent·driver_data 연결hid_add_device로 등록HID core callback 사용 가능hid_destroy_device 반환 후 callback 사용 종료

할당부터 안전한 callback 종료까지의 순서입니다.

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_<...>;
        }

        strscpy(hid->name, <device-name-src>, sizeof(hid->name));
        strscpy(hid->phys, <device-phys-src>, sizeof(hid->phys));
        strscpy(hid->uniq, <device-uniq-src>, sizeof(hid->uniq));

        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.

start·stop·open·close callback

228-275

`start(struct hid_device *hdev)`는 HID device driver가 device 사용을 시작할 때 호출됩니다. Transport driver는 여기서 device를 setup할 수 있지만 보통 core 등록 전에 이미 setup하므로 주로 USB-HID만 사용합니다.

`stop(struct hid_device *hdev)`은 HID device driver가 device 사용을 마쳤을 때 호출됩니다. Transport driver는 buffer를 해제하고 device를 deinitialize할 수 있습니다. 하지만 다른 HID device driver가 load되면 `start()`가 다시 호출될 수 있습니다.

Transport driver는 `stop()`을 무시하고 `hid_destroy_device()`로 device를 destroy한 뒤 deinitialize해도 됩니다.

`open(struct hid_device *hdev)`은 HID device driver가 data report에 관심을 갖기 시작할 때 호출됩니다. Userspace가 input API 등을 열지 않은 동안에는 device driver가 data에 관심이 없으므로 transport driver가 device를 sleep시킬 수 있습니다.

`open()`이 호출되면 transport driver는 I/O 준비를 마쳐야 합니다. HID device를 여는 client마다 `open()` call이 중첩됩니다.

`close(struct hid_device *hdev)`는 앞서 `open()`한 device report에 더 이상 관심이 없을 때 호출됩니다. 일반적으로 userspace가 driver의 input device를 닫은 경우입니다.

모든 `open()`에 대응하는 `close()`가 호출되면 transport driver는 device를 sleep시키고 I/O를 종료할 수 있습니다. 원문은 input report가 다시 필요해지면 `start()`가 다시 호출될 수 있다고 설명합니다.

Lifecycle callback
Callback의미재호출·중첩
startHID device driver가 device 사용 시작다른 driver load 시 재호출 가능
stop현재 driver의 device 사용 종료뒤에 start 재호출 가능
openData report 수신 필요Client마다 중첩
closeData report 관심 종료모든 open과 짝을 이룬 뒤 sleep 가능

Device setup과 report 관심 상태의 callback을 구분합니다.

I/O 활성 상태
HID device driver startUserspace가 input API openLow-level open 중첩 count 증가Transport가 I/O ready 유지Userspace close마다 count 감소모든 open이 닫히면 I/O 종료·sleep 가능필요 시 lifecycle 재시작

Userspace 관심에 따라 transport I/O를 켜고 끕니다.


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.

parse·power·request·wait·raw_request

276-322

`parse(struct hid_device *hdev)`는 device setup 중 `start()` 뒤 한 번 호출됩니다. Transport driver는 device에서 HID report descriptor를 읽고 `hid_parse_report()`로 HID core에 전달해야 합니다.

`power(struct hid_device *hdev, int level)`는 HID core가 transport driver에 power-management hint를 줄 때 호출합니다. 보통 `open()`과 `close()` hint와 비슷해 중복입니다.

`request(struct hid_device *hdev, struct hid_report *report, int reqtype)`는 `ctrl` channel로 HID request를 보냅니다. `report`에는 전송할 report가, `reqtype`에는 `HID_REQ_SET_REPORT` 또는 `HID_REQ_GET_REPORT`가 들어갑니다.

`request` callback은 선택 사항입니다. 제공하지 않으면 HID core가 HID 명세에 따라 raw report를 조립해 `raw_request()` callback으로 보냅니다. Transport driver는 `request`를 asynchronous 방식으로 구현할 수 있습니다.

`wait(struct hid_device *hdev)`는 HID core가 `request()`를 다시 호출하기 전에 사용합니다. 한 번에 request 하나만 허용하는 transport driver는 pending request가 끝날 때까지 여기서 기다릴 수 있습니다.

`raw_request(struct hid_device *hdev, unsigned char reportnum, __u8 *buf, size_t count, unsigned char rtype, int reqtype)`는 `request()`와 같지만 report를 raw buffer로 제공합니다.

`raw_request`는 synchronous여야 하며 transport driver가 완료를 위해 `wait()`를 사용하면 안 됩니다. 이 callback은 필수이고 누락되면 HID core가 device를 거부합니다.

Low-level request callback
Operation동작계약
parseDescriptor read 후 hid_parse_reportSetup 중 1회
powerPM hint 전달대개 open/close와 중복
request구조화 report를 ctrl로 전송선택 · async 가능
waitPending request 완료 대기다음 request 전 사용
raw_requestRaw buffer GET/SET_REPORT필수 · synchronous · wait 금지

각 operation의 동기성과 필수 여부를 정리했습니다.

Request fallback
HID core가 GET/SET_REPORT 요청request callback 존재 여부 확인있으면 구조화 hid_report 전달없으면 core가 raw report 조립필수 raw_request를 synchronous 호출Transport가 response를 직접 완료

선택 request callback이 없을 때 core가 raw_request를 사용합니다.


   ::

      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 a 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. This request is mandatory and hid core will reject the device if
   it is missing.

고처리량 output과 idle operation

323-338

`output_report(struct hid_device *hdev, __u8 *buf, size_t len)`는 raw output report를 `intr` channel로 보냅니다. `intr`의 높은 outgoing throughput이 필요한 일부 HID device driver가 사용합니다.

이 operation은 `SET_REPORT` call을 발생시키면 안 됩니다. 반드시 `intr` channel의 asynchronous output report로 구현해야 합니다.

`idle(struct hid_device *hdev, int report, int idle, int reqtype)`는 SET/GET_IDLE request를 수행합니다. USB-HID만 사용하므로 다른 transport driver는 구현하지 않아야 합니다.

특수 output operation
OperationChannel주의
output_reportintrAsynchronous raw OUTPUT · SET_REPORT 금지
idlectrlUSB-HID 전용 · 다른 transport는 구현 금지

일반 ctrl SET_REPORT와 구분되는 두 callback입니다.

Asynchronous OUTPUT
HID driver가 raw OUTPUT buffer 준비output_report callback 호출Transport가 intr channel 선택Acknowledgement 없이 asynchronous 전송SET_REPORT request는 생성하지 않음

고처리량 report가 control request를 우회합니다.


   ::

      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 (*idle) (struct hid_device *hdev, int report, int idle, int reqtype)

   Perform SET/GET_IDLE request. Only used by USB-HID, do not implement!

Raw data path와 response 분리

339-359

Transport driver는 I/O device에서 data를 읽을 책임이 있으며 I/O 관련 state tracking도 스스로 처리해야 합니다. HID core는 transport 명세가 요구하는 protocol handshake나 다른 management command를 구현하지 않습니다.

Device에서 읽은 모든 raw data packet은 `hid_input_report()`를 통해 HID core에 넣어야 합니다. 이때 channel type인 `intr` 또는 `ctrl`과 report type인 input, output, feature를 지정해야 합니다. 정상 상황에서는 이 API로 input report만 전달합니다.

`request()`를 통한 GET_REPORT response도 `hid_input_report()`로 전달해야 합니다. 반면 `raw_request()` response는 synchronous이므로 transport driver가 가로채야 하며 `hid_input_report()`에 넘기면 안 됩니다.

SET_REPORT request의 acknowledgement는 HID core의 관심 대상이 아닙니다.

이 문서는 David Herrmann이 2013년에 작성했습니다.

Incoming packet 처리
Packet처리
일반 raw data packetChannel·report type과 함께 hid_input_report 호출
request()의 GET_REPORT answerhid_input_report 호출
raw_request() responseTransport가 synchronous하게 intercept, core에 미전달
SET_REPORT acknowledgementHID core가 사용하지 않음

Packet 출처에 따른 HID core 전달 여부입니다.

Transport data path
Transport driver가 raw packet readPacket의 channel·report type 식별일반 packet은 hid_input_report로 전달request GET_REPORT answer도 같은 API로 전달raw_request response는 transport가 직접 완료SET_REPORT ack는 core에서 무시

I/O packet을 generic event와 synchronous response로 분리합니다.

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 <[email protected]>