色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区

當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > Input子系統(tǒng)剖析

Input子系統(tǒng)剖析 時(shí)間:2018-09-29      來(lái)源:未知

1.input子系統(tǒng)框架圖

input子系統(tǒng)解決什么問(wèn)題?

解決不同input硬件在應(yīng)用層與驅(qū)動(dòng)層之間的信息的傳輸;

(1)用戶層

各層之間通信的基本單位就是事件,任何一個(gè)輸入設(shè)備的動(dòng)作都可以抽象成一個(gè)事件。事件有三種屬性:類型(type),編碼(code),值(value)。

(2)事件處理層

事件處理層負(fù)責(zé)與用戶程序打交道,將硬件驅(qū)動(dòng)層傳來(lái)的事件報(bào)告給用戶程序。

(3)核心層

核心層是鏈接設(shè)備驅(qū)動(dòng)層與事件處理層之間的紐帶與橋梁,向下提供驅(qū)動(dòng)層的接口,向上提供事件處理層的接口。

(4)設(shè)備驅(qū)動(dòng)層

硬件驅(qū)動(dòng)層負(fù)責(zé)操作具體的硬件設(shè)備,這層的代碼是針對(duì)具體的驅(qū)動(dòng)程序的,需要驅(qū)動(dòng)程序的作者來(lái)編寫。

 

2.input各層的相關(guān)數(shù)據(jù)結(jié)構(gòu)

Input子系統(tǒng)的主設(shè)備號(hào):13

[1]事件結(jié)構(gòu)體

input類設(shè)備,在驅(qū)動(dòng)層與應(yīng)用層進(jìn)行標(biāo)準(zhǔn)類輸入事件的傳送驅(qū)動(dòng)層封裝具體的事件結(jié)構(gòu)體,從驅(qū)動(dòng)層返回到應(yīng)用層,再在應(yīng)用層進(jìn)行該結(jié)構(gòu)體

struct input_event {

struct timeval time;//具體的時(shí)間點(diǎn)

__u16 type;//輸入事件的類型:鼠標(biāo),鍵盤,觸摸屏

__u16 code;//事件編碼值:鍵盤那個(gè)鍵的編碼,鼠標(biāo)左右鍵,移動(dòng)

__s32 value;//操作值:按下,抬起,移動(dòng)多少

};

事件處理器

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);//過(guò)濾正常事件

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;//能支持的設(shè)備的次設(shè)備號(hào)

const char *name;//名稱

 

const struct input_device_id *id_table;//驅(qū)動(dòng)能夠處理的設(shè)備表

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]核心層相關(guān)

struct input_handle {  

    void *private;   //每個(gè)配對(duì)的事件處理器都會(huì)分配一個(gè)對(duì)應(yīng)的設(shè)備結(jié)構(gòu),如evdev事件處理器的evdev結(jié)構(gòu),注意這個(gè)結(jié)構(gòu)與設(shè)備驅(qū)動(dòng)層的input_dev不同,初始化handle時(shí),保存到這里。   

    int open;        //打開標(biāo)志,每個(gè)input_handle 打開后才能操作,這個(gè)一般通過(guò)事件處理器的open方法間接設(shè)置   

    const char *name;   

    struct input_dev *dev;  //關(guān)聯(lián)的input_dev結(jié)構(gòu)   

    struct input_handler *handler; //關(guān)聯(lián)的input_handler結(jié)構(gòu)   

    struct list_head    d_node;  //input_handle通過(guò)d_node連接到了input_dev上的h_list鏈表上   

    struct list_head    h_node;  //input_handle通過(guò)h_node連接到了input_handler的h_list鏈表上   

};  

[3]input設(shè)備結(jié)構(gòu)體

struct input_dev {

const char *name;//設(shè)備名

const char *phys;//設(shè)備的物理路徑所屬的系統(tǒng)層次

const char *uniq;//設(shè)備的唯一標(biāo)識(shí)代碼

struct input_id id;//設(shè)備ID

struct input_id {//標(biāo)識(shí)設(shè)備驅(qū)動(dòng)特征

__u16 bustype;

__u16 vendor;

__u16 product;

__u16 version;

};

 

unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];//設(shè)備的位圖的特殊

 

unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//表示能產(chǎn)生的事件類型

#define EV_SYN 0x00//同步類事件

#define EV_KEY 0x01//按鍵事件

#define EV_REL 0x02//相對(duì)位移事件

#define EV_ABS 0x03//絕對(duì)位移事件

#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)生哪些相對(duì)位移

unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];//表示能產(chǎn)生哪些絕對(duì)位移

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;//每個(gè)包產(chǎn)生的平均事件數(shù)量

unsigned int keycodemax;//鍵碼表的大小

unsigned int keycodesize;//鍵碼表成員的大小

void *keycode;//設(shè)備鍵碼

 

int (*setkeycode)(struct input_dev *dev,//設(shè)置鍵碼

 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;//重復(fù)按鍵

struct timer_list timer;//重復(fù)按鍵的時(shí)間點(diǎn)

 

int rep[REP_CNT];//重復(fù)按鍵的參數(shù)

 

struct input_mt *mt;//多點(diǎn)觸控狀態(tài)

 

struct input_absinfo *absinfo;/軸線分辨率

//設(shè)備當(dāng)前狀態(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)];

//開,關(guān),刷新,事件處理

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);

//事件處理層結(jié)構(gòu)體

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)的各個(gè)函數(shù)接口

(1)事件處理層相關(guān)

int input_register_handler(struct input_handler *handler);

功能:注冊(cè)input_handler

參數(shù):struct input_handler的結(jié)構(gòu)體指針

返回值:成功 :0    失敗:錯(cuò)誤碼的絕對(duì)值

 

void input_unregister_handler(struct input_handler *handler);

功能:注銷input_handler

參數(shù):struct input_handler的結(jié)構(gòu)體指針

返回值:無(wú)

 

(2)核心層相關(guān)

int input_register_handle(struct input_handle *handle);

功能:注冊(cè)input_handle

參數(shù):struct input_handle的結(jié)構(gòu)體指針

返回值:成功 :0    失敗:錯(cuò)誤碼的絕對(duì)值

 

void input_unregister_handle(struct input_handle *handle)

功能:注銷input_handle

參數(shù):struct input_handle的結(jié)構(gòu)體指針

返回值:無(wú)

 

(3)設(shè)備驅(qū)動(dòng)層相關(guān)

struct input_dev *input_allocate_device(void)

功能:申請(qǐng)input_device

參數(shù):  struct input_device結(jié)構(gòu)體指針

返回值:成功:struct input_dev結(jié)構(gòu)體指針

失敗:NULL

void input_free_device(struct input_dev *dev)

功能:釋放input_device

參數(shù):  struct input_device結(jié)構(gòu)體指針

返回值:無(wú)

 

int input_register_device(struct input_dev *dev);

功能:注冊(cè)input_device

參數(shù):struct input_device的結(jié)構(gòu)體指針

返回值:成功 :0    失敗:錯(cuò)誤碼的絕對(duì)值

 

void input_unregister_device(struct input_dev *dev)

功能:注銷input_device

參數(shù):struct input_device的結(jié)構(gòu)體指針

返回值:無(wú)

 

void input_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)

功能:上報(bào)事件

參數(shù):struct input_dev *dev:input設(shè)備結(jié)構(gòu)體指針

Type:事件類型

Code:事件代碼

Value:事件值

返回值:無(wú)

 

static inline void input_sync(struct input_dev *dev)

功能:同步事件

參數(shù):struct input_dev *dev:input設(shè)備結(jié)構(gòu)體指針

返回值:無(wú)

 

static inline void set_bit(int nr, volatile unsigned long *addr)

功能:設(shè)置事件類型或者具體事件

參數(shù):int nr:具體的事件類型或者具體事件

 volatile unsigned long *addr:事件類型或具體事件

返回值:無(wú)

 

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ìn)行設(shè)備屬性 //信息判斷

根據(jù)id->flag檢查id是否匹配。id->flag記錄需要匹配哪些域。

“if((id->bit[i]&dev->bit[i])!=id->bit[i])”,這句話意味著id支持的事件種類是dev支持的事件的子集就算匹配了。如果某個(gè)handler的id除了id->driver_info之外的域都為0,那么此handler可以和任意dev匹配。實(shí)際上<內(nèi)核>/driver/input/evdev.c中就是這么初始化id的。現(xiàn)在總結(jié)一下input_dev注冊(cè)的過(guò)程:一個(gè)input_dev注冊(cè)的過(guò)程主要是在將自己加入input_dev_list,然后在input_handler_list中找到id和事件種類相匹配的handler并與之建立連接的過(guò)程。 input_dev產(chǎn)生的事件會(huì)分發(fā)給所有建立連接的handler。下面繼續(xù)分析事件的傳遞

 

 

error = handler->connect(handler, dev, id);//當(dāng)匹配完成之后自動(dòng)執(zhí)行   //input_handler中的connect函數(shù)進(jìn)行   //匹配連接

//查找具體的connect的函數(shù)實(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);//初始化等待隊(duì)列頭

error = input_register_handle(&evdev->handle);//注冊(cè)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中主要

實(shí)現(xiàn)了字符設(shè)備及相關(guān)操作方法集合的綁定;

該input子系統(tǒng)相關(guān)的操作方法如下:

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)事件上報(bào)的函數(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);//阻塞時(shí),將不滿 //足條件的事件添加至等待隊(duì)列,全局搜索evdev->wait

wake_up_interruptible(&evdev->wait);//喚醒等待隊(duì)列,在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上報(bào)。

 

具體的evdev_events();的上報(bào)事件的實(shí)現(xiàn):

evdev_events

evdev_pass_values

__pass_event(client, &event);

client->buffer[client->head++] = *event;//將input_event存放至client的  //input_event數(shù)組中;

//如果事件類型是同步且上報(bào),則觸發(fā)異步通知

if (event->type == EV_SYN && event->code == SYN_REPORT) {

client->packet_head = client->head;

kill_fasync(&client->fasync, SIGIO, POLL_IN);//觸發(fā)異步通知

}

此時(shí)查找evdev_handler->evdev_connect經(jīng)查看得知,connect主要實(shí)現(xiàn)了struct event的結(jié)構(gòu)體填充和一個(gè)字符設(shè)備驅(qū)動(dòng)的程序編寫;

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);//給用戶層上報(bào)事件

if (copy_to_user(buffer, &compat_event,sizeof(struct  input_event_compat)));

綜上所述:事件通過(guò)input_event來(lái)進(jìn)行傳遞;

Input_event上報(bào)流程分析:

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)的歸納總結(jié)

上一篇:ARM異常處理

下一篇:關(guān)于scanf( )函數(shù)使用

熱點(diǎn)文章推薦
華清學(xué)員就業(yè)榜單
高薪學(xué)員經(jīng)驗(yàn)分享
熱點(diǎn)新聞推薦
前臺(tái)專線:010-82525158 企業(yè)培訓(xùn)洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠(yuǎn)見科技集團(tuán)有限公司 版權(quán)所有 ,京ICP備16055225號(hào)-5京公海網(wǎng)安備11010802025203號(hào)

回到頂部

色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区
主站蜘蛛池模板: 亚洲男女性事视频| 日韩亚洲欧美中文高清在线| 亚洲成人av中文字幕| 亚洲一区二区三区在线视频 | 国产精品91视频| 国产成人中文字幕| 国产精品视频精品| 成人在线播放av| 日韩理论片久久| 一区二区欧美亚洲| 美女视频黄免费的亚洲男人天堂| 精品久久久久久国产| 国模视频一区二区| 日韩av免费网站| 亚洲sss综合天堂久久| 亚洲欧美国产一区二区三区| 色偷偷噜噜噜亚洲男人的天堂| 米奇精品一区二区三区在线观看| 久久免费国产视频| 国产精品久久久久久久7电影| 亚洲精品999| 久久久精品在线| 韩国19禁主播vip福利视频| 国产精品444| 亚洲精品国产精品国产自| 中文字幕久久久| 欧美俄罗斯性视频| 国产精品视频区1| 亚洲美女中文字幕| 欧美日韩国产成人在线观看| 2024亚洲男人天堂| 亚洲黄色在线观看| 欧美成人精品在线| 久久久久久亚洲| 成人羞羞国产免费| 上原亚衣av一区二区三区| 国模精品视频一区二区| 国产伊人精品在线| 日韩中文字幕精品视频| 97香蕉超级碰碰久久免费软件| 91久久久久久久久久|