標籤:問題 不同的 mtd use dev 規格 需要 cm5 儲存
轉自:http://www.thinksaas.cn/topics/0/646/646797.html
將A/B協議這部分單獨拿出來說一方面是因為這部分內容是比較容易忽視的,周圍大多數用到input子系統的開發人員也不甚理解;另一方面是由於這部分知識一旦擴充到TP(觸控螢幕Touch Panel)的多點觸摸就要與Middleware/Framework一起結合起來看才能完全掌握,複雜性所在。這裡的Middleware/Framework是針對android來說的,本人從事android這幾個層次的工作,所以就從android的角度來講講這部分內容,其他系統雖然代碼不同,但原理上是完全一樣的。
B協議又稱為slot協議,那麼input子系統裡面使用的slot是什麼,A/B協議究竟是如何劃分的? slot直譯為位置、槽,有兩層含義,一層是位置,另一層是容器。在Input子系統中,它扮演的就是這兩個角色。它產生於這樣一個背景: 如果從Device擷取的當前資料與上一個資料相同,我們有必要再上報當前資料嗎?如果我們不管兩次資料是否一致都上報,那就是A協議;如果我們選擇不上報,那麼既然需要比較,總需要把上一次資料存起來吧,slot就是做這個事情的,顯然這就是Slot(B)協議。 其實到這裡,對TP不感興趣的童鞋可以不繼續向下看了,瞭解了兩個協議的區別看或者寫一般模組的代碼不會有問題了。需要注意的是,想要測試Device驅動的input部分是否正常的時候,假如使用的是B協議,input_report資料的時候要記得每次都要report不同的值,否則在HAL層是看不到資料不停上報的,因為前後兩個資料相同的時候,B協議是不會上報到系統的。另外,在上層測試資料上報頻率的時候,採用 資料總量/時間差 的方法,如果驅動採用的是B協議,測試結果也是不準確的。 下面要說的與TP的多點觸摸(MT Multi-touch)的功能關係密切,沒有興趣的可以略過。由於這部分代碼不從事TP或者android的人是不會接觸到的,所以代碼就不貼出來了,有興趣的童鞋可以單獨交流O(∩_∩)O~ 我們都知道,在支援MT的手機上多指滑動的時候,多條手指滑動過的軌跡彼此是不相交的,這也是我們所期望的。但這個功能究竟是如何?的呢?看了上面的分析應該就知道,A/B兩種協議方式都可以實現該功能。 A協議不會使用slot,多指處理中,它的報點序列如下(每一個序列都以input_report_***函數實現):點擊(此處)摺疊或開啟ABS_MT_POSITION_X x[0]ABS_MT_POSITION_Y y[0]SYN_MT_REPORTABS_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_REPORTSYN_REPORT 只有SYNC,沒有其它任何資訊,系統就會認為此次事件為UP。 B協議使用了slot,還有一個新面孔TRACKING_ID.點擊(此處)摺疊或開啟ABS_MT_SLOT 0ABS_MT_TRACKING_ID **ABS_MT_POSITION_X x[0]ABS_MT_POSITION_Y y[0]ABS_MT_SLOT 1ABS_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 0ABS_MT_TRACKING_ID -1SYN_REPORTABS_MT_SLOT 1ABS_MT_TRACKING_ID -1SYN_REPORT 這裡上報的ABS_MT_TRACKING_ID為-1,也只有這裡該值才可以小於零,收到該值,系統就會清除對應的ID。看似簡單的兩個協議內容到這裡就分析完畢了。 看了上面的分析,明顯可以看出B協議要由於A協議,但事實上並不如此簡單。B協議需要硬體上的支援,ID值並不是隨便賦值的,而是硬體上跟蹤了點的軌跡;如果硬體上滿足不了這個條件,那麼採用B協議只能鬧成笑話。另外,B協議的複雜性如果掌握不好往往會帶來一些莫名其妙的問題,比如如果因為某些因素(同步等),在UP的時候少清除了一個slot的資訊,那麼下次單擊的時候你也會驚奇地發現竟然有兩個點(採用了B協議,slot已經儲存了點資訊,除非明確清除)。 希望本文對希望瞭解TP或者多點觸摸功能的童鞋有所協助。參考於:http://www.cnblogs.com/rutian2013/p/3341118.htmlPS:多點觸控協議相關知識Multi-touch (MT) Protocol ------------------------- Copyright(C) 2009-2010 Henrik Rydberg<[email protected]> 簡介------------ 為了發揮新近的多點觸摸和多使用者裝置的強大功能,為多點觸摸定義一種上報詳細資料的方法(比如有多個物體直接接觸到裝置的表面),是非常有必要的。這篇文檔描述了多點觸摸協議(multi-touch,MT),是的核心驅動可以對多個隨意數量的觸控事件上報詳細的資料資訊。 基於硬體的能力,該協議被分為兩種類型。對於只能處理匿名接觸(type A)的裝置,該協議描述了如何把所有的原始觸摸資料發送給接收者。對於那些有能力跟蹤並識別每個觸摸點的裝置(type B),該協議描述了如何把每個觸摸點的單獨更新通過事件slots發送給接受者。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本部分由DroidPhone 翻譯:http://blog.csdn.net/droidphoneKernel版本:V3.7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 協議的使用-------------- 詳細的觸控資訊被按順序地分割為多個ABS_MT事件數目據包進行發送。只有ABS_MT事件資訊被識別為觸控資料包的一部分,因為這些事件在當前的單點觸控(single-touch,ST)應用中是被忽略掉的,我們可以在現有的驅動中基於ST協議之上來實現MT協議。 對於type A裝置的驅動,在每個資料包的結尾用input_mt_sync()對多個觸控包進行分割,這將會產生一個SYN_MT_REPORT事件,它通知接收者接受當前的觸控資訊並準備接收下一個資訊。 對於type B裝置的驅動,在每個資料包的開始,通過調用input_mt_slot()進行分割,同時帶入一個參數:slot。這會產生一個ABS_MT_SLOT事件,它通知接收者準備更新給定slot的資訊。. 兩種類型的驅動通常都通過調用input_sync()函數來標記一個多點觸摸資料傳送的結束,這通知接收者對從上一個EV_SYN/SYN_REPORT以來的所有累加事件作出響應,並準備接收新的一組事件/資料包。 無狀態的type A協議和有狀態的type B slot協議之間的主要區別是通過識別相同接觸點來減低發送到使用者空間的資料量。slot協議需要使用到ABS_MT_TRACKING_ID,它要不由硬體來提供,或者通過未經處理資料進行計算【5】。 對於type A裝置,核心驅動應該根據裝置表面上全部有效觸控進行列舉並建置事件。每個觸控點資料包在這次事件流中的順序並不重要。事件過濾和手指跟蹤的工作留給使用者空間來實現【3】。 對於type B裝置,核心驅動應該把每一個識別出的觸控和一個slot相關聯,並使用該slot來傳播觸摸狀態的改變。通過修改關聯slot的ABS_MT_TRACKING_ID來達到對觸摸點的建立,替換和銷毀。一個非負數的跟蹤id被解釋為有效觸摸,-1則代表一個不再使用的slot。一個之前沒有出現過的跟蹤id被認為是一個新的接觸點,當一個跟蹤id不再出現時則認為該接觸點已經被移除。因為只有變化的部分被傳播,每個被啟動的接觸點的狀態資訊必須駐留在接收端。每當接收到一個MT事件,只需對當前slot的相關屬性進行一次簡單的更新即可。 有些裝置可以識別和/或跟蹤比它能報告給驅動更多的接觸點,對於這種裝置的驅動應該使得硬體上報的每一個接觸點關聯一個type B的slot。一旦識別到一個關聯了slot的接觸點發生了變化,驅動應該通過改變他的ABS_MT_TRACKING_ID使得該slot無效。如果硬體發出通知它跟蹤到了比目前上報的還要多的接觸點,驅動應該使用BTN_TOOL_*TAP事件知會使用者空間此刻硬體跟蹤的總的接觸點數目已經改變。要完成此工作,驅動應該顯式地發送BTN_TOOL_*TAP事件,並在調用input_mt_report_pointer_emulation()時把use_count參數設為false。驅動應該只通告硬體所能報告的slots數量。使用者空間可以通過注意到最大支援的BTN_TOOL_*TAP事件大於在ABS_MT_SLOT軸的absinfo中報告的type B的slots總數,來檢測驅動是否能報告比slots數還多的觸控點。 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 實際上,在移動其中一個觸控點後的上報序列看起來是一樣的、所有存在觸控點的未經處理資料被發送,然後在它們之間用SYN_REPORT進行同步。 當第一個接觸點離開後,事件序列如下: ABS_MT_POSITION_X x[1] ABS_MT_POSITION_Y y[1] SYN_MT_REPORT SYN_REPORT 當第二個接觸點離開後,事件序列如下: 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相關聯的slot 0,於是接觸點45被銷毀,slot 0被釋放後可以被另一個接觸點重用。 最後,第二個接觸點離開後的時間序列如下: ABS_MT_SLOT 1 ABS_MT_TRACKING_ID -1 SYN_REPORT 事件的使用----------- 一組ABS_MT事件集合按需要的特性被定義。這些事件被分成幾個組,以便允許只實現其中的一部分。最小的集合由ABS_MT_POSITION_X和ABS_MT_POSITION_Y組成,用於跟蹤多點接觸。如果裝置支援,ABS_MT_TOUCH_MAJOR和ABS_MT_WIDTH_MAJOR可以用來提供接觸面積和對應的接觸工具。 TOUCH和WIDTH參數有一個幾何解釋。想象一下通過一個窗戶觀察一個人把一個手指按壓在對面的玻璃上,你會看到兩個地區,內圈的地區包含了手指實際和玻璃接觸的部分,而外圈則是手指的外輪廓。接觸地區(a)就是ABS_MT_POSITION_X/Y,而手指輪廓地區(b) 的中心就是ABS_MT_TOOL_X/Y。接觸地區的直徑是ABS_MT_TOUCH_MAJOR,而手指輪廓的直徑就是ABS_MT_WIDTH_MAJOR。現在想象一下此人把手指向玻璃壓得更緊,接觸地區會增加,通常,ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR的比值,總是小於1的,它和接觸的壓力相關。不過對於基於壓力的裝置,應該改為使用ABS_MT_PRESSURE來提供接觸的壓力值。可以檢測懸浮的裝置可以使用ABS_MT_DISTANCE來指出離表面的距離。 Linux MT Win8 __________ _______________________ / | | / | | / ____ | | / / | | a | a | ____/ | | | | b | b | | | | | | | / | | / | | / | | __________/ |_______________________| 除了MAJOR參數之外,接觸和手指地區的橢圓外形還可以增加一個MINOR參數,MAJOR和MINOR參數相當於橢圓的長軸和短軸。接觸地區的橢圓的方向可以用ORIENTATION參數描述,而手指地區的橢圓方向可以通過向量運算(a-b)來獲得。 對於type A裝置,將來的規格可能會通過ABS_MT_BLOB_ID來描述接觸的外形。 ABS_MT_TOOL_TYPE可以用來指出觸控工具是手指還是筆或者其它物體。最後,ABS_MT_TRACKING_ID應該一直用來跟蹤被識別的接觸點【5】。 在type B協議裡,ABS_MT_TOOL_TYPE和ABS_MT_TRACKING_ID被隱藏在input核心層中進行處理,驅動程式應該改為調用input_mt_report_slot_state()。 事件的語義說明--------------- ABS_MT_TOUCH_MAJOR 接觸地區的長軸的長度。該長度應該按接觸表面的單位提供。如果表面的解析度是X-Y,則ABS_MT_TOUCH_MAJOR可能的最大值是sqrt(X^2 + Y^2),它的對角線【4】。 ABS_MT_TOUCH_MINOR 接觸地區短軸的表面單位長度。如果地區是圓形,該事件可以忽略【4】。 ABS_MT_WIDTH_MAJOR 工具輪廓地區長軸的表面單位長度。這應該就是工具本省的大小。接觸面和輪廓面的方向被假設是一樣的【4】。 ABS_MT_WIDTH_MINOR 工具輪廓地區短軸的表面單位長度,圓形的話可以被忽略【4】。 上述4個值可以被用來推匯出接觸面的額外資訊。ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR可以被用作接近的壓力。手指和手掌有不用的特徵寬度。 ABS_MT_PRESSURE 接觸地區的壓力值,可以是任意單位。基於壓力的裝置應該使用該事件而不是TOUCH和 WIDTH事件。也用於可以報告空間訊號強度的裝置。 ABS_MT_DISTANCE 接觸物到接觸表面之間的表面單位距離。距離為0表明已經接觸到了表面。一個正值表示接觸物懸浮在表面之上。 ABS_MT_ORIENTATION 接觸橢圓地區的方向。該值描述了圍繞觸摸中心做1/4順時針轉動的有符號數。沒有限定該數值的範圍,但是在橢圓和表面的Y方向對齊時應該返回0值,橢圓往左轉時應該返回負值,往右轉時應該返回正值。當和X軸完全對齊時,應該返回最大值。 接觸的橢圓預設為是對稱點。對於可以360度轉動的裝置,需要報告超出最大範圍來指出轉動多於1/4圈。對於倒置的手指,應該上報最大範圍的兩倍。 如果接觸面是一個圓形,或者方向資訊在核心驅動中不可用,此時方向參數可以被忽略。如果裝置可以識別出兩個軸方向,有可能只支援部分不連續的方向,在這種情況下,ABS_MT_ORIENTATION的範圍應該是[0,1]【4】。 ABS_MT_POSITION_X 接觸中心的X座標。 ABS_MT_POSITION_Y 接觸中心的Y座標 ABS_MT_TOOL_X 接觸工具輪廓中心的X座標。如果裝置不能區分接觸面和工具本身時,可以忽略該事件。 ABS_MT_TOOL_Y 接觸工具輪廓中心的Y座標。如果裝置不能區分接觸面和工具本身時,可以忽略該事件。 這4個位置值可以用於從觸控工具位置中分離實際的接觸位置。如果兩種位置資訊都存在,那麼觸控工具的長軸指向接觸點,否則,工具和接觸面的軸互相對其。 ABS_MT_TOOL_TYPE 接近工具的類型。很多核心驅動程式不能區分不同的觸控工具,比如手指和筆。這種情況下,該事件可以被忽略。目前的協議支援MT_TOOL_FINGER 和MT_TOOL_PEN【2】兩種類型。對於type B裝置,該事件由input核心層處理,驅動應該改為使用input_mt_report_slot_state()來上報。 ABS_MT_BLOB_ID BLOB_ID事件把幾個資料包組合在一起來組成一個任意的接觸形狀。一些點組成的序列定義了一個多邊形的外形。這是一個type A裝置的底層匿名資料群組合,不應該和上層的跟蹤ID相混淆。多數type A裝置沒有blog這一能力,所以驅動可以放心地忽略該事件。 ABS_MT_TRACKING_ID TRACKING_ID識別一個被啟動的觸控點的整個生命週期【5】。TRACKING_ID的範圍應該足夠大,從而保證在足夠長的時間內都可以維護一個唯一的值。對於type B裝置,該事件由input核心層處理,驅動程式應該改為使用input_mt_report_slot_state()來上報該事件。 事件的計算----------------- 一堆不同的硬體不可避免地導致一些裝置比另一些更適合於MT協議。為了簡單和統一地進行對應,本節給出一些方法來確定如何計算某些事件。 對於那些報告接觸形狀為矩形的裝置,我們不能獲得帶符號的方向值,假設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],以便裝置可以區分手指是沿著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)之間的距離。最後,假設觸摸地區的直徑等於觸控工具的厚度,我們可以得到上述公式。 手指跟蹤--------------- 跟蹤手指的處理過程,例如,為在表面上啟動的每個觸控點分配一個唯一的trackingID,是一個歐幾裡得偶匹配問題。在每一次的事件同步中,一組實際的觸控點要和上一個同步的一組觸控點進行匹配,完整的實現請參考【3】。 手勢-------- 在某些可以產生手勢事件的特殊應用中,可以使用TOUCH和WIDTH參數,比如,近似手指的壓力或者區分食指和拇指。利用額外的MINOR參數,可以區分整個手指壓下還是只是手指的一個點壓。利用ORIENTATION參數,我們可以檢測手指的擰動。 注意事項------------ 為了和現有的應用相容,一個手指資料包中報告的資料不能被識別為單點觸控事件。 對於type A裝置,所有的手指資料都要略過輸入過濾演算法,因為接下來的同一類型的事件指向的是不同的手指。 使用type A協議裝置的例子,請參考bcm5974的驅動。對於type B協議的例子,請參考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://bitmath.org/code/mtdev/. [4] 參看事件計算一節的內容。 [5] 參看手指跟蹤一節的內容。
Android驅動之 Linux Input子系統之TP——A/B(Slot)協議【轉】