Linux Android 多点触摸协议 原文出自【比特网】,转载请保留原文链接:http://soft.chinabyte.com/os/71/12306571.shtml

为了使用功能强大的多点触控设备。就须要一种方案去上报用户层所需的具体的手指触摸数据。

这个文档所描写叙述的多点触控协议能够让内核驱动程序向用户层上报随意多指的数据信息。


  使用说明


  单点触摸信息是以ABS承载并按一定顺序发送,如BTN_TOUCH、ABS_X、ABS_Y、SYNC。而多点触摸信息则是以ABS_MT承载并按一定顺序发送。如ABS_MT_POSITION_X、ABS_MT_POSITION_Y,然后通过调用input_mt_sync()产生一个 SYN_MT_REPORT event来标记一个点的结束,告诉接收方接收当前手指的信息并准备接收其他手指的触控信息。

最后调用 input_sync()函数上报触摸信息開始动作并告诉接收方開始接收下一系列多点触摸信息。




  协议定义了一系列ABS_MT事件。这些事件被分为几大类,充许仅仅应用当中的一部份,多点触摸最小的事件集中应包含ABS_MT_TOUCH_MAJOR、ABS_MT_POSITION_X和 ABS_MT_POSITION_Y。以此来实现多点触摸。

假设设备支持ABS_MT_WIDTH_MAJOR这个事件,那么此事件能够提供手指触摸接触面积大小。

触摸方向等信息能够由ABS_MT_TOUCH_MINOR, ABS_MT_WIDTH_MINOR and ABS_MT_ORIENTATION提供。ABS_MT_TOOL_TYPE提供触摸设备的类别。如手或是笔或是其他。

最后有些设备可能会支持ABS_MT_TRACKING_ID,用来支持硬件跟踪多点信息,即该点属于哪一条线等。


  下面是两点触摸支持的最小事件集序列:


  ABS_MT_TOUCH_MAJOR


  ABS_MT_POSITION_X


  ABS_MT_POSITION_Y


  SYN_MT_REPORT //上报第一个点


  ABS_MT_TOUCH_MAJOR


  ABS_MT_POSITION_X


  ABS_MT_POSITION_Y


  SYN_MT_REPORT //上报第二个点


  SYN_REPORT //開始动作


  Event 原语


  “接触”一词用来描写叙述一个物体直接碰到还有一个物体的表面。




  ABS_MT_TOUCH_MAJOR描写叙述了主接触面的长轴,它和X,Y同一个单位,假设一个面的分辨率为X*Y。则ABS_MT_TOUCH_MAJOR的最大值为sqrt(X^2+Y^2)


  ABS_MT_TOUCH_MINOR描写叙述了接触面的短轴。假设接触面是圆形,它能够不用。


  ABS_MT_WIDTH_MAJOR描写叙述了接触工具的长轴


  ABS_MT_WIDTH_MINOR描写叙述了接触工具的短轴


  ABS_MT_TOUCH_MAJOR := max(X, Y)


  ABS_MT_TOUCH_MINOR := min(X, Y)


  ABS_MT_ORIENTATION := bool(X > Y)


  以上四个參数能够用来生成额外的触摸信息,如ABS_MT_TOUCH_MAJOR/ABS_MT_WIDTH_MAJOR的比率能够用来描写叙述压力。


  ABS_MT_ORIENTATION


  ABS_MT_POSITION_X接触面的中心点X坐标


  ABS_MT_POSITION_Y接触面的中心点Y坐标


  ABS_MT_TOOL_TYPE描写叙述接触工具类型。非常多内核驱动无法区分此參数如手指及笔,假设是这样,该參数能够不用。协议眼下支持MT_TOOL_FINGER和MT_TOOL_PEN两种类型。


  ABS_MT_BLOB_ID形状集ID,集合几个点以描写叙述一个形状,非常多驱动没有形状属性,此參数能够不用。




  ABS_MT_TRACKING_ID描写叙述了从接触開始到释放的整个过程的集合。假设设备不支持。此參数但是不用。


  触摸轨迹


  仅有少数设备能够明触的标识真实的 trackingID,多数情况下 trackingID仅仅能来标识一次触摸动作的过程。


  手势


  多点触摸指定的应用是创建手势动作, TOUCH和 WIDTH參数经经常使用来差别手指的压力和手指间的距离,另外 MINOR类的參数能够用来差别设备的接触面的大小(点接触还是面接触)。ORIENTATION能够产生旋转事件。




  ===============================================================================================================


  在Linux内核支持的基础上。Android在其2.0源代码中添加多点触摸功能。由此触摸屏在Android的frameworks被全然分为2种实现途径:单点触摸屏的单点方式,多点触摸屏的单点和多点方式。


  在Linux的input.h中。多点触摸功能依赖于下面几个基本的软件位:


  ……


  #define SYN_REPORT0


  #define SYN_CONFIG1


  #define SYN_MT_REPORT2


  ……


  #define ABS_MT_TOUCH_MAJOR0x30


  #define ABS_MT_TOUCH_MINOR0x31


  #define ABS_MT_WIDTH_MAJOR0x32


  #define ABS_MT_WIDTH_MINOR0x33


  #define ABS_MT_ORIENTATION0x34


  #define ABS_MT_POSITION_X0x35


  #define ABS_MT_POSITION_Y0x36


  #define ABS_MT_TOOL_TYPE0x37


  #define ABS_MT_BLOB_ID0x38


  ……


  在Android中相应的软件位定义在RawInputEvent.java中:


  ……


  public class RawInputEvent {


  ……


  public static final int CLASS_TOUCHSCREEN_MT = 0x00000010;


  ……


  public static final int ABS_MT_TOUCH_MAJOR = 0x30;


  public static final int ABS_MT_TOUCH_MINOR = 0x31;


  public static final int ABS_MT_WIDTH_MAJOR = 0x32;


  public static final int ABS_MT_WIDTH_MINOR = 0x33;


  public static final int ABS_MT_ORIENTATION = 0x34;


  public static final int ABS_MT_POSITION_X = 0x35;


  public static final int ABS_MT_POSITION_Y = 0x36;


  public static final int ABS_MT_TOOL_TYPE = 0x37;


  public static final int ABS_MT_BLOB_ID = 0x38;


  ……


  public static final int SYN_REPORT = 0;


  public static final int SYN_CONFIG = 1;


  public static final int SYN_MT_REPORT = 2;


  ……


  在Android中。多点触摸的实现方法在具体的代码实现中和单点是全然区分开的。

在Android代码的EventHub.cpp中,单点屏和多点屏由例如以下代码段来判定:


  int EventHub::open_device(const char *deviceName)


  {


  ……


  if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)


  && test_bit(ABS_MT_POSITION_X, abs_bitmask)


  && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {


  device->classes |= CLASS_TOUCHSCREEN | CLASS_TOUCHSCREEN_MT;


  //LOGI("It is a multi-touch screen!");


  }


  //single-touch?


  else if (test_bit(BTN_TOUCH, key_bitmask)


  && test_bit(ABS_X, abs_bitmask)


  && test_bit(ABS_Y, abs_bitmask)) {


  device->classes |= CLASS_TOUCHSCREEN;


  //LOGI("It is a single-touch screen!");


  }


  ……


  }


  我们知道。在触摸屏驱动中,通常在probe函数中会调用input_set_abs_params给设备的input_dev结构体初始化,这些input_dev的參数会在Android的EventHub.cpp中被读取。如上可知,假设我们的触摸屏想被当成多点屏被处理,仅仅须要在驱动中给input_dev额外添加下面几个參数就可以:


  input_set_abs_params(mcs_data.input, ABS_MT_POSITION_X, pdata->abs_x_min, pdata->abs_x_max, 0, 0);


  input_set_abs_params(mcs_data.input, ABS_MT_POSITION_Y, pdata->abs_y_min, pdata->abs_y_max, 0, 0);


  input_set_abs_params(mcs_data.input, ABS_MT_TOUCH_MAJOR, 0, 15, 0, 0);


  //相当于单点屏的ABX_PRESSURE


  input_set_abs_params(mcs_data.input, ABS_MT_WIDTH_MAJOR, 0, 15, 0, 0);


  //相当于单点屏的ABS_TOOL_WIDTH


  因为多点触摸技术须要採集到多个点,然后再一起处理这些点,所以在软件实现中须要保证每一波点的准确性和完整性。因此。Linux内核提供了input_mt_sync(struct input_dev * input)函数。

在每波的每一个点上报后须要紧跟一句input_mt_sync()。 当这波全部点上报后再使用input_sync()进行同步。比如一波要上报3个点:


  ……


  input_mt_sync(input);


  ……


  input_mt_sync(input);


  ……


  input_mt_sync(input);


  input_sync(input);


  注:即使是仅上报一个点的单点事件。也须要一次input_my_sync。


原文出自【比特网】,转载请保留原文链接:http://soft.chinabyte.com/os/71/12306571.shtml

原文地址:https://www.cnblogs.com/cxchanpin/p/7288922.html