歡迎關(guān)注,每周更新!?
本合集分享的是,我當(dāng)初學(xué)習(xí)Linux驅(qū)動(dòng)的來(lái)時(shí)路——《《驅(qū)動(dòng)之路》開篇:自序&前言》。
正文
回答3個(gè)問(wèn)題:
(1)什么是 Input 子系統(tǒng)?
(2)為什么需要 Input 子系統(tǒng)?
(3)如何使用 Input 子系統(tǒng)?
1 什么是 Input 子系統(tǒng)?
Input 子系統(tǒng)是 Linux 內(nèi)核中一套統(tǒng)一管理輸入設(shè)備的框架,主要是為了將鍵盤、鼠標(biāo)、觸摸屏、按鍵、搖桿等各類輸入設(shè)備的硬件差異抽象化,為上層應(yīng)用提供統(tǒng)一的輸入事件接口(如/dev/input/eventX),這樣可以避免為每種設(shè)備單獨(dú)編寫驅(qū)動(dòng)程序。一句話總結(jié)其作用:“屏蔽硬件差異、提供統(tǒng)一接口”。
2 為什么需要 Input 子系統(tǒng)?
假如沒(méi)有 Input 子系統(tǒng),想要使用一個(gè)輸入設(shè)備,我們需要為每一種設(shè)備單獨(dú)編寫完整的驅(qū)動(dòng)程序,包括硬件初始化、數(shù)據(jù)讀取、事件解析等所有邏輯。這是由于每個(gè)輸入設(shè)備(比如 USB 鍵盤、GPIO 按鍵、I2C 觸摸屏、紅外遙控器)的通信協(xié)議、數(shù)據(jù)格式、觸發(fā)方式都不同。
另外,每新增一種輸入設(shè)備(如新型觸摸屏)時(shí),不僅要編寫全新驅(qū)動(dòng),還可能與現(xiàn)有設(shè)備沖突,甚至需要修改上層應(yīng)用才能適配。這樣不僅導(dǎo)致 Linux 內(nèi)核代碼冗余嚴(yán)重,而且開發(fā)成本和維護(hù)成本極高。
面對(duì)以上種種問(wèn)題,"封裝"與"分層"這兩大經(jīng)典的程序設(shè)計(jì)思想再次發(fā)威,Input 子系統(tǒng)正是基于這樣思想設(shè)計(jì)出來(lái)解決以上問(wèn)題的。
Input 子系統(tǒng)有如下主要作用:
硬件差異屏蔽:不同輸入設(shè)備的通信協(xié)議(如 USB、I2C、SPI、GPIO)和數(shù)據(jù)格式不同,Input 子系統(tǒng)通過(guò)統(tǒng)一的驅(qū)動(dòng)模型,將底層硬件細(xì)節(jié)封裝,上層無(wú)需關(guān)心設(shè)備是 USB 鍵盤還是 GPIO 按鍵;
統(tǒng)一事件接口:所有輸入設(shè)備最終都通過(guò) /dev/input/eventX節(jié)點(diǎn)暴露給用戶空間,應(yīng)用程序可通過(guò)標(biāo)準(zhǔn)的 read ()/poll () 等系統(tǒng)調(diào)用讀取事件(如按鍵按下 / 松開、坐標(biāo)移動(dòng)、手勢(shì)等);
事件標(biāo)準(zhǔn)化:定義了統(tǒng)一的事件類型(如 EV_KEY、EV_ABS、EV_REL)和事件碼(如 KEY_0、ABS_X),確保不同設(shè)備的事件格式一致,上層應(yīng)用可跨設(shè)備兼容。
3 如何使用 Input 子系統(tǒng)?
要想正確使用 Input 子系統(tǒng),不得不理清其3 層架構(gòu):事件處理層、核心層以及驅(qū)動(dòng)層。核心源代碼位于/drivers/input/目錄。
事件處理層(evdev.c):接收核心層轉(zhuǎn)發(fā)的事件,為上層應(yīng)用提供訪問(wèn)接口(如/dev/input/eventX設(shè)備節(jié)點(diǎn))。
核心層(input.c):管理所有輸入設(shè)備,提供驅(qū)動(dòng)注冊(cè) / 注銷接口,轉(zhuǎn)發(fā)驅(qū)動(dòng)層事件到合適的事件層。
驅(qū)動(dòng)層(輸入設(shè)備驅(qū)動(dòng)程序,如gpio_keys.c 等):直接操作硬件(如 GPIO 中斷、讀取電平),將硬件信號(hào)轉(zhuǎn)換為 “標(biāo)準(zhǔn)化輸入事件”。從底層硬件到上層應(yīng)用鏈路如下:

從硬件底層到用戶空間數(shù)據(jù)是如何層層傳遞的?假如用戶空間直接訪問(wèn)/dev/input/event0設(shè)備節(jié)點(diǎn),數(shù)據(jù)的流程大致如下:
(1)用戶空間應(yīng)用程序通過(guò)read()系統(tǒng)調(diào)用讀取/dev/input/eventX設(shè)備節(jié)點(diǎn)。如果此時(shí)內(nèi)核輸入緩沖區(qū)中沒(méi)有可用的事件數(shù)據(jù),該read()調(diào)用會(huì)使應(yīng)用程序進(jìn)入休眠狀態(tài),等待數(shù)據(jù)到達(dá)。
(2)當(dāng)用戶進(jìn)行操作(如觸摸屏幕、按下按鍵)時(shí),輸入設(shè)備的硬件會(huì)產(chǎn)生一個(gè)中斷信號(hào)(例如,觸摸芯片的中斷引腳電平發(fā)生變化)。
(3)當(dāng)驅(qū)動(dòng)程序檢測(cè)到這個(gè)電平時(shí),輸入系統(tǒng)驅(qū)動(dòng)層對(duì)應(yīng)的驅(qū)動(dòng)程序會(huì)調(diào)用中斷處理函數(shù):讀取到數(shù)據(jù),轉(zhuǎn)換為標(biāo)準(zhǔn)的輸入事件,向核心層匯報(bào)。
(4)Input核心層接收到事件后,會(huì)根據(jù)設(shè)備和事件的類型,上報(bào)事件層——將其分發(fā)給已注冊(cè)并匹配的事件處理器(Input Handler),例如evdev_handler。當(dāng)用戶空間正在等待數(shù)據(jù)時(shí),evdev_handler會(huì)把它喚醒,這樣用戶空間就可以獲取到硬件底層的上報(bào)數(shù)據(jù)。
最后,了解下用戶空間獲得數(shù)據(jù)的兩種方法:
直接訪問(wèn)設(shè)備節(jié)點(diǎn)(比如/dev/input/event0,1,2,...);
通過(guò)tslib、libinput 這類庫(kù)來(lái)間接訪問(wèn)設(shè)備節(jié)點(diǎn),這些庫(kù)簡(jiǎn)化了對(duì)數(shù)據(jù)的處理。
如果想繼續(xù)深入理解 Input 子系統(tǒng)是如何將不同輸入設(shè)備的硬件差異統(tǒng)一成標(biāo)準(zhǔn)的輸入事件?請(qǐng)聽(tīng)下回分解。
(完)
本人專注 Linux 驅(qū)動(dòng) & Linux/Android BSP 開發(fā)調(diào)試,可接外包項(xiàng)目/技術(shù)支持/問(wèn)題定位。有需求或交個(gè)朋友可加微信:【Chen_WeChat2026】。
審核編輯 黃宇
-
驅(qū)動(dòng)
+關(guān)注
關(guān)注
12文章
1954瀏覽量
88522 -
Linux
+關(guān)注
關(guān)注
88文章
11758瀏覽量
219009
發(fā)布評(píng)論請(qǐng)先 登錄
迅為RK3568開發(fā)板驅(qū)動(dòng)指南GPIO子系統(tǒng)GPIO子系統(tǒng)API函數(shù)的引入
迅為RK3568驅(qū)動(dòng)指南GPIO子系統(tǒng) GPIO操作函數(shù)實(shí)驗(yàn)
RK3568驅(qū)動(dòng)指南|第十二篇 GPIO子系統(tǒng)-第135章 GPIO子系統(tǒng)與pinctrl子系統(tǒng)相結(jié)合實(shí)驗(yàn)
迅為RK3568驅(qū)動(dòng)指南GPIO子系統(tǒng)實(shí)戰(zhàn):實(shí)現(xiàn)動(dòng)態(tài)切換引腳復(fù)用功能
驅(qū)動(dòng)之路#10:淺談 Input 子系統(tǒng)
評(píng)論