kernel:input subsystem-2[A/B slot]

多点触摸技术A/B(Slot)协议

A/B协议究竟是如何划分

B协议又称为slot协议,slot直译为位置、槽,有两层含义,一层是位置,另一层是容器。在Input子系统中,它扮演的就是这两个角色。它产生于这样一个背景:

如果从Device获取的当前数据与上一个数据相同,我们有必要再上报当前数据吗?如果我们不管两次数据是否一致都上报,那就是A协议;如果我们选择不上报,那么既然需要比较,总需要把上一次数据存起来吧,slot就是做这个事情的,显然这就是Slot(B)协议。

A协议实现方式

A协议不会使用slot,多指处理中,它的报点序列如下(每一个序列都以input_report_***函数实现):

手指按下的动作:

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为一次事件的结尾。也就是说多指触摸的时候,android的中间件部分每收到一次SYN_MT_REPORT就形成一个点信息,收到一个点之后并不会立即处理,而是一个事件完成之后才会处理,SYN_REPORT就是这个事件的标志。A协议比较简单,我们也可以发现在上面的序列中根本就没有轨迹跟踪的信息,有的只是点坐标等信息

系统如果去判断当前的多个点各属于哪一条线 

我们假设前一次事件共有5个点,本次触摸也有5个点,系统会分别计算前一次5个点与本次5个点的距离,distance[prev_i, curr_j] (i=0,1,...,4;j=0,1,...4),这样会产生总共5*5=25个数字。然后对这25个数字进行排序,android用的是堆排序。(我们在系统上如果用多指,一般最多也是双值,也就是4个数据,这里采用了堆排序,不知是出于什么情况考虑,感觉换个方法可能更实用些。)下面的任务就是判断哪些当前点与前一次的点最近,那么赋予它们相同的id,应用收到这个信息后,就可以知道当前点属于哪条线了。

 

手抬起来的时候又用什么样的序列来通知系统

 

SYN_MT_REPORT

SYN_REPORT

只有SYNC,没有其它任何信息,系统就会认为此次事件为UP。

 

B协议实现方式

 

B协议使用了slot,还有一个新面孔TRACKING_ID.

手指按下的动作:

ABS_MT_SLOT 0

ABS_MT_TRACKING_ID **

ABS_MT_POSITION_X x[0]

ABS_MT_POSITION_Y y[0]

ABS_MT_SLOT 1

ABS_MT_TRACKING_ID **

ABS_MT_POSITION_X x[1]

ABS_MT_POSITION_Y y[1]

SYN_REPORT

没有SYN_MT_REPORT,那么它用什么来跟踪当前点属于哪一条线呢,用的就是ABS_MT_TRACKING_ID,当前序列中某点的ID值,如果与前一次序列中某点的ID值相等,那么他们就属于同一条线。既然如此,那么android系统中还需要做排序等运算吗?当然不需要。

 

手指全部抬起的时候序列又是怎样的
ABS_MT_SLOT 0
ABS_MT_TRACKING_ID -1
SYN_REPORT
ABS_MT_SLOT 1
ABS_MT_TRACKING_ID -1
SYN_REPORT
这里上报的ABS_MT_TRACKING_ID为-1,也只有这里该值才可以小于零,收到该值,系统就会清除对应的ID。看似简单的两个协议内容到这里就分析完毕了。
 
附上android 4.0上报方式(linux必须2.6.38以上)

1.  #include <linux/input/mt.h>

1.  //down

2.      input_mt_slot(ts->input_dev, id);

3.     //input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);

4.     input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, true);

5.     input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);

6.      input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);

7.      input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);

ps:个人感觉注释的那一行是在初次手指摁下才会执行,移动的时候就不执行这句话了
//up

1.      input_mt_slot(ts->input_dev, id);

2.    //input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);

3.     input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);

ps:同理,注释的这句应该是在slot为0的时候不执行
 

1.  //init

2.     //__set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);

3.      input_mt_init_slots(ts->input_dev, 255);

上面两条ps是在本人看了内核文档介绍多触点以后的感觉,不一定对

  对于type B设备的驱动,在每个数据包的开始,通过调用input_mt_slot()进行分割,同时带入一个参数:slot。这会产生一个ABS_MT_SLOT事件,它通知接收者准备更新给定slot的信息。.

 

总结

看了上面的分析,明显可以看出B协议要优于A协议,但事实上并不如此简单。B协议需要硬件上的支持,ID值并不是随便赋值的,而是硬件上跟踪了点的轨迹;另外,B协议的复杂性如果掌握不好往往会带来一些莫名其妙的问题,比如如果因为某些因素(同步等),在UP的时候少清除了一个slot的信息,那么下次单击的时候你也会惊奇地发现竟然有两个点(采用了B协议,slot已经保存了点信息,除非明确清除)。


Ps:
事件报告完毕后,设备驱动需要使用input_sync函数告诉输入子系统一个完整的报告已经发送。
void input_sync(struct input_dev *dev)
{
      input_event(dev,EV_SYN,SYN_REPORT,0);
}
这一点在鼠标移动处理中很重要,因为鼠标坐标的X分量和Y分量是分开传送的,需要利用input_sync函数来同步。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值