Linux字符设备驱动程序源文件(4)

if (owner && !try_module_get(owner))
        return NULL;
    kobj = kobject_get(&p->kobj);
    if (!kobj)
        module_put(owner);
    return kobj;
}

void cdev_put(struct cdev *p)
{
    if (p) {
        struct module *owner = p->owner;
        kobject_put(&p->kobj);
        module_put(owner);
    }
}

/*
 * Called every time a character special file is opened
 */
static int chrdev_open(struct inode *inode, struct file *filp)
{
    struct cdev *p;
    struct cdev *new = NULL;
    int ret = 0;

spin_lock(&cdev_lock);
    p = inode->i_cdev;
    if (!p) {
        struct kobject *kobj;
        int idx;
        spin_unlock(&cdev_lock);
        kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);
        if (!kobj)
            return -ENXIO;
        new = container_of(kobj, struct cdev, kobj);
        spin_lock(&cdev_lock);
        /* Check i_cdev again in case somebody beat us to it while
           we dropped the lock. */
        p = inode->i_cdev;
        if (!p) {
            inode->i_cdev = p = new;
            list_add(&inode->i_devices, &p->list);
            new = NULL;
        } else if (!cdev_get(p))
            ret = -ENXIO;
    } else if (!cdev_get(p))
        ret = -ENXIO;
    spin_unlock(&cdev_lock);
    cdev_put(new);
    if (ret)
        return ret;

ret = -ENXIO;
    filp->f_op = fops_get(p->ops);
    if (!filp->f_op)
        goto out_cdev_put;

if (filp->f_op->open) {
        ret = filp->f_op->open(inode,filp);
        if (ret)
            goto out_cdev_put;
    }

return 0;

out_cdev_put:
    cdev_put(p);
    return ret;
}

int cdev_index(struct inode *inode)
{
    int idx;
    struct kobject *kobj;

kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);
    if (!kobj)
        return -1;
    kobject_put(kobj);
    return idx;
}

void cd_forget(struct inode *inode)
{
    spin_lock(&cdev_lock);
    list_del_init(&inode->i_devices);
    inode->i_cdev = NULL;
    spin_unlock(&cdev_lock);
}

static void cdev_purge(struct cdev *cdev)
{
    spin_lock(&cdev_lock);
    while (!list_empty(&cdev->list)) {
        struct inode *inode;
        inode = container_of(cdev->list.next, struct inode, i_devices);
        list_del_init(&inode->i_devices);
        inode->i_cdev = NULL;
    }
    spin_unlock(&cdev_lock);
}

/*
 * Dummy default file-operations: the only thing this does
 * is contain the open that then fills in the correct operations
 * depending on the special file...
 */
const struct file_operations def_chr_fops = {
    .open = chrdev_open,
};

static struct kobject *exact_match(dev_t dev, int *part, void *data)
{
    struct cdev *p = data;
    return &p->kobj;
}

static int exact_lock(dev_t dev, void *data)
{
    struct cdev *p = data;
    return cdev_get(p) ? 0 : -1;
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwxwpj.html