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函式進行註冊。裝置有資料時...