歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux設備驅動工程師之路——input子系統

一、input子系統系統框架

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子系統解析》

Copyright © Linux教程網 All Rights Reserved