看一下 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))
语句中的内容不能执行了,所以内核定时器也就停止了工作,既停止了按键的重复。