Linux内核(十七)Input 子系统详解 IV —— 配对的input设备与input事件处理器 input_register_handle

news2025/2/27 0:57:12

文章目录

    • input_handle结构体详解
    • 配对的input设备与input事件处理器实例
    • input核心层对驱动层和事件层之间的框架建立流程图


本文章中与input子系统相关的结构体可参考input子系统结构体解析
input函数路径:drivers/input/input.c

input_handle结构体详解

input_handle结构体属于核心层,代表一个配对的input设备与input事件处理器。

int input_register_handle(struct input_handle *handle)
{
    struct input_handler *handler = handle->handler;
    struct input_dev *dev = handle->dev;
    int error;
    
    /* 获取互斥锁 */
    error = mutex_lock_interruptible(&dev->mutex);
    if (error)
        return error;

    /* 将handle的d_node,链接到其相关的input_dev的h_list链表中  */
    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);
    
    /* 将handle的h_node,链接到其相关的input_handler的h_list链表中 */
    list_add_tail_rcu(&handle->h_node, &handler->h_list);

    if (handler->start)
        handler->start(handle);

    return 0;
}
EXPORT_SYMBOL(input_register_handle);

配对的input设备与input事件处理器实例

当 input设备注册Input_register_device 和 一个新的input事件注册input_register_handler 匹配上,都会调用回调函数handler->connect(handler, dev, id)

以事件处理器evdev为例:

/* drivers/input/evdev.c */
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;
     /* 获取次设备号,从evdev_table中找到一个未使用的最小的数组项,最大值32 */
     minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);
     if (minor < 0) {
          error = minor;
          pr_err("failed to reserve new minor: %d\n", error);
          return error;
     }
    /* 分配空间 */
     evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
     if (!evdev) {
          error = -ENOMEM;
          goto err_free_minor;
     }
     /* 初始化client_list链表头,代表多少应用读写这个设备 */
     INIT_LIST_HEAD(&evdev->client_list);    
     spin_lock_init(&evdev->client_lock);  /* 加锁 */ 
     mutex_init(&evdev->mutex);  /*  */
     init_waitqueue_head(&evdev->wait);  /* 初始化等待队列,当evdev没有数据可读时,就 在 该队列上睡眠 */
     evdev->exist = true;  /* 设备存在 */
    
     dev_no = minor;
    
     if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS)
          dev_no -= EVDEV_MINOR_BASE;
     dev_set_name(&evdev->dev, "event%d", dev_no);  /* 设置设备名为eventX */
    
     evdev->handle.dev = input_get_device(dev);  /* 获取设备 */
     evdev->handle.name = dev_name(&evdev->dev);  /* 设备名称 */
     evdev->handle.handler = handler;  /* handler绑定 */  
     evdev->handle.private = evdev;  /* evdev数据指向 */
    
     evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);  /* sysfs下的设备号 */
     evdev->dev.class = &input_class;  /* 将input_class作为设备类 */
     evdev->dev.parent = &dev->dev;  /* input_dev作为evdev的父设备 */
     evdev->dev.release = evdev_free;  /* 释放函数 */
     device_initialize(&evdev->dev);  /* 初始化设备 */
            /* 注册一个handle处理事件 */
     error = input_register_handle(&evdev->handle);    
     if (error)
          goto err_free_evdev;
    
     cdev_init(&evdev->cdev, &evdev_fops);  /* 字符设备初始化 */
    
     error = cdev_device_add(&evdev->cdev, &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;
}

(1)保存驱动设备名字,event0是表示input子系统,驱动名字就由event1、event2…递增
(2)保存驱动设备的主次设备号,其中主设备号INPUT_MAJOR=13,次设备号=EVSEV_MINOR_BASE+驱动程序本身设备号。
(3)会在/sys/class/input类下创建驱动设备event%d,比如键盘驱动event1
(4)最终进入input_register_handler()函数来注册handle。


input核心层对驱动层和事件层之间的框架建立流程图

在这里插入图片描述
input核心层对驱动层和事件层之间的框架建立流程图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/520652.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法之美:探究左右元素和的差值

本篇博客会讲解力扣“2574. 左右元素和的差值”的解题思路&#xff0c;这是题目链接。 先来审题&#xff1a; 以下是输出示例&#xff1a; 以下是提示&#xff1a; 本题的关键在于&#xff0c;“左和”和“右和”是如何变化的。下面我通过代码来演示。 一上来&#xff0c;…

唐朔飞计算机组成原理常见的寄存器(时不时就更新)

EINT中断允许触发器 如果是1代表开中断就是可以中断 如果0表示关中断 不能触发中断程序&#xff0c;1.响应中断的条件是当设备有请求并且 中断允许触发器为1的时候 时间是指令执行周期结束的时候。2.实现多重中断的条件是 中断允许触发器置为1并且 有更高的服务程序才能除法多重…

【数据结构】- 几个步骤教你认识并实现一个链表之带头(哨兵位)双向循环链表(上)

文章目录 前言&#x1f31f;一、带头双向循环链表&#x1f31f;二、带头双向循环链表结构图&#xff1a;&#x1f31f;三、带头双向循环链表代码实现&#xff1a;&#x1f30f;3.1头插&#xff1a;&#x1f4ab;3.1.1头插流程图&#x1f4ab;3.1.2 相较于无头单向非循环链表&am…

高边输出和低边输出

文章目录 高边和低边高边驱动&#xff08;HSD&#xff0c;High Side Drive&#xff09;和低边驱动&#xff08;LSD&#xff0c;Low Side Drive&#xff09;应用示例举例高/低边驱动芯片 按照开关闭合时开关输出的电压高低&#xff0c;可以分为高边输出和低边输出开关。 高边和低…

ubuntu 20.04 通过 sshfs 共享文件夹到 windows

功能需求 最近需要 让 ubuntu 共享文件夹&#xff0c;windows 来映射成磁盘或者共享目录的方式使用 windows 的文件夹可以通过 VMware Workstation Pro 虚拟机【共享文件夹】设置&#xff0c;轻松的实现 文件共享&#xff0c;不过这里的共享是 单向的&#xff0c;也就是 文件夹…

Windows服务器加固

文章目录 一、 账户安全要求二、 权限安全要求三、 通用安全管理四、 日志审计安全五、网络协议安全 一、 账户安全要求 1、 账户错误登录锁定 次数&#xff08;8&#xff09; 开始->运行->输入“gpedit.msc”打开本地组策略编辑器&#xff0c;浏览 路径&#xff1a;“…

快来学习SQL数据库,MySQL的保姆级安装,MySQL的入门使用以及DBeaver软件的安装

SQL数据库 无处不在的SQL&#xff0c;不管是何种开发语言&#xff0c;亦或是何种开发方向&#xff0c;SQL都是开发人员无法绕开的话题。除了一门趁手的编程语言外&#xff0c;SQL语言也是开发人员人人必备的开发技能。 数据库有三个层级&#xff1a;库——表——数据 市面上的…

路径规划算法:基于斑点鬣狗优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于斑点鬣狗优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于斑点鬣狗优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

第五十八章 Unity 发布PC平台

本章节我们介绍一些如何打包游戏到PC平台&#xff0c;这里重点介绍如何制作Windows操作系统下的游戏包。首先&#xff0c;我们创建一个“PcDemo”工程&#xff0c;然后简单布置一下场景内容&#xff0c;如下 想要打包发布Unity项目&#xff0c;我们可以在菜单栏选择“File”→ …

PHP 面向对象,构造函数,析构函数,继承,方法的重写,接口抽象类,static,final,this,parent,self的异同和作用

PHP 面向对象&#xff0c;构造函数&#xff0c;析构函数&#xff0c;继承&#xff0c;方法的重写&#xff0c;接口抽象类&#xff0c;static&#xff0c;final&#xff0c;this&#xff0c;parent&#xff0c;self的异同和作用 PHP 面向对象1.构造函数2.析构函数3.继承4.方法重…

520到了还有人不会表白吗——Python GUI实现爆火抖音的弹窗表白

文章目录 源码1.正常版本2.BT(变态)版本 代码实现(正常版本)结束语 最近抖音爆火的窗口表白 心中的女孩如果收到了&#xff0c;肯定会看着满屏幕的窗口感动不止&#xff0c;对你倾心 本文是正常版本的源码&#xff0c;BT版本的源码链接待审核 源码 1.正常版本 点击喜欢或者不喜…

【Linux】KMP算法

目录 主题 橙色 主题 好了&#xff0c;解释清楚这个表是什么之后&#xff0c;我们再来看如何使用这个表来加速字符串的查找&#xff0c;以及这样用的道理是什么。如图 1.12 所示&#xff0c;要在主字符串"ababababca"中查找模式字符串"abababca"。 如果在…

源码解读guava cache get方法的秘密

guava cache是谷歌开源的一种本地缓存&#xff0c;实现原理类似于ConcurrentHashMap&#xff0c;使用segments分段锁&#xff0c;保证线程安全&#xff0c;支持高并发场景。同时支持多种类型的缓存清理策略&#xff0c;包括基于容量的清理、基于时间的清理、基于引用的清理等。…

嵌入式系统中常见的摄像头接口

MIPI CSI&#xff1a;MIPI CSI&#xff08;Mobile Industry Processor Interface Camera Serial Interface&#xff09;是一种专用于手机和移动媒体设备的摄像头接口标准。它具有高速传输、低功耗和可靠性等优点&#xff0c;已经成为现代嵌入式摄像头的主要接口之一。 USB cam…

day31_JDBC

今日内容 零、 复习昨日 一、数据库连接池 二、反射 三、封装DBUtil 零、 复习昨日 三表关联 create table teacher ( tid int, tname varchar(10) ) insert into teacher values(1,老邱); insert into teacher values(2,老王);-- 三表关联 -- 查询学生以及班级信息 select * f…

FPGA实现Cordic算法求解arctan和sqr(x*2 + y* 2)

一. 简介 由于在项目中需要使用的MPU6050&#xff0c;进行姿态解算&#xff0c;计算中设计到**arctan 和 sqr(x2 y 2),**这两部分的计算&#xff0c;在了解了一番之后&#xff0c;发现Cordic算法可以很方便的一次性求出这两个这两部分的计算。另外也可以一次性求出sin和cos的…

MHA高可用配置及故障切换

单组mha 多组mmm mha &#xff08;master high availability&#xff09; mha解决mysql单点的问题 mysql故障切换的过程中最大程度上保证数据的一致性&#xff0c;一达到真正意义上的高可用 mha组成 mha node&#xff08;数据节点&#xff09; mha node 运行在每个mysql服…

数据库 SERVERLESS 与 RDS 产品逐步淘汰 和 云数据库的价值

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

HTML + CSS + JavaScript 实现注册页面信息验证 详细教程(表单验证)

>>> 本文介绍使用HTML CSS JavaScript 实现注册页面信息验证的详细方法。完整代码见文章末尾。 要求 创建一个注册页面&#xff0c;如下图。 然后再对注册信息进行判断&#xff0c;判断其是否符合要求。&#xff08;如&#xff1a;密码6-12位字符&#xff0c;不能…

Unity通过深度图做有交互效果的水泡沫

通过深度图做交互水泡沫 大家好&#xff0c;我是阿赵。 这里做一个有交互效果的水面&#xff0c;物体浸入水面时&#xff0c;会根据物体的形状&#xff0c;有一圈水泡沫的效果&#xff0c;并且水泡沫的形状会跟随这物体变化。由于想做得稍微完整一点&#xff0c;又不想其他效果…