【stm32MP157】linux应用开发-鼠标读取数据详解和代码分享

目录

一、简介

1.1  type:事件类型

2.1 鼠标事件


一、简介

        Linux系统是通过输入子系统来管理输入设备(如鼠标、键盘、触摸屏、游戏摇杆)的。配置了内核支持且安装对应驱动后,当系统接入输入设备,会在/dev/input下生成对应设备文件,下图是鼠标、键盘在不同情况下/dev/input的设备文件。

        当输入设备有事件产生时,内核就会将事件上报到设备文件,事件的数据以struct input_event为单位存入设备文件,所以读取事件数据时使用struct input_event结构体,这个结构体定义在/usr/include/linux/input.h中。

struct input_event {
        struct timeval time;
        __u16 type;
        __u16 code;
        __s32 value;
};

1.1  type:事件类型

type:事件类型,常见的有:EV_KEY(键盘)、EV_REL(相对坐标)、EV_ABS(绝对坐标)、,定义在[input-event-codes.h] (https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h#LC35) 或 input.h 中。

EV_REL  按键事件:(鼠标,键盘等)

EV_REL  相对坐标(如:鼠标移动,报告相对最后一次位置的偏移)

EV_ABS  绝对坐标(如:触摸屏或操作杆,报告绝对的坐标位置)

/*
 * Event types
 */
#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 //LED
#define EV_SND            0x12 //声音
#define EV_REP            0x14 //repeat、会自动发出重复按键
#define EV_FF             0x15
#define EV_PWR            0x16 //电源开关、按键
#define EV_FF_STATUS      0x17
#define EV_MAX            0x1f
#define EV_CNT			(EV_MAX+1)

1.2  code

        code:事件的代码,对事件进一步的描述

        盘事件的键值(KEY_NUMLOCK、KEY_ESC、KEY_1、KEY_A),定义在[input-event-codes.h] 
        鼠标事件的位置信息(REL_X、REL_Y),滚轮信息(REL_WHEEL),定义在[input-event-codes.h] 
        触摸屏事的地位置信息(ABS_MT_POSITION_X),slot信息(ABS_MT_SLOT)定义在[input-event-codes.h] 

1.3 value 

 value:事件的值,对事件更具体地描述,如:
        按键的按下/抬起
        鼠标位置信息的具体 x值、y值
        触摸屏事件slot信息表示第几个的值、ABS_MT_TRACKING_ID的值

二 linux应用系统编程

2.1 驱动对象的确定

        通常情况下,开发板的出厂系统,已经帮我们配置好了底层的驱动。我们只需要确定驱动的位置和名称,使用open,read,write,close等函数对驱动进行操作即可。

       一般鼠标、键盘、触摸屏等输入设备的驱动都放在 /dev/input 这个文件夹下。

     查看对应的硬件。注意,测试时需要将鼠标插上,有些开发板的驱动在外设插入的时候才启动

     但是还是有点模糊,比如出现好几个Mouse,到底是哪个? 通过一下命令来测试:

hexdump /dev/input/event2     //event3、event4

        来测试一下,我使用的开发板,当测试event2时,发现鼠标移动就不断输出数据,说明正是event2。

2.2 鼠标事件的介绍

 鼠标的事件一般有 EV_REL(相对坐标)、EV_KEY(按键) 两种类型,EV_REL用来表示鼠标在屏幕的位置(相对位置),EV_KEY用来表示鼠标的按钮。

EV_REL类型(相对坐标)
        如果事件是相对坐标时,读取到的struct input_event的type字段的值为 2 ,
code字段的取值可能是REL_X(相对坐标X值)、REL_X(相对坐标Y值)、REL_WHEEL(滚轮),
value字段根据code的取值不同而不同,可以表示坐标(X值、Y值),滚轮上滑(-1)、下滑(1)
下图是相对坐标时,code的定义的值。

#define REL_X           0x00
#define REL_Y           0x01
#define REL_Z           0x02
#define REL_RX          0x03
#define REL RY          0x04
#define REL_RZ          0x05
#define REL_HWHEEL      0x06
#define REL_DIAL        0x07
#define REL_WHEEL       0x08
#define REL_MISC        0x09

EV_KEY类型(按键:左键、右键、滚轮键)
        上文说过,鼠标事件也有按键类型,表示左键、右键、滚轮键按下/抬起,读取到的struct input_event的type字段的值为 1 ,
        code字段取值可能是BTN_LEFT(左键)、BTN_RIGHT(右键)、BTN_MIDDLE(滚轮键),
value字段一般是 1 表示按下,0 表示抬起,
        下图是鼠标按键,code的定义的值:

#define BTN_MOUSE		0x110
#define BTN_LEFT		0x110
#define BTN_RIGHT		0x111
#define BTN_MIDDLE		0x112
#define BTN_SIDE		0x113
#define BTN_EXTRA		0x114
#define BTN_FORWARD		0x115
#define BTN_BACK		0x116
#define BTN_TASK		0x117

2.3  编写代码步骤 

第一步:定义一个事件的结构体变量,我们要用到事件,需要得到事件,在程序中肯定需要一个变量来描述这个事件。

第二步:打开设备节点,Linux中一切皆文件,所以用open函数,打开输入设备节点

第三步:读取事件,读取打开的输入设备节点中的数据,到我们第一步的定义的事件变量中

第四步:利用获取的事件信息来完成我们自己编写的处理逻辑,这里就简单输出一下鼠标位置。

2.4 完整代码 

        代码实现的功能:

        1、 读取鼠标的相对位移x,y,以及中间滑轮上下的数值(上滑动为1,下滑动为0);

        2、读取鼠标左键,右键和中间滑轮点击情况,点击(按下)为1,松开为0 。

        具体代码如下: 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(int argc, char *argv[])
{
    //1、定义一个结构体变量用来描述input事件
    struct input_event event_mouse ;
    //2、打开input设备的事件节点  我的通用USB鼠标事件的节点是event2
    int fd    = -1 ;
    if(2!= argc){
      fprintf(stderr,"usage: %s <input-dev>\n", argv[0]);
      exit(-1);
}
           fd = open(argv[1], O_RDONLY);
    if(-1 == fd)
    {
        printf("open mouse event fair!\n");
        return -1 ;
    }
    while(1)
    {
        //3、读事件
        read(fd, &event_mouse, sizeof(event_mouse));
        if(EV_REL == event_mouse.type)
        {
            //code表示位移X或者Y,当判断是X时,打印X的位移value
            //当判断是Y时,打印Y的位移value
         	if(event_mouse.code == REL_X)
            {
                printf("event_mouse.code_X:%d\n", event_mouse.code);
                printf("event_mouse.value_X:%d\n", event_mouse.value);
            }
            else if(event_mouse.code == REL_Y)
            {
                printf("event_mouse.code_Y:%d\n", event_mouse.code);
                printf("event_mouse.value_Y:%d\n", event_mouse.value);
            }
            else if(event_mouse.code == REL_WHEEL)
            {
            	printf("event_mouse.code_WHEEL:%d\n", event_mouse.code);
                printf("event_mouse.value_WHEEL:%d\n", event_mouse.value);
			}
        }
        else if(EV_KEY == event_mouse.type)
        {
        	if(event_mouse.code == BTN_LEFT)
            {
                printf("event_mouse.code_left:%d\n", event_mouse.code);
                printf("event_mouse.value_left:%d\n", event_mouse.value);
            }
            else if(event_mouse.code == BTN_RIGHT)
            {
                printf("event_mouse.code_right:%d\n", event_mouse.code);
                printf("event_mouse.value_right:%d\n", event_mouse.value);
            }
            else if(event_mouse.code == BTN_MIDDLE)
            {
            	printf("event_mouse.code_middle:%d\n", event_mouse.code);
                printf("event_mouse.value_middle:%d\n", event_mouse.value);
			}
		}
    }
    close(fd);
    return 0 ;
}

2.5 代码编译和测试 

        使用交叉编译器编译好之后,通过nfs或其他方法挂载(或拷贝)到开发板上,在USB口插入鼠标。

        运行如下代码(代码名字和路径根据实际开发板情况修改)

        ./read_mouse /dev/input/event2

运行效果:

                ​​​​​​​        

  • 57
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值