看一下 input_dev<include/linux/input.h> 結構體,只列出了和我們討論的內用有關的成員:
struct input_dev
{
.........
/* stores key code of the last key pressed; used to implement software autorepeat */
unsigned int repeat_key;
/* timer for software autorepeat */
struct timer_list timer;
.......
}
接下來我們看一下input_register_device函數,只關心我們討論的部分:
int input_register_device(struct input_dev *dev)
{
......
init_timer(&dev->timer);
if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
dev->timer.data = (long) dev;
dev->timer.function = input_repeat_key;
dev->rep[REP_DELAY] = 250;
dev->rep[REP_PERIOD] = 33;
}
......
}
我麼看到該函數初始化了一個內核定時器。input_repeat_key則爲按鍵重複的關鍵函數,源碼如下:
static void input_repeat_key(unsigned long data)
{
struct input_dev *dev = (void *) data;
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
if (test_bit(dev->repeat_key, dev->key) &&
is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
/* input_pass_event函數會執行handler中event函數 */
input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
if (dev->sync) {
/*
* Only send SYN_REPORT if we are not in a middle
* of driver parsing a new hardware packet.
* Otherwise assume that the driver will send
* SYN_REPORT once it's done.
*/
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
}
if (dev->rep[REP_PERIOD])
mod_timer(&dev->timer, jiffies +
msecs_to_jiffies(dev->rep[REP_PERIOD]));
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
但是我們沒有看到add_timer函數,內核定時器是在什麼時候加入內核定時器鏈表的呢?我們知道在有按鍵按下是要使用input_report_key函數報告的,看一下該函數:
static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
{
input_event(dev, EV_KEY, code, !!value);
}
繼續往下看:
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
......
input_handle_event(dev, type, code, value);
......
}
在該函數中我們主要看input_handle_event函數:
static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
int disposition = INPUT_IGNORE_EVENT;
switch (type) {
......
case EV_KEY:
if (is_event_supported(code, dev->keybit, KEY_MAX) &&
!!test_bit(code, dev->key) != value) {
if (value != 2) {
__change_bit(code, dev->key); /* 每執行該函數就會將該位的值和原來的值進行異或 */
if (value)
input_start_autorepeat(dev, code);
}
disposition = INPUT_PASS_TO_HANDLERS;
}
break;
......
case EV_REP:
if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) {
dev->rep[code] = value;
disposition = INPUT_PASS_TO_ALL;
}
break;
......
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
dev->sync = 0;
if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
dev->event(dev, type, code, value);
if (disposition & INPUT_PASS_TO_HANDLERS)
input_pass_event(dev, type, code, value);
}
我們主要看input_start_autorepeat函數:
static void input_start_autorepeat(struct input_dev *dev, int code)
{
if (test_bit(EV_REP, dev->evbit) &&
dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
dev->timer.data) {
dev->repeat_key = code;
mod_timer(&dev->timer,
jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
}
}
我們還是沒看到add_timer函數,其實不需要add_timer函數也是可以啓動內核定時器的,那就是mod_timer函數,該函數的執行過程等於del_timer(timer); timer->expires = expires; add_timer(timer);所以就會啓動內核定時器。
input_report_key的原型如下:
static inline void input_report_key(struct input_dev *dev, unsigned int code, int value);
我們知道在使用input_report_key函數時參數value表示的是按鍵的按下還是沒按下。0表示按鍵釋放,非0表示按鍵按下。我們看到當按鍵按下時,如果配置了按鍵是可以重複的,就會執行input_start_autorepeat函數,該函數就會啓動內核定時器,接着就會執行input_repeat_key函數,在該函數中執行:
input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
其中dev->repeat_key保存的爲按下按鍵時的值,我們看到value參數的值爲2,在看input_handle_event,該函數中if (value != 2) 裏面的語句就不能執行,也就不會執行__change_bit(code, dev->key);所以可以一直執行input_repeat_key中的
if (test_bit(dev->repeat_key, dev->key) &&
is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX))
裏面的語句。執行:
mod_timer(&dev->timer, jiffies +msecs_to_jiffies(dev->rep[REP_PERIOD]));
重啓定時器,如此定時器就一直執行下去。
但我們釋放按鍵時。就會改變dev->key的值,使input_repeat_key中的
if (test_bit(dev->repeat_key, dev->key) &&
is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX))
語句中的內容不能執行了,所以內核定時器也就停止了工作,既停止了按鍵的重複。