Linux Input子系统(中)--设备的注册和打开
Linux Input子系统(中)--设备的注册和打开
这节结合even handler来分析设备的注册和打开的过程,在设备注册之前,必须先初始化INPUT子系统,由input_init()函数来完成
相关阅读:Linux Input子系统(上)--概述
- static int __init input_init(void)
- {
- int err;
- input_init_abs_bypass();
- err = class_register(&input_class);//注册input类
- if (err) {
- printk(KERN_ERR "input: unable to register input_dev class\n");
- return err;
- }
- err = input_proc_init();//创建/proc中的项
- if (err)
- goto fail1;
- /*注册设备,设备号为INPUT_MAJOR(13),后面注册的输入设备都使用该主设备号*/
- err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
- if (err) {
- printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
- goto fail2;
- }
- return 0;
- fail2: input_proc_exit();
- fail1: class_unregister(&input_class);
- return err;
- }
input_fops中只定义了open函数。
- static const struct file_operations input_fops = {
- .owner = THIS_MODULE,
- .open = input_open_file,
- };
我们需要在设备驱动层中完成输入设备的注册,通过调用input_register_device()函数来完成,该函数的一个重要任务就是完成设备与事件驱动的匹配。
- int input_register_device(struct input_dev *dev)
- {
- static atomic_t input_no = ATOMIC_INIT(0);
- struct input_handler *handler;
- const char *path;
- int error;
- __set_bit(EV_SYN, dev->evbit);
- /*
- * If delay and period are pre-set by the driver, then autorepeating
- * is handled by the driver itself and we don't do it in input.c.
- */
- init_timer(&dev->timer);
- if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
- dev->timer.data = (long) dev;
- dev->timer.function = input_repeat_key;
- dev->rep[REP_DELAY] = 250;
- dev->rep[REP_PERIOD] = 33;
- }
- /*没有定义设备的getkeycode函数,则使用默认的获取键值函数*/
- if (!dev->getkeycode)
- dev->getkeycode = input_default_getkeycode;
- /*没有定义设备的setkeycode函数,则使用默认的设定键值函数*/
- if (!dev->setkeycode)
- dev->setkeycode = input_default_setkeycode;
- /*设定dev的名字*/
- dev_set_name(&dev->dev, "input%ld",
- (unsigned long) atomic_inc_return(&input_no) - 1);
- /*添加设备*/
- error = device_add(&dev->dev);
- if (error)
- return error;
- path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
- printk(KERN_INFO "input: %s as %s\n",
- dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
- kfree(path);
- error = mutex_lock_interruptible(&input_mutex);
- if (error) {
- device_del(&dev->dev);
- return error;
- }
- /*将设备添加到input_dev_list设备链表*/
- list_add_tail(&dev->node, &input_dev_list);
- /*遍历input_handler_list,试图与每一个handler进行匹配*/
- list_for_each_entry(handler, &input_handler_list, node)
- input_attach_handler(dev, handler);
- input_wakeup_procfs_readers();
- mutex_unlock(&input_mutex);
- return 0;
- }
- static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
- {
- const struct input_device_id *id;
- int error;
- /*如果定义了handler的黑名单,并且设备和黑名单中的id匹配了,则该设备不能和handler匹配*/
- if (handler->blacklist && input_match_device(handler->blacklist, dev))
- return -ENODEV;
- id = input_match_device(handler->id_table, dev);
- if (!id)
- return -ENODEV;
- /*执行handler的connect,建立handler与设备之间的联系*/
- error = handler->connect(handler, dev, id);
- if (error && error != -ENODEV)
- printk(KERN_ERR
- "input: failed to attach handler %s to device %s, "
- "error: %d\n",
- handler->name, kobject_name(&dev->dev.kobj), error);
- return error;
- }
|
评论暂时关闭