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); }
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; }