[media] em28xx: properly handle subdev controls
authorMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 22 Feb 2011 04:00:58 +0000 (01:00 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 21 Mar 2011 23:32:04 +0000 (20:32 -0300)
Subdev controls return codes are evil, as they return -EINVAL to mean
both unsupported and invalid arguments. Due to that, we need to use a
trick to identify what controls are supported by a subdev.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/em28xx/em28xx-video.c

index 1ddd3ee22812a6fc415d2aedd451651d9db90d78..a83131bd00b2b13e2808b06386fb6a816b3b60e7 100644 (file)
@@ -1387,6 +1387,27 @@ static int vidioc_queryctrl(struct file *file, void *priv,
                return -EINVAL;
 }
 
+/*
+ * FIXME: This is an indirect way to check if a control exists at a
+ * subdev. Instead of that hack, maybe the better would be to change all
+ * subdevs to return -ENOIOCTLCMD, if an ioctl is not supported.
+ */
+static int check_subdev_ctrl(struct em28xx *dev, int id)
+{
+       struct v4l2_queryctrl qc;
+
+       memset(&qc, 0, sizeof(qc));
+       qc.id = id;
+
+       /* enumerate V4L2 device controls */
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, &qc);
+
+       if (qc.type)
+               return 0;
+       else
+               return -EINVAL;
+}
+
 static int vidioc_g_ctrl(struct file *file, void *priv,
                                struct v4l2_control *ctrl)
 {
@@ -1399,7 +1420,6 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
                return rc;
        rc = 0;
 
-
        /* Set an AC97 control */
        if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
                rc = ac97_get_ctrl(dev, ctrl);
@@ -1408,6 +1428,9 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 
        /* It were not an AC97 control. Sends it to the v4l2 dev interface */
        if (rc == 1) {
+               if (check_subdev_ctrl(dev, ctrl->id))
+                       return -EINVAL;
+
                v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
                rc = 0;
        }
@@ -1434,8 +1457,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 
        /* It isn't an AC97 control. Sends it to the v4l2 dev interface */
        if (rc == 1) {
-               rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
-
+               rc = check_subdev_ctrl(dev, ctrl->id);
+               if (!rc)
+                       v4l2_device_call_all(&dev->v4l2_dev, 0,
+                                            core, s_ctrl, ctrl);
                /*
                 * In the case of non-AC97 volume controls, we still need
                 * to do some setups at em28xx, in order to mute/unmute