mirror of https://gitee.com/openkylin/linux.git
[media] em28xx: properly handle subdev controls
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>
This commit is contained in:
parent
78e51566f0
commit
fb8decfabd
|
@ -1387,6 +1387,27 @@ static int vidioc_queryctrl(struct file *file, void *priv,
|
||||||
return -EINVAL;
|
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,
|
static int vidioc_g_ctrl(struct file *file, void *priv,
|
||||||
struct v4l2_control *ctrl)
|
struct v4l2_control *ctrl)
|
||||||
{
|
{
|
||||||
|
@ -1399,7 +1420,6 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
|
||||||
return rc;
|
return rc;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
|
||||||
|
|
||||||
/* Set an AC97 control */
|
/* Set an AC97 control */
|
||||||
if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
|
if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
|
||||||
rc = ac97_get_ctrl(dev, ctrl);
|
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 */
|
/* It were not an AC97 control. Sends it to the v4l2 dev interface */
|
||||||
if (rc == 1) {
|
if (rc == 1) {
|
||||||
|
if (check_subdev_ctrl(dev, ctrl->id))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
|
v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
|
||||||
rc = 0;
|
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 */
|
/* It isn't an AC97 control. Sends it to the v4l2 dev interface */
|
||||||
if (rc == 1) {
|
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
|
* In the case of non-AC97 volume controls, we still need
|
||||||
* to do some setups at em28xx, in order to mute/unmute
|
* to do some setups at em28xx, in order to mute/unmute
|
||||||
|
|
Loading…
Reference in New Issue