上报流程
事件的生产者 是 input 设备驱动
途径 input.c(input core),到达 handler,
然后由handler 提供给消费者.
事件的生产者可以看做都是 设备驱动 ,但是消费者 不一定是 应用程序,可能是 kernel 其他模块,例如 key input 的消费者可以是 console subsystem


input_report_key(button_dev, KEY_POWER,1);
input_report_key(button_dev, KEY_POWER,0);
input_sync(button_dev);
evdev 监听之前 和 监听之后 ,上报流程不一样, 区别 在 if (handle->open)
监听之前, (handle->open) 为 假,不会传送到 handler
监听之后, (handle->open) 为 真, 会传送到 handler
input_report_key
---------------------
input_event(dev, EV_KEY, code, !!value);
input_handle_event(dev, type, code, value);
if (disposition & INPUT_PASS_TO_HANDLERS){
}
if (disposition & INPUT_FLUSH) {
input_pass_values
input_to_handler
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
if (handle->open) {
input_to_handler(handle, vals, count);
---------------------------------------
}
}
上文代码重点讲解:
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
这个会遍历 该 device 的 handle , 每匹配一次(该 device 和 handler) ,就会产生一个handle
一般至少会有一个handle ,就是 device 和 evdev handler 匹配产生的handler
demo 中产生了两次匹配
1. device 和 evdev handler ,产生了handle 1
2. device 和 kbd handler , 产生了 handle 2
然后会分别检查 handle->open
1. handle 1 在 设备被监听之前, (handle->open)为假,在监听之后,(handle->open)被加1,为真
2. handle 2 (handle->open) 为 真
然后 调用 input_to_handler
1. handle1 对应的 不会调用 input_to_handler
2. handle2 对应的 会调用 input_to_handler
input_to_handler(handle, vals, count);
handler->events
---------------------------------------
evdev_events
evdev_pass_values
static void __pass_event(struct evdev_client *client,const struct input_event *event)
client->tail = (client->head - 2) & (client->bufsize - 1);
client->buffer[client->tail].time = event->time;
client->buffer[client->tail].type = EV_SYN;
client->buffer[client->tail].code = SYN_DROPPED;
client->buffer[client->tail].value = 0;
client->packet_head = client->tail;
if (wakeup)
wake_up_interruptible(&evdev->wait);
监听流程
evdev_open
unsigned int size = sizeof(struct evdev_client) + bufsize * sizeof(struct input_event);
client = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
evdev_attach_client(evdev, client);
list_add_tail_rcu(&client->node, &evdev->client_list);
file->private_data = client;
evdev_open_device
handle->open ++;
open 了之后,建立了缓冲区.建立缓冲区 ,64 字节
这个buffer的作用是,上层OPEN了此节点,但是没有读取此节点的数据的时候,会保存到该缓冲区
在open 之前,evdev handler 就没有接收到 事件,事件消亡在 input.c
- 阻塞流程
evdev_poll
poll_wait(file, &evdev->wait, wait);
- 唤醒流程
evdev_pass_values
if (v->type == EV_SYN && v->code == SYN_REPORT)
wakeup = true;
if (wakeup)
wake_up_interruptible(&evdev->wait);
static ssize_t evdev_read(struct file *file, char __user *buffer,size_t count, loff_t *ppos)
struct evdev *evdev = client->evdev;
evdev_fetch_next_event(client, &event)
*event = client->buffer[client->tail++];
input_event_to_user(buffer + read, &event)