




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、驅動】 input 子系統(tǒng)整體流程全面分析(觸摸屏驅動為例)input 輸入子系統(tǒng)整體流程input 子系統(tǒng)在內核中的實現(xiàn),包括輸入子系統(tǒng)( InputCore ),事件處理層( Event Handler )和設備驅動層。在開頭部分會從設備驅動層做為線索,分析輸入子系統(tǒng) 和事件處理層是如何配合的,最后從用戶角度出發(fā),從 “ /dev/input/* ”接口如何使用輸入子系統(tǒng)提供的服務。既然需要詳細分析,有一個這樣的流程圖能夠幫助我們 在被繞進代碼的過程中,找到出口,你能夠知道你現(xiàn)在位于 代碼框架的什么位置,不會忘記正在分析的代碼的“身份”。設備驅動層注冊到 input 子系統(tǒng)以 S3C244
2、0 觸摸屏的驅動代碼代例,初始化函數(shù)定義 了 struct input_dev input 結構體,它用于描述一個輸入子系 統(tǒng)設備。任何驅動設備如果想標明自己是輸入設備,都應該通過 初始化這樣的結構體,并且調用 input_allocate_device () 函數(shù)進行注冊。了解這一過程,先看一下 struct input_dev 結構體的內 容:View Code 就這樣赤裸裸的看上面的結構體,會覺得摸不著頭腦, 但是有一點是確定的,我們在寫輸入設備驅動時會定義這樣 一個輸入設備結構體,并調用 input_allocate_device() 函數(shù), 這個函數(shù)的功能是為新添加的輸入設備分配內存
3、,如果成功, 將返回 input_dev * 的指針結構, 因此在寫驅動的時候應該接 受返回值,作為驅動層獲得了一個新的輸入設備操作的接口。那么 input_allocate_device() 函數(shù)做了什么呢?打開函 數(shù)看一下( input.c 中實現(xiàn)):View Code通過 input_allocate_device() 函數(shù),我們設備驅動現(xiàn)在持 有的 input_dev 里面就被賦予了 input 的“形象”,但是還需要 我們去充實一下“內在”,因此,設備驅動程序,還需要為自 己的設備增加自己的特性,才能創(chuàng)造獨有的設備“形象”View Code這部分完成了輸入設備的初始化工作。但是這僅是
4、初始 化自己的“特點”,還需要通知輸入子系統(tǒng)有這樣一個新設備 誕生了,這就需要調用輸入子系統(tǒng)的注冊函數(shù) input_register_device ( input_dev )來完成。input_register_device() 用于注冊一個輸入設備。那么注 冊過程是怎樣的呢?這是一個重點,在下面的代碼中進行注 釋分析:View Code 上面的代碼主要的功能有以下幾個功能,也是設備驅動 注冊為輸入設備委托內核做的事情:進一步初始化輸入設備,例如連擊事件; 注冊輸入設備到 input 類中; 把輸入設備掛到輸入設備鏈表 input_dev_list 中; 查找并匹配輸入設備對應的事件處理層,通
5、過 input_handler_list 鏈表我們需要再分析下這個匹配的過程,但是需要注意的 是下面分析的代碼是我們暫時無法分析的,因為那樣會使得 情況變得更加復雜,當我們從應用層往下分析的時候一切都會明白。 input_attach_handler 匹配過程如下:View Code先來看下 input_match_device() 函數(shù),看一下這個匹配 的條件是什么,如何匹配的過程是怎樣的,匹配的結果會是 什么?View Code既然證明是合適的, 接下來就應該登記注冊, 并公證了。 還記得 handler->connect(handler, dev, id) 函數(shù)吧。當 input_
6、match_device ()找到最合適的事件處理層驅 動時,便執(zhí)行 handler->connect 函數(shù)進行公證了, 看下面 這部分代碼(假如說找到了 evdev 類型的驅動,在 input/evdev.c 中):View Code通過上述代碼的執(zhí)行,最終,輸入設備在 input_register_handle() 的關聯(lián)下與已經匹配上的 handler 結 合View Code以上是輸入設備驅動注冊的全過程,牽涉的代碼比較多, 需要從宏觀上理順??v觀整個過程: 輸入設備驅動最終的目的就是能夠與事件處理層的事 件驅動相互匹配,但是在 drivers/input 目錄下有 evdev.
7、c 事 件驅動、 mousedev.c 事件驅動、 joydev.c 事件驅動等等, 我們的輸入設備產生的事件應該最終上報給誰,然后讓事件 驅動再去處理呢?知道了這么個原因再看上面代碼就會明白,其實 evdev.c 、mousedev.c 等根據(jù)硬件輸入設備的處理方式的不 同抽象出了不同的事件處理接口幫助上層去調用,而我們寫 的設備驅動程序只不過是完成了硬件寄存器中數(shù)據(jù)的讀寫, 但提交給用戶的事件必須是經過事件處理層的封裝和同步 才能夠完成的,事件處理層提供給用戶一個統(tǒng)一的界面來操 作。由于以上的這些原因,才有了上述代碼的關聯(lián)過程,看 一下整個關聯(lián)注冊的過程:通過上圖我們可以看到 input
8、輸入設備匹配關聯(lián)的關鍵過程以及涉及到的關鍵函數(shù)和數(shù)據(jù)以上主要是從 input 設備驅動程序的角度去看輸入子系統(tǒng)的注冊過程和三層之間的關聯(lián)。下面將從應用層的角度分析事件的接受過程和處理過程以及三層之間是如何配合處理輸入事件的。從應用層的角度出發(fā)看 input 子系統(tǒng)以上部分已經借助 input 子系統(tǒng)把 input 設備驅動層與事 件驅動層進行了關聯(lián),以 s3c2440_ts.c (輸入設備層驅動) 和 evdev.c (事件處理層驅動)為例,來分析這一過程。 由于 s3c2440_ts.c 中上報的事件類型為按鍵、絕對值坐標, 而 evdev 事件驅動程序是全匹配的, 因此早在 s3c2440
9、_ts.c 注冊的過程中,就會創(chuàng)建設備節(jié)點 /dev/input/event0 (假設 內核中沒有其他的 event 類型的輸入設備, 這里就是 event0 )我們知道,應用層使用設備的第一步,是open( “ /dev/event0 ”因)此,這里 event0 的主設備號成為關鍵, 因為主設備號將表明你是什么設備,我們 ls -l 查看 /dev/event0 發(fā)現(xiàn):crw-r1 root root 13, 64 2012-07-26 14:32/dev/input/event0由此可見主設備是 13 ,輸入命令 cat /proc/devices 查看 主設備為 13 的是 input
10、 設備,因此可以確定當我們執(zhí)行 open 函數(shù)打開 event0 設備的時候,會調用 input 設備的 open 驅 動函數(shù), 這個函數(shù)在 input.c 中,為了說明這一問題, 需要從 input 驅動注冊過程開始,還是 input.c 文件:View Code可以看到,輸入設備初始化的過程首先建立了 input 類, 初始化 input 在 proc 下的節(jié)點,然后注冊 input 設備,設備 名稱為 input ,操作接口是 input_fops ,主設備號是 INPUT_MAJOR=13 。由以上可知,只要是主設備號為 13 的設備驅動程序, 都是用 input_fops 接口,即當
11、 event0 設備使用 open 函數(shù)打 開時,會調用到 input_fops 接口中的 open 驅動函數(shù),這個 結構體的初始化為:View Code可以看到,只實現(xiàn)了一個 open 功能字段,再看input_open_file 的實現(xiàn):View Code以上代碼的功能為找到對應事件驅動層的fops ,即進行fops 的接口轉換,指向對應設備的事件處理接口。其中 input_tableiminor(inode)>>5 的 input_table 是一個全局的 input_handler 類型的數(shù)組, iminor(inode) 取得 次設備號,并且右移 5 位索引 input_
12、table 表中對應的位置, 為什么這樣做呢?這是因為這個表格中填寫的就是事件處 理的指針,待會分析。繼續(xù)查看下面的代碼。 if 中將判斷是否為空并且事件處 理層中的 fops 有沒有初始化, 如果沒有就不能進行接口轉換, 報出設備不存在的錯誤, 如果設備存在則把 input 設備的 f_op 驅動接口指向 input_table 表中存在的接口,并調用其 open 函數(shù)。那么這個 input_table 里面到底存放了什么呢?我們還 是拿觸摸屏驅動來講解。由于觸摸屏驅動已經完成了和 evdev.c 事件處理層的匹配,且次設備號為 64 ,設備名稱為 /dev/event0 ,這是我們通過分析
13、驅動注冊中獲得的內容,既 然 input 核心設備注冊了, s3c2440 觸摸屏驅動也注冊了, 那會不會 evdev 設備也會注冊了呢?答案是肯定的, 要想知 道 input_table 里面放了什么,必須要去查看 evdev 設備的注冊過程,打開 input/evdev.c 查看它的注冊過程:View Code 由以上的內容可以知道 evdev_handler 也被作為一個設 備來操作, 但是它屬于 input handler 事件處理設備, 然而我 們在 evdev_handler 結構體的 .fops 字段又發(fā)現(xiàn)它的驅動接 口為字符設備類型,在 input 中,如果 input_tab
14、le 匹配到了 evdev_handler ,將會把 file->f_op=&evdev_fops , 那么如果使用 read 、 write 等函數(shù)操作,將會調用到 evdev_fops 中的 read 、 write 。為了進一步查看 input_table 表中的內容是如何填充的, 還需要查看這個注冊的過程:View Code當然這個注冊過程并不是只有這么一句話,看到這條語 句,相信應該知道什么意思了。在 input 的 open 函數(shù)執(zhí)行之前, 即我們的 open 代碼打 開之前, input_table 中的字段已經被事件處理層填充了。由于 evdev 的次設備號在初始
15、化的時候就設置成了64 ,因此這里相當于:View Code回到 input_open_file 函數(shù)查看 new_fops->open(inode, file) 便知道了調用的是 :View Code在分析 open 函數(shù)之前,解釋一下為什么要右移 5 位? 這說明一個問題,次設備號的低 5 位被忽略,這說明 evdev的最大支持的輸入設備驅動個數(shù)為2A5次方等于32個,你可能會看到你的 /dev 目錄下面有 event0 、 event1 、 event2 等設備,他們的次設備號分別為64、65、66 等等。但最大是 64+32-1 ,因此 input_table 為這些輸入設備增加
16、的 一個統(tǒng)一接口,通過上層打開設備時,只要次設備號在 64+32-1 之間的設備都會重新定位到 evdev_handler 中,即 event* 設備打開后執(zhí)行的底層函數(shù)將被重新定義到 evdev_handler 中。相信上面的問題已經描述清楚,如果還是不明白,最起 碼應該知道的是, input 設備中的 open 函數(shù)只是一個接口, 通過次設備號才找到了真正的事件處理接口。接下來要看新 的 open 接口的實現(xiàn)了, evdev_handler-> fops->open 實現(xiàn)如下:View Code上面截取了片段,并沒有執(zhí)行到 open 函數(shù), open 進行 自減操作,表示沒有調
17、用過 open ,這個值主要是為了 close 中判斷 open 為 0 時釋放資源使用。不僅如此,我們在觸摸屏驅動中也沒有定義 read 、write , 那當觸摸屏上報事件時,是如何處理的呢?我們需要先到觸摸屏驅動程序中找到上報事件的函數(shù) 再做進一步分析。輸入設備上報事件的處理過程觸摸屏驅動程序上報事件的函數(shù)為:View Code然而他們其實是 input_event 函數(shù)的封裝,調用的都是input_event 函數(shù),這一函數(shù)在 input.c 中實現(xiàn)如下:View Code代碼被做了精簡,其中就是在匹配上報的事件,并根據(jù) 事件的類型調用驅動程序中相應的函數(shù)來完成,但是由于我 們并沒有定
18、義過這些函數(shù),因此執(zhí)行最后的 handle_handler_event 函數(shù), 由事件處理層 evdev_event 函 數(shù)來完成事件的保存工作,具體過程如下:View Code這里列舉了關鍵代碼,即上報的事件被保存到了 client_buffer 中,其中 client_buffer 是一個循環(huán)緩沖區(qū), client->head 表示當前數(shù)據(jù)的位置,因此每次都寫到 client->head 的位置,而讀數(shù)據(jù)時需要到 client_tail 中讀 取。因為在 open 的時候, client 已經被鏈入到了 evdev->client_list 中,因此通過可以通過 list_for_each_entry 重 evdev->client_list 中找到對應的 client 。事件的上報都會把數(shù)據(jù)保存到 client->buffer 中,以 便上層通過 read 和 write 進行讀去和寫入。通過設備節(jié)點讀取輸入事件還是以觸摸屏驅動程序和 evdev 事件處理層驅動來分析:View Code這里如果沒有數(shù)據(jù),進程會睡眠,那由誰來喚醒呢?細 心的話可以發(fā)現(xiàn),當設備驅動層調用 input_event 上報事件 調用相應的 event 函數(shù)進行事件寫入時,是會喚醒阻塞等待 的進程的。通過設備節(jié)點寫入輸入事件寫入過程:View Code上述代碼中的 eve
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 旅游景區(qū)開發(fā)及運營服務合同
- 工程合同管理工作制度
- 擔保合同第三方擔保
- 職工勞動合同協(xié)議書
- 個人集資房屋買賣合同
- 商場物業(yè)合同年
- 房屋土地出租合同書
- 出租車庫正式合同
- 淺析合同擔保之定金
- 福建幼兒師范高等??茖W?!冬F(xiàn)代企業(yè)管理》2023-2024學年第二學期期末試卷
- 《古詩三首》五年級下冊第一單元教學方案
- 中國農業(yè)大學人文與發(fā)展學院管理服務崗位招聘筆試真題2023
- 2025年農村婦婦兩癌檢查項目實施方案工作計劃
- 上海美食介紹
- 新人教版三年級下冊《道德與法治》教案
- 2024年11月時事政治試題及答案
- 烈士褒揚課件教學課件
- 退休延期留用崗位協(xié)議書
- 3.1 歌曲《音階歌》課件(10張內嵌音頻)
- 中醫(yī)適宜技術-中藥熱奄包
- 2024年儲能行業(yè)市場全景分析及發(fā)展趨勢展望報告
評論
0/150
提交評論