CTP多点触摸协议【转】
转自:http://blog.chinaunix.net/uid-26403844-id-5063920.html
linux kernel 2.6.30开始对多点触摸支持,最近高通要求所有CTP器件要用B 协议上报数据,协议A/B(slot)分析如下:
一、文档
多点触摸协议文档 kernel/Documentation/input/multi-touch-protocol.txt
二、协议分析
基于硬件的能力,触摸协议分为两种类型:
type A: 只能处理匿名接触,描述了如何把所有原始触摸数据发给接收者。
type B: 有能力跟踪并识别每个触摸点的设备,描诉了如何把每个触摸点的单独跟 新通过事件slot发给接收者。
两种协议的使用:
Protocol Example A:
--------------------
type A设备的最小的事件序列看起来就像下面这样
(可以通过adb shell getevent -lt /dev/input/event0 查看 eventX对应触摸屏):
ABS_MT_POSITION_X x[0]
ABS_MT_POSITION_Y y[0]
SYN_MT_REPORT
ABS_MT_POSITION_X x[1]
ABS_MT_POSITION_Y y[1]
SYN_MT_REPORT
…
SYN_REPORT
手抬起的时候是如下样子:
SYN_MT_REPORT
SYN_REPORT
只有SYNC,没有其它任何信息,系统就会认为此次事件为UP。
系统以SYN_MT_REPORT为一个点信息的结尾,收到一个点之后并不会立即处理, 而是一个事件完成之后才会处理,
SYN_REPORT就是这个事件的标志。A协议比较简单,我们也可以发现在上面的序列 中根本就没有轨迹跟踪的信息,
有的只是点坐标等信息,报上去的信息简单粗暴不需要什么顺序,系统根本无法识 别报上的点是属于哪一条线的,
事件过滤和手指跟踪的工作留给用户空间来实现。
Protocol Example B:
-------------------
type B设备的最小的事件序列看起来就像下面这样:
ABS_MT_SLOT 0
ABS_MT_TRACKING_ID 46
ABS_MT_POSITION_X x[0]
ABS_MT_POSITION_Y y[0]
ABS_MT_SLOT 1
ABS_MT_TRACKING_ID 47
ABS_MT_POSITION_X x[1]
ABS_MT_POSITION_Y y[1]
SYN_REPORT
手抬起的时候如下样子:
ABS_MT_SLOT 0
ABS_MT_TRACKING_ID -1
SYN_REPORT
ABS_MT_SLOT 1
ABS_MT_TRACKING_ID -1
SYN_REPORT
对于协议B,内核驱动应该把每一个识别出的触控和一个slot相关联,并使用该 slot来传播触摸状态的改变,通过修改关联
slot的ABS_MT_TRACKING_ID来达到对触摸点的创建,替换和销毁。上报 ABS_MT_TRACKING_ID -1 系统会清除对应的ID和slot,
再次按下手指时分配新ID值(ID值是每次+1的)
和协议A相比没有SYN_MT_REPORT,那么它用什么来跟踪当前点属于哪一条线呢,用 的就是ABS_MT_TRACKING_ID,当前序列中
某点的ID值,如果与前一次序列中某点的ID值相等,那么他们就属于同一条线,应 用层就不用在去劳心劳神的算那个点是那条线上
的啦。如果按下并一直按同一个点,那么input子系统会做个处理来屏蔽上下两次 相同的点,减少IO的负担。
协议B明显优越于协议A,但注意协议B是需要硬件支持的,ID值并不是随便赋值 的,而是硬件上跟踪了点的轨迹,比如按下一个点
硬件会跟踪这个点的ID,只要不抬起上报的点都会和这个ID相关。
三、代码编写
Protocol A:
-------------------------------------------------------------------------------------
注册:
set_bit(EV_SYN, input_dev->evbit);
set_bit(EV_KEY, input_dev->evbit);
set_bit(EV_ABS, input_dev->evbit);
set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, sensor_max_x, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, sensor_max_y, 0, 0);
input_register_device(input_dev);
上报:
for (finger = 0; finger < num_of_fingers; finger++) {
...//读取计算x、y坐标,id值,触摸的状态
if (finger_down) {
input_report_abs(input_dev, ABS_MT_POSITION_X, x);
input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
input_mt_sync(input_dev);
} else {
input_mt_sync(input_dev);
}
input_sync(input_dev);
如果注册了ABS_MT_PRESSURE,上报时就要上报ABS_MT_PRESSURE。
如果注册了BTN_TOUCH, 上报时就要上报BTN_TOUCH, 1:按下 0:抬起
上报log:
按下一个点抬起
[ 140.781791] EV_ABS ABS_MT_POSITION_X 00000148
[ 140.781801] EV_ABS ABS_MT_POSITION_Y 0000044f
[ 140.781805] EV_SYN SYN_MT_REPORT 00000000
[ 140.781807] EV_SYN SYN_REPORT 00000000
[ 140.796553] EV_SYN SYN_MT_REPORT 00000000
[ 140.796563] EV_SYN SYN_REPORT 00000000
按下两个点抬起
[ 245.011718] EV_ABS ABS_MT_POSITION_X 00000102
[ 245.011757] EV_ABS ABS_MT_POSITION_Y 000003d0
[ 245.011771] EV_SYN SYN_MT_REPORT 00000000
[ 245.011785] EV_ABS ABS_MT_POSITION_X 00000220
[ 245.011798] EV_ABS ABS_MT_POSITION_Y 00000419
[ 245.011810] EV_SYN SYN_MT_REPORT 00000000
[ 245.011819] EV_SYN SYN_REPORT 00000000
[ 245.025296] EV_SYN SYN_MT_REPORT 00000000
[ 245.025311] EV_SYN SYN_MT_REPORT 00000000
[ 245.025313] EV_SYN SYN_REPORT 00000000
Protocol B:
----------------------------------------------------------------------------------
注册:
set_bit(EV_SYN, input_dev->evbit);
set_bit(EV_KEY, input_dev->evbit);
set_bit(EV_ABS, input_dev->evbit);
set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, sensor_max_x, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, sensor_max_y, 0, 0);
input_mt_init_slots(input_dev, num_of_fingers); //和A相比多注册slot
input_register_device(input_dev);
如果注册了ABS_MT_PRESSURE,上报时就要上报ABS_MT_PRESSURE。
上报:
for (finger = 0; finger < num_of_fingers; finger++) {
...//读取计算x、y坐标和id,触摸的状态
input_mt_slot(input_dev, id);
if (finger_down) {
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 1);
input_report_abs(input_dev, ABS_MT_POSITION_X, x);
input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
} else { //finger_up
input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
}
}
input_mt_report_pointer_emulation(input_dev, false);
input_sync(input_dev);
上报log:
按下一个点抬起
[ 78.541863] EV_ABS ABS_MT_TRACKING_ID 00000007 按下分配ID
[ 78.541928] EV_ABS ABS_MT_POSITION_X 0000021b
[ 78.541944] EV_ABS ABS_MT_POSITION_Y 00000442
[ 78.541981] EV_SYN SYN_REPORT 00000000
[ 78.605574] EV_ABS ABS_MT_TRACKING_ID ffffffff 抬起释放ID ID=-1释放
[ 78.605595] EV_SYN SYN_REPORT 00000000
再次按下一个点抬起
[ 98.324526] EV_ABS ABS_MT_TRACKING_ID 00000008 按下分配ID 上一次的ID +1
[ 98.324590] EV_ABS ABS_MT_POSITION_X 000000c8
[ 98.324605] EV_ABS ABS_MT_POSITION_Y 0000037a
[ 98.324641] EV_SYN SYN_REPORT 00000000
[ 98.388583] EV_ABS ABS_MT_TRACKING_ID ffffffff 抬起释放ID ID=-1释放
[ 98.388603] EV_SYN SYN_REPORT 00000000
两个点同时按下抬起
[ 208.775409] EV_ABS ABS_MT_SLOT 00000000 多点时标示 属于哪个slot 标示slot 0
[ 208.775462] EV_ABS ABS_MT_TRACKING_ID 0000000e 分配ID
[ 208.775484] EV_ABS ABS_MT_POSITION_X 00000215
[ 208.775498] EV_ABS ABS_MT_POSITION_Y 0000037c
[ 208.775533] EV_SYN SYN_REPORT 00000000
[ 208.859516] EV_ABS ABS_MT_SLOT 00000001 标示slot 1
[ 208.859534] EV_ABS ABS_MT_TRACKING_ID 0000000f 分配ID 上一 次ID +1
[ 208.859538] EV_ABS ABS_MT_POSITION_X 000000e6
[ 208.859541] EV_ABS ABS_MT_POSITION_Y 0000031f
[ 208.859550] EV_SYN SYN_REPORT 00000000
[ 208.873597] EV_ABS ABS_MT_SLOT 00000000
[ 208.873637] EV_ABS ABS_MT_TRACKING_ID ffffffff 释放slot0 的ID
[ 208.873659] EV_ABS ABS_MT_SLOT 00000001
[ 208.873667] EV_ABS ABS_MT_TRACKING_ID ffffffff 释放slot1 的ID
[ 208.873688] EV_SYN SYN_REPORT 00000000
代码分析:
input_mt_slot()根据ID注册一个slot
static inline void input_mt_slot(struct input_dev *dev, int slot)
{
input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
}
input_mt_report_slot_state()分配ABS_MT_TRACKING_ID
void input_mt_report_slot_state(struct input_dev *dev,
unsigned int tool_type, bool active)
{
struct input_mt_slot *mt;
int id;
if (!dev->mt || !active) { //如果active 为0就上报 ABS_MT_TRACKING_ID = -1表示手指抬起
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
return;
}
mt = &dev->mt[dev->slot];
id = input_mt_get_value(mt, ABS_MT_TRACKING_ID);
if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type)//如果是从新触摸的点即上一次ABS_MT_TRACKING_ID=-1
id = input_mt_new_trkid(dev); //就从新分配ABS_MT_TRACKING_ID, 新ID上在上一次的基础上+1
//如果手指没抬起,即ABS_MT_TRACKING_ID大于0,ABS_MT_TRACKING_ID本次并没 有改变即还在一个轨迹上
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type);
}
input_mt_report_pointer_emulation(input_dev, false); 文档中写函数是用来 检测驱动是否能报告比slot还多的触控点。
CTP多点触摸协议【转】的更多相关文章
- Android 中多点触摸协议
http://blog.csdn.net/zuosifengli/article/details/7398661 Android 中多点触摸协议: 参考: http://www.kernel.org/ ...
- Linux/Android多点触摸协议
链接点击打开链接 关于Linux多点触摸协议大家可以参考kernel中的文档:https://www.kernel.org/doc/Documentation/input/multi-touch-pr ...
- 内核中的多点触摸协议文档 Multi【转】
转自:http://www.arm9home.net/read.php?tid=24754 前段时间改写了一个GT801的内核驱动,仔细阅读 MT Event 上报的时候,发现这个驱动是针对 Andr ...
- Linux与Android 多点触摸协议【转】
本文转载自:http://blog.csdn.net/xubin341719/article/details/7833277 一.Linux与Android 多点触摸协议 为了使用功能强大的多点触控设 ...
- Linux & Android 多点触摸协议
Linux & Android 多点触摸协议 Android4.0多点触摸入门 1 KERNEL 对于触摸屏的驱动我们简单的划分为两个主要的部分,一个是注册,另一个是上报. 1.1 注册 单点 ...
- Linux/Android多点触摸协议【转】
本文转载自: 链接点击打开链接 关于Linux多点触摸协议大家可以参考kernel中的文档:https://www.kernel.org/doc/Documentation/input/multi-t ...
- Linux Android 多点触摸协议 原文出自【比特网】,转载请保留原文链接:http://soft.chinabyte.com/os/71/12306571.shtml
为了使用功能强大的多点触控设备,就需要一种方案去上报用户层所需的详细的手指触摸数据.这个文档所描述的多点触控协议可以让内核驱动程序向用户层上报任意多指的数据信息. 使用说明 单点触摸信息是以ABS承载 ...
- 多点触摸(MT)协议(翻译)
参考: http://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt 转自:http://www.arm9home.ne ...
- 10.13 android输入系统_多点触摸驱动理论与框架
1.多点触摸驱动理论 驱动程序仅上报多个触点的位置就可以,是放大还是缩小由应用程序控制 对于多点触摸驱动在linux系统中有个输入子系统,其已经实现了open/read/write等接口 我们只需要实 ...
随机推荐
- 第二篇 Python初识别及变量名定义规范
第一个Python程序 可以打开notepad或者其他文本编辑器,输入:print("Hello Python!"),将文件保存到任意盘符下,后缀名是 .py 两种python程 ...
- 06-Mysql数据库----表的操作
06-表的操作 本节掌握 存储引擎介绍(了解) 表的增删改查 一.存储引擎(了解) 前几节我们知道mysql中建立的库===>文件夹,库中的表====>文件 现实生活中我们用来存储数据 ...
- Mininet简单性能测试
建一个简单的模型,使用一个单交换机,然后链接n个主机形成拓扑,然后对每个链路设置带宽,延迟时间,和丢包率. 这里就选择建一个单交换机和六个主机的作为例子. 创建py脚本生成拓扑:写一个类生成一个单交换 ...
- SQL SERVER 时间相关操作笔记
1.DATEADD函数: A. MSDN上的示例:http://msdn.microsoft.com/zh-cn/library/ms186819%28v=sql.90%29.aspx
- jquery UI 跟随学习笔记——拖拽(Draggable)
引言 这周暂时没有任务下达,所以老大给我的任务就是熟悉jquery相关插件,我就先选择了jquery UI插件,以及jquery库学习. 我用了两天的时候熟悉Interactions模块中的Dragg ...
- 浅析Python中的main函数
Python作为一门较为灵活的解释型脚本语言,其中定义的main()函数只有当该Python脚本直接作为执行程序时才会执行: 当该python脚本被作为模块(module)引入(import)时,其中 ...
- java线程(6)——线程池(下)
上篇博客java线程(5)--线程池(上)介绍了线程池的基本知识,这篇博客我们介绍一下常用的ThreadPoolExecutor. 定义 类图关系: ThreadPoolExecutor继承了Abst ...
- iOS 定时器开发详情
目录 概述 NSTimer performSelector GCD timer CADisplayLink 一.概述 在平时的开发任务中,定时器是我们常用的技术.这一节我们来学习iOS怎么使用定时器. ...
- 你试过不用if写代码吗?
我在教新手编程时,喜欢给他们一些小小的挑战,比如:不使用if语句(或者三元运算符.switch语句等)解决一些编程问题.这样做有什么意义吗?事实上,它可以迫使你从不同的角度寻找解决方法,也许可以找到更 ...
- 洛谷 P2218 [HAOI2007]覆盖问题 解题报告
P2218 [HAOI2007]覆盖问题 题目描述 某人在山上种了\(N\)棵小树苗.冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄膜把这些小树遮盖起来,经过一番长久的思考,他 ...