本文內提到的內容來至于 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 數據進行緩存,然后通過修改變更的數據來同步當前接觸點的數據)。