版权声明:本文为博主原创文章,任何组织或者个人可以在任何媒介上发表或转载我的文章、图片等.且转载后必须注明出处和邮箱,博客地址(https://blog.csdn.net/u011011827),本人邮箱([email protected]) https://blog.csdn.net/u011011827/article/details/87891596
上报流程
事件的生产者 是 input 设备驱动
途径 input.c(input core),到达 handler,
然后由handler 提供给消费者.
- 驱动中的上报
input_report_key(button_dev, KEY_POWER,1);
input_report_key(button_dev, KEY_POWER,0);
input_sync(button_dev);
- 上报流程
//监听 /dev/input/eventX 之前
input_report_key
input_event(dev, EV_KEY, code, !!value); // 检查dev 是否支持该事件
input_handle_event(dev, type, code, value);
if (disposition & INPUT_PASS_TO_HANDLERS){
// 存储 sync及 之前的
}
if (disposition & INPUT_FLUSH) { // 如果 sync 到来
//
input_pass_values
input_to_handler
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
if (handle->open) { // 一定要注意,这个是handle ,还有一个 handler ,下两行会提到 ,在 open /dev/input/eventX 事,才会将 evdev对应的handle->open ++ .默认为0
input_to_handler(handle, vals, count); // 执行一次 , 这一次 是 kbd 的 event
handler->event // 第一次,没有下文 // 此时 handler->events 为 NULL
}
}
//监听 /dev/input/eventX 之后 //调用了evdev_open
input_report_key
input_event(dev, EV_KEY, code, !!value);
input_handle_event(dev, type, code, value);
if (disposition & INPUT_FLUSH) {
input_pass_values
input_to_handler
list_for_each_entry_rcu(handle, &dev->h_list, d_node) // rcu
if (handle->open) {
input_to_handler(handle, vals, count); // 执行两次
handler->event // 第一次 kbd // kbd_event
handler->events // 第二次 evdev evdev_events // 优先 events
evdev_events
evdev_pass_values
__pass_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;
}
}
监听流程
- open
evdev_open 做了什么
evdev_attach_client
list_add_tail_rcu(&client->node, &evdev->client_list); //rcu
handle->open ++;
open 了之后,建立了缓冲区.建立缓冲区 ,64 字节
这个buffer的作用是,上层OPEN了此节点,但是没有读取此节点的数据的时候,会保存到该缓冲区
在open 之前,事件就没有到 handler 中. 消亡在 input.c
- poll
- 阻塞流程
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);
- read
evdev_read