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还多的触控点。 

时间: 2024-09-27 21:22:52

CTP多点触摸协议【转】的相关文章

内核中的多点触摸协议文档 Multi【转】

转自:http://www.arm9home.net/read.php?tid=24754 前段时间改写了一个GT801的内核驱动,仔细阅读 MT Event 上报的时候,发现这个驱动是针对 Android 系统有所偏重的.于是便仔细阅读了一下内核文档中关于多点触摸协议的介绍. 多点触摸的信息,是触摸屏这样的触摸设备向 input core 上报 MT 消息传递的.这些 MT消息,可以通过 设备文件的接口,被应用程序读取到. 整个消息传递过程,以及 上层应用程序(DirectFB / Xorg

Linux内核触摸屏驱动--多点触摸 【转】

  转自:http://blog.chinaunix.net/uid-24227137-id-3127126.html 简介 为了使用功能强大的多点触控设备,就需要一种方案去上报用户层所需的详细的手指触摸数据.这个文档所描述的多点触控协议可以让内核驱动程序向用户层上报任意多指的数据信息. 使用说明 单点触摸信息是以ABS承载并按一定顺序发送,如BTN_TOUCH.ABS_X.ABS_Y.SYNC.而多点触摸信息则是以 ABS_MT承载并按一定顺序发送,如ABS_MT_POSITION_X.ABS

Linux 内核驱动--多点触摸接口【转】

转自:http://blog.csdn.net/joard_yang/article/details/6225937 译自:linux-2.6.31.14/Documentation/input/multi-touch-protocol.txt 简介 为了使用功能强大的多点触控设备,就需要一种方案去上报用户层所需的详细的手指触摸数据.这个文档所描述的多点触控协议可以让内核驱动程序向用户层上报任意多指的数据信息. 使用说明 单点触摸信息是以ABS承载并按一定顺序发送,如BTN_TOUCH.ABS_

Windows 7开发:多点触摸之手势

目标 在本动手实验中,我们将学习如何管理手势事件,包括: • 理解使用手势事件操作对象的含义 • 检查多点触摸 硬件是否存在及其就绪情况 • 从手势 Windows Message 中提取信息 系统要求 要完成本实验,必须拥有以下工具: • Microsoft Visual Studio 2008 SP1 • Windows 7 • Windows 7 SDK • 一台多点触摸硬件设备 引言 要创建多点触摸驱动的应用程序,有 3 种方法可供 选择:"好"."出色"或

Windows 7开发:多点触摸之WM_TOUCH

目标 在本动手实验中,我们将学习如何管理手势事件,包括: • 理解使用手势事件操作对象的含义 • 检查多点触摸 硬件是否存在及其就绪情况 • 从手势 Windows Message 中提取信息 系统要求 要完成本实验,必须拥有以下工具: • Microsoft Visual Studio 2008 SP1 • Windows 7 • Windows 7 SDK • 一台多点触摸硬件设备 引言 要创建多点触摸驱动的应用程序,有 3 种方法可供 选择:"好"."出色"或

win7系统下多点触摸功能的方法

Win 7系统中的多点触摸功能相信很多朋友都知道,但是很多朋友都不知道要怎么开启使用.可如何在Win 7 Beta中开启多点触摸功能呢?下面小编就为大家详细介绍! 首先,需要一台支持触摸特性的PC,目前市面上可选的产品主要有: * HP TouchSmart All-in-One PCs (IQ500 series & IQ800 series) * HP TouchSmart tx2 Tablet PC * Dell Latitude XT Tablet PC 其次,需要安装最新的多点触摸驱动

Win7系统新功能介绍:多点触摸和跳跃菜单

Windows 7新增了许多实用的功能,有些功能虽然很小,不太引人注目,但是小细节里的隐藏着大秘密,下面我们就为大家一一解读Windows 7系统新功能小细节里的大秘密. 1.多点触摸 Windows 7的多点触控功能可谓是顺应民心,由于近两年触屏手机的大肆宣扬,电脑产品也开始跃跃欲试,而windows 7为触摸屏技术提供了发挥的软件空间,使之成为可能. 不同于一般的触摸屏,Windows 7引入了全新的多点触控概念,即一个屏幕多点操作.由于是多点触摸,机器能够感应到手指滑动的快慢以及力度(力度

Android实现手势滑动多点触摸放大缩小图片效果_Android

网上文章虽多,但是这种效果少之又少,我真诚的献上以供大家参考 实现原理:自定义ImageView对此控件进行相应的layout(动态布局). 这里你要明白几个方法执行的流程: 首先ImageView是继承自View的子类.onLayout方法:是一个回调方法.该方法会在在View中的layout方法中执行,在执行layout方法前面会首先执行setFrame方法.setFrame方法:判断我们的View是否发生变化,如果发生变化,那么将最新的l,t,r,b传递给View,然后刷新进行动态更新UI

android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果

转自: http://blog.csdn.net/jj120522/article/details/8467810 首先呢,还是一贯作风,我们先来看看众多应用中的示例:(这种效果是很常见的,可以说应用的必须品.)                             搜狐客户端                                    百度新闻客户端                              新浪微博                              凤凰新