OpenHarmony开发者论坛
标题:
【SUBJECT技术】探索 OpenHarmony libudev 设备热插拔机制
[打印本页]
作者:
诚迈_雨哥
时间:
2024-1-28 16:34
标题:
【SUBJECT技术】探索 OpenHarmony libudev 设备热插拔机制
[md]# 一、多模输入子系统设备热插拔事件来源
当前多模输入子系统处理设备热插拔事件的过程如图所示

现有多模输入子系统框架中,设备原始输入事件要经由libinput处理,封装成libinput的事件类型。多模输入子系统接收并处理libinput封装的事件。特别地,libinput依赖udev获得输入设备热插拔事件的通知。udev将监听热插拔事件、读取热插拔的设备信息,连同枚举已加载设备等接口实现封装成libudev共享库。libinput通过libudev封装的这些功能接口与udev通信,因而在编译时多模输入模块需要链接到libudev。
libinput依赖的两个关键路径是设备节点“/dev/input/<devnode>”和设备系统路径“/sys/class/input/<devnode>”。系统路径可以通过设备节点关联得到。通过设备节点可获得设备支持的事件和属性,以及接收和发送输入事件。通过系统路径可以获得设备的详细信息。
libinput依赖设备能力标记来分设备类型进行事件处理。这些标记是由udevd通过应用配置的规则计算得到的。
总结下来有几个关键点:
(1)libudev是在eudev项目中实现的。
(2)多模输入子系统从udevd获知输入设备热插拔,而设备节点由ueventd创建。
(3)多模输入子系统依赖udev提供的信息包括:输入设备热插拔通知;输入设备节点路径;输入设备的能力标记。udev支持广泛的设备类型,为此定义了一整套复杂的规则来处理设备热插拔事件。多模输入子系统只支持输入设备,我们可以通过简单的逻辑来获取这些信息。
# 二、判断设备类型
不同的输入设备支持不同的输入事件和属性的组合。
## 2.1 如触摸屏支持的事件
```cpp
Discriminator:
eviceType::TOUCHSCREEN, {
.eventTypes {
EV_KEY,
EV_ABS,
},
.keys {
BTN_TOUCH,
},
.abs {
ABS_MT_TOUCH_MAJOR,
ABS_MT_TOUCH_MINOR,
ABS_MT_POSITION_X,
ABS_MT_POSITION_Y,
ABS_MT_TRACKING_ID,
ABS_MT_PRESSURE,
......
},
.properties {
INPUT_PROP_DIRECT,
},
}
```
## 2.2 鼠标支持的输入事件和属性
```cpp
Discriminator:
eviceType::MOUSE, {
.eventTypes {
EV_KEY,
EV_REL,
},
.keys {
BTN_LEFT,
BTN_RIGHT,
BTN_MIDDLE
},
.rels {
REL_X,
REL_Y,
REL_WHEEL
}
},
```
## 2.3 键盘支持的输入事件和属性
```cpp
Discriminator:
eviceType::KEYBOARD,
{
.eventTypes {
EV_KEY,
},
.keys {
KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9,
KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_TAB, KEY_Q,
KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I,
KEY_O, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE,
KEY_ENTER, KEY_LEFTCTRL, KEY_A, KEY_S, KEY_D, KEY_F,
KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON,
KEY_LEFTSHIFT, KEY_BACKSLASH, KEY_Z, KEY_X,
KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA, KEY_DOT,
KEY_SLASH, KY_RIGHTSHIFT, KEY_LEFTALT, KEY_SPACE,
KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6,
KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_NUMLOCK,
KEY_SCROLLLOCK, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KPMINUS,
KEY_KP4, KEY_KP5, KEY_KP6, KEY_KPPLUS, KEY_KP1, KEY_KP2,
KEY_KP3, KEY_KP0, KEY_KPDOT, KEY_F11, KEY_F12, ......
},
},
```
# 三、主要程序处理逻辑
## 3.1 libinput初始化

## 3.2 热插拔事件处理

## 3.3 模块结构

## 3.4 接口列表struct udev;
# 四、udevd进程
## 4.1 udevd是一个守护进程
udevd启动时通过netlink scoket监听内核通知的设备热插拔事件:
src/udev/udevd.c:main()

当接收到内核发出的设备热插拔事件时,udevd将事件加入事件队列,启动工作进程处理事件:
src/udev/udevd.c:main()

工作进程处理热插拔事件,应用配置的规则,执行处理例程,然后将处理后的事件转发给libudev事件监听者(libinput):
src/udev/udevd.c:worker_spawn()

libinput依赖udevd处理过的事件进行设备识别。如果去掉规则匹配部分的逻辑,测试时libinput不能正常识别设备。参考日志:




## 4.2 udevd规则处理逻辑
udevd启动时会遍历预定的目录,寻找规则配置文件。udevd逐个解析每个规则配置文件,形成一个规则项的数组。单个配置文件解析得到的规则项是按序连续排列的,其中第一项(如下图的蓝色项)记录了一些从相应规则配置文件解析得到的规则项的信息,包括规则项的个数等。从该配置文件解析得到的规则项紧接着按规则的类型顺序排列。这些规则项可分为两类,一类用来做匹配,另一类指示执行的动作。如下图所示:

应用规则时,单个规则配置文件中的所有规则项是作为一个整体考虑的。设备的属性应匹配所有的匹配项,才能应用后面的动作。
## 4.3 UDEV鼠标标记

# 五、ueventd进程
## 5.1 ueventd是一个守护进程
它通过netlink scoket监听内核生成的uevent消息。当ueventd接收到uevent消息时,采取适当的动作来处理。典型的场景是当有设备热插/拔时,内核发送uevent事件通知用户端;ueventd接收到此uevent事件,执行如创建/移除设备节点的动作。
系统正常启动后,ueventd会超时退出。当有设备热插拔事件上报时,如果udevd进程未运行,则系统会拉起ueventd进程处理事件,创建设备节点。
OpenHarmony的ueventd进程的代码在“/base/startup/init_lite/ueventd/”目录中。系统启动后,ueventd通过netlink scoket监听内核发送的输入设备热插拔事件。
## 5.2 当前ueventd的实现支持“input”子系统事件的处理
参考日志:

## 5.3 ueventd可接收并处理设备热插拔事件
测试时加载了两个虚拟触摸屏设备,uevent响应并创建了设备节点,ueventd输出日志:

## 5.4 测试插入键盘,uevent创建了设备节点
参考日志:

## 5.5 测试插入鼠标,uevent创建了设备节点

## 5.6 ueventd的日志输出

## 5.7 一个问题是ueventd有监听超时时间设置
设备启动后uevent进程因超时而结束运行。如果去除ueventd的超时设置,ueventd则保持运行:

## 5.8 另一个问题是ueventd的功能简单
未提供事件通知的接口和设备信息获取的接口,如果多模依赖ueventd实现设备热插拔,则需要增加实现这些接口。
# 六、各类型输入设备支持的事件和属性
## 6.1 键盘支持的事件类型和属性






## 6.2 鼠标支持的事件类型和属性

## 6.3 触摸屏支持的事件类型和属性


## 6.4 数位板支持的事件类型和属性














## 6.5 手写笔支持的事件类型和属性





[/md]
欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/)
Powered by Discuz! X3.5