我是靠谱客的博主 狂野灰狼,这篇文章主要介绍input输入子系统框架,现在分享给大家,希望可以做个参考。

http://blog.csdn.net/myarrow/article/details/7098504

http://blog.csdn.net/sdvch/article/details/44619789

网上的例子很多,如上。

数据结构


复制代码
1
2
3
static LIST_HEAD(input_dev_list); static LIST_HEAD(input_handler_list);


复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct input_dev { const char *name; const char *phys; const char *uniq; struct input_id id; ........ spinlock_t event_lock; struct mutex mutex; unsigned int users; bool going_away; struct device dev; struct list_head h_list; struct list_head node; unsigned int num_vals; unsigned int max_vals; struct input_value *vals; bool devres_managed; };

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct input_handler { void *private; void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); void (*events)(struct input_handle *handle, const struct input_value *vals, unsigned int count); bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value); bool (*match)(struct input_handler *handler, struct input_dev *dev); int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id); void (*disconnect)(struct input_handle *handle); void (*start)(struct input_handle *handle); bool legacy_minors; int minor; const char *name; const struct input_device_id *id_table; struct list_head h_list; struct list_head node; };


匹配,connect成功后,会把handler和input_dev放进来。并且把h_node和d_node分别放到handler和input_dev的h_list链表中。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
struct input_handle { void *private; int open; const char *name; struct input_dev *dev; struct input_handler *handler; struct list_head d_node; struct list_head h_node; };
复制代码
1
evdev.c注册
复制代码
1
2
3
4
5
6
7
8
9
10
static struct input_handler evdev_handler = { .event = evdev_event, .events = evdev_events, .connect = evdev_connect, .disconnect = evdev_disconnect, .legacy_minors = true, .minor = EVDEV_MINOR_BASE, .name = "evdev", .id_table = evdev_ids, };



input.c是核心层,向设备驱动层和事件驱动层提供接口,我们需要实现的是设备驱动层,通常会调用input_event,input_sync之类的函数,事件驱动层就是evdev和kbd之类的。   

当系统启动时候,设备驱动程序会调用input_register_device,并执行list_add_tail(&dev->node, &input_dev_list);将此设备假如到链表中。并去input_handler_list中查找此dev对应的handler,比如dev对应acc_gyro,handler对应evdev,如果对应上了,就进行connect,在connect函数中将创建evdev,并将匹配上的handler和input_dev,分别填充到结构体中。并注册input_register_handle。此函数的作用是将已经创建的handle结构体中的d_node 和 h_node分别加入自己的成员变量input_dev->h_list和hander_dev->h_list中。这个有什么作用,搜索下d_node,在函数input_pass_values中,会遍历所有的dev->h_list,中的d_node,找到对应的handle,handle在找到对应的handler,handler在找到对应的client,client对应的eventX节点。这个也是数据传输的过程。基本是connect时候是绑定,发送数据时候找到对应的client。

handle对应的是eventX,handler对应的是kdb或者evdev,client对应的是event_number,input_dev对应得是acc_gyro.另外分层的设计一般都会设计到函数的注册和查询匹配。

这是发送数据的代码片段,遍历input_dev的链表,如果设备在上层已经打开就开始传输数据。

复制代码
1
2
3
4
5
list_for_each_entry_rcu(handle, &dev->h_list, d_node) if (handle->open){ count = input_to_handler(handle, vals, count); } }


函数

设备驱动注册。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
int input_register_device(struct input_dev *dev) { struct input_devres *devres = NULL; struct input_handler *handler; unsigned int packet_size; const char *path; int error; if (dev->devres_managed) { devres = devres_alloc(devm_input_device_unregister, sizeof(struct input_devres), GFP_KERNEL); if (!devres) return -ENOMEM; devres->input = dev; } /* Every input device generates EV_SYN/SYN_REPORT events. */ __set_bit(EV_SYN, dev->evbit); /* KEY_RESERVED is not supposed to be transmitted to userspace. */ __clear_bit(KEY_RESERVED, dev->keybit); /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ input_cleanse_bitmasks(dev); packet_size = input_estimate_events_per_packet(dev); if (dev->hint_events_per_packet < packet_size) dev->hint_events_per_packet = packet_size; dev->max_vals = dev->hint_events_per_packet + 2; dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); if (!dev->vals) { error = -ENOMEM; goto err_devres_free; } /* * 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. */ 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; } if (!dev->getkeycode) dev->getkeycode = input_default_getkeycode; if (!dev->setkeycode) dev->setkeycode = input_default_setkeycode; error = device_add(&dev->dev); if (error) goto err_free_vals; path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); pr_info("%s as %sn", dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); kfree(path); error = mutex_lock_interruptible(&input_mutex); if (error) goto err_device_del; list_add_tail(&dev->node, &input_dev_list); printk("========dev->node=%pn",&dev->node); list_for_each_entry(handler, &input_handler_list, node) input_attach_handler(dev, handler); input_wakeup_procfs_readers(); mutex_unlock(&input_mutex); if (dev->devres_managed) { dev_dbg(dev->dev.parent, "%s: registering %s with devres.n", __func__, dev_name(&dev->dev)); devres_add(dev->dev.parent, devres); } return 0; err_device_del: device_del(&dev->dev); err_free_vals: kfree(dev->vals); dev->vals = NULL; err_devres_free: devres_free(devres); return error; } EXPORT_SYMBOL(input_register_device);
复制代码
1
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* * input_register_handler - register a new input handler * @handler: handler to be registered * * This function registers a new input handler (interface) for input * devices in the system and attaches it to all input devices that * are compatible with the handler. */ int input_register_handler(struct input_handler *handler) { struct input_dev *dev; int error; error = mutex_lock_interruptible(&input_mutex); if (error) return error; INIT_LIST_HEAD(&handler->h_list); list_add_tail(&handler->node, &input_handler_list); printk("========handler->node=%pn",&handler->node); list_for_each_entry(dev, &input_dev_list, node) input_attach_handler(dev, handler); input_wakeup_procfs_readers(); mutex_unlock(&input_mutex); return 0; }

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
static int evdev_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { struct evdev *evdev; int minor; int dev_no; int error; minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true); if (minor < 0) { error = minor; pr_err("failed to reserve new minor: %dn", error); return error; } evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); if (!evdev) { error = -ENOMEM; goto err_free_minor; } INIT_LIST_HEAD(&evdev->client_list); spin_lock_init(&evdev->client_lock); mutex_init(&evdev->mutex); init_waitqueue_head(&evdev->wait); evdev->exist = true; dev_no = minor; /* Normalize device number if it falls into legacy range */ if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS) dev_no -= EVDEV_MINOR_BASE; dev_set_name(&evdev->dev, "event%d", dev_no); evdev->handle.dev = input_get_device(dev); evdev->handle.name = dev_name(&evdev->dev); evdev->handle.handler = handler; evdev->handle.private = evdev; evdev->dev.devt = MKDEV(INPUT_MAJOR, minor); evdev->dev.class = &input_class; evdev->dev.parent = &dev->dev; evdev->dev.release = evdev_free; device_initialize(&evdev->dev); printk("========evdev->handle.handler=%s,evdev->handle.dev=%sn",evdev->handle.handler->name,evdev->handle.dev->name); error = input_register_handle(&evdev->handle); if (error) goto err_free_evdev; cdev_init(&evdev->cdev, &evdev_fops); evdev->cdev.kobj.parent = &evdev->dev.kobj; error = cdev_add(&evdev->cdev, evdev->dev.devt, 1); if (error) goto err_unregister_handle; error = device_add(&evdev->dev); if (error) goto err_cleanup_evdev; return 0; err_cleanup_evdev: evdev_cleanup(evdev); err_unregister_handle: input_unregister_handle(&evdev->handle); err_free_evdev: put_device(&evdev->dev); err_free_minor: input_free_minor(minor); return error; }
connect之后把对应的handler和input_dev放在一起。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
int input_register_handle(struct input_handle *handle) { struct input_handler *handler = handle->handler; struct input_dev *dev = handle->dev; int error; printk("============input_register_handle=%sn", handle->name); /* * We take dev->mutex here to prevent race with * input_release_device(). */ error = mutex_lock_interruptible(&dev->mutex); if (error) return error; /* * Filters go to the head of the list, normal handlers * to the tail. */ if (handler->filter) list_add_rcu(&handle->d_node, &dev->h_list); else list_add_tail_rcu(&handle->d_node, &dev->h_list); mutex_unlock(&dev->mutex); /* * Since we are supposed to be called from ->connect() * which is mutually exclusive with ->disconnect() * we can't be racing with input_unregister_handle() * and so separate lock is not needed here. */ list_add_tail_rcu(&handle->h_node, &handler->h_list); if (handler->start) handler->start(handle); return 0; }
evdev中传输数据的代码。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
static void evdev_events(struct input_handle *handle, const struct input_value *vals, unsigned int count) { struct evdev *evdev = handle->private; struct evdev_client *client; ktime_t time_mono, time_real; time_mono = ktime_get(); time_real = ktime_mono_to_real(time_mono); rcu_read_lock(); client = rcu_dereference(evdev->grab); printk("=====%s client=%pn",__func__,client); if (client) evdev_pass_values(client, vals, count, time_mono, time_real); else list_for_each_entry_rcu(client, &evdev->client_list, node) evdev_pass_values(client, vals, count, time_mono, time_real); rcu_read_unlock(); }


系统在初始化的时候,会分别做匹配,evdev的初始化函数是module_init,此时调用input_register_handler,input.c的启动高于module_init,它是调用subsys_initcall(input_init);

并创建字符设备。设备驱动和evdev驱动都会注册,并且查找对应链表的匹配成功的项。比如key的input_dev对应kdb和event0,打开并读取 对应的event0,之后,上报到对应event0,而不是kdb。


对应Log

复制代码
1
2
3
4
5
[ 2.692105] ========handler->node=c0c3cb6c name=evdev [ 2.696292] msm_otg 78d9000.usb: phy_reset: success [ 2.701052] ========evdev->handle.handler=evdev,evdev->handle.dev=qpnp_pon [ 2.707886] ============input_register_handle=event0----------------------------》connect OK,注册成功。 [ 2.712915] input: Try to attach handler evdev to device input0, error: 0
复制代码
1
2
3
[ 2.719607] ========evdev->handle.handler=evdev,evdev->handle.dev=i2c_key [ 2.726366] ============input_register_handle=event1 [ 2.731381] input: Try to attach handler evdev to device input1, error: 0
复制代码
1
2
3
[ 2.738091] ========evdev->handle.handler=evdev,evdev->handle.dev=tpl5010 [ 2.744855] ============input_register_handle=event2 [ 2.749870] input: Try to attach handler evdev to device input2, error: 0
复制代码
1
2
3
[ 2.756581] ========evdev->handle.handler=evdev,evdev->handle.dev=hs_uart [ 2.763310] ============input_register_handle=event3 [ 2.768403] input: Try to attach handler evdev to device input3, error: 0
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[ 2.775147] bmi160 4-0068: BMI160 i2c function probe entrance [ 2.781354] bmi160 4-0068: Regulator client_data->vdd enable success! [ 2.787736] (NULL device *): Bosch Sensortec Device detected, HW IC name: BMI160C3 [ 2.795062] input: bmi160_accel as /devices/virtual/input/input4 [ 2.800725] ========dev->node=ce5523a8 name = bmi160_accel [ 2.806368] ========evdev->handle.handler=evdev,evdev->handle.dev=bmi160_accel [ 2.813519] ============input_register_handle=event4 [ 2.819260] input: Try to attach handler evdev to device input4, error: 0 [ 2.825173] bmi160 4-0068: bmi160 input_accel register successfully! [ 2.831686] input: bmi160_gyro as /devices/virtual/input/input5 [ 2.837399] ========dev->node=ce552ba8 name = bmi160_gyro [ 2.842748] ========evdev->handle.handler=evdev,evdev->handle.dev=bmi160_gyro [ 2.849892] ============input_register_handle=event5 [ 2.854961] input: Try to attach handler evdev to device input5, error: 0 [ 2.861578] bmi160 4-0068: bmi160 input register successfully, bmi160_gyro! [ 2.869323] dev->platform_data = NULL



这是sensor驱动中调用input_event和input_sync,打印出来的log。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 bmi_signification_motion_interrupt_handle [ 5675.678310] ======1input_handle_event  disposition=3 dev->vals=ce549680, dev->num_vals=0 [ 5675.686366] ======2input_handle_event  disposition=3 dev->vals=ce549680, dev->num_vals=1 [ 5675.695120] ======1input_handle_event  disposition=9 dev->vals=ce549680, dev->num_vals=1 [ 5675.702511] ======2input_handle_event  disposition=9 dev->vals=ce549680, dev->num_vals=2 [ 5675.710586] enter input_pass_values count =2 [ 5675.714837] ========2 input_to_handler=2 [ 5675.718742] ========1 input_to_handler=2 [ 5675.722656] =====evdev_events client=  (null) [ 5675.726984] ========evdev_pass_values [ 5675.730638] ========evdev_pass_values val=ce549680 count=2 [ 5675.736105] ====__pass_event,head=1,tail=0,packet_head=0,event4-1552/n====__pass_event,head=2,tail=0,packet_head=0,event4-1552/nenter the SYN [ 5675.748792] =====2 handle->name=event4 [ 5675.752504] ============= last  inputdev->name=bmi160_accel [ 5675.758362] ======evdev_fetch_next_event [ 5675.761977] =====!client->packet_head=2,client->tail=1,client->head=2 [ 5675.770859] ======evdev_fetch_next_event [ 5675.773753] =====!client->packet_head=2,client->tail=2,client->head //循环buffer,一次事件传输完。

最后

以上就是狂野灰狼最近收集整理的关于input输入子系统框架的全部内容,更多相关input输入子系统框架内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(79)

评论列表共有 0 条评论

立即
投稿
返回
顶部