1. 程式人生 > >輸入子系統之events訊息資料傳遞

輸入子系統之events訊息資料傳遞

參考連結:http://book.51cto.com/art/200803/66870.htm

在Linux核心中,input裝置用input_dev結構體描述,使用input子系統實現輸入裝置驅動的時候,驅動的核心工作是向系統報告按鍵、觸控式螢幕、鍵盤、滑鼠等輸入事件(event,通過input_event結構體描述),不再需要關心檔案操作介面,因為input子系統已經完成了檔案操作介面。驅動報告的事件經過InputCore和 Eventhandler最終到達使用者空間。

通過input子系統,具體的輸入裝置驅動只需要完成如下工作。

l 在模組載入函式中告知input子系統它可以報告的事件。

裝置驅動通過set_bit()告訴input子系統它支援哪些事件,如下所示:

set_bit(EV_KEY, button_dev.evbit);

l 在模組載入函式中註冊輸入裝置。

註冊輸入裝置的函式為:

int input_register_device(struct input_dev *dev);

l 在鍵被按下/擡起、觸控式螢幕被觸控/擡起/移動、滑鼠被移動/單擊/擡起時通過input_ report_xxx()報告發生的事件及對應的鍵值/座標等狀態。

主要的事件型別包括EV_KEY(按鍵事件)、EV_REL(相對值,如游標移動,報告的是相對最後一次位置的偏移)和EV_ABS(絕對值,如觸控式螢幕和操縱桿,它們工作在絕對座標系統)。

用於報告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_report_abs(input_dev, ABS_X, x);  //X座標
input_report_abs(input_dev, ABS_Y, y);   //Y座標
input_report_abs(input_dev, ABS_PRESSURE, pres); //壓力
input_sync(input_dev);  //同步

在模組解除安裝函式中登出輸入裝置。登出輸入裝置的函式為:

void input_unregister_device(struct input_dev *dev);

程式碼清單給出了一個最簡單的使用input介面實現按鍵裝置驅動的範例,它在中斷服務程式中向系統報告按鍵及同步事件。

程式碼清單 最簡單的input裝置驅動

1  /*在按鍵中斷中報告事件*/
2  static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
3  {
4    input_report_key(&button_dev, BTN_1, inb(BUTTON_PORT) &1);
5    input_sync(&button_dev);
6  }
7  
8  static int _ _init button_init(void)
9  {
10   /*申請中斷*/
11   if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL))
12   {
13     printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
14     return  - EBUSY;
15   }
16 
17   button_dev.evbit[0] = BIT(EV_KEY);    //支援EV_KEY事件
18   button_dev.keybit[LONG(BTN_0)] = BIT(BTN_0);
19 
20   input_register_device(&button_dev);   //註冊input裝置
21 }
22 
23 static void _ _exit button_exit(void)
24 {
25   input_unregister_device(&button_dev);   //登出input裝置
26   free_irq(BUTTON_IRQ, button_interrupt); //釋放中斷
27 }