input子系统二 驱动层input设备注册

以i2c总线接口的edt-ft5x06.c触摸屏驱动为例

一 input设备注册


1 主要数据结构

  1. static struct i2c_driver edt_ft5x06_ts_driver = {  
  2.     .driver = {  
  3.         .owner = THIS_MODULE,  
  4.         .name = "edt_ft5x06",  
  5.         .pm = &edt_ft5x06_ts_pm_ops,  
  6.     },  
  7.     .id_table = edt_ft5x06_ts_id,  
  8.     .probe    = edt_ft5x06_ts_probe,  
  9.     .remove   = edt_ft5x06_ts_remove,  
  10. };  
标准的驱动框架,主要字段的意义:
owner:模块的所有者,THIS_MODULE宏类似于进程的CURRENT,指向当前的模块;
name:driver的name,register的过程中,会根据driver->name和driver->bus判断该driver是否已经注册过,出现在 /sys/bus/i2c/drivers/

pm:电源管理睡眠唤醒时调用;

  1. static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops,  
  2.              edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume);  

include/Linux/pm.h

  1. #define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \  
  2. const struct dev_pm_ops name = { \  
  3.     SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \  
  4. }  
const struct dev_pm_ops edt_ft5x06_ts_pm_ops= { 
SET_SYSTEM_SLEEP_PM_OPS(edt_ft5x06_ts_suspend, edt_ft5x06_ts_resum) 
  1. #define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \  
  2.     .suspend = suspend_fn, \  
  3.     .resume = resume_fn, \  
  4.     .freeze = suspend_fn, \  
  5.     .thaw = resume_fn, \  
  6.     .poweroff = suspend_fn, \  
  7.     .restore = resume_fn,  

相当于定义了const struct dev_pm_ops edt_ft5x06_ts_pm_ops= {
.resume = edt_ft5x06_ts_resum,
.suspend = edt_ft5x06_ts_suspend,
}

这样一个结构。

id_table:用于device和driver的匹配;

  1. static const struct i2c_device_id edt_ft5x06_ts_id[] = {  
  2.     { "edt-ft5x06", 0 },  
  3.     { }  
  4. };  
  1. MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id);  

include/linux/module.h

  1. #define MODULE_DEVICE_TABLE(type,name)<span style="white-space:pre">        </span>\  
  2.   MODULE_GENERIC_TABLE(type##_device,name)  

上述宏展开为 MODULE_GENERIC_TABLE(i2c_device,edt_ft5x06_ts_id);

  1. #define MODULE_GENERIC_TABLE(gtype,name)            \  
  2. extern const struct gtype##_id __mod_##gtype##_table        \  
  3.   __attribute__ ((unused, alias(__stringify(name))))  
再展开为
extern const struct i2c_device_id __mod_i2c_device_table
  __attribute__ ((unused, alias("edt_ft5x06_ts_id")))
最终生成一个i2c_device_id类型的外部变量__mod_i2c_device_table;被alias到了本驱动专用的由用户自定义的变量。之后的内核构建中,depmod程序会在所以的模块中搜索符号__mod_i2c_device_table,找到后把数据重模块中抽出,利用这些数据在/lib/modules/‘uname -r’/下生成modules.i2cmap文件,该文件包含了各核心模块和它所支持硬件设备的对应关系。depmod程序结束后,内核模块支持的所以i2c设备连同他们的模块名都在该文件中列出。当内核告知热插拔系统一个新的i2c设备被发现时,热插拔系统会使用modules.i2cmap文件来寻找要加载的驱动程序。
一般i2c_device_id需要导出到用户空间时,才使用MODULE_DEVICE_TABLE宏,使模块加载系统在加载模块时知道模块和硬件的对应关系。
probe:device和driver匹配成功会执行的探测函数;

remove:驱动卸载时执行。

2  i2c驱动加载卸载

2.1 驱动加载

  1. module_i2c_driver(edt_ft5x06_ts_driver);  
include/linux/i2c.h
  1. #define module_i2c_driver(__i2c_driver) \  
  2.     module_driver(__i2c_driver, i2c_add_driver, \  
  3.             i2c_del_driver)  
展开为module_driver(edt_ft5x06_ts_driver, i2c_add_driver, i2c_del_driver)

include/linux/device.h

  1. #define module_driver(__driver, __register, __unregister, ...) \  
  2. static int __init __driver##_init(void) \  
  3. { \  
  4.     return __register(&(__driver) , ##__VA_ARGS__); \  
  5. } \  
  6. module_init(__driver##_init); \  
  7. static void __exit __driver##_exit(void) \  
  8. { \  
  9.     __unregister(&(__driver) , ##__VA_ARGS__); \  
  10. } \  
  11. module_exit(__driver##_exit);  
module_i2c_driver(edt_ft5x06_ts_driver);做了很多事情:

static int __init edt_ft5x06_ts_driver_init(void)
{
return i2c_add_driver(&edt_ft5x06_ts_driver);
}
module_init(edt_ft5x06_ts_driver_init);
static void __exit edt_ft5x06_ts_driver_exit(void)
{
return i2c_del_driver(&edt_ft5x06_ts_driver);
}

module_exit(edt_ft5x06_ts_driver_exit);

  1. #define i2c_add_driver(driver) \  
  2.     i2c_register_driver(THIS_MODULE, driver)  
  1. int i2c_register_driver(struct module *owner, struct i2c_driver *driver)  
  2. {  
  3.     int res;  
  4.   
  5.     /* Can't register until after driver model init */  
  6.     if (unlikely(WARN_ON(!i2c_bus_type.p)))  
  7.         return -EAGAIN;  
  8.   
  9.     /* add the driver to the list of i2c drivers in the driver core */  
  10.     driver->driver.owner = owner;  
  11.     driver->driver.bus = &i2c_bus_type;  
  12.   
  13.     /* When registration returns, the driver core 
  14.      * will have called probe() for all matching-but-unbound devices. 
  15.      */  
  16.     res = driver_register(&driver->driver);  
  17.     if (res)  
  18.         return res;  
  19.   
  20.     /* Drivers should switch to dev_pm_ops instead. */  
  21.     if (driver->suspend)  
  22.         pr_warn("i2c-core: driver [%s] using legacy suspend method\n",  
  23.             driver->driver.name);  
  24.     if (driver->resume)  
  25.         pr_warn("i2c-core: driver [%s] using legacy resume method\n",  
  26.             driver->driver.name);  
  27.   
  28.     pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);  
  29.   
  30.     INIT_LIST_HEAD(&driver->clients);  
  31.     /* Walk the adapters that are already present */  
  32.     i2c_for_each_dev(driver, __process_new_driver);  
  33.   
  34.     return 0;  
  35. }  
设置driver->driver.bus = &i2c_bus_type;
  1. struct bus_type i2c_bus_type = {  
  2.     .name       = "i2c",  
  3.     .match      = i2c_device_match,  
  4.     .probe      = i2c_device_probe,  
  5.     .remove     = i2c_device_remove,  
  6.     .shutdown   = i2c_device_shutdown,  
  7.     .pm     = &i2c_device_pm_ops,  
  8. };  

关键函数res = driver_register(&driver->driver);(在这个函数中会执行探测函数driver->probe),接着初始化driver->clients list,i2c_for_each_dev(driver, __process_new_driver);会遍历每个adapter执行i2c_detect、driver->attach_adapter(adap);将adapter和i2c_device的信息相关联,这个过程是双向的register adapter时也会走一遍;现在的driver一般不需要实现attach_adapter,基本被probe取代了。

  1. int driver_register(struct device_driver *drv)  
  2. {  
  3.     int ret;  
  4.     struct device_driver *other;  
  5.   
  6.     BUG_ON(!drv->bus->p);  
  7.   
  8.     if ((drv->bus->probe && drv->probe) ||  
  9.         (drv->bus->remove && drv->remove) ||  
  10.         (drv->bus->shutdown && drv->shutdown))  
  11.         printk(KERN_WARNING "Driver '%s' needs updating - please use "  
  12.             "bus_type methods\n", drv->name);  
  13.   
  14.     other = driver_find(drv->name, drv->bus);  
  15.     if (other) {  
  16.         printk(KERN_ERR "Error: Driver '%s' is already registered, "  
  17.             "aborting...\n", drv->name);  
  18.         return -EBUSY;  
  19.     }  
  20.   
  21.     ret = bus_add_driver(drv);  
  22.     if (ret)  
  23.         return ret;  
  24.     ret = driver_add_groups(drv, drv->groups);  
  25.     if (ret) {  
  26.         bus_remove_driver(drv);  
  27.         return ret;  
  28.     }  
  29.     kobject_uevent(&drv->p->kobj, KOBJ_ADD);  
  30.   
  31.     return ret;  
  32. }  
这是所有driver的注册都要走的流程。先确认该driver没有被注册过,然后注册,添加sysfs接口,向用户空间发送uevent。

bus_add_driver()->driver_attach(drv)->__driver_attach()->driver_match_device()->i2c_match_id()

  1. int driver_attach(struct device_driver *drv)  
  2. {  
  3.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);  
  4. }  

遍历每个i2c device,match client->name, id->name;如果match成功i2c_match_id会返回id,driver_match_device返回1,如果该device没有绑定driver,__driver_attach继续执行driver_probe_device(drv, dev);->really_probe()->(dev->bus->probe(dev))->(drv->probe(dev));终于执行到probe了。really_probe中还会执行driver_bound(dev);

bus_add_driver()->klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);添加到bus->p->klist_drivers,那么register device执行bind的时候才能够遍历到。

  1. static void driver_bound(struct device *dev)  
  2. {  
  3.     if (klist_node_attached(&dev->p->knode_driver)) {  
  4.         printk(KERN_WARNING "%s: device %s already bound\n",  
  5.             __func__, kobject_name(&dev->kobj));  
  6.         return;  
  7.     }  
  8.   
  9.     pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),  
  10.          __func__, dev->driver->name);  
  11.   
  12.     klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);  
  13.   
  14.     /* 
  15.      * Make sure the device is no longer in one of the deferred lists and 
  16.      * kick off retrying all pending devices 
  17.      */  
  18.     driver_deferred_probe_del(dev);  
  19.     driver_deferred_probe_trigger();  
  20.   
  21.     if (dev->bus)  
  22.         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,  
  23.                          BUS_NOTIFY_BOUND_DRIVER, dev);  
  24. }  
主要是把dev->p->knode_driver添加到dev->driver->p->klist_devices上。

driver能够bound的前提是device已经建立了;如果没有建立呢?那就等到device建立的时候bound driver吧。

i2c_new_device()->device_register()->device_add(dev)->bus_add_device(dev)->klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices)添加到bus->p->klist_devices,那么register driver 执行bound的时候才能够遍历到。

device_add()->bus_probe_device()->device_attach()

  1. int device_attach(struct device *dev)  
  2. {  
  3.     int ret = 0;  
  4.   
  5.     device_lock(dev);  
  6.     if (dev->driver) {  
  7.         if (klist_node_attached(&dev->p->knode_driver)) {  
  8.             ret = 1;  
  9.             goto out_unlock;  
  10.         }  
  11.         ret = device_bind_driver(dev);  
  12.         if (ret == 0)  
  13.             ret = 1;  
  14.         else {  
  15.             dev->driver = NULL;  
  16.             ret = 0;  
  17.         }  
  18.     } else {  
  19.         ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);  
  20.         pm_runtime_idle(dev);  
  21.     }  
  22. out_unlock:  
  23.     device_unlock(dev);  
  24.     return ret;  
  25. }  
如果dev->driver已经存在了,判断是否执行了bind,没有执行,也会调用device_bind_driver()->driver_bound()执行bind;

否则

  1. ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);  
遍历每个i2c driver,__device_attach()->driver_match_device()同样是match,如果成功继续执行,driver_probe_device()->really_probe()。

总结:driver和device的bind过程是双向的;热插拔设备可以动态地bind driver。

2.2 驱动卸载

  1. void i2c_del_driver(struct i2c_driver *driver)  
  2. {  
  3.     i2c_for_each_dev(driver, __process_removed_driver);  
  4.   
  5.     driver_unregister(&driver->driver);  
  6.     pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);  
  7. }  
遍历i2c device,执行__process_removed_driver()->i2c_do_del_adapter()->(driver->detach_adapter(adapter))解除对应关系。
  1. void driver_unregister(struct device_driver *drv)  
  2. {  
  3.     if (!drv || !drv->p) {  
  4.         WARN(1, "Unexpected driver unregister!\n");  
  5.         return;  
  6.     }  
  7.     driver_remove_groups(drv, drv->groups);  
  8.     bus_remove_driver(drv);  
  9. }  
remove sysfs接口,remove driver。
  1. void bus_remove_driver(struct device_driver *drv)  
  2. {  
  3.     if (!drv->bus)  
  4.         return;  
  5.   
  6.     if (!drv->suppress_bind_attrs)  
  7.         remove_bind_files(drv);  
  8.     driver_remove_attrs(drv->bus, drv);  
  9.     driver_remove_file(drv, &driver_attr_uevent);  
  10.     klist_remove(&drv->p->knode_bus);  
  11.     pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name);  
  12.     driver_detach(drv);  
  13.     module_remove_driver(drv);  
  14.     kobject_put(&drv->p->kobj);  
  15.     bus_put(drv->bus);  
  16. }  
  1. void driver_detach(struct device_driver *drv)  
  2. {  
  3.     struct device_private *dev_prv;  
  4.     struct device *dev;  
  5.   
  6.     for (;;) {  
  7.         spin_lock(&drv->p->klist_devices.k_lock);  
  8.         if (list_empty(&drv->p->klist_devices.k_list)) {  
  9.             spin_unlock(&drv->p->klist_devices.k_lock);  
  10.             break;  
  11.         }  
  12.         dev_prv = list_entry(drv->p->klist_devices.k_list.prev,  
  13.                      struct device_private,  
  14.                      knode_driver.n_node);  
  15.         dev = dev_prv->device;  
  16.         get_device(dev);  
  17.         spin_unlock(&drv->p->klist_devices.k_lock);  
  18.   
  19.         if (dev->parent) /* Needed for USB */  
  20.             device_lock(dev->parent);  
  21.         device_lock(dev);  
  22.         if (dev->driver == drv)  
  23.             __device_release_driver(dev);  
  24.         device_unlock(dev);  
  25.         if (dev->parent)  
  26.             device_unlock(dev->parent);  
  27.         put_device(dev);  
  28.     }<pre name="code" class="cpp"></pre>}  

drv->p->klist_devices.k_list.prev是对应&dev->p->knode_driver的list,是bound的时候加进去的;klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);

通过这个list可以找到dev->p的p,即dev_prv;
device_register()->device_add()->device_private_init()->(dev->p->device = dev;)
通过dev_prv可以找到device了,如果这个device匹配的driver是要del的,就执行__device_release_driver。
__device_release_driver()->(dev->bus->remove)->(driver->remove(client))

__device_release_driver()->devres_release_all()->klist_remove(&dev->p->knode_driver)->klist_del(n)->klist_put(n, true)->klist_dec_and_del()->klist_release()->list_del(&n->n_node);终于把自己给del了,所以drv->p->klist_devices.k_list.prev会自然向前移动,之前被删除list的前驱。用了for (;;)循环,保证drv->p->klist_devices.k_list全都删除,driver关联的每个dev都做del处理,一份driver可以对应多个device,每个device只能对应一个driver。如果dev->driver != drv,那__device_release_driver(dev);就不会执行drv->p->klist_devices.k_list.prev也不会移动了,岂不是死在看for循环了;drv->p->klist_devices.k_list挂的其实是deive,要保证不死循环,这个device对应的driver一定是bound的drvier,事实也是如此。

3 input设备注册

执行到driver->probe函数就开始了input设备的注册,简化后的probe函数如下。
  1. static int edt_ft5x06_ts_probe(struct i2c_client *client,  
  2.                      const struct i2c_device_id *id)  
  3. {  
  4.     const struct edt_ft5x06_platform_data *pdata =  
  5.                         client->dev.platform_data;  
  6.     struct input_dev *input;  
  7.   
  8.     input = input_allocate_device();  
  9.     if (!tsdata || !input) {  
  10.         dev_err(&client->dev, "failed to allocate driver data.\n");  
  11.         error = -ENOMEM;  
  12.         goto err_free_mem;  
  13.     }  
  14.   
  15.     input->name = tsdata->name;  
  16.     input->id.bustype = BUS_I2C;  
  17.     input->dev.parent = &client->dev;  
  18.   
  19.     __set_bit(EV_SYN, input->evbit);  
  20.     __set_bit(EV_KEY, input->evbit);  
  21.     __set_bit(EV_ABS, input->evbit);  
  22.     __set_bit(BTN_TOUCH, input->keybit);  
  23.     input_set_abs_params(input, ABS_X, 0, tsdata->num_x * 64 - 1, 0, 0);  
  24.     input_set_abs_params(input, ABS_Y, 0, tsdata->num_y * 64 - 1, 0, 0);  
  25.     input_set_abs_params(input, ABS_MT_POSITION_X,  
  26.                  0, tsdata->num_x * 64 - 1, 0, 0);  
  27.     input_set_abs_params(input, ABS_MT_POSITION_Y,  
  28.                  0, tsdata->num_y * 64 - 1, 0, 0);  
  29.     error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0);  
  30.     if (error) {  
  31.         dev_err(&client->dev, "Unable to init MT slots.\n");  
  32.         goto err_free_mem;  
  33.     }  
  34.   
  35.     error = request_threaded_irq(client->irq, NULL, edt_ft5x06_ts_isr,  
  36.                      IRQF_TRIGGER_FALLING | IRQF_ONESHOT,  
  37.   
  38.     error = input_register_device(input);  
  39.     if (error)  
  40.         goto err_remove_attrs;  
  41.   
  42.     return 0;  
  43.   
  44. err_remove_attrs:  
  45.     sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group);  
  46. err_free_irq:  
  47.     free_irq(client->irq, tsdata);  
  48. err_free_mem:  
  49.     input_free_device(input);  
  50.     kfree(tsdata);  
  51.   
  52.     if (gpio_is_valid(pdata->irq_pin))  
  53.         gpio_free(pdata->irq_pin);  
  54.   
  55.     return error;<pre name="code" class="cpp">}</pre>  
input_dev结构代表一个具体的input设备,getevent –p可以查看到,如果用到idc文件,也可以根据这个name匹配。
set_bit这些函数是填充input_dev的一些位掩码,代表支持的事件,寻找handler处理器的时候要做匹配。
  1. static inline void __set_bit(int nr, volatile unsigned long *addr)  
  2. {  
  3.     unsigned long mask = BIT_MASK(nr);  
  4.     unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);  
  5.   
  6.     *p  |= mask;  
  7. }  
  8. #define BIT_MASK(nr)        (1UL << ((nr) % BITS_PER_LONG))  
  9. #define BIT_WORD(nr)        ((nr) / BITS_PER_LONG)  
  10. #define BITS_PER_LONG 32  
例如:
__set_bit(EV_SYN, input->evbit); 等价于input->evbit[0] = 0;
__set_bit(EV_KEY, input->evbit); 等价于input->evbit[0] = 1;
__set_bit(EV_ABS, input->evbit); 等价于input->evbit[0] = 2;
__set_bit(BTN_TOUCH, input->keybit); 等价于input->keybit[0x14a/32] = 1<< (0x14a%32) 
也有直接input->evbit[ xx ] = xx 形式进行初始化的,这样初始化的时候注意要用或”1“。
input_set_abs_params()是初始化absinfo[]和absbit[],前者是信息;后者同样是位掩码,支持的事件。
也就是说如果input_set_abs_params(input, ABS_Y, 0, tsdata->num_y * 64 - 1, 0, 0);就不需要再调用set_bit(ABS_Y, input->absbit);了,因为它已经执行了这个动作。
现在的很多代码会set_bit(INPUT_PROP_DIRECT, input->propbit);这个位,目的是让上层直接识别为input设备。
input_mt_init_slots()用于type B上报的初始化,有两个参数,slot num和flag。slot num用于初始化dev->mt->slots的size,也就是最大手指数。flag用于mt task任务的处理,一般不设置。
input_dev初始化好了之后,就开始关键的注册函数了。
  1. int input_register_device(struct input_dev *dev)  
  2. {  
  3.     static atomic_t input_no = ATOMIC_INIT(0);  
  4.     struct input_devres *devres = NULL;  
  5.     struct input_handler *handler;  
  6.     unsigned int packet_size;  
  7.     const char *path;  
  8.     int error;  
  9.   
  10.     if (dev->devres_managed) {  
  11.         devres = devres_alloc(devm_input_device_unregister,  
  12.                       sizeof(struct input_devres), GFP_KERNEL);  
  13.         if (!devres)  
  14.             return -ENOMEM;  
  15.   
  16.         devres->input = dev;  
  17.     }  
  18.   
  19.     /* Every input device generates EV_SYN/SYN_REPORT events. */  
  20.     __set_bit(EV_SYN, dev->evbit);  
  21.   
  22.     /* KEY_RESERVED is not supposed to be transmitted to userspace. */  
  23.     __clear_bit(KEY_RESERVED, dev->keybit);  
  24.   
  25.     /* Make sure that bitmasks not mentioned in dev->evbit are clean. */  
  26.     input_cleanse_bitmasks(dev);  
  27.   
  28.     packet_size = input_estimate_events_per_packet(dev);  
  29.     if (dev->hint_events_per_packet < packet_size)  
  30.         dev->hint_events_per_packet = packet_size;  
  31.   
  32.     dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2;  
  33.     dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL);  
  34.     if (!dev->vals) {  
  35.         error = -ENOMEM;  
  36.         goto err_devres_free;  
  37.     }  
  38.   
  39.     /* 
  40.      * If delay and period are pre-set by the driver, then autorepeating 
  41.      * is handled by the driver itself and we don't do it in input.c. 
  42.      */  
  43.     init_timer(&dev->timer);  
  44.     if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {  
  45.         dev->timer.data = (long) dev;  
  46.         dev->timer.function = input_repeat_key;  
  47.         dev->rep[REP_DELAY] = 250;  
  48.         dev->rep[REP_PERIOD] = 33;  
  49.     }  
  50.   
  51.     if (!dev->getkeycode)  
  52.         dev->getkeycode = input_default_getkeycode;  
  53.   
  54.     if (!dev->setkeycode)  
  55.         dev->setkeycode = input_default_setkeycode;  
  56.   
  57.     dev_set_name(&dev->dev, "input%ld",  
  58.              (unsigned long) atomic_inc_return(&input_no) - 1);  
  59.   
  60.     error = device_add(&dev->dev);  
  61.     if (error)  
  62.         goto err_free_vals;  
  63.   
  64.     path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);  
  65.     pr_info("%s as %s\n",  
  66.         dev->name ? dev->name : "Unspecified device",  
  67.         path ? path : "N/A");  
  68.     kfree(path);  
  69.   
  70.     error = mutex_lock_interruptible(&input_mutex);  
  71.     if (error)  
  72.         goto err_device_del;  
  73.   
  74.     list_add_tail(&dev->node, &input_dev_list);  
  75.   
  76.     list_for_each_entry(handler, &input_handler_list, node)  
  77.         input_attach_handler(dev, handler);  
  78.   
  79.     input_wakeup_procfs_readers();  
  80.   
  81.     mutex_unlock(&input_mutex);  
  82.   
  83.     if (dev->devres_managed) {  
  84.         dev_dbg(dev->dev.parent, "%s: registering %s with devres.\n",  
  85.             __func__, dev_name(&dev->dev));  
  86.         devres_add(dev->dev.parent, devres);  
  87.     }  
  88.     return 0;  
  89.   
  90. err_device_del:  
  91.     device_del(&dev->dev);  
  92. err_free_vals:  
  93.     kfree(dev->vals);  
  94.     dev->vals = NULL;  
  95. err_devres_free:  
  96.     devres_free(devres);  
  97.     return error;  
  98. }  
  重新set了EV_SYN,因为么给input设备都要产生EV_SYN/SYN_REPORT事件,还要clear KEY_RESERVED,这个事件不允许传入到用户空间,是个保留事件。clean位掩码是说如果test出evbit[]中该type事件类型没有设置,那么相应位掩码对应的code事件编码就无效;自然需要清除了。比如说没有设置EV_KEY(这是一个type);那么keybit[]就清0了。hint_events_per_packet是一个packet里事件的平均值,被事件处理器用于估计hold event需要的buffer size。这个均值的计算分为几种情况,
如果初始化了dev->mt,mt_slots = dev->mt->num_slots。
否则,如果设置了ABS_MT_TRACKING_ID,那么
mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum -
dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1,并且限制在2到32之间。
再否则,如果设置了ABS_MT_POSITION_X为2。
再否则为0。
此时计算的事件值为events = mt_slots + 1;//count SYN_MT_REPORT and SYN_REPORT
此后ABS_MT_FIRST和ABS_MT_LAST之间以及ABS_MT_SLOT的事件代码events += mt_slots;其余0到ABS_CNT之间的events++;0到REL_CNT之间的也是events++;;最后还要为KEY和MSC时间放大一些空间,最后计算出这么一个平均值。
  初始化了一个timer,这个timer干什么用?是为了处理重复按键的。
input_repeat_key()->mod_timer(&dev->timer, jiffies +
msecs_to_jiffies(dev->rep[REP_PERIOD]));针对repeat_key,每33ms会处理一次。
input_repeat_key()->input_pass_values()->input_start_autorepeat()把定时器的到期时间改为dev->rep[REP_DELAY]。如果设置EV_REP,非repeat_key会设置为repeat_key,每250ms处理一次。总结一下重复按键:当按键按下的时候,如果设置EV_REP,把非repeat_key设置为repeat_key;到期时间还是250ms;到期后会执行input_repeat_key();更改timer到期时间为33ms;每33ms处理一次;抬手的时候,input_stop_autorepeat()->del_timer(&dev->timer);。
dev->rep[REP_DELAY]是指第一次按下多久算一次,这里是250ms, dev->rep[REP_PERIOD]指如果按键没有被抬起,每33ms算一次。
  input%ld,这个名字一般出现在./sys/devices/virtual/input/input2和/sys/class/input/input2。
  所有register的input device都会挂到全局的input_dev_list上。
  遍历input_handler_list处理器的list,为input device匹配handler,它们是多对多的关系。
  1. static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)  
  2. {  
  3.     const struct input_device_id *id;  
  4.     int error;  
  5.   
  6.     id = input_match_device(handler, dev);  
  7.     if (!id)  
  8.         return -ENODEV;  
  9.   
  10.     error = handler->connect(handler, dev, id);  
  11.     if (error && error != -ENODEV)  
  12.         pr_err("failed to attach handler %s to device %s, error: %d\n",  
  13.                handler->name, kobject_name(&dev->dev.kobj), error);  
  14.   
  15.     return error;  
  16. }  

input_match_device()中根据handler->id_table(input_device_id)的设置与input device的设置进行匹配,触摸屏对应的handlerevdev..c

  1. static const struct input_device_id evdev_ids[] = {  
  2.     { .driver_info = 1 },   /* Matches all devices */  
  3.     { },            /* Terminating zero entry */  
  4. };  
  1. static inline int bitmap_subset(const unsigned long *src1,  
  2.             const unsigned long *src2, int nbits)  
  3. {  
  4.     if (small_const_nbits(nbits))  
  5.         return ! ((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits));  
  6.     else  
  7.         return __bitmap_subset(src1, src2, nbits);  
  8. }  
  1. #define small_const_nbits(nbits) \  
  2.     (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)  

  做匹配时,主要是位图的匹配。例如:
bitmap_subset(id->absbit, dev->absbit, ABS_MAX);就是比较dev->absbit的设置与id->absbit设置是否完全一致,一致就算匹配成功。
  __builtin_constant_p(x)gcc的内建函数,当x为常数时返回1, x为变量时返回0。常数是指编译时常数。int len = sizeof(struct ...);紧接着的__builtin_constant_p(len)返回值就是1,len虽然为变量,但编译时可确定其值。
  走到最后要调用handler->match(handler, dev);貌似evdev.c没有实现这个match。
  匹配成功就要进行连接了。

  1. static int evdev_connect(struct input_handler *handler, struct input_dev *dev,  
  2.              const struct input_device_id *id)  
  3. {  
  4.     struct evdev *evdev;  
  5.     int minor;  
  6.     int dev_no;  
  7.     int error;  
  8.   
  9.     minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);  
  10.     if (minor < 0) {  
  11.         error = minor;  
  12.         pr_err("failed to reserve new minor: %d\n", error);  
  13.         return error;  
  14.     }  
  15.   
  16.     evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);  
  17.     if (!evdev) {  
  18.         error = -ENOMEM;  
  19.         goto err_free_minor;  
  20.     }  
  21.   
  22.     INIT_LIST_HEAD(&evdev->client_list);  
  23.     spin_lock_init(&evdev->client_lock);  
  24.     mutex_init(&evdev->mutex);  
  25.     init_waitqueue_head(&evdev->wait);  
  26.     evdev->exist = true;  
  27.   
  28.     dev_no = minor;  
  29.     /* Normalize device number if it falls into legacy range */  
  30.     if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS)  
  31.         dev_no -= EVDEV_MINOR_BASE;  
  32.     dev_set_name(&evdev->dev, "event%d", dev_no);  
  33.   
  34.     evdev->handle.dev = input_get_device(dev);  
  35.     evdev->handle.name = dev_name(&evdev->dev);  
  36.     evdev->handle.handler = handler;  
  37.     evdev->handle.private = evdev;  
  38.   
  39.     evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);  
  40.     evdev->dev.class = &input_class;  
  41.     evdev->dev.parent = &dev->dev;  
  42.     evdev->dev.release = evdev_free;  
  43.     device_initialize(&evdev->dev);  
  44.   
  45.     error = input_register_handle(&evdev->handle);  
  46.     if (error)  
  47.         goto err_free_evdev;  
  48.   
  49.     cdev_init(&evdev->cdev, &evdev_fops);  
  50.     evdev->cdev.kobj.parent = &evdev->dev.kobj;  
  51.     error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);  
  52.     if (error)  
  53.         goto err_unregister_handle;  
  54.   
  55.     error = device_add(&evdev->dev);  
  56.     if (error)  
  57.         goto err_cleanup_evdev;  
  58.   
  59.     return 0;  
  60.   
  61.  err_cleanup_evdev:  
  62.     evdev_cleanup(evdev);  
  63.  err_unregister_handle:  
  64.     input_unregister_handle(&evdev->handle);  
  65.  err_free_evdev:  
  66.     put_device(&evdev->dev);  
  67.  err_free_minor:  
  68.     input_free_minor(minor);  
  69.     return error;  
  70. }  
为每个匹配的设备,分配一个evdev结构,并初始化,注意handle.dev是当前的input device,handle.handler是匹配上的handler,这个信息在事件处理的时候还要用。evdev对应的eventx,是一个char设备。
input_register_handle(&evdev->handle);
  list_add_tail_rcu(&handle->d_node, &dev->h_list);把handle挂在dev->h_list上
  list_add_tail_rcu(&handle->h_node, &handler->h_list);把handle挂在handler->h_list上
这样通过handle就可以把handler和dev联系到一起了,本来handle就是个纽带。
至此,把一个input设备注册到了input子系统中;并为其匹配了handler,为时间处理做准备。前面关于i2c device注册和input子系统本身没有关系;也可以理解为touch即是一个i2c client,也是一个input device。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值