1 KERNEL
對於觸摸屏的驅動我們簡單的划分為兩個主要的部分,一個是注冊,另一個是上報。
1.1 注冊
單點觸摸信息是以ABS承載並按一定順序發送,如BTN_TOUCH、ABS_X、ABS_Y、SYNC。而多點觸摸信息則是以ABS_MT承載並按一定順序發送,如ABS_MT_POSITION_X、ABS_MT_POSITION_Y,然后通過調用input_mt_sync()產生一個 SYN_MT_REPORT event來標記一個點的結束,告訴接收方接收當前手指的信息並准備接收其它手指的觸控信息。最后調用 input_sync()函數上報觸摸信息開始動作並告訴接收方開始接收下一系列多點觸摸信息。
1.2 上報
協議定義了一系列ABS_MT事件,這些事件被分為幾大類,允許只應用其中的一部份,多點觸摸最小的事件集中包括 ABS_MT_TOUCH_MAJOR、ABS_MT_POSITION_X和 ABS_MT_POSITION_Y,以此來實現多點觸摸。如果設備支持ABS_MT_WIDTH_MAJOR這個事件,那么此事件可以提供手指觸摸接觸面積大小。觸摸方向等信息可以由ABS_MT_TOUCH_MINOR, ABS_MT_WIDTH_MINOR and ABS_MT_ORIENTATION提供。ABS_MT_TOOL_TYPE提供觸摸設備的類別,如手或是筆或是其它。最后有些設備可能會支持 ABS_MT_TRACKING_ID,用來支持硬件跟蹤多點信息,即該點屬於哪一條線等。
2、 framework
在Android 4.0中,Event Input地位提高了.在Adroid2.3.5中,它在frameworks/base/libs/ui之下,在Android4.0中,它在 frameworks/base/services/input之下,看到沒有,它有了自己的地位,就像在Kernel中一樣,有自己門戶了。
在此文件夾下,目前主要研究兩個文件,一個是EventHub.cpp,另一個是InputReader.cpp兩個文件。EventHub.cpp主要是完成設備的掃描和識別。而InputReader.cpp完成對設備上報的原始數據的處理工作。
而具體的對於APP開發人員來講主要的數據是通過MotionEvent.java獲取。而MotionEvent.java是通過JNI機制與底層進行通信的。
frameworks/base/core/java/android/view/MotionEvent.java --> jni --> frameworks/base/core/jni/android_view_MotionEvent.cpp
3、app
參考代碼TouchExample.java & TouchExampleActivity.java
單點觸摸信息是以ABS承載並按一定順序發送,如BTN_TOUCH、ABS_X、ABS_Y、SYNC。而多點觸摸信息則是以ABS_MT承載並按一定順序發送,如ABS_MT_POSITION_X、ABS_MT_POSITION_Y,然后通過調用input_mt_sync()產生一個 SYN_MT_REPORT event來標記一個點的結束,告訴接收方接收當前手指的信息並准備接收其它手指的觸控信息。最后調用 input_sync()函數上報觸摸信息開始動作並告訴接收方開始接收下一系列多點觸摸信息。
協議定義了一系列ABS_MT事件,這些事件被分為幾大類,充許只應用其中的一部份,多點觸摸最小的事件集中應包括ABS_MT_TOUCH_MAJOR、ABS_MT_POSITION_X和 ABS_MT_POSITION_Y,以此來實現多點觸摸。如果設備支持ABS_MT_WIDTH_MAJOR這個事件,那么此事件可以提供手指觸摸接觸面積大小。觸摸方向等信息可以由ABS_MT_TOUCH_MINOR, ABS_MT_WIDTH_MINOR and ABS_MT_ORIENTATION提供。ABS_MT_TOOL_TYPE提供觸摸設備的類別,如手或是筆或是其它。最后有些設備可能會支持ABS_MT_TRACKING_ID,用來支持硬件跟蹤多點信息,即該點屬於哪一條線等。
下面是兩點觸摸支持的最小事件集序列:
ABS_MT_TOUCH_MAJOR
ABS_MT_POSITION_X
ABS_MT_POSITION_Y
SYN_MT_REPORT //上報第一個點
ABS_MT_TOUCH_MAJOR
ABS_MT_POSITION_X
ABS_MT_POSITION_Y
SYN_MT_REPORT //上報第二個點
SYN_REPORT //開始動作
Event 原語
“接觸”一詞用來描述一個物體直接碰到另一個物體的表面。
ABS_MT_TOUCH_MAJOR描述了主接觸面的長軸,它和X,Y同一個單位,如果一個面的分辨率為X*Y,則ABS_MT_TOUCH_MAJOR的最大值為sqrt(X^2+Y^2)
ABS_MT_TOUCH_MINOR描述了接觸面的短軸,如果接觸面是圓形,它可以不用。
ABS_MT_WIDTH_MAJOR描述了接觸工具的長軸
ABS_MT_WIDTH_MINOR描述了接觸工具的短軸
ABS_MT_TOUCH_MAJOR := max(X, Y)
ABS_MT_TOUCH_MINOR := min(X, Y)
ABS_MT_ORIENTATION := bool(X > Y)
以上四個參數可以用來生成額外的觸摸信息,如ABS_MT_TOUCH_MAJOR/ABS_MT_WIDTH_MAJOR的比率可以用來描述壓力。
ABS_MT_ORIENTATION
ABS_MT_POSITION_X接觸面的中心點X坐標
ABS_MT_POSITION_Y接觸面的中心點Y坐標
ABS_MT_TOOL_TYPE描述接觸工具類型,很多內核驅動無法區分此參數如手指及筆,如果是這樣,該參數可以不用,協議目前支持MT_TOOL_FINGER和MT_TOOL_PEN兩種類型。
ABS_MT_BLOB_ID形狀集ID,集合幾個點以描述一個形狀,很多驅動沒有形狀屬性,此參數可以不用。
ABS_MT_TRACKING_ID描述了從接觸開始到釋放的整個過程的集合,如果設備不支持,此參數可是不用。
觸摸軌跡
僅有少數設備可以明觸的標識真實的 trackingID,多數情況下 trackingID只能來標識一次觸摸動作的過程。
手勢
多點觸摸指定的應用是創建手勢動作, TOUCH和 WIDTH參數經常用來區別手指的壓力和手指間的距離,另外 MINOR類的參數可以用來區別設備的接觸面的大小(點接觸還是面接觸),ORIENTATION可以產生旋轉事件。
Android Input系統之觸摸屏
最近開始在TI平台調試觸摸屏,之前研究過Android的Event輸入設備驅動,對鍵盤比較了解。Input驅動程序包含游戲桿、鼠標和事件設備3中驅動,而鍵盤和觸摸屏都輸入事件設備。
Input驅動程序的主設備號是13,3種驅動程序的設備號分配是:
游戲桿:0~31
鼠標:32~62
mice鼠標:63
事件設備:64~95
每種Input設備占用5位,每種設備個數是32。Event設備在文件系統中的設備節點是:/dev/input/eventX。
Android針對輸入子系統設備有一套統一的架構,基本層次結構:
其詳細結構:
觸摸屏驅動分析:
Host端通過IIC總線,從芯片讀出需要的數據,一般為X,Y的絕對坐標,還有數據的標志位。采用的觸摸屏最多支持五點觸摸,因此驅動代碼相對單點觸摸相對復雜些。
在probe函數的設備初始化階段的input_set_abs_params()函數設置方式不同:
#ifdef CONFIG_MULTITOUCH
set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit);
set_bit(ABS_MT_POSITION_X, input_dev->absbit);
set_bit(ABS_MT_POSITION_Y, input_dev->absbit);
set_bit(ABS_MT_WIDTH_MAJOR, input_dev->absbit);
input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0); //相當於單點屏的ABS_PRESSURE
input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);
#else
set_bit(ABS_X, input_dev->absbit);
set_bit(ABS_Y, input_dev->absbit);
set_bit(ABS_PRESSURE, input_dev->absbit);
set_bit(BTN_TOUCH, input_dev->keybit);
input_set_abs_params(input_dev, ABS_X, 0, SCREEN_MAX_X, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 0, SCREEN_MAX_Y, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, PRESS_MAX, 0 , 0);
#endif
android 4.0已經漸漸流行,很多方案都已經基於其上,android 4.0的linux內核版本已經更新為linux 3.0,這個變化導致和內核直接接觸的驅動需要或多或少的變化,以下描述的是觸摸設備驅動的一些小變化:
1.當一個(這時候的情境應該是多點觸摸的情況)手指或是觸摸工具抬起(UP)時,他應該立即消失在多點出沒的同步報告中,當所有的工具或手指抬起,驅動應該立即發送一個“空”同步消息,使用SYN_MT_REPORT其次是SYN_REPORT。
之前的版本是向上報告一個presssure為0的消息,現在新的多點觸摸協議已經不再兼容舊的協議了。
2.物理接觸或是信號強度將使用ABS_MT_PRESSURE上報。
之前的版本是用ABS_MT_TOUCH_MAJOR上報這個消息,同樣,舊的方式也已經不被兼容了。
3.觸摸接觸面積使用ABS_MT_TOUCH_MAJOR向上報告
舊的版本使用ABS_MT_TOOL_MAJOR向上報告,舊的方式也已經不被兼容了。
觸摸設備驅動程序不再需要特定的Android定制。依靠標准的Linux輸入協議,Android可以更廣泛支持觸摸外設,如外部HID多點觸摸觸摸屏,使用未修改的驅動程序。
example:
static irqreturn_t xxx_ts_irq_handler(int irq, void *dev_id)
{
struct xxx_ts_data *ts = dev_id;
struct xxx_ts_finger *finger = ts->finger;
struct input_dev *input_dev = ts->input_dev;
int count = 0;
int i, ret;
ret = xxx_ts_read_data(ts);
if (ret < 0)
goto end;
/* multi touch protocol */
for (i = 0; i < MAX_FINGERS; i++) {
if (!finger[i].is_valid)
continue;
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, finger[i].t);
input_report_abs(input_dev, ABS_MT_POSITION_X, finger[i].x);
input_report_abs(input_dev, ABS_MT_POSITION_Y, finger[i].y);
input_mt_sync(input_dev);
count++;
}
/* SYN_MT_REPORT only if no contact */
if (!count)
input_mt_sync(input_dev);
/* SYN_REPORT */
input_sync(input_dev);
end:
return IRQ_HANDLED;
}
