人机接口设备的维护与使用¶
介绍¶
除了普通的输入类型 HID 设备之外,USB 还使用人机接口协议来处理一些实际上并非人机接口,但具有类似通信需求的事物。 这两个主要的例子是电源设备(尤其是不间断电源)和高端监视器上的监视器控制。
为了支持这些不同的需求,Linux USB 系统为 HID 事件提供了两个独立的接口:* input 子系统,它将 HID 事件转换为普通的输入设备接口(例如键盘、鼠标和操纵杆)以及标准化的事件接口 - 请参阅 介绍 * hiddev 接口,它提供相当原始的 HID 事件
由设备生成的 HID 事件的数据流如下所示
usb.c ---> hid-core.c ----> hid-input.c ----> [keyboard/mouse/joystick/event]
|
|
--> hiddev.c ----> POWER / MONITOR CONTROL
此外,其他子系统(除了 USB)也可能将事件馈送到 input 子系统中,但这不会对 HID 设备接口产生影响。
使用 HID 设备接口¶
hiddev 接口是一个字符接口,使用普通的 USB 主设备号,次设备号从 96 开始到 111 结束。 因此,您需要以下命令
mknod /dev/usb/hiddev0 c 180 96
mknod /dev/usb/hiddev1 c 180 97
mknod /dev/usb/hiddev2 c 180 98
mknod /dev/usb/hiddev3 c 180 99
mknod /dev/usb/hiddev4 c 180 100
mknod /dev/usb/hiddev5 c 180 101
mknod /dev/usb/hiddev6 c 180 102
mknod /dev/usb/hiddev7 c 180 103
mknod /dev/usb/hiddev8 c 180 104
mknod /dev/usb/hiddev9 c 180 105
mknod /dev/usb/hiddev10 c 180 106
mknod /dev/usb/hiddev11 c 180 107
mknod /dev/usb/hiddev12 c 180 108
mknod /dev/usb/hiddev13 c 180 109
mknod /dev/usb/hiddev14 c 180 110
mknod /dev/usb/hiddev15 c 180 111
因此,您将您的 hiddev 兼容用户空间程序指向设备的正确接口,它就可以正常工作了。
当然,前提是您有一个 hiddev 兼容的用户空间程序。 如果您需要编写一个,请继续阅读。
HIDDEV API¶
此描述应与 HID 规范结合阅读,该规范可从 https://www.usb.org 免费获得,并方便地链接到 http://www.linux-usb.org。
hiddev API 使用 read() 接口和一组 ioctl() 调用。
HID 设备使用称为“报告”的数据包与主机计算机交换数据。 每个报告分为“字段”,每个字段可以有一个或多个“用法”。 在 hid-core 中,这些用法中的每一个都有一个带符号的 32 位值。
read():¶
这是事件接口。 当 HID 设备的状态发生变化时,它会执行中断传输,其中包含一个报告,其中包含已更改的值。 hid-core.c 模块解析报告,并将报告中已更改的各个用法返回给 hiddev.c。 在其基本模式下,hiddev 将使用 struct hiddev_event 向读者提供这些单独的用法更改
struct hiddev_event {
unsigned hid;
signed int value;
};
其中包含已更改状态的 HID 用法标识符以及更改为的值。 请注意,该结构是在 <linux/hiddev.h> 中定义的,以及其他一些有用的 #defines 和结构。 HID 用法标识符是移位到 16 个高位,并与用法代码进行 OR 运算的 HID 用法页面的组合。 可以使用下面描述的 HIDIOCSFLAG ioctl() 修改 read() 函数的行为。
ioctl():¶
这是控制接口。 有许多控件
- HIDIOCGVERSION
int (读取)
从 hiddev 驱动程序中获取版本代码。
- HIDIOCAPPLICATION
(无)
此 ioctl 调用返回与 HID 设备关联的 HID 应用程序用法。 ioctl() 的第三个参数指定要获取的应用程序索引。 当设备有多个应用程序集合时,这很有用。 如果索引无效(大于或等于此设备拥有的应用程序集合的数量),则 ioctl 返回 -1。 您可以从 hiddev_devinfo 结构的 num_applications 字段预先了解设备有多少个应用程序集合。
- HIDIOCGCOLLECTIONINFO
struct hiddev_collection_info (读/写)
这返回上述信息的超集,不仅提供应用程序集合,还提供设备拥有的所有集合。 它还返回集合在层次结构中存在的级别。 用户传入一个 hiddev_collection_info 结构,并将 index 字段设置为应返回的索引。 ioctl 填充其他字段。 如果索引大于最后一个集合索引,则 ioctl 返回 -1 并将 errno 设置为 -EINVAL。
- HIDIOCGDEVINFO
struct hiddev_devinfo (读取)
获取描述设备的 hiddev_devinfo 结构。
- HIDIOCGSTRING
struct hiddev_string_descriptor (读/写)
从设备获取字符串描述符。 调用者必须填写“index”字段以指示应返回哪个描述符。
- HIDIOCINITREPORT
(无)
指示内核从设备检索所有输入和特征报告值。 此时,所有用法结构都将包含设备的当前值,并在设备更改时保持该值。 请注意,通常不需要使用此 ioctl,因为后来的内核会在连接时自动从设备初始化报告。
- HIDIOCGNAME
字符串 (可变长度)
获取设备名称
- HIDIOCGREPORT
struct hiddev_report_info (写入)
指示内核从设备获取特征或输入报告,以便选择性地更新用法结构(与 INITREPORT 相比)。
- HIDIOCSREPORT
struct hiddev_report_info (写入)
指示内核将报告发送到设备。 用户可以通过 HIDIOCSUSAGE 调用(如下所示)填充此报告,以在将整个报告发送到设备之前填充报告中的各个用法值。
- HIDIOCGREPORTINFO
struct hiddev_report_info (读/写)
为用户填写 hiddev_report_info 结构。 按类型(输入、输出或特征)和 ID 查找报告,因此用户必须填写这些字段。 ID 可以是绝对的 - 设备报告的实际报告 ID - 或相对的 - HID_REPORT_ID_FIRST 表示第一个报告,(HID_REPORT_ID_NEXT | report_id) 表示 report_id 之后的下一个报告。 如果没有关于报告 ID 的先验信息,使用此 ioctl 的正确方法是使用上面的相对 ID 来枚举有效 ID。 当没有更多下一个 ID 时,ioctl 返回非零值。 真正的报告 ID 填充到返回的 hiddev_report_info 结构中。
- HIDIOCGFIELDINFO
struct hiddev_field_info (读/写)
以 hiddev_field_info 结构返回与报告关联的字段信息。 用户必须像上面一样在此结构中填写 report_id 和 report_type。 还应填写 field_index,它应该是一个从 0 到 maxfield-1 的数字,如先前 HIDIOCGREPORTINFO 调用返回的。
- HIDIOCGUCODE
struct hiddev_usage_ref (读/写)
给定其报告类型、报告 ID、字段索引以及字段内的索引已填写到结构中,则在 hiddev_usage_ref 结构中返回 usage_code。
- HIDIOCGUSAGE
struct hiddev_usage_ref (读/写)
返回 hiddev_usage_ref 结构中用法的价值。 要检索的用法可以如上所述指定,或者用户可以选择填写 report_type 字段并将 report_id 指定为 HID_REPORT_ID_UNKNOWN。 在这种情况下,如果找到该用法,hiddev_usage_ref 将填充与此用法关联的报告和字段信息。
- HIDIOCSUSAGE
struct hiddev_usage_ref (写入)
设置输出报告中用法的价值。 用户如上所述填写 hiddev_usage_ref 结构,但另外填写 value 字段。
- HIDIOGCOLLECTIONINDEX
struct hiddev_usage_ref (写入)
返回与此用法关联的集合索引。 这表示此用法在集合层次结构中的位置。
- HIDIOCGFLAG
int (读取)
- HIDIOCSFLAG
int (写入)
这些操作分别检查和替换影响上面 read() 调用的模式标志。 标志如下
- HIDDEV_FLAG_UREF
read() 调用现在将返回 struct hiddev_usage_ref 而不是 struct hiddev_event。 这是一个更大的结构,但在设备在其报告中使用具有相同用法代码的多个用法的情况下,此模式有助于解决此类歧义。
- HIDDEV_FLAG_REPORT
此标志只能与 HIDDEV_FLAG_UREF 结合使用。 设置此标志后,当设备发送报告时,将向 read() 返回一个 struct hiddev_usage_ref,其中填充了 report_type 和 report_id,但 field_index 设置为 FIELD_INDEX_NONE。 当设备已发送报告时,这可用作额外的通知。