Пример #1
0
int a4l_close(struct rtdm_dev_context *context, rtdm_user_info_t * user_info)
{
	int err;
	a4l_cxt_t *cxt = (a4l_cxt_t *)rtdm_context_to_private(context);

	/* Cancel the maybe occuring asynchronous transfer */
	err = a4l_cancel_buffer(cxt);
	if (err < 0) {
		__a4l_err("close: unable to stop the asynchronous transfer\n");
		return err;
	}

	/* Free the buffer which was linked with this context and... */
	a4l_free_buffer(cxt->buffer);

	/* ...free the other buffer resources (sync) and... */
	a4l_cleanup_buffer(cxt->buffer);

	/* ...free the structure */
	rtdm_free(cxt->buffer);

	return 0;
}
Пример #2
0
int a4l_ioctl_cmd(struct a4l_device_context * ctx, void *arg)
{
    int ret = 0, simul_flag = 0;
    struct a4l_cmd_desc *cmd_desc = NULL;
    struct a4l_device *dev = a4l_get_dev(ctx);
    unsigned int *chan_descs, *tmp;
    struct a4l_subdevice *subd;

    /* The command launching cannot be done in real-time because
       of some possible buffer allocations in the drivers */
    if (rtdm_in_rt_context())
        return -ENOSYS;

    /* Basically check the device */
    if (!test_bit(A4L_DEV_ATTACHED_NR, &dev->flags)) {
        __a4l_err("a4l_ioctl_cmd: cannot command "
                  "an unattached device\n");
        return -EINVAL;
    }

    /* Allocates the command */
    cmd_desc = (struct a4l_cmd_desc *) rtdm_malloc(sizeof(struct a4l_cmd_desc));
    if (cmd_desc == NULL)
        return -ENOMEM;
    memset(cmd_desc, 0, sizeof(struct a4l_cmd_desc));

    /* Gets the command */
    ret = a4l_fill_cmddesc(ctx, cmd_desc, &chan_descs, arg);
    if (ret != 0)
        goto out_ioctl_cmd;

    /* Checks the command */
    ret = a4l_check_cmddesc(ctx, cmd_desc);
    if (ret != 0)
        goto out_ioctl_cmd;

    ret = a4l_check_generic_cmdcnt(cmd_desc);
    if (ret != 0)
        goto out_ioctl_cmd;

    ret = a4l_check_specific_cmdcnt(ctx, cmd_desc);
    if (ret != 0)
        goto out_ioctl_cmd;

    __a4l_dbg(1, core_dbg,"1st cmd checks passed\n");
    subd = dev->transfer.subds[cmd_desc->idx_subd];

    /* Tests the command with the cmdtest function */
    if (cmd_desc->flags & A4L_CMD_SIMUL) {
        simul_flag = 1;

        if (!subd->do_cmdtest) {
            __a4l_err("a4l_ioctl_cmd: driver's cmd_test NULL\n");
            ret = -EINVAL;
            goto out_ioctl_cmd;
        }

        ret = subd->do_cmdtest(subd, cmd_desc);
        if (ret != 0) {
            __a4l_err("a4l_ioctl_cmd: driver's cmd_test failed\n");
            goto out_ioctl_cmd;
        }
        __a4l_dbg(1, core_dbg, "driver's cmd checks passed\n");
        goto out_ioctl_cmd;
    }


    /* Gets the transfer system ready */
    ret = a4l_setup_buffer(ctx, cmd_desc);
    if (ret < 0)
        goto out_ioctl_cmd;

    /* Eventually launches the command */
    ret = subd->do_cmd(subd, cmd_desc);

    if (ret != 0) {
        a4l_cancel_buffer(ctx);
        goto out_ioctl_cmd;
    }

out_ioctl_cmd:

    if (simul_flag) {
        /* copy the kernel based descriptor */
        tmp = cmd_desc->chan_descs;
        /* return the user based descriptor */
        cmd_desc->chan_descs = chan_descs;
        rtdm_safe_copy_to_user(rtdm_private_to_fd(ctx), arg, cmd_desc,
                               sizeof(struct a4l_cmd_desc));
        /* make sure we release the memory associated to the kernel */
        cmd_desc->chan_descs = tmp;

    }

    if (ret != 0 || simul_flag == 1) {
        a4l_free_cmddesc(cmd_desc);
        rtdm_free(cmd_desc);
    }

    return ret;
}