Linux/Android多點觸摸協議【轉】

來源:互聯網
上載者:User

標籤:部分   為什麼   使用者空間   函數實現   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 
  1. for (i = 0; i < count; i++) {  
  2.         input_report_abs(input_dev, ABS_MT_POSITION_X, finger[i].x);  
  3.         input_report_abs(input_dev, ABS_MT_POSITION_Y, finger[i].x);  
  4.         input_mt_sync(input_dev);  
  5. }  
  6.   
  7. if (!count)  
  8.         input_mt_sync(input_dev);  
  9.   
  10. input_sync(input_dev);  

其中count值表示觸點個數,如果是2個,那麼這裡值就為2,如果所有觸點都離開了,那麼count值就為0。

上面可以說是最簡單,也是最基本的A協議報點了。除了報點以外,我們也來關注一下input device註冊時需要setting的一些東西。

[cpp] view plain copy 
  1. input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, MAX_X, 0, 0);  
  2. input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, MAX_Y, 0, 0);  
  3.   
  4. __set_bit(EV_SYN, input_dev->evbit);  
  5. __set_bit(EV_ABS, input_dev->evbit);  
  6.   
  7. __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);  

 

可能你會看到有的代碼會多下面這兩句:

[cpp] view plain copy 
  1. __set_bit(ABS_MT_POSITION_X, input_dev->absbit);  
  2. __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 
  1. __set_bit(KEY_MENU, input_dev->keybit);  
  2. __set_bit(KEY_HOMEPAGE, input_dev->keybit);  
  3. __set_bit(KEY_BACK, input_dev->keybit);  
  4.   
  5. __set_bit(EV_KEY, input_dev->evbit);  
  6. __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 
  1. input_report_key(input_dev, key_value, 1);  
  2. input_sync(input_dev);  

按鍵抬起:

[cpp] view plain copy 
  1. input_report_key(input_dev, key_value, 0);  
  2. input_sync(input_dev);  

如果是按鍵一直被按下,重複上報按鍵被按下那部分就可以了。

有的地方可能會看到直接使用input_event函數,例如:

[cpp] view plain copy 
  1. 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多點觸摸協議【轉】

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.