|
Multi-touch (MT) Protocol ------------------------- Copyright(C) 2009-2010 Henrik Rydberg<rydberg@euromail.se> 簡介------------ 為了發(fā)揮新近的多點觸摸和多用戶設備的強大功能,為多點觸摸定義一種上報詳細數(shù)據(jù)的方法(比如有多個物體直接接觸到設備的表面),是非常有必要的。這篇文檔描述了多點觸摸協(xié)議(multi-touch,MT),是的內核驅動可以對多個隨意數(shù)量的觸控事件上報詳細的數(shù)據(jù)信息。 基于硬件的能力,該協(xié)議被分為兩種類型。對于只能處理匿名接觸(type A)的設備,該協(xié)議描述了如何把所有的原始觸摸數(shù)據(jù)發(fā)送給接收者。對于那些有能力跟蹤并識別每個觸摸點的設備(type B),該協(xié)議描述了如何把每個觸摸點的單獨更新通過事件slots發(fā)送給接受者。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本文由DroidPhone 翻譯:http://blog.csdn.net/droidphone 協(xié)議的使用-------------- 詳細的觸控信息被按順序地分割為多個ABS_MT事件數(shù)據(jù)包進行發(fā)送。只有ABS_MT事件信息被識別為觸控數(shù)據(jù)包的一部分,因為這些事件在當前的單點觸控(single-touch,ST)應用中是被忽略掉的,我們可以在現(xiàn)有的驅動中基于ST協(xié)議之上來實現(xiàn)MT協(xié)議。 對于type A設備的驅動,在每個數(shù)據(jù)包的結尾用input_mt_sync()對多個觸控包進行分割,這將會產生一個SYN_MT_REPORT事件,它通知接收者接受當前的觸控信息并準備接收下一個信息。 對于type B設備的驅動,在每個數(shù)據(jù)包的開始,通過調用input_mt_slot()進行分割,同時帶入一個參數(shù):slot。這會產生一個ABS_MT_SLOT事件,它通知接收者準備更新給定slot的信息。. 兩種類型的驅動通常都通過調用input_sync()函數(shù)來標記一個多點觸摸數(shù)據(jù)傳送的結束,這通知接收者對從上一個EV_SYN/SYN_REPORT以來的所有累加事件作出響應,并準備接收新的一組事件/數(shù)據(jù)包。 無狀態(tài)的type A協(xié)議和有狀態(tài)的type B slot協(xié)議之間的主要區(qū)別是通過識別相同接觸點來減低發(fā)送到用戶空間的數(shù)據(jù)量。slot協(xié)議需要使用到ABS_MT_TRACKING_ID,它要不由硬件來提供,或者通過原始數(shù)據(jù)進行計算【5】。 對于type A設備,內核驅動應該根據(jù)設備表面上全部有效觸控進行列舉并生成事件。每個觸控點數(shù)據(jù)包在這次事件流中的順序并不重要。事件過濾和手指跟蹤的工作留給用戶空間來實現(xiàn)【3】。 對于type B設備,內核驅動應該把每一個識別出的觸控和一個slot相關聯(lián),并使用該slot來傳播觸摸狀態(tài)的改變。通過修改關聯(lián)slot的ABS_MT_TRACKING_ID來達到對觸摸點的創(chuàng)建,替換和銷毀。一個非負數(shù)的跟蹤id被解釋為有效的觸摸,-1則代表一個不再使用的slot。一個之前沒有出現(xiàn)過的跟蹤id被認為是一個新的接觸點,當一個跟蹤id不再出現(xiàn)時則認為該接觸點已經被移除。因為只有變化的部分被傳播,每個被啟動的接觸點的狀態(tài)信息必須駐留在接收端。每當接收到一個MT事件,只需對當前slot的相關屬性進行一次簡單的更新即可。 有些設備可以識別和/或跟蹤比它能報告給驅動更多的接觸點,對于這種設備的驅動應該使得硬件上報的每一個接觸點關聯(lián)一個type B的slot。一旦識別到一個關聯(lián)了slot的接觸點發(fā)生了變化,驅動應該通過改變他的ABS_MT_TRACKING_ID使得該slot無效。如果硬件發(fā)出通知它跟蹤到了比目前上報的還要多的接觸點,驅動應該使用BTN_TOOL_*TAP事件知會用戶空間此刻硬件跟蹤的總的接觸點數(shù)目已經改變。要完成此工作,驅動應該顯式地發(fā)送BTN_TOOL_*TAP事件,并在調用input_mt_report_pointer_emulation()時把use_count參數(shù)設為false。驅動應該只通告硬件所能報告的slots數(shù)量。用戶空間可以通過注意到最大支持的BTN_TOOL_*TAP事件大于在ABS_MT_SLOT軸的absinfo中報告的type B的slots總數(shù),來檢測驅動是否能報告比slots數(shù)還多的觸控點。 Protocol Example A------------------ 對于一個兩點觸控的觸摸信息,type A設備的最小的事件序列看起來就像下面這樣: 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 實際上,在移動其中一個觸控點后的上報序列看起來是一樣的、所有存在觸控點的原始數(shù)據(jù)被發(fā)送,然后在它們之間用SYN_REPORT進行同步。 當?shù)谝粋€接觸點離開后,事件序列如下: ABS_MT_POSITION_X x[1] ABS_MT_POSITION_Y y[1] SYN_MT_REPORT SYN_REPORT 當?shù)诙€接觸點離開后,事件序列如下: SYN_MT_REPORT SYN_REPORT 假如驅動在ABS_MT事件之外上報一個BTN_TOUCH 或ABS_PRESSURE事件,最后一個SYN_MT_REPORT可以省略掉,否則,最后的SYN_REPORT會被input核心層扔掉,結果就是一個0觸控點事件被傳到用戶空間中。 Protocol Example B------------------ 對于一個兩點觸控的觸摸信息,type B設備的最小的事件序列看起來就像下面這樣: ABS_MT_SLOT 0 ABS_MT_TRACKING_ID 45 ABS_MT_POSITION_X x[0] ABS_MT_POSITION_Y y[0] ABS_MT_SLOT 1 ABS_MT_TRACKING_ID 46 ABS_MT_POSITION_X x[1] ABS_MT_POSITION_Y y[1] SYN_REPORT id 45的觸控點在x方向移動后的事件序列如下: ABS_MT_SLOT 0 ABS_MT_POSITION_X x[0] SYN_REPORT slot 0對應的接觸點離開后,對應的事件序列如下: ABS_MT_TRACKING_ID -1 SYN_REPORT 上一個被修改的slot也是0,所以ABS_MT_SLOT被省略掉。這一消息移除了接觸點45相關聯(lián)的slot 0,于是接觸點45被銷毀,slot 0被釋放后可以被另一個接觸點重用。 最后,第二個接觸點離開后的時間序列如下: ABS_MT_SLOT 1 ABS_MT_TRACKING_ID -1 SYN_REPORT 事件的使用----------- 一組ABS_MT事件集合按需要的特性被定義。這些事件被分成幾個組,以便允許只實現(xiàn)其中的一部分。最小的集合由ABS_MT_POSITION_X和ABS_MT_POSITION_Y組成,用于跟蹤多點接觸。如果設備支持,ABS_MT_TOUCH_MAJOR和ABS_MT_WIDTH_MAJOR可以用來提供接觸面積和對應的接觸工具。 TOUCH和WIDTH參數(shù)有一個幾何解釋。想象一下通過一個窗戶觀察一個人把一個手指按壓在對面的玻璃上,你會看到兩個區(qū)域,內圈的區(qū)域包含了手指實際和玻璃接觸的部分,而外圈則是手指的外輪廓。接觸區(qū)域(a)就是ABS_MT_POSITION_X/Y,而手指輪廓區(qū)域(b) 的中心就是ABS_MT_TOOL_X/Y。接觸區(qū)域的直徑是ABS_MT_TOUCH_MAJOR,而手指輪廓的直徑就是ABS_MT_WIDTH_MAJOR。現(xiàn)在想象一下此人把手指向玻璃壓得更緊,接觸區(qū)域會增加,通常,ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR的比值,總是小于1的,它和接觸的壓力相關。不過對于基于壓力的設備,應該改為使用ABS_MT_PRESSURE來提供接觸的壓力值。可以檢測懸浮的設備可以使用ABS_MT_DISTANCE來指出離表面的距離。 Linux MT Win8 __________ _______________________ / \ | | / \ | | / ____ \ | | / / \ \ | | \ \ a \ \ | a | \ \____/ \ | | \ \ | | \ b \ | b | \ \ | | \ \ | | \ \ | | \ / | | \ / | | \ / | | \__________/ |_______________________| 除了MAJOR參數(shù)之外,接觸和手指區(qū)域的橢圓外形還可以增加一個MINOR參數(shù),MAJOR和MINOR參數(shù)相當于橢圓的長軸和短軸。接觸區(qū)域的橢圓的方向可以用ORIENTATION參數(shù)描述,而手指區(qū)域的橢圓方向可以通過向量運算(a-b)來獲得。 對于type A設備,將來的規(guī)格可能會通過ABS_MT_BLOB_ID來描述接觸的外形。 ABS_MT_TOOL_TYPE可以用來指出觸控工具是手指還是筆或者其它物體。最后,ABS_MT_TRACKING_ID應該一直用來跟蹤被識別的接觸點【5】。 在type B協(xié)議里,ABS_MT_TOOL_TYPE和ABS_MT_TRACKING_ID被隱藏在input核心層中進行處理,驅動程序應該改為調用input_mt_report_slot_state()。 事件的語義說明--------------- ABS_MT_TOUCH_MAJOR接觸區(qū)域的長軸的長度。該長度應該按接觸表面的單位提供。如果表面的分辨率是X-Y,則ABS_MT_TOUCH_MAJOR可能的最大值是sqrt(X^2 + Y^2),它的對角線【4】。 ABS_MT_TOUCH_MINOR接觸區(qū)域短軸的表面單位長度。如果區(qū)域是圓形,該事件可以忽略【4】。 ABS_MT_WIDTH_MAJOR工具輪廓區(qū)域長軸的表面單位長度。這應該就是工具本省的大小。接觸面和輪廓面的方向被假設是一樣的【4】。 ABS_MT_WIDTH_MINOR工具輪廓區(qū)域短軸的表面單位長度,圓形的話可以被忽略【4】。 上述4個值可以被用來推導出接觸面的額外信息。ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR可以被用作接近的壓力。手指和手掌有不用的特征寬度。 ABS_MT_PRESSURE接觸區(qū)域的壓力值,可以是任意單位?;趬毫Φ脑O備應該使用該事件而不是TOUCH和 WIDTH事件。也用于可以報告空間信號強度的設備。 ABS_MT_DISTANCE接觸物到接觸表面之間的表面單位距離。距離為0表明已經接觸到了表面。一個正值表示接觸物懸浮在表面之上。 ABS_MT_ORIENTATION接觸橢圓區(qū)域的方向。該值描述了圍繞觸摸中心做1/4順時針轉動的有符號數(shù)。沒有限定該數(shù)值的范圍,但是在橢圓和表面的Y方向對齊時應該返回0值,橢圓往左轉時應該返回負值,往右轉時應該返回正值。當和X軸完全對齊時,應該返回最大值。 接觸的橢圓默認為是對稱點。對于可以360度轉動的設備,需要報告超出最大范圍來指出轉動多于1/4圈。對于倒置的手指,應該上報最大范圍的兩倍。 如果接觸面是一個圓形,或者方向信息在內核驅動中不可用,此時方向參數(shù)可以被忽略。如果設備可以識別出兩個軸方向,有可能只支持部分不連續(xù)的方向,在這種情況下,ABS_MT_ORIENTATION的范圍應該是[0,1]【4】。 ABS_MT_POSITION_X接觸中心的X坐標。 ABS_MT_POSITION_Y接觸中心的Y坐標 ABS_MT_TOOL_X接觸工具輪廓中心的X坐標。如果設備不能區(qū)分接觸面和工具本身時,可以忽略該事件。 ABS_MT_TOOL_Y接觸工具輪廓中心的Y坐標。如果設備不能區(qū)分接觸面和工具本身時,可以忽略該事件。 這4個位置值可以用于從觸控工具位置中分離實際的接觸位置。如果兩種位置信息都存在,那么觸控工具的長軸指向接觸點,否則,工具和接觸面的軸互相對其。 ABS_MT_TOOL_TYPE接近工具的類型。很多內核驅動程序不能區(qū)分不同的觸控工具,比如手指和筆。這種情況下,該事件可以被忽略。目前的協(xié)議支持MT_TOOL_FINGER 和MT_TOOL_PEN【2】兩種類型。對于type B設備,該事件由input核心層處理,驅動應該改為使用input_mt_report_slot_state()來上報。 ABS_MT_BLOB_IDBLOB_ID事件把幾個數(shù)據(jù)包組合在一起來組成一個任意的接觸形狀。一些點組成的序列定義了一個多邊形的外形。這是一個type A設備的底層匿名數(shù)據(jù)組合,不應該和上層的跟蹤ID相混淆。多數(shù)type A設備沒有blog這一能力,所以驅動可以放心地忽略該事件。 ABS_MT_TRACKING_IDTRACKING_ID識別一個被啟動的觸控點的整個生命周期【5】。TRACKING_ID的范圍應該足夠大,從而保證在足夠長的時間內都可以維護一個唯一的值。對于type B設備,該事件由input核心層處理,驅動程序應該改為使用input_mt_report_slot_state()來上報該事件。 事件的計算----------------- 一堆不同的硬件不可避免地導致一些設備比另一些更適合于MT協(xié)議。為了簡單和統(tǒng)一地進行對應,本節(jié)給出一些方法來確定如何計算某些事件。 對于那些報告接觸形狀為矩形的設備,我們不能獲得帶符號的方向值,假設X和Y分別是接觸面矩形的兩個邊長,以下這些公式可以最大可能地獲取最多的信息: ABS_MT_TOUCH_MAJOR := max(X, Y) ABS_MT_TOUCH_MINOR := min(X, Y) ABS_MT_ORIENTATION := bool(X > Y) ABS_MT_ORIENTATION的范圍應該被設為[0,1],以便設備可以區(qū)分手指是沿著Y軸還是沿著X軸【1】。 對于有T和C坐標的win8設備,位置信息的對應關系是: ABS_MT_POSITION_X := T_X ABS_MT_POSITION_Y := T_Y ABS_MT_TOOL_X := C_X ABS_MT_TOOL_X := C_Y 很不幸的是,沒有足夠的信息可以確定觸摸橢圓和工具橢圓,所以只能求助于近似算法。一種兼容早期使用方式的簡單的方案是: ABS_MT_TOUCH_MAJOR := min(X, Y) ABS_MT_TOUCH_MINOR := <not used> ABS_MT_ORIENTATION := <not used> ABS_MT_WIDTH_MAJOR := min(X, Y) + distance(T, C) ABS_MT_WIDTH_MINOR := min(X, Y) 基本原理是:我們沒有關于觸摸橢圓的相關信息,所以改用它的內切圓形來近似它。觸控工具的橢圓應該與向量(T - C)對齊,所以它的直徑必須增加(T, C)之間的距離。最后,假設觸摸區(qū)域的直徑等于觸控工具的厚度,我們可以得到上述公式。 手指跟蹤--------------- 跟蹤手指的處理過程,例如,為在表面上啟動的每個觸控點分配一個唯一的trackingID,是一個歐幾里得偶匹配問題。在每一次的事件同步中,一組實際的觸控點要和上一個同步的一組觸控點進行匹配,完整的實現(xiàn)請參考【3】。 手勢-------- 在某些可以產生手勢事件的特殊應用中,可以使用TOUCH和WIDTH參數(shù),比如,近似手指的壓力或者區(qū)分食指和拇指。利用額外的MINOR參數(shù),可以區(qū)分整個手指壓下還是只是手指的一個點壓。利用ORIENTATION參數(shù),我們可以檢測手指的擰動。 注意事項------------ 為了和現(xiàn)有的應用兼容,一個手指數(shù)據(jù)包中報告的數(shù)據(jù)不能被識別為單點觸控事件。 對于type A設備,所有的手指數(shù)據(jù)都要略過輸入過濾算法,因為接下來的同一類型的事件指向的是不同的手指。 使用type A協(xié)議設備的例子,請參考bcm5974的驅動。對于type B協(xié)議的例子,請參考hid-egalax的驅動。
[1] Also, the difference (TOOL_X -POSITION_X) can be used to model tilt. [2] The list can of course be extended. [3] mtdev 項目: http:///code/mtdev/. [4] 參看事件計算一節(jié)的內容。 [5] 參看手指跟蹤一節(jié)的內容。 |
|
|
來自: dwlinux_gs > 《設備驅動》