@@ -542,13 +542,14 @@ static long __video_do_ioctl(struct file *file,
void *fh = file->private_data;
struct v4l2_fh *vfh = NULL;
struct v4l2_format f_copy;
+ bool have_op;
int use_fh_prio = 0;
- long ret = -ENOTTY;
+ long ret = -EINVAL;
if (ops == NULL) {
printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n",
vfd->name);
- return ret;
+ return -ENOTTY;
}
if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
@@ -562,6 +563,275 @@ static long __video_do_ioctl(struct file *file,
use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
}
+ switch (cmd) {
+ case VIDIOC_QUERYCAP:
+ have_op = ops->vidioc_querycap;
+ break;
+ case VIDIOC_G_PRIORITY:
+ have_op = ops->vidioc_g_priority || use_fh_prio;
+ break;
+ case VIDIOC_S_PRIORITY:
+ have_op = ops->vidioc_s_priority || use_fh_prio;
+ break;
+ case VIDIOC_ENUM_FMT:
+ have_op = ops->vidioc_enum_fmt_vid_cap ||
+ ops->vidioc_enum_fmt_vid_out ||
+ ops->vidioc_enum_fmt_vid_cap_mplane ||
+ ops->vidioc_enum_fmt_vid_out_mplane ||
+ ops->vidioc_enum_fmt_vid_overlay ||
+ ops->vidioc_enum_fmt_type_private;
+ break;
+ case VIDIOC_G_FMT:
+ have_op = ops->vidioc_g_fmt_vid_cap ||
+ ops->vidioc_g_fmt_vid_out ||
+ ops->vidioc_g_fmt_vid_cap_mplane ||
+ ops->vidioc_g_fmt_vid_out_mplane ||
+ ops->vidioc_g_fmt_vbi_cap ||
+ ops->vidioc_g_fmt_vid_overlay ||
+ ops->vidioc_g_fmt_vid_out_overlay ||
+ ops->vidioc_g_fmt_vbi_out ||
+ ops->vidioc_g_fmt_sliced_vbi_cap ||
+ ops->vidioc_g_fmt_sliced_vbi_out ||
+ ops->vidioc_g_fmt_type_private;
+ break;
+ case VIDIOC_S_FMT:
+ have_op = ops->vidioc_s_fmt_vid_cap ||
+ ops->vidioc_s_fmt_vid_out ||
+ ops->vidioc_s_fmt_vid_cap_mplane ||
+ ops->vidioc_s_fmt_vid_out_mplane ||
+ ops->vidioc_s_fmt_vbi_cap ||
+ ops->vidioc_s_fmt_vid_overlay ||
+ ops->vidioc_s_fmt_vid_out_overlay ||
+ ops->vidioc_s_fmt_vbi_out ||
+ ops->vidioc_s_fmt_sliced_vbi_cap ||
+ ops->vidioc_s_fmt_sliced_vbi_out ||
+ ops->vidioc_s_fmt_type_private;
+ break;
+ case VIDIOC_TRY_FMT:
+ have_op = ops->vidioc_try_fmt_vid_cap ||
+ ops->vidioc_try_fmt_vid_out ||
+ ops->vidioc_try_fmt_vid_cap_mplane ||
+ ops->vidioc_try_fmt_vid_out_mplane ||
+ ops->vidioc_try_fmt_vbi_cap ||
+ ops->vidioc_try_fmt_vid_overlay ||
+ ops->vidioc_try_fmt_vid_out_overlay ||
+ ops->vidioc_try_fmt_vbi_out ||
+ ops->vidioc_try_fmt_sliced_vbi_cap ||
+ ops->vidioc_try_fmt_sliced_vbi_out ||
+ ops->vidioc_try_fmt_type_private;
+ break;
+ case VIDIOC_REQBUFS:
+ have_op = ops->vidioc_reqbufs;
+ break;
+ case VIDIOC_QUERYBUF:
+ have_op = ops->vidioc_querybuf;
+ break;
+ case VIDIOC_QBUF:
+ have_op = ops->vidioc_qbuf;
+ break;
+ case VIDIOC_DQBUF:
+ have_op = ops->vidioc_dqbuf;
+ break;
+ case VIDIOC_OVERLAY:
+ have_op = ops->vidioc_overlay;
+ break;
+ case VIDIOC_G_FBUF:
+ have_op = ops->vidioc_g_fbuf;
+ break;
+ case VIDIOC_S_FBUF:
+ have_op = ops->vidioc_s_fbuf;
+ break;
+ case VIDIOC_STREAMON:
+ have_op = ops->vidioc_streamon;
+ break;
+ case VIDIOC_STREAMOFF:
+ have_op = ops->vidioc_streamoff;
+ break;
+ case VIDIOC_ENUMSTD:
+ have_op = vfd->tvnorms;
+ break;
+ case VIDIOC_G_STD:
+ have_op = ops->vidioc_g_std || vfd->current_norm;
+ break;
+ case VIDIOC_S_STD:
+ have_op = ops->vidioc_s_std;
+ break;
+ case VIDIOC_QUERYSTD:
+ have_op = ops->vidioc_querystd;
+ break;
+ case VIDIOC_ENUMINPUT:
+ have_op = ops->vidioc_enum_input;
+ break;
+ case VIDIOC_G_INPUT:
+ have_op = ops->vidioc_g_input;
+ break;
+ case VIDIOC_S_INPUT:
+ have_op = ops->vidioc_s_input;
+ break;
+ case VIDIOC_ENUMOUTPUT:
+ have_op = ops->vidioc_enum_output;
+ break;
+ case VIDIOC_G_OUTPUT:
+ have_op = ops->vidioc_g_output;
+ break;
+ case VIDIOC_S_OUTPUT:
+ have_op = ops->vidioc_s_output;
+ break;
+ case VIDIOC_QUERYCTRL:
+ have_op = (vfh && vfh->ctrl_handler) || vfd->ctrl_handler ||
+ ops->vidioc_queryctrl;
+ break;
+ case VIDIOC_G_CTRL:
+ have_op = (vfh && vfh->ctrl_handler) || vfd->ctrl_handler ||
+ ops->vidioc_g_ctrl || ops->vidioc_g_ext_ctrls;
+ break;
+ case VIDIOC_S_CTRL:
+ have_op = (vfh && vfh->ctrl_handler) || vfd->ctrl_handler ||
+ ops->vidioc_s_ctrl || ops->vidioc_s_ext_ctrls;
+ break;
+ case VIDIOC_G_EXT_CTRLS:
+ have_op = (vfh && vfh->ctrl_handler) || vfd->ctrl_handler ||
+ ops->vidioc_g_ext_ctrls;
+ break;
+ case VIDIOC_S_EXT_CTRLS:
+ have_op = (vfh && vfh->ctrl_handler) || vfd->ctrl_handler ||
+ ops->vidioc_s_ext_ctrls;
+ break;
+ case VIDIOC_TRY_EXT_CTRLS:
+ have_op = (vfh && vfh->ctrl_handler) || vfd->ctrl_handler ||
+ ops->vidioc_try_ext_ctrls;
+ break;
+ case VIDIOC_QUERYMENU:
+ have_op = (vfh && vfh->ctrl_handler) || vfd->ctrl_handler ||
+ ops->vidioc_querymenu;
+ break;
+ case VIDIOC_ENUMAUDIO:
+ have_op = ops->vidioc_enumaudio;
+ break;
+ case VIDIOC_G_AUDIO:
+ have_op = ops->vidioc_g_audio;
+ break;
+ case VIDIOC_S_AUDIO:
+ have_op = ops->vidioc_s_audio;
+ break;
+ case VIDIOC_ENUMAUDOUT:
+ have_op = ops->vidioc_enumaudout;
+ break;
+ case VIDIOC_G_AUDOUT:
+ have_op = ops->vidioc_g_audout;
+ break;
+ case VIDIOC_S_AUDOUT:
+ have_op = ops->vidioc_s_audout;
+ break;
+ case VIDIOC_G_MODULATOR:
+ have_op = ops->vidioc_g_modulator;
+ break;
+ case VIDIOC_S_MODULATOR:
+ have_op = ops->vidioc_s_modulator;
+ break;
+ case VIDIOC_G_CROP:
+ have_op = ops->vidioc_g_crop;
+ break;
+ case VIDIOC_S_CROP:
+ have_op = ops->vidioc_s_crop;
+ break;
+ case VIDIOC_CROPCAP:
+ have_op = ops->vidioc_cropcap;
+ break;
+ case VIDIOC_G_JPEGCOMP:
+ have_op = ops->vidioc_g_jpegcomp;
+ break;
+ case VIDIOC_S_JPEGCOMP:
+ have_op = ops->vidioc_g_jpegcomp;
+ break;
+ case VIDIOC_G_ENC_INDEX:
+ have_op = ops->vidioc_g_enc_index;
+ break;
+ case VIDIOC_ENCODER_CMD:
+ have_op = ops->vidioc_encoder_cmd;
+ break;
+ case VIDIOC_TRY_ENCODER_CMD:
+ have_op = ops->vidioc_try_encoder_cmd;
+ break;
+ case VIDIOC_G_PARM:
+ have_op = ops->vidioc_g_parm || vfd->current_norm;
+ break;
+ case VIDIOC_S_PARM:
+ have_op = ops->vidioc_s_parm;
+ break;
+ case VIDIOC_G_TUNER:
+ have_op = ops->vidioc_g_tuner;
+ break;
+ case VIDIOC_S_TUNER:
+ have_op = ops->vidioc_s_tuner;
+ break;
+ case VIDIOC_G_FREQUENCY:
+ have_op = ops->vidioc_g_frequency;
+ break;
+ case VIDIOC_S_FREQUENCY:
+ have_op = ops->vidioc_s_frequency;
+ break;
+ case VIDIOC_G_SLICED_VBI_CAP:
+ have_op = ops->vidioc_g_sliced_vbi_cap;
+ break;
+ case VIDIOC_LOG_STATUS:
+ have_op = ops->vidioc_log_status;
+ break;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_DBG_G_REGISTER:
+ have_op = ops->vidioc_g_register;
+ break;
+ case VIDIOC_DBG_S_REGISTER:
+ have_op = ops->vidioc_s_register;
+ break;
+#endif
+ case VIDIOC_DBG_G_CHIP_IDENT:
+ have_op = ops->vidioc_g_chip_ident;
+ break;
+ case VIDIOC_S_HW_FREQ_SEEK:
+ have_op = ops->vidioc_s_hw_freq_seek;
+ break;
+ case VIDIOC_ENUM_FRAMESIZES:
+ have_op = ops->vidioc_enum_framesizes;
+ break;
+ case VIDIOC_ENUM_FRAMEINTERVALS:
+ have_op = ops->vidioc_enum_frameintervals;
+ break;
+ case VIDIOC_ENUM_DV_PRESETS:
+ have_op = ops->vidioc_enum_dv_presets;
+ break;
+ case VIDIOC_S_DV_PRESET:
+ have_op = ops->vidioc_s_dv_preset;
+ break;
+ case VIDIOC_G_DV_PRESET:
+ have_op = ops->vidioc_g_dv_preset;
+ break;
+ case VIDIOC_QUERY_DV_PRESET:
+ have_op = ops->vidioc_query_dv_preset;
+ break;
+ case VIDIOC_S_DV_TIMINGS:
+ have_op = ops->vidioc_s_dv_timings;
+ break;
+ case VIDIOC_G_DV_TIMINGS:
+ have_op = ops->vidioc_g_dv_timings;
+ break;
+ case VIDIOC_DQEVENT:
+ have_op = ops->vidioc_subscribe_event;
+ break;
+ case VIDIOC_SUBSCRIBE_EVENT:
+ have_op = ops->vidioc_subscribe_event;
+ break;
+ case VIDIOC_UNSUBSCRIBE_EVENT:
+ have_op = ops->vidioc_unsubscribe_event;
+ break;
+ default:
+ have_op = ops->vidioc_default;
+ break;
+ }
+
+ if (!have_op)
+ return -ENOTTY;
+
if (use_fh_prio) {
switch (cmd) {
case VIDIOC_S_CTRL:
@@ -603,9 +873,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_capability *cap = (struct v4l2_capability *)arg;
- if (!ops->vidioc_querycap)
- break;
-
cap->version = LINUX_VERSION_CODE;
ret = ops->vidioc_querycap(file, fh, cap);
if (!ret)
@@ -625,7 +892,7 @@ static long __video_do_ioctl(struct file *file,
if (ops->vidioc_g_priority) {
ret = ops->vidioc_g_priority(file, fh, p);
- } else if (use_fh_prio) {
+ } else {
*p = v4l2_prio_max(&vfd->v4l2_dev->prio);
ret = 0;
}
@@ -637,8 +904,6 @@ static long __video_do_ioctl(struct file *file,
{
enum v4l2_priority *p = arg;
- if (!ops->vidioc_s_priority && !use_fh_prio)
- break;
dbgarg(cmd, "setting priority to %d\n", *p);
if (ops->vidioc_s_priority)
ret = ops->vidioc_s_priority(file, fh, *p);
@@ -1101,8 +1366,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_requestbuffers *p = arg;
- if (!ops->vidioc_reqbufs)
- break;
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -1121,8 +1384,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_buffer *p = arg;
- if (!ops->vidioc_querybuf)
- break;
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -1136,8 +1397,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_buffer *p = arg;
- if (!ops->vidioc_qbuf)
- break;
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -1151,8 +1410,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_buffer *p = arg;
- if (!ops->vidioc_dqbuf)
- break;
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -1166,8 +1423,6 @@ static long __video_do_ioctl(struct file *file,
{
int *i = arg;
- if (!ops->vidioc_overlay)
- break;
dbgarg(cmd, "value=%d\n", *i);
ret = ops->vidioc_overlay(file, fh, *i);
break;
@@ -1176,8 +1431,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_framebuffer *p = arg;
- if (!ops->vidioc_g_fbuf)
- break;
ret = ops->vidioc_g_fbuf(file, fh, arg);
if (!ret) {
dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
@@ -1191,8 +1444,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_framebuffer *p = arg;
- if (!ops->vidioc_s_fbuf)
- break;
dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
p->capability, p->flags, (unsigned long)p->base);
v4l_print_pix_fmt(vfd, &p->fmt);
@@ -1203,8 +1454,6 @@ static long __video_do_ioctl(struct file *file,
{
enum v4l2_buf_type i = *(int *)arg;
- if (!ops->vidioc_streamon)
- break;
dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
ret = ops->vidioc_streamon(file, fh, i);
break;
@@ -1213,8 +1462,6 @@ static long __video_do_ioctl(struct file *file,
{
enum v4l2_buf_type i = *(int *)arg;
- if (!ops->vidioc_streamoff)
- break;
dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
ret = ops->vidioc_streamoff(file, fh, i);
break;
@@ -1266,10 +1513,8 @@ static long __video_do_ioctl(struct file *file,
/* Calls the specific handler */
if (ops->vidioc_g_std)
ret = ops->vidioc_g_std(file, fh, id);
- else if (vfd->current_norm)
- *id = vfd->current_norm;
else
- ret = -EINVAL;
+ *id = vfd->current_norm;
if (!ret)
dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
@@ -1286,10 +1531,7 @@ static long __video_do_ioctl(struct file *file,
break;
/* Calls the specific handler */
- if (ops->vidioc_s_std)
- ret = ops->vidioc_s_std(file, fh, &norm);
- else
- ret = -EINVAL;
+ ret = ops->vidioc_s_std(file, fh, &norm);
/* Updates standard information */
if (ret >= 0)
@@ -1300,8 +1542,6 @@ static long __video_do_ioctl(struct file *file,
{
v4l2_std_id *p = arg;
- if (!ops->vidioc_querystd)
- break;
ret = ops->vidioc_querystd(file, fh, arg);
if (!ret)
dbgarg(cmd, "detected std=%08Lx\n",
@@ -1327,9 +1567,6 @@ static long __video_do_ioctl(struct file *file,
if (ops->vidioc_s_dv_timings)
p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
- if (!ops->vidioc_enum_input)
- break;
-
ret = ops->vidioc_enum_input(file, fh, p);
if (!ret)
dbgarg(cmd, "index=%d, name=%s, type=%d, "
@@ -1345,8 +1582,6 @@ static long __video_do_ioctl(struct file *file,
{
unsigned int *i = arg;
- if (!ops->vidioc_g_input)
- break;
ret = ops->vidioc_g_input(file, fh, i);
if (!ret)
dbgarg(cmd, "value=%d\n", *i);
@@ -1356,8 +1591,6 @@ static long __video_do_ioctl(struct file *file,
{
unsigned int *i = arg;
- if (!ops->vidioc_s_input)
- break;
dbgarg(cmd, "value=%d\n", *i);
ret = ops->vidioc_s_input(file, fh, *i);
break;
@@ -1368,9 +1601,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_output *p = arg;
- if (!ops->vidioc_enum_output)
- break;
-
/*
* We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
* CAP_STD here based on ioctl handler provided by the
@@ -1397,8 +1627,6 @@ static long __video_do_ioctl(struct file *file,
{
unsigned int *i = arg;
- if (!ops->vidioc_g_output)
- break;
ret = ops->vidioc_g_output(file, fh, i);
if (!ret)
dbgarg(cmd, "value=%d\n", *i);
@@ -1408,8 +1636,6 @@ static long __video_do_ioctl(struct file *file,
{
unsigned int *i = arg;
- if (!ops->vidioc_s_output)
- break;
dbgarg(cmd, "value=%d\n", *i);
ret = ops->vidioc_s_output(file, fh, *i);
break;
@@ -1424,10 +1650,8 @@ static long __video_do_ioctl(struct file *file,
ret = v4l2_queryctrl(vfh->ctrl_handler, p);
else if (vfd->ctrl_handler)
ret = v4l2_queryctrl(vfd->ctrl_handler, p);
- else if (ops->vidioc_queryctrl)
- ret = ops->vidioc_queryctrl(file, fh, p);
else
- break;
+ ret = ops->vidioc_queryctrl(file, fh, p);
if (!ret)
dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, "
"step=%d, default=%d, flags=0x%08x\n",
@@ -1448,7 +1672,7 @@ static long __video_do_ioctl(struct file *file,
ret = v4l2_g_ctrl(vfd->ctrl_handler, p);
else if (ops->vidioc_g_ctrl)
ret = ops->vidioc_g_ctrl(file, fh, p);
- else if (ops->vidioc_g_ext_ctrls) {
+ else {
struct v4l2_ext_controls ctrls;
struct v4l2_ext_control ctrl;
@@ -1462,8 +1686,7 @@ static long __video_do_ioctl(struct file *file,
if (ret == 0)
p->value = ctrl.value;
}
- } else
- break;
+ }
if (!ret)
dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
else
@@ -1476,10 +1699,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_ext_controls ctrls;
struct v4l2_ext_control ctrl;
- if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
- !ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
- break;
-
dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
if (vfh && vfh->ctrl_handler) {
@@ -1494,8 +1713,6 @@ static long __video_do_ioctl(struct file *file,
ret = ops->vidioc_s_ctrl(file, fh, p);
break;
}
- if (!ops->vidioc_s_ext_ctrls)
- break;
ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
ctrls.count = 1;
@@ -1515,7 +1732,7 @@ static long __video_do_ioctl(struct file *file,
ret = v4l2_g_ext_ctrls(vfh->ctrl_handler, p);
else if (vfd->ctrl_handler)
ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
- else if (ops->vidioc_g_ext_ctrls && check_ext_ctrls(p, 0))
+ else if (check_ext_ctrls(p, 0))
ret = ops->vidioc_g_ext_ctrls(file, fh, p);
else
break;
@@ -1527,9 +1744,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_ext_controls *p = arg;
p->error_idx = p->count;
- if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
- !ops->vidioc_s_ext_ctrls)
- break;
v4l_print_ext_ctrls(cmd, vfd, p, 1);
if (vfh && vfh->ctrl_handler)
ret = v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p);
@@ -1544,9 +1758,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_ext_controls *p = arg;
p->error_idx = p->count;
- if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
- !ops->vidioc_try_ext_ctrls)
- break;
v4l_print_ext_ctrls(cmd, vfd, p, 1);
if (vfh && vfh->ctrl_handler)
ret = v4l2_try_ext_ctrls(vfh->ctrl_handler, p);
@@ -1564,10 +1775,8 @@ static long __video_do_ioctl(struct file *file,
ret = v4l2_querymenu(vfh->ctrl_handler, p);
else if (vfd->ctrl_handler)
ret = v4l2_querymenu(vfd->ctrl_handler, p);
- else if (ops->vidioc_querymenu)
- ret = ops->vidioc_querymenu(file, fh, p);
else
- break;
+ ret = ops->vidioc_querymenu(file, fh, p);
if (!ret)
dbgarg(cmd, "id=0x%x, index=%d, name=%s\n",
p->id, p->index, p->name);
@@ -1581,8 +1790,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audio *p = arg;
- if (!ops->vidioc_enumaudio)
- break;
ret = ops->vidioc_enumaudio(file, fh, p);
if (!ret)
dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
@@ -1596,9 +1803,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audio *p = arg;
- if (!ops->vidioc_g_audio)
- break;
-
ret = ops->vidioc_g_audio(file, fh, p);
if (!ret)
dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
@@ -1612,8 +1816,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audio *p = arg;
- if (!ops->vidioc_s_audio)
- break;
dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
"mode=0x%x\n", p->index, p->name,
p->capability, p->mode);
@@ -1624,8 +1826,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audioout *p = arg;
- if (!ops->vidioc_enumaudout)
- break;
dbgarg(cmd, "Enum for index=%d\n", p->index);
ret = ops->vidioc_enumaudout(file, fh, p);
if (!ret)
@@ -1638,9 +1838,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audioout *p = arg;
- if (!ops->vidioc_g_audout)
- break;
-
ret = ops->vidioc_g_audout(file, fh, p);
if (!ret)
dbgarg2("index=%d, name=%s, capability=%d, "
@@ -1652,8 +1849,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audioout *p = arg;
- if (!ops->vidioc_s_audout)
- break;
dbgarg(cmd, "index=%d, name=%s, capability=%d, "
"mode=%d\n", p->index, p->name,
p->capability, p->mode);
@@ -1665,8 +1860,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_modulator *p = arg;
- if (!ops->vidioc_g_modulator)
- break;
ret = ops->vidioc_g_modulator(file, fh, p);
if (!ret)
dbgarg(cmd, "index=%d, name=%s, "
@@ -1681,8 +1874,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_modulator *p = arg;
- if (!ops->vidioc_s_modulator)
- break;
dbgarg(cmd, "index=%d, name=%s, capability=%d, "
"rangelow=%d, rangehigh=%d, txsubchans=%d\n",
p->index, p->name, p->capability, p->rangelow,
@@ -1694,9 +1885,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_crop *p = arg;
- if (!ops->vidioc_g_crop)
- break;
-
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
ret = ops->vidioc_g_crop(file, fh, p);
if (!ret)
@@ -1707,8 +1895,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_crop *p = arg;
- if (!ops->vidioc_s_crop)
- break;
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
dbgrect(vfd, "", &p->c);
ret = ops->vidioc_s_crop(file, fh, p);
@@ -1719,9 +1905,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_cropcap *p = arg;
/*FIXME: Should also show v4l2_fract pixelaspect */
- if (!ops->vidioc_cropcap)
- break;
-
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
ret = ops->vidioc_cropcap(file, fh, p);
if (!ret) {
@@ -1734,9 +1917,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_jpegcompression *p = arg;
- if (!ops->vidioc_g_jpegcomp)
- break;
-
ret = ops->vidioc_g_jpegcomp(file, fh, p);
if (!ret)
dbgarg(cmd, "quality=%d, APPn=%d, "
@@ -1750,21 +1930,17 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_jpegcompression *p = arg;
- if (!ops->vidioc_g_jpegcomp)
- break;
dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
"COM_len=%d, jpeg_markers=%d\n",
p->quality, p->APPn, p->APP_len,
p->COM_len, p->jpeg_markers);
- ret = ops->vidioc_s_jpegcomp(file, fh, p);
+ ret = ops->vidioc_s_jpegcomp(file, fh, p);
break;
}
case VIDIOC_G_ENC_INDEX:
{
struct v4l2_enc_idx *p = arg;
- if (!ops->vidioc_g_enc_index)
- break;
ret = ops->vidioc_g_enc_index(file, fh, p);
if (!ret)
dbgarg(cmd, "entries=%d, entries_cap=%d\n",
@@ -1775,8 +1951,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_encoder_cmd *p = arg;
- if (!ops->vidioc_encoder_cmd)
- break;
ret = ops->vidioc_encoder_cmd(file, fh, p);
if (!ret)
dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1786,8 +1960,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_encoder_cmd *p = arg;
- if (!ops->vidioc_try_encoder_cmd)
- break;
ret = ops->vidioc_try_encoder_cmd(file, fh, p);
if (!ret)
dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1825,8 +1997,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_streamparm *p = arg;
- if (!ops->vidioc_s_parm)
- break;
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -1839,9 +2009,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_tuner *p = arg;
- if (!ops->vidioc_g_tuner)
- break;
-
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
ret = ops->vidioc_g_tuner(file, fh, p);
@@ -1860,8 +2027,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_tuner *p = arg;
- if (!ops->vidioc_s_tuner)
- break;
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd, "index=%d, name=%s, type=%d, "
@@ -1879,9 +2044,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_frequency *p = arg;
- if (!ops->vidioc_g_frequency)
- break;
-
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
ret = ops->vidioc_g_frequency(file, fh, p);
@@ -1894,8 +2056,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_frequency *p = arg;
- if (!ops->vidioc_s_frequency)
- break;
dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
p->tuner, p->type, p->frequency);
ret = ops->vidioc_s_frequency(file, fh, p);
@@ -1905,9 +2065,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_sliced_vbi_cap *p = arg;
- if (!ops->vidioc_g_sliced_vbi_cap)
- break;
-
/* Clear up to type, everything after type is zerod already */
memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
@@ -1919,8 +2076,6 @@ static long __video_do_ioctl(struct file *file,
}
case VIDIOC_LOG_STATUS:
{
- if (!ops->vidioc_log_status)
- break;
ret = ops->vidioc_log_status(file, fh);
break;
}
@@ -1929,24 +2084,20 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dbg_register *p = arg;
- if (ops->vidioc_g_register) {
- if (!capable(CAP_SYS_ADMIN))
- ret = -EPERM;
- else
- ret = ops->vidioc_g_register(file, fh, p);
- }
+ if (!capable(CAP_SYS_ADMIN))
+ ret = -EPERM;
+ else
+ ret = ops->vidioc_g_register(file, fh, p);
break;
}
case VIDIOC_DBG_S_REGISTER:
{
struct v4l2_dbg_register *p = arg;
- if (ops->vidioc_s_register) {
- if (!capable(CAP_SYS_ADMIN))
- ret = -EPERM;
- else
- ret = ops->vidioc_s_register(file, fh, p);
- }
+ if (!capable(CAP_SYS_ADMIN))
+ ret = -EPERM;
+ else
+ ret = ops->vidioc_s_register(file, fh, p);
break;
}
#endif
@@ -1954,8 +2105,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dbg_chip_ident *p = arg;
- if (!ops->vidioc_g_chip_ident)
- break;
p->ident = V4L2_IDENT_NONE;
p->revision = 0;
ret = ops->vidioc_g_chip_ident(file, fh, p);
@@ -1968,8 +2117,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_hw_freq_seek *p = arg;
enum v4l2_tuner_type type;
- if (!ops->vidioc_s_hw_freq_seek)
- break;
type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd,
@@ -1985,9 +2132,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_frmsizeenum *p = arg;
- if (!ops->vidioc_enum_framesizes)
- break;
-
ret = ops->vidioc_enum_framesizes(file, fh, p);
dbgarg(cmd,
"index=%d, pixelformat=%c%c%c%c, type=%d ",
@@ -2021,9 +2165,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_frmivalenum *p = arg;
- if (!ops->vidioc_enum_frameintervals)
- break;
-
ret = ops->vidioc_enum_frameintervals(file, fh, p);
dbgarg(cmd,
"index=%d, pixelformat=%d, width=%d, height=%d, type=%d ",
@@ -2056,9 +2197,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_enum_preset *p = arg;
- if (!ops->vidioc_enum_dv_presets)
- break;
-
ret = ops->vidioc_enum_dv_presets(file, fh, p);
if (!ret)
dbgarg(cmd,
@@ -2072,9 +2210,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_preset *p = arg;
- if (!ops->vidioc_s_dv_preset)
- break;
-
dbgarg(cmd, "preset=%d\n", p->preset);
ret = ops->vidioc_s_dv_preset(file, fh, p);
break;
@@ -2083,9 +2218,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_preset *p = arg;
- if (!ops->vidioc_g_dv_preset)
- break;
-
ret = ops->vidioc_g_dv_preset(file, fh, p);
if (!ret)
dbgarg(cmd, "preset=%d\n", p->preset);
@@ -2095,9 +2227,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_preset *p = arg;
- if (!ops->vidioc_query_dv_preset)
- break;
-
ret = ops->vidioc_query_dv_preset(file, fh, p);
if (!ret)
dbgarg(cmd, "preset=%d\n", p->preset);
@@ -2107,9 +2236,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_timings *p = arg;
- if (!ops->vidioc_s_dv_timings)
- break;
-
switch (p->type) {
case V4L2_DV_BT_656_1120:
dbgarg2("bt-656/1120:interlaced=%d, pixelclock=%lld,"
@@ -2137,9 +2263,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_timings *p = arg;
- if (!ops->vidioc_g_dv_timings)
- break;
-
ret = ops->vidioc_g_dv_timings(file, fh, p);
if (!ret) {
switch (p->type) {
@@ -2171,9 +2294,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_event *ev = arg;
- if (!ops->vidioc_subscribe_event)
- break;
-
ret = v4l2_event_dequeue(fh, ev, file->f_flags & O_NONBLOCK);
if (ret < 0) {
dbgarg(cmd, "no pending events?");
@@ -2190,9 +2310,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_event_subscription *sub = arg;
- if (!ops->vidioc_subscribe_event)
- break;
-
ret = ops->vidioc_subscribe_event(fh, sub);
if (ret < 0) {
dbgarg(cmd, "failed, ret=%ld", ret);
@@ -2205,9 +2322,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_event_subscription *sub = arg;
- if (!ops->vidioc_unsubscribe_event)
- break;
-
ret = ops->vidioc_unsubscribe_event(fh, sub);
if (ret < 0) {
dbgarg(cmd, "failed, ret=%ld", ret);
@@ -2220,8 +2334,6 @@ static long __video_do_ioctl(struct file *file,
{
bool valid_prio = true;
- if (!ops->vidioc_default)
- break;
if (use_fh_prio)
valid_prio = v4l2_prio_check(vfd->prio, vfh->prio) >= 0;
ret = ops->vidioc_default(file, fh, valid_prio, cmd, arg);
Hi all, While converting v4l2-compliance to correctly handle ENOTTY errors I found several regressions in v4l2-ioctl.c: 1) VIDIOC_ENUM/G/S/TRY_FMT would return -ENOTTY if the op for the particular format type was not set, even though the op for other types might have been present. In such a case -EINVAL should have been returned. 2) The priority check could cause -EBUSY or -EINVAL to be returned instead of -ENOTTY if the corresponding ioctl was unsupported. 3) Certain ioctls that have an internal implementation (ENUMSTD, G_STD, S_STD, G_PARM and the extended control ioctls) could return -EINVAL when -ENOTTY should have been returned or vice versa. I first tried to fix this by adding extra code for each affected ioctl, but that made the code rather ugly. So I ended up with this code that first checks whether a certain ioctl is supported or not and returns -ENOTTY if not. Comments? Hans Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> --- drivers/media/video/v4l2-ioctl.c | 466 +++++++++++++++++++++++--------------- 1 files changed, 289 insertions(+), 177 deletions(-)