本文内提到的内容來至于 Kernel Documentation
。
協定被分為了兩種類型的裝置:
- 所有裝置都處理匿名接觸點(A類), 協定描述如何發送 raw 資料來自所有接觸點給接收者
- 處理帶Tracking ID 的接觸點(B類),協定描述如何通過事件slot發送更新每個獨立接觸點
協定使用
接觸點描述的每個包都通過 ABS_MT_* 事件來進行發送單條資訊。
在Type A 裝置驅動中每個獨立接觸點之後都會使用 input_mt_sync() 來發送 SYN_MT_REPORT 事件。
而在Type B 裝置驅動中每個獨立接觸點之前都會使用 input_mt_slot() 函數來發送 ABS_MT_SLOT 事件,用來表示準備開始更新某給定的slot 事件。同時要求使用 ABS_MT_TRACKING_ID 來描述slot協定。
所有類型的驅動都會通過 input_sync() 函數來結束單次操作的 EV_SYN/SYN_REPORT事件來進行同步。表示目前事件已經結束,可以使用之前更新的資料。
無狀态的Type A 協定與含狀态的Type B slot協定主要差別在于使用接觸點Id 來減少大量資料發送給到使用者空間中。
對于A類裝置來說,核心驅動随意疊代所有接觸點,資料包在事件流中的位置并不重要。事件過濾及事件tracking都被遺留給了使用者空間來處理。而 B 類裝置,核心用 slot 來關聯每個接觸點,通過 slot 來傳遞接觸點的變化。接觸點的建立,更新及銷毀都通過修改關聯的slot的 ABS_MT_TRACKING_ID 來完成(非負數表示诠釋一個接觸點,-1 表示為一個無用的接觸點)。當出現一個之前沒有出現過tracking id 時,表示為一個新的點。某個tracking id 不再次出現時,表示已經移除。
如果tracking的接觸點多餘目前上報的硬體信号時,驅動應該使用 BTN_TOOL_TAP 事件來告知使用者空間目前tracking的接觸點總數量。驅動應該通過發送相應的 BTN_TOOL_TAP 事件以及在調用 input_mt_report_pointer_emulation() 函數時設定 use_count 為 false 。
ABS_MT_SLOT 最小值為 0。
協定樣例
A 類協定
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
當其中某點發送移動,進行更新時,這時所有呈現的接觸點的 raw 資料通過發送 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 事件可能會省略。
B 類協定
如下是兩個接觸點的 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
如下是在當第一個 slot 在 x 軸上移動之後,上報的日志:
ABS_MT_SLOT 0
ABS_MT_POSITION_X x[0]
SYN_REPORT
如下是當slot 關聯的 slot 擡起(release)之後,上報如下事件:
ABS_MT_TRACKING_ID -1
SYN_REPORT
如果第二點擡起之後,則上報如下事件:
ABS_MT_SLOT 1
ABS_MT_TRACKING_ID -1
SYN_REPORT
即當變化的接觸點所關聯的 slot 與上次同步資料的 slot 不一緻時,必須先發送 ABS_MT_SLOT 來标記目前要修改的 slot 資料。(類似于 patch 将單個 slot 資料進行緩存,然後通過修改變更的資料來同步目前接觸點的資料)。