linux 输入子系统(4)---- input子系统的初始化

时间:2023-01-29 19:44:00

Input子系统的初始化函数为input_init(),如下:

static int __init input_init(void)
{
    int err;

    input_init_abs_bypass();

    err = class_register(&input_class);
    if (err) {
        printk(KERN_ERR "input: 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) {
        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”的类.所有input device都属于这个类.在sysfs中表现就是.所有input device所代表的目录都位于/dev/class/input下面.

然后调用input_proc_init()在/proc下面建立相关的交互文件.

再后调用register_chrdev()注册了主设备号为INPUT_MAJOR(13).次设备号为0~255的字符设备.它的操作指针为input_fops.
在这里,我们看到.所有 主设备号13的字符设备的操作最终都会转入到input_fops中./dev/input/event0~/dev/input/event4的主设备号为13.操作也不例外的落在了input_fops中.
 
Input_fops定义如下:
static const struct file_operations input_fops = {
    .owner = THIS_MODULE,
    .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? */
    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;
}

 

 iminor(inode)为打开文件所对应的次设备号.input_table是一个struct  input_handler全局数组.在这里.它先设备结点的次设备号右移5位做为索引值到input_table中取对应项.从这里我们也可以看到.一 个handle代表1<<5个设备节点(因为在input_table中取值是以次备号右移5位为索引的.即低5位相同的次备号对应的是同一 个索引).在这里,终于看到了input_talbe大显身手的地方了.input_talbe[ ]中取值和input_talbe[  ]的赋值,这两个过程是相对应的.

 在input_table中找到对应的handler之后,就会检验这个handle是否存,是否带有fops文件操作集.如果没有.则返回一个设备不存在的错误.
然后将handler中的fops替换掉当前的fops.如果新的fops中有open()函数,则调用它.