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

使用DeepSeek、MCP和AKShare实现智能金融问答系统技术方案

DeepSeek是由深度求索公司开发的大规模语言模型,最新版本DeepSeek-V3采用混合专家(MoE)架构,拥有671B参数,激活37B参数,在多项基准测试中表现优异3。要使用DeepSeek的API服务:访问DeepSeek平台注册账号获取API Key(形如AKShare是基于Python的金融数据接口库,提供股票、基金、期货、宏观经济等领域的海量数据。主要特点包括:免费开源,数据源丰富支持多种数据格式(DataFrame/JSON)持续更新维护安装命令。

Kin 3174

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

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

qq_64928278的博客 649

操作系统知识点汇总(王道)

操作系统不论是就业还是升学都是核心的一门课程,对于大部分工科更是必修课程。本文章是对《王道操作系统》所有知识点的总结笔记,以供大家学习以及在备考期间复习使用。让我们一起把知识往脑子里旋好吗!!!......

S mile0804的博客 5万+

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

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

iriczhao的博客 1692

SigmaStar(星宸科技)SSC33X系列

目前,SSC33X系列已经量产了接近两年,SDK成熟稳定,功耗表现良好,图像效果出色,广泛应用在AI枪机、AI球机、AI云台机、多目摄像机、停车场闸机、人脸门禁、人脸锁、门铃猫眼等产品上。

Comake Online的博客 1万+

Java对接快递鸟,查询快递物流信息

根据用户输入的订单号,我们的后台识别订单号并根据快递鸟查询快递API接口,实现自动查询的功能。下面是java版本的根据单号查询物流跟踪信息的详细示例代码。只需要下载就可以运行,(自己需要简单的修改)注:登录快递鸟用户管理后台后获得。登录快递鸟用户管理后台。

Roc的博客 958

Linux输入子系统简析

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

JiMoKuangXiangQu的专栏 1090

OCS2 移动机械臂深度解析:ocs2_mobile_manipulator 与 ocs2_mobile_manipulator_ros 源码全拆解

摘要:本文深入解析OCS2移动机械臂MPC控制框架的两个核心工具包。ocs2_mobile_manipulator负责算法建模,通过MobileManipulatorInterface统一构建最优控制问题,支持4种机械臂模型并实现自动维度推导;ocs2_mobile_manipulator_ros负责ROS集成,包含MPC求解、虚拟跟踪等4个核心节点。文章详细剖析了工具包分工、最优控制建模架构(含动力学、代价约束设计)、ROS运行管线、参数配置映射,并提供了高效的源码阅读顺序建议,帮助开发者快速掌握移动机械

m0_73309445的博客 655

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

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

weixin_39624360的博客 130

DA14531-蓝牙温度传感器-真实案例

传感器低功耗系统功能需求: 1)平时为关机状态,通过GPIO管脚唤醒,霍尔器件触发拉低IO唤醒系统。 2)唤醒后,进入BLE广播状态,等待主机连接,若一分钟无被主机连接,则进入关机状态。 3)连接后(0.1mA),每秒上报一次温度值,同时主机可以读取设备读电池电量。 4)连接断开后,1分钟后,设备进入关机(1uA)。 5)LED灯在连接时点亮,断开灭,低电量时会闪,提示闪烁。

hejinwu1314的博客 857

芒果YOLO11改进44:主干Backbone篇之MobileViT::结合最新 ICLR2022 顶会|轻量通用的MobileViT结构(一)Transformer,轻量级、通用且移动友好的视觉转换

MobileViT::结合最新 ICLR2022 顶会|轻量通用的MobileViT结构(一)Transformer,轻量级、通用且移动友好的视觉转换

包括YOLOv5、YOLOv7、YOLOv8等模型改进 370

【Linux驱动】Linux输入子系统

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

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

uniapp [全端兼容] - 实现接入使用天地图及卫星视图切换功能,在国家天地图上自由切换地图显示类型(卫星视图/地形视图/卫星混合/地形混合/普通视图)天地图切换视图显示改成卫星风格,切换地图图层

uni-app,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,天地图,视图,卫星,地图类型切换,uniAPP天地图,改成卫星视角,在线地图切换,来回切换卫星图,天地图如何实现来回切换卫星图,地形图,卫星视图,VUE3引入天地图卫星版,详细教程示例源码代码,天地图切换卫星用什么api,卫星视角API方法,vue3卫星天地图,能改地图的显示方式,vue3中使用天地图自定义样式切换地图图层,切换报错,加载出错,卫星图太卡,地图图层更换,vue3安装集成天地图详细示例源

🏆 前端领域优质创作者 1万+

初识linux输入子系统

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

嵌入式与人工智能 520

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

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

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

weixin_36091906的博客 141

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

linux驱动 -- 输入子系统

输入子系统

jcf5832的博客 812

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、付费专栏及课程。

余额充值