在輸入子系統(tǒng)的設(shè)備驅(qū)動(dòng)中,最重要的數(shù)據(jù)結(jié)構(gòu)是struct input_dev,如下所示。需要完成的大部分工作都是圍繞著它來的,它是驅(qū)動(dòng)的主體。每個(gè)struct input_dev代表一個(gè)輸入設(shè)備。
/* include/linux/input.h */
struct input_dev {
const char *name;//設(shè)備名
const char *phys;
const char *uniq;
struct input_id id;//用于匹配事件處理層handler
unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//用于記錄支持的事件類型的位圖
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//記錄支持的按鍵值的位圖
unsigned long relbit[BITS_TO_LONGS(REL_CNT)];//記錄支持的相對(duì)坐標(biāo)的位圖
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];//記錄支持的絕對(duì)坐標(biāo)的位圖
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];//led
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];//beep
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
unsigned int keycodemax;//支持的按鍵值的個(gè)數(shù)
unsigned int keycodesize;//每個(gè)鍵值的字節(jié)數(shù)
void *keycode;//存儲(chǔ)按鍵值的數(shù)組首地址
int (*setkeycode)(struct input_dev *dev,
unsigned int scancode, unsigned int keycode);//修改鍵值的函數(shù),可選
int (*getkeycode)(struct input_dev *dev,
unsigned int scancode, unsigned int *keycode);//獲取掃描碼的鍵值,可選
struct ff_device *ff;
unsigned int repeat_key;//最近一次按鍵值,用于連擊
struct timer_list timer;//自動(dòng)連擊計(jì)時(shí)器
int sync;//最后一次同步后沒有新的事件置1
int abs[ABS_CNT];//當(dāng)前各個(gè)坐標(biāo)的值
int rep[REP_MAX + 1];//自動(dòng)連擊的參數(shù)
unsigned long key[BITS_TO_LONGS(KEY_CNT)];//反映當(dāng)前按鍵狀態(tài)的位圖
unsigned long led[BITS_TO_LONGS(LED_CNT)];//反映當(dāng)前l(fā)ed狀態(tài)的位圖
unsigned long snd[BITS_TO_LONGS(SND_CNT)];//反映當(dāng)前beep狀態(tài)的位圖
unsigned long sw[BITS_TO_LONGS(SW_CNT)];
/*tp驅(qū)動(dòng)代碼里一般使用input_set_abs_params函數(shù)設(shè)置
函數(shù)參數(shù)從右往左依次代表輸入設(shè)備指針、坐標(biāo)軸、最小值、最大值、分辨率、基準(zhǔn)值。
最后兩個(gè)參數(shù)也可以填為0,代表設(shè)備非常精確并且總能精確的回到中心位置。*/
int absmax[ABS_CNT];//記錄各個(gè)坐標(biāo)的最大值
int absmin[ABS_CNT];//記錄各個(gè)坐標(biāo)的最小值
int absfuzz[ABS_CNT];//記錄各個(gè)坐標(biāo)的分辨率
int absflat[ABS_CNT];//記錄各個(gè)坐標(biāo)的基準(zhǔn)值
int absres[ABS_CNT];
int (*open)(struct input_dev *dev);//打開函數(shù)
void (*close)(struct input_dev *dev);//關(guān)閉函數(shù)
int (*flush)(struct input_dev *dev, struct file *file);//斷開連接時(shí)沖洗數(shù)據(jù)
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);//回調(diào)函數(shù),可選
struct input_handle *grab;
spinlock_t event_lock;
struct mutex mutex;
unsigned int users;
bool going_away;
struct device dev;
struct list_head h_list;//handle鏈表
struct list_head node;//input_dev鏈表
};
struct input_event是事件傳送的載體,輸入子系統(tǒng)的事件都是包裝成struct input_event傳給用戶空間。各個(gè)成員如下所示:
/* include/linux/input.h */
struct input_event {
struct timeval time;//時(shí)間戳
__u16 type;//事件類型
__u16 code;//事件代碼
__s32 value;//事件值,如坐標(biāo)的偏移值
};
struct input_dev注冊(cè)的時(shí)候需要跟匹配的hanlder建立連接,匹配的依據(jù)就是struct input_dev所包含的struct input_id。
/* include/linux/input.h */
struct input_id {
__u16 bustype;//總線類型
__u16 vendor;//生產(chǎn)商編號(hào)
__u16 product;//產(chǎn)品編號(hào)
__u16 version;//版本號(hào)
};
input_handler這個(gè)結(jié)構(gòu)體是事件驅(qū)動(dòng)的主體,每一種處理方式對(duì)應(yīng)一個(gè)handler結(jié)構(gòu)體。注冊(cè)input_handler,其實(shí)就是將
input_hangler加入到input_handler_list當(dāng)中。使用input_register_handler注冊(cè)。
/* include/linux/input.h */
struct input_handler {
//私有數(shù)據(jù)指針
void *private;
//事件處理函數(shù)指針。設(shè)備驅(qū)動(dòng)報(bào)告的事件最終由這個(gè)函數(shù)來處理
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
bool (*match)(struct input_handler *handler, struct input_dev *dev);
//連接handler和input_dev的函數(shù)指針
int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
//斷開連接函數(shù)指針
void (*disconnect)(struct input_handle *handle);
//為給定的handle啟動(dòng)handler函數(shù)指針
void (*start)(struct input_handle *handle);
//文件操作結(jié)構(gòu)體
const struct file_operations *fops;
//這個(gè)handler可以使用的32個(gè)次設(shè)備號(hào)的最小值
int minor;
//此handler的名字
const char *name;
//可以處理的input_device_ids列表
const struct input_device_id *id_table;
//需要被忽略的input_device_ids列表
const struct input_device_id *blacklist;
//用來連接handle的鏈表鏈表節(jié)點(diǎn)。每個(gè)與此handler相關(guān)的handle都放入此鏈表
struct list_head h_list;
//用來放入全局handler鏈表的節(jié)點(diǎn)
struct list_head node;
};
input_handle這個(gè)結(jié)構(gòu)體用來連接input_dev和input_handler。
/* include/linux/input.h */
struct input_handle {
void *private;//私有數(shù)據(jù)指針
int open;//記錄本設(shè)備被打開的次數(shù)
const char *name;//創(chuàng)建此handle的handler所賦予的名字
struct input_dev *dev;//指向附著的input_dev
struct input_handler *handler;//指向創(chuàng)建此handle的handler
struct list_head d_node;//鏈表節(jié)點(diǎn),用來加入附著的input_dev
struct list_head h_node;//鏈表節(jié)點(diǎn),用來加入附著的input_handler
};
input_dev和input_handler匹配過程中用到了input_device_id
/* include/linux/mod_devicetable.h */
struct input_device_id {
kernel_ulong_t flags;//定義需要匹配input_id的哪些域
__u16 bustype;//對(duì)應(yīng)input_id的四個(gè)數(shù)據(jù)域
__u16 vendor;
__u16 product;
__u16 version;
//存儲(chǔ)支持事件的位圖,與input_dev中的同名數(shù)據(jù)成員功能一致
kernel_ulong_t evbit[INPUT_DEVICE_ID_EV_MAX / BITS_PER_LONG + 1];
kernel_ulong_t keybit[INPUT_DEVICE_ID_KEY_MAX / BITS_PER_LONG + 1];
kernel_ulong_t relbit[INPUT_DEVICE_ID_REL_MAX / BITS_PER_LONG + 1];
kernel_ulong_t absbit[INPUT_DEVICE_ID_ABS_MAX / BITS_PER_LONG + 1];
kernel_ulong_t mscbit[INPUT_DEVICE_ID_MSC_MAX / BITS_PER_LONG + 1];
kernel_ulong_t ledbit[INPUT_DEVICE_ID_LED_MAX / BITS_PER_LONG + 1];
kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];
kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];
kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];
kernel_ulong_t driver_info;//指示結(jié)構(gòu)體中是否含有驅(qū)動(dòng)信息
};