Esempio n. 1
0
int a4l_check_cmddesc(struct a4l_device_context * cxt, struct a4l_cmd_desc * desc)
{
    struct a4l_device *dev = a4l_get_dev(cxt);
    struct a4l_subdevice *subd;

    if (desc->idx_subd >= dev->transfer.nb_subd) {
        __a4l_err("a4l_check_cmddesc: "
                  "subdevice index out of range (idx=%u)\n",
                  desc->idx_subd);
        return -EINVAL;
    }

    subd = dev->transfer.subds[desc->idx_subd];

    if ((subd->flags & A4L_SUBD_TYPES) == A4L_SUBD_UNUSED) {
        __a4l_err("a4l_check_cmddesc: "
                  "subdevice type incoherent\n");
        return -EIO;
    }

    if (!(subd->flags & A4L_SUBD_CMD)) {
        __a4l_err("a4l_check_cmddesc: operation not supported, "
                  "synchronous only subdevice\n");
        return -EIO;
    }

    if (test_bit(A4L_SUBD_BUSY, &subd->status)) {
        __a4l_err("a4l_check_cmddesc: subdevice busy\n");
        return -EBUSY;
    }

    return a4l_check_chanlist(dev->transfer.subds[desc->idx_subd],
                              desc->nb_chan, desc->chan_descs);
}
Esempio n. 2
0
int a4l_do_insn(a4l_cxt_t * cxt, a4l_kinsn_t * dsc)
{
	int ret;
	a4l_subd_t *subd;
	a4l_dev_t *dev = a4l_get_dev(cxt);
	int (*hdlr) (a4l_subd_t *, a4l_kinsn_t *) = NULL;

	/* Checks the subdevice index */
	if (dsc->idx_subd >= dev->transfer.nb_subd) {
		__a4l_err("a4l_do_insn: "
			  "subdevice index out of range (idx=%d)\n",
			  dsc->idx_subd);
		return -EINVAL;
	}

	/* Recovers pointers on the proper subdevice */
	subd = dev->transfer.subds[dsc->idx_subd];

	/* Checks the subdevice's characteristics */
	if ((subd->flags & A4L_SUBD_TYPES) == A4L_SUBD_UNUSED) {
		__a4l_err("a4l_do_insn: wrong subdevice selected\n");
		return -EINVAL;
	}

	/* Checks the channel descriptor */
	ret = a4l_check_chanlist(dev->transfer.subds[dsc->idx_subd],
				 1, &dsc->chan_desc);
	if (ret < 0)
		return ret;

	/* Choose the proper handler, we can check the pointer because
	   the subdevice was memset to 0 at allocation time */
	switch (dsc->type) {
	case A4L_INSN_READ:
		hdlr = subd->insn_read;
		break;
	case A4L_INSN_WRITE:
		hdlr = subd->insn_write;
		break;
	case A4L_INSN_BITS:
		hdlr = subd->insn_bits;
		break;
	case A4L_INSN_CONFIG:
		hdlr = subd->insn_config;
		break;
	default:
		ret = -EINVAL;
	}

	/* We check the instruction type */
	if (ret < 0)
		return ret;

	/* We check whether a handler is available */
	if (hdlr == NULL)
		return -ENOSYS;

	/* Prevents the subdevice from being used during 
	   the following operations */
	ret = a4l_reserve_transfer(cxt, dsc->idx_subd);
	if (ret < 0)
		goto out_do_insn;

	/* Let's the driver-specific code perform the instruction */
	ret = hdlr(subd, dsc);

	if (ret < 0) 
		__a4l_err("a4l_do_insn: "
			  "execution of the instruction failed (err=%d)\n",
			  ret);

out_do_insn:

	/* Releases the subdevice from its reserved state */
	a4l_cancel_transfer(cxt, dsc->idx_subd);

	return ret;
}