media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha
[pandora-kernel.git] / drivers / media / video / v4l2-compat-ioctl32.c
index 1b8999f..8fb6b74 100644 (file)
@@ -17,6 +17,9 @@
 #include <linux/videodev2.h>
 #include <linux/module.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
 
 #ifdef CONFIG_COMPAT
 
@@ -43,15 +46,17 @@ struct v4l2_window32 {
        compat_caddr_t          clips; /* actually struct v4l2_clip32 * */
        __u32                   clipcount;
        compat_caddr_t          bitmap;
+       __u8                    global_alpha;
 };
 
 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
 {
-       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
+       if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
            copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
            get_user(kp->field, &up->field) ||
            get_user(kp->chromakey, &up->chromakey) ||
-           get_user(kp->clipcount, &up->clipcount))
+           get_user(kp->clipcount, &up->clipcount) ||
+           get_user(kp->global_alpha, &up->global_alpha))
                return -EFAULT;
        if (kp->clipcount > 2048)
                return -EINVAL;
@@ -64,7 +69,7 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user
                if (get_user(p, &up->clips))
                        return -EFAULT;
                uclips = compat_ptr(p);
-               kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
+               kclips = compat_alloc_user_space(n * sizeof(*kclips));
                kp->clips = kclips;
                while (--n >= 0) {
                        if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
@@ -84,7 +89,8 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user
        if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) ||
            put_user(kp->field, &up->field) ||
            put_user(kp->chromakey, &up->chromakey) ||
-           put_user(kp->clipcount, &up->clipcount))
+           put_user(kp->clipcount, &up->clipcount) ||
+           put_user(kp->global_alpha, &up->global_alpha))
                return -EFAULT;
        return 0;
 }
@@ -156,14 +162,14 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
 
 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 {
-       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
+       if (!access_ok(VERIFY_READ, up, sizeof(*up)))
                return -EFAULT;
        return __get_v4l2_format32(kp, up);
 }
 
 static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
 {
-       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
+       if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
            copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format)))
                return -EFAULT;
        return __get_v4l2_format32(&kp->format, &up->format);
@@ -207,14 +213,14 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
 
 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 {
-       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)))
+       if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
                return -EFAULT;
        return __put_v4l2_format32(kp, up);
 }
 
 static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
 {
-       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
+       if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
            copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) ||
            copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
                return -EFAULT;
@@ -233,7 +239,7 @@ struct v4l2_standard32 {
 static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
 {
        /* other fields are not set by the user, nor used by the driver */
-       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
+       if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
            get_user(kp->index, &up->index))
                return -EFAULT;
        return 0;
@@ -241,13 +247,13 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32
 
 static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
 {
-       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
+       if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
            put_user(kp->index, &up->index) ||
            put_user(kp->id, &up->id) ||
-           copy_to_user(up->name, kp->name, 24) ||
+           copy_to_user(up->name, kp->name, sizeof(up->name)) ||
            copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
            put_user(kp->framelines, &up->framelines) ||
-           copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
+           copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
                return -EFAULT;
        return 0;
 }
@@ -293,19 +299,23 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __
 
        if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
            copy_in_user(&up->data_offset, &up32->data_offset,
-                        sizeof(__u32)))
+                        sizeof(up->data_offset)))
                return -EFAULT;
 
-       if (memory == V4L2_MEMORY_USERPTR) {
+       switch (memory) {
+       case V4L2_MEMORY_MMAP:
+       case V4L2_MEMORY_OVERLAY:
+               if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
+                                sizeof(up32->m.mem_offset)))
+                       return -EFAULT;
+               break;
+       case V4L2_MEMORY_USERPTR:
                if (get_user(p, &up32->m.userptr))
                        return -EFAULT;
                up_pln = compat_ptr(p);
                if (put_user((unsigned long)up_pln, &up->m.userptr))
                        return -EFAULT;
-       } else {
-               if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
-                                sizeof(__u32)))
-                       return -EFAULT;
+               break;
        }
 
        return 0;
@@ -314,17 +324,27 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __
 static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
                            enum v4l2_memory memory)
 {
+       unsigned long p;
+
        if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
            copy_in_user(&up32->data_offset, &up->data_offset,
-                        sizeof(__u32)))
+                        sizeof(up->data_offset)))
                return -EFAULT;
 
-       /* For MMAP, driver might've set up the offset, so copy it back.
-        * USERPTR stays the same (was userspace-provided), so no copying. */
-       if (memory == V4L2_MEMORY_MMAP)
+       switch (memory) {
+       case V4L2_MEMORY_MMAP:
+       case V4L2_MEMORY_OVERLAY:
                if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
-                                sizeof(__u32)))
+                                sizeof(up->m.mem_offset)))
+                       return -EFAULT;
+               break;
+       case V4L2_MEMORY_USERPTR:
+               if (get_user(p, &up->m.userptr) ||
+                   put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
+                            &up32->m.userptr))
                        return -EFAULT;
+               break;
+       }
 
        return 0;
 }
@@ -337,7 +357,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
        int num_planes;
        int ret;
 
-       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
+       if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
            get_user(kp->index, &up->index) ||
            get_user(kp->type, &up->type) ||
            get_user(kp->flags, &up->flags) ||
@@ -349,8 +369,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
                if (get_user(kp->bytesused, &up->bytesused) ||
                    get_user(kp->field, &up->field) ||
                    get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
-                   get_user(kp->timestamp.tv_usec,
-                            &up->timestamp.tv_usec))
+                   get_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec))
                        return -EFAULT;
 
        if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
@@ -370,13 +389,13 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
 
                uplane32 = compat_ptr(p);
                if (!access_ok(VERIFY_READ, uplane32,
-                              num_planes * sizeof(struct v4l2_plane32)))
+                              num_planes * sizeof(*uplane32)))
                        return -EFAULT;
 
                /* We don't really care if userspace decides to kill itself
                 * by passing a very big num_planes value */
                uplane = compat_alloc_user_space(num_planes *
-                                                sizeof(struct v4l2_plane));
+                                                sizeof(*uplane));
                kp->m.planes = (__force struct v4l2_plane *)uplane;
 
                while (--num_planes >= 0) {
@@ -422,7 +441,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
        int num_planes;
        int ret;
 
-       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
+       if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
            put_user(kp->index, &up->index) ||
            put_user(kp->type, &up->type) ||
            put_user(kp->flags, &up->flags) ||
@@ -434,7 +453,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
            put_user(kp->field, &up->field) ||
            put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
            put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
-           copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
+           copy_to_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) ||
            put_user(kp->sequence, &up->sequence) ||
            put_user(kp->reserved, &up->reserved))
                return -EFAULT;
@@ -489,7 +508,7 @@ static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
 {
        u32 tmp;
 
-       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
+       if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
            get_user(tmp, &up->base) ||
            get_user(kp->capability, &up->capability) ||
            get_user(kp->flags, &up->flags) ||
@@ -503,7 +522,7 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
 {
        u32 tmp = (u32)((unsigned long)kp->base);
 
-       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
+       if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
            put_user(tmp, &up->base) ||
            put_user(kp->capability, &up->capability) ||
            put_user(kp->flags, &up->flags) ||
@@ -528,14 +547,14 @@ struct v4l2_input32 {
    Otherwise it is identical to the 32-bit version. */
 static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
 {
-       if (copy_from_user(kp, up, sizeof(struct v4l2_input32)))
+       if (copy_from_user(kp, up, sizeof(*up)))
                return -EFAULT;
        return 0;
 }
 
 static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
 {
-       if (copy_to_user(up, kp, sizeof(struct v4l2_input32)))
+       if (copy_to_user(up, kp, sizeof(*up)))
                return -EFAULT;
        return 0;
 }
@@ -559,31 +578,39 @@ struct v4l2_ext_control32 {
        };
 } __attribute__ ((packed));
 
-/* The following function really belong in v4l2-common, but that causes
-   a circular dependency between modules. We need to think about this, but
-   for now this will do. */
-
-/* Return non-zero if this control is a pointer type. Currently only
-   type STRING is a pointer type. */
-static inline int ctrl_is_pointer(u32 id)
+/* Return true if this control is a pointer type. */
+static inline bool ctrl_is_pointer(struct file *file, u32 id)
 {
-       switch (id) {
-       case V4L2_CID_RDS_TX_PS_NAME:
-       case V4L2_CID_RDS_TX_RADIO_TEXT:
-               return 1;
-       default:
-               return 0;
+       struct video_device *vdev = video_devdata(file);
+       struct v4l2_fh *fh = NULL;
+       struct v4l2_ctrl_handler *hdl = NULL;
+
+       if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
+               fh = file->private_data;
+
+       if (fh && fh->ctrl_handler)
+               hdl = fh->ctrl_handler;
+       else if (vdev->ctrl_handler)
+               hdl = vdev->ctrl_handler;
+
+       if (hdl) {
+               struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
+
+               return ctrl && ctrl->type == V4L2_CTRL_TYPE_STRING;
        }
+       return false;
 }
 
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
+static int get_v4l2_ext_controls32(struct file *file,
+                                  struct v4l2_ext_controls *kp,
+                                  struct v4l2_ext_controls32 __user *up)
 {
        struct v4l2_ext_control32 __user *ucontrols;
        struct v4l2_ext_control __user *kcontrols;
        int n;
        compat_caddr_t p;
 
-       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
+       if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
            get_user(kp->ctrl_class, &up->ctrl_class) ||
            get_user(kp->count, &up->count) ||
            get_user(kp->error_idx, &up->error_idx) ||
@@ -597,10 +624,9 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
        if (get_user(p, &up->controls))
                return -EFAULT;
        ucontrols = compat_ptr(p);
-       if (!access_ok(VERIFY_READ, ucontrols,
-                      n * sizeof(struct v4l2_ext_control32)))
+       if (!access_ok(VERIFY_READ, ucontrols, n * sizeof(*ucontrols)))
                return -EFAULT;
-       kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
+       kcontrols = compat_alloc_user_space(n * sizeof(*kcontrols));
        kp->controls = (__force struct v4l2_ext_control *)kcontrols;
        while (--n >= 0) {
                u32 id;
@@ -609,7 +635,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
                        return -EFAULT;
                if (get_user(id, &kcontrols->id))
                        return -EFAULT;
-               if (ctrl_is_pointer(id)) {
+               if (ctrl_is_pointer(file, id)) {
                        void __user *s;
 
                        if (get_user(p, &ucontrols->string))
@@ -624,7 +650,9 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
        return 0;
 }
 
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
+static int put_v4l2_ext_controls32(struct file *file,
+                                  struct v4l2_ext_controls *kp,
+                                  struct v4l2_ext_controls32 __user *up)
 {
        struct v4l2_ext_control32 __user *ucontrols;
        struct v4l2_ext_control __user *kcontrols =
@@ -632,7 +660,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
        int n = kp->count;
        compat_caddr_t p;
 
-       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) ||
+       if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
            put_user(kp->ctrl_class, &up->ctrl_class) ||
            put_user(kp->count, &up->count) ||
            put_user(kp->error_idx, &up->error_idx) ||
@@ -644,8 +672,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
        if (get_user(p, &up->controls))
                return -EFAULT;
        ucontrols = compat_ptr(p);
-       if (!access_ok(VERIFY_WRITE, ucontrols,
-                      n * sizeof(struct v4l2_ext_control32)))
+       if (!access_ok(VERIFY_WRITE, ucontrols, n * sizeof(*ucontrols)))
                return -EFAULT;
 
        while (--n >= 0) {
@@ -657,7 +684,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
                /* Do not modify the pointer when copying a pointer control.
                   The contents of the pointer was changed, not the pointer
                   itself. */
-               if (ctrl_is_pointer(id))
+               if (ctrl_is_pointer(file, id))
                        size -= sizeof(ucontrols->value64);
                if (copy_in_user(ucontrols, kcontrols, size))
                        return -EFAULT;
@@ -682,14 +709,14 @@ struct v4l2_event32 {
 
 static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up)
 {
-       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) ||
+       if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
            put_user(kp->type, &up->type) ||
            copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
            put_user(kp->pending, &up->pending) ||
            put_user(kp->sequence, &up->sequence) ||
            put_compat_timespec(&kp->timestamp, &up->timestamp) ||
            put_user(kp->id, &up->id) ||
-           copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
+           copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
                return -EFAULT;
        return 0;
 }
@@ -821,7 +848,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
        case VIDIOC_G_EXT_CTRLS:
        case VIDIOC_S_EXT_CTRLS:
        case VIDIOC_TRY_EXT_CTRLS:
-               err = get_v4l2_ext_controls32(&karg.v2ecs, up);
+               err = get_v4l2_ext_controls32(file, &karg.v2ecs, up);
                compatible_arg = 0;
                break;
        case VIDIOC_DQEVENT:
@@ -848,7 +875,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
        case VIDIOC_G_EXT_CTRLS:
        case VIDIOC_S_EXT_CTRLS:
        case VIDIOC_TRY_EXT_CTRLS:
-               if (put_v4l2_ext_controls32(&karg.v2ecs, up))
+               if (put_v4l2_ext_controls32(file, &karg.v2ecs, up))
                        err = -EFAULT;
                break;
        }