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

文章目录

    • 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.mfbz.cn/a/20338.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(转)雪花算法(SnowFlake)

简介 现在的服务基本是分布式、微服务形式的&#xff0c;而且大数据量也导致分库分表的产生&#xff0c;对于水平分表就需要保证表中 id 的全局唯一性。 对于 MySQL 而言&#xff0c;一个表中的主键 id 一般使用自增的方式&#xff0c;但是如果进行水平分表之后&#xff0c;多…

第八章结构型模式—装饰者模式

文章目录 装饰者模式解决的问题概念结构 案例使用装配者进行改进 使用场景JDK源码分析 静态代理和装饰者的区别 结构型模式描述如何将类或对象按某种布局组成更大的结构&#xff0c;有以下两种&#xff1a; 类结构型模式&#xff1a;采用继承机制来组织接口和类。对象结构型模式…

【Wi-Fi】802.11/802.11b/802.11g/802.11n/802.11a/802.11ac/802.11ax/802.11be

WiFi发展历史 IEEE 802.11 Protocol Release Date Frequency Band Bandwidth Max Throughput 802.11-1997 1997 2.4GHz 22MHz 2Mbps 802.11b 1999 2.4GHz 22MHz 11Mbps 802.11a 1999 5GHz 20MHz 54Mbps 802.11g 2003 2.4GHz 20MHz 54Mbps 802.11n (W…

计算机组成原理基础练习题第一章

有些计算机将一部分软件永恒地存于只读存储器中&#xff0c;称之为&#xff08;&#xff09; A.硬件    B.软件C.固件    D.辅助存储器输入、输出装置以及外界的辅助存储器称为&#xff08;&#xff09; A.操作系统    B.存储器 C.主机      D.外围设备完整的计算机系…

OpenCL编程指南-4.1OpenCL C编程

使用OpenCL C编写数据并行内核 OpenCL中的数据并行性表述为一个N维计算域&#xff0c;其中N1、2或3。N-D域定义了可以并行执行的工作项的总数。下面通过一个简单的例子来了解如何用OpenCL C编写一个数据并行内核&#xff0c;将两个浮点数数组相加。这个代码的串行版本求和时需…

力扣19删除链表的倒数第 N 个结点:思路分析+图文全解+方法总结(快慢指针法递归法)+深入思考

文章目录 第一部分&#xff1a;题目描述第二部分&#xff1a;代码实现2.1 快慢指针法2.2 递归 第一部分&#xff1a;题目描述 &#x1f3e0; 链接&#xff1a;19. 删除链表的倒数第 N 个结点 - 力扣&#xff08;LeetCode&#xff09; ⭐ 难度&#xff1a;中等 第二部分&#…

lol由于找不到vcruntine140_1.dll文件,vcruntime140_1.dll修复方法

家人们有没有遇到过打开游戏或者软件提示由于找不到vcruntime140_1.dll&#xff0c;无法继续执行此代码的情况&#xff0c;是不是不知道怎么修复呢&#xff1f;Vcruntime140_1.dll是一个Windows系统文件&#xff0c;它是Microsoft Visual C Redistributable for Visual Studio …

【嵌入式环境下linux内核及驱动学习笔记-(11-设备树)】

目录 1、设备树体系1.1 DTS /DTSI / DTC / DTB 2、基础语法2.1 节点语法2.1.1 通用名称建议 2.2 属性语法2.2.1 属性值 2.3 关于label2.4 节点的[unit-address] 与reg属性2.5 根节点 /2.6 标准属性compatible2.6.1 of_machine_is_compatible函数 2.7 地址编码2.7.1 标准属性#ad…

RabbitMQ养成记 (3.MQ的简单工作模式 和 Pub/sub 订阅模式)

上一篇是一个简单的helloworld。 我们直接发直接收 这种是最简单的。 下面我们再来接触更加复杂一点&#xff1a; 简单工作模式 work queues 工作队列模式&#xff1a; 这里注意 这里的消息 对两个消费者 c1 c2来说是竞争关系 而不是等份分发关系&#xff0c; 就像两个线程…

JVM 方法区

栈、堆、方法区的交互关系 线程共享角度: 新建对象分配: 方法区的理解 方法区(Method Area) 与 Java 堆一样&#xff0c;是各个线程共享的内存区域方法区在 JVM 启动的时候被创建&#xff0c;并且它的实际物理内存空间中和 Java 堆区一样都可以不连续的方法区的大小&#xf…

HNU-操作系统OS-实验Lab5

OS_Lab5_Experimental report 湖南大学信息科学与工程学院 计科 210X wolf &#xff08;学号 202108010XXX&#xff09; 实验目的 了解第一个用户进程创建过程了解系统调用框架的实现机制了解ucore如何实现系统调用sys_fork/sys_exec/sys_exit/sys_wait来进行进程管理 实验…

1099 Build A Binary Search Tree(超详细注解+38行代码)

分数 30 全屏浏览题目 作者 CHEN, Yue 单位 浙江大学 A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties: The left subtree of a node contains only nodes with keys less than the nodes key.The right subtree…

使用云服务器可以做什么?十大使用场景举例说明

使用阿里云服务器可以做什么&#xff1f;阿里云百科分享使用阿里云服务器常用的十大使用场景&#xff0c;说是十大场景实际上用途有很多&#xff0c;阿里云百科分享常见的云服务器使用场景&#xff0c;如本地搭建ChatGPT、个人网站或博客、运维测试、学习Linux、跑Python、小程…

详解c++STL—string组件

目录 一、string基本概念 1、本质 2、string和char * 区别&#xff1a; 3、特点&#xff1a; 二、string构造函数 1、构造函数原型 2、示例 三、string赋值操作 1、赋值的函数原型 2、示例 四、string字符串拼接 1、函数原型 2、示例 五、string查找和替换 1、功…

2023系统分析师---软件工程、系统规划高频错题

系统规划---成本效益分析 评价信息系统经济效益常用的方法主要有成本效益分析法,投入产出分析法和价值工程方法。盈亏平衡法常用于销售定价; 可行性分析 系统规划是信息系统生命周期的第一个阶段,其任务是对企业的环境、目标以及现有系统的状况进行初步调查,根据企业目标…

【利用AI让知识体系化】万字深入浅出Nginx

思维导图 文章目录 思维导图 第一部分&#xff1a;入门篇1.1 起步下载和安装Nginx启动NginxNginx配置文件Nginx命令行总结 1.2 Nginx的基本架构1.3 安装和配置Nginx1.4 Nginx的基本操作 第二部分&#xff1a;核心篇2.1 Nginx的请求处理2.2 Nginx的缓存机制2.3 Nginx的负载均衡机…

题解校验码—CRC循环校验码与海明校验码

码距 一个编码系统的码距是任意两个码字的最小距离。 例如个编码系统采用三位长度的二进制编码&#xff0c;若该系统有四种编码分别为&#xff1a;000&#xff0c;011&#xff0c;100&#xff0c;111&#xff0c;此编码系统中000与111的码距为3&#xff1b;011与000的码距为2…

Hard Patches Mining for Masked Image Modeling

摘要 蒙面图像建模&#xff08;MIM&#xff09;因其在学习可伸缩视觉表示方面的潜力而引起了广泛的研究关注。在典型的方法中&#xff0c;模型通常侧重于预测掩码补丁的特定内容&#xff0c;并且它们的性能与预定义的掩码策略高度相关。直观地说&#xff0c;这个过程可以被看作…

WiFi(Wireless Fidelity)基础(九)

目录 一、基本介绍&#xff08;Introduction&#xff09; 二、进化发展&#xff08;Evolution&#xff09; 三、PHY帧&#xff08;&#xff08;PHY Frame &#xff09; 四、MAC帧&#xff08;MAC Frame &#xff09; 五、协议&#xff08;Protocol&#xff09; 六、安全&#x…

【GAMES101】作业2学习总结

本系列博客为记录笔者在学习GAMES101课程时遇到的问题与思考。 GAMES101&#xff1a;课程官网GAMES101&#xff1a;B站视频GAMES101&#xff1a;相关文件下载(百度网盘) 一、基础题 本次作业的目的是为了让我们熟悉三角形栅格化的相关操作&#xff0c;通过Assignment2.pdf可以…