media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF
[pandora-kernel.git] / drivers / media / video / v4l2-compat-ioctl32.c
index 61979b7..37cffb7 100644 (file)
@@ -159,11 +159,28 @@ struct v4l2_format32 {
        } fmt;
 };
 
-static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+/**
+ * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
+ * @index:     on return, index of the first created buffer
+ * @count:     entry: number of requested buffers,
+ *             return: number of created buffers
+ * @memory:    buffer memory type
+ * @format:    frame format, for which buffers are requested
+ * @reserved:  future extensions
+ */
+struct v4l2_create_buffers32 {
+       __u32                   index;
+       __u32                   count;
+       enum v4l2_memory        memory;
+       struct v4l2_format32    format;
+       __u32                   reserved[8];
+};
+
+static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 {
-       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
-                       get_user(kp->type, &up->type))
-                       return -EFAULT;
+       if (get_user(kp->type, &up->type))
+               return -EFAULT;
+
        switch (kp->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
@@ -192,11 +209,26 @@ static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
        }
 }
 
-static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
+       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
+               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_WRITE, up, sizeof(struct v4l2_format32)) ||
-               put_user(kp->type, &up->type))
+       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
+           copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format)))
                return -EFAULT;
+       return __get_v4l2_format32(&kp->format, &up->format);
+}
+
+static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
+       if (put_user(kp->type, &up->type))
+               return -EFAULT;
+
        switch (kp->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
@@ -225,9 +257,25 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
        }
 }
 
+static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
+       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)))
+               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)) ||
+           copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) ||
+           copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
+               return -EFAULT;
+       return __put_v4l2_format32(&kp->format, &up->format);
+}
+
 struct v4l2_standard32 {
        __u32                index;
-       __u32                id[2]; /* __u64 would get the alignment wrong */
+       compat_u64           id;
        __u8                 name[24];
        struct v4l2_fract    frameperiod; /* Frames, not fields */
        __u32                framelines;
@@ -247,7 +295,7 @@ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32
 {
        if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
                put_user(kp->index, &up->index) ||
-               copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
+               put_user(kp->id, &up->id) ||
                copy_to_user(up->name, kp->name, 24) ||
                copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
                put_user(kp->framelines, &up->framelines) ||
@@ -289,7 +337,7 @@ struct v4l2_buffer32 {
        __u32                   reserved;
 };
 
-static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
+static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
                                enum v4l2_memory memory)
 {
        void __user *up_pln;
@@ -315,7 +363,7 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
        return 0;
 }
 
-static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
+static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
                                enum v4l2_memory memory)
 {
        if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
@@ -381,7 +429,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
                 * by passing a very big num_planes value */
                uplane = compat_alloc_user_space(num_planes *
                                                sizeof(struct v4l2_plane));
-               kp->m.planes = uplane;
+               kp->m.planes = (__force struct v4l2_plane *)uplane;
 
                while (--num_planes >= 0) {
                        ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
@@ -448,7 +496,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
                if (num_planes == 0)
                        return 0;
 
-               uplane = kp->m.planes;
+               uplane = (__force struct v4l2_plane __user *)kp->m.planes;
                if (get_user(p, &up->m.planes))
                        return -EFAULT;
                uplane32 = compat_ptr(p);
@@ -498,7 +546,7 @@ static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
                get_user(kp->capability, &up->capability) ||
                get_user(kp->flags, &up->flags))
                        return -EFAULT;
-       kp->base = compat_ptr(tmp);
+       kp->base = (__force void *)compat_ptr(tmp);
        get_v4l2_pix_format(&kp->fmt, &up->fmt);
        return 0;
 }
@@ -522,10 +570,11 @@ struct v4l2_input32 {
        __u32        type;              /*  Type of input */
        __u32        audioset;          /*  Associated audios (bitfield) */
        __u32        tuner;             /*  Associated tuner */
-       v4l2_std_id  std;
+       compat_u64   std;
        __u32        status;
-       __u32        reserved[4];
-} __attribute__ ((packed));
+       __u32        capabilities;
+       __u32        reserved[3];
+};
 
 /* The 64-bit v4l2_input struct has extra padding at the end of the struct.
    Otherwise it is identical to the 32-bit version. */
@@ -604,11 +653,15 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
                        n * sizeof(struct v4l2_ext_control32)))
                return -EFAULT;
        kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
-       kp->controls = kcontrols;
+       kp->controls = (__force struct v4l2_ext_control *)kcontrols;
        while (--n >= 0) {
+               u32 id;
+
                if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
                        return -EFAULT;
-               if (ctrl_is_pointer(kcontrols->id)) {
+               if (get_user(id, &kcontrols->id))
+                       return -EFAULT;
+               if (ctrl_is_pointer(id)) {
                        void __user *s;
 
                        if (get_user(p, &ucontrols->string))
@@ -626,7 +679,8 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
 {
        struct v4l2_ext_control32 __user *ucontrols;
-       struct v4l2_ext_control __user *kcontrols = kp->controls;
+       struct v4l2_ext_control __user *kcontrols =
+               (__force struct v4l2_ext_control __user *)kp->controls;
        int n = kp->count;
        compat_caddr_t p;
 
@@ -648,11 +702,14 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
 
        while (--n >= 0) {
                unsigned size = sizeof(*ucontrols);
+               u32 id;
 
+               if (get_user(id, &kcontrols->id))
+                       return -EFAULT;
                /* 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(kcontrols->id))
+               if (ctrl_is_pointer(id))
                        size -= sizeof(ucontrols->value64);
                if (copy_in_user(ucontrols, kcontrols, size))
                        return -EFAULT;
@@ -665,6 +722,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
 struct v4l2_event32 {
        __u32                           type;
        union {
+               compat_s64              value64;
                __u8                    data[64];
        } u;
        __u32                           pending;
@@ -702,6 +760,8 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u
 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
 #define        VIDIOC_DQEVENT32        _IOR ('V', 89, struct v4l2_event32)
+#define VIDIOC_CREATE_BUFS32   _IOWR('V', 92, struct v4l2_create_buffers32)
+#define VIDIOC_PREPARE_BUF32   _IOWR('V', 93, struct v4l2_buffer32)
 
 #define VIDIOC_OVERLAY32       _IOW ('V', 14, s32)
 #define VIDIOC_STREAMON32      _IOW ('V', 18, s32)
@@ -721,6 +781,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                struct v4l2_standard v2s;
                struct v4l2_ext_controls v2ecs;
                struct v4l2_event v2ev;
+               struct v4l2_create_buffers v2crt;
                unsigned long vx;
                int vi;
        } karg;
@@ -751,6 +812,8 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
        case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
        case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
        case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
+       case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
+       case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
        }
 
        switch (cmd) {
@@ -775,6 +838,12 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                compatible_arg = 0;
                break;
 
+       case VIDIOC_CREATE_BUFS:
+               err = get_v4l2_create32(&karg.v2crt, up);
+               compatible_arg = 0;
+               break;
+
+       case VIDIOC_PREPARE_BUF:
        case VIDIOC_QUERYBUF:
        case VIDIOC_QBUF:
        case VIDIOC_DQBUF:
@@ -860,6 +929,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                err = put_v4l2_format32(&karg.v2f, up);
                break;
 
+       case VIDIOC_CREATE_BUFS:
+               err = put_v4l2_create32(&karg.v2crt, up);
+               break;
+
+       case VIDIOC_PREPARE_BUF:
        case VIDIOC_QUERYBUF:
        case VIDIOC_QBUF:
        case VIDIOC_DQBUF:
@@ -959,6 +1033,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case VIDIOC_DQEVENT32:
        case VIDIOC_SUBSCRIBE_EVENT:
        case VIDIOC_UNSUBSCRIBE_EVENT:
+       case VIDIOC_CREATE_BUFS32:
+       case VIDIOC_PREPARE_BUF32:
                ret = do_video_ioctl(file, cmd, arg);
                break;