博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
手把手教你写Linux设备驱动---input子系统(一)--input事件应用程序的读写实现(基于友善之臂4412开发板)...
阅读量:6278 次
发布时间:2019-06-22

本文共 6976 字,大约阅读时间需要 23 分钟。

     这节,我们来说下input子系统,什么是input子系统?

input子系统就是输入子系统。

     输入子系统是 Linux内核用于管理各种输入设备 (键盘,鼠标,遥控杆,书写板等等 )的部分,用户通过输入子系统进行内核,命令行,图形接口之间的交换。输入子系统在内核里实现,因为设备经常要通过特定的硬件接口被访问 (例如串口, ps/2, usb等等 ),这些硬件接口由内核保护和管理。内核给用户导出一套固定的硬件无关的 input API,供用户空间程序使用。

输入子系统分为三块: input core, drivers和 event handlers。正常的路径是从底层硬件到驱动,从驱动到 input core,

从 input core到 event handler,从 event handler到 user space。在应用程序的角度,我们只要关心user space就行了

其余的部分我们不用关心。

我们先从应用程序的角度来认识下input子系统,我们可以从这个文件可以看到对应的设备

/proc/bus/input/devices

I: Bus=0003 Vendor=046d Product=c018 Version=0111N: Name=" USB Optical Mouse"P: Phys=usb-0000:00:1d.1-2/input0S: Sysfs=/class/input/input24U: Uniq=H: Handlers=mouse1 event2B: EV=7B: KEY=70000 0 0 0 0 0 0 0 0B: REL=103

在Linux系统下cat //proc/bus/input/devices即可看到以上相关的信息,这些devices主要是用来描述注册在input子系统的一些

设备文件,可能有鼠标,键盘,触摸屏,重力传感器,温度传感器等等的设备。

那我们如何来描述这样的一个设备呢?Linux系统为我们提供了以下这个头文件:

#include <linux/input.h>

在这个文件中,我们可以找到这个结构体:

描述一个输入事件/* * The event structure itself */struct input_event {	struct timeval time;	__u16 type;	__u16 code;	__s32 value;};

先来解读下这个结构体的含义:

struct timeval结构体在time.h中的定义为:
struct timeval{__time_t tv_sec;        /* Seconds. */__suseconds_t tv_usec;    /*Microseconds. */};

其中,tv_sec为Epoch到创建struct timeval时的秒数,tv_usec为微秒数,即秒后面的零头。

type域显示了被报告事件的类型,例如,一个 key press或者 button press, relative motion(比如移动鼠标 )

或者 absolute motion(比如移动游戏杆 ); code域告诉你是哪一个key或者坐标轴在被操作; 

value域告诉你现在的状态或者运动情况是什么。

那么,最主要的事件有以下三种:

相对事件(鼠标),绝对事件(触摸屏),键盘事件。

例如:我们说说鼠标,我们在移动鼠标的时候鼠标就是一个相对事件,所以type的类型也就是底层上报给用户的事件为

相对事件类型,那么code表示的就是相对于鼠标当前的位置的X或者Y的坐标,value也就是相对于当前的位置偏移多少。

事件类型(type)在input.h主要有以下:

/* * 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#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#define EV_CNT			(EV_MAX+1)
我们这节主要来写写鼠标的事件读取还有控制,所以我们找到鼠标相关的code:

/* * Relative axes *///在这里,我们暂时只会用来REL_X和REL_Y这两个参数#define REL_X			0x00    //相对X坐标#define REL_Y			0x01    //相对Y坐标#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#define REL_MAX			0x0f#define REL_CNT			(REL_MAX+1)
那么value,就是选择具体的type,具体的code以后所反应出来的值,鼠标就是相对于当前X或者相对于当前Y的值。

接下来,我们来看一下如何来读取鼠标事件,写一段代码测试一下:

#include 
#include
#include
#include
#include
/*struct input_event { struct timeval time; __u16 type; __u16 code; __s32 value;};*//*Event types#define EV_SYN 0x00#define EV_KEY 0x01#define EV_REL 0x02#define EV_ABS 0x03*//* Relative axes#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#define REL_MAX 0x0f#define REL_CNT (REL_MAX+1)*///event8 mouse//event9 keyboardint main(void){ //1、定义一个结构体变量用来描述input事件 struct input_event event_mouse ; //2、打开input设备的事件节点 我的电脑鼠标事件的节点是event3 int fd = open("/dev/input/event3",O_RDWR); int value ; int type ; int buffer[10]={0}; if(-1 == fd){ printf("open mouse event fair!\n"); return -1 ; } while(1){ //3、读事件 read(fd ,&event_mouse ,sizeof(event_mouse)); //4、判断事件类型,并打印键码 switch(event_mouse.type){ case EV_SYN: printf("sync!\n"); break ; case EV_REL: //鼠标事件,XY相对位移 //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); } 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); } defalut: break ; } } return 0 ;}
编译完后,执行,当移动鼠标的时候我们就可以看到以下信息:

说明,此时已经读到鼠标事件所反应出来的值了。

那么,既然可以做读的操作,那肯定也就可以写了,可不可以写一个程序,让鼠标画个正方形,或者让它自动按着自己

的路径去移动?答案是肯定可以的,要不然游戏外挂都是怎么做出来的?大家说是吧,下面我们就让鼠标来自己画一个

正方形,上代码:

#include 
#include
#include
#include
#include
/*struct input_event { struct timeval time; __u16 type; __u16 code; __s32 value;};*//*Event types#define EV_SYN 0x00#define EV_KEY 0x01#define EV_REL 0x02#define EV_ABS 0x03*//* Relative axes#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#define REL_MAX 0x0f#define REL_CNT (REL_MAX+1)*///event8 mouse//event9 keyboardint main(void){ //1、定义一个结构体变量用来描述input事件 struct input_event event_mouse ; //2、打开input设备的事件节点 我的电脑鼠标事件的节点是event3 int fd = open("/dev/input/event3",O_RDWR); int value ; int type ; int i ; int buffer[10]={0}; if(-1 == fd){ printf("open mouse event fair!\n"); return -1 ; } while(1){ //3、写事件 for(i = 0 ; i < 20 ; i++){ event_mouse.type = EV_REL ; event_mouse.code = REL_X ; event_mouse.value = i ; write(fd,&event_mouse,sizeof(event_mouse)); event_mouse.code = 0 ; event_mouse.value = 0; event_mouse.type = EV_SYN ; write(fd,&event_mouse,sizeof(event_mouse)); usleep(50000); } for(i = 0 ; i < 20 ; i++){ event_mouse.type = EV_REL ; event_mouse.code = REL_Y ; event_mouse.value = i ; write(fd,&event_mouse,sizeof(event_mouse)); event_mouse.code = 0 ; event_mouse.value = 0 ; event_mouse.type = EV_SYN ; write(fd,&event_mouse,sizeof(event_mouse)); usleep(50000); } for(i = 0 ; i > -20 ; i--){ event_mouse.type = EV_REL ; event_mouse.code = REL_X ; event_mouse.value = i ; write(fd,&event_mouse,sizeof(event_mouse)); event_mouse.code = 0 ; event_mouse.value = 0; event_mouse.type = EV_SYN ; write(fd,&event_mouse,sizeof(event_mouse)); usleep(50000); } for(i = 0 ; i > -20 ; i--){ event_mouse.type = EV_REL ; event_mouse.code = REL_Y ; event_mouse.value = i ; write(fd,&event_mouse,sizeof(event_mouse)); event_mouse.code = 0 ; event_mouse.value = 0 ; event_mouse.type = EV_SYN ; write(fd,&event_mouse,sizeof(event_mouse)); usleep(50000); } } return 0 ;}
执行结果:

此时鼠标是在移动的,由于以下的图片是禁止的,效果留给大家自己去尝试。

下节,我们将来实现一下input驱动。

你可能感兴趣的文章
技术人员的焦虑
查看>>
js 判断整数
查看>>
建设网站应该考虑哪些因素
查看>>
mongodb $exists
查看>>
js实现页面跳转的几种方式
查看>>
sbt笔记一 hello-sbt
查看>>
常用链接
查看>>
pitfall override private method
查看>>
!important 和 * ----hack
查看>>
聊天界面图文混排
查看>>
控件的拖动
查看>>
svn eclipse unable to load default svn client的解决办法
查看>>
Android.mk 文件语法详解
查看>>
QT liunx 工具下载
查看>>
内核源码树
查看>>
Java 5 特性 Instrumentation 实践
查看>>
AppScan使用
查看>>
Java NIO框架Netty教程(三) 字符串消息收发(转)
查看>>
Ucenter 会员同步登录通讯原理
查看>>
php--------获取当前时间、时间戳
查看>>