在介紹觸摸屏驅動之前,先來認識一下這個input子系統。在學習觸摸屏之前,我幾乎完全沒有聽說過input子系統這個概念,現在就讓我們一起來揭開它神祕的面紗吧。
在我們的Linux系統中,按鍵、觸摸屏、鼠標等輸入型設備都可以利用input接口函數來實現設備驅動。
一.系統架構
左邊部分是我們驅動工程師應該完成的部分,而input core 和handlers 是內核已經提供好的,我們只需要根據input core 所要求的接口編寫driver部分即可。那我們的驅動實際做了什麼工作呢?它完成的工作其實很簡單,將底層的硬件輸入轉化爲同一事件形式,向input core彙報。input core起了承上啓下的作用,它爲驅動層提供輸入設備註冊與操作接口,如input_register_device;通知handlers 對事件進行處理;在/PROC 下產生相應的設備信息。而handlers 則主要和我們的用戶空間打交道。我們知道Linux在用戶空間將所有設備當成文件來處理,在一般的驅動程序中都有提供fops接口,以及在/dev下生成相應的設備文件,而在輸入子系統中,這些工作都是由handlers 完成。
二.設備描述
在Linux內核中,input設備用input_dev結構體描述,使用input子系統實現輸入設備驅動的時候,驅動的核心工作就是向系統報告按鍵、觸摸屏、鍵盤、鼠標等輸入事件(event,通過input_event結構體描述),不再需要關心文件操作接口,因爲Input子系統已經完成了文件操作接口。驅動報告的時間經過inputcore 和handlers 最終到達用戶空間。其實它仍然是一個字符設備,只是劃分方法不一樣罷了。
三.設備註冊/註銷
註冊輸入設備的函數
int input_register_device(struct input_dev *dev)
註銷輸入設備的函數
void input_unregister_device(struce input_dev *dev)
四.驅動實現——事件支持
設備驅動通過set_bit()告訴input子系統它支持哪些時間,哪些按鍵。
例子:
set_bit(EV_KEY, button_dev.evbit)
其中我們關注第二個參數button_dev,它是一個input_dev 結構體,有兩個成員:
evbit:事件類型
keybit:按鍵類型
常見事件類型:EV_KEY 按鍵
EV_REL 相對座標
EV_ABS 絕對座標
當事件類型爲EV_KEY時,還需指明按鍵類型:
BTN_LEFT 鼠標左鍵
BTN_RIGHT 鼠標右鍵
BTN_MIDDLE 鼠標中鍵
BTN_0 數字0鍵
BTN_1 數字1鍵
上述set_bit函數實則完成了把EV_KEY賦值到button_dev.evbit
五.驅動實現——報告事件
用於報告EV_KEY事件的函數
void input_report_key(struct input_dev *dev, unsigned int code, int value)
需要注意的參數如下:
code : 事件的代碼,如果事件是ev_key,該代碼則爲設備的鍵盤代碼。例如鼠標按鍵代碼爲0x110~0x116,其中0x110(BTN_LEFT),0x111(BTN_RIGHT),0x112(BTN_MIDDLE)。其它帶按摩含義參考include/linux/input.h文件
value : 事件的值,如果事件的類型是EV_KEY,當按鍵按下時值爲1,鬆開時爲0。
六.驅動實現——報告結束
input_sync()用於高速input core 此次報告已經結束,能夠根據上報的信息往後面處理了,不然input core還在傻傻地等待着我們的驅動呢。
實例:在觸摸屏設備驅動中,一次點擊的整個報告過程如下:
input_report_abs(input_dev, ABS_X, x); //報告X座標
input_report_abs(input_dev, ABS_Y, y); //報告Y座標
input_report_abs(input_dev, ABS_PRESSURE, 1); //報告狀態
input_sync(input_dev); //同步(結束)
七.實例分析
下面是按鍵驅動的簡單例子,並不完整:
只要之前瞭解過鍵盤驅動程序的朋友,都對文件操作ops有印象吧?所有的read、ioctl 等操作函數都要我們自己去編寫,而使用input子系統之後,這些工作內核都爲我們做好了,舒心吧?
下面再給出應用程序的代碼
到此爲止,input子系統的介紹就告一段落了,下一篇博文的觸摸屏驅動就是建立在這個input子系統之上搭建而成的,事先了解一下這個是相當有必要的。不是有這麼一句話麼:磨刀不誤砍柴工!