diff -r d83ab09dff5c linux/drivers/media/video/v4l2-compat-ioctl32.c --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c Sat Nov 22 21:23:01 2008 -0500 +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c Sat Nov 22 21:26:40 2008 -0500 @@ -540,6 +540,61 @@ return 0; } + +struct v4l2_ext_controls32 { + __u32 ctrl_class; + __u32 count; + __u32 error_idx; + __u32 reserved[2]; + compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ +}; + +static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) +{ + if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) || + get_user(kp->ctrl_class, &up->ctrl_class) || + get_user(kp->count, &up->count) || + get_user(kp->error_idx, &up->error_idx) || + copy_from_user(kp->reserved, up->reserved, 2 * sizeof(__u32))) + return -EFAULT; + if (kp->count) { + struct v4l2_ext_control __user *ucontrols; + struct v4l2_ext_control __user *kcontrols; + int n = kp->count; + compat_caddr_t p; + + if (get_user(p, &up->controls)) + return -EFAULT; + ucontrols = compat_ptr(p); + kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); + kp->controls = kcontrols; + while (--n >= 0) { + if (copy_in_user(&kcontrols->id, &ucontrols->id, sizeof(__u32))) + return -EFAULT; + if (copy_in_user(&kcontrols->reserved2, &ucontrols->reserved2, 2 * sizeof(__u32))) + return -EFAULT; + if (copy_in_user(&kcontrols->value, &ucontrols->value, sizeof(ucontrols->value))) + return -EFAULT; + ucontrols++; + kcontrols++; + } + } else { + kp->controls = NULL; + } + return 0; +} + +static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) +{ + if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) || + put_user(kp->ctrl_class, &up->ctrl_class) || + put_user(kp->count, &up->count) || + put_user(kp->error_idx, &up->error_idx) || + copy_to_user(up->reserved, kp->reserved, 2 * sizeof(__u32))) + return -EFAULT; + return 0; +} + #ifdef CONFIG_VIDEO_V4L1_COMPAT struct video_code32 { char loadwhat[16]; /* name or tag of file being passed */ @@ -588,6 +643,7 @@ #define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t) #define VIDIOC_S_INPUT32 _IOWR ('V', 39, compat_int_t) #define VIDIOC_TRY_FMT32 _IOWR ('V', 64, struct v4l2_format32) +#define VIDIOC_S_EXT_CTRLS32 _IOWR ('V', 72, struct v4l2_ext_controls32) #ifdef CONFIG_VIDEO_V4L1_COMPAT enum { @@ -672,6 +728,7 @@ struct v4l2_standard v2s; struct v4l2_input v2i; struct v4l2_tuner v2t; + struct v4l2_ext_controls v2ecs; unsigned long vx; } karg; void __user *up = compat_ptr(arg); @@ -707,6 +764,7 @@ case VIDIOC_G_INPUT32: realcmd = cmd = VIDIOC_G_INPUT; break; case VIDIOC_S_INPUT32: realcmd = cmd = VIDIOC_S_INPUT; break; case VIDIOC_TRY_FMT32: realcmd = cmd = VIDIOC_TRY_FMT; break; + case VIDIOC_S_EXT_CTRLS32: realcmd = cmd = VIDIOC_S_EXT_CTRLS; break; }; switch (cmd) { @@ -800,6 +858,11 @@ compatible_arg = 0; break; #endif + + case VIDIOC_S_EXT_CTRLS: + err = get_v4l2_ext_controls32(&karg.v2ecs, up); + compatible_arg = 0; + break; }; if (err) goto out; @@ -877,6 +940,10 @@ case VIDIOC_G_INPUT: err = put_user(((u32)karg.vx), (u32 __user *)up); break; + + case VIDIOC_S_EXT_CTRLS: + err = put_v4l2_ext_controls32(&karg.v2ecs, up); + break; }; } out: @@ -944,6 +1011,9 @@ case VIDIOC_S_HW_FREQ_SEEK: case VIDIOC_ENUM_FRAMESIZES: case VIDIOC_ENUM_FRAMEINTERVALS: + case VIDIOC_ENCODER_CMD: + case VIDIOC_S_AUDIO: + case VIDIOC_S_EXT_CTRLS32: ret = do_video_ioctl(file, cmd, arg); break;