我们看input.c文件,其中首先看输入init函数
static int __init input_init(void)
函数中有注册file_operation的结构体,查看该结构体:
static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
};
里面只有一个input_open_file函数,一般来说,正常的驱动程序会有open,read,write等函数,这边只有一个open函数,那么这个原因必然在open函数中。
我们继续分析这个函数(忽略一些不必要的代码):
static int input_open_file(struct inode *inode, struct file *file)
{
struct input_handler *handler;
const struct file_operations *old_fops, *new_fops = NULL;
。。。。。
/* No load-on-demand here? */
handler = input_table[iminor(inode) >> 5];
if (!handler || !(new_fops = fops_get(handler->fops))) {
err = -ENODEV;
goto out;
}
。。。。
old_fops = file->f_op;
file->f_op = new_fops;
err = new_fops->open(inode,file);
上面的的代码中,定义了一个struct input_handler结构体,handler从input_table中去取值,然后从新的ops中调用open函数
new_fops->open(inode,file);
这个结构体作用是什么?还有input_table是在哪里初始化的,作用是什么?
我们先分析下input_table是在哪里构造的,搜索代码:
首先是一个全局变量
static structinput_handler *input_table[8];
在函数input_register_handler中有使用,分析函数:
注册input_handler:
int input_register_handler(struct input_handler *handler)
{
struct input_dev *dev;
// 放入数组中
input_table[handler->minor >> 5] = handler;
// 放入链表
list_add_tail(&handler->node, &input_handler_list);
// 对于每个input_dev,调用input_attach_handler
list_for_each_entry(dev, &input_dev_list, node)
// 根据input_handler的id_table判断能否支持这个input_dev
input_attach_handler(dev, handler);
。。。。。。
}
函数中主要工作是先把input_handler注册到数组input_table中,索引值是minor值右移5位,相当于除以32,然后将input_handler挂入到全局链表input_handler_list中,最后对于每个input_dev,调用input_attach_handler,根据input_handler的id_table判断能否支持这个input_dev。具体的分析函数input_attach_handler。
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
。。。。。
// 根据id_table看是否支持该设备
id = input_match_device(handler->id_table, dev);
if (!id)
return -ENODEV;
// 支持,则调用connect函数
error = handler->connect(handler, dev, id);
。。。。
}
以上分析我们知道了结构体structinput_handler *handler初始化好后,调用input_register_handler进行注册,注册过程中会从input_dev_list链表中去寻找是否有支持的设备,如果找到匹配的,则会调用handler->connect函数。
以上是注册handler的过程,让我们看看注册input_dev是怎么实现的?
注册输入设备:
int input_register_device(struct input_dev *dev)
{
// 放入链表
list_add_tail(&dev->node, &input_dev_list);
// 对于每一个input_handler,都调用input_attach_handler
list_for_each_entry(handler, &input_handler_list, node)
// 根据input_handler的id_table判断能否支持这个input_dev
input_attach_handler(dev, handler);
}
我们分析到这可以看到函数input_register_handler和input_register_device是对称的,不管是先注册handler还是dev,都会调用函数input_attach_handler进行匹配,匹配成功调用connect函数。
linux-2.6.30.4\drivers\input\evdev.c
初始化函数
static int __init evdev_init(void)
{
return input_register_handler(&evdev_handler);
}
调用了函数input_register_handler进行handler的注册,
static struct input_handler evdev_handler = {
.event = evdev_event,
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.fops = &evdev_fops,
.minor = EVDEV_MINOR_BASE,
.name = "evdev",
.id_table = evdev_ids,
};
其中我们主要看下connect函数,id_table。
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
// 分配一个设备结构体
evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
evdev->handle.dev = input_get_device(dev);// 设置input_dev
evdev->handle.name = evdev->name;
evdev->handle.handler = handler; // 设置input_handler
evdev->handle.private = evdev;
// 注册 handle
error = input_register_handle(&evdev->handle);
。。。
}
这里要注意一下handle,
将input_dev和input_handler链接起来,input_register_handle函数注册handle
int input_register_handle(struct input_handle *handle)
{
// 将d_node放入到dev的h_list中
list_add_tail_rcu(&handle->d_node, &dev->h_list);
// 将h_node放入到handler的h_list中
list_add_tail(&handle->h_node, &handler->h_list);
if (handler->start)
handler->start(handle);
}
通过input_register_handle函数,我们就可以通过dev的h_list找到handle结构体,从而找到对应的handler,或者通过input_handler的h_list找到handle结构体,从而找到对应的dev,所以结构体structinput_handle是沟通dev和handler的桥梁。
总结下建立连接的方式:
怎么建立连接?
1. 分配一个input_handle结构体
2.
input_handle.dev = input_dev; // 指向左边的input_dev
input_handle.handler = input_handler; // 指向右边的input_handler
3. 注册:
input_handler->h_list = &input_handle;
inpu_dev->h_list = &input_handle;
怎么读呢??
static ssize_t evdev_read(struct file *file, char __user *buffer,
size_t count, loff_t *ppos)
{
// 等待事件发生,等待条件是client->head != client->tail || !evdev->exist
retval = wait_event_interruptible(evdev->wait,
client->head != client->tail || !evdev->exist);
。。。
}
既然这里有等待,那必然会有函数去唤醒,那么唤醒函数在哪里呢?搜索代码,有个函数叫evdev_event,其中
evdev_event
evdev_pass_event(client, &event);
kill_fasync(&client->fasync, SIGIO, POLL_IN); // 发送信号给其他进程
wake_up_interruptible(&evdev->wait); // 唤醒进程
evdev_event 被谁调用呢???
evdev_event 在static struct input_handlerevdev_handler中被赋值了。
static structinput_handler evdev_handler = {
.event =evdev_event,
。。。
};
从上面可以看到调用函数evdev_event是通过evdev_handler的event函数调用的。