input子系統詳解


一、初識linux輸入子系統

linux輸入子系統(linux input subsystem)從上到下由三層實現,分別為:輸入子系統事件處理層(EventHandler)、輸入子系統核心層(InputCore)和輸入子系統設備驅動層。

 

對於輸入子系統設備驅動層而言,主要實現對硬件設備的讀寫訪問,中斷設置,並把硬件產生的事件轉換為核心層定義的規范提交給事件處理層。即將底層的硬件輸入轉化為統一事件形式,想輸入核心(Input Core)匯報。

 

對於核心層而言,為設備驅動層提供了規范和接口。設備驅動層只要關心如何驅動硬件並獲得硬件數據(例如按下的按鍵數據),然后調用核心層提供的接口,核心層會自動把數據提交給事件處理層。承上啟下。為驅動層提供輸入設備注冊與操作接口,如:input_register_device;通知事件處理層對事件進行處理;在/Proc下產生相應的設備信息

 

對於事件處理層而言,則是用戶編程的接口(設備節點),並處理驅動層提交的數據處理。和用戶空間交互。(Linux中在用戶空間將所有的設備都當初文件來處理,由於在一般的驅動程序中都有提供fops接口,以及在/dev下生成相應的設備文件nod,這些操作在輸入子系統中由事件處理層完成)

 

對於linux輸入子系統的框架結構如下圖1所示:

 

由上圖所展現的內容就是linux輸入子系統的分層結構。

 

/dev/input目錄下顯示的是已經注冊在內核中的設備編程接口,用戶通過open這些設備文件來打開不同的輸入設備進行硬件操作。

 

事件處理層為不同硬件類型提供了用戶訪問及處理接口。例如當我們打開設備/dev/input/mice時,會調用到事件處理層的Mouse Handler來處理輸入事件,這也使得設備驅動層無需關心設備文件的操作,因為Mouse Handler已經有了對應事件處理的方法。

 

輸入子系統由內核代碼drivers/input/input.c構成,它的存在屏蔽了用戶到設備驅動的交互細節,為設備驅動層和事件處理層提供了相互通信的統一界面。

由上圖可知輸入子系統核心層提供的支持以及如何上報事件到input event drivers。

作為輸入設備的驅動開發者,需要做以下幾步:

  在驅動加載模塊中,設置你的input設備支持的事件類型,類型參見表1設置

    注冊中斷處理函數,例如鍵盤設備需要編寫按鍵的抬起、放下,觸摸屏設備需要編寫按下、抬起、絕對移動,鼠標設備需要編寫單擊、抬起、相對移動,並且需要在必要的時候提交硬件數據(鍵值/坐標/狀態等等)

      將輸入設備注冊到輸入子系統中

 

 

表1  Linux輸入子系統支持的數據類型

EV_SYN     0x00    同步事件

EV_KEY     0x01    按鍵事件

EV_REL     0x02    相對坐標(如:鼠標移動,報告相對最后一次位置的偏移)

EV_ABS     0x03    絕對坐標(如:觸摸屏或操作桿,報告絕對的坐標位置)

EV_MSC     0x04    其它

EV_SW      0x05    開關

EV_LED     0x11    按鍵/設備燈

EV_SND     0x12    聲音/警報

EV_REP     0x14    重復

EV_FF      0x15    力反饋

EV_PWR    0x16    電源

EV_FF_STATUS    0x17   力反饋狀態

EV_MAX    0x1f    事件類型最大個數和提供位掩碼支持


由表1可知,設備所能表示的事件種類,一個設備可以選擇一個或多個事件類型上報給輸入子系統。

 

Linux輸入子系統提供了設備驅動層上報輸入事件的函數,在include/linux/input.h中:

voidinput_report_key(struct input_dev *dev, unsigned int code, int value);      //上報按鍵事件

voidinput_report_rel(struct input_dev *dev, unsigned int code, int value);       //上報相對坐標事件

voidinput_report_abs(struct input_dev *dev, unsigned int code, int value);       //上報絕對坐標事件

……

當提交輸入設備產生的輸入事件之后,需要調用下面的函數來通知輸入子系統,以處理設備產生的完整事件:

void input_sync(struct input_dev *dev);  

 

 設備描述:

input_dev結構

 實現設備驅動核心工作是:向系統報告按鍵、觸摸屏等輸入事件(event,通過input_event結構描述),不再需要關心文件操作接口。驅動報告事件經過inputCoreEventhandler到達用戶空間。

 

注冊輸入設備函數:

int input_register_device(struct input_dev *dev)

 

注銷輸入設備函數:

void input_unregister_device(struct input_dev *dev)

 

驅動實現——初始化(事件支持)

set_bit()告訴input輸入子系統支持哪些事件,哪些按鍵。例如:

 

set_bit(EV_KEY,button_dev.evbit)  (其中button_devstruct input_dev類型)

struct input_dev中有兩個成員為:

evbit:

事件類型(包括

EV_RST,EV_REL,EV_MSC,EV_KEY,EV_ABS,EV_REP等)

keybit:

按鍵類型(當事件類型為EV_KEY時包括

BTN_LEFT,BTN_0,BTN_1,BTN_MIDDLE等)

驅動實現——報告事件:

用於報告EV_KEY,EV_REL,EV_ABS事件的函數分別為void input_report_key(struct

  input_dev *dev,unsigned int code,int value)

void input_report_rel(struct

  input_dev *dev,unsigned int code,int value)

void input_report_abs(struct

  input_dev *dev,unsigned int code,int value)

 

驅動實現——報告結束:

input_sync()同步用於告訴input core子系統報告結束。

 

實例:觸摸屏設備驅動中,一次點擊的整個報告過程如下:

input_reprot_abs(input_dev,ABS_X,x);   //x坐標

input_reprot_abs(input_dev,ABS_Y,y);   // y坐標

input_reprot_abs(input_dev,ABS_PRESSURE,1);

input_sync(input_dev);//同步結束

 

 

實例分析(按鍵中斷程序):

//按鍵初始化

static int __init button_init(void)

{//申請中斷

if(request_irq(BUTTON_IRQ,button_interrupt,0,”button”,NUll))

      return –EBUSY;

set_bit(EV_KEY,button_dev.evbit); //支持EV_KEY事件

 

set_bit(BTN_0,button_dev.keybit); //支持設備兩個鍵

 

set_bit(BTN_1,button_dev.keybit); //

 

input_register_device(&button_dev);//注冊input設備

}

/*在按鍵中斷中報告事件*/

Static void button_interrupt(int irq,void *dummy,struct pt_regs *fp)

{

input_report_key(&button_dev,BTN_0,inb(BUTTON_PORT0));//讀取寄存器BUTTON_PORT0的值

input_report_key(&button_dev,BTN_1,inb(BUTTON_PORT1));

input_sync(&button_dev);

}

總結:input子系統仍然是字符設備驅動程序,但是代碼量減少很多,input子系統只需要完成兩個工作:初始化和事件報告(這里在linux中是通過中斷來實現的)。讀者不妨用sourceinsignt 輸入input_init去搜關於輸入子系統的實現

 

 

http://blog.csdn.net/ielife/article/details/7798952

http://www.cnblogs.com/deng-tao/p/6094049.html

http://www.cnblogs.com/myblesh/articles/2367648.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM