二.input handler的註冊
在input device的註冊中存在下列疑問: 1,
匹配dev和handler時,input_handler_list上的handler是什麼時候掛上去的呢?
2,匹配成功後會呼叫相應handler的connect函式,此函式做了什麼事?
帶著這兩個疑問,我們以鍵盤為例進行分析。
在系統啟動初始化vty(vty_init函式,tty、vty部分內容將在以後分析)時會呼叫kbd_init()進行鍵盤初始化,kbd_init函式定義於drivers/char/keyboard.c:
1403 int __init kbd_init(void)
1404
1417
1418 error = input_register_handler(&kbd_handler);
1419 if (error)
1420 return error;
1421
1422 tasklet_enable(&keyboard_tasklet);
1423 tasklet_schedule(&keyboard_tasklet);
1424
1425 return 0;
1426 }
第1408~1416行初始化kbd_table陣列,這部分與tty內容相關,以後再分析。
1418行,這裡我們終於看到呼叫input_register_handler函式註冊kbd_handler,kbd_handler定義如下:
1394 static struct input_handler kbd_handler = ;
我們看到id_table指向kbd_ids陣列,kbd_ids定義如下:
1378 static const struct input_device_id kbd_ids = ,
1382 },
1383
1384 ,
1387 },
1388
1389 , /* terminating entry */
1390 };
從這個id_table看到,只要input_dev設定了其evbit欄位支援ev_key或ev_snd都會匹配到hnadler,回想一下在鍵盤驅動中建立input_dev後呼叫的atkbd_set_device_attrs設定input_dev的函式中有下列語句:
input_dev->evbit[0] = bit_mask(ev_key) | bit_mask(ev_rep) |
bit_mask(ev_msc);
說明at鍵盤的input_dev會匹配到這個hnadler。
我們接著看input_register_handler函式:
1600 int input_register_handler(struct input_handler *handler)
1601
1616 input_table[handler->minor >> 5] = handler;
1617 }
1618
1619 list_add_tail(&handler->node, &input_handler_list);
1620
1621 list_for_each_entry(dev, &input_dev_list, node)
1622 input_attach_handler(dev, handler);
1623
1624 input_wakeup_procfs_readers();
1625
1626 out:
1627 mutex_unlock(&input_mutex);
1628 return retval;
1629 }
第1605行獲得互斥訊號量,1609行初始化handler 的h_list欄位,這個h_list指向的鍊錶用於存放input_handle。
第1611~1617行,我們的kbd_handler沒有定義fops函式,所以這段**不會執行,不過我們還是看一下,這裡的input_table陣列是乙個struct input_handler結構陣列,根據裝置的次裝置號除以32的值為下標的元素為input_handler為什麼是32?輸入子系統最多支援256個裝置,而input_handler結構的陣列最多處理8類事件,所以分給每一類的次裝置號段分配32個。
第1619行把handler鏈結到input_handler_list尾部。
第1621~1622用handler去匹配input_dev_list上的input_dev,input_attach_handler函式在上面已經分析過,再最後如果匹配成功會呼叫handler的connect函式,對於這個kbd_handler相應的函式為kbd_connect,看一下這個函式:
1314 static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
1315 const struct input_device_id *id)
1316
第1321~1326行判斷dev->keybit,如果屬於例外的情況,則不再往下走,返回-enodev。
第1328行,為handle分配記憶體空間,1332~1334行初始化handle的部分字段。
第1336行呼叫input_register_handle註冊handle,看一下這個函式:
1671 int input_register_handle(struct input_handle *handle)
1672
第1684、1693將handle分別鏈結到dev->h_list和handler->h_list。
第1695~1696行,如果handler的start函式存在,則呼叫它。對於這個kbd_handler相應的函式為kbd_start,看一下這個函式:
1364 static void kbd_start(struct input_handle *handle)
1365
1375 tasklet_enable(&keyboard_tasklet);
1376 }
禁止keyboard_tasklet,初始化鍵盤的三個led燈及syn_report,然後啟用keyboard_tasklet,這個keyboard_tasklet也是對led燈進行操作的,函式如下
1032declare_tasklet_disabled(keyboard_tasklet, kbd_bh, 0);
1014 static void kbd_bh(unsigned long dummy)
1015
1027 }
1028
1029 ledstate = leds;
1030 }
input_register_handle函式返回後,第1340行呼叫input_open_device函式,這個函式執行後相應的handle就能接受裝置上報的事件。函式如下:
0421 int input_open_device(struct input_handle *handle)
0422
0434
0435 handle->open++;
0436
0437 if (!dev->users++ && dev->open)
0438 retval = dev->open(dev);
0439
0440 if (retval)
0449 }
0450
0451 out:
0452 mutex_unlock(&dev->mutex);
0453 return retval;
0454 }
增加handle的open計數,如果handle->dev->users不為0,則自增1,如果為0並且handle->dev的open函式存在則會呼叫它,對於前面分析的atkbd,相應的handle->dev的open函式不存在。
至此,input handler和input handler的註冊都分析完了,接著將分析事件處理部分內容。
linux裝置驅動 輸入子系統
輸入裝置都能用輸入子系統來寫,比如說按鍵 觸控螢幕 滑鼠等,但是有的輸入裝置不止用到了輸入子系統,比如說usb輸入裝置,他們還用到了usb子系統。我們以最簡單的按鍵 直接接到cpu上 為例介紹一下輸入子系統。輸入子系統將硬體相關的 與軟體相關的 分開寫,目的是為了以後編寫修改 簡便。軟體部分系統已經...
LINUX裝置驅動之輸入子系統 二
eric fang 2010 02 03 本站分析linux核心原始碼,版本號為2.6.32.3 二 input handler的註冊 在input device的註冊中存在下列疑問 1,匹配dev和handler時,input handler list上的handler是什麼時候掛上去的呢?2,匹...
Linux裝置驅動 input輸入子系統
不同的輸入裝置 如按鍵 鍵盤 觸控螢幕 滑鼠等 都有它們的差異性 如中斷 讀鍵值 座標值是裝置相關的 及共同性 如輸入事件的緩衝區管理以及字元裝置驅動的file operations介面則對輸入裝置是通用的 因此在linux核心中設計了input輸入子系統來完成輸入裝置之間的共性工作,而我們只需要使...