linux输入子系统

Linux 输入子系统 Input子系统介绍 以前我们写一些输入设备(键盘、鼠标等)的驱动都是采用字符设备、混杂设备处理的。问题由此而来,Linux开源社区的大神们看到了这大量输入设备如此分散不堪,有木有可以实现一种机制,可以对分散的、不同类别的输入设备进行统一的驱动,所以才出现了输入子系统。 输入子系统引入的好处: (1)统一了物理形态各异的相似的输入设备的处理功能。例如,各种鼠标,不论PS/2、USB、还是蓝牙,都被同样处理。 (2)提供了用于分发输入报告给用户应用程序的简单的事件(even... 阅读详情

1、为何引入input system?

   以前我们写一些输入设备(键盘、鼠标等)的驱动都是采用字符设备、混杂设备处理的。问题由此而来,Linux开源社区的大神们看到了这大量输入设备如此分散不堪,有木有可以实现一种机制,可以对分散的、不同类别的输入设备进行统一的驱动,所以才出现了输入子系统。

   输入子系统引入的好处:

(1)统一了物理形态各异的相似的输入设备的处理功能。例如,各种鼠标,不论PS/2、USB、还是蓝牙,都被同样处理。

(2)提供了用于分发输入报告给用户应用程序的简单的事件(event)接口。你的驱动不必创建、管理/dev节点以及相关的访问方法。因此它能够很方便的调用输入API以发送鼠标移动、键盘按键,或触摸事件给用户空间。X windows这样的应用程序能够无缝地运行于输入子系统提供的event接口之上。

(3)抽取出了输入驱动的通用部分,简化了驱动,并提供了一致性。例如,输入子系统提供了一个底层驱动(成为serio)的集合,支持对串口和键盘控制器等硬件输入的访问。

2、输入子系统架构 
这里写图片描述

上图展示了输入子系统的操作。此子系统包括一前一后运行的两类驱动:输入事件(event)驱动和输入设备(device)驱动。

    输入事件驱动负责和应用程序的接口;

    而输入设备驱动负责和底层输入设备的通信。

    输入事件驱动和输入设备驱动都可以利用输入子系统的高效、可重用的核心提供的服务。

    Now,我们看到输入子系统中有两个类型的驱动,当我们要为一个输入设备(如触摸屏)的编写驱动的时候,我们是要编写两个驱动:输入设备驱动和输入事件驱动??

   答案是否定的。在子系统中,事件驱动是标准的,对所有的输入类都是可以用的,所以你更可能的是实现输入设备驱动而不是输入事件驱动。你的设备可以利用一个已经存在的,合适的输入事件驱动通过输入核心和用户应用程序接口。

总结如下:

  输入子系统由输入子系统核心层( Input Core ),驱动层和事件处理层(Event Handler)三部份组成。一个输入事件,如鼠标移动,键盘按键按下,joystick的移动等等通过 input driver -> Input core -> Event handler -> userspace 到达用户空间传给应用程序。

  设备驱动层:将底层的硬件输入转化为统一事件型式,向输入核心(InputCore)汇报。

  输入核心层:为设备驱动层提供输入设备注册与操作接口,如:input_register_device;通知事件处理层对事件进行处理;

  事件驱动层:主要作用是和用户空间交互,如提供read,open等设备方法,创建设备文件等。

内核代码分析:以键盘输入设备为例 
这里写图片描述
 

  输入设备注册分析:

    通过input_register_device函数注册一个输入设备,在这个函数中,首先通过设备ID去匹配handler的ID,以此找到对应的handler(事件处理者)。以按键输入设备为例:若匹配成功,则调用handler(evdev_handler是一个常用的handler,能够匹配任意设备)结构的connect函数创建一个设备文件,通过设备文件里的主设备号和次设备号将设备文件与字符设备驱动关联起来。(此处不用注册字符设备驱动,因为字符设备驱动已经在整个输入子系统初始化(input_init)的时候创建好)

  事件上报分析:

    以按键输入设备为例:通过调用input_report_key—input_event—input_handle_event—input_pass_event函数,调用handler(evdev_handler)结构中的event函数将事件的信息(事件类型:按键;键值;按键状态etc,)打包成一个input_event结构,保存在handler的buffer中。当有app访问时,会通过访问字符设备文件(例如dev/event1),间接访问输入子系统初始化时创建的字符设备驱动,此处字符设备驱动的fops中只有open的实现函数,并没有其他实现函数,当进入fops中的open函数时,此处巧妙地将handler(evdev_handler)中的fops赋给字符设备驱动当中的fops,当app进行read时,此时调用的即为handler结构中的fops中的read函数(evdev_read—evdev_fetch_next_event)从buffer当中取出事件信息,交给用户空间(input_event_to_user—copy_to_user)。

Input driver编写要点

1、分配、注册、注销input设备

struct input_dev *input_allocate_device(void) 
int input_register_device(struct input_dev *dev) 
void input_unregister_device(struct input_dev *dev)

2、设置input设备支持的事件类型、事件码、事件值的范围、input_id等信息

include/Linux/input.h中定义了支持的类型(下面列出的是2.6.22内核的情况)

define EV_SYN 0x00

    #define EV_KEY           0x01
    #define EV_REL           0x02
    #define EV_ABS           0x03
    #define EV_MSC          0x04
    #define EV_SW            0x05
    #define EV_LED          0x11
    #define EV_SND         0x12
    #define EV_REP         0x14
    #define EV_FF               0x15
    #define EV_PWR        0x16
    #define EV_FF_STATUS        0x17
    #define EV_MAX          0x1f

一个设备可以支持一个或多个事件类型。每个事件类型下面还需要设置具体的触发事件码。比如:EV_KEY事件,需要定义其支持哪些按键事件码。

3、如果需要,设置input设备的打开、关闭、写入数据时的处理方法

参见usb键盘驱动:usbkbd.c

input_dev->open = usb_kbd_open; 
input_dev->close = usb_kbd_close; 
input_dev->event = usb_kbd_event;

4、在发生输入事件时,向子系统报告事件

用于报告EV_KEY、EV_REL、EV_ABS等事件的函数有:

void input_report_key(struct input_dev *dev, unsigned int code, int value) 
void input_report_rel(struct input_dev *dev, unsigned int code, int value) 
void input_report_abs(struct input_dev *dev, unsigned int code, int value)

如果你觉得麻烦,你也可以只记住1个函数(因为上述函数都是通过它实现的)

void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)

三、Event Handler层解析

1、Input输入子系统数据结构关系图

这里写图片描述

2、input_handler结构体

以evdev.c中的evdev_handler为例:

static struct input_handler evdev_handler = { 
.event = evdev_event, //向系统报告input事件,系统通过read方法读取 
.connect = evdev_connect, //和input_dev匹配后调用connect构建 
.disconnect = evdev_disconnect, 
.fops = &evdev_fops, //event设备文件的操作方法 
.minor = EVDEV_MINOR_BASE, //次设备号基准值 
.name = “evdev”, 
.id_table = evdev_ids, //匹配规则 
};

3、input字符设备注册过程

drivers/input/input.c中: 
static int __init input_init(void) 
{ 
int err; 
err = class_register(&input_class); 
…… 
err = register_chrdev(INPUT_MAJOR, “input”, &input_fops); 
…… 
}

input_fops定义:

static const struct file_operations input_fops = { 
.owner = THIS_MODULE, 
.open = input_open_file, 
};

Input_dev和input_handler匹配后调用input_handler的connect。以evdev_handler为例:

static int evdev_connect(struct input_handler *handler, struct input_dev *dev,const struct input_device_id *id) 
{ 
struct evdev *evdev; 
struct class_device *cdev; 
dev_t devt; 
int minor; 
int error;

    for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
            if (minor == EVDEV_MINORS) {
                    printk(KERN_ERR "evdev: no more free evdev devices\n");
                    return -ENFILE;
            }

    evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);//为每个匹配evdev_handler的设备创建一个evdev。
            if (!evdev)
                    return -ENOMEM;

    INIT_LIST_HEAD(&evdev->client_list);
            init_waitqueue_head(&evdev->wait);

    evdev->exist = 1;
            evdev->minor = minor;
            evdev->handle.dev = dev;
            evdev->handle.name = evdev->name;
            evdev->handle.handler = handler;
            evdev->handle.private = evdev;
            sprintf(evdev->name, "event%d", minor);

    evdev_table[minor] = evdev;//记录evdev的位置,字符设备/dev/input/evnetx访问时根据次设备号及EVDEV_MINOR_BASE最终在evdev_open中找到对应的evdev
            devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
            cdev = class_device_create(&input_class, &dev->cdev, devt,dev->cdev.dev, evdev->name);//创建了event字符设备节点
            ……
    }

4、input字符设备的打开过程

static int input_open_file(struct inode *inode, struct file *file) 
{ 
struct input_handler *handler = input_table[iminor(inode) >> 5]; 
//得到对应的input_handler 
const struct file_operations *old_fops, *new_fops = NULL; 
int err; 
if (!handler || !(new_fops = fops_get(handler->fops))) 
//取出对应input_handler的file_operations 
return -ENODEV; 
if (!new_fops->open) { 
fops_put(new_fops); 
return -ENODEV; 
} 
old_fops = file->f_op; 
file->f_op = new_fops;//重定位打开的设备文件的操作方法 
err = new_fops->open(inode, file); 
if (err) { 
fops_put(file->f_op); 
file->f_op = fops_get(old_fops); 
} 
fops_put(old_fops); 
return err; 
}

5、input字符设备的其它操作

由于在open阶段已经把设备文件的操作操作方法重定位了到了具体的input_handler,所以其它接口操作(read、write、ioctl等),由各个input_handler的fops方法决定。如evdev.c中的:evdev_fops

linux输入子系统概念介绍 在此文章之前,我们讲解的都是简单的字符驱动,涉及的内容有字符驱动的框架、自动创建设备节点、linux中断、poll机制、异步通知、同步互斥、非阻塞、定时器去抖动。 上一节文章链接:http://blog.youkuaiyun.com/lwj103862095/article/details/17589311 在这一节里,我们要引入linux的分离分层的概念,linux输入子系统是一个很好的代表,在讲解如何 阅读详情

相关推荐

Linux下输入子系统上报触摸屏坐标

在 Linux 中,输入子系统是由输入子系统设备驱动层、输入子系统核心层(Input Core)和输入子系统事件处理层(Event Handler)组成。

weixin_44453694的博客 4190

linux输入子系统详解——看这一篇就够了

linux内核输入子系统详解

weixin_42031299的博客 6565

Linux内核编程(十三)Input输入子系统

Input 子系统是 Linux 内核中专门为输入设备设计的一个子系统,它提供了一个通用的框架来管理各种输入设备,如键盘、鼠标、触摸屏、游戏手柄等。这个子系统的主要目的是简化和规范化输入设备驱动的开发,同时提高驱动的通用性和兼容性。(1)输入设备:如键盘、鼠标、触摸屏、游戏手柄等,它们是用户与计算机进行交互的主要方式。(2)输入设备驱动的复杂性:传统上,为每种输入设备编写驱动都需要创建文件、进行硬件初始化、实现文件操作函数集和处理中断等。每种设备的驱动可能都有许多重复性的工作。

qq_1033275663的博客 2866

Linux Input 子系统

一、输入子系统的基本框架 输入子系统主要由三部分构成: 核心层(input.c,linux提供的中间核心层,向事件处理曾和设备驱动层提供接口函数)、事件处理层(evdev.c, keyboard.c, mousedev.c 等等)、设备驱动层(具体的设备驱动程序,比如按键驱动,触摸屏驱动等等, 具体硬件设备相关的驱动) 1、核心层 - input.c 这一层是linux内核实现的的一些通用的接口,可以向事件处理层和设备驱动层提供一些公用函数 input_register_handler /inpu.

db_linux_driver的博客 2670

输入子系统第四步完成注册后硬件操作.emmx

对应着硬件操作的流程图 #define EV_SYN 0x00 //同步类 #define EV_KEY 0x01 //按键类,如键盘上的 a,b 等按键事件。 #define EV_REL 0x02 //relation 相对位移事件(如鼠标的位移是基于上一个位置的)。 #define EV_ABS 0x03 //ABS 是绝对位移(如触摸屏是 XY 坐标绝对位置)。 #define EV_MSC 0x04 #define EV_SW 0x05 #define EV_LED 0x11 #define EV_SND 0x12 #define EV_REP 0x14 #define EV_FF 0x15 #define EV_PWR 0x16 #define EV_FF_STATUS 0x17 #define EV_MAX 0x1f

莫比乌斯反演

本文从算法竞赛和数论角度出发,系统介绍了狄利克雷卷积与莫比乌斯反演的核心概念。首先定义了数论函数及其基本性质,重点阐述了狄利克雷卷积的代数结构(交换环)和关键恒等式(如μ*1=ε)。随后通过卷积视角简化了莫比乌斯反演的证明过程。最后将理论提升至抽象代数层面,揭示这些数论工具本质上是偏序集关联代数在整除关系下的特例,其中莫比乌斯函数对应Zeta函数的逆元。全文展现了数学概念从具体到抽象的升华过程,为理解这些工具提供了更深刻的代数视角。

aichitang2024的博客 391

【玩转Linux】Linux输入子系统简介

重点是输入设备文件,例如触摸屏

qq_64928278的博客 649

深入解析以太网接口中的BOB Smith电路设计

本文深入解析以太网接口中的BOB Smith电路设计,详细介绍了其在共模噪声抑制、浪涌防护和EMI优化中的关键作用。通过实际案例和设计要点,帮助工程师正确选择75Ω电阻和高压电容等元件,优化PCB布局,解决电压型与电流型PHY的设计差异,以及千兆与百兆以太网的特殊考量。

weixin_28339967的博客 688

【linux kernel】一文总结linux输入子系统

本文记录linux输入子系统的一些知识点。

iriczhao的博客 1692

2xmax96717+max96724+agx orin驱动代码

说明:这里主要解决max96717的设备地址和sensor地址映射,vc0->vc1多颗max96717+max96724使用配置思路如下: 1、改变max96717的pipez stream id,然后max96724的pipe绑定使用相应的stream id 2、max96717默认是vc0,把vc0改写成vc1\vc2\vc3,然后max96724再重新映射vc输出

mantouyouyou的博客 113

python利用IQR方法与3σ方法进行异常值处理(含代码)

python利用IQR方法进行异常值处理

weixin_46713695的博客 2031

Linux输入子系统简析

linux, 输入子系统,输入驱动

JiMoKuangXiangQu的专栏 1090

2025华为od机试真题B卷【版本管理】JavaScript实现

在 软件版本管理中,版本号由点分割的数字组成,例如 1.2.3 和 2.8。现在,你需要编写一个函数,计算两个版本号之间的可用版本号个数。这里的可用版本号指的是所有满足 version1<x<version2的版本号x的个数。若 version1 >=version2 返回0.,

MISAYAONE的博客 254

linux输入子系统概述,Linux输入子系统分析

1输入子系统架构Overview输入子系统(Input Subsystem)的架构如下图所示输入子系统由 输入子系统核心层( Input Core ),驱动层和事件处理层(Event Handler)三部份组成。一个输入事件,如鼠标移动,键盘按键按下,joystick的移动等等通过 Driver -> InputCore -> Eventhandler -> userspace...

weixin_39624360的博客 130

YOLO26优化:注意力魔改 | EMA:基于跨空间学习的高效多尺度注意力,效果优于ECA、CBAM、CA

加入EMA注意力,一种基于跨空间学习的高效多尺度注意力,效果优于ECA、CBAM、CA等经典注意力。

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 334

你知道几种数字地与模拟地连接方式及优缺点?

频率选择性:磁珠的阻抗特性随频率变化,只对某个频点的噪声有显著抑制作用,对于频率不确定或无法预知的情况,可能不是最佳选择。在实际应用中,选择合适的连接方式需要根据具体的电路频率、信号类型、设计要求等因素综合考虑,以达到最佳的电磁兼容效果.高频信号干扰:在高频电路中,单点接地可能导致信号回流路径过长,增加地线电感,从而引入高频噪声。限制噪声电流:0欧姆电阻相当于一个非常窄的电流通路,能够有效地限制环路电流,使噪声得到抑制。抑制高频信号:电感对高频信号有较大的阻碍作用,可以有效抑制高频噪声。

linkking27的博客 801

【Linux驱动】Linux输入子系统

输入设备总类繁杂,包括按键,键盘,触摸屏,鼠标,摇杆等等,它们本身都是字符设备,不过内核为了能将这些设备的共性抽象出来,简化驱动的开发,建立了一个 Input 子系统。用户只需要根据内核提供的 input 子系统下提供的 API 函数接口,完成设备的注册即可。Input 子系统就是管理输入的子系统,和 pinctrl 和 gpio 子系统一样,都是 Linux 内核针对某一类设备而创建的框架。

C/C++软件工程师、嵌入式软件工程师、物联网研发工程师、C/C++讲师、物联网讲师、嵌入式讲师、鸿蒙讲师---欢迎大家一起交流(私信添加博主微信) 1660

告别手动读摘要!爬虫+大模型做学术助手:爬知网论文,10秒生成摘要+关键词(附完整代码)

知网的官方摘要往往冗长(200-300字),关键词可能不够精准,用大模型提炼“100字精简摘要”和“3-5个核心关键词”,更适合快速筛选文献。这套学术助手的核心价值,是把“找论文、读摘要、提关键词”这些重复劳动,交给爬虫和大模型自动化完成,让科研人从繁琐的文献整理中解放出来,把时间花在实验设计、数据分析等核心工作上。需要注意的是:爬取知网论文仅用于个人科研和学习,不得用于商业用途,遵守知网的用户协议和版权规定;大模型生成的摘要和关键词需后续核对原文,确保准确性。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1942

初识linux输入子系统

一、初识linux输入子系统 linux输入子系统(linux input subsystem)从上到下由三层实现,分别为:输入子系统事件处理层(EventHandler)、输入子系统核心层(InputCore)和输入子系统设备驱动层。 对于输入子系统设备驱动层而言,主要实现对硬件设备的读写访问,中断设置,并把硬件产生的事件转换为核心层定义的规范提交给事件处理层。即将底层的硬件输入转化为统一事件形式,想输入核心(Input Core)汇报。 对于核心层而言,为设备驱动层提供了规范和接口。设..

嵌入式与人工智能 520

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

linux输入子系统点灯,Linux输入子系统详解

导读linux输入子系统由驱动层、输入子系统核心、事件处理层三部分组成。一个输入事件,如鼠标移动、键盘按下等通过Driver->Inputcore->Event handler->userspace的顺序到达用户控件的应用程序。驱动层将底层的硬件输入转化为统一事件形式,想输入核心(Input Core)汇报。输入子系统核心层它承上启下为驱动层提供输入设备注册与操作接口,如:inp...

weixin_36091906的博客 141

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

linux驱动 -- 输入子系统

输入子系统

jcf5832的博客 812

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Linux驱动学习—输入子系统

输入子系统是Linux专门做的一套框架来处理输入事件的,像鼠标,键盘,触摸屏这些都是输入设备,但是这邪恶输入设备的类型又都不是一样的,所以为了统一这些输入设备驱动标准应运而生的。统一了以后,在节点/dev/input下面则是我们输入设备的节点,如下图所示:这些节点对应的则是我们当前系统的输入设备,我们要怎么查看当前系统都有哪些输入设备呢?

suifen_的博客 1743

【 Linux 输入子系统】

摘要: Linux输入子系统是人机交互的核心枢纽,负责将物理设备的原始信号转化为标准化事件。其采用三层架构:设备驱动层获取数据,核心层抽象事件,事件处理层传递给应用。文章通过虚拟按键设备的实现案例(定时上报按键值),展示了输入子系统的核心机制,包括设备注册、事件上报等流程。该系统实现跨硬件兼容,并与Android InputFlinger等组件协同工作,为上层应用提供统一的输入事件处理接口。开发者可基于此架构扩展特定硬件驱动逻辑。

highersister的博客 492
上一篇: SD/MMC 初始化及热插拔检测机制
下一篇: 【Spring Boot】Spring Boot解决循环依赖
rexling1
博客等级 码龄16年 4粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值