The patch number 8112 was added via Hans Verkuil <[EMAIL PROTECTED]> to http://linuxtv.org/hg/v4l-dvb master development tree.
Kernel patches in this development tree may be modified to be backward compatible with older kernels. Compatibility modifications will be removed before inclusion into the mainstream Kernel If anyone has any objections, please let us know by sending a message to: [EMAIL PROTECTED] ------ From: Hans Verkuil <[EMAIL PROTECTED]> videodev: improve extended control support in video_ioctl2() - add sanity checks for the extended controls argument. - if the driver only supports extended controls, then convert old-style controls to an extended control callback. Signed-off-by: Hans Verkuil <[EMAIL PROTECTED]> --- linux/drivers/media/video/videodev.c | 91 +++++++++++++++++++++------ 1 file changed, 74 insertions(+), 17 deletions(-) diff -r 6742fedbc990 -r fae200f98d47 linux/drivers/media/video/videodev.c --- a/linux/drivers/media/video/videodev.c Wed Jun 25 08:00:17 2008 +0200 +++ b/linux/drivers/media/video/videodev.c Wed Jun 25 08:29:01 2008 +0200 @@ -748,6 +748,29 @@ static inline void v4l_print_ext_ctrls(u printk(KERN_CONT "\n"); }; +static inline int check_ext_ctrls(struct v4l2_ext_controls *c) +{ + __u32 i; + + /* zero the reserved fields */ + c->reserved[0] = c->reserved[1] = 0; + for (i = 0; i < c->count; i++) { + c->controls[i].reserved2[0] = 0; + c->controls[i].reserved2[1] = 0; + } + /* V4L2_CID_PRIVATE_BASE cannot be used as control class + * when using extended controls. */ + if (c->ctrl_class == V4L2_CID_PRIVATE_BASE) + return 0; + /* Check that all controls are from the same control class. */ + for (i = 0; i < c->count; i++) { + if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) { + c->error_idx = i; + return 0; + } + } + return 1; +} static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type) { @@ -1430,10 +1453,24 @@ static int __video_do_ioctl(struct inode { struct v4l2_control *p = arg; - if (!vfd->vidioc_g_ctrl) - break; - - ret = vfd->vidioc_g_ctrl(file, fh, p); + if (vfd->vidioc_g_ctrl) + ret = vfd->vidioc_g_ctrl(file, fh, p); + else if (vfd->vidioc_g_ext_ctrls) { + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ctrl; + + ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); + ctrls.count = 1; + ctrls.controls = &ctrl; + ctrl.id = p->id; + ctrl.value = p->value; + if (check_ext_ctrls(&ctrls)) { + ret = vfd->vidioc_g_ext_ctrls(file, fh, &ctrls); + if (ret == 0) + p->value = ctrl.value; + } + } else + break; if (!ret) dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value); else @@ -1443,21 +1480,39 @@ static int __video_do_ioctl(struct inode case VIDIOC_S_CTRL: { struct v4l2_control *p = arg; - - if (!vfd->vidioc_s_ctrl) - break; + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ctrl; + + if (!vfd->vidioc_s_ctrl && !vfd->vidioc_s_ext_ctrls) + break; + dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value); - ret = vfd->vidioc_s_ctrl(file, fh, p); + if (vfd->vidioc_s_ctrl) { + ret = vfd->vidioc_s_ctrl(file, fh, p); + break; + } + if (!vfd->vidioc_s_ext_ctrls) + break; + + ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); + ctrls.count = 1; + ctrls.controls = &ctrl; + ctrl.id = p->id; + ctrl.value = p->value; + if (check_ext_ctrls(&ctrls)) + ret = vfd->vidioc_s_ext_ctrls(file, fh, &ctrls); break; } case VIDIOC_G_EXT_CTRLS: { struct v4l2_ext_controls *p = arg; + p->error_idx = p->count; if (!vfd->vidioc_g_ext_ctrls) break; - ret = vfd->vidioc_g_ext_ctrls(file, fh, p); + if (check_ext_ctrls(p)) + ret = vfd->vidioc_g_ext_ctrls(file, fh, p); v4l_print_ext_ctrls(cmd, vfd, p, !ret); break; } @@ -1465,22 +1520,24 @@ static int __video_do_ioctl(struct inode { struct v4l2_ext_controls *p = arg; - if (vfd->vidioc_s_ext_ctrls) { - v4l_print_ext_ctrls(cmd, vfd, p, 1); - + p->error_idx = p->count; + if (!vfd->vidioc_s_ext_ctrls) + break; + v4l_print_ext_ctrls(cmd, vfd, p, 1); + if (check_ext_ctrls(p)) ret = vfd->vidioc_s_ext_ctrls(file, fh, p); - } break; } case VIDIOC_TRY_EXT_CTRLS: { struct v4l2_ext_controls *p = arg; - if (vfd->vidioc_try_ext_ctrls) { - v4l_print_ext_ctrls(cmd, vfd, p, 1); - + p->error_idx = p->count; + if (!vfd->vidioc_try_ext_ctrls) + break; + v4l_print_ext_ctrls(cmd, vfd, p, 1); + if (check_ext_ctrls(p)) ret = vfd->vidioc_try_ext_ctrls(file, fh, p); - } break; } case VIDIOC_QUERYMENU: --- Patch is available at: http://linuxtv.org/hg/v4l-dvb/rev/fae200f98d476bfffdb113ee6774f7aaece56ef3 _______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits