linux设备驱动(13)input子系统(二)API详解

input子系统分为三层:

事件驱动层input_handler,提供事件注册接口。

输入核心层input_handle,是input子系统实现的核心。

设备驱动层input_dev,提供设备注册接口,输入信息反馈接口。

1 输入核心层

1.1input的初始化

input_init(),属于输入核心层

定义位于:drivers\input\input.c

 1 static int __init input_init(void)
 2 {
 3     int err;
 4 
 5     err = class_register(&input_class);/* 在sysfs中的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文件系统 *就是创建/proc中入口项,在/proc中就可以查看input/
12     if (err)
13         goto fail1;
14 
15     err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0),/* 注册字符设备驱动,主设备号为INPUT_MAJOR,就是13,后面注册的输入设备都使用该主设备号 */
16                      INPUT_MAX_CHAR_DEVICES, "input");
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 }

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

1.2 handle的注册 

其实就是把handler和dev的链表加入到handle的数据中。

 1 /**
 2  * input_register_handle - register a new input handle
 3  * @handle: handle to register
 4  *
 5  * This function puts a new input handle onto device's
 6  * and handler's lists so that events can flow through
 7  * it once it is opened using input_open_device().
 8  *
 9  * This function is supposed to be called from handler's
10  * connect() method.
11  */
12 int input_register_handle(struct input_handle *handle)
13 {
14     struct input_handler *handler = handle->handler;
15     struct input_dev *dev = handle->dev;
16     int error;
17 
18     /*
19      * We take dev->mutex here to prevent race with
20      * input_release_device().
21      */
22     error = mutex_lock_interruptible(&dev->mutex);
23     if (error)
24         return error;
25 
26     /*
27      * Filters go to the head of the list, normal handlers
28      * to the tail.
29      */
30     if (handler->filter)
31         list_add_rcu(&handle->d_node, &dev->h_list);
32     else
33         list_add_tail_rcu(&handle->d_node, &dev->h_list);/*把dev加入到handle*/
34 
35     mutex_unlock(&dev->mutex);
36 
37     /*
38      * Since we are supposed to be called from ->connect()
39      * which is mutually exclusive with ->disconnect()
40      * we can't be racing with input_unregister_handle()
41      * and so separate lock is not needed here.
42      */
43     list_add_tail_rcu(&handle->h_node, &handler->h_list);/*把handler加入到handle*/
44 
45     if (handler->start)
46         handler->start(handle);
47 
48     return 0;
49 }

RCU形式的锁机制,它允许多个执行单元对它同时对它进行读,但是多个执行单元对它进行写操作时,要求你先复制一个副本,要改要删随你便,反正你改的不是其本身。当所有的写单元都一一改完后,再统一写回,比一般的自旋锁高级些。但是不要轻易用它,因为系统开销较大。

1.3input_open_device()

 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 }

2.设备驱动层。

2.1.input_allocate_device()

设备描述结构体变量input_dev分配,同时初始化一些通用性数据。其他数据对于不同设备特有的数据需要自己填充。

 1 /**
 2  * input_allocate_device - allocate memory for new input device
 3  *
 4  * Returns prepared struct input_dev or %NULL.
 5  *
 6  * NOTE: Use input_free_device() to free devices that have not been
 7  * registered; input_unregister_device() should be used for already
 8  * registered devices.
 9  */
10 struct input_dev *input_allocate_device(void)
11 {
12     struct input_dev *dev;
13 
14     dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
15     if (dev) {
16         dev->dev.type = &input_dev_type;/* 绑定设备信息 */
17         dev->dev.class = &input_class;/* 绑定在sysfs所属的类,后面的register里面的add_device后才能出现在sysfs下的input文件夹下 */
18         device_initialize(&dev->dev);/*初始化设备*/
19         mutex_init(&dev->mutex);
20         spin_lock_init(&dev->event_lock);/*初始化挂载input_device的input_hander的链表*/
21         INIT_LIST_HEAD(&dev->h_list);/*初始化挂载input_device的链表*/
22         INIT_LIST_HEAD(&dev->node);
23 
24         __module_get(THIS_MODULE);
25     }
26 
27     return dev;
28 }
1 static struct device_type input_dev_type = {
2     .groups        = input_dev_attr_groups,
3     .release    = input_dev_release,
4     .uevent        = input_dev_uevent,
5 #ifdef CONFIG_PM
6     .pm        = &input_dev_pm_ops,
7 #endif
8 };

2.2 设置dev设备的能力,只有注册前设置来它拥有的能力,将来该设备注册后,发送的信息才能被上报。

注意:该函数每次只能设置一个能力。

 1 /**
 2  * input_set_capability - mark device as capable of a certain event
 3  * @dev: device that is capable of emitting or accepting event
 4  * @type: type of the event (EV_KEY, EV_REL, etc...)
 5  * @code: event code
 6  *
 7  * In addition to setting up corresponding bit in appropriate capability
 8  * bitmap the function also adjusts dev->evbit.
 9  */
10 void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
11 {
12     switch (type) {/*根据type类型,设置code到相应的typebit*/
13     case EV_KEY:
14         __set_bit(code, dev->keybit);
15         break;
16 
17     case EV_REL:
18         __set_bit(code, dev->relbit);
19         break;
20 
21     case EV_ABS:
22         input_alloc_absinfo(dev);
23         if (!dev->absinfo)
24             return;
25 
26         __set_bit(code, dev->absbit);
27         break;
28 
29     case EV_MSC:
30         __set_bit(code, dev->mscbit);
31         break;
32 
33     case EV_SW:
34         __set_bit(code, dev->swbit);
35         break;
36 
37     case EV_LED:
38         __set_bit(code, dev->ledbit);
39         break;
40 
41     case EV_SND:
42         __set_bit(code, dev->sndbit);
43         break;
44 
45     case EV_FF:
46         __set_bit(code, dev->ffbit);
47         break;
48 
49     case EV_PWR:
50         /* do nothing */
51         break;
52 
53     default:
54         pr_err("input_set_capability: unknown type %u (code %u)\n",
55                type, code);
56         dump_stack();
57         return;
58     }
59 
60     __set_bit(type, dev->evbit);
61 }

2.3.input设备注册

向核心层注册input设备,需要以上两步申请空间和填充能力完成之后才能call下面的函数进行注册。一个重要任务就是完成设备与事件驱动的匹配。

  1 /**
  2  * input_register_device - register device with input core
  3  * @dev: device to be registered
  4  *
  5  * This function registers device with input core. The device must be
  6  * allocated with input_allocate_device() and all it's capabilities
  7  * set up before registering.
  8  * If function fails the device must be freed with input_free_device().
  9  * Once device has been successfully registered it can be unregistered
 10  * with input_unregister_device(); input_free_device() should not be
 11  * called in this case.
 12  *
 13  * Note that this function is also used to register managed input devices
 14  * (ones allocated with devm_input_allocate_device()). Such managed input
 15  * devices need not be explicitly unregistered or freed, their tear down
 16  * is controlled by the devres infrastructure. It is also worth noting
 17  * that tear down of managed input devices is internally a 2-step process:
 18  * registered managed input device is first unregistered, but stays in
 19  * memory and can still handle input_event() calls (although events will
 20  * not be delivered anywhere). The freeing of managed input device will
 21  * happen later, when devres stack is unwound to the point where device
 22  * allocation was made.
 23  */
 24 int input_register_device(struct input_dev *dev)
 25 {
 26     static atomic_t input_no = ATOMIC_INIT(0);
 27     struct input_devres *devres = NULL;
 28     struct input_handler *handler;
 29     unsigned int packet_size;
 30     const char *path;
 31     int error;
 32 
 33     if (dev->devres_managed) {
 34         devres = devres_alloc(devm_input_device_unregister,
 35                       sizeof(struct input_devres), GFP_KERNEL);
 36         if (!devres)
 37             return -ENOMEM;
 38 
 39         devres->input = dev;
 40     }
 41 
 42     /* Every input device generates EV_SYN/SYN_REPORT events. */
 43     __set_bit(EV_SYN, dev->evbit);//通用的同步包
 44 
 45     /* KEY_RESERVED is not supposed to be transmitted to userspace. */
 46     __clear_bit(KEY_RESERVED, dev->keybit);
 47 
 48     /* Make sure that bitmasks not mentioned in dev->evbit are clean. */
 49     input_cleanse_bitmasks(dev);
 50 
 51     packet_size = input_estimate_events_per_packet(dev);
 52     if (dev->hint_events_per_packet < packet_size)
 53         dev->hint_events_per_packet = packet_size;
 54 
 55     dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2;
 56     dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL);
 57     if (!dev->vals) {
 58         error = -ENOMEM;
 59         goto err_devres_free;
 60     }
 61 
 62     /*
 63      * If delay and period are pre-set by the driver, then autorepeating
 64      * is handled by the driver itself and we don't do it in input.c.
 65      */
 66     init_timer(&dev->timer);//重复上报功能数据填充
 67     if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
 68         dev->timer.data = (long) dev;
 69         dev->timer.function = input_repeat_key;
 70         dev->rep[REP_DELAY] = 250;
 71         dev->rep[REP_PERIOD] = 33;
 72     }
 73     /*继续初始化结构体*/
 74     if (!dev->getkeycode)/*没有定义设备的getkeycode函数,就是用默认的键值获取函数*/
 75         dev->getkeycode = input_default_getkeycode;
 76 
 77     if (!dev->setkeycode)
 78         dev->setkeycode = input_default_setkeycode;
 79     /*设置设备名字,从input0开始,依次增大1*/
 80     dev_set_name(&dev->dev, "input%ld",
 81              (unsigned long) atomic_inc_return(&input_no) - 1);
 82     /*把该inputx设备加入到设备链表中,同时在sysfs的input文件夹系出现inputx以及我们初始化的name,phy等参数*/
 83     error = device_add(&dev->dev);
 84     if (error)
 85         goto err_free_vals;
 86     /*打印调试信息,安装设备会出现*/
 87     path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
 88     pr_info("%s as %s\n",
 89         dev->name ? dev->name : "Unspecified device",
 90         path ? path : "N/A");
 91     kfree(path);
 92 
 93     error = mutex_lock_interruptible(&input_mutex);
 94     if (error)
 95         goto err_device_del;
 96     /*把该设备加入到核心层维护的两个重要链表之一的设备链表input_dev_list中去*/
 97     list_add_tail(&dev->node, &input_dev_list);
 98     /*依次遍历另一条重要链表input_handler_list,看该设备能不能匹配到那个handler*/
 99     list_for_each_entry(handler, &input_handler_list, node)
100         input_attach_handler(dev, handler);/*匹配,和链接两者*/
101 
102     input_wakeup_procfs_readers();/*匹配到了,则更新proc文件系统*/
103 
104     mutex_unlock(&input_mutex);
105 
106     if (dev->devres_managed) {
107         dev_dbg(dev->dev.parent, "%s: registering %s with devres.\n",
108             __func__, dev_name(&dev->dev));
109         devres_add(dev->dev.parent, devres);
110     }
111     return 0;
112 
113 err_device_del:
114     device_del(&dev->dev);
115 err_free_vals:
116     kfree(dev->vals);
117     dev->vals = NULL;
118 err_devres_free:
119     devres_free(devres);
120     return error;
121 }

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

2.4 input_attach_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     /*匹配hander和dev*/
 6     id = input_match_device(handler, dev);
 7     if (!id)
 8         return -ENODEV;
 9     /*做具体的绑定handler和dev工作,由具体的事驱动层实现*/
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 }

 2.4.1 每一个事件驱动层在实现的时候都要实现一个struct input_device_id的表(数组),用来表明该事件驱动可以支持的设备。

定义位于:include\linux\mod_devicetable.h

 1 struct input_device_id {
 2 
 3     kernel_ulong_t flags;/*flags表明下面的四个要不要匹配,已经用相关宏定义好*/
 4 
 5     __u16 bustype;
 6     __u16 vendor;
 7     __u16 product;
 8     __u16 version;
 9 
10     kernel_ulong_t evbit[INPUT_DEVICE_ID_EV_MAX / BITS_PER_LONG + 1];
11     kernel_ulong_t keybit[INPUT_DEVICE_ID_KEY_MAX / BITS_PER_LONG + 1];
12     kernel_ulong_t relbit[INPUT_DEVICE_ID_REL_MAX / BITS_PER_LONG + 1];
13     kernel_ulong_t absbit[INPUT_DEVICE_ID_ABS_MAX / BITS_PER_LONG + 1];
14     kernel_ulong_t mscbit[INPUT_DEVICE_ID_MSC_MAX / BITS_PER_LONG + 1];
15     kernel_ulong_t ledbit[INPUT_DEVICE_ID_LED_MAX / BITS_PER_LONG + 1];
16     kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];
17     kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];
18     kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];
19 
20     kernel_ulong_t driver_info;
21 }

2.4.2 如果填充时在handler里面的在flags标志里面置位了下面的某一个,则匹配时就会检查响应的(总线类型,厂商,设备号,设备版本)。如果没有置位相应位,则表明匹配时不检查响应的标志位。

#define INPUT_DEVICE_ID_MATCH_BUS    1
#define INPUT_DEVICE_ID_MATCH_VENDOR    2
#define INPUT_DEVICE_ID_MATCH_PRODUCT    4
#define INPUT_DEVICE_ID_MATCH_VERSION    8

2.4.3同时也可以置位需要匹配类型

#define INPUT_DEVICE_ID_MATCH_EVBIT    0x0010
#define INPUT_DEVICE_ID_MATCH_KEYBIT    0x0020
#define INPUT_DEVICE_ID_MATCH_RELBIT    0x0040
#define INPUT_DEVICE_ID_MATCH_ABSBIT    0x0080
#define INPUT_DEVICE_ID_MATCH_MSCIT    0x0100
#define INPUT_DEVICE_ID_MATCH_LEDBIT    0x0200
#define INPUT_DEVICE_ID_MATCH_SNDBIT    0x0400
#define INPUT_DEVICE_ID_MATCH_FFBIT    0x0800
#define INPUT_DEVICE_ID_MATCH_SWBIT    0x1000

2.4.4 input_match_device

接下来真正的通过input_device_id来匹配

 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     /*input_device_id是一个数组,从前向后依次遍历id_table中和dev里面的id和xxbit中完全匹配的*/
 6     for (id = handler->id_table; id->flags || id->driver_info; id++) {
 7         /*正如前面描述的handler中id_table置位了相应标志位才做匹配检查*/
 8         if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
 9             if (id->bustype != dev->id.bustype)
10                 continue;
11 
12         if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
13             if (id->vendor != dev->id.vendor)
14                 continue;
15 
16         if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
17             if (id->product != dev->id.product)
18                 continue;
19 
20         if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
21             if (id->version != dev->id.version)
22                 continue;
23         /*同一id_table里面的flags匹配成功,才能MATCH_BIT匹配*/
24         if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX))
25             continue;
26 
27         if (!bitmap_subset(id->keybit, dev->keybit, KEY_MAX))
28             continue;
29 
30         if (!bitmap_subset(id->relbit, dev->relbit, REL_MAX))
31             continue;
32 
33         if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX))
34             continue;
35 
36         if (!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX))
37             continue;
38 
39         if (!bitmap_subset(id->ledbit, dev->ledbit, LED_MAX))
40             continue;
41 
42         if (!bitmap_subset(id->sndbit, dev->sndbit, SND_MAX))
43             continue;
44 
45         if (!bitmap_subset(id->ffbit, dev->ffbit, FF_MAX))
46             continue;
47 
48         if (!bitmap_subset(id->swbit, dev->swbit, SW_MAX))
49             continue;
50         /*看handler层有没有再定义macth匹配函数,如果没有,那到这里就是已经找到id了,否则,还要通过handler里面的match才能确定就是该id*/
51         if (!handler->match || handler->match(handler, dev))
52             return id;
53     }
54 
55     return NULL;
56 }

2.4.5input_handler中connect()函数

最后input_attach_handler调用handler->connect(handler, dev, id)函数。即到事件驱动层handler。 

3.事件驱动层input_handler

以evdev事件为例来讲解input_handler,定义:drivers/input/evdev.c中:

3.1evdev_init()

1 static int __init evdev_init(void)
2 {
3     return input_register_handler(&evdev_handler);
4 }

3.2.input_register_handler

input_handler的注册,定义位于:drivers\input\input.c

注册前,先要对input_handler结构体初始化

 1 static struct input_handler evdev_handler = {
 2     .event        = evdev_event,
 3     .events        = evdev_events,
 4     .connect    = evdev_connect,
 5     .disconnect    = evdev_disconnect,
 6     .legacy_minors    = true,
 7     .minor        = EVDEV_MINOR_BASE,
 8     .name        = "evdev",
 9     .id_table    = evdev_ids,
10 };

给input_device_id 赋值

1 static const struct input_device_id evdev_ids[] = {
2     { .driver_info = 1 },    /* Matches all devices */
3     { },            /* Terminating zero entry */
4 };

然后再初始化

 1 /**
 2  * input_register_handler - register a new input handler
 3  * @handler: handler to be registered
 4  *
 5  * This function registers a new input handler (interface) for input
 6  * devices in the system and attaches it to all input devices that
 7  * are compatible with the handler.
 8  */
 9 int input_register_handler(struct input_handler *handler)
10 {
11     struct input_dev *dev;
12     int error;
13 
14     error = mutex_lock_interruptible(&input_mutex);
15     if (error)
16         return error;
17 
18     INIT_LIST_HEAD(&handler->h_list);//初始化挂载input_hand的list
19 
20     list_add_tail(&handler->node, &input_handler_list);//将handler_node加到input_handler_list中
21     /*用当前的handler遍历核心层维护的两条重要链表之一的dev链表,并尝试匹配*/
22     list_for_each_entry(dev, &input_dev_list, node)
23         input_attach_handler(dev, handler);
24 
25     input_wakeup_procfs_readers();/*更新proce文件*/
26 
27     mutex_unlock(&input_mutex);
28     return 0;
29 }

匹配算法和device那边的完全一样(调用的同一个函数都)。这里要说明的是为什么即在注册handler的时候匹配一遍,又要在注册device的时候匹配一次。

这是因为,通常系统不能确定是handler先注册,还是dev先注册。假设只在注册dev的时候匹配handler(注册handler去掉匹配那几句代码  ),结果,devi先执行的,因为handler还没被注册,所以dev匹配失败。当注册handler的时候,因为没有了再次匹配,所以两者无法再接续到一块了。所以要在handler和dev注册都匹配一次,当然肯定是后面注册的才能匹配成。

 3.3 connect函数

然后再回到我们上面2.4.5中的遗留问题看看input_handler的connect函数.对于event handler来说,这个函数就是evdev_connect函数。

定义位于:drivers/input/evdev.c

 1 /*
 2  * Create new evdev device. Note that input core serializes calls
 3  * to connect and disconnect.
 4  */
 5 static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
 6              const struct input_device_id *id)
 7 {
 8     struct evdev *evdev;
 9     int minor;
10     int dev_no;
11     int error;
12 
13     minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);
14     if (minor < 0) {
15         error = minor;
16         pr_err("failed to reserve new minor: %d\n", error);
17         return error;
18     }
19 
20     evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
21     if (!evdev) {
22         error = -ENOMEM;
23         goto err_free_minor;
24     }
25 
26     INIT_LIST_HEAD(&evdev->client_list);
27     spin_lock_init(&evdev->client_lock);
28     mutex_init(&evdev->mutex);
29     init_waitqueue_head(&evdev->wait);
30     evdev->exist = true;
31 
32     dev_no = minor;
33     /* Normalize device number if it falls into legacy range */
34     if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS)
35         dev_no -= EVDEV_MINOR_BASE;
36     dev_set_name(&evdev->dev, "event%d", dev_no);
37 
38     /*初始化handle,每个evdev中都有一个handle*/
39     evdev->handle.dev = input_get_device(dev);/*这里就将handle的dev指针指向了input_dev*/
40     evdev->handle.name = dev_name(&evdev->dev);
41     evdev->handle.handler = handler;/*这里将handle的handler指向了当前的input_handler.注意本函数evdev_connect,可能是在在输入设备注册的时候
42     在input_register_device函数中调用input_attach_handler的时候调用;也可能是在输入设备的处理方法input_handler时在input_register_handler
43     函数中也会用到input_attach_handler函数,就会调用本函数.这里就很明显了,本函数就将input_handler和input_dev都放在input_handle中统一管理*/
44     evdev->handle.private = evdev;
45 
46     /*初始化evdev中的内嵌device*/
47     evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);
48     evdev->dev.class = &input_class;
49     evdev->dev.parent = &dev->dev;
50     evdev->dev.release = evdev_free;
51     device_initialize(&evdev->dev);
52 
53     /*注册handle,主要将handle链接到input_dev和handler的h_list链表中去*/
54     error = input_register_handle(&evdev->handle);
55     if (error)
56         goto err_free_evdev;
57 
58     cdev_init(&evdev->cdev, &evdev_fops);
59     evdev->cdev.kobj.parent = &evdev->dev.kobj;
60     error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
61     if (error)
62         goto err_unregister_handle;
63 
64     error = device_add(&evdev->dev);
65     if (error)
66         goto err_cleanup_evdev;
67 
68     return 0;
69 
70  err_cleanup_evdev:
71     evdev_cleanup(evdev);
72  err_unregister_handle:
73     input_unregister_handle(&evdev->handle);
74  err_free_evdev:
75     put_device(&evdev->dev);
76  err_free_minor:
77     input_free_minor(minor);
78     return error;
79 }
 1 struct evdev {//evdev结构体再配对成功的时候生成,由handler->connect生成
 2     int open;//打开引用计数
 3     struct input_handle handle;//关联的input_handle
 4     wait_queue_head_t wait;/等待队列
 5     struct evdev_client __rcu *grab;
 6     struct list_head client_list;//evdev_client链表,说明一个evdev设备可以处理多个evdev_client,可以有多个进程访问
 7     spinlock_t client_lock; /* protects client_list */
 8     struct mutex mutex;
 9     struct device dev;
10     struct cdev cdev;
11     bool exist;
12 };

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

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

3.4evdev_fops.

 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 };

3.4.1evdev_open

首先来看打开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);//打开evdev(如果将inpit_dev抽象为一个父对象,这其实就是一个子对象,或者说这个结构封装了一个具体的实例化的input_dev)
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 }

3.2evdev_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 }

3.3输入子系统核心层的接口input_open_device

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

见上2.3分析

3.4 怎么读一个event(x)设备文件的,即evdev_read()

 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 }

3.4.1 evdev_fetch_next_event

查看有没有数据,有的话返回1,且*event参数会把数据带出来一包

 1 static int evdev_fetch_next_event(struct evdev_client *client,
 2                   struct input_event *event)
 3 {
 4     int have_event;
 5 
 6     spin_lock_irq(&client->buffer_lock);
 7 
 8     have_event = client->packet_head != client->tail;/*头不等于尾说明有数据*/
 9     if (have_event) {
10         *event = client->buffer[client->tail++];/*读数据到*event,每次只能读一个包*/
11         client->tail &= client->bufsize - 1;/**读完一个包,指针移到下一个/
12     }
13 
14     spin_unlock_irq(&client->buffer_lock);
15 
16     return have_event;
17 }

3.5 evdev_event()

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

 1 /*
 2  * Pass incoming event to all connected clients.
 3  */
 4 static void evdev_event(struct input_handle *handle,
 5             unsigned int type, unsigned int code, int value)
 6 {
 7     struct input_value vals[] = { { type, code, value } };
 8 
 9     evdev_events(handle, vals, 1);
10 }
11 
12 /*
13  * Pass incoming events to all connected clients.
14  */
15 static void evdev_events(struct input_handle *handle,
16              const struct input_value *vals, unsigned int count)
17 {
18     struct evdev *evdev = handle->private;
19     struct evdev_client *client;
20     ktime_t time_mono, time_real;/*输入信息打包成标准格式*/
21      
22     time_mono = ktime_get();
23     time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
24 
25     rcu_read_lock();
26     /*如果该evdev有个专用的client,那么就将事件发给它如果该evdev不存在专用的client,那个就把该事件发送给evdev上client_list链表上所有的client*/
27     client = rcu_dereference(evdev->grab);
28 
29     if (client)
30         evdev_pass_values(client, vals, count, time_mono, time_real);
31     else
32         list_for_each_entry_rcu(client, &evdev->client_list, node)
33             evdev_pass_values(client, vals, count,
34                       time_mono, time_real);
35 
36     rcu_read_unlock();
37 }
38 
39 static void evdev_pass_values(struct evdev_client *client,
40             const struct input_value *vals, unsigned int count,
41             ktime_t mono, ktime_t real)
42 {
43     struct evdev *evdev = client->evdev;
44     const struct input_value *v;
45     struct input_event event;
46     bool wakeup = false;
47 
48     event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
49                       mono : real);
50 
51     /* Interrupts are disabled, just acquire the lock. */
52     spin_lock(&client->buffer_lock);
53 
54     for (v = vals; v != vals + count; v++) {
55         event.type = v->type;
56         event.code = v->code;
57         event.value = v->value;
58         __pass_event(client, &event);
59         if (v->type == EV_SYN && v->code == SYN_REPORT)
60             wakeup = true;
61     }
62 
63     spin_unlock(&client->buffer_lock);
64 
65     if (wakeup)
66         wake_up_interruptible(&evdev->wait);/*唤醒等到队列上的进程,注意这里是唤醒,connect中有定义,read中让他睡眠*/
67 }

3.5.1__pass_event

发送数据给client函数

 1 static void __pass_event(struct evdev_client *client,
 2              const struct input_event *event)
 3 {
 4     client->buffer[client->head++] = *event;
 5     client->head &= client->bufsize - 1;
 6 
 7     if (unlikely(client->head == client->tail)) {
 8         /*
 9          * This effectively "drops" all unconsumed events, leaving
10          * EV_SYN/SYN_DROPPED plus the newest event in the queue.
11          */
12         client->tail = (client->head - 2) & (client->bufsize - 1);
13         /*把键值写入client缓冲队列中,方便app层读,app层可能一次读多个输入信息*/
14         client->buffer[client->tail].time = event->time;
15         client->buffer[client->tail].type = EV_SYN;
16         client->buffer[client->tail].code = SYN_DROPPED;
17         client->buffer[client->tail].value = 0;
18 
19         client->packet_head = client->tail;
20     }
21 
22     if (event->type == EV_SYN && event->code == SYN_REPORT) {
23         client->packet_head = client->head;
24         kill_fasync(&client->fasync, SIGIO, POLL_IN);/*发送一个异步通知,通知该打开该client的应用程序,执行信号处理函数*/
25     }
26 }

参考博文:
https://blog.csdn.net/qq_16777851/java/article/details/81229209

https://www.cnblogs.com/jason-lu/p/3156411.html

posted @ 2020-05-23 12:41  Action_er  阅读(509)  评论(0编辑  收藏  举报