From: Hans Verkuil Date: Sun, 10 Mar 2013 16:12:25 +0000 (-0300) Subject: [media] v4l2-ioctl: check if an ioctl is valid X-Git-Tag: firefly_0821_release~3680^2~618^2~289 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=73f35418a1e921443b5c9f4c58ae70df8b9d1bb6;p=firefly-linux-kernel-4.4.55.git [media] v4l2-ioctl: check if an ioctl is valid Just checking if the op exists isn't correct, you should check if the ioctl is valid (which implies that the op exists as well). One exception is g_std: if current_norm is non-zero, then the g_std op may be absent. This sort of weird behavior is one of the reasons why I am trying to get rid of current_norm. This patch fixes the case where the g/s_std op is set, but these ioctls are disabled. This can happen in drivers supporting multiple models, some that have TV input (and support the STD API) and some that have a sensor (and do not support the STD API). In the latter case qv4l2 would still show the Standards combobox. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 168b51e193cd..72c22fde2b69 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -35,6 +35,8 @@ memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \ 0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field)) +#define is_valid_ioctl(vfd, cmd) test_bit(_IOC_NR(cmd), (vfd)->valid_ioctls) + struct std_descr { v4l2_std_id std; const char *descr; @@ -1005,6 +1007,7 @@ static int v4l_s_priority(const struct v4l2_ioctl_ops *ops, static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { + struct video_device *vfd = video_devdata(file); struct v4l2_input *p = arg; /* @@ -1013,11 +1016,11 @@ static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, * driver. If the driver doesn't support these * for a specific input, it must override these flags. */ - if (ops->vidioc_s_std) + if (is_valid_ioctl(vfd, VIDIOC_S_STD)) p->capabilities |= V4L2_IN_CAP_STD; - if (ops->vidioc_s_dv_preset) + if (is_valid_ioctl(vfd, VIDIOC_S_DV_PRESET)) p->capabilities |= V4L2_IN_CAP_PRESETS; - if (ops->vidioc_s_dv_timings) + if (is_valid_ioctl(vfd, VIDIOC_S_DV_TIMINGS)) p->capabilities |= V4L2_IN_CAP_DV_TIMINGS; return ops->vidioc_enum_input(file, fh, p); @@ -1026,6 +1029,7 @@ static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { + struct video_device *vfd = video_devdata(file); struct v4l2_output *p = arg; /* @@ -1034,11 +1038,11 @@ static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops, * driver. If the driver doesn't support these * for a specific output, it must override these flags. */ - if (ops->vidioc_s_std) + if (is_valid_ioctl(vfd, VIDIOC_S_STD)) p->capabilities |= V4L2_OUT_CAP_STD; - if (ops->vidioc_s_dv_preset) + if (is_valid_ioctl(vfd, VIDIOC_S_DV_PRESET)) p->capabilities |= V4L2_OUT_CAP_PRESETS; - if (ops->vidioc_s_dv_timings) + if (is_valid_ioctl(vfd, VIDIOC_S_DV_TIMINGS)) p->capabilities |= V4L2_OUT_CAP_DV_TIMINGS; return ops->vidioc_enum_output(file, fh, p); @@ -1521,7 +1525,7 @@ static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; p->parm.capture.readbuffers = 2; - if (ops->vidioc_g_std) + if (is_valid_ioctl(vfd, VIDIOC_G_STD) && ops->vidioc_g_std) ret = ops->vidioc_g_std(file, fh, &std); if (ret == 0) v4l2_video_std_frame_period(std, @@ -1881,7 +1885,7 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, return -EINVAL; if (ops->vidioc_enum_freq_bands) return ops->vidioc_enum_freq_bands(file, fh, p); - if (ops->vidioc_g_tuner) { + if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) { struct v4l2_tuner t = { .index = p->tuner, .type = type, @@ -1899,7 +1903,7 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB; return 0; } - if (ops->vidioc_g_modulator) { + if (is_valid_ioctl(vfd, VIDIOC_G_MODULATOR)) { struct v4l2_modulator m = { .index = p->tuner, };