触摸屏操作

一、输入子系统

连接操作系统的输入设备,可不止一种,也许是一个标准PS/2键盘,也许是一个USB鼠标,或者是一块触摸屏,甚至是一个游戏机摇杆,Linux在处理这些纷繁各异的输入设备的时候,采用的办法还是找中间层来屏蔽各种细节,请看下图:
输入子系统

输入子系统

在Linux的内核中,对输入设备的使用,实际上运用了3大块来管理,他们分别是所谓的输入设备驱动层、输入子系统核心层,以及事件触发层。他们各自的工作分别是:

1.输入设备驱动层:每一种设备都有其特定的驱动程序,他们被妥当地装载到操作系统的设备模型框架内,封装硬件所提供的功能,向上提供规定的接口。
2.核心层:此处将收集由设备驱动层发来的数据,整合之后触发某一事件
3.事件触发层:这一层是我们需要关注的,我们可以通过在用户空间读取相应设备的节点文件来获知某设备的某一个动作。

以触摸屏为例,当手指在屏幕上滑动的时候,数据流大致是这样的:驱动层中的触摸屏驱动会源源不断地产生触摸屏相关数据,并向上递送给内核输入子系统,输入子系统进一步将这些信息规整为统一的结构体,并借助事件触发层发往对应的设备节点,至此,应用程序即可从这些设备节点读取相关信息。

值得注意的是,底层驱动产生的设备数据与上层应用读取设备数据是两个完全异步的过程,彼此之间是没有耦合和约束的,例如:当底层驱动产生的触摸屏坐标信息比应用层读取的速度要快时,应用程序将会丢失一部分坐标信息。


二、检查触摸屏是否能正常运行:

使用cat 命令来查看触摸屏的设备文件是否能读取到数据,需要用手指触摸屏以下屏幕,如果如下有数据(乱码)出现则表示触摸屏能正常工作。

#cat /dev/input/event0
��TC  ��TC      V��T
                    C   J��TC ��T��
J��T�
��T�o��T�o���T�oJ��T�o��Th�J��Tl���Tq�
                                      ���Tv�
                                            ��Tz�
                                                 J��T¼�
��T£J��T(                                              ��T��

三、分析头文件

/usr/include/linux/input.h
/usr/include/linux/input-event-codes.h

以下是对/usr/include/linux/input.h头文件中声明的事件类型结构体:
也就是所以后所有通过输入子系统获得的输入信息都会被封装为以下格式。

struct input_event {
    struct timeval time;  // 事件发生的时间
    __u16 type;         // 事件的类型(用于区分事件触发的硬件),比如键盘、鼠标、触摸屏....
    __u16 code;         // 事件的编码, 比如是键盘事件,本成员用于区分具体的按键编号
    __s32 value;        // 事件的值,0 - 1 比如某一个按键是按下还是松手 
};

四、尝试读取触摸屏的数据

分析数据

Time:1420075279.538277   Type:3   Code:0         Value:189
Time:1420075279.538299   Type:3   Code:1         Value:382
Time:1420075279.538303   Type:1   Code:330       Value:1
Time:1420075279.538307   Type:0   Code:0         Value:0
Time:1420075279.638614   Type:1   Code:330       Value:0
Time:1420075279.638619   Type:0   Code:0         Value:0

分析头文件/usr/include/linux/input-event-codes.h

/*
 * Event types  事件的类型
 */
#define EV_SYN          0x00  同步信号(事件的分割标记)
#define EV_KEY          0x01  按键事件
#define EV_REL          0x02  相对位移事件 一般指鼠标事件
#define EV_ABS          0x03  绝对位移事件 一般指触摸屏事件

/*
 * Keys and buttons  key事件的编码
 */
 #define BTN_TOUCH       0x14a  触摸屏被触摸的事件
 
 /*
 * Absolute axes  绝对位移事件
 */ 
#define ABS_X           0x00   X轴 
#define ABS_Y           0x01   Y轴
#define ABS_Z           0x02   Z轴
Time:1420075279.538277   Type:3   Code:0         Value:189  触摸屏事件 X轴 189
Time:1420075279.538299   Type:3   Code:1         Value:382  触摸屏事件 X轴 382
Time:1420075279.538303   Type:1   Code:330       Value:1    按键事件  触摸的事件 按下
========================================================    同步信号
Time:1420075279.638614   Type:1   Code:330       Value:0    按键事件  触摸的事件 松开
========================================================    同步信号

分析得到:
    (189,382)

五、其他外设

ioctl()
该函数是沟通应用层和驱动层的有力武器,底层开发人员在为硬件设备编写驱动的时候,常常将某些操作封装为一个函数,并为这些接口提供一个所谓的命令字CMD,应用层开发者可以通过 ioctl() 函数配合命令字,非常迅捷地绕过操作系统中间层层机构直达驱动层,调用对应的功能。
从这个意义上讲,函数 ioctl() 像是一个通道,只提供函数调用路径,具体的功能由所谓命令字决定,下面是函数的接口规范说明:

函数原型

关键点:

  • request 就是所谓的命令字。
  • 底层驱动开发者可以自定义命令字。
  • 对于某些常见的硬件设备的常见功能,系统提供了规范的命令字。

如何使用

.
├── led.c   # 驱动的源代码 (参观一下就好)
├── led.ko  # 驱动文件(编译驱动源码led.c之后得到的驱动文件)
└── led_test.c # 驱动的测试代码(应用层代码)

1. 下载到开发板

led.ko + 测试程序传到开发板上

 #编译测试代码
 arm-linux-gcc led_test.c  -o ledTest
 
#下载到开发板
scp -O ledTest  root@192.168.46.3:/
scp -O led.ko   root@192.168.46.3:/

2. 在开发板中安装驱动

lsmode   # 查看当前已经按照的模块
insmod led.ko  # 安装led.ko 模块

# 当我们发现如果已经安装了一个驱动
[root@GEC6818 /]#lsmod
led 1593 0 - Live 0xbf000000 (O)

# 可以先把他卸载掉
rmmod led
函数原型

3.运行测试程序

posted @ 2025-11-11 08:25  林明杰  阅读(3)  评论(0)    收藏  举报