aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx/em28xx-video.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-video.c')
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index f34d524ccb09..a83131bd00b2 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1387,6 +1387,27 @@ static int vidioc_queryctrl(struct file *file, void *priv,
1387 return -EINVAL; 1387 return -EINVAL;
1388} 1388}
1389 1389
1390/*
1391 * FIXME: This is an indirect way to check if a control exists at a
1392 * subdev. Instead of that hack, maybe the better would be to change all
1393 * subdevs to return -ENOIOCTLCMD, if an ioctl is not supported.
1394 */
1395static int check_subdev_ctrl(struct em28xx *dev, int id)
1396{
1397 struct v4l2_queryctrl qc;
1398
1399 memset(&qc, 0, sizeof(qc));
1400 qc.id = id;
1401
1402 /* enumerate V4L2 device controls */
1403 v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, &qc);
1404
1405 if (qc.type)
1406 return 0;
1407 else
1408 return -EINVAL;
1409}
1410
1390static int vidioc_g_ctrl(struct file *file, void *priv, 1411static int vidioc_g_ctrl(struct file *file, void *priv,
1391 struct v4l2_control *ctrl) 1412 struct v4l2_control *ctrl)
1392{ 1413{
@@ -1399,7 +1420,6 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
1399 return rc; 1420 return rc;
1400 rc = 0; 1421 rc = 0;
1401 1422
1402
1403 /* Set an AC97 control */ 1423 /* Set an AC97 control */
1404 if (dev->audio_mode.ac97 != EM28XX_NO_AC97) 1424 if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
1405 rc = ac97_get_ctrl(dev, ctrl); 1425 rc = ac97_get_ctrl(dev, ctrl);
@@ -1408,6 +1428,9 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
1408 1428
1409 /* It were not an AC97 control. Sends it to the v4l2 dev interface */ 1429 /* It were not an AC97 control. Sends it to the v4l2 dev interface */
1410 if (rc == 1) { 1430 if (rc == 1) {
1431 if (check_subdev_ctrl(dev, ctrl->id))
1432 return -EINVAL;
1433
1411 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); 1434 v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
1412 rc = 0; 1435 rc = 0;
1413 } 1436 }
@@ -1434,8 +1457,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
1434 1457
1435 /* It isn't an AC97 control. Sends it to the v4l2 dev interface */ 1458 /* It isn't an AC97 control. Sends it to the v4l2 dev interface */
1436 if (rc == 1) { 1459 if (rc == 1) {
1437 rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); 1460 rc = check_subdev_ctrl(dev, ctrl->id);
1438 1461 if (!rc)
1462 v4l2_device_call_all(&dev->v4l2_dev, 0,
1463 core, s_ctrl, ctrl);
1439 /* 1464 /*
1440 * In the case of non-AC97 volume controls, we still need 1465 * In the case of non-AC97 volume controls, we still need
1441 * to do some setups at em28xx, in order to mute/unmute 1466 * to do some setups at em28xx, in order to mute/unmute
@@ -1452,7 +1477,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
1452 rc = em28xx_audio_analog_set(dev); 1477 rc = em28xx_audio_analog_set(dev);
1453 } 1478 }
1454 } 1479 }
1455 return rc; 1480 return (rc < 0) ? rc : 0;
1456} 1481}
1457 1482
1458static int vidioc_g_tuner(struct file *file, void *priv, 1483static int vidioc_g_tuner(struct file *file, void *priv,