一、linux系统IO应用实例。 -> 触摸屏。 1、触摸屏设备叫什么名字? 在linux下,一切都是文件,连触摸屏也是一个文件。 触摸屏设备名字:/dev/input/event0
2、熟悉了解触摸屏两个专业术语。 1)事件。 -> event0 当一些外接控制设备(鼠标、键盘,wifi,触摸屏,按键)接入到嵌入式平台(GEC6818)时,这些外接设备的状态发生了改变(鼠标的左键被按下了,键盘的R键被按下,有人连接上wifi了,触摸屏被滑动了一下,按键被按下了)时,这个动作就称之为事件。
2)输入子系统。 -> input 当事件发生的时候,就是由输入子系统来计算这些事件中产生的值。
3、如果我们想把触摸屏的坐标读取出来,思路是如何的呢? 1)访问触摸屏设备文件。 fd = open("/dev/input/event0");
2)直接读取即可。 read(fd);
3)分析读取出来的数据是什么类型的? int ? char ? char []? *?
4)根据获取到的坐标做进一步的判断就可以。 if(坐标满足某一个条件) { }
5)关闭文件 close(fd);
例题: 尝试将数据读取到一个数组中。
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h>
int main(int argc,char *argv[]) { //1. 访问触摸屏设备 int fd; fd = open("/dev/input/event0",O_RDONLY); if(fd < 0) { printf("open ts error!\n"); } //2. 读取触摸屏设备的数据 char buf[100] = {0}; while(1) { read(fd,buf,sizeof(buf)); printf("from file:%s\n",buf); } //3. 关闭文件。 close(fd); return 0; } 结果: 打印乱码。
二、究竟触摸屏数据对应的类型是什么? 如果想知道从event0这个文件中读取出来的这个文件的数据是什么类型的,那么就必须先知道输入子系统计算完这个结果之后,是以什么形式放到这个event0这个文件中。
1、如何来描述一个事件? -> 需要很多值 -> 结构体。 该结构体已经定义好了,是被封装在一个头文件,头文件的路径在: /usr/include/linux/input.h
/* * The event structure itself //事件结构体 */
struct input_event { -> 专门用于描述一个事件。 struct timeval time; -> 事件发生的时间。 __u16 type; -> 事件的类型 (输入子系统会用这个值来描述刚才发生事件的硬件设备) __u16 code; -> 事件的编码 -> 对事件进一步的描述 左键/右键 A键/R键 x轴/y轴 __s32 value; -> 事件的值 };
struct timeval { long tv_sec; /* 秒 */ long tv_usec; /* 微秒 */ };
例子2: 现在我们知道读取出来的,就是一个结构体。 我们现在就把结构体里面的成员打印出来看看,究竟等于多少?
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <linux/input.h>
int main(int argc,char *argv[]) { //1. 访问触摸屏设备 int fd; fd = open("/dev/input/event0",O_RDONLY); if(fd < 0) { printf("open ts error!\n"); } //2. 读取触摸屏设备的数据 struct input_event buf; while(1) { read(fd,&buf,sizeof(buf)); printf("buf.type = %d\n",buf.type); printf("buf.code = %d\n",buf.code); printf("buf.value = %d\n",buf.value); } //3. 关闭文件。 close(fd); return 0; }
结果: [root@GEC6818 /]#./ts buf.type = 3 -> 触摸屏位移 buf.code = 0 -> 触摸屏的x轴 buf.value = 274-> 点击的坐标的x轴坐标
buf.type = 3 -> 触摸屏位移 buf.code = 1 -> 触摸屏的y轴 buf.value = 384-> 点击的坐标的y轴坐标
buf.type = 1 -> 按键 buf.code = 330 -> 触摸屏压力 buf.value = 1 -> 按下
buf.type = 0 buf.code = 0 buf.value = 0
buf.type = 1 -> 按键 buf.code = 330 -> 触摸屏压力 buf.value = 0 -> 松开
buf.type = 0 buf.code = 0 buf.value = 0
结果的值也是被封装在一个头文件中:#include "input-event-codes.h" 1)事件的类型有哪些? /* * Event types */
#define EV_SYN 0x00 -> 异步通信。 #define EV_KEY 0x01 -> 按键事件 (一般指的就是这类设备:键盘/压力/按键) #define EV_REL 0x02 -> 相对位移 (一般指的就是鼠标) #define EV_ABS 0x03 -> 绝对位移 (一般指的就是触摸屏)
2)事件的编码由哪些? EV_KEY -> 对应的code有哪些? #define BTN_TOUCH 0x14a(等价于十进制的330)
EV_ABS -> 对应的code有哪些? #define ABS_X 0x00 -> 代表触摸屏的x轴 #define ABS_Y 0x01 -> 代表触摸屏的y轴
例子3: 点击屏幕松开手,就打印一句话。
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <linux/input.h>
int main(int argc,char *argv[]) { //1. 访问触摸屏设备 int fd; fd = open("/dev/input/event0",O_RDONLY); if(fd < 0) { printf("open ts error!\n"); } //2. 读取触摸屏设备的数据 struct input_event buf; while(1) { read(fd,&buf,sizeof(buf)); //发生了很多个事件 //但是只有松手的事件才是我想要的。 if(buf.type == 1 && buf.code == 330 && buf.value == 0) { printf("your hand leave lcd!\n"); } } //3. 关闭文件。 close(fd); return 0; }
练习1: 写一个程序,实现当你的手在屏幕上滑动时,就不断打印当前坐标出来,顺便看看原点在哪里? x y (100,200)
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <linux/input.h>
int main(int argc,char *argv[]) { //1. 访问触摸屏设备 int fd; fd = open("/dev/input/event0",O_RDONLY); if(fd < 0) { printf("open ts error!\n"); } //2. 读取触摸屏设备的数据 struct input_event buf; int x,y; while(1) { read(fd,&buf,sizeof(buf)); //发生了很多个事件 if(buf.type == 3 && buf.code == 0) { x = buf.value; } if(buf.type == 3 && buf.code == 1) { y = buf.value; } printf("(%d,%d)\n",x,y); } close(fd); return 0; }
练习2: 写一个程序,实现点击屏幕的左边松开,就打印一次"left"。 点击屏幕的右边松开,就打印一次"right"。
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <linux/input.h> #include <strings.h>
int main(int argc,char *argv[]) { int fd,x; struct input_event buf;
/* 1. 访问触摸屏设备 */ fd = open("/dev/input/event0",O_RDONLY); if(fd < 0) printf("open event0 error!\n"); /*2. 不断读取触摸屏数据 */ while(1) { bzero(&buf,sizeof(buf)); //每次读取之前,都保证缓冲区是清空的状态。 read(fd,&buf,sizeof(buf)); //3. 获取手触摸到的坐标 if(buf.type == EV_ABS && buf.code == ABS_X) x = buf.value; //4. 判断你什么时候松手。 if(buf.type == EV_KEY && buf.code == BTN_TOUCH && buf.value == 0) { //5. 判断下你刚刚松手的位置在哪里 if(x < 500) //左边 { printf("left!\n"); } if(x > 500) //右边 { printf("right!\n"); } if(x == 500) { break; } } } //6. 关闭文件 close(fd); return 0; }
=================================== 补充理解输入子系统的现实例子。 type: 吃饭 -> 0 睡觉 -> 1
code: 早餐 -> 0 午餐 -> 1 晚餐 -> 2
午觉 -> 0 晚觉 -> 1
value; 饱 -> 0 饿 -> 1 睡得着 -> 2 睡不着 -> 3
struct input_event{ -> 代表输入子系统分析出来: 你刚刚睡午觉没睡着 .type = 1 .code = 0 .value = 3 }