input 子系统(四) input设备 注册及匹配

  • 基于 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 有哪些
Filehandler名在哪个函数里注册的
drivers/input/apm-power.capmpower_handlerapmpower_init()
drivers/input/evbug.cevbug_handlerevbug_init()
drivers/input/input-leds.cinput_leds_handlerinput_leds_init()
drivers/input/joydev.cjoydev_handlerjoydev_init()
drivers/input/mousedev.cmousedev_handlermousedev_init()
drivers/input/evdev.cevdev_handlerevdev_init()
drivers/tty/serial/kgdboc.c kgdboc_reset_handlerkgdboc_restore_input_helper()
drivers/macintosh/mac_hid.cmac_hid_emumouse_handlermac_hid_start_emulation()
net/rfkill/input.crfkill_handlerrfkill_handler_init()
drivers/tty/sysrq.csysrq_handlersysrq_register_handler()
drivers/tty/vt/keyboard.ckbd_handlerkbd_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 自动添加节点

    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值