1.4 input_dev 的注册
在输入设备驱动的初始化函数的最后一步就是调用 input_register_device 注册设备。这个函数如 程序清单 1 .9 所示。
程序清单 1 . 9 input_register_device
/* driver/input/input.c */
int input_register_device(struct input_dev *dev)
{
static atomic_t input_no = ATOMIC_INIT(0);
struct input_handler *handler;
const char *path;
int error;
__set_bit(EV_SYN, dev->evbit); ⑴
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;
}
if (!dev->getkeycode) ⑶
dev->getkeycode = input_default_getkeycode;
if (!dev->setkeycode)
dev->setkeycode = input_default_setkeycode;
snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
"input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
error = device_add(&dev->dev);
if (error)
return error;
path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
printk(KERN_INFO "input: %s as %s/n",
dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
kfree(path);
error = mutex_lock_interruptible(&input_mutex);
if (error) {
device_del(&dev->dev);
return error;
}
list_add_tail(&dev->node, &input_dev_list); ⑷
list_for_each_entry(handler, &input_handler_list, node) ⑸
input_attach_handler(dev, handler);
input_wakeup_procfs_readers();
mutex_unlock(&input_mutex);
return 0;
}
下面就标记的几点进行说明:
⑴ 注册同步事件为支持的类型,任何设备都默认支持同步事件。
⑵ 初始化设备连击计时器,如果驱动没有填写连击参数就使用默认值。
⑶ 如果驱动没有实现映射修改和查看的函数,填充默认函数。
⑷ 将本设备加入设备链表 ( 这个链表是全局的 ) 。
⑸ 将本设备和已经存在的 handler 进行比较,与 id 相匹配的 handler 建立连接。需要说明的是设备可能跟多个 handler 连接,这样此设备产生的事件会分发给所有连接的 handler 。
可以看出上面第五步是最重要的一步,下面继续分析 input_attach_handler 这个函数。它的代码如 程序清单 1 .10 所示。
程序清单 1 . 10 input_attach_handler
/* driver/input/input.c */
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
const struct input_device_id *id;
int error;
if (handler->blacklist && input_match_device(handler->blacklist, dev)) ⑴
return -ENODEV;
id = input_match_device(handler->id_table, dev); ⑵
if (!id)
return -ENODEV;
error = handler->connect(handler, dev, id); ⑶
if (error && error != -ENODEV)
printk(KERN_ERR
"input: failed to attach handler %s to device %s, "
"error: %d/n",
handler->name, kobject_name(&dev->dev.kobj), error);
return error;
}
需要说明的地方有三点:
⑴ handler->blacklist 中存储的是禁止连接的设备 id ,因此首先查看该设备是否允许连接。
⑵ handler->id_table 存储 handler 支持的设备 id 。如果能够找到匹配的 id ,则建立 dev 和 handler 之间的连接。
⑶ 建立 dev 和 handler 之间的连接。
connect 函数的实现下章再讲,下面看看 input_match_device 的实现。代码如 程序清单 1 .11 所示。
程序清单 1 . 11 input_match_device
/* driver/input/input.c */
#define MATCH_BIT(bit, max) /
for (i = 0; i < BITS_TO_LONGS(max); i++) /
if ((id->bit[i] & dev->bit[i]) != id->bit[i]) / ⑴
break; /
if (i != BITS_TO_LONGS(max)) /
continue;
static const struct input_device_id *input_match_device(const struct input_device_id *id,
struct input_dev *dev)
{
int i;
for (; id->flags || id->driver_info; id++) {
if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) ⑵
if (id->bustype != dev->id.bustype)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
if (id->vendor != dev->id.vendor)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
if (id->product != dev->id.product)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
if (id->version != dev->id.version)
continue;
MATCH_BIT(evbit, EV_MAX); ⑶
MATCH_BIT(keybit, KEY_MAX);
MATCH_BIT(relbit, REL_MAX);
MATCH_BIT(absbit, ABS_MAX);
MATCH_BIT(mscbit, MSC_MAX);
MATCH_BIT(ledbit, LED_MAX);
MATCH_BIT(sndbit, SND_MAX);
MATCH_BIT(ffbit, FF_MAX);
MATCH_BIT(swbit, SW_MAX);
return id;
}
return NULL;
}
匹配的过程主要做了两件事:
⑵ 根据 id->flag 检查 id 是否匹配。 id->flag 记录需要匹配哪些域。
⑶ 检查支持的事件种类是否一致。
第二种检查用到的宏 MATCH_BIT 定义在 ⑴ 处。其中最重要的一句是“ if ((id->bit[i] & dev->bit[i]) != id->bit[i]) ”,这句话意味着 id 支持的事件种类是 dev 支持的事件的子集就算匹配了。如果某个 handler 的 id 除了 id->driver_info 之外的域都为 0 ,那么此 handler 可以和任意 dev 匹配。实际上 < 内核 >/driver/input/evdev.c 中就是这么初始化 id 的。
现在总结一下 input_dev 注册的过程:一个 input_dev 注册的过程主要是在将自己加入 input_dev_list ,然后在 input_handler_list 中找到 id 和事件种类相匹配的 handler 并与之建立连接的过程。
input_dev 产生的事件会分发给所有建立连接的 handler 。下面继续分析事件的传递。