本文共 3791 字,大约阅读时间需要 12 分钟。
基于
input系统的 启动顺序
1. input core 初始化// drivers/input/input.csubsys_initcall(input_init);2. handler 的注册// drivers/input/evdev.cmodule_init(evdev_init); input_register_handler(&evdev_handler);// drivers/input/mousedev.cmodule_init(mousedev_init); input_register_handler(&mousedev_handler);3/ device 的注册drivers/input/touchscreen/bu21013_ts.cmodule_i2c_driver(bu21013_driver); bu21013_probe input_register_device// 一般是这样子的,当然, 2和 3 可以颠倒
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 __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 来创建 字符设备 }
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_subsetint __bitmap_subset(const unsigned long *bitmap1, const unsigned long *bitmap2, int bits)功能: 判断bitmap2是否是bitmap1的子集,是返回1,不是返回0
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 自动添加节点
转载地址:http://exigi.baihongyu.com/