Linux系统中标准输入设备的控制方法

大家好,我是st。
    今天主要和大家聊一聊,如何使用标准输入设备,进行控制信息的识别。
第一:按键应用编程方法
     编写一个应用程序,获取按键状态,判断按键当前是按下,松开或长按状态。
#以字母a键为例key_a    //上报key_a事件syn_report //同步  
      如果是按下,则上报key_a事件时,value=1;如果是松开,则value=0;如果长按,则value=2。接下来编写按钮应用程序,读取按键状态并将结果打印出来,代码如下所示。
#include #include #include #include #include #include #include int main(int argc, char *argv[]){ struct input_event in_ev = {0}; int fd = -1; int value = -1; /* 校验传参 */ if (2 != argc) { fprintf(stderr, usage: %s , argv[0]); exit(-1); } /* 打开文件 */ if (0 > (fd = open(argv[1], o_rdonly))) { perror(open error); exit(-1); } for ( ; ; ) { /* 循环读取数据 */ if (sizeof(struct input_event) != read(fd, &in_ev, sizeof(struct input_event))) { perror(read error); exit(-1); } if (ev_key == in_ev.type) { //按键事件 switch (in_ev.value) { case 0: printf(code: 松开, in_ev.code); break; case 1: printf(code: 按下, in_ev.code); break; case 2: printf(code: 长按, in_ev.code); break; } } }}  
    在for循环中,调用read()读取输入设备上报的数据,当按键按下或松开(以及长按)动作发生时,read()会读取到输入设备上报的数据,首先判断此次上报的事件是否是按键类事件(ev_key),如果是按键类事件,接着根据value值来判断按键当前的状态是松开、按下还是长按。
    将编译得到的可执行文件复制到开发板linux系统的家目录下:
注意:除了能够测试key0按键之外,还可以测试键盘上的按键,可以找到一个usb键盘连接到开发板的usb host接口上,当键盘插入之后,终端将会打印出相应的驱动加载信息。
     驱动加载成功之后,可以查看下该键盘设备对应的设备节点,使用命令cat /proc/bus/input/devices,在打印信息中找到键盘设备的信息:
操作的时候,可以对应相应的设备节点/dev/input/event3,运行测试程序并按下、松开键盘上的按键;
大家可以根据code值查询对应的按键,譬如code=30对应的键盘上的字母a键,code=48对应的字母b键。
第二:单点触摸应用程序实现
     通过上面的详细介绍,大家应该知道如何编写一个触摸屏的应用程序了,接下来我们编写一个单点触摸屏应用程序,获取一个触摸点的坐标信息,并将其打印出来。具体代码实现如下:
#include #include #include #include #include #include #include int main(int argc, char *argv[]){ struct input_event in_ev; int x, y; //触摸点 x 和 y 坐标 int down; //用于记录 btn_touch 事件的 value,1 表示按下,0 表示松开,-1 表示移动 int valid; //用于记录数据是否有效(我们关注的信息发生更新表示有效,1 表示有效,0 表示无效) int fd = -1; /* 校验传参 */ if (2 != argc) { fprintf(stderr, usage: %s , argv[0]); exit(exit_failure); } /* 打开文件 */ if (0 > (fd = open(argv[1], o_rdonly))) { perror(open error); exit(exit_failure); } x = y = 0; //初始化 x 和 y 坐标值 down = -1; //初始化 valid = 0;//初始化 for ( ; ; ) { /* 循环读取数据 */ if (sizeof(struct input_event) != read(fd, &in_ev, sizeof(struct input_event))) { perror(read error); exit(exit_failure); } switch(in_ev.type) { case ev_key: //按键事件 if (btn_touch == in_ev.code) { down = in_ev.value; valid = 1; } break; case ev_abs: //绝对位移事件 switch (in_ev.code) { case abs_x: //x 坐标 x = in_ev.value; valid = 1; break; case abs_y: //y 坐标 y = in_ev.value; valid = 1; break; } break; case ev_syn: //同步事件 if (syn_report == in_ev.code) { if (valid) {//判断是否有效 switch (down) {//判断状态 case 1: printf(按下(%d, %d), x, y); break; case 0: printf(松开); break; case -1: printf(移动(%d, %d), x, y); break; } valid = 0; //重置 valid down = -1; //重置 down } } break; } }}  
     分析:程序中先传入参数,main()函数中定义了4个变量;
⑴、变量 x 表示触摸点的 x 坐标;
⑵、变量 y 表示触摸点的 y 坐标;
⑶、变量 down 表示手指状态时候按下、松开还是滑动,down=1 表示手指按下、down=0 表示手指松开、down=-1 表示手指滑动;
⑷、变量 valid 表示数据是否有效,valid=1 表示有效、valid=0 表示无效;有效指的是我们检测的信息发生了更改,譬如程序中只检测了手指的按下、松开动作以及坐标值的变化。接着调用 open()打开触摸屏设备文件得到文件描述符 fd;在 for 循环之前,首先对 x、y、down、valid这 4 个变量进行初始化操作。在 for 循环读取触摸屏上报的数据,将读取到的数据存放在 struct input_event数据结构中。在 switch…case 语句中对读取到的数据进行解析,获取 btn_touch 事件的 value 数据,判断触摸屏是按下还是松开状态,获取 abs_x 和 abs_y 事件的 value 变量,得到触摸点的 x 轴坐标和 y 轴坐标。
    当上报同步事件时,表示数据已上传完整,接着对得到的数据进行分析,打印坐标信息。
第三:多点触摸应用程序实现
    实现了单点触摸应用程序之后,可以再来实现多点触摸屏应用程序该如何实现。
#include #include #include #include #include #include #include #include #include /* 用于描述 mt 多点触摸每一个触摸点的信息 */struct ts_mt { int x; //x 坐标 int y; //y 坐标 int id; //对应 abs_mt_tracking_id int valid; //数据有效标志位(=1 表示触摸点信息发生更新)};/* 一个触摸点的 x 坐标和 y 坐标 */struct tp_xy { int x; int y;};static int ts_read(const int fd, const int max_slots, struct ts_mt *mt){ struct input_event in_ev; static int slot = 0;//用于保存上一个 slot static struct tp_xy xy[12] = {0};//用于保存上一次的 x 和 y 坐标值,假设触摸屏支持的最大触摸点数不会超过 12 int i; /* 对缓冲区初始化操作 */ memset(mt, 0x0, max_slots * sizeof(struct ts_mt)); //清零 for (i = 0; i =0 表示创建 for ( ; ; ) { if (sizeof(struct input_event) != read(fd, &in_ev, sizeof(struct input_event))) { perror(read error); return -1; } switch (in_ev.type) { case ev_abs: switch (in_ev.code) { case abs_mt_slot: slot = in_ev.value; break; case abs_mt_position_x: xy[slot].x = in_ev.value; mt[slot].valid = 1; break; case abs_mt_position_y: xy[slot].y = in_ev.value; mt[slot].valid = 1; break; case abs_mt_tracking_id: mt[slot].id = in_ev.value; mt[slot].valid = 1; break; } break; //case ev_key://按键事件对单点触摸应用比较有用// break; case ev_syn: if (syn_report == in_ev.code) { for (i = 0; i fd) { perror(open error); exit(exit_failure); } /* 获取触摸屏支持的最大触摸点数 */ if (0 > ioctl(fd, eviocgabs(abs_mt_slot), &slot)) { perror(ioctl error); close(fd); exit(exit_failure); } max_slots = slot.maximum + 1 - slot.minimum; printf(max_slots: %d, max_slots); /* 申请内存空间并清零 */ mt = calloc(max_slots, sizeof(struct ts_mt)); /* 读数据 */ for ( ; ; ) { if (0 > ts_read(fd, max_slots, mt)) break; for (i = 0; i < max_slots; i++) { if (mt[i].valid) {//判断每一个触摸点信息是否发生更新(关注的信息发生更新) if (0 <= mt[i].id) printf(slot, 按下(%d, %d), i, mt[i].x, mt[i].y); else if (-1 == mt[i].id) printf(slot, 松开, i); else printf(slot, 移动(%d, %d), i, mt[i].x, mt[i].y); } } } /* 关闭设备、退出 */ close(fd); free(mt); exit(exit_failure);}  
      示例代码中申明了 struct ts_mt 数据结构,用于描述多点触摸情况下每一个触摸点的信息。
      首先来看下 main()函数,定义了 max_slots 变量,用于指定触摸屏设备的支持的最大触摸点数,通过:
ioctl(fd, eviocgabs(abs_mt_slot), &slot)
获取到触摸屏该信息。
接着根据 max_slots 变量的值,为 mt 指针申请内存:
            mt = calloc(max_slots, sizeof(struct ts_mt));
     for( ; ; )循环中调用 ts_read()函数,该函数是自定义函数,用于获取触摸屏上报的数据,第一个参数表示文件描述符 fd、第二个参数表示触摸屏支持的最大触摸点数、第三个参数则是 struct ts_mt 数组,ts_read()函数会将获取到的数据存放在数组中,mt[0]表示 slot数据、mt[1]表示 slot的数据依次类推!
    在内部的 for 循环中,则对获取到的数据进行分析,判断数据是否有效,并根据 id 判断手指的动作,在单点触摸应用程序中,我们是通过 btn_touch 事件来判断手指的动作;而在多点触摸应用中,我们需要通过 id 来判断多个手指的动作。
     关于自定义函数 ts_read()就不再介绍了,代码的注释已经描述很清楚了!
     接着编译应用程序,将编译得到的可执行文件拷贝到开发板 linux 系统的用户家目录下,执行应用程序,接着可以用多个手指触摸触摸屏、松开、滑动等操作。
总结:每一个不同的slot表示不同的触摸点,譬如 slot表示触摸点 0、slot表示触摸点 1 以此类推!


基于无线通讯技术的边缘计算网关及其在电网中的应用
智能制造的定义、关键技术与实现智能制造的意义是什么
STM32F407总线存储框架及应用设计
Gartner2021年安全和风险管理领域的八大趋势
同欣智能科技PS1356开关介绍
Linux系统中标准输入设备的控制方法
利用异步采样速率转换简化数字数据接口
车规级电感厂家科普相同封装的贴片式共模电感可以通用吗 gujing
英诺达为芯片厂商提供EDA硬件验证一站式解决方案
SpectraProHRS多功能高分辨率成像光栅光谱仪
小米6怎么样?小米6是否值得你们前赴后继的抢购?看了这6点你还抢购吗?
aigo移动固态硬盘S7 Pro评测:凭实力圈粉无数 真国民好物
紫光国微荣获安全之星“2021年度优秀汽车安全芯片方案奖”
光数字继电保护测试仪的功能有哪些
基于三网融合的互联网电视的技术方案、优势特点与发展趋势介绍
比亚迪在新能源市场不断领先,但不同能源车型发展不均衡问题不可忽视
如何减少分立元件的数量和电路板空间
HTC Vive与澳大利亚最大零售商合作建立用户体验店
IDC交换机互连-10G/25G/40G/100G高速电缆
超两万台Linksys无线路由器被曝信息泄露 依旧存在缺陷