標籤:部分 為什麼 使用者空間 函數實現 tar 意思 word boa device
本文轉載自:
連結點擊開啟連結
關於Linux多點觸摸協議大家可以參考kernel中的文檔:https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt,而這雷根據實際的例子來理解多點觸摸協議。
多點觸摸協議有兩種,A協議和B協議。
首先來看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
如果第一個觸點離開(抬起),這裡的意思是說還有一個觸點,需要繼續上報這個觸點。
ABS_MT_POSITION_X x[1] ABS_MT_POSITION_Y y[1] SYN_MT_REPORT SYN_REPORT
如果兩個觸點都離開了,那麼只需要報告一個同步事件就可以了。
SYN_MT_REPORT SYN_REPORT
而程式碼範例如下:
[cpp] view plain copy
- for (i = 0; i < count; i++) {
- input_report_abs(input_dev, ABS_MT_POSITION_X, finger[i].x);
- input_report_abs(input_dev, ABS_MT_POSITION_Y, finger[i].x);
- input_mt_sync(input_dev);
- }
-
- if (!count)
- input_mt_sync(input_dev);
-
- input_sync(input_dev);
其中count值表示觸點個數,如果是2個,那麼這裡值就為2,如果所有觸點都離開了,那麼count值就為0。
上面可以說是最簡單,也是最基本的A協議報點了。除了報點以外,我們也來關注一下input device註冊時需要setting的一些東西。
[cpp] view plain copy
- input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, MAX_X, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, MAX_Y, 0, 0);
-
- __set_bit(EV_SYN, input_dev->evbit);
- __set_bit(EV_ABS, input_dev->evbit);
-
- __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
可能你會看到有的代碼會多下面這兩句:
[cpp] view plain copy
- __set_bit(ABS_MT_POSITION_X, input_dev->absbit);
- __set_bit(ABS_MT_POSITION_X, input_dev->absbit);
其實這兩句(包括上面的__set_bit(EV_ABS, input_dev->evbit);)是可有可無的,因為在input_set_abs_params函數中會做相應的設定。
而這句__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);也是必須要有的,否則在Android中會出現一個白色小圓環,感覺像是缺少idc檔案一樣。最後通過getevent -p命令看一下觸控螢幕的setting。
add device 1: /dev/input/event1 name: "ft6x36" events: ABS (0003): 0035 : value 0, min 0, max 540, fuzz 0, flat 0, resolution 0 0036 : value 0, min 0, max 960, fuzz 0, flat 0, resolution 0 input props: INPUT_PROP_DIRECT
對於B協議就稍微顯得有點複雜。B協議需要硬體支援,和A協議主要區別在哪裡呢?B協議可以使用一個ID來標識觸點,可以減少上報到使用者空間的資料量,這個ID(ABS_MT_TRACKING_ID)可以有硬體提供或者從未經處理資料計算而得。那>麼下面我們就來看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
如果觸點45隻是在x方向做了移動,那麼應該怎麼報告這個事件呢?
ABS_MT_SLOT 0 ABS_MT_POSITION_X x[0] SYN_REPORT
可以看到減少了很多資料的上報,這就是同A協議最大的區別。
如果同slot 0相關的觸點離開(抬起),只需要做下面的操作。 ABS_MT_TRACKING_ID -1 SYN_REPORT
這裡為什麼沒有發送ABS_MT_SLOT 0事件呢,因為之前slot已經被置成了0,再次發送ABS_MT_SLOT 0是會被忽略掉的。
如果第二個觸點被抬起,發送下面的事件序列。
ABS_MT_SLOT 1 ABS_MT_TRACKING_ID -1 SYN_REPORT
其他event
ABS_MT_POSITION_X和ABS_MT_POSITION_Y是多點觸摸協議的最小事件集,是最基本的事件,也是必須的事件。除此之外呢,還包括下面的一些時間集(需要設定支援):
ABS_MT_TOUCH_MAJOR
ABS_MT_TOUCH_MINOR
ABS_MT_TOUCH*用來表示接觸點地區大小(即手指與玻璃接觸地區大小),通常接觸地區是一個橢圓形狀,那麼MAJOR就表示橢圓的長軸,而MINOR就表示橢圓的短軸。如果接觸地區是圓形的話,那麼可以忽略MINOR,而MAJOR就表示圓形的直徑大小。
ABS_MT_WIDTH_MAJOR
ABS_MT_WIDTH_MINOR
上面的TOUCH表示接觸地區的大小,而WIDTH則表示為接觸工具的大小(例如手指,觸控筆等)。
ABS_MT_PRESSURE
而PRESSURE表示壓力值,這個壓力值可以通過上面的4個參數計算而得,例如:ABS_MT_TOUCH_MAJOR/ABS_MT_WIDTH_MAJOR,可以看到接觸面積越大,壓力值也就越大。當然這個壓力值也可以直接由裝置提供。
ABS_MT_DISTANCE
觸點與接觸面的距離,0表示觸點在接觸面的表面(已經實實在在的接觸到了),而正數表示在接觸面的上方。
ABS_MT_ORIENTATION
觸點的方向。
ABS_MT_TOOL_X
ABS_MT_TOOL_Y
ABS_MT_TOOL_TYPE
關於上報虛擬按索引值
通常觸控螢幕下方都有3個虛擬按鍵,而這3個按鍵同其它實體按鍵(例如:power按鍵、音量按鍵)又有所不同,它是觸控螢幕提供的一組虛擬按鍵,我們通過觸控螢幕會得到這一組按鍵的座標值,可以通過這個座標值上報相應的按索引值來實
現按鍵功能,那麼怎麼來上報這個按索引值呢。首先需要對input裝置做一些setting:
[cpp] view plain copy
- __set_bit(KEY_MENU, input_dev->keybit);
- __set_bit(KEY_HOMEPAGE, input_dev->keybit);
- __set_bit(KEY_BACK, input_dev->keybit);
-
- __set_bit(EV_KEY, input_dev->evbit);
- __set_bit(EV_SYN, input_dev->evbit);
OK,這些索引值呢在kernel中是定義在uapi/linux/input.h中的,而通常我們的driver只需要包含linux/input.h就可以了,這個檔案中include了的uapi/linux/input.h。
好的,再來看怎麼上報索引值。
按鍵按下:
[cpp] view plain copy
- input_report_key(input_dev, key_value, 1);
- input_sync(input_dev);
按鍵抬起:
[cpp] view plain copy
- input_report_key(input_dev, key_value, 0);
- input_sync(input_dev);
如果是按鍵一直被按下,重複上報按鍵被按下那部分就可以了。
有的地方可能會看到直接使用input_event函數,例如:
[cpp] view plain copy
- input_event(input_dev, EV_KEY, key_value, 1);
大家也可以去看看input_report_key函數,它其實是對input_event函數做了封裝,不管是input_report_abs也好,還是input_sync,最終都是調用的input_event函數,所以真正上報event的函數其實是input_event函數。
最後一點在setting時除了__set_bit之外,可能還會看到另外一個函數input_set_capability,這個函數實現在drivers/input/input.c中,而它最終還是調用了__set_bit函數,所以最後效果都是一樣的。
Linux/Android多點觸摸協議【轉】