Linux內核實現了一套input子系統,很多輸入設備,比如說按鍵、鍵盤、鼠標、觸摸屏等等都可以利用input子系統提供的接口來編寫驅動,這樣可以幫驅動編寫者減少大量工作量。因為input子系統會幫驅動完成open,read,close等一些列的設備方法。驅動編寫者只需要在按鍵按下或者鼠標點擊事件時想input子系統上層的event hander報告相應的事件信息就可以了。下圖是input子系統的框架。最下層是輸入設備的驅動層,也就是我們需要編寫的,在最底層上面的一層是input子系統的core層。由input.c文件實現。再上面一層是對應設備的handler層,每種設備對應一種handler。handler會在/dev/input文件夾下創建對應的文件,並對底層報告上來的時間進行相應的處理,並且完成一些相應的文件操作等。
二、Input driver編寫要點
1、分配、注冊、注銷input設備
struct input_dev*input_allocate_device(void)
intinput_register_device(struct input_dev *dev)
voidinput_unregister_device(struct input_dev *dev)
2、設置input設備支持的事件類型、事件碼、事件值的范圍、input_id等信息
參見usb鍵盤驅動:usbkbd.c
usb_to_input_id(dev,&input_dev->id);//設置bustype、vendo、product等
input_dev->evbit[0] =BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);//支持的事件類型
input_dev->ledbit[0] =BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) |BIT(LED_KANA);// EV_LED事件支持的事件碼
for (i = 0; i < 255; i++)
set_bit(usb_kbd_keycode[i],input_dev->keybit); //EV_KEY事件支持的事件碼
include/linux/input.h中定義了支持的類型(下面列出的是2.6.22內核的情況)
#define EV_SYN 0x00
#defineEV_KEY 0x01
#defineEV_REL 0x02
#defineEV_ABS 0x03
#defineEV_MSC 0x04
#defineEV_SW 0x05
#defineEV_LED 0x11
#defineEV_SND 0x12
#defineEV_REP 0x14
#define EV_FF 0x15
#defineEV_PWR 0x16
#defineEV_FF_STATUS 0x17
#defineEV_MAX 0x1f
一個設備可以支持一個或多個事件類型。每個事件類型下面還需要設置具體的觸發事件碼。比如:EV_KEY事件,需要定義其支持哪些按鍵事件碼。
3、如果需要,設置input設備的打開、關閉、寫入數據時的處理方法
參見usb鍵盤驅動:usbkbd.c
input_dev->open= usb_kbd_open;
input_dev->close =usb_kbd_close;
input_dev->event =usb_kbd_event;
4、在發生輸入事件時,向子系統報告事件
用於報告EV_KEY、EV_REL、EV_ABS等事件的函數有:
void input_report_key(structinput_dev *dev, unsigned int code, int value)
void input_report_rel(structinput_dev *dev, unsigned int code, int value)
void input_report_abs(structinput_dev *dev, unsigned int code, int value)
如果你覺得麻煩,你也可以只記住1個函數(因為上述函數都是通過它實現的)
voidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, intvalue)
報告時間之後需要調用
input_sync(input_dev),它告知事件的接收者:驅動已經發生了一個完整的報告。
參考文章:劉洪濤《linux內核input子系統解析》