冷烟花
哎呀哎呀哎呀我的妈~蜗牛背着那重重的壳呀,一步一步地往上爬~

内核版本:3.9.5

本节将以even handler来分析设备的注册和打开的过程,分析之前不妨回顾一下上节介绍的数据结构.

结合前两节分析可知,input子系统分为3层,最上一层是event handler,中间层是input core,底层是input driver.input driver把event report到input core层,input core对event进行分发,传到 event handler,相应的event handler层把event 放到event buffer中,等待应用程序读取!这就是input的基本思想.

那么我我们来看,Linux模块机制告诉我们在设备注册之前必须先初始化INPUT子系统,这个工作由input_init()函数来完成.在drivers/input.c中:

 1 static int __init input_init(void)
 2 {
 3     int err;
 4 
 5     err = class_register(&input_class);//注册input类
 6     if (err) {
 7         pr_err("unable to register input_dev class\n");
 8         return err;
 9     }
10 
11     err = input_proc_init();//创建/proc中的项
12     if (err)
13         goto fail1;
14 
15     err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0),
16                      INPUT_MAX_CHAR_DEVICES, "input");/*注册设备,主设备号为INPUT_MAJOR,就是13,后面注册的输入设备都使用该主设备号*/
17     if (err) {
18         pr_err("unable to register char major %d", INPUT_MAJOR);
19         goto fail2;
20     }
21 
22     return 0;
23 
24  fail2:    input_proc_exit();
25  fail1:    class_unregister(&input_class);
26     return err;
27 }
28 
29 static void __exit input_exit(void)
30 {
31     input_proc_exit();
32     unregister_chrdev_region(MKDEV(INPUT_MAJOR, 0),
33                  INPUT_MAX_CHAR_DEVICES);
34     class_unregister(&input_class);
35 }
36 
37 subsys_initcall(input_init);
38 module_exit(input_exit);

subsys_initcall和module_exit宏相信大家都很熟悉,这俩函数也很简单,没什么看的.

在入口函数里面创建了一个input_class类,其实就在/sys/class下创建了一个目录input.当然对于一个新设备,可以注册进一个class也可以不注册进去,如果存在对应class的话注册进去更好.另外在/proc创建了入口项,这样就可以/proc目录看到input的信息,然后就注册设备,可以看出输入子系统的主设备号是13,在这里并没有生成设备文件.只是在/dev/目录下创建了input目录,以后所有注册进系统的输入设备文件都放在这个目录下.

那么接下来看看怎么注册input设备的.我们需要在设备驱动层中完成输入设备的注册,通过调用input_register_device()函数来完成,该函数的一个重要任务就是完成设备与事件驱动的匹配.

 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)/*没有定义设备的getkeycode函数,则使用默认的获取键值函数*/
52         dev->getkeycode = input_default_getkeycode;
53 
54     if (!dev->setkeycode)/*没有定义设备的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);/*设定dev的名字*/
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);/*将设备添加到input_dev_list设备链表*/
75 
76     list_for_each_entry(handler, &input_handler_list, node)
77         input_attach_handler(dev, handler);/*遍历input_handler_list,试图与每一个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 }

第76,77行对于每个input_dev,遍历input_handler_list,调用input_attach_handler,根据input_handler的id_table判断能否支持这个input_dev.

 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);/*执行handler的connect,建立handler与设备之间的联系*/
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 }

匹配的具体过程如下:

 1 static const struct input_device_id *input_match_device(struct input_handler *handler,
 2                             struct input_dev *dev)
 3 {
 4     const struct input_device_id *id;
 5 
 6     /*遍历handler的id_table与device进行匹配*/
 7     for (id = handler->id_table; id->flags || id->driver_info; id++) {
 8 
 9         /*根据flags的标志位,按需要匹配相应的字段*/
10         if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
11             if (id->bustype != dev->id.bustype)//总线类型不匹配
12                 continue;
13 
14         if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
15             if (id->vendor != dev->id.vendor)//生产厂商不匹配
16                 continue;
17 
18         if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
19             if (id->product != dev->id.product)//产品不匹配
20                 continue;
21 
22         if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
23             if (id->version != dev->id.version)//版本不匹配
24                 continue;
25 
26         if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX))//匹配所有的事件类型
27             continue;
28 
29         /*匹配所有事件的子事件*/
30         if (!bitmap_subset(id->keybit, dev->keybit, KEY_MAX))
31             continue;
32 
33         if (!bitmap_subset(id->relbit, dev->relbit, REL_MAX))
34             continue;
35 
36         if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX))
37             continue;
38 
39         if (!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX))
40             continue;
41 
42         if (!bitmap_subset(id->ledbit, dev->ledbit, LED_MAX))
43             continue;
44 
45         if (!bitmap_subset(id->sndbit, dev->sndbit, SND_MAX))
46             continue;
47 
48         if (!bitmap_subset(id->ffbit, dev->ffbit, FF_MAX))
49             continue;
50 
51         if (!bitmap_subset(id->swbit, dev->swbit, SW_MAX))
52             continue;
53 
54         if (!handler->match || handler->match(handler, dev))
55             return id;//匹配成功,返回id
56     }
57 
58     return NULL;
59 }

这里接下来就到input_handler的connect了,看来注册input_handler是一道绕不过去的坎儿.那么我们来看具体的event handler的注册,在drivers/input/evdev.c中:

 1 static const struct input_device_id evdev_ids[] = {
 2     { .driver_info = 1 },    /* Matches all devices */
 3     { },            /* Terminating zero entry */
 4 };
 5 
 6 MODULE_DEVICE_TABLE(input, evdev_ids);
 7 
 8 static struct input_handler evdev_handler = {
 9     .event        = evdev_event,
10     .events        = evdev_events,
11     .connect    = evdev_connect,
12     .disconnect    = evdev_disconnect,
13     .legacy_minors    = true,
14     .minor        = EVDEV_MINOR_BASE,
15     .name        = "evdev",
16     .id_table    = evdev_ids,
17 };
18 
19 static int __init evdev_init(void)
20 {
21     return input_register_handler(&evdev_handler);
22 }
23 
24 static void __exit evdev_exit(void)
25 {
26     input_unregister_handler(&evdev_handler);
27 }
28 
29 module_init(evdev_init);
30 module_exit(evdev_exit);

这里一些相关的代码我也顺便贴出来了,再来一个:

 1 int input_register_handler(struct input_handler *handler)
 2 {
 3     struct input_dev *dev;
 4     int error;
 5 
 6     error = mutex_lock_interruptible(&input_mutex);
 7     if (error)
 8         return error;
 9 
10     INIT_LIST_HEAD(&handler->h_list);
11 
12     list_add_tail(&handler->node, &input_handler_list);
13 
14     list_for_each_entry(dev, &input_dev_list, node)
15         input_attach_handler(dev, handler);
16 
17     input_wakeup_procfs_readers();
18 
19     mutex_unlock(&input_mutex);
20     return 0;
21 }

这个函数不用多说了,注册event handler这个input_haner的实例,并且在注册之后迅速遍历了一下input_dev_list链表,查找所有的input_dev设备,看这个input_handler是否支持它.那么回到我们上面的遗留问题看看input_handler的connect函数.对于event handler来说,这个函数就是evdev_connect.在drivers/input/evdev.c中:

 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     /*初始化handle,每个evdev中都有一个handle*/
35     evdev->handle.dev = input_get_device(dev);/*这里就将handle的dev指针指向了input_dev*/
36     evdev->handle.name = dev_name(&evdev->dev);
37     evdev->handle.handler = handler;/*这里将handle的handler指向了当前的input_handler.注意本函数evdev_connect,可能是在在输入设备注册的时候
38     在input_register_device函数中调用input_attach_handler的时候调用;也可能是在输入设备的处理方法input_handler时在input_register_handler
39     函数中也会用到input_attach_handler函数,就会调用本函数.这里就很明显了,本函数就将input_handler和input_dev都放在input_handle中统一管理*/
40     evdev->handle.private = evdev;
41 
42     /*初始化evdev中的内嵌device*/
43     evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);
44     evdev->dev.class = &input_class;
45     evdev->dev.parent = &dev->dev;
46     evdev->dev.release = evdev_free;
47     device_initialize(&evdev->dev);
48 
49     /*注册handle,主要将handle链接到input_dev和handler的h_list链表中去*/
50     error = input_register_handle(&evdev->handle);
51     if (error)
52         goto err_free_evdev;
53 
54     cdev_init(&evdev->cdev, &evdev_fops);
55     evdev->cdev.kobj.parent = &evdev->dev.kobj;
56     error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
57     if (error)
58         goto err_unregister_handle;
59 
60     error = device_add(&evdev->dev);
61     if (error)
62         goto err_cleanup_evdev;
63 
64     return 0;
65 
66  err_cleanup_evdev:
67     evdev_cleanup(evdev);
68  err_unregister_handle:
69     input_unregister_handle(&evdev->handle);
70  err_free_evdev:
71     put_device(&evdev->dev);
72  err_free_minor:
73     input_free_minor(minor);
74     return error;
75 }

至此设备的注册完成!对应event handler,在/dev/input中将多出一个event(x)设备文件,对应一个evdev实例,应用程序打开它的话也就意味着通过event handler来和设备驱动层传递事件.

第54~60行这几行字符设备初始化,这里之后再将字符设备注册,然后我们打开event(x)设备文件的时候实际上就调用evdev_fops里定义的open回调函数.相应的操作函数也在evdev_fops中定义了.我们来看看evdev_fops.同样在drivers/input/evdev.c中:

 1 static const struct file_operations evdev_fops = {
 2     .owner        = THIS_MODULE,
 3     .read        = evdev_read,
 4     .write        = evdev_write,
 5     .poll        = evdev_poll,
 6     .open        = evdev_open,
 7     .release    = evdev_release,
 8     .unlocked_ioctl    = evdev_ioctl,
 9 #ifdef CONFIG_COMPAT
10     .compat_ioctl    = evdev_ioctl_compat,
11 #endif
12     .fasync        = evdev_fasync,
13     .flush        = evdev_flush,
14     .llseek        = no_llseek,
15 };

首先来看打开event(x)设备文件,evdev_open函数.

 1 static int evdev_open(struct inode *inode, struct file *file)
 2 {
 3     struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev);
 4     unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev);
 5     struct evdev_client *client;
 6     int error;
 7 
 8     /*每当一个应用程序打开该文件都会生成一个client*/
 9     client = kzalloc(sizeof(struct evdev_client) +
10                 bufsize * sizeof(struct input_event),
11              GFP_KERNEL);
12     if (!client)
13         return -ENOMEM;
14 
15     client->bufsize = bufsize;
16     spin_lock_init(&client->buffer_lock);
17     client->evdev = evdev;
18     evdev_attach_client(evdev, client);/*将client链入evdev的client_list中*/
19 
20     error = evdev_open_device(evdev);
21     if (error)
22         goto err_free_client;
23 
24     file->private_data = client;
25     nonseekable_open(inode, file);
26 
27     return 0;
28 
29  err_free_client:
30     evdev_detach_client(evdev, client);
31     kfree(client);
32     return error;
33 }

第20行调用evdev_open_device来打开evdev(如果将inpit_dev抽象为一个父对象,这其实就是一个子对象,或者说这个结构封装了一个具体的实例化的input_dev).

 1 static int evdev_open_device(struct evdev *evdev)
 2 {
 3     int retval;
 4 
 5     retval = mutex_lock_interruptible(&evdev->mutex);
 6     if (retval)
 7         return retval;
 8 
 9     if (!evdev->exist)
10         retval = -ENODEV;
11     else if (!evdev->open++) {/*如果是第一次打开该设备,则要执行输入设备的open*/
12         retval = input_open_device(&evdev->handle);
13         if (retval)
14             evdev->open--;
15     }
16 
17     mutex_unlock(&evdev->mutex);
18     return retval;
19 }

这里终于看到了输入子系统核心层的接口input_open_device,此函数就是内核为我们做好的初始化input_dev的函数接口.

 1 int input_open_device(struct input_handle *handle)
 2 {
 3     struct input_dev *dev = handle->dev;
 4     int retval;
 5 
 6     retval = mutex_lock_interruptible(&dev->mutex);
 7     if (retval)
 8         return retval;
 9 
10     if (dev->going_away) {
11         retval = -ENODEV;
12         goto out;
13     }
14 
15     handle->open++;
16 
17     if (!dev->users++ && dev->open)/*如果是第一次打开此设备(当前input_dev的使用者数为0),并且input_dev中定义的open函数不为空*/
18         retval = dev->open(dev);//执行input_dev中定义的open,完成设备的初始化
19 
20     if (retval) {
21         dev->users--;
22         if (!--handle->open) {
23             /*
24              * Make sure we are not delivering any more events
25              * through this handle
26              */
27             synchronize_rcu();
28         }
29     }
30 
31  out:
32     mutex_unlock(&dev->mutex);
33     return retval;
34 }

至于具体的如何初始化input_dev,这个是具体的输入设备去实现的.我们这里不分析了.现在来看看,对于一个event(x)设备文件的.

 1 static ssize_t evdev_read(struct file *file, char __user *buffer,
 2               size_t count, loff_t *ppos)
 3 {
 4     struct evdev_client *client = file->private_data;
 5     struct evdev *evdev = client->evdev;
 6     struct input_event event;
 7     size_t read = 0;
 8     int error;
 9 
10     if (count != 0 && count < input_event_size())
11         return -EINVAL;
12 
13     for (;;) {
14         if (!evdev->exist)/*evdev没有定义返回函数,直接返回吧,因为我们下面必须要用到这个函数*/
15             return -ENODEV;
16 
17         if (client->packet_head == client->tail &&
18             (file->f_flags & O_NONBLOCK))/*无数据并且是非阻塞状态,则直接返回,说明没什么要处理的*/
19             return -EAGAIN;
20 
21         /*
22          * count == 0 is special - no IO is done but we check
23          * for error conditions (see above).
24          */
25         if (count == 0)
26             break;
27 
28         while (read + input_event_size() <= count &&
29                evdev_fetch_next_event(client, &event)) {
30 
31             if (input_event_to_user(buffer + read, &event))
32                 return -EFAULT;
33 
34             read += input_event_size();
35         }
36 
37         if (read)
38             break;
39 
40         if (!(file->f_flags & O_NONBLOCK)) {/*如果是可阻塞状态的话,则等待在wait队列上.直到有数据要被处理,当前进程才被唤醒.这很好理解,既然是
41         输入设备,读的话比如读按键,那么必须要有硬件设备有按键按下才会返回按键值,这里还是处于事件处理层,应用程序在这里休眠,那么谁来唤醒?
42         当然是有按键按下才去唤醒,因此这个工作就交给了设备驱动层,那么找到这个唤醒呢,直接去找不好找,那么可以直接搜索evdev->wait,搜索结果
43         可知evdev->wait在evdev_event()函数中被唤醒*/
44             error = wait_event_interruptible(evdev->wait,
45                     client->packet_head != client->tail ||
46                     !evdev->exist);
47             if (error)
48                 return error;
49         }
50     }
51 
52     return read;
53 }

注释中说的很清楚,evdev_event()会唤醒此处的读按键进程.那么evdev_event()又是被谁调用?显然是设备驱动层,现在看一个设备层例子,内核中有个按键的例子,gpiokey.c,这只是个例子不针对任何设备,在gpiokey.c终端处理函数里面.

 1 static void evdev_pass_values(struct evdev_client *client,
 2             const struct input_value *vals, unsigned int count,
 3             ktime_t mono, ktime_t real)
 4 {
 5     struct evdev *evdev = client->evdev;
 6     const struct input_value *v;
 7     struct input_event event;
 8     bool wakeup = false;
 9 
10     event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
11                       mono : real);
12 
13     /* Interrupts are disabled, just acquire the lock. */
14     spin_lock(&client->buffer_lock);
15 
16     for (v = vals; v != vals + count; v++) {
17         event.type = v->type;
18         event.code = v->code;
19         event.value = v->value;
20         __pass_event(client, &event);
21         if (v->type == EV_SYN && v->code == SYN_REPORT)
22             wakeup = true;
23     }
24 
25     spin_unlock(&client->buffer_lock);
26 
27     if (wakeup)
28         wake_up_interruptible(&evdev->wait);
29 }
30 
31 /*
32  * Pass incoming events to all connected clients.
33  */
34 static void evdev_events(struct input_handle *handle,
35              const struct input_value *vals, unsigned int count)
36 {
37     struct evdev *evdev = handle->private;
38     struct evdev_client *client;
39     ktime_t time_mono, time_real;
40 
41     time_mono = ktime_get();
42     time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
43 
44     rcu_read_lock();
45 
46     client = rcu_dereference(evdev->grab);
47 
48     if (client)
49         evdev_pass_values(client, vals, count, time_mono, time_real);
50     else
51         list_for_each_entry_rcu(client, &evdev->client_list, node)
52             evdev_pass_values(client, vals, count,
53                       time_mono, time_real);
54 
55     rcu_read_unlock();
56 }
57 
58 /*
59  * Pass incoming event to all connected clients.
60  */
61 static void evdev_event(struct input_handle *handle,
62             unsigned int type, unsigned int code, int value)
63 {
64     struct input_value vals[] = { { type, code, value } };
65 
66     evdev_events(handle, vals, 1);
67 }

好了,就贴到这里,input子系统的大体脉络以及比较清楚了.

posted on 2013-06-26 12:58  冷烟花  阅读(2432)  评论(0编辑  收藏  举报