概述
-
基于 linux-4.0
-
input系统的 启动顺序
1. input core 初始化
// drivers/input/input.c
subsys_initcall(input_init);
2. handler 的注册
// drivers/input/evdev.c
module_init(evdev_init);
input_register_handler(&evdev_handler);
// drivers/input/mousedev.c
module_init(mousedev_init);
input_register_handler(&mousedev_handler);
3/ device 的注册
drivers/input/touchscreen/bu21013_ts.c
module_i2c_driver(bu21013_driver);
bu21013_probe
input_register_device
// 一般是这样子的,当然, 2和 3 可以颠倒
- handler 有哪些
File | handler名 | 在哪个函数里注册的 |
---|---|---|
drivers/input/apm-power.c | apmpower_handler | apmpower_init() |
drivers/input/evbug.c | evbug_handler | evbug_init() |
drivers/input/input-leds.c | input_leds_handler | input_leds_init() |
drivers/input/joydev.c | joydev_handler | joydev_init() |
drivers/input/mousedev.c | mousedev_handler | mousedev_init() |
drivers/input/evdev.c | evdev_handler | evdev_init() |
drivers/tty/serial/ | kgdboc.c kgdboc_reset_handler | kgdboc_restore_input_helper() |
drivers/macintosh/mac_hid.c | mac_hid_emumouse_handler | mac_hid_start_emulation() |
net/rfkill/input.c | rfkill_handler | rfkill_handler_init() |
drivers/tty/sysrq.c | sysrq_handler | sysrq_register_handler() |
drivers/tty/vt/keyboard.c | kbd_handler | kbd_init() |
- input_register_device 流程
input_register_device
__set_bit(EV_SYN, dev->evbit);
__clear_bit(KEY_RESERVED, dev->keybit);
device_add(&dev->dev); // 注册 input 设备
kobject_get_path // 获取 路径 /devices/virtual/input/input3
//pr_info // 打印 input: I am simplest input subsystem as /devices/virtual/input/input3
list_add_tail(&dev->node, &input_dev_list); // 将设备添加到链表
list_for_each_entry(handler, &input_handler_list, node){ //遍历 handler 链表
input_attach_handler(dev, handler); // 将 handler 与 device 匹配
id = input_match_device(handler, dev);
... // 这个过程中校验 set_bit(EV_KEY, button_dev->evbit);
handler->match // 如果进行到此补,该handler 为 kbd 或者 evdev// 此时校验, set_bit(KEY_POWER,button_dev->keybit);
handler->connect(handler, dev, id); // 用 cdev 来创建 字符设备
}
- input_match_device
1/ 使用 id->flags 匹配
判断 id->flags 是否 为 INPUT_DEVICE_ID_MATCH_BUS
如果是,判断是否 id->bustype 和 dev->id.bustype 是否相等,相等则返回 id
判断 id->flags 是否 为 INPUT_DEVICE_ID_MATCH_PRODUCT
如果是,判断是否相等,相等则返回
2/ 使用 id->evbit 匹配
bitmap_subset(id->keybit, dev->keybit, KEY_MAX)
dev->keybit 不是 id->keybit 的子集, 就进行 下一个 xxxbit 的匹配,否则跳出
3/ 进行handler 相关的匹配
!handler->match || handler->match(handler, dev)
如果handler 没有match 成员, 则表示按照input core 匹配的结果,到这一步,input core 匹配的结果为 匹配成功
如果 handler 有match 成员,必须调用且返回为真 才表示匹配成功.
__bitmap_subset
int __bitmap_subset(const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits)
功能: 判断bitmap2是否是bitmap1的子集,是返回1,不是返回0
- handler->connect(handler, dev, id);
evdev_connect
struct evdev *evdev;
evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
// 初始化链表,用来管理缓冲区
INIT_LIST_HEAD(&evdev->client_list);
// 填充 handle 成员
// 这个handler 成员 是为了 表示 该 device 和 handler 的一个对应关系
// 一个 device 可以对应多个 handler ,一个 handler 可以对应多个 device
// 2个handler 2个dev 在 最复杂的情况下,可以形成 4个handle
// 创建 handler 是为了解决 handler 对 device M*N 的耦合.添加 handle ,就形成了 M*1 1*N 的耦合
evdev->handle.dev = input_get_device(dev);
evdev->handle.name = dev_name(&evdev->dev);
evdev->handle.handler = handler;
input_register_handle(&evdev->handle);
// 将 handle 加入 d_node // device的 hlist 链表中 // 每个 input_dev 都有一个 hlist 链表头
// 将 handle 加入 h_node // handler 的 hlist 链表中// 每个 handler 都有一个 hlist 链表头
//填充 cdev 成员
cdev_init(&evdev->cdev, &evdev_fops);
cdev_add(&evdev->cdev, evdev->dev.devt, 1);
// 将 cdev 添加到内核中,提供 fops
// 填充 dev 成员
evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);
evdev->dev.class = &input_class;
device_initialize(&evdev->dev);
device_add(&evdev->dev); //利用系统在 /dev/input 下面 创建 字符设备
// 利用 mdev 或者 udev 为 cdev 自动添加节点
最后
以上就是魔幻天空为你收集整理的input 子系统(四) input设备 注册及匹配的全部内容,希望文章能够帮你解决input 子系统(四) input设备 注册及匹配所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复