1. 学习目标
- 理解 Linux Input 子系统的作用
理解 Linux 如何统一管理:
键盘
鼠标
触摸屏
按键
游戏手柄
- 理解 Input 子系统架构
理解三层结构:
Input Device
Input Core
Input Handler
- 理解 Input 事件机制
理解 Linux 如何表示输入事件
EV_KEY
EV_REL
EV_ABS
- 能编写简单 Input 驱动
掌握核心 API:
input_allocate_device
input_register_device
input_report_key
input_sync
- 能分析用户空间 Input 设备
掌握:
/dev/input/eventX
以及:
evtest
工具。
2. 为什么需要 Input 子系统
如果没有 Input 子系统,每个输入设备驱动都需要自己实现:
字符设备
事件解析
用户接口
例如:
键盘驱动
鼠标驱动
触摸屏驱动
接口都不同。
Linux 于是引入
Input Subsystem
统一输入设备。
3. Input 子系统整体结构
Input 子系统结构:
Input Device Driver
│
▼
Input Core
│
▼
Input Handler
│
▼
User Space
例如:
按键驱动
│
input subsystem
│
evdev
│
/dev/input/event0
│
用户程序
4. Input 子系统核心结构
Input 子系统核心对象:
input_dev
input_handler
input_event
input_dev
表示:
输入设备
例如:
keyboard
mouse
touchscreen
button
结构:
struct input_dev
{
const char *name;
struct input_id id;
};
input_handler
表示:
输入事件处理器
例如:
evdev
keyboard handler
mouse handler
input_event
表示:
输入事件
结构:
struct input_event
{
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
5. Input 事件类型
Linux 定义多种输入事件:
EV_KEY
按键事件:
键盘
按键
EV_REL
相对坐标:
鼠标移动
EV_ABS
绝对坐标:
触摸屏
EV_SYN
同步事件:
事件结束
6. Input 驱动工作流程
Input 驱动基本流程:
驱动初始化
│
分配 input_dev
│
设置设备能力
│
注册设备
│
产生事件
流程图:
input_allocate_device
│
input_set_capability
│
input_register_device
│
input_report_xxx
│
input_sync
7. 分配 Input 设备
驱动首先需要:
input_allocate_device()
示例:
struct input_dev *input;
input = input_allocate_device();
8. 设置设备能力
例如:
按键设备
代码:
set_bit(EV_KEY, input->evbit);
set_bit(KEY_ENTER, input->keybit);
表示:
支持按键事件
9. 注册 Input 设备
注册设备:
input_register_device(input);
注册成功后:
系统生成:
/dev/input/eventX
10. 上报输入事件
驱动检测到按键
button pressed
上报:
input_report_key(input,KEY_ENTER,1);
input_sync(input);
释放按键:
input_report_key(input,KEY_ENTER,0);
input_sync(input);
11. 完整 Input 驱动示例
简单按键驱动:
static struct input_de *button_dev;
static int __init button_init(void)
{
button_key = input_allocate_device();
button_dev->name = "my_button";
set_bit(EV_KEY, button_dev->evbit);
set_bit(KEY_ENTER, button_dev->keybit);
input_register_device(button_dev);
return 0;
}
按键触发:
input_report_key(button_dev, KEY_ENTER, 1);
input_sync(button_dev);
12. 用户空间访问
Input 设备位于:
/dev/input/
例如:
/dev/input/event0
/dev/input/event1
用户程序读取:
struct input_event
evtest 工具
测试 Input 设备:
测试 Input 设备:
evtest
示例:
evtest /dev/input/event0
输出:
Event: type 1 (EV_KEY), code 28 (KEY_ENTER), value 1
13. Input 子系统结构总结
Input 子系统结构:
Hardware
│
Driver
│
Input Device
│
Input Core
│
Input Handler
│
/dev/input/eventX
│
User Space
14. 驱动常见问题
没有生成 eventX
原因:
input_register_device 没调用
evtest 无事件
原因:
没有 input_report
事件类型错误
原因:
EV_KEY / EV_REL / EV_ABS 设置错误
15. 总结
Input 子系统核心结构:
Input Device
│
▼
Input Core
│
▼
Input Handler
│
▼
/dev/input/eventX
事件机制:
input_report_key
input_sync
最重要原则:
Input 子系统负责统一输入事件接口
16. Q&A
16.1 架构理解
-
为什么 Linux 需要 Input 子系统?
-
Input Device 和 Input Handler 的关系?
16.2 事件机制
-
input_event 结构表示什么?
-
EV_KEY 和 EV_ABS 的区别?
16.3 驱动流程
-
input_register_device 做了什么?
-
input_report_key 的作用是什么?