linux驱动之input子系统简述

文章目录

  • 一、什么是input子系统
  • 二、内核代码
  • 三、代码分析

一、什么是input子系统

Input驱动程序是linux输入设备的驱动程序,我们最常见的就按键,触摸,插拔耳机这些。其中事件设备驱动程序是目前通用的驱动程序,可支持键盘、鼠标、触摸屏等多种输入设备。
Linux input 子系统将一个输入设备的输入过程分成了设备驱动(input device driver)和事件驱动(input event driver)两个层。前者负责从底层硬件采集数据;后者负责与用户程序接口,将采集到的数据分发给不同的用户接口。
通过这样的设计,将千差万别的设备统一到了为数不多的几种驱动接口上。同一种事件驱动可以用来处理多个同类设备;同一个设备也可以和多种事件驱动相衔接。而事件驱动和设备驱动则由输入核心层进行连接,匹配。

在这里插入图片描述这个是网上赵的一张图,写的还是很详细的。

二、内核代码

位置:

相关代码位置在: Linuxdrivers/input这个目录 

常见的驱动有这些

tony@lc:~/sdcard/imx6ull-pro/Linux-4.9.88/drivers/input$ ls
apm-power.c  ff-memless.c    input-leds.c     joydev.c         misc             tablet
built-in.o   gameport        input-leds.o     joystick         mouse            touchscreen
evbug.c      input.c         input-mt.c       Kconfig          mousedev.c
evdev.c      input-compat.c  input-mt.o       keyboard         mousedev.o
evdev.o      input-compat.h  input.o          Makefile         rmi4
ff-core.c    input-compat.o  input-polldev.c  matrix-keymap.c  serio
ff-core.o    input-core.o    input-polldev.o  matrix-keymap.o  sparse-keymap.c

三、代码分析

我们主要关注三个函数:
input_dev 表示一个输入设备,包含输入设备的一些相关信息;
内核中通过这个结构体来填充输入设备,填充后通过input_register_device来注册就好了
一旦我们注册成功,我们就可以在对应的目录下看到
所有的输入设备都存在这个input_dev中。

struct input_dev {const char *name;const char *phys;const char *uniq;struct input_id id;unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];unsigned long evbit[BITS_TO_LONGS(EV_CNT)];unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];unsigned long relbit[BITS_TO_LONGS(REL_CNT)];unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];unsigned long swbit[BITS_TO_LONGS(SW_CNT)];unsigned int hint_events_per_packet;unsigned int keycodemax;unsigned int keycodesize;void *keycode;int (*setkeycode)(struct input_dev *dev,const struct input_keymap_entry *ke,unsigned int *old_keycode);int (*getkeycode)(struct input_dev *dev,struct input_keymap_entry *ke);struct ff_device *ff;unsigned int repeat_key;struct timer_list timer;int rep[REP_CNT];struct input_mt *mt;struct input_absinfo *absinfo;unsigned long key[BITS_TO_LONGS(KEY_CNT)];unsigned long led[BITS_TO_LONGS(LED_CNT)];unsigned long snd[BITS_TO_LONGS(SND_CNT)];unsigned long sw[BITS_TO_LONGS(SW_CNT)];int (*open)(struct input_dev *dev);void (*close)(struct input_dev *dev);int (*flush)(struct input_dev *dev, struct file *file);int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);struct input_handle __rcu *grab;spinlock_t event_lock;struct mutex mutex;unsigned int users;bool going_away;struct device dev;struct list_head	h_list;struct list_head	node;unsigned int num_vals;unsigned int max_vals;struct input_value *vals;bool devres_managed;
};

可以通过下面的命令进行查看现在有哪些事件

# ls sys/class/input/
event0  event1  event2  input0  input1  input2  mice

input_handler 这个是代表的处理类型 比如我们的耳机插入和我们触摸屏幕就是不同的类型
一个input_handler 可以处理多个input_dev 比我们的音量加减,屏幕亮灭的事件处理都是可以通过同一个handler来处理
struct input_handler {

	void *private;void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);void (*events)(struct input_handle *handle,const struct input_value *vals, unsigned int count);bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);bool (*match)(struct input_handler *handler, struct input_dev *dev);int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);void (*disconnect)(struct input_handle *handle);void (*start)(struct input_handle *handle);bool legacy_minors;int minor;const char *name;const struct input_device_id *id_table;struct list_head	h_list;struct list_head	node;
};

input_handle 因为一个 input_handler 可以处理多个event ,如果不进行管理的话,就会很乱,所以我们需要一个管理者来管理,所以抽象一个input_handle 来把 input_handler和input_dev联系起来,就好像input_dev是横坐标 input_handler 是纵坐标, input_handle就是交点,每一个交点都是一个input节点。

struct input_handle {void *private;int open;const char *name;struct input_dev *dev;struct input_handler *handler;struct list_head	d_node;struct list_head	h_node;
};

一个按键驱动的大概步骤是这样的 :

 
struct input_dev *inputdev; /* input 结构体变量 *//* 驱动入口函数 */static int __init xxx_init(void)
{......inputdev = input_allocate_device(); /* 申请 input_dev */inputdev->name = "test_inputdev"; /* 设置 input_dev 名字 *//*********第一种设置事件和事件值的方法***********/__set_bit(EV_KEY, inputdev->evbit); /* 设置产生按键事件 */__set_bit(EV_REP, inputdev->evbit); /* 重复事件 */__set_bit(KEY_0, inputdev->keybit); /*设置产生哪些按键值 *//************************************************//*********第二种设置事件和事件值的方法***********/keyinputdev.inputdev->evbit[0] = BIT_MASK(EV_KEY) |BIT_MASK(EV_REP);keyinputdev.inputdev->keybit[BIT_WORD(KEY_0)] |=BIT_MASK(KEY_0);/************************************************//*********第三种设置事件和事件值的方法***********/keyinputdev.inputdev->evbit[0] = BIT_MASK(EV_KEY) |BIT_MASK(EV_REP);input_set_capability(keyinputdev.inputdev, EV_KEY, KEY_0);/************************************************//* 注册 input_dev */input_register_device(inputdev);......return 0;
}/* 驱动出口函数 */
static void __exit xxx_exit(void)
{input_unregister_device(inputdev); /* 注销 input_dev */input_free_device(inputdev); /* 删除 input_dev */
}

我们在ui界面上为了可以更加快速的反馈时间,就需要在内核中将事件上报上去,这样我们UI就可以及时的进行处理。
上报事件就是通过 input_event 上报event 事件。

我们获取健值这些,其实也是通过open wirte函数这些去获取的。

参考博客:input子系统

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

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

相关文章

Go基础语法:list

概述 container/list包实现了基本的双向链表功能,包括元素的插入、删除、移动功能 链表元素 链表中元素定义如下: type Element struct {Value interface{} }func (e *Element) Next() *Element func (e *Element) Prev() *Element通过Value属性来获…

C++ -- IO流

目录 C语言的输入与输出 CIO流 C标准IO流 C文件IO流 文件常见的打开方式如下 以二进制的形式操作文件 以文本的形式操作文件 读写结构体 stringstream的简单介绍 C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 scanf(): 从标准输…

零基础学空手道_3_空手道的站姿(上)

欢迎回来一起学习刚柔流空手道。 讲一些比较严肃的内容,就是礼仪和站姿。 空手道一开始不是要学习怎么打,而是要学习怎么去尊重别人和不打。所以礼仪很重要。 一切事情都是以礼仪开始,以礼仪结束。这叫以理始以理终。 空手道也是这样&#xf…

MySQL - DML数据增删改

功能介绍: DML(Data Manipulation Language)数据操作语言,用来对数据库中表的数据记录进 行增、删、改操作。 添加数据(INSERT) 基本语法:insert into 表名(字段列表) values (值列表); …

HTML计时事件(JavaScript)网页电子钟+网页计时器

setTimeout("函数","未来指定毫秒后调用函数"); clearTimeout(setTimeout("函数","未来指定毫秒后调用函数")); <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title>…

【问题解决】Android Studio 无法连接手机(荣耀90)无法识别手机usb

问题描述&#xff1a; 使用AS调试的时候遇到一个问题&#xff0c;由于是重装后的电脑&#xff0c;什么都没配置&#xff0c;但是两个旧手机都在安装SDK tools里的Google usb driver后直接连上AS&#xff0c;而我的新手机却死活连不上&#xff0c;查了一下午&#xff0c;啥方法都…

前端架构师之09_JavaScript_BOM

1 什么是 BOM 对象 BOM&#xff1a;Brower Object Model&#xff0c;指的是浏览器对象模型。 BOM 用来操作浏览器窗口及窗口上的控件&#xff0c;实现用户和页面的动态交互。 浏览器对象&#xff1a;浏览器提供的一系列内置对象的统称。 BOM 浏览器对象模型&#xff1a;各内…

Redis原理(一):Redis数据结构(上)

文章目录 1、 Redis数据结构-动态字符串2、 Redis数据结构-intset3、 Redis数据结构-Dict4、 Redis数据结构-ZipList5、 Redis数据结构-ZipList的连锁更新问题6、 Redis数据结构-QuickList1、 Redis数据结构-动态字符串 我们都知道Redis中保存的Key是字符串,value往往是字符串…

MongoDB(二)基础操作 创建、删除,查询等

mongodb有一个特点&#xff0c;如果某个库&#xff0c;库下面没数据&#xff08;mongodb成集合&#xff09;&#xff0c;该库等于不存在的 mongodb只要创建一个库&#xff0c;在库下写入数据&#xff0c;该库才会生成 mongoshe [-hhost -pxxx] 创建数据库 use 数据库名 # 如果…

Android - Monkey 测试应用出现Crash报错IllegalStateException

问题描述 平时使用Lottie动画都是正常的&#xff0c;没出过这个crash问题&#xff0c;看下的报错信息&#xff0c;代码中文件夹也设置了&#xff0c;没看出来问题。 AndroidRuntime: java.lang.IllegalStateException: You must set an images folder before loading an imag…

c语言常见字符函数、内存函数(详讲)

前言&#xff1a; 其实在c语言当中是没有字符串这一概念的&#xff0c;不像c里面有string类型用来存放字符串。在c语言中我们只能把字符串放在字符串常量以及字符数组中。 1.常见字符串函数 1.1strlen size_t strlen ( const char * str );作用&#xff1a;用来求字符串中 …

C语言 L1-016 查验身份证

L1-016 查验身份证 一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下&#xff1a; 首先对前17位数字加权求和&#xff0c;权重分配为&#xff1a;{7&#xff0c;9&#xff0c;10&#xff0c;5&#xff0c;8&#xff0c;4&#xff0c…

【MySQL】基础实战篇(1)—数据库与数据表的操作

创建管理数据库创建数据库查看与选择数据库修改数据库删除数据库 创建管理数据表创建数据表查看数据修改数据表删除数据表 创建管理数据库 创建数据库 语法&#xff1a; CREATE DATABASE 数据库名称;注&#xff1a; 在同一个数据库服务器上必须是唯一的&#xff0c;不允许存…

c++模版元编程,基于递归的编程

基于递归的模版元编程允许在模版中进行递归调用&#xff0c;以便在编译时生成更复杂的代码。这种技术的核心思想是将问题分解为一个个较小的子问题&#xff0c;并通过递归地调用模版来处理它们。 模版元编程的基本概念和原理&#xff1a; 模版元编程是一种利用C模版系统在编译时…

人工智能的未来:从 Jetson 到 GPT,沙龙见闻与洞察

前言 在当今数字化时代&#xff0c;人工智能正以惊人的速度改变着我们的生活和工作方式。从智能语音助手到自动驾驶汽车&#xff0c;从智能家居到医疗诊断&#xff0c;人工智能技术已经广泛渗透到各个行业&#xff0c;并为其带来了巨大的变革和创新。越来越多的行业专家、学者…

postman发送图片

POSTMAN 如何发送携带图片的请求? 闲话不叙 步骤如下&#xff1a; 新建一个请求&#xff0c;在Headers中添加一对k-v : Content-Type > multipart/form-data 请求的接口: RequestMapping("/fileUploadController")public String fileUpload(MultipartFile fil…

【C++】构造函数和析构函数第一部分(构造函数和析构函数的作用)--- 2023.9.25

目录 前言初始化和清理的概念构造函数和析构函数的作用构造函数的作用析构函数的作用 使用构造函数和析构函数的注意事项默认的构造函数和析构函数结束语 前言 在使用c语言开发的项目场景中&#xff0c;我们往往会遇到申请空间的需求&#xff0c;同时也肯定遇到过程序运行一段…

蓝牙核心规范(V5.4)10.9-BLE 入门笔记之GAP

1.概述 蓝牙核心规范的通用访问配置文件(GAP)部分定义了与设备发现和在两个设备之间建立连接有关的过程。如何执行数据的基本无连接通信、如何使用周期性广播(参见 PADVB-LE Periodic Advertising Broadcast)以及如何设置等时通信(参见 LE BIS和LE CIS - Isochronous Com…

购物车案例

1功能模块分析 请求动态渲染购物车&#xff0c;数据存vuex 数据框控件 修改数据 动态计算总价和总数量 2脚手架新建项目 终端安装axios&#xff1a;npm install axios -g 基于json-server工具&#xff0c;准备后端接口服务环境:&#xff08;模拟后台假数据&#xff09; 1…

积跬步致千里 || 可视化动图展示

可视化动图展示 目前只能在 jupyter notebook 中测试成功 %matplotlib notebook import numpy as np import matplotlib.pyplot as plt import timen 500 data np.random.normal(0,1,n)fig plt.figure() ax fig.add_subplot(111)fig.show() fig.canvas.draw()for i in ra…