嵌入式Linux入门-输入系统应用编程(鼠标、键盘、触摸屏)
目录
1. 输入系统
1.1 基本概念
1.2 获取输入设备信息
1.3 输入系统框架
2. 输入系统编程
2.1 确定对应关系
2.2 编写代码步骤
3. 开发板上的编程
学习带着问题学会比较好,比如,在Linux系统下,我们如何编写程序获得鼠标的位置?键盘的哪一个按键被按下了?触摸屏的哪个位置被触摸了?
学过单片机的都知道,这些本质上都是一些信号,由驱动程序解析,但我们讲的是应用编程,也就是说从驱动程序中直接获取我们需要的。
那么必然就需要一套规范的接口,不然每个人写的都不一样,做个应用,还得阅读驱动源码,就离谱了。
嵌入式Linux入门完整教程:嵌入式Linux教程—裸机、应用、驱动完整教程目录
1. 输入系统
1.1 基本概念
常见的输入设备有键盘、鼠标、触摸屏、蓝牙等等,用户通过这些输入设备与Linux系统进行数据交换。
Linux 系统为了统一管理这些输入设备,实现了一套能兼容所有输入设备的框架:输入系统。驱动开发人员基于这套框架开发出程序,应用开发人员就可以使用统一的 API 去使用设备。
1.2 获取输入设备信息
确定设备信息:输入设备的设备节点名为/dev/input/eventX(也可能是/dev/eventX, X表示 0、 1、 2 等数字)。查看设备节点,可以执行以下命令:
ls /dev/input
如果是开发板可能没有input文件夹,直接就在/dev下。
怎么知道这些设备节点对应什么硬件呢?可以执行以下命令:
cat /proc/bus/input/devices
这条指令的可以获取与 event 对应的相关设备信息:
I:id of the device(设备 ID)
N:name of the device设备名称
P:physical path to the device in the system hierarchy系统层次结构中设备的物理路径。
S:sysfs path位于 sys 文件系统的路径
U:unique identification code for the device(if device has it)设备的唯一标识码
H:list of input handles associated with the device.与设备关联的输入句柄列表。
B:bitmaps(位图)
值得注意的是 B 位图,比如上图中“ B: EV=b”用来表示该设备支持哪类输入事件。 b 的二进制是 1011, bit0、 1、 3 为 1,表示该设备支持 0、 1、 3 这三类事件,即 EV_SYN、 EV_KEY、 EV_ABS。
再举一个例子,“ B: ABS=2658000 3”如何理解?
它表示该设备支持 EV_ABS 这一类事件中的哪一些事件。这是 2 个 32 位的数 字: 0x2658000、 0x3, 高位在 前低 位在 后, 组成一 个 64 位 的数字 :“ 0x2658000,00000003”,数值为 1 的位有: 0、 1、 47、 48、 50、 53、 54,即:0、 1、 0x2f、 0x30、 0x32、 0x35、 0x36,对应以下这些宏:
内核版本低的在 /usr/include/linux/input.h下。
1.3 输入系统框架
以按键为例:按键按下–>输入系统驱动层–>输入系统核心层–>输入系统事件层—>用户空间
对于应用程序软件编程的角度,我们只需要关注用户空间得到按键按下以后获取的是什么事件就可以了,例如我想知道我当前按下的按是短按还是长按?或者我想知道当前我按下键盘的是空格键还是回车键等等。
在input子系统中,每个事件的发生都使用事件(type)->子事件(code)->值(value) 所有的输入设备的主设备号都是13,input-core通过次设备来将输入设备进行分类,如0-31是游戏杆,32-63是鼠标(对应Mouse Handler)、64-95是事件设备(如触摸屏,对应Event Handler)。
在input.h中的源码:
struct input_event {struct timeval time;__u16 type;__u16 code;__s32 value;
};
timeval 表示的是“自系统启动以来过了多少时间”,它是一个结构体,含有“ tv_sec、 tv_usec”两项(即秒、微秒)。
Linux输入子系统支持的事件类型
事件类型 | 编码 | 含义 |
---|---|---|
EV_SYN | 0x00 | 同步事件 |
EV_KEY | 0x01 | 按键事件(鼠标,键盘等) |
EV_REL | 0x02 | 相对坐标(如:鼠标移动,报告相对最后一次位置的偏移) |
EV_ABS | 0x03 | 绝对坐标(如:触摸屏或操作杆,报告绝对的坐标位置) |
EV_MSC | 0x04 | 其它 |
EV_SW | 0x05 | 开关 |
EV_LED | 0x11 | 按键/设备灯 |
EV_SND | 0x12 | 声音/警报 |
EV_REP | 0x14 | 重复 |
EV_FF | 0x15 | 力反馈 |
EV_PWR | 0x16 | 电源 |
EV_FF_STATUS | 0x17 | 力反馈状态 |
EV_MAX | 0x1f | 事件类型最大个数和提供位掩码支持 |
驱动程序上报完一系列的数据后,会上报一个“同步事件”,表示数据上报完毕。 APP 读到“同步事件”时,就知道已经读完了当前的数据。同步事件也是一个 input_event 结构体,它的 type、code、 value 三项都是 0。
2. 输入系统编程
2.1 确定对应关系
通过上文已经知道了,可以通过:
ls /dev/input
查看输入设备节点,通过:
cat /proc/bus/input/devices
查看对应的硬件。
但是还是有点模糊,比如出现好几个Mouse,到底是哪个? 通过:
hexdump /dev/input/event2 //event3、event4
来测试一下,当测试event2时,发现鼠标移动就不断输出数据,说明正是event2。
2.2 编写代码步骤
第一步:定义一个事件的结构体变量,我们要用到事件,需要得到事件,在程序中肯定需要一个变量来描述这个事件。
第二步:打开设备节点,Linux中一切皆文件,所以用open函数,打开输入设备节点
第三步:读取事件,读取打开的输入设备节点中的数据,到我们第一步的定义的事件变量中
第四步:利用获取的事件信息来完成我们自己编写的处理逻辑,这里就简单输出一下鼠标位置。
完整代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/input.h>int main(void)
{//1、定义一个结构体变量用来描述input事件struct input_event event_mouse ;//2、打开input设备的事件节点 我的通用USB鼠标事件的节点是event2int fd = -1 ;fd = open("/dev/input/event2", 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_ABS == event_mouse.type){//code表示位移X或者Y,当判断是X时,打印X的位移value//当判断是Y时,打印Y的位移valueif(event_mouse.code == ABS_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 == ABS_Y){printf("event_mouse.code_Y:%d\n", event_mouse.code);printf("event_mouse.value_Y:%d\n", event_mouse.value);}}}close(fd);return 0 ;
}
3. 开发板上的编程
EV=b,B表示支持KEY,ABS事件,可以看到KEY=400 0 0 0 0 0 0 0 0 0 0 ,也就是第330位为1,十六进制就是0x14A,查源码
#define BTN_TOUCH 0x14a
表示支持KEY事件的BTN_TOUCH子事件。ABS自己算一算,我就不用了。
我开发板上只有触摸屏这一个输入设备,用之前文章中的Linux下LCD显示程序随便改改
功能:按压触摸屏变黑,释放,屏幕变白
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/input.h>#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <linux/fb.h>static int fd_fb;
static struct fb_var_screeninfo var; /* Current var */
static int screen_size;
static unsigned char *fb_base;
static unsigned int line_width;
static unsigned int pixel_width;void lcd_put_pixel(int x, int y, unsigned int color)
//传入的 color 表示颜色,它的格式永远是 0x00RRGGBB,即 RGB888。
//当 LCD 是 16bpp 时,要把 color 变量中的 R、 G、 B 抽出来再合并成 RGB565 格式。
{unsigned char *pen_8 = fb_base+y*line_width+x*pixel_width;//计算(x,y)坐标上像素对应的 Framebuffer 地址。unsigned short *pen_16;unsigned int *pen_32;unsigned int red, green, blue;pen_16 = (unsigned short *)pen_8;pen_32 = (unsigned int *)pen_8;switch (var.bits_per_pixel){//对于 8bpp, color 就不再表示 RBG 三原色了,这涉及调色板的概念, color 是调色板的值。case 8:{*pen_8 = color;break;}case 16:{/* 565 *///先从 color 变量中把 R、 G、 B 抽出来。red = (color >> 16) & 0xff;green = (color >> 8) & 0xff;blue = (color >> 0) & 0xff;//把 red、 green、 blue 这三种 8 位颜色值,根据 RGB565 的格式,//只保留 red 中的高 5 位、 green 中的高 6 位、 blue 中的高 5 位,//组合成一个新的 16 位颜色值。color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);//把新的 16 位颜色值写入 Framebuffer*pen_16 = color;break;}case 32:{//对于 32bpp,颜色格式跟 color 参数一致,可以直接写入Framebuffer*pen_32 = color;break;}default:{printf("can't surport %dbpp\n",var.bits_per_pixel);break;}}
}int main(void)
{//1、定义一个结构体变量用来描述input事件struct input_event event_TouchScreen ;int fd = -1 ;int i;fd_fb = open("/dev/fb0", O_RDWR);if (fd_fb < 0){printf("can't open /dev/fb0\n");return -1;} if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)){printf("can't get var\n");return -1;}line_width = var.xres * var.bits_per_pixel / 8;pixel_width = var.bits_per_pixel / 8;screen_size = var.xres * var.yres * var.bits_per_pixel / 8;fb_base = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);if (fb_base == (unsigned char *)-1){printf("can't mmap\n");return -1;}//2、打开input设备的事件节点 fd = open("/dev/event0", O_RDONLY);if(-1 == fd){printf("open mouse event fair!\n");return -1 ;}while(1){//3、读事件read(fd, &event_TouchScreen, sizeof(event_TouchScreen));if(EV_KEY == event_TouchScreen.type){//code表示位移X或者Y,当判断是X时,打印X的位移value//当判断是Y时,打印Y的位移valueif(event_TouchScreen.code == BTN_TOUCH){if(event_TouchScreen.value==0)/* 清屏: 全部设为白色 */memset(fb_base, 0xff, screen_size);else/* 清屏: 全部设为黑色 */memset(fb_base, 0x0, screen_size);}else;}}close(fd);close(fd_fb);return 0 ;
}
完成,复杂的逻辑就自己根据需求编写就行了。
嵌入式Linux入门-输入系统应用编程(鼠标、键盘、触摸屏)相关推荐
- 嵌入式Linux入门11:应用层编程应用和分类
本文针对Linux系统环境应用层的编程应用做一个概述. 有的人把Linux底层和应用层严格区分对待,在一定程度上是没有错误的.但很多时候需要进行交叉学习.比如,编写了底层驱动程序,如何验证这个驱动能正 ...
- 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(十五)输入系统应用编程
文章目录 1.输入系统应用编程 1.1 什么是输入系统 1.2 输入系统框架及调试 1.2.1 框架概述 1.2.2 编写APP需要掌握的知识 1.2.3 调试技巧 **1. 确定设备信息** **2 ...
- 【嵌入式Linux】嵌入式Linux应用开发基础知识之输入系统应用编程
文章目录 前言 1.输入系统应用编程 1.1.输入系统框架及调试 1.1.1.框架概述 1.1.2.编写APP需要的基础知识 1.2.调试技巧 1.2.1.查看设备信息 1.2.2.使用命令查看节点数 ...
- 嵌入式输入系统应用编程
在线课堂:https://www.100ask.net/index(课程观看) 论 坛:http://bbs.100ask.net/(学术答疑) 开 发 板:https://100ask.taoba ...
- 嵌入式 Linux 入门(十、Linux 下的 C 编程)
嵌入式 Linux 入门第十课,聊聊 linux 下的 C 编程...... 矜辰所致 插一句,问题讨论群在文末的推广,以后大家提问可以在群中,即便我不在也能看到历史记录. 目录 前言 一.C 语言编 ...
- 嵌入式 Linux 入门(五、Shell 脚本编程上:认识 Shell 脚本)
大家好,是矜辰所致,嵌入式 Linux入 门第五课,本课开始简单学习一下 Shell 脚本编程. 目录 前言 一.Shell 脚本基础说明 1.1 什么是 Shell 脚本 1.2 Shell 脚本的 ...
- 分享:嵌入式Linux入门学习指导
很多嵌入式linux初学者对嵌入式linux学习十分迷茫,不知道该怎么一步步学习,嵌入式linux学习方法,学习的流程步骤以及学习过程中需要看哪些好的书籍.下面凌阳教育嵌入式培训网就为大家整理的嵌入式 ...
- 嵌入式linux入门3-3-套接字
个人博客对应地址:嵌入式linux入门3-3-套接字 socket主要函数 创建套接字 socket,我们一般翻译为套接字,其是一种通讯接口,允许位于不同计算机之间的线程通过网络进行通讯,我们可以使用 ...
- 嵌入式 Linux 入门(二、Linux 文件系统、文件类型及权限管理)
嵌入式 Linux入 门第二课, linux 文件系统.文件类型及权限管理. ...... 矜辰所致 目录 前言 一.Linux 文件属性 1.1 Linux 文件类型 1.2 Linux 文件权限及 ...
- 嵌入式 Linux 入门(七、Linux 下的环境变量)
嵌入式 Linux 入门第七课,学习理解 linux 的环境变量 ......矜辰所致 前言 学习完 Linux 的 Shell 命令 和 Shell 脚本,我们还需要理解一个东西 :环境变量,理解了 ...
最新文章
- ADPRL - 近似动态规划和强化学习 - Note 7 - Approximate Dynamic Programming
- 号称史上最牛逼的几篇博客整理(python+java+js等)
- 让Jexus支持高并发请求的优化技巧
- 014PHP基础知识——流程控制(二)
- vc设置按钮文字颜色
- java用循环给map里面存值_Java中如何遍历Map对象的4种方法
- 2017蓝桥杯省赛---java---C---2(兴趣小组)
- linux无后缀名程序运行,linux – 如何在Ubuntu上运行无扩展(也许是ELF)文件?
- C#通过COM组件调用IDL的pro程序
- C++设计模式10--命令模式(二)(Command)--降低请求发送者与接收者耦合
- 7 EDA实用技术教程【基本语句3】
- 02 python入门
- 掌握Python核心编程的四大神兽,何尝拿不到高薪资
- 10个可以让你达到谷歌首页的谷歌SEO技巧
- 功能强大~带你走近Smartbi增强分析模块
- seo专员日常工作内容是什么?
- vue 获取元素宽高
- 新浪财经沪深300指数期权和商品期权行情接口
- java 微博sdk_Java基于新浪微博SDK实现发微博的功能
- elixir 教程_认识Elixir,Laravel编译资产的方式
热门文章
- yar php使用,PHP yar的使用简介
- 三维建模,三维地理信息的作用
- html属于页面的底部标签是,HTML5中footer标签的用法你知道吗?,HTML5中的footer标签是什么意思?...
- 【JZOJ A组】Melancholy
- html图片排版技巧,【CSS技巧】多图片的垂直居中排版
- aliyun阿里云发送短信验证码和校验
- python钉钉机器人定时发送消息服务器_用Python写一个定时提醒的钉钉机器人
- MT2523用户手册,MT2523设计指南资料
- java web应用开发期末考试_JavaWeb期末考试A卷
- STM8S003超声波测距