input輸入子系統分析1

2021-06-18 06:54:16 字數 4721 閱讀 9918

input_register_handler(struct input_handler *handler)

/* 1:

* 在開始的時候讓input_handler的h_list指向自己,也就是乙個空的迴圈鍊錶,在後來註冊input_handle的時候

* 讓input_handle的hnode與匹配的input_handler的h_list組成乙個迴圈鍊錶

*/init_list_head(&handler->h_list);//init_list_head(struct list_head *list)

list->next = list;

list->prev = list;

/* 2:

* 把handler->node掛到input_handler_list鍊錶的尾部,這是個全域性鍊錶 

*/list_add_tail(&handler->node, &input_handler_list);

/* 3:

* 搜尋input_dev_list的鍊錶的成員node,node是input_handler的node,

* 但是input_dev裡也有這個成員,實際上就是用作input_handler搜尋用過的,並把struct input_dev *dev返回 

*/list_for_each_entry(dev, &input_dev_list, node)   // #define list_for_each_entry(pos, head, member)

for (pos = list_entry((head)->next, typeof(*pos), member),prefetch(pos->member.next);

&pos->member != (head);

pos = list_entry(pos->member.next, typeof(*pos), member),prefetch(pos->member.next))

for(初始;條件;更新)

/* 4: 

* 匹配並建立鏈結

*/input_attach_handler(dev, handler);

const struct input_device_id *id

/* 通過id_table,呼叫input_match_device函式,把input_handler與input_dev做匹配 */

if (handler->blacklist && input_match_device(handler->blacklist, dev))

input_match_device(handler->id_table, dev);

/* 建立handler dev id三者之間的聯絡 */

handler->connect(handler, dev, id);

/* 5:

* 如果handler對應具體的evdev_handler 

*/evdev_handler->evdev_connect(struct input_handler *handler, struct input_dev *dev,const struct input_device_id *id)

struct evdev *evdev;

evdev->handle.dev = input_get_device(dev);//這裡的handle就是input_handle,它的dev成員指向input_dev

evdev->handle.name = dev_name(&evdev->dev);

evdev->handle.handler = handler;//它的handler成員指向input_handler

input_register_handle(&evdev->handle);

/* 這個函式與input_register_handler幾乎一致,而且最後結尾呼叫的附加函式是一樣的 */    

input_register_device(struct input_dev *dev)

list_add_tail(&dev->node, &input_dev_list);

list_for_each_entry(handler, &input_handler_list, node)

/* 與input_register_device中一樣呼叫這個函式,匹配並建立建立 */

input_attach_handler(dev, handler)

struct input_handle 

struct input_dev *dev;

struct input_handler *handler;

struct list_head    d_node;//鏈入input_dev的h_list代表的鍊錶

struct list_head    h_node;//鏈入input_handler的h_list代表的鍊錶

input_register_handle(struct input_handle *handle)

/* 把handle->d_node掛到dev->h_list的尾端 */

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

/* 把handle->h_node掛到handler->h_list的尾端 */

list_add_tail_rcu(&handle->h_node, &handler->h_list);//上段**的第6行的注釋

總結:註冊input_dev或input_handler時,會兩兩比較左邊的input_dev和右邊的input_handler,

根據input_handler的id_table判斷這個input_handler能否支援這個input_dev,

如果能支援,則呼叫input_handler的connect函式建立"連線"

input_register_device  → list_for_each_entry(handler, &input_handler_list, node), input_attach_handler(dev, handler) → input_register_handle

input_register_handler → list_for_each_entry(dev, &input_dev_list, node),         input_attach_handler(dev, handler) → input_register_handle

通過input_dev,可以遍歷所有與它有關的input_handler;

通過input_handler,也可以遍歷所有與它有關的input_dev。

可以看出,從任何乙個雙向箭頭出發,通過handle的過度,完全實現了我們的最終目標。

dev想要report資料的時候無非是呼叫了handler的event函式指標指向的函式,我們可以在這個函式裡定義任何想讓系統去做的任務

input_dev與input_handler是多對多的關係,乙個dev可以對應多個handler,乙個handler也可以對應多個dev

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

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

這裡可以理解:比方說evdev_handler與gpio_keys建立鏈結,生成handle,

handle->dev,    handle->d_node←---→input_dev->hlist,

handle->handler,handle->h_node←---→input_handler->hlist

但是同時evdev_handler還可以ts等驅動建立聯絡,在我們的驅動中不需要關注一對多和多對多的關係,只需要關注一對一的關係

input_register_handler這個函式一般不需要我們來實現,核心裡已經提供了常用的型別,如下:

如:evdev.c tsdev.c joydev.c mousedev.c keyboard.c

每乙個input_dev裡面都有evbit這個引數,指明是什麼型別的事件,

在註冊這個裝置的時候,回去匹配handler,呼叫相應的handelr,

比如我們buttons,對於ev_eky這樣的事件,核心中的輸入子系統input.c中的會呼叫evdev.c上報事件

這個檔案裡面的evdev_handler這個函式來處理ev_key這個事件

set_bit(ev_key, buttons_dev->evbit); 

set_bit(ev_rep, buttons_dev->evbit);

input_register_device(buttons_dev);

struct input_dev {

unsigned long evbit[nbits(ev_max)];   // 表示能產生哪類事件

unsigned long keybit[nbits(key_max)]; // 表示能產生哪些按鍵

unsigned long relbit[nbits(rel_max)]; // 表示能產生哪些相對位移事件, x,y,滾輪

unsigned long absbit[nbits(abs_max)]; // 表示能產生哪些絕對位移事件, x,y

unsigned long mscbit[nbits(msc_max)];

unsigned long ledbit[nbits(led_max)];

unsigned long sndbit[nbits(snd_max)];

unsigned long ffbit[nbits(ff_max)];}

input輸入子系統分析

1.檢視input子系統支援哪些裝置 cat proc bus input devices 2.應用程式如何使用 fd mouse open dev input event0 o rdwr event1表示滑鼠事件,input下的裝置檔案主裝置號都為13,如下圖所示 根據開啟裝置的主裝置號為13,知...

Linux輸入子系統分析一

輸入裝置分散不堪,用input子系統可以對分散的,不同類別的輸入裝置進行統一驅動。好處 1.統一了物理形態各異的輸入裝置相似的裝置處理,例如各種滑鼠,鍵盤,觸控螢幕。2.提供了用於分發輸入報告給使用者應用程式的簡單事件介面。你的驅動不必建立管理 dev節點以及相關的訪問方法。因此他能夠很方便的呼叫輸...

Linux 輸入子系統分析(二)

linux 輸入子系統分析 一 linux 輸入子系統分析 二 分析乙個核心提供的input handler input dev驅動程式的工作主要是 申請一些硬體資源,如註冊中斷等,申請input dev並設定,然後呼叫核心層提供的input register device函式進行註冊。裝置有資料時...