1.input子系統(tǒng)框架圖
input子系統(tǒng)解決什么問題?
解決不同input硬件在應用層與驅(qū)動層之間的信息的傳輸;
(1)用戶層
各層之間通信的基本單位就是事件,任何一個輸入設備的動作都可以抽象成一個事件。事件有三種屬性:類型(type),編碼(code),值(value)。
(2)事件處理層
事件處理層負責與用戶程序打交道,將硬件驅(qū)動層傳來的事件報告給用戶程序。
(3)核心層
核心層是鏈接設備驅(qū)動層與事件處理層之間的紐帶與橋梁,向下提供驅(qū)動層的接口,向上提供事件處理層的接口。
(4)設備驅(qū)動層
硬件驅(qū)動層負責操作具體的硬件設備,這層的代碼是針對具體的驅(qū)動程序的,需要驅(qū)動程序的作者來編寫。
2.input各層的相關數(shù)據(jù)結構
Input子系統(tǒng)的主設備號:13
[1]事件結構體
input類設備,在驅(qū)動層與應用層進行標準類輸入事件的傳送驅(qū)動層封裝具體的事件結構體,從驅(qū)動層返回到應用層,再在應用層進行該結構體
struct input_event {
struct timeval time;//具體的時間點
__u16 type;//輸入事件的類型:鼠標,鍵盤,觸摸屏
__u16 code;//事件編碼值:鍵盤那個鍵的編碼,鼠標左右鍵,移動
__s32 value;//操作值:按下,抬起,移動多少
};
事件處理器
struct input_handler {
void *private;//私有數(shù)據(jù)域
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);//事件處理
void (*events)(struct input_handle *handle,//事件順序處理
const struct input_value *vals, unsigned int count);
bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);//過濾正常事件
bool (*match)(struct input_handler *handler, struct input_dev *dev);//匹配dev與 //handler
int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);//dev與handler匹配上執(zhí)行connect函數(shù)
void (*disconnect)(struct input_handle *handle);//分離handler
void (*start)(struct input_handle *handle);
bool legacy_minors;
int minor;//能支持的設備的次設備號
const char *name;//名稱
const struct input_device_id *id_table;//驅(qū)動能夠處理的設備表
struct input_device_id {
kernel_ulong_t flags;
__u16 bustype;
__u16 vendor;
__u16 product;
__u16 version;
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;
};
struct list_head h_list;//添加至input_handle的鏈表
struct list_head node;//添加至input_handler_list
};
[2]核心層相關
struct input_handle {
void *private; //每個配對的事件處理器都會分配一個對應的設備結構,如evdev事件處理器的evdev結構,注意這個結構與設備驅(qū)動層的input_dev不同,初始化handle時,保存到這里。
int open; //打開標志,每個input_handle 打開后才能操作,這個一般通過事件處理器的open方法間接設置
const char *name;
struct input_dev *dev; //關聯(lián)的input_dev結構
struct input_handler *handler; //關聯(lián)的input_handler結構
struct list_head d_node; //input_handle通過d_node連接到了input_dev上的h_list鏈表上
struct list_head h_node; //input_handle通過h_node連接到了input_handler的h_list鏈表上
};
[3]input設備結構體
struct input_dev {
const char *name;//設備名
const char *phys;//設備的物理路徑所屬的系統(tǒng)層次
const char *uniq;//設備的唯一標識代碼
struct input_id id;//設備ID
struct input_id {//標識設備驅(qū)動特征
__u16 bustype;
__u16 vendor;
__u16 product;
__u16 version;
};
unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];//設備的位圖的特殊
unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//表示能產(chǎn)生的事件類型
#define EV_SYN 0x00//同步類事件
#define EV_KEY 0x01//按鍵事件
#define EV_REL 0x02//相對位移事件
#define EV_ABS 0x03//絕對位移事件
#define EV_MSC 0x04
#define EV_SW 0x05
#define EV_LED 0x11
#define EV_SND 0x12
#define EV_REP 0x14
#define EV_FF 0x15
#define EV_PWR 0x16
#define EV_FF_STATUS 0x17
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//表示能產(chǎn)生哪些按鍵
unsigned long relbit[BITS_TO_LONGS(REL_CNT)];//表示能產(chǎn)生哪些相對位移
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];//表示能產(chǎn)生哪些絕對位移
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];//表示能產(chǎn)生哪些按鍵
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];//表示能產(chǎn)生哪些按鍵
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];//表示能產(chǎn)生哪些按鍵
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];//表示能產(chǎn)生哪些按鍵
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];//表示能產(chǎn)生哪些按鍵
unsigned int hint_events_per_packet;//每個包產(chǎn)生的平均事件數(shù)量
unsigned int keycodemax;//鍵碼表的大小
unsigned int keycodesize;//鍵碼表成員的大小
void *keycode;//設備鍵碼
int (*setkeycode)(struct input_dev *dev,//設置鍵碼
const struct input_keymap_entry *ke,
unsigned int *old_keycode);
int (*getkeycode)(struct input_dev *dev,//獲取鍵碼
struct input_keymap_entry *ke);
struct ff_device *ff;//作用力反饋
unsigned int repeat_key;//重復按鍵
struct timer_list timer;//重復按鍵的時間點
int rep[REP_CNT];//重復按鍵的參數(shù)
struct input_mt *mt;//多點觸控狀態(tài)
struct input_absinfo *absinfo;/軸線分辨率
//設備當前狀態(tài)的反饋
unsigned long key[BITS_TO_LONGS(KEY_CNT)];
unsigned long led[BITS_TO_LONGS(LED_CNT)];
unsigned long snd[BITS_TO_LONGS(SND_CNT)];
unsigned long sw[BITS_TO_LONGS(SW_CNT)];
//開,關,刷新,事件處理
int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
int (*flush)(struct input_dev *dev, struct file *file);
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
//事件處理層結構體
struct input_handle __rcu *grab;
spinlock_t event_lock;
struct mutex mutex;
unsigned int users;
bool going_away;
struct device dev;
struct list_head h_list;//連接input_handle
struct list_head node;//將input_dev連接成鏈表
unsigned int num_vals;
unsigned int max_vals;
struct input_value *vals;
bool devres_managed;
};
3.Input子系統(tǒng)的各個函數(shù)接口
(1)事件處理層相關
int input_register_handler(struct input_handler *handler);
功能:注冊input_handler
參數(shù):struct input_handler的結構體指針
返回值:成功 :0 失敗:錯誤碼的絕對值
void input_unregister_handler(struct input_handler *handler);
功能:注銷input_handler
參數(shù):struct input_handler的結構體指針
返回值:無
(2)核心層相關
int input_register_handle(struct input_handle *handle);
功能:注冊input_handle
參數(shù):struct input_handle的結構體指針
返回值:成功 :0 失敗:錯誤碼的絕對值
void input_unregister_handle(struct input_handle *handle)
功能:注銷input_handle
參數(shù):struct input_handle的結構體指針
返回值:無
(3)設備驅(qū)動層相關
struct input_dev *input_allocate_device(void)
功能:申請input_device
參數(shù): struct input_device結構體指針
返回值:成功:struct input_dev結構體指針
失敗:NULL
void input_free_device(struct input_dev *dev)
功能:釋放input_device
參數(shù): struct input_device結構體指針
返回值:無
int input_register_device(struct input_dev *dev);
功能:注冊input_device
參數(shù):struct input_device的結構體指針
返回值:成功 :0 失敗:錯誤碼的絕對值
void input_unregister_device(struct input_dev *dev)
功能:注銷input_device
參數(shù):struct input_device的結構體指針
返回值:無
void input_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)
功能:上報事件
參數(shù):struct input_dev *dev:input設備結構體指針
Type:事件類型
Code:事件代碼
Value:事件值
返回值:無
static inline void input_sync(struct input_dev *dev)
功能:同步事件
參數(shù):struct input_dev *dev:input設備結構體指針
返回值:無
static inline void set_bit(int nr, volatile unsigned long *addr)
功能:設置事件類型或者具體事件
參數(shù):int nr:具體的事件類型或者具體事件
volatile unsigned long *addr:事件類型或具體事件
返回值:無
4.input子系統(tǒng)的源碼分析
參考:driver/input/evdev.c
evdev_init
input_register_handler
INIT_LIST_HEAD(&handler->h_list);//初始化input_handler中的h_list鏈表
list_add_tail(&handler->node, &input_handler_list);//將input_handler加入 //input_handler_list
list_for_each_entry(dev, &input_dev_list, node)//從input_dev_list鏈表中查找
//input_dev
input_attach_handler(dev, handler);//若input_dev與input_handler相匹配,則執(zhí)行 //該函數(shù)
id = input_match_device(handler, dev);//比較struct input_handler中struct //input_device_id中的flags進行設備屬性 //信息判斷
根據(jù)id->flag檢查id是否匹配。id->flag記錄需要匹配哪些域。
“if((id->bit[i]&dev->bit[i])!=id->bit[i])”,這句話意味著id支持的事件種類是dev支持的事件的子集就算匹配了。如果某個handler的id除了id->driver_info之外的域都為0,那么此handler可以和任意dev匹配。實際上<內(nèi)核>/driver/input/evdev.c中就是這么初始化id的。現(xiàn)在總結一下input_dev注冊的過程:一個input_dev注冊的過程主要是在將自己加入input_dev_list,然后在input_handler_list中找到id和事件種類相匹配的handler并與之建立連接的過程。 input_dev產(chǎn)生的事件會分發(fā)給所有建立連接的handler。下面繼續(xù)分析事件的傳遞
error = handler->connect(handler, dev, id);//當匹配完成之后自動執(zhí)行 //input_handler中的connect函數(shù)進行 //匹配連接
//查找具體的connect的函數(shù)實現(xiàn)
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,const struct input_device_id *id)
init_waitqueue_head(&evdev->wait);//初始化等待隊列頭
error = input_register_handle(&evdev->handle);//注冊input_handle
//將input_handle的d_node成員掛接到input_dev->h_list
list_add_tail_rcu(&handle->d_node,&dev->h_list);
//將input_handle的h_node成員掛接到input_handler->h_list
list_add_tail_rcu(&handle->h_node, &handler->h_list);
cdev_init(&evdev->cdev, &evdev_fops);//由此可知,在connect中主要
實現(xiàn)了字符設備及相關操作方法集合的綁定;
該input子系統(tǒng)相關的操作方法如下:
static const struct file_operations evdev_fops = {
.owner= THIS_MODULE,
.read= evdev_read,
.write= evdev_write,
.poll = evdev_poll,
.open= evdev_open,
.release = evdev_release,
.unlocked_ioctl = evdev_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = evdev_ioctl_compat,
#endif
.fasync= evdev_fasync,
.flush= evdev_flush,
.llseek= no_llseek,
};
分析input子系統(tǒng)事件上報的函數(shù)調(diào)用:
evdev_read
static ssize_t evdev_read(struct file *file, char __user *buffer,size_t count, loff_t *ppos)
error = wait_event_interruptible(evdev->wait,client->packet_head != client->tail ||
!evdev->exist || client->revoked);//阻塞時,將不滿 //足條件的事件添加至等待隊列,全局搜索evdev->wait
wake_up_interruptible(&evdev->wait);//喚醒等待隊列,在evdev_pass_values中被調(diào)
evdev_events();//evdev_pass_values被evdev_events調(diào)用
evdev_event();//evdev_events被evdev_event調(diào)用
綜上得:事件終由input_handler中的event上報。
具體的evdev_events();的上報事件的實現(xiàn):
evdev_events
evdev_pass_values
__pass_event(client, &event);
client->buffer[client->head++] = *event;//將input_event存放至client的 //input_event數(shù)組中;
//如果事件類型是同步且上報,則觸發(fā)異步通知
if (event->type == EV_SYN && event->code == SYN_REPORT) {
client->packet_head = client->head;
kill_fasync(&client->fasync, SIGIO, POLL_IN);//觸發(fā)異步通知
}
此時查找evdev_handler->evdev_connect經(jīng)查看得知,connect主要實現(xiàn)了struct event的結構體填充和一個字符設備驅(qū)動的程序編寫;
cdev_init(&evdev->cdev, &evdev_fops);//跳入evdev_fops
evdev_fops:
----->evdev_fasync
返回fasync_helper(fd, file, on, &client->fasync);
----->evdev_read
evdev_fetch_next_event(client, &event)
have_event = client->packet_head != client->tail;
//將client中的input_event賦值給event
*event = client->buffer[client->tail++];
input_event_to_user(buffer + read, &event);//給用戶層上報事件
if (copy_to_user(buffer, &compat_event,sizeof(struct input_event_compat)));
綜上所述:事件通過input_event來進行傳遞;
Input_event上報流程分析:
input_event
input_pass_values(dev, dev->vals, dev->num_vals);
input_to_handler(handle, vals, count);
handler->event(handle, v->type, v->code, v->value);
5.Input子系統(tǒng)的歸納總結