Linux驅(qū)動(dòng)之輸入子系統(tǒng)(張棲銀詳談)

一、input子系統(tǒng)介紹

1.1 系統(tǒng)介紹

本文是基于linux-2.6.32內(nèi)核進(jìn)行分析的州泊,如果使用的是其他版本的內(nèi)核捕捂,其內(nèi)核調(diào)用的函數(shù)可能有所不同,但是其實(shí)現(xiàn)原理是相通的春霍。

1.2 input子系統(tǒng)的引入

以前我們寫(xiě)一些輸入設(shè)備(鍵盤(pán)砸西、鼠標(biāo)等)的驅(qū)動(dòng)都是采用字符設(shè)備、混雜設(shè)備處理的址儒。問(wèn)題由此而來(lái)芹枷,Linux開(kāi)源社區(qū)的大神們看到了這大量輸入設(shè)備如此分散不堪,有木有可以實(shí)現(xiàn)一種機(jī)制莲趣,可以對(duì)分散的鸳慈、不同類(lèi)別的輸入設(shè)備進(jìn)行統(tǒng)一的驅(qū)動(dòng),所以才出現(xiàn)了輸入子系統(tǒng)喧伞。

輸入設(shè)備(如按鍵走芋、鍵盤(pán)绩郎,觸摸屏,鼠標(biāo)等)是典型的字符設(shè)備翁逞,其主設(shè)備號(hào)固定為13肋杖,其一般的工作機(jī)制是在底層在按鍵、觸摸挖函、鼠標(biāo)點(diǎn)擊等動(dòng)作發(fā)生時(shí)產(chǎn)生一個(gè)中斷(或驅(qū)動(dòng)通過(guò)timer定時(shí)查詢)状植,然后CPU通過(guò)SPI、IIC或者外部存儲(chǔ)器總線讀取鍵值怨喘、坐標(biāo)等數(shù)據(jù)津畸,放在一個(gè)緩沖區(qū),字符設(shè)備驅(qū)動(dòng)管理該緩沖區(qū)必怜,而驅(qū)動(dòng)的read()接口讓用戶可以讀取鍵值肉拓、坐標(biāo)等數(shù)據(jù),其過(guò)程如圖1.1所示棚赔。

image
image

在Linux中帝簇,輸入子系統(tǒng)是由輸入子系統(tǒng)設(shè)備驅(qū)動(dòng)層、輸入子系統(tǒng)核心層(input core)和輸入子系統(tǒng)事件處理層(Event handler)組成靠益,如圖1.2所示丧肴。其中設(shè)備驅(qū)動(dòng)層提供對(duì)硬件各寄存器的讀寫(xiě)訪問(wèn)和將底層硬件對(duì)用戶輸入訪問(wèn)的響應(yīng)轉(zhuǎn)換為標(biāo)準(zhǔn)的輸入事件,再通過(guò)核心層提交給事件處理層胧后;而核心層對(duì)下提供了設(shè)備驅(qū)動(dòng)層的編程接口芋浮,對(duì)上又提供了事件處理層的編程接口;而事件處理層就為我們用戶空間的應(yīng)用程序提供了統(tǒng)一訪問(wèn)設(shè)備的接口和驅(qū)動(dòng)層提交來(lái)的事件處理壳快。所以這使得我們輸入設(shè)備的驅(qū)動(dòng)部分不在用戶關(guān)心對(duì)設(shè)備文件的操作纸巷,而是要關(guān)心對(duì)各硬件寄存器的操作和提交的輸入事件。

image
image

1.3 input子系統(tǒng)的優(yōu)點(diǎn)

輸入子系統(tǒng)的引入眶痰,也為我們帶來(lái)了許多的好處:

  • 統(tǒng)一了物理形態(tài)各異的相似的輸入設(shè)備的處理功能瘤旨。例如,各種鼠標(biāo)竖伯,不論P(yáng)S/2存哲、USB、還是藍(lán)牙七婴,都被同樣處理祟偷。
  • 提供了用于分發(fā)輸入報(bào)告給用戶應(yīng)用程序的簡(jiǎn)單的事件(event)接口。你的驅(qū)動(dòng)不必創(chuàng)建打厘、管理/dev節(jié)點(diǎn)以及相關(guān)的訪問(wèn)方法修肠。因此它能夠很方便的調(diào)用輸入API以發(fā)送鼠標(biāo)移動(dòng)、鍵盤(pán)按鍵户盯,或觸摸事件給用戶空間嵌施。X windows這樣的應(yīng)用程序能夠無(wú)縫地運(yùn)行于輸入子系統(tǒng)提供的event接口之上饲化。
  • 抽取出了輸入驅(qū)動(dòng)的通用部分,簡(jiǎn)化了驅(qū)動(dòng)艰管,并提供了一致性滓侍。例如,輸入子系統(tǒng)提供了一個(gè)底層驅(qū)動(dòng)(稱為serio)的集合牲芋,支持對(duì)串口和鍵盤(pán)控制器等硬件輸入的訪問(wèn)。

注:更多詳細(xì)描述可參見(jiàn)《精通Linux設(shè)備驅(qū)動(dòng)程序開(kāi)發(fā)》這本書(shū)捺球。

更重要的是缸浦,input子系統(tǒng)的引入,使我們在具體的開(kāi)發(fā)中可以在輸入硬件設(shè)備更換的情況下保持應(yīng)用不做任何修改氮兵。

1.4 input子系統(tǒng)與字符設(shè)備實(shí)現(xiàn)比較

在進(jìn)行字符設(shè)備驅(qū)動(dòng)程序開(kāi)發(fā)的過(guò)程中裂逐,我們的實(shí)現(xiàn)步驟如下:

  • 申請(qǐng)一個(gè)字符設(shè)備號(hào):可以自己指定,也可系統(tǒng)自動(dòng)分配泣栈;
  • 構(gòu)造一個(gè)file_operations結(jié)構(gòu)體卜高,其包含對(duì)設(shè)備的所有操作;
  • 實(shí)現(xiàn)file_operations結(jié)構(gòu)體中的成員函數(shù)南片;
  • 將字符設(shè)備注冊(cè)進(jìn)系統(tǒng)中:register_chrdev()掺涛;
  • 創(chuàng)建設(shè)備類(lèi)和設(shè)備節(jié)點(diǎn):class_create()、device_create()疼进;
  • 告訴內(nèi)核入口與出口函數(shù):module_init()薪缆、module_exit();

輸入子系統(tǒng)與混雜設(shè)備驅(qū)動(dòng)一樣伞广,也是一個(gè)典型的字符設(shè)備拣帽,那么其注冊(cè)的過(guò)程與字符設(shè)備驅(qū)動(dòng)一樣,也必須經(jīng)過(guò)上面的這些步驟嚼锄。只是輸入子系統(tǒng)中的輸入設(shè)備一般只接收輸入設(shè)備的中斷和獲取輸入設(shè)備的數(shù)據(jù)减拭,而不輸出數(shù)據(jù)到輸入設(shè)備而已。

在輸入子系統(tǒng)中区丑,將字符設(shè)備驅(qū)動(dòng)分為了三個(gè)部分:與硬件操作相關(guān)的設(shè)備驅(qū)動(dòng)層(由驅(qū)動(dòng)工程師實(shí)現(xiàn))拧粪、輸入子系統(tǒng)核心層(input core)和輸入子系統(tǒng)事件處理層(Event handler),其中后面兩個(gè)部分都已經(jīng)由系統(tǒng)幫我們實(shí)現(xiàn)了刊苍。其實(shí)后面兩個(gè)部分可以把它看作是一個(gè)整體既们,就是與硬件操作無(wú)關(guān)的軟件部分。那么我們實(shí)現(xiàn)input設(shè)備驅(qū)動(dòng)的過(guò)程為:

  • 申請(qǐng)一個(gè)輸入設(shè)備結(jié)構(gòu)體:input_allocate_device()正什;
  • 設(shè)置輸入設(shè)備支持的事務(wù)類(lèi)型:set_bit(xxx,devp->evbit)啥纸;
  • 設(shè)置輸入設(shè)備支持的具體哪些事務(wù):set_bit(xxx,devp->xxxbit);
  • 注冊(cè)輸入設(shè)備到輸入子系統(tǒng):input_register_device(devp);
  • 實(shí)現(xiàn)具體的硬件相關(guān)操作,如注冊(cè)中斷等婴氮,并在中斷處理函數(shù)中通知事務(wù)已發(fā)生:input_event()斯棒、input_sync()盾致;

也就是說(shuō):無(wú)論輸入子系統(tǒng)多么強(qiáng)大、封裝的多么的好荣暮,與硬件相關(guān)的操作還是得我們親自實(shí)現(xiàn)庭惜。

1.5 input子系統(tǒng)與字符設(shè)備與應(yīng)用層數(shù)據(jù)交互比較

編寫(xiě)過(guò)字符設(shè)備驅(qū)動(dòng)的人都知道,應(yīng)用程序與驅(qū)動(dòng)之間實(shí)現(xiàn)數(shù)據(jù)交互就是通過(guò)應(yīng)用API的read()穗酥、write()調(diào)用护赊,從而產(chǎn)生一個(gè)SWI軟件中斷,然后通過(guò)主設(shè)備號(hào)找到對(duì)應(yīng)的struct cdev結(jié)構(gòu)體實(shí)體砾跃,從而找到具體硬件設(shè)備的struct file_operations結(jié)構(gòu)體骏啰,然后具體調(diào)用底層的drv_read()、drv_write()抽高,我們就是在具體的drv_read()和drv_write()中實(shí)現(xiàn)對(duì)硬件的操作的判耕,其過(guò)程如下:

read()—>swi_read()—>drv_read()—>硬件操作

那么對(duì)應(yīng)到輸入子系統(tǒng)呢?前面已經(jīng)說(shuō)了翘骂,輸入子系統(tǒng)也是字符設(shè)備壁熄,那么它也必須經(jīng)歷上面的這些步驟,只是中間穿插了幾個(gè)查找具體輸入設(shè)備的過(guò)程(畢竟將所有的輸入設(shè)備都加入到輸入子系統(tǒng)碳竟,就不止一個(gè)設(shè)備了)而已草丧。那么是如何穿插的呢:

首先在input.c(輸入子系統(tǒng)的核心)文件的打開(kāi)函數(shù)中找到具體的input_handler,然后取出具體input_handler中的fops(也即struct file_operations結(jié)構(gòu)體)填充struct file中的f_op成員瞭亮,那么之后應(yīng)用調(diào)用read()方仿、write()函數(shù)就是調(diào)用具體input_handler指向的struct file_operations結(jié)構(gòu)體中的成員了;最后再調(diào)用fops中的open()函數(shù)打開(kāi)具體的函數(shù):

struct input_handler *handler;
handler = input_table[iminor(inode) >> 5];
old_fops = file->f_op;
file->f_op = new_fops;
err = new_fops->open(inode, file);

這里說(shuō)明一下:input.c是input子系統(tǒng)的核心统翩,內(nèi)核已經(jīng)實(shí)現(xiàn)仙蚜,各種input_handler(包含open、release厂汗、read委粉、write、ioctl娶桦、fasync贾节、poll等,即硬件處理函數(shù))也由系統(tǒng)抽象出來(lái)幫我們實(shí)現(xiàn)了衷畦,后面會(huì)講解其具體實(shí)現(xiàn)過(guò)程栗涂。

通過(guò)前面的介紹,不太理解也沒(méi)有關(guān)系祈争。你只需要記住斤程,其實(shí)輸入子系統(tǒng)就是一個(gè)典型的字符設(shè)備,它也逃不過(guò)字符設(shè)備的框架菩混,其應(yīng)用與驅(qū)動(dòng)交互的流程也和字符設(shè)備驅(qū)動(dòng)一樣忿墅,沒(méi)有什么不同就是了(要從心里小瞧它)扁藕。

要想搞明白輸入子系統(tǒng)的框架,只需要弄明白應(yīng)用程序是如何與具體的硬件設(shè)備驅(qū)動(dòng)進(jìn)行交互的就行了疚脐。而這個(gè)過(guò)程如下其實(shí)就是主設(shè)備號(hào)13的字符設(shè)備亿柑、input_handler、input_handle和input_dev幾個(gè)的關(guān)系

  • Linux系統(tǒng)啟動(dòng)時(shí)注冊(cè)輸入子系統(tǒng)(注冊(cè)主設(shè)備號(hào)為13的字符設(shè)備)棍弄;
  • 應(yīng)用程序調(diào)用open()望薄,對(duì)應(yīng)調(diào)用輸入子系統(tǒng)的input_open_file();
  • input_open_file()找到對(duì)應(yīng)的input_handler照卦,并調(diào)用其中的open()式矫;
  • 應(yīng)用程序調(diào)用read()函數(shù),對(duì)應(yīng)調(diào)用open()中找到的input_handler中的read()函數(shù)役耕,阻塞;
  • 驅(qū)動(dòng)收到硬件訪問(wèn)需求聪廉,進(jìn)入中斷處理函數(shù)瞬痘,對(duì)應(yīng)到input_dev;
  • 驅(qū)動(dòng)調(diào)用input_event()上報(bào)事件板熊,上報(bào)過(guò)程為:通過(guò)input_dev找到input_handle框全,再通過(guò)input_handle找到匹配的input_handler,然后調(diào)用該input_handler的event()函數(shù)干签,該函數(shù)即是喚醒對(duì)應(yīng)read()津辩、write()函數(shù)的實(shí)現(xiàn);

詳細(xì)過(guò)程如下三條線路所示:

  1. open()—>input_open_file()—>input_handler->fops->open()
  2. read()/write()/ioctl()—>input_handler->fops->read()/write()/ioctl()
  3. 硬件—>input_dev的中斷處理程序—>input_event()—>input_handle->input_handler->event()

注意:->是指針容劳;—>是下一步調(diào)用喘沿。

從應(yīng)用到底層的匹配過(guò)程是通過(guò)input_handler,具體驅(qū)動(dòng)中是通過(guò)靜態(tài)全局指針數(shù)組變量input_table[]實(shí)現(xiàn)的竭贩;而硬件到應(yīng)用程序的匹配過(guò)程是通過(guò)input_handle結(jié)構(gòu)體找到對(duì)應(yīng)的input_handler蚜印,從而實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)模唧w到代碼就是通過(guò)input_handler->connect()函數(shù)將input_dev留量、input_handler和input_handle三者進(jìn)行綁定的窄赋,三者綁定的關(guān)系如圖1.3所示。


image
image

二楼熄、input子系統(tǒng)實(shí)現(xiàn)

本章節(jié)將詳細(xì)講解input子系統(tǒng)的框架忆绰,也就是input子系統(tǒng)中如何實(shí)現(xiàn)應(yīng)用層數(shù)據(jù)與底層硬件之間的數(shù)據(jù)交互、底層硬件(input_dev)如何與系統(tǒng)實(shí)現(xiàn)的驅(qū)動(dòng)(input_handler)關(guān)聯(lián)等可岂。

2.1 input子系統(tǒng)框架

正如前面的介紹错敢,input子系統(tǒng)將所有的輸入設(shè)備統(tǒng)稱為像鼠標(biāo)輸入、鍵盤(pán)輸入青柄、joydev輸入等伐债,將輸入的數(shù)據(jù)封裝成統(tǒng)一的事務(wù)格式(struct input_event)上傳到應(yīng)用预侯,而將具體的硬件設(shè)備分離出來(lái)(這才是我們要做的事),如圖2.1所示峰锁。


image
image

在如上的系統(tǒng)分層結(jié)構(gòu)下萎馅,我們的應(yīng)用程序就可以不用關(guān)心獲取到的數(shù)據(jù)是來(lái)源于SPI的鍵盤(pán)、還是IIC的鍵盤(pán)虹蒋,它只需要關(guān)心獲取到數(shù)據(jù)的具體含義就行了糜芳,這樣就保證了更換不同的硬件設(shè)備,而不用修改一行應(yīng)用程序代碼魄衅,如圖2.2所示峭竣。

還有 80% 的精彩內(nèi)容
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
支付 ¥3.99 繼續(xù)閱讀
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市晃虫,隨后出現(xiàn)的幾起案子皆撩,更是在濱河造成了極大的恐慌,老刑警劉巖哲银,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扛吞,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡荆责,警方通過(guò)查閱死者的電腦和手機(jī)滥比,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)做院,“玉大人盲泛,你說(shuō)我怎么就攤上這事〖” “怎么了寺滚?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)郁竟。 經(jīng)常有香客問(wèn)我玛迄,道長(zhǎng),這世上最難降的妖魔是什么棚亩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任蓖议,我火速辦了婚禮,結(jié)果婚禮上讥蟆,老公的妹妹穿的比我還像新娘勒虾。我一直安慰自己,他們只是感情好瘸彤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布修然。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪愕宋。 梳的紋絲不亂的頭發(fā)上玻靡,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音中贝,去河邊找鬼囤捻。 笑死,一個(gè)胖子當(dāng)著我的面吹牛邻寿,可吹牛的內(nèi)容都是我干的蝎土。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼绣否,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼誊涯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蒜撮,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤暴构,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后段磨,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體丹壕,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年薇溃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缭乘。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡沐序,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出堕绩,到底是詐尸還是另有隱情策幼,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布奴紧,位于F島的核電站特姐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏黍氮。R本人自食惡果不足惜唐含,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望沫浆。 院中可真熱鬧捷枯,春花似錦、人聲如沸专执。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至攀痊,卻和暖如春桐腌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背苟径。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工案站, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涩笤。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓嚼吞,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蹬碧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子舱禽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 輸入子系統(tǒng)概述 Linux內(nèi)核為了能夠處理各種不同類(lèi)型的輸入設(shè)備,比如 觸摸屏 恩沽,鼠標(biāo) , 鍵盤(pán) , 操縱桿...
    JalynFang閱讀 10,353評(píng)論 4 9
  • 大學(xué)的時(shí)候誊稚,幫朋友寫(xiě)的操作系統(tǒng)調(diào)研的作業(yè),最近整理過(guò)去的文檔時(shí)候偶然發(fā)現(xiàn)罗心,遂作為博客發(fā)出來(lái)里伯。 從串口驅(qū)動(dòng)到Linu...
    free_will閱讀 7,391評(píng)論 7 59
  • 本文開(kāi)啟 linux 內(nèi)核 V4L2 框架部分的學(xué)習(xí)之旅,本文僅先對(duì) V4L2 的框架做一個(gè)綜述性的概括介紹渤闷,然后...
    yellowmax閱讀 7,583評(píng)論 0 13
  • 1:InputChannel提供函數(shù)創(chuàng)建底層的Pipe對(duì)象 2: 1)客戶端需要新建窗口 2)new ViewRo...
    自由人是工程師閱讀 5,313評(píng)論 0 18
  • ??JavaScript 與 HTML 之間的交互是通過(guò)事件實(shí)現(xiàn)的飒箭。 ??事件狼电,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特...
    霜天曉閱讀 3,495評(píng)論 1 11