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.verk...@cisco.com>
---
 drivers/media/video/v4l2-ioctl.c |  466 +++++++++++++++++++++++---------------
 1 files changed, 289 insertions(+), 177 deletions(-)

diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 002ce13..6a5062a 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -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);
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to