输入系统框架及调试

一、框架概述

在应用开发中,只需要知道API使用输入子系统。但是如果了解更多的内核中子系统框架,了解数据流程,有助于解决开发过程中碰到的硬件问题、驱动问题。
输入子系统的框架如下:
核心层把五花八门的硬件数据转换成统一的格式,发送给事件层,事件层会统一分发给App。
在这里插入图片描述

假设用户程序直接访问/dev/input/event0设备节点,或者使用tslib访问设备节点,数据的流程如下:

  1. App发起读操作,若无数据则休眠
  2. 用户操作设备,硬件产生中断
  3. 输入系统驱动层对应的驱动程序处理中断。
    • 读取到数据,转换位标准的输入事件,向核心层汇报
    • 输入事件就是一个struct input_event结构体
  4. 核心层可以决定把输入事件转发给上面哪个handler来处理
    • 从handler名字来看,它就是用来处理输入操作的。其中有evdev_handler、kdb_handler、joydev_handler等等
    • 最常用的是evdev_handler:它把input_event保存在内核,APP可以读取到原始数据,同时支持多个APP同时访问,获得同一份数据
    • 当APP在等待数据时,evdev_handler会把它唤醒,App就可以返回数据
  5. App对输入事件的处理
    • App获得数据的方法有2中,直接访问设备节点(/dev/input/event0),或者通过tslib、libinput着类库来间接访问设备节点。

二、编写App需要的知识

2.1 内核中输入设备的表示

内核中使用input_dev结构体来表示输入设备,内容如下:

struct input_dev {
    const char *name;
    const char *phys;
    const char *uniq;
    struct input_id id;

    unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
	//各种的事件类型支持表,每个位都表示特定类型中的具体细节
    unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
    unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
    unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
    unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
    unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
    unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
    unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
    unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
    unsigned long swbit[BITS_TO_LONGS(SW_CNT)];

		//....
		
};

2.2 App可以得到什么数据

每个输入事件,对应一个一个的struct input_event,内容如下:

// include/uapi/linux/input.h
struct input_event { 
//每个输入事件input_event中都含有发生时间,"自系统启动以来过了多少时间"
    struct timeval time;		
    __u16 type;				//哪类事件
    __u16 code;				//哪个事件
    __s32 value;			//事件值
};

// include/uapi/linux/time.h
struct timeval {
    __kernel_time_t     tv_sec;     /* seconds */
    __kernel_suseconds_t    tv_usec;    /* microseconds */
};

上面的input_event中的三个属性,分别对应不同的内容:

  1. type:表示哪类事件
    比如EV_KEY表示按键类、EV_REL表示相对位移(比如鼠标),EV_ABS表示绝对位置(比如触摸屏)
/*
 * Event types
 */
//include/uapi/linux/input-event-codes.h
#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)
  1. code:表示该类事件下的哪一个事件
    比如对于EV_KEY(按键)类事件,它表示键盘。
    键盘上有很多键盘,比如数字键1、2、3,字母键A、B、C里等。
//include/uapi/linux/input-event-codes.h
#define KEY_RESERVED			0			//KEY_开头的各种各样的按键
#define KEY_ESC					1
#define KEY_1					2
#define KEY_2					3
#define KEY_3					4
#define KEY_4					5
#define KEY_5					6
#define KEY_6					7
#define KEY_7					8
#define KEY_8					9
#define KEY_9					10
#define KEY_0					11
#define KEY_MINUS				12
#define KEY_EQUAL				13
#define KEY_BACKSPACE			14
#define KEY_TAB					15

然后对于触摸屏,它提供的是绝对位置信息,有X方向、Y方向,还有压力值。

#define ABS_X           0x00		//X方向
#define ABS_Y           0x01		//y方向
#define ABS_Z           0x02		//压力值
  1. value:表示事件值
    对于按键:它的value可以是0(表示按键被按下)、1(表示按键被松开)、2(表示长按)
    对于触摸屏:它的value就是坐标值、压力值。
  2. 事件之间的界限
    APP读取数据时,可以得到一个或多个数据,比如一个触摸屏的一个触电会上报X、Y位置信息,也可能会上报压力值。
    APP怎么知道它已经读到了完整的数据?
    驱动程序上报完一些列的数据后,它会上报一个“同步事件”,表示数据上报完毕。
    App读到”同步事件“时,就知道已经读完了当前的数据。
    同步事件也是一个input_event结构体,它的type、code、value三项都是0

2.3 输入子系统支持完成的API操作

输入子系统支持这些机制:
阻塞和非阻塞
POLL/SELECT
异步通知

三、调试技巧

3.1 了解设备信息

输入设备节点名为/dev/input/eventX(也可能时/dev/eventX,X可以是0、1、2…)
查看设备节点,可以执行下面的命令

[root@ebf6ull:~]# ls /dev/input/* -l
crw-rw----    1 root     input      13,  64 Jan  1 00:08 /dev/input/event0
crw-rw----    1 root     input      13,  65 Jan  1 00:08 /dev/input/event1
crw-rw----    1 root     input      13,  63 Jan  1 00:08 /dev/input/mice

/dev/input/by-path:
total 0
lrwxrwxrwx    1 root     root             9 Jan  1 00:08 platform-20cc000.snvs:snvs-powerkey-event -> ../event0
lrwxrwxrwx    1 root     root             9 Jan  1 00:08 platform-gpio-keys-event -> ../event1
[root@ebf6ull:~]#

怎么知道这些设备节点对应什么硬件呢?可以在板子上执行以下命令:
cat /proc/bus/input/devices
这条指令的含义就是获取与event对应的相关设备信息,可以看到类似以下的结果:

[root@ebf6ull:~]# cat /proc/bus/input/devices
I: Bus=0019 Vendor=0000 Product=0000 Version=0000
N: Name="20cc000.snvs:snvs-powerkey"
P: Phys=snvs-pwrkey/input0
S: Sysfs=/devices/soc0/soc/2000000.aips-bus/20cc000.snvs/20cc000.snvs:snvs-powerkey/input/input0
U: Uniq=
H: Handlers=kbd event0
B: PROP=0
B: EV=3
B: KEY=100000 0 0 0

I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="sgpio-keys"
P: Phys=gpio-keys/input0
S: Sysfs=/devices/soc0/sgpio-keys/input/input1
U: Uniq=
H: Handlers=kbd event1
B: PROP=0
B: EV=3
B: KEY=800

I: Bus=0018 Vendor=0416 Product=1001 Version=0200
N: Name="Goodix Capacitive TouchScreen"
P: Phys=input/ts
S: Sysfs=/devices/soc0/soc/2100000.aips-bus/21a0000.i2c/i2c-0/0-005d/input/input2
U: Uniq=
H: Handlers=kbd event2
B: PROP=2
B: EV=b
B: KEY=400 0 0 0 0 0 0 20000000 0 0 0
B: ABS=2658000 3

这个结果的第一列有I、N、P、S、U、H、B,这些对应的一行的含义是:

  1. I:由结构体struct inputid来进行描述,驱动程序中会定义这样的结构体:
// include/uapi/linux/input.h
struct input_id {
	__u16 bustype;
	__u16 vendor;
	__u16 product;
	__u16 version;
};
  1. N:name of the device,设备名称
  2. P:physical path to the device in the system hierarchy,系统层次结构体中设备的物理路径
  3. S:sysfs path,位于sys文件系统的路径
  4. U:unique identification code for the device(if device has it),设备的位移标识码
  5. H:list of input handles associated with the device,与设备关联的输入句柄列表
  6. B:bitmaps(位图)
    • PROP:device properties and quirks(设备属性)
    • EV:types of events supported by the device(设备支持的事件类型)
    • KEY:keys/buttons this device has(此设备具有的键/按钮)
    • MSC:miscellaneous events supported by the device(设备支持的其他事件)
    • LED:leds present on the device(设备上的指示灯)

这里需要注意以下B的属性,比如B: EV=b用来表示该设备支持哪类输入事件。
b的二进制是1011,根据Event types的选项,支持的是第0位(EV_SYN)、第1位(EV_KEY),第三位(EV_ABS)

同样的B: ABS=2658000 3abs后面的是2个32位的数字,即0x2658000和0x3。组成一个64位的数字“0x2658000 00000003"
对应的位有0、1、47、48、50、53、54,转换成宏是0、1、0x2f、0x30、0x32、0x35、0x36:

#define ABS_X           0x00
#define ABS_Y           0x01
#define ABS_MT_SLOT     0x2f    /* MT slot being modified */
#define ABS_MT_TOUCH_MAJOR  0x30    /* Major axis of touching ellipse */
#define ABS_MT_WIDTH_MAJOR  0x32    /* Major axis of approaching ellipse */
#define ABS_MT_POSITION_X   0x35    /* Center X touch position */
#define ABS_MT_POSITION_Y   0x36    /* Center Y touch position */

这个输入设备支持上述的ABS_X、ABS_Y ABS_MT_SLOT、ABS_MT_TOUCH_MAJOR、ABS_MT_WIDTH_MAJOR、ABS_MT_POSITION_X、ABS_MT_POSITION_Y这些绝对位置事件。

3.2 使用命令读取数据

调试输入系统时,直接执行类似下面的命令,然后操作对应的输入设备即可读出数据:
root@npi:~# hexdump /dev/input/event2
在开发板上执行上述命令之后,点击按键或是点击触摸屏,就会打印下面的信息:

# 序号	秒(占2个) 微秒(占2个) type code  value(占2个)
0000000 46d4 6148 7f73 0004 0003 002f 0000 0000		# type是3,对应EV_ABS, code=0x2f对应ABS_MT_SLOT,
0000010 46d4 6148 7f73 0004 0003 0039 0002 0000		# type=3, code=0x39,对应ABS_MT_TRACKING_ID,值位0x20000
0000020 46d4 6148 7f73 0004 0003 0035 01e0 0000		# type=3, code=0x35,对应ABS_MT_POSITION_X,值为0x1e00000
0000030 46d4 6148 7f73 0004 0003 0036 00fb 0000	
0000040 46d4 6148 7f73 0004 0003 0030 0049 0000
0000050 46d4 6148 7f73 0004 0003 0032 0049 0000
0000060 46d4 6148 7f73 0004 0001 014a 0001 0000
0000070 46d4 6148 7f73 0004 0003 0000 01e0 0000
0000080 46d4 6148 7f73 0004 0003 0001 00fb 0000
0000090 46d4 6148 7f73 0004 0000 0000 0000 0000		# type=0, code=0, value=0,同步事件
00000a0 46d4 6148 70be 0006 0003 0039 ffff ffff
00000b0 46d4 6148 70be 0006 0001 014a 0000 0000
00000c0 46d4 6148 70be 0006 0000 0000 0000 0000		# type=0, code=0, value=0,同步事件
阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
W3C联盟系统是一个收集展现web技术教程等系统,完美的展现给用户最好的简单学习一的一面,布局等优化借鉴了菜鸟教程的精华,在线调试预览 用户体验放到第一位,非常符合当代站长的阅读学习等,主要使用功能等在详细介绍下会有,W3C联盟系统前端前台采用UIkit框架,后台采用layui后台框架,后端采用PHP+MYSQL开发而成,布局精美、没有一点残余代码 、多年的编程经验养成良好的注释习惯 代码易懂易开发,布局简单合理。W3C联盟系统和普通的文档系统内不一样、我们采用强大的可视化编辑器,html及php等多种代码在线演示一键插入、布局简单明了,你要是有点前端基础的还可以自定义添加单页内容自定义调用。系统采用自动seo优化给链接自动添加nofollow及后台自定义优化替换。 基本设置: 网站名称、自定义首页独立标题、seo关键字描述、底部版权自定义布局、统计代码。 网站状态可关闭开启等操作自定义提示关站内容。 修改了css及js无需清除浏览器缓存主题版本变更下即可。 上传配置、可自定义配置上传文件后缀,上传到七牛云端,上传大小,编辑器截图粘贴配置图片类型、base64 保存图片和上传服务器可选。 php在线运行权限控制。 邮箱配置等一系列操作。 其他配置 全局css及全局js、没错是我们的主要优点我们其他的系统必须的配置,方便在后台自定义主题 及js脚本自定义添加。 通用过滤添加有效,自定义过滤替换你在编辑的内容。 通用过滤展示有效,同上 在内容自定义喜欢展示的关键字,seo的必备。 添加一键获取配置,由于考虑到大家添加教程会在其他网站进行搬家,这里添加了输入链接一键获取内容等配置减少我们的手动复制。 百度主动推送配置,自由推送想推送多少就推送多少。 自定义布局 这个功能主要非常的好用集合多年的用站经验来添加的,自定义可视化编辑布局得到自定义的变量名称 添加到任意你喜欢的模板位置 可用于广告等多用户,不要想到太单一。 强大的模型系统 对模型进行分类、添加模型等,对模型进行单独的seo标题描述图标自定义表名。 什么是模型,模型就是自定义添加一个数据库的表对这个表下单独进行分类文章数据等添加,市场上很多的网站太过单一自由一张的表不能自定义模型添加删除体验非常不友好。 自定义单页 单页不单单是单页、可以指定单页的文件路径,添加生成html文件自定义布局 边界层采用可视化布局直接编辑html代码等。 链接管理 前台顶部自定义链接及底部自定义链接,可自己添加代码前台调用自定义链接,后期可在w3cdata.com查看开发文档; 会员中心 前台会员登录余姚邮箱验证即可登录,登录状态1到2年内有效,登录可以收藏等简单操作; 插件使用 插件模板扩展非常方便 第一款插件文件后台编辑 使用方便后台制作 编辑增加目录增加文件等; 安全 对于w3c联盟的安全维护我们做的非常好,不对外报错有关信息,多年的php开发经验对php的安全一直在加强。 使用: 管理员在前台可对当前内容进行编辑 当前分类添加、在线预览数据可以直接修改。 后台内容单项更新采用一键操作非常方便。 前后台源代码布局整齐展示页面无任何报错,注释齐全使用明了。 后台一键自动升级  更多体验及需求欢迎提问及反馈,实用功能会毫不犹豫添加 W3C联盟系统 v1.3升级内容 对结构整体优化访问速度提升一倍 修复已知模板bug 对html在线运行进行优化 个别不能识别运行 新增对插件兼容 新增一键获取自定义过滤 内容详情页,描述进行优化 新增单页自动生成文件 在线文件编辑  修复后台模板手机管理出现遮挡 修复单页数据统计出错 对登录是发送验证码按钮显示文字提示 去掉系统添加的nofollow标签 需要后台自行配置

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

习惯就好zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值