input 子系统(五) 事件上报及监听

2024-05-27 16:48

本文主要是介绍input 子系统(五) 事件上报及监听,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上报流程

事件的生产者 是 input 设备驱动 // 还可能是 用户空间通过write接口 上报的事件,这个可以忽略不计.
途径 input.c(input core),到达 handler,
然后由handler 提供给消费者.事件的生产者可以看做都是 设备驱动 ,但是消费者 不一定是 应用程序,可能是 kernel 其他模块,例如 key input 的消费者可以是 console subsystem

input subsystem1

input subsystem2

  • 驱动中的上报
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 // 这一句 调用 在 驱动文件里面,但是 实现在 include/linux/input.h 
--------------------- // 往下 为 input core 的实现(input.c)input_event(dev, EV_KEY, code, !!value); // 检查dev 是否支持该事件input_handle_event(dev, type, code, value);if (disposition & INPUT_PASS_TO_HANDLERS){ // 一般 report 都会进// 存储每一次上报事件}if (disposition & INPUT_FLUSH) { // 如果 sync 到来// input_pass_valuesinput_to_handlerlist_for_each_entry_rcu(handle, &dev->h_list, d_node) if (handle->open) { // 一定要注意,这个是handle ,还有一个 handler ,下两行会提到 ,在 open /dev/input/eventX 事,才会将 evdev对应的handle->open ++ ,该值初始化为0input_to_handler(handle, vals, count); // 执行一次 , 这一次 是 kbd 的 event
---------------------------------------//往下为 handler 的实现 evdev.c 或者 其他 handler}}上文代码重点讲解:list_for_each_entry_rcu(handle, &dev->h_list, d_node)这个会遍历 该 device 的 handle , 每匹配一次(该 device 和 handler) ,就会产生一个handle一般至少会有一个handle ,就是 device  和  evdev handler 匹配产生的handlerdemo 中产生了两次匹配1. device 和 evdev handler ,产生了handle 12. device 和 kbd handler , 产生了 handle 2然后会分别检查 handle->open1. handle 1 在 设备被监听之前, (handle->open)为假,在监听之后,(handle->open)被加1,为真2. handle 2 (handle->open) 为 真然后 调用 input_to_handler1. handle1 对应的 不会调用 input_to_handler2. handle2 对应的 会调用 input_to_handlerinput_to_handler(handle, vals, count); // 执行两次handler->events //如果handler实现了handler->events,则优先调用 handler->events ,否则,调用 handler->event
---------------------------------------//往下为 handler 的实现 evdev.cevdev_events // 这里分析 evdev handlerevdev_pass_valuesstatic 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);

监听流程

  • open

// 缓冲区 由 struct evdev_client *client; 管理 , struct evdev_client *client; 中有 buffer 成员// struct evdev_client *client; 由 rcu 链表管理.evdev_openunsigned int size = sizeof(struct evdev_client) + bufsize * sizeof(struct input_event); // 计算环形队列缓冲区大小client = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); // 申请缓冲区 // client 中 有 buffer 成员evdev_attach_client(evdev, client); // 将 client 串入链表list_add_tail_rcu(&client->node, &evdev->client_list);file->private_data = client;evdev_open_devicehandle->open ++;open 了之后,建立了缓冲区.建立缓冲区 ,64 字节这个buffer的作用是,上层OPEN了此节点,但是没有读取此节点的数据的时候,会保存到该缓冲区在open 之前,evdev handler 就没有接收到 事件,事件消亡在 input.c
  • poll

- 阻塞流程evdev_pollpoll_wait(file, &evdev->wait, wait);- 唤醒流程evdev_pass_valuesif (v->type == EV_SYN && v->code == SYN_REPORT)wakeup = true;if (wakeup) wake_up_interruptible(&evdev->wait); 
  • read

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)

这篇关于input 子系统(五) 事件上报及监听的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1008041

相关文章

SpringBoot整合Canal+RabbitMQ监听数据变更详解

《SpringBoot整合Canal+RabbitMQ监听数据变更详解》在现代分布式系统中,实时获取数据库的变更信息是一个常见的需求,本文将介绍SpringBoot如何通过整合Canal和Rabbit... 目录需求步骤环境搭建整合SpringBoot与Canal实现客户端Canal整合RabbitMQSp

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

Python中的异步:async 和 await以及操作中的事件循环、回调和异常

《Python中的异步:async和await以及操作中的事件循环、回调和异常》在现代编程中,异步操作在处理I/O密集型任务时,可以显著提高程序的性能和响应速度,Python提供了asyn... 目录引言什么是异步操作?python 中的异步编程基础async 和 await 关键字asyncio 模块理论

禁止平板,iPad长按弹出默认菜单事件

通过监控按下抬起时间差来禁止弹出事件,把以下代码写在要禁止的页面的页面加载事件里面即可     var date;document.addEventListener('touchstart', event => {date = new Date().getTime();});document.addEventListener('touchend', event => {if (new

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

【经验交流】修复系统事件查看器启动不能时出现的4201错误

方法1,取得『%SystemRoot%\LogFiles』文件夹和『%SystemRoot%\System32\wbem』文件夹的权限(包括这两个文件夹的所有子文件夹的权限),简单点说,就是使你当前的帐户拥有这两个文件夹以及它们的子文件夹的绝对控制权限。这是最简单的方法,不少老外说,这样一弄,倒是解决了问题。不过对我的系统,没用; 方法2,以不带网络的安全模式启动,运行命令行,输入“ne

BT天堂网站挂马事件后续:“大灰狼”远控木马分析及幕后真凶调查

9月初安全团队披露bt天堂网站挂马事件,该网站被利用IE神洞CVE-2014-6332挂马,如果用户没有打补丁或开启安全软件防护,电脑会自动下载执行大灰狼远控木马程序。 鉴于bt天堂电影下载网站访问量巨大,此次挂马事件受害者甚众,安全团队专门针对该木马进行严密监控,并对其幕后真凶进行了深入调查。 一、“大灰狼”的伪装 以下是10月30日一天内大灰狼远控的木马样本截图,可以看到该木马变种数量不

react笔记 8-19 事件对象、获取dom元素、双向绑定

1、事件对象event 通过事件的event对象获取它的dom元素 run=(event)=>{event.target.style="background:yellowgreen" //event的父级为他本身event.target.getAttribute("aid") //这样便获取到了它的自定义属性aid}render() {return (<div><h2>{

react笔记 8-18 事件 方法 定义方法 获取/改变数据 传值

1、定义方法并绑定 class News extends React.Component {constructor(props) {super(props)this.state = {msg:'home组件'}}run(){alert("我是一个run") //方法写在类中}render() {return (<div><h2>{this.state.msg}</h2><button onCli

【Qt】定时器事件

定时器事件 在之前学习QTimer中实现了定时器的功能,而在QTimer背后是QTimerEvent定时器事件进行支撑的。在QObject中提供了一个timeEvent这个函数。 startTimer启动定时器killTimer关闭定时器 Qt 中在进⾏窗⼝程序的处理过程中,经常要周期性的执⾏某些操作,或者制作⼀些动画效果,使⽤定 时器就可以实现。所谓定时器就是在间隔⼀定时间后,去执⾏某⼀