国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

linux驅動-Input輸入子系統

發布時間:2015-5-21 08:37    發布者:Fundyqds
關鍵詞: linux , 驅動 , Input子系統
以前,看過國嵌關于input子系統的視頻課程,說實話,我看完后腦子里很亂,給我的印象好像是input子系統驅動是一個全新的驅動架構,疑惑相當多。前幾天在網上,看到有很多人介紹韋東山老師的linux驅動課程很不錯,于是,我就買了第二期的視頻,看了韋老師講解的input子系統視頻課程后,我完全明白了整個input子系統的工作機制。為了方便以后查閱,對input子系統的整體框架總結如下:

典型的輸入設備(如鍵盤、鼠標)的工作機制都是差不多的,都是在設備有動作時,向CPU產生一個中斷,通知它讀取相應的數據。Linux為了方便開發這一類驅動,它實現了這類驅動的通用部分,只留下與設備相關的部分,這樣使得開發這一類驅動更加方便。
在Linux中,Input子系統由三大部分組成,它們是Input子系統核心層、Input子系統事件處理層和Input子系統設備驅動層。在通常情況下,Input子系統核心層和Input子系統事件處理層都已經實現了,而作為驅動開發者,我們僅僅只需要完成Input子系統設備驅動層。
對于一個完整的驅動程序,我們首先需要確定設備的主設備號,次設備號,然后向系統注冊該設備,最后實現file_operations結構體中的函數。在Input子系統中,這些步驟會分布到不同的層中,最后三個層通過一些聯系構成了一個完整的驅動程序。
在input子系統中有三個比較中要的結構體,它們分別是input_handler結構體、input_dev結構體、input_handle結構體。它們的具體代碼如下:
struct input_handler {
void *private; //driver相關數據
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); //input_event函數會調用此函數
int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
void (*disconnect)(struct input_handle *handle);
void (*start)(struct input_handle *handle);
const struct file_operations *fops; //file_operation結構體,會替換input.c里的file_operation結構體
int minor;
const char *name; //input_handler名稱
const struct input_device_id *id_table;
const struct input_device_id *blacklist;
struct list_head        h_list; //與該handler相關的handle
struct list_head        node;
};
struct input_dev {
const char *name;
const char *phys;
const char *uniq;
struct input_id id;
unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
unsigned int keycodemax;
unsigned int keycodesize;
void *keycode;
int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);
int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
struct ff_device *ff;
unsigned int repeat_key;
struct timer_list timer;
int sync;
int abs[ABS_MAX + 1];
int rep[REP_MAX + 1];
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 absmax[ABS_MAX + 1];
int absmin[ABS_MAX + 1];
int absfuzz[ABS_MAX + 1];
int absflat[ABS_MAX + 1];
int absres[ABS_MAX + 1];
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 *grab;
spinlock_t event_lock;
struct mutex mutex;
unsigned int users;
bool going_away;
struct device dev;
struct list_head        h_list;  //與該input_dev相關的handle
struct list_head        node;
};
struct input_handle {
void *private;
int open;
const char *name;
struct input_dev *dev;  //指向input_dev
struct input_handler *handler; //指向input_handler
struct list_head        d_node;
struct list_head        h_node;
};
在Input.c(drivers/input)的input_init函數中,有:
err=register_chrdev(INPUT_MAJOR, "input", &input_fops)
它向系統中注冊了一個主設備號為INPUT_MAJOR(13),名為input的設備。而它的file_operations結構體,如下所示:
static const struct file_operations input_fops = {
   .owner = THIS_MODULE,
   .open = input_open_file,
};
它僅僅實現了open函數,為沒有實現其他函數。其實其他函數會在其open函數中實現。
在input_open_file函數中,會把Input子系統的事件處理層相關結構體handler的file_operations賦值給input_fops,從而完整的實現了file_operations結構體。具體實現的代碼:
new_fops = fops_get(handler->fops)
file->f_op = new_fops;
從這里我們可以看出一個Input子系統的驅動的file_operations結構體是在handler結構體中實現的。
對于input_handler結構體,它是input子系統中事件處理層相關的結構體,對于一個具體的事件處理,需要向事件處理層注冊這樣一個結構體,如在鼠標的事件處理程序mousedev.c的mousedev_init函數中,會調用input_register_handler函數,注冊一個具體的handler。而在input_register_handler函數中,會將handler添加到input_handler_list中,然后在input_dev_list中尋找相匹配的dev。具體代碼:
list_for_each_entry(dev, &input_dev_list, node)
input_attach_handler(dev, handler);
因而,要形成一個完成的驅動,則必須有相應的dev。
對于input_dev結構體,它是input子系統中設備驅動層相關的結構體,對于一個具體的設備,需要向設備驅動層注冊這樣一個結構體,如在鼠標的設備驅動程序usbmouse.c的usb_mouse_probe函數中,會調用input_register_device函數,注冊一個具體的dev。而在input_register_device函數中,會將dev添加到input_dev_list中,然后再input_handler_list尋找相匹配的handler。具體代碼:
list_add_tail(&dev->node, &input_dev_list);
list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler);
在input_attach_handler函數中,會調用input_match_device函數,將input_dev_list中的dev與handler相匹配或將input_handler_list中的handler與dev相匹配,匹配成功后就會調用handler中的connect函數。而在connect函數中,會通過handle結構體將匹配好的handler和dev聯系起來。如mousedev.c中,connect函數中調用了mousedev_create函數,而在mousedev_create函數中,將handle結構中的handler指向匹配好的handler,而dev指向匹配好的dev,然后會調用input_register_handle函數。
mousedev->handle.dev = input_get_device(dev);
mousedev->handle.name = dev_name(&mousedev->dev);
error = input_register_handle(&mousedev->handle);
在 input_register_handle函數中,將input_handle結構體中的d_node和h_node成員分別添加到了匹配好的dev結構體的h_list中和匹配好的handler結構體的h_list中。
struct input_handler *handler = handle->handler;
struct input_dev *dev = handle->dev;
list_add_tail_rcu(&handle->d_node, &dev->h_list);
list_add_tail(&handle->h_node, &handler->h_list);
這樣,Input驅動程序中的設備驅動和事件處理就這樣無縫連接起來了,無論是我們先有了handler還是先有了dev,input子系統都會找了與之匹配的dev或handler,使得三部分之間更加整體化。

本文地址:http://www.qingdxww.cn/thread-149581-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • 基于CEC1712實現的處理器SPI FLASH固件安全彈性方案培訓教程
  • PIC18-Q71系列MCU概述
  • 安靜高效的電機控制——這才是正確的方向!
  • 無線充電基礎知識及應用培訓教程3
  • 貿澤電子(Mouser)專區

相關視頻

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美大片在线欧美大片 | 天堂网在线最新版www | 国产日韩免费 | 天堂网在线最新版官网 | 在线视频一区二区三区三区不卡 | 岛田阳子五十路在线观看 | 国产情侣一区二区 | 在线不卡 | 香蕉国产成版人视频在线观看 | 欧美一级特黄特黄做受 | 亚洲精品在线第一页 | 久久久国产99久久国产久 | ntr中文字幕亚洲综合 | 国产一级黄色大片 | 欧美黄色免费 | 两个人免费在线观看 | 在线国产福利 | 伊人手机视频 | 成人黄色在线播放 | 日本黄大片视频在线播放 | avove在线播放 | 啦啦啦高清影视在线观看视频? | 91精品国产免费久久国语蜜臀 | 中文字幕第10页 | 久久99国产精品成人欧美 | 国产一区亚洲二区 | 国产黄在线免费观看 | 欧美日韩国产高清一区二区三区 | 色综合天天综合网国产人 | 亚洲人成一区二区不卡 | 99视频免费看 | 青青青青草原国产免费 | 国产视频 每日更新 | 国产中字| 99re在线观看| 香港三级日本三级三级人妇99 | 日本一区免费观看 | 黄网页在线观看 | 欧美人在线一区二区三区 | 欧美精品超清在线播放 | 亚洲欧美高清视频 |