Linux Input子系统1

Linux Input子系统1(基于Linux6.6)---基础介绍

 


一、Linux中的input子系统介绍

Linux中的input子系统是负责处理各种输入设备(如键盘、鼠标、触摸屏、游戏控制器等)与操作系统之间交互的核心部分。它是Linux内核中负责抽象和管理输入设备的一个子系统,能够处理不同类型的硬件输入,提供统一的接口,使得各种输入设备能够在不同的硬件平台和驱动程序之间进行兼容。

1.1、Input子系统的组成

  • Input事件接口: Input子系统通过标准的事件接口 (/dev/input/eventX) 提供输入设备的状态和事件数据。每当设备发生状态变化时,它会通过该接口将事件传递给用户空间程序(例如,X服务器或图形界面)。

  • 设备驱动: 各种输入设备(如键盘、鼠标、触摸板等)有各自的驱动程序,负责与硬件进行交互,并将硬件生成的输入事件传递到Linux内核的输入子系统中。驱动程序通常在内核空间中工作。

  • 输入事件类型: 输入事件是由设备驱动生成的,通常包括几种类型,例如:

    • EV_KEY:按键事件(例如,键盘上的按键按下或释放)。
    • EV_ABS:绝对值事件(例如,鼠标的位置或触摸屏上的触摸点位置)。
    • EV_REL:相对值事件(例如,鼠标的移动)。
    • EV_SYN:同步事件,标记输入设备的状态更新。
    • EV_MSC:额外的控制事件,例如中断、滚轮等。
  • 设备模型: Input子系统与Linux设备模型紧密集成,输入设备通过设备模型中的节点与内核及用户空间进行通信。每个输入设备都会在内核中创建一个input_dev结构体,它包含了该设备的信息、状态和输入事件的处理函数。

1.2、输入设备的分类

  • 按键设备:如键盘、按键板等,负责按键事件的输入。
  • 相对设备:如鼠标、触控板、触摸屏等,这些设备提供相对位置信息(例如,鼠标的移动距离)。
  • 绝对坐标设备:例如触摸屏、绘图板等设备,它们提供的是屏幕上的绝对位置。
  • 游戏设备:如游戏手柄、飞行摇杆等,通常包括多个按钮和控制轴(如X、Y坐标)。

1.3、输入事件流

在Linux中,输入事件流大致分为以下几个阶段:

  1. 硬件生成输入事件: 输入设备(如键盘、鼠标)产生一个物理事件,比如按键被按下或鼠标位置发生变化。

  2. 设备驱动处理事件: 输入设备的驱动程序接收这些硬件事件,并将它们转换为标准化的输入事件(例如EV_KEY, EV_REL, EV_ABS等)。驱动程序通过内核的input subsystem将这些事件传递到系统中。

  3. 内核中断和事件分发: 内核的输入子系统会将这些事件转发到相应的输入设备节点。例如,当鼠标移动时,input_event()函数会被调用,并将该事件放入相应的事件队列。

  4. 用户空间处理事件: 用户空间的程序(例如X Window系统、Wayland、图形界面或其他应用程序)通过读取/dev/input/eventX设备节点,获取这些事件并进行处理。例如,X服务器通过这些事件来处理键盘输入和鼠标操作。

1.4、与用户空间的交互

  • 设备文件: 输入设备通常暴露为/dev/input/eventX设备文件(X为设备编号)。用户空间程序可以通过读取这些文件来获取输入事件。常见的输入设备文件包括:

    • /dev/input/event0:第一个输入设备。
    • /dev/input/mouse0:鼠标设备。
    • /dev/input/kbd:键盘设备(在某些系统中可能会使用)。

    程序可以通过标准的文件IO接口(open(), read(), close()等)读取事件数据。例如,X Window系统通过读取/dev/input/eventX来获得键盘或鼠标的输入事件。

  • 输入事件接口: 每个输入设备会暴露一个事件接口,用户空间程序可以从中读取事件数据。通过ioctl()系统调用,程序可以查询设备的特性(如支持的事件类型、键值等),以及控制设备的行为。

1.5、Input子系统的配置和管理

  • xinput命令: 在Linux桌面环境中,xinput是一个常用的工具,允许用户配置和管理输入设备。它可以列出所有已识别的输入设备、查看设备的属性、禁用或启用某些设备等。

  • udev设备管理器udev是Linux下的设备管理器,负责动态管理设备节点。它为输入设备提供了自动化的配置功能,如在设备插入时自动加载适当的驱动、创建设备文件、设置设备权限等。

  • Input事件调试: 可以使用evtest工具来调试和测试输入设备。通过evtest,你可以查看输入设备的原始事件,帮助诊断硬件问题或调试驱动程序。

1.6、常见的输入设备驱动

  • 键盘驱动atkbd, psmouse等):这些驱动程序负责处理传统键盘和鼠标的输入。
  • 触摸屏驱动ft5x_ts, evdev等):这些驱动程序处理触摸屏等设备的输入。
  • 游戏控制器驱动joydev, xpad等):这些驱动程序负责管理游戏控制器(如游戏手柄、飞行摇杆等)的输入。

Linux input  子系统将一个输入设备的输入过程分成了设备驱动(input device driver)和事件驱动(input event driver)两个层。前者负责从底层硬件采集数据;后者负责与用户程序接口,将采集到的数据分发给不同的用户接口。通过这样的设计,将千差万别的设备统一到了为数不多的几种驱动接口上。同一种事件驱动可以用来处理多个同类设备;同一个设备也可以和多种事件驱动相衔接。而事件驱动和设备驱动则由输入核心层进行连接,匹配。

上:输入事件驱动层         (打包数据,面向应用)
 
中:输入核心层             (向下提供注册接口,向上给具体的hander发送数据)
 
下:输入设备驱动层         (底层驱动,面向硬件)     

二、举例分析

应用程序使用input子系统的核心是,对驱动层打包好的数据进行分析。其中打包的数据结构如下:

 /*
 * The event structure itself
 */
 
struct input_event {
	struct timeval time;
	__u16 type;
	__u16 code;
	__s32 value;
};

一个设备驱动可能对应两个设备驱动,比如鼠标既可以对应mouse,也可以对应event。

event事件设备驱动程序是通用的,可以包括所有类型的输入设备,也是目前的主流,我们就以它为例分析。

应用层操作驱动有2条路:/dev目录下的设备文件,/sys目录下的属性文件。两个效果是一样的,用那个都可以。

2.1、应用举例

先写一个简单的应用程序。

其作用是,读电脑鼠标的数据并打印出来。

 #include <linux/input.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
 
 
#define  INPUT_MOUSE    "/dev/input/event3"    /* 电脑的键盘 */
#define  INPUT_KEY      "/dev/input/event1"    /* 电脑的鼠标 */
 
 
int main(void)
{
    int fd = -1, ret = -1;
    struct input_event ev;
 
    fd = open(INPUT_MOUSE , O_RDONLY);    /* 打开鼠标的设备文件 */
    if(fd < 0)
    {
        perror("open");
        return -1;
    }
 
    while(1)
    {
        memset(&ev, 0, sizeof(struct input_event));    
        ret = read(fd, &ev, sizeof(struct input_event));    /* 读鼠标(会阻塞) */
        if(ret != sizeof(struct input_event))
        {
            perror("read");
            close(fd);
            return -1;
        }
        /* 打印读到的键值 */
        printf("--------------------\n");
        printf("type = %u.\n", ev.type);
        printf("code = %u.\n", ev.code);
        printf("value = %u.\n", ev.value);
    }
    return 0;
}

下面是移动打印出来的数据。

 --------------------
type = 2.               /* 相对坐标设备(鼠标) */
code = 0.               /* x轴 */
value = 1.              /* 位移方向 */
--------------------
type = 2.               /* 相对坐标设备(鼠标) */
code = 1.               /* y轴 */
value = 1.              /* 位移方向 */
--------------------
type = 0.               /* 同步包 */
code = 0.
value = 0.
--------------------
type = 2.
code = 0.
value = 1.
--------------------
type = 2.
code = 1.
value = 1.
--------------------
type = 0.
code = 0.
value = 0.
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值