久久婷婷香蕉热狠狠综合,精品无码国产自产拍在线观看蜜,寡妇房东在做爰3,中文字幕日本人妻久久久免费,国产成人精品三上悠亚久久

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 > Input子系統剖析

Input子系統(tong)剖析 時間:2018-09-29     ; 來源:未知(zhi)

1.input子(zi)系統框架圖(tu)

input子系統解(jie)決什么(me)問題?

 解決不同input硬件在應用層(ceng)與(yu)驅動層(ceng)之(zhi)間的信息(xi)的傳(chuan)輸;

(1)用戶層(ceng)

各層之間通(tong)信的基(ji)本單位就(jiu)是(shi)事件(jian),任(ren)何一個(ge)輸入設備的動作都可以(yi)抽象成一個(ge)事件(jian)。事件(jian)有三種屬性:類型(type),編碼(code),值(value)。

(2)事件處理層

事件(jian)處理層負(fu)責(ze)與用戶程序打交道,將(jiang)硬(ying)件(jian)驅動層傳來(lai)的事件(jian)報告(gao)給用戶程序。

(3)核心層

核心層是鏈接(jie)設(she)備驅動層與(yu)事件處理層之間的(de)紐帶與(yu)橋梁(liang),向(xiang)下提供驅動層的(de)接(jie)口,向(xiang)上提供事件處理層的(de)接(jie)口。

(4)設備驅(qu)動層

硬(ying)(ying)件(jian)驅(qu)動(dong)(dong)層(ceng)負責操(cao)作(zuo)具體(ti)的(de)硬(ying)(ying)件(jian)設備,這層(ceng)的(de)代碼是針(zhen)對具體(ti)的(de)驅(qu)動(dong)(dong)程序的(de),需要驅(qu)動(dong)(dong)程序的(de)作(zuo)者來(lai)編寫。

 

2.input各層(ceng)的相關數據結構

Input子系統的主(zhu)設備號:13

[1]事件(jian)結構體(ti)

input類設備,在驅(qu)動層(ceng)與應(ying)用(yong)層(ceng)進行標準(zhun)類輸入事件(jian)的(de)傳送驅(qu)動層(ceng)封裝具體(ti)(ti)的(de)事件(jian)結構(gou)體(ti)(ti),從驅(qu)動層(ceng)返回到(dao)應(ying)用(yong)層(ceng),再(zai)在應(ying)用(yong)層(ceng)進行該結構(gou)體(ti)(ti)

struct input_event {

struct timeval time;//具(ju)體的時間點

__u16 type;//輸入事件(jian)的類(lei)型:鼠(shu)標,鍵盤,觸摸屏(ping)

__u16 code;//事(shi)件編碼(ma)值(zhi):鍵(jian)盤(pan)那(nei)個鍵(jian)的(de)編碼(ma),鼠標左右(you)鍵(jian),移動(dong)

__s32 value;//操作值(zhi):按(an)下,抬起,移動多少

};

事件處理器

struct input_handler {

void *private;//私有數據(ju)域

void (*event)(struct input_handle *handle, unsigned int type, unsigned int code,  int value);//事件處理

void (*events)(struct input_handle *handle,//事件順序處理(li)

      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匹配(pei)上執行connect函數

void (*disconnect)(struct input_handle *handle);//分離handler

void (*start)(struct input_handle *handle);

 

bool legacy_minors;

int minor;//能支持的設備的次設備號(hao)

const char *name;//名稱

 

const struct input_device_id *id_table;//驅(qu)動能夠處理的設備表(biao)

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;//添(tian)加至input_handle的鏈表

struct list_head node;//添加至input_handler_list

};

[2]核心層相關

struct input_handle {  

    void *private;   //每(mei)個配對的事(shi)件(jian)處理(li)器都會(hui)分配一個對應的設備結(jie)構,如evdev事(shi)件(jian)處理(li)器的evdev結(jie)構,注意這個結(jie)構與設備驅動層的input_dev不(bu)同(tong),初始化handle時,保存到這里。   

     int open;        //打開(kai)標(biao)志,每個input_handle 打開(kai)后才能操作,這(zhe)個一般通過事件處理器的(de)open方法間接設(she)置   

    const char *name;   

    struct input_dev *dev;  //關聯的input_dev結構(gou)   

    struct input_handler *handler; //關聯的input_handler結(jie)構   

    struct list_head    d_node;  //input_handle通(tong)過(guo)d_node連接(jie)到了input_dev上的(de)h_list鏈表上   

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

};  

[3]input設備結構體

struct input_dev {

const char *name;//設(she)備名

const char *phys;//設備的(de)物理(li)路徑所屬的(de)系統層次(ci)

const char *uniq;//設備的(de)唯一標識代碼

struct input_id id;//設備(bei)ID

struct input_id {//標識設備驅動特征

__u16 bustype;

__u16 vendor;

__u16 product;

__u16 version;

};

 

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

 

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

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

#define EV_KEY 0x01//按鍵事件(jian)

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

#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)];//表示能產生哪些按鍵

unsigned long relbit[BITS_TO_LONGS(REL_CNT)];//表示(shi)能產(chan)生哪些相對位移(yi)

unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];//表(biao)示能產生哪(na)些絕對位移

unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];//表(biao)示能產生哪些按鍵

unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];//表示能產生哪些按鍵

unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];//表(biao)示能(neng)產生哪(na)些(xie)按鍵

unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];//表示能(neng)產生哪些(xie)按鍵

unsigned long swbit[BITS_TO_LONGS(SW_CNT)];//表示能產生哪些按鍵(jian)

 

unsigned int hint_events_per_packet;//每個包產(chan)生的平均事(shi)件數量(liang)

unsigned int keycodemax;//鍵碼表的大小(xiao)

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

void *keycode;//設備鍵碼(ma)

 

int (*setkeycode)(struct input_dev *dev,//設(she)置(zhi)鍵碼

 const struct input_keymap_entry *ke,

 unsigned int *old_keycode);

int (*getkeycode)(struct input_dev *dev,//獲取(qu)鍵碼

 struct input_keymap_entry *ke);

 

struct ff_device *ff;//作用力(li)反饋

 

unsigned int repeat_key;//重復(fu)按鍵

struct timer_list timer;//重復(fu)按鍵(jian)的時間點

 

int rep[REP_CNT];//重(zhong)復按(an)鍵的參(can)數

 

struct input_mt *mt;//多點觸控狀態

 

struct input_absinfo *absinfo;/軸線分辨率

//設備當前狀態的(de)反饋(kui)

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

//開,關,刷(shua)新,事件處(chu)理

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連接(jie)成鏈表

 

unsigned int num_vals;

unsigned int max_vals;

struct input_value *vals;

 

bool devres_managed;

};

 

3.Input子系(xi)統的各個(ge)函數接口

(1)事(shi)件處理層相關

int input_register_handler(struct input_handler *handler);

功能:注冊(ce)input_handler

參數(shu):struct input_handler的結構體指(zhi)針(zhen)

返回值:成(cheng)功 :0    失敗:錯誤碼的絕對值

 

void input_unregister_handler(struct input_handler *handler);

功能:注銷input_handler

參數:struct input_handler的結(jie)構體指針

返回值:無

 

(2)核心層相關

int input_register_handle(struct input_handle *handle);

功能:注冊input_handle

參數(shu):struct input_handle的結構體(ti)指針

返回值:成功 :0    失敗:錯誤碼(ma)的絕對(dui)值

 

void input_unregister_handle(struct input_handle *handle)

功能:注銷input_handle

參數(shu):struct input_handle的結構體指(zhi)針

返回值:無

 

(3)設(she)備驅動層相關

struct input_dev *input_allocate_device(void)

功能:申請input_device

參數:  struct input_device結構體指針

返回值:成功(gong):struct input_dev結構體(ti)指針

失(shi)敗:NULL

void input_free_device(struct input_dev *dev)

功能:釋(shi)放(fang)input_device

參數:  struct input_device結構(gou)體指(zhi)針

返回值:無

 

int input_register_device(struct input_dev *dev);

功能:注冊input_device

參數(shu):struct input_device的結構體指針

返回值:成功 :0    失敗:錯誤碼的絕對值

 

void input_unregister_device(struct input_dev *dev)

功能:注銷input_device

參數:struct input_device的結(jie)構(gou)體指針

返回值:無

 

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

功能:上報(bao)事件

參數:struct input_dev *dev:input設備(bei)結構(gou)體指針(zhen)

Type:事件(jian)類型(xing)

Code:事件代碼

Value:事件值(zhi)

返回值:無

 

static inline void input_sync(struct input_dev *dev)

功能:同(tong)步事件(jian)

參(can)數:struct input_dev *dev:input設備結構體指針

返回值:無

 

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

功能:設(she)置(zhi)事(shi)件類型或者具體事(shi)件

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

 volatile unsigned long *addr:事件(jian)類型(xing)或(huo)具體(ti)事件(jian)

返回值:無

 

4.input子系統的源碼(ma)分析(xi)

參考:driver/input/evdev.c

evdev_init

input_register_handler

INIT_LIST_HEAD(&handler->h_list);//初始(shi)化input_handler中的(de)h_list鏈表(biao)

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相匹配,則執行   //該函數

id = input_match_device(handler, dev);//比較struct input_handler中struct  //input_device_id中的flags進行設備屬性 //信息判斷

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

“if((id->bit[i]&dev->bit[i])!=id->bit[i])”,這句話(hua)意(yi)味著id支持(chi)的(de)(de)事(shi)(shi)件(jian)種(zhong)類是dev支持(chi)的(de)(de)事(shi)(shi)件(jian)的(de)(de)子集就(jiu)算匹配了。如果某個(ge)handler的(de)(de)id除了id->driver_info之(zhi)外的(de)(de)域都為0,那么此(ci)handler可(ke)以和(he)任意(yi)dev匹配。實(shi)際上(shang)<內核>/driver/input/evdev.c中就(jiu)是這么初(chu)始化id的(de)(de)。現在總結一下input_dev注(zhu)冊(ce)的(de)(de)過(guo)程:一個(ge)input_dev注(zhu)冊(ce)的(de)(de)過(guo)程主要是在將(jiang)自己加(jia)入input_dev_list,然后(hou)在input_handler_list中找到(dao)id和(he)事(shi)(shi)件(jian)種(zhong)類相(xiang)匹配的(de)(de)handler并與(yu)之(zhi)建(jian)(jian)立連接的(de)(de)過(guo)程。 input_dev產生的(de)(de)事(shi)(shi)件(jian)會分(fen)發給所有建(jian)(jian)立連接的(de)(de)handler。下面繼續分(fen)析事(shi)(shi)件(jian)的(de)(de)傳遞

 

 

error = handler->connect(handler, dev, id);//當匹配完成之后自動執行   //input_handler中的connect函數進行   //匹配連接(jie)

//查找具體(ti)的(de)connect的(de)函(han)數(shu)實現

static int evdev_connect(struct input_handler *handler, struct input_dev  *dev,const struct input_device_id *id)

 init_waitqueue_head(&evdev->wait);//初始化等待(dai)隊列(lie)頭

error = input_register_handle(&evdev->handle);//注冊(ce)input_handle

//將input_handle的d_node成(cheng)員(yuan)掛接到(dao)input_dev->h_list

 list_add_tail_rcu(&handle->d_node,&dev->h_list);

//將input_handle的h_node成員掛(gua)接(jie)到input_handler->h_list

list_add_tail_rcu(&handle->h_node, &amp;handler->h_list);

cdev_init(&evdev->cdev, &evdev_fops);//由(you)此(ci)可(ke)知,在(zai)connect中主要

實現了字符設(she)備及相(xiang)關操作方法集合(he)的綁(bang)定;

該input子系(xi)統相關的操(cao)作方法如下:

 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子系統事件(jian)上報的函數調用:

evdev_read

static ssize_t evdev_read(struct file *file, char __user *buffer,size_t count, loff_t *ppos)

error = wait_event_interruptible(evdev-&gt;wait,client->packet_head != client->tail ||

!evdev->exist || client->revoked);//阻塞時,將不滿 //足條件(jian)的事件(jian)添(tian)加至等待隊列(lie),全局搜索evdev->wait

wake_up_interruptible(&evdev->wait);//喚醒等(deng)待隊(dui)列,在(zai)evdev_pass_values中(zhong)被調

evdev_events();//evdev_pass_values被evdev_events調用

evdev_event();//evdev_events被(bei)evdev_event調用

綜上得:事件終(zhong)由input_handler中的event上報。

 

具體(ti)的evdev_events();的上報事件的實現:

evdev_events

evdev_pass_values

__pass_event(client, &event);

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

//如果事(shi)件類型是同步且上報,則觸發異步通知

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

client->packet_head = client->head;

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

}

 此時查找evdev_handler->evdev_connect經查看得知,connect主要實現了struct event的(de)結構(gou)體填充和(he)一個字符設備驅動的(de)程序(xu)編寫;

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

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

綜上(shang)所(suo)述(shu):事件(jian)通過input_event來進行傳遞;

Input_event上(shang)報流(liu)程分析:

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子(zi)系(xi)統的歸納總結

上一篇:ARM異常處理

下一篇:關于scanf( )函數使用

熱點文章推薦
華清(qing)學員就業(ye)榜單
高薪(xin)學(xue)員經驗分享
熱(re)點新聞推薦
前臺專線:010-82525158 企業培訓洽談專(zhuan)線:010-82525379 院校合作(zuo)洽談專(zhuan)線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,,京公海網安備11010802025203號

回到頂部