input子系统学习笔记八 input子系统的详细分析
2013-03-04 14:36
162 查看
为了对输入子系统有一个清晰的认识,本节将分析输入系统的初始化过程。在 Linux 中,输入子系统作为一个模块存在,向上,为用户层提供接口函数,向下,为驱动层程序提供统一的接口函数。这样,就能够使输入设备的事件通过输入子系统发送给用户层应用程序,用户层应用程序也可以通过输入子系统通知驱动程序完成某项功能。
子系统初始化函数 input_init()
输入子系统作为一个模块存在,必然有一个初始化函数。在/drivers/input/input.c 文件中定义了输入子系统的初始化函数 input_init(),该函数的代码如下:
C/C++代码
static
int __init input_init(void)
{
int err;
input_init_abs_bypass();
err = class_register(&input_class);
/*调用 class_register()函数先注册了一个名为 input 的类。所有 input device 都属于这个类。在 sysfs 中表现就是,所有 input device 所代表的目录都位于/dev/class/input 下面。
代码如下:
struct class input_class = {
.name= "input",
};
*/
if (err) {
printk(KERN_ERR
"input: unable to register input_dev class\n");
return err;
}
err = input_proc_init();/*调用 input_proc_init()在/proc 下面建立相关的交互文件。*/
if (err)
goto fail1;
err = register_chrdev(INPUT_MAJOR,
"input", &input_fops);/*调用 register_chrdev()注册了主设备号为
INPUT_MAJOR(13)。次设备号为 0~255 的字符设备。它的操作指针为 input_fops。在这里,可以看到所有主设备号 13 的字符设备的操作最终都会转入到 input_fops 中。例如/dev/input/event0~/
dev/input/event4 的主设备号为 13,对其的操作会落在 input_fops 中。input_fops 只定义了一个 input_open_file()函数,input_fops 的定义代码如下:
static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
}; */
if (err) {
printk(KERN_ERR
"input: unable to register char major %d",
INPUT_MAJOR);
goto fail2;
}
return 0;
fail2: input_proc_exit();
fail1: class_unregister(&input_class);
return err;
}
文件打开函数 input_open_file()
文件操作指针中定义了 input_open_file()函数,该函数将控制转到 input_handler 中定义的fops 文件指针的 open()函数。该函数在 input_handler 中实现,这样就使不同的 handler 处理器对应了不同的文件打开方法,为完成不同功能提供了方便。input_open_file()函数的代码如下:
C/C++代码
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];/*出现了熟悉的 input_table[]数组。iminor(inode)为打开文件所对应的次设备号。input_table 是一个 struct input_handler
全局数组,只有 8 个元素,其定义为:
static struct input_handler *input_table[8];
在这里,首先将设备结点的次设备号右移 5 位做为索引值到 input_table 中取对应项,从这里也可以看到,一个 handler 代表 32(1<<5)个设备结点,也就是一个 handler 最多可以处理 32 个设备结点。因为在 input_table
中取值是以次备号右移 5 位为索引的,即第 5 位相同的 次 备 号 对 应 的 是 同 一 个 索 引 。 回 忆 input_register_handler() 函 数 的 第 14 行input_table[handler->minor >> 5] = handler,其将 handler 赋给了 input_table 数组,所使用的规则也是右移 5 位。
*/
if (handler)/*在 input_table 中找到对应的 handler 之后,就会检验这个 handler 是否存在,如果没有,则返回一个设备不存在的错误。在存在的情况下,从 handler->fops 中获得新的文件操作指针
file_operation,并增加引用计数。此后,对设备的操作都通过新的文件操作指针 new_fops 来完成。*/
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...
*/
/*判断 new_fops->open()函数是否定义,如果没有定义,则表示设备不存在。*/
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);/*使用新的 open()函数,重新打开设备。*/
if (err) {
fops_put(file->f_op);
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
out:
return err;
}
子系统初始化函数 input_init()
输入子系统作为一个模块存在,必然有一个初始化函数。在/drivers/input/input.c 文件中定义了输入子系统的初始化函数 input_init(),该函数的代码如下:
C/C++代码
static
int __init input_init(void)
{
int err;
input_init_abs_bypass();
err = class_register(&input_class);
/*调用 class_register()函数先注册了一个名为 input 的类。所有 input device 都属于这个类。在 sysfs 中表现就是,所有 input device 所代表的目录都位于/dev/class/input 下面。
代码如下:
struct class input_class = {
.name= "input",
};
*/
if (err) {
printk(KERN_ERR
"input: unable to register input_dev class\n");
return err;
}
err = input_proc_init();/*调用 input_proc_init()在/proc 下面建立相关的交互文件。*/
if (err)
goto fail1;
err = register_chrdev(INPUT_MAJOR,
"input", &input_fops);/*调用 register_chrdev()注册了主设备号为
INPUT_MAJOR(13)。次设备号为 0~255 的字符设备。它的操作指针为 input_fops。在这里,可以看到所有主设备号 13 的字符设备的操作最终都会转入到 input_fops 中。例如/dev/input/event0~/
dev/input/event4 的主设备号为 13,对其的操作会落在 input_fops 中。input_fops 只定义了一个 input_open_file()函数,input_fops 的定义代码如下:
static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
}; */
if (err) {
printk(KERN_ERR
"input: unable to register char major %d",
INPUT_MAJOR);
goto fail2;
}
return 0;
fail2: input_proc_exit();
fail1: class_unregister(&input_class);
return err;
}
文件打开函数 input_open_file()
文件操作指针中定义了 input_open_file()函数,该函数将控制转到 input_handler 中定义的fops 文件指针的 open()函数。该函数在 input_handler 中实现,这样就使不同的 handler 处理器对应了不同的文件打开方法,为完成不同功能提供了方便。input_open_file()函数的代码如下:
C/C++代码
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];/*出现了熟悉的 input_table[]数组。iminor(inode)为打开文件所对应的次设备号。input_table 是一个 struct input_handler
全局数组,只有 8 个元素,其定义为:
static struct input_handler *input_table[8];
在这里,首先将设备结点的次设备号右移 5 位做为索引值到 input_table 中取对应项,从这里也可以看到,一个 handler 代表 32(1<<5)个设备结点,也就是一个 handler 最多可以处理 32 个设备结点。因为在 input_table
中取值是以次备号右移 5 位为索引的,即第 5 位相同的 次 备 号 对 应 的 是 同 一 个 索 引 。 回 忆 input_register_handler() 函 数 的 第 14 行input_table[handler->minor >> 5] = handler,其将 handler 赋给了 input_table 数组,所使用的规则也是右移 5 位。
*/
if (handler)/*在 input_table 中找到对应的 handler 之后,就会检验这个 handler 是否存在,如果没有,则返回一个设备不存在的错误。在存在的情况下,从 handler->fops 中获得新的文件操作指针
file_operation,并增加引用计数。此后,对设备的操作都通过新的文件操作指针 new_fops 来完成。*/
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...
*/
/*判断 new_fops->open()函数是否定义,如果没有定义,则表示设备不存在。*/
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);/*使用新的 open()函数,重新打开设备。*/
if (err) {
fops_put(file->f_op);
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
out:
return err;
}
相关文章推荐
- input子系统学习笔记八 input子系统的详细分析
- input子系统学习笔记八 input子系统的详细分析
- input子系统学习笔记五 按键驱动实例分析上
- input子系统学习笔记六 按键驱动实例分析下
- input子系统学习笔记六 按键驱动实例分析下
- input子系统学习笔记六 按键驱动实例分析下
- input子系统学习笔记七 handler处理器注册分析
- input子系统学习笔记七 handler处理器注册分析
- input子系统学习笔记七 handler处理器注册分析
- input子系统学习笔记九 evdev输入事件驱动分析
- input子系统学习笔记九 evdev输入事件驱动分析
- input子系统学习笔记九 evdev输入事件驱动分析
- input子系统学习笔记 按键驱动实例分析下
- input子系统学习笔记五 按键驱动实例分析上
- input子系统学习笔记六 按键驱动实例分析下
- input子系统学习笔记七 handler处理器注册分析
- input子系统学习笔记五 按键驱动实例分析上
- input子系统学习笔记九 evdev输入事件驱动分析
- input 子系统的分析与学习(二)
- java学习笔记,java中类的详细分析