handler都有什么?搜索源码
drivers/macintosh/mac_hid.c: err = input_register_handler(&mac_hid_emumouse_handler);
net/rfkill/input.c: return input_register_handler(&rfkill_handler);
drivers/tty/sysrq.c: error = input_register_handler(&sysrq_handler);
drivers/input/input-leds.c: return input_register_handler(&input_leds_handler);
drivers/input/evdev.c: return input_register_handler(&evdev_handler);
drivers/input/evbug.c: return input_register_handler(&evbug_handler);
drivers/input/apm-power.c: return input_register_handler(&apmpower_handler);
drivers/input/joydev.c: return input_register_handler(&joydev_handler);
drivers/input/mousedev.c: error = input_register_handler(&mousedev_handler);
对于一个input设备我们要为其找一个合适的事件处理者(handler)
我们这里选择evdev_handler,因为它无条件匹配所有的input设备
static struct input_handler evdev_handler = {
.event = evdev_event,
.events = evdev_events,
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.legacy_minors = true,
.minor = EVDEV_MINOR_BASE,
.name = "evdev",
.id_table = evdev_ids,
};
分析handler的注册
input_register_handler()
int input_register_handler(struct input_handler *handler)
{
struct input_dev *dev;
int error;
error = mutex_lock_interruptible(&input_mutex);
if (error)
return error;
INIT_LIST_HEAD(&handler->h_list);
list_add_tail(&handler->node, &input_handler_list);
list_for_each_entry(dev, &input_dev_list, node)
input_attach_handler(dev, handler);
input_wakeup_procfs_readers();
mutex_unlock(&input_mutex);
return 0;
}
首先将handler挂载到input_handler_list上,然后遍历input_dev_list,与已经注册的input设备进行匹配,匹配函数input_attach_handler
input_register_handler() -> input_attach_handler()
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
const struct input_device_id *id;
int error;
id = input_match_device(handler, dev);
if (!id)
return -ENODEV;
error = handler->connect(handler, dev, id);
if (error && error != -ENODEV)
pr_err("failed to attach handler %s to device %s, error: %d\n",
handler->name, kobject_name(&dev->dev.kobj), error);
return error;
}
这里先分析input_match_device
input_register_handler() -> input_attach_handler() -> input_match_device()
static const struct input_device_id *input_match_device(struct input_handler *handler,
struct input_dev *dev)
{
const struct input_device_id *id;
for (id = handler->id_table; id->flags || id->driver_info; id++) {
if (input_match_device_id(dev, id) &&
(!handler->match || handler->match(handler, dev))) {
return id;
}
}
return NULL;
}
对于id_table,这里分析的evdev_handler对应的是 evdev_ids,其原型如下
static const struct input_device_id evdev_ids[] = {
{ .driver_info = 1 }, /* Matches all devices */
{ }, /* Terminating zero entry */
};
可以看到只有个driver_info,没有flags,接着跟进分析 input_match_device_id,这里的id表示的是id_table
bool input_match_device_id(const struct input_dev *dev,
const struct input_device_id *id)
{
if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
if (id->bustype != dev->id.bustype)
return false;
if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
if (id->vendor != dev->id.vendor)
return false;
if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
if (id->product != dev->id.product)
return false;
if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
if (id->version != dev->id.version)
return false;
if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX) ||
!bitmap_subset(id->keybit, dev->keybit, KEY_MAX) ||
!bitmap_subset(id->relbit, dev->relbit, REL_MAX) ||
!bitmap_subset(id->absbit, dev->absbit, ABS_MAX) ||
!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX) ||
!bitmap_subset(id->ledbit, dev->ledbit, LED_MAX) ||
!bitmap_subset(id->sndbit, dev->sndbit, SND_MAX) ||
!bitmap_subset(id->ffbit, dev->ffbit, FF_MAX) ||
!bitmap_subset(id->swbit, dev->swbit, SW_MAX) ||
!bitmap_subset(id->propbit, dev->propbit, INPUT_PROP_MAX)) {
return false;
}
return true;
}
可以看到flags中会有这些标志,之前input设备注册的时候,还讨论过vendor,product,version作用是什么,这里随便没有去匹配,但是可以知道通过这些变量可以匹配到特殊的handler
对于其中的bitmap_subset来说,以bitmap_subset(id->evbit, dev->evbit, EV_MAX)为例,
主要判断就是id->evbit中标记的事件必须等同或者是dev->evbit中标记事件的子集,下面对应的具体事件也是如此。
对于id_table中都为空的情况,空集是任何集合的子集,是任何非空集合的真子集,所以一样满足。
input_match_device_id满足,接着分析handler的match函数,如果有match的话,这里没有。
此时可以认为input_match_device 函数满足,返回input_attach_handler()
input_register_handler() -> input_attach_handler()
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
const struct input_device_id *id;
int error;
id = input_match_device(handler, dev);
if (!id)
return -ENODEV;
error = handler->connect(handler, dev, id);
if (error && error != -ENODEV)
pr_err("failed to attach handler %s to device %s, error: %d\n",
handler->name, kobject_name(&dev->dev.kobj), error);
return error;
}
继续分析connect函数
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct evdev *evdev;
int minor;
int dev_no;
int error;
minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);
if (minor < 0) {
error = minor;
pr_err("failed to reserve new minor: %d\n", error);
return error;
}
evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
if (!evdev) {
error = -ENOMEM;
goto err_free_minor;
}
INIT_LIST_HEAD(&evdev->client_list);
spin_lock_init(&evdev->client_lock);
mutex_init(&evdev->mutex);
init_waitqueue_head(&evdev->wait);
evdev->exist = true;
dev_no = minor;
/* Normalize device number if it falls into legacy range */
if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS)
dev_no -= EVDEV_MINOR_BASE;
dev_set_name(&evdev->dev, "event%d", dev_no);
evdev->handle.dev = input_get_device(dev);
evdev->handle.name = dev_name(&evdev->dev);
evdev->handle.handler = handler;
evdev->handle.private = evdev;
evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);
evdev->dev.class = &input_class;
evdev->dev.parent = &dev->dev;
evdev->dev.release = evdev_free;
device_initialize(&evdev->dev);
error = input_register_handle(&evdev->handle);
if (error)
goto err_free_evdev;
cdev_init(&evdev->cdev, &evdev_fops);
error = cdev_device_add(&evdev->cdev, &evdev->dev);
if (error)
goto err_cleanup_evdev;
return 0;
}
这个connect函数主要做了3件事情
这里分析一下handle的注册
int input_register_handle(struct input_handle *handle)
{
struct input_handler *handler = handle->handler;
struct input_dev *dev = handle->dev;
int error;
/*
* We take dev->mutex here to prevent race with
* input_release_device().
*/
error = mutex_lock_interruptible(&dev->mutex);
if (error)
return error;
/*
* Filters go to the head of the list, normal handlers
* to the tail.
*/
if (handler->filter)
list_add_rcu(&handle->d_node, &dev->h_list);
else
list_add_tail_rcu(&handle->d_node, &dev->h_list);
mutex_unlock(&dev->mutex);
/*
* Since we are supposed to be called from ->connect()
* which is mutually exclusive with ->disconnect()
* we can't be racing with input_unregister_handle()
* and so separate lock is not needed here.
*/
list_add_tail_rcu(&handle->h_node, &handler->h_list);
if (handler->start)
handler->start(handle);
return 0;
}
对应handler->filter,filter是过滤器的意思,如果有filter则将handle挂载到dev->h_list的头部,没有的话则挂载到尾部,有种优先的感觉,具体的作用遇到再分析,这里还不知道。
同时将handle挂载到handler->h_list,具体作用?
最后如果handler有start方法,则调用start方法,当前的handler没有。
以上就完成了handler的注册,进而引发了input设备和handler的匹配过程,最终注册了eventX节点。
该篇文章中只是分析了一个handler,对于一个input设备匹配多个handler的情况,后面单独再分析。