输入子系统核心 input core
通过前面的学习,我们学习了输入子系统中的输入设备驱动和输入事件驱动,这两者都是基于输入核心层input core 基础之上的。input core负责管理所有资源并连接输入设备驱动和输入事件驱动。这小节就让我们来深入input core,探其究竟...
1、input core 初始化
输入核心层input core 在drivers/input/input.c文件中实现,下面来研究其源代码。
static int __init input_init(void)
{
int err;
/*
* 注册一个input_class类
*/
err = class_register(&input_class);
if (err) {
pr_err("unable to register input_dev class\n");
return err;
}
/*
* 在/proc/bus/input下面创建两个节点devices和handlers,
* 通过打印这两个节点的内容可以查看输入子系统的设备驱
* 动层信息和处理层信息。
*/
err = input_proc_init();
if (err)
goto fail1;
/*
*申请注册输入子系统的主设备号13,并注册文件结构体input_fops。
*input core申请了主设备号,那么所有打开输入设备的处理请求都
*会传给input_fops的打开函数处理input_open_file
*
*/
err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
if (err) {
pr_err("unable to register char major %d", INPUT_MAJOR);
goto fail2;
}
return 0;
{
int err;
/*
* 注册一个input_class类
*/
err = class_register(&input_class);
if (err) {
pr_err("unable to register input_dev class\n");
return err;
}
/*
* 在/proc/bus/input下面创建两个节点devices和handlers,
* 通过打印这两个节点的内容可以查看输入子系统的设备驱
* 动层信息和处理层信息。
*/
err = input_proc_init();
if (err)
goto fail1;
/*
*申请注册输入子系统的主设备号13,并注册文件结构体input_fops。
*input core申请了主设备号,那么所有打开输入设备的处理请求都
*会传给input_fops的打开函数处理input_open_file
*
*/
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;
}
2、应用程序访问输入设备
上面我们知道了,当应用程序访问输入设备文件的时候,当调用open打开输入设备文件时,导致输入核心层的input_open_file的调用。以下是input_open_file的源码:
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?
* 根据次设备号从input_table取出用户需要的handler
* 把取到的handler支持的文件操作拷贝到new_fops中
*/
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;
/*
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;
/*
* file指的是用户想要打开的输入设备文件
* new_fops->open(inode, file)是调用对应handler的XX_open函数
* 到这里,input core已经完成了输入设备驱动和输入事件驱动的通信管道
* 剩下的就是输入设备驱动报告事件,输入事件驱动处理事件并与应用程序
* 交互数据信息
*/
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;
}
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;
}
3、