日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android 电容屏(二):驱动调试之基本概念篇

發布時間:2025/4/16 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 电容屏(二):驱动调试之基本概念篇 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

關鍵詞:android??電容屏 tp 工作隊列 中斷 多點觸摸協議
平臺信息:
內核:linux2.6/linux3.0
系統:android/android4.0?
平臺:S5PV310(samsung exynos 4210)?

作者:xubin341719(歡迎轉載,請注明作者)

參考網站:http://edsionte.com/techblog/archives/1582
這部分參考別人的多一點

android 電容屏(一):電容屏基本原理篇

android 電容屏(二):驅動調試之基本概念篇

android 電容屏(三):驅動調試之驅動程序分析篇


??????? 電容屏驅動調試先了解Linux電容屏驅動中幾個常用的概念:
????????????? 中斷下半部-工作隊列;
????????????? input機制;
????????????? Linux與Android 多點觸摸協議。


一、中斷下半部-工作隊列

1、中斷

?????????????? 先看一下宋寶華先生的《linux設備驅動開發詳解》里面對中斷的描述吧。這本書個人感覺 寫的比較好,從開始學驅動到現在,還能從中得到不少知識。

?????????????? 設備的中斷會打斷內核中進程的正常調度和運行,系統對更高吞吐率的追求勢必要求中斷服務程序盡可能地短小精悍。但是,這個良好的愿望往往與現實并不吻合。在大多數真實的系統中,當中斷到來時,要完成的工作往往并不會是短小的,它可能要進行較大量的耗時處理。如下圖描述了Linux內核的中斷處理機制。為了在中斷執行時間盡可能短和中斷處理需完成大量工作之間找到一個平衡點,Linux將中斷處理程序分解為兩個半部:頂半部(top? half)和底半部(bottom half)。頂半部完成盡可能少的比較緊急的功能,它往往只是簡單地讀取寄存器中的中斷狀態并清除中斷標志后就進行“登記中斷”的工作。“登記中斷”意味著將底半部處理程序掛到該設備的底半部執行隊列中去。這樣,頂半部執行的速度就會很快,可以服務更多的中斷請求。現在,中斷處理工作的重心就落在了底半部的頭上,它來完成中斷事件的絕大多數任務。底半部幾乎做了中斷處理程序所有的事情,而且可以被新的中斷打斷,這也是底半部和頂半部的最大不同,因為頂半部往往被設計成不可中斷。底半部則相對來說并不是非常緊急的,而且相對比較耗時,不在硬件中斷服務程序中執行。盡管頂半部、底半部的結合能夠改善系統的響應能力,但是,僵化地認為Linux設備驅動中的中斷處理一定要分兩個半部則是不對的。如果中斷要處理的工作本身很少,則完全可以直接在頂半部全部完成。

?????????? 其實上面這一段大致說明一個問題,那就是:中斷要盡可能耗時比較短,盡快恢復系統正常調試,所以把中斷觸發、中斷執行分開,也就是所說的“上半部分(中斷觸發)、底半部(中斷執行)”,其實就是我們后面說的中斷上下文。下半部分一般有tasklet、工作隊列實現,觸摸屏中中斷實現以工作隊列形式實現的,所以我們今天重點講工作隊列。


2、為什么還需要工作隊列?

?????????? 工作隊列(work queue)是另外一種將中斷的部分工作推后的一種方式,它可以實現一些tasklet不能實現的工作,比如工作隊列機制可以睡眠。這種差異的本質原因是,在工作隊列機制中,將推后的工作交給一個稱之為工作者線程(worker thread)的內核線程去完成(單核下一般會交給默認的線程events/0)。因此,在該機制中,當內核在執行中斷的剩余工作時就處在進程上下文(process context)中。也就是說由工作隊列所執行的中斷代碼會表現出進程的一些特性,最典型的就是可以重新調度甚至睡眠。

???????????? 對于tasklet機制(中斷處理程序也是如此),內核在執行時處于中斷上下文(interrupt context)中。而中斷上下文與進程毫無瓜葛,所以在中斷上下文中就不能睡眠。因此,選擇tasklet還是工作隊列來完成下半部分應該不難選擇。當推后的那部分中斷程序需要睡眠時,工作隊列毫無疑問是你的最佳選擇;否則,還是用tasklet吧。

3、中斷上下文

????????? 有上面那個圖可以看出上下兩部分吧,就是上下文吧,這個比較好理解。

???? ? ? ?看下別人比較專業的解釋:

????????? 在了解中斷上下文時,先來回顧另一個熟悉概念:進程上下文(這個中文翻譯真的不是很好理解,用“環境”比它好很多)。一般的進程運行在用戶態,如果這個進程進行了系統調用,那么此時用戶空間中的程序就進入了內核空間,并且稱內核代表該進程運行于內核空間中。由于用戶空間和內核空間具有不同的地址映射,并且用戶空間的進程要傳遞很多變量、參數給內核,內核也要保存用戶進程的一些寄存器、變量等,以便系統調用結束后回到用戶空間繼續執行。這樣就產生了進程上下文。

?????????? 所謂的進程上下文,就是一個進程在執行的時候,CPU的所有寄存器中的值、進程的狀態以及堆棧中的內容。當內核需要切換到另一個進程時(上下文切換),它需要保存當前進程的所有狀態,即保存當前進程的進程上下文,以便再次執行該進程時,能夠恢復切換時的狀態繼續執行。上述所說的工作隊列所要做的工作都交給工作者線程來處理,因此它可以表現出進程的一些特性,比如說可以睡眠等。??????????????對于中斷而言,是硬件通過觸發信號,導致內核調用中斷處理程序,進入內核空間。這個過程中,硬件的一些變量和參數也要傳遞給內核,內核通過這些參數進行中斷處理,中斷上下文就可以理解為硬件傳遞過來的這些參數和內核需要保存的一些環境,主要是被中斷的進程的環境。因此處于中斷上下文的tasklet不會有睡眠這樣的特性。

4、工作隊列的使用方法

內核中通過下述結構體來表示一個具體的工作:

[cpp]?view plain?copy
  • struct?work_struct??
  • ????{??
  • ??????unsigned?long?pending;//這個工作是否正在等待處理??
  • ??????struct?list_head?entry;//鏈接所有工作的鏈表,形成工作隊列??
  • ??????void?(*func)(void?*);//處理函數??
  • ??????void?*data;//傳遞給處理函數的參數??
  • ??????void?*wq_data;//內部使用數據??
  • ??????struct?timer_list?timer;//延遲的工作隊列所用到的定時器??
  • ????};??
  • ?????????? 而這些工作(結構體)鏈接成的鏈表就是所謂的工作隊列。工作者線程會在被喚醒時執行鏈表上的所有工作,當一個工作被執行完畢后,相應的work_struct結構體也會被刪除。當這個工作鏈表上沒有工作時,工作線程就會休眠。

    (1)、通過如下宏可以創建一個要推后的完成的工作:

    [cpp]?view plain?copy
  • DECLARE_WORK(name,void(*func)(void*),void*data);??
  • (2)、也可以通過下述宏動態創建一個工作:

    [cpp]?view plain?copy
  • INIT_WORK(struct?work_struct*work,void(*func)(void*),void?*data);??
  • 與tasklet類似,每個工作都有具體的工作隊列處理函數,原型如下:

    [cpp]?view plain?copy
  • void?work_handler(void?*data)??
  • 將工作隊列機制對應到具體的中斷程序中,即那些被推后的工作將會在func所指向的那個工作隊列處理函數中被執行。

    (3)、實現了工作隊列處理函數后,就需要schedule_work函數對這個工作進行調度,就像這樣:

    [cpp]?view plain?copy
  • schedule_work(&work);??
  • 這樣work會馬上就被調度,一旦工作線程被喚醒,這個工作就會被執行(因為其所在工作隊列會被執行)。

    二、input子系統概述 可見文章基于 mini2440 電阻式觸摸屏(三):Linux輸入子系統(InputSubsystem):

    ??????????? 按鍵、鼠標、觸摸屏、電池信息等,都是通過input子系統上報。

    三、Linux與Android 多點觸摸協議

    ??????????? 為了使用功能強大的多點觸控設備,就需要一種方案去上報用戶層所需的詳細的手指觸摸數據。這個文檔所描述的多點觸控協議可以讓內核驅動程序向用戶層上報任意多指的數據信息。

    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()函數上報觸摸信息開始動作并告訴接收方開始接收下一系列多點觸摸信息。

    ???????????? 協議定義了一系列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,用來支持硬件跟蹤多點信息,即該點屬于哪一條線等。

    [cpp]?view plain?copy
  • 下面是兩點觸摸支持的最小事件集序列:??
  • 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?//開始動作??
  • 2、Event原語

    ??????????????? 接觸”一詞用來描述一個物體直接碰到另一個物體的表面。

    ??????????????? ABS_MT_TOUCH_MAJOR描述了主接觸面的長軸,它和X,Y同一個單位,如果一個面的分辨率為X*Y,則ABS_MT_TOUCH_MAJOR的最大值為sqrt(X^2+Y^2)

    [cpp]?view plain?copy
  • <span?style="white-space:pre">??</span>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描述了從接觸開始到釋放的整個過程的集合,如果設備不支持,此參數可是不用。

    3、觸摸軌跡

    ??????????? 僅有少數設備可以明觸的標識真實的 trackingID,多數情況下 trackingID只能來標識一次觸摸動作的過程。

    4、手勢

    ??????????? 多點觸摸指定的應用是創建手勢動作, TOUCH和 WIDTH參數經常用來區別手指的壓力和手指間的距離,另外 MINOR類的參數可以用來區別設備的接觸面的大小(點接觸還是面接觸),ORIENTATION可以產生旋轉事件。

    5、在Linux內核支持的基礎上,Android在其2.0源碼中加入多點觸摸功能(android4.0中間層有所不同)

    ??????????? 由此觸摸屏在Android的frameworks被完全分為2種實現途徑:單點觸摸屏的單點方式,多點觸摸屏的單點和多點方式。

    ?????????????在Linux的input.h中,多點觸摸功能依賴于以下幾個主要的軟件位:

    [cpp]?view plain?copy
  • ……??
  • #define?SYN_REPORT0??
  • #define?SYN_CONFIG1??
  • #define?SYN_MT_REPORT2??
  • ……??
  • #define?ABS_MT_TOUCH_MAJOR0x30??
  • #define?ABS_MT_TOUCH_MINOR0x31??
  • #define?ABS_MT_WIDTH_MAJOR0x32??
  • #define?ABS_MT_WIDTH_MINOR0x33??
  • #define?ABS_MT_ORIENTATION0x34??
  • #define?ABS_MT_POSITION_X0x35??
  • #define?ABS_MT_POSITION_Y0x36??
  • #define?ABS_MT_TOOL_TYPE0x37??
  • #define?ABS_MT_BLOB_ID0x38??
  • ……??

  • 在Android 中對應的軟件位定義在RawInputEvent.java中:

    ??

    [cpp]?view plain?copy
  • ……??
  • ?public?class?RawInputEvent?{??
  • ?……??
  • ?public?static?final?int?CLASS_TOUCHSCREEN_MT?=?0x00000010;??
  • ?……??
  • ?public?static?final?int?ABS_MT_TOUCH_MAJOR?=?0x30;??
  • ?public?static?final?int?ABS_MT_TOUCH_MINOR?=?0x31;??
  • ?public?static?final?int?ABS_MT_WIDTH_MAJOR?=?0x32;??
  • ?public?static?final?int?ABS_MT_WIDTH_MINOR?=?0x33;??
  • ?public?static?final?int?ABS_MT_ORIENTATION?=?0x34;??
  • ?public?static?final?int?ABS_MT_POSITION_X?=?0x35;??
  • ?public?static?final?int?ABS_MT_POSITION_Y?=?0x36;??
  • ?public?static?final?int?ABS_MT_TOOL_TYPE?=?0x37;??
  • ?public?static?final?int?ABS_MT_BLOB_ID?=?0x38;??
  • ?……??
  • ?public?static?final?int?SYN_REPORT?=?0;??
  • ?public?static?final?int?SYN_CONFIG?=?1;??
  • ?public?static?final?int?SYN_MT_REPORT?=?2;??
  • ?……??
  • ? ??在Android中,多點觸摸的實現方法在具體的代碼實現中和單點是完全區分開的。在Android代碼的EventHub.cpp中,單點屏和多點屏由如下代碼段來判定:

    [cpp]?view plain?copy
  • int?EventHub::open_device(const?char?*deviceName)??
  • {??
  • ……??
  • if?(test_bit(ABS_MT_TOUCH_MAJOR,?abs_bitmask)??
  • &&?test_bit(ABS_MT_POSITION_X,?abs_bitmask)??
  • &&?test_bit(ABS_MT_POSITION_Y,?abs_bitmask))?{??
  • device->classes?|=?CLASS_TOUCHSCREEN?|?CLASS_TOUCHSCREEN_MT;??
  • //LOGI("It?is?a?multi-touch?screen!");??
  • }??
  • ??
  • //single-touch???
  • else?if?(test_bit(BTN_TOUCH,?key_bitmask)??
  • &&?test_bit(ABS_X,?abs_bitmask)??
  • &&?test_bit(ABS_Y,?abs_bitmask))?{??
  • device->classes?|=?CLASS_TOUCHSCREEN;??
  • //LOGI("It?is?a?single-touch?screen!");??
  • }??
  • ……??
  • }??
  • ??????????????? 我們知道,在觸摸屏驅動中,通常在probe函數中會調用input_set_abs_params給設備的input_dev結構體初始化,這些input_dev的參數會在Android的EventHub.cpp中被讀取。如上可知,如果我們的觸摸屏想被當成多點屏被處理,只需要在驅動中給input_dev額外增加以下幾個參數即可:

    [cpp]?view plain?copy
  • ?input_set_abs_params(mcs_data.input,?ABS_MT_POSITION_X,?pdata->abs_x_min,?pdata->abs_x_max,?0,?0);??
  • ?input_set_abs_params(mcs_data.input,?ABS_MT_POSITION_Y,?pdata->abs_y_min,?pdata->abs_y_max,?0,?0);??
  • ?input_set_abs_params(mcs_data.input,?ABS_MT_TOUCH_MAJOR,?0,?15,?0,?0);//相當于單點屏的ABX_PRESSURE??
  • ?input_set_abs_params(mcs_data.input,?ABS_MT_WIDTH_MAJOR,?0,?15,?0,?0);//相當于單點屏的ABS_TOOL_WIDTH??
  • ?????????????? 由于多點觸摸技術需要采集到多個點,然后再一起處理這些點,所以在軟件實現中需要保證每一波點的準確性和完整性。因此,Linux內核提供了input_mt_sync(struct input_dev * input)函數。在每波的每個點上報后需要緊跟一句input_mt_sync(),當這波所有點上報后再使用input_sync()進行同步。

    [cpp]?view plain?copy
  • 例如一波要上報3個點:??
  • ???……??
  • ??input_mt_sync(input);??
  • ??……??
  • ??input_mt_sync(input);??
  • ??……??
  • ??input_mt_sync(input);??
  • ??input_sync(input);??
  • ?注:即使是僅上報一個點的單點事件,也需要一次input_mt_sync。<span?style="font-family:Arial,?Helvetica,?sans-serif;"><span?style="white-space:?normal;">??
  • </span></span> ?
  • 總結

    以上是生活随笔為你收集整理的android 电容屏(二):驱动调试之基本概念篇的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。