LINUX裝置驅動之輸入子系統 二

2021-06-04 06:47:23 字數 4739 閱讀 1701

eric fang  2010-02-03

本站分析linux核心原始碼,版本號為2.6.32.3

二.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燈進行操作的,函式如下

1032              declare_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裝置驅動之輸入子系統 二

二 input handler的註冊 在input device的註冊中存在下列疑問 1,匹配dev和handler時,input handler list上的handler是什麼時候掛上去的呢?2,匹配成功後會呼叫相應handler的connect函式,此函式做了什麼事?帶著這兩個疑問,我們以鍵盤...

Linux裝置驅動 input輸入子系統

不同的輸入裝置 如按鍵 鍵盤 觸控螢幕 滑鼠等 都有它們的差異性 如中斷 讀鍵值 座標值是裝置相關的 及共同性 如輸入事件的緩衝區管理以及字元裝置驅動的file operations介面則對輸入裝置是通用的 因此在linux核心中設計了input輸入子系統來完成輸入裝置之間的共性工作,而我們只需要使...