如上一篇《
Linux input 子系统学习之开篇》所述,input.c文件是input子系统的核心,其目录是在lichee/linux-3.4/drivers/input/input.c。好的,我们现在就来分析一下这个文件吧。
1、分析一个驱动,当然是从入口函数开始。
-
static int __init input_init(void)
-
{
-
int err;
-
-
err = class_register(&input_class);
-
if (err) {
-
pr_err("unable to register input_dev class\n");
-
return err;
-
}
-
-
err = input_proc_init();
-
if (err)
-
goto fail1;
-
-
err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
-
if (err) {
-
pr_err("unable to register char major %d", INPUT_MAJOR);
-
goto fail2;
-
}
-
-
return 0;
-
-
fail2: input_proc_exit();
-
fail1: class_unregister(&input_class);
-
-
return err;
-
}
首先是注册一个input_class类,然后向系统申请设备号(主设备号是INPUT_MAJOR)。
另外有个input_proc_init()
-
static int __init input_proc_init(void)
-
{
-
struct proc_dir_entry *entry;
-
-
proc_bus_input_dir = proc_mkdir("bus/input", NULL);
-
if (!proc_bus_input_dir)
-
return -ENOMEM;
-
-
entry = proc_create("devices", 0, proc_bus_input_dir,
-
&input_devices_fileops);
-
if (!entry)
-
goto fail1;
-
-
entry = proc_create("handlers", 0, proc_bus_input_dir,
-
&input_handlers_fileops);
-
if (!entry)
-
goto fail2;
-
-
return 0;
-
-
fail2: remove_proc_entry("devices", proc_bus_input_dir);
-
fail1: remove_proc_entry("bus/input", NULL);
-
return -ENOMEM;
-
}
很明显,这里会在proc下建立 bus/input,bus/input/devices,bus/input/handlers
2、下面,来看看 input_fops
-
static const struct file_operations input_fops = {
-
.owner = THIS_MODULE,
-
.open = input_open_file,
-
.llseek = noop_llseek,
-
};
很简单,里面主要的函数就是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;
-
int err;
-
-
err = mutex_lock_interruptible(&input_mutex);
-
if (err)
-
return err;
-
-
/* No load-on-demand here? */
-
handler = input_table[iminor(inode) >> 5];
-
if (handler)
-
new_fops = fops_get(handler->fops);
-
-
mutex_unlock(&input_mutex);
-
-
/*
-
* That's _really_ odd. Usually NULL ->open means "nothing special",
-
* not "no device". Oh, well...
-
*/
-
if (!new_fops || !new_fops->open) {
-
fops_put(new_fops);
-
err = -ENODEV;
-
goto out;
-
}
-
-
old_fops = file->f_op;
-
file->f_op = new_fops;
-
-
err = new_fops->open(inode, file);
-
if (err) {
-
fops_put(file->f_op);
-
file->f_op = fops_get(old_fops);
-
}
-
fops_put(old_fops);
-
out:
-
return err;
-
}
先通过inode节点获取到次设备号,然后在input_table数组中,找到一个handler。找到handler后,获取其中的fops,并将此fops赋值给file->fops,最后实执行里面的open函数。
可以想象到,input_table这个数组里面都是input_handler,而这个数组肯定是另外的文件通过某种方式注册上去,然后把它放在数组里面的。说得这么明白,相信大家都猜测到了,这个当
然就是上一篇所讲的input_register_handle函数了。
好的,下一篇,我们就去看看这个神奇的input_register_handler函数。
阅读(1789) | 评论(0) | 转发(0) |