输入设备编程实践

  1. 功能描述
  2. 实践要点
    1. input子系统
    2. 关键代码
    3. /proc/bus/input/devices
    4. 触摸屏设备
  3. 附录

功能描述

  • 通过输入设备编程,读取鼠标、键盘、触摸屏等设备的输入信息。

实践要点

input子系统

  • Linux系统为了统一管理输入设备,实现了一套能够兼容所有输入设备的框架,即input子系统。

  • 基于input子系统注册成功的输入设备,会在/dev/input目录下生成对应的设备节点,名称通常为eventX。

  • input子系统中最关键的数据结构是一个名为input_event的结构体,定义在<linux/input.h>中,其定义如下:

    struct input_event {
        struct timeval time;	//内核会记录每个上报的事件发生的时间,并通过time变量返回给应用程序
        __u16 type;				//用于描述发生了哪一种类型的事件,如EV_SYN 同步类事件 EV_KEY 按键类事件等,
                                //更多的宏定义定义在<linux/input.h>中
        __u16 code;				//表示该类事件中具体的事件,例如对于按键类事件,KEY_ESC表示ESC键,
                                //更多宏定义见<linux/input.h>
        __s32 value;			//对value的解释随着code的变化而变化。例如对于按键类事件来说,如果code=2(KEY_1),
                                //此时value=1的话表示KEY_1按下,value=0表示KEY_1键松开,value等于2表示KEY_1键长按
    }
    

关键代码

struct input_event in_ev = {0};

read(fd, &in_ev, sizeof(struct input_event));	//fd为输入设备对应的文件描述符,根据读到的内容判断发生了什么事情

/proc/bus/input/devices

  • 具体设备节点的查看,可以通过查看/proc/bus/input/devices得知,查看结果如下图所示:
- 上图中,name表示的是设备的名称,eventX代表的是设备节点号。如goodix-ts是触摸屏,其节点号是event1。

触摸屏设备

  • 触摸屏设备分为单点触摸和多点触摸。单点触摸设备只支持单点触摸,一轮完整的数据只包含一个触摸点信息。多点触摸设备,一轮完整的数据可能包含多个触摸点信息。

  • 对于不同的触摸屏设备,可以获取到的信息量大小是不同的,如有的屏只能读取到X和Y坐标,有的却还可以读到压力大小和触点面积等。

  • 在Linux内核中,多点触摸设备使用多点触摸(MT)协议上报各个触摸点的数据。实际使用中,MT Type B使用的较多,Type A几乎处于淘汰的边缘。

  • 触摸屏支持的最大触摸点数代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <linux/input.h>
    
    int main(int argc, char **argv) {
        struct input_absinfo info;
        int fd = -1;
        int max_slots;
        int ret;
    
        if(argc != 2) {
            printf("usage : %s <input-dev> \n", argv[0]);
            exit(-1);
        }
    
        fd = open(argv[1], O_RDONLY);
        if(fd == -1) {
            perror("open error");
            exit(-1);
        }
    
        ret = ioctl(fd, EVIOCGABS(ABS_MT_SLOT), &info);
        if(ret < 0) {
            perror("ioctl error");
            close(fd);
            exit(-1);
        }
    
        max_slots = info.maximum + 1 - info.minimum;
        printf("max_slots : %d\n", max_slots);
    
        close(fd);
        exit(0);
    }
    

附录


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 sigma_poet@126.com

💰

×

Help us with donation