blob: 8618eba6474e8027e42d209192f960d20f477ad3 [file] [log] [blame]
Philippe De Muytercf664a62006-01-09 15:24:59 -02001/*
2 * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
3 * Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
4 *
5 * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
6 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
7 * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
Pavel Macheka2531292010-07-18 14:27:13 +02008 * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz)
Philippe De Muytercf664a62006-01-09 15:24:59 -02009 * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be)
Hans Verkuil92f45ba2008-12-21 10:35:25 -030010 * Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
Philippe De Muytercf664a62006-01-09 15:24:59 -020011 *
12 * These routines maintain argument size conversion between 32bit and 64bit
13 * ioctls.
14 */
15
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020016#include <linux/compat.h>
Nickolay V. Shmyrev133b7352006-01-09 15:24:58 -020017#include <linux/module.h>
Laurent Pinchartb9d0aa62011-12-18 20:41:19 -030018#include <linux/videodev2.h>
Hans Verkuiled45ce22012-08-10 06:07:12 -030019#include <linux/v4l2-subdev.h>
Laurent Pinchartb9d0aa62011-12-18 20:41:19 -030020#include <media/v4l2-dev.h>
Hans Verkuil9a7cd412018-02-14 12:48:24 +010021#include <media/v4l2-fh.h>
22#include <media/v4l2-ctrls.h>
Mauro Carvalho Chehab28644622008-07-20 20:26:54 -030023#include <media/v4l2-ioctl.h>
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020024
Daniel Mentzf2d4bed2018-02-14 12:48:30 +010025/* Use the same argument order as copy_in_user */
26#define assign_in_user(to, from) \
27({ \
28 typeof(*from) __assign_tmp; \
29 \
30 get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \
31})
32
Hans Verkuil069b7472008-12-30 07:04:34 -030033static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020034{
Hans Verkuil069b7472008-12-30 07:04:34 -030035 long ret = -ENOIOCTLCMD;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020036
Philippe De Muyter13d133b2006-01-09 15:25:00 -020037 if (file->f_op->unlocked_ioctl)
38 ret = file->f_op->unlocked_ioctl(file, cmd, arg);
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020039
40 return ret;
41}
42
43
Hans Verkuild1f81da2008-10-22 00:04:45 -030044struct v4l2_clip32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -020045 struct v4l2_rect c;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +010046 compat_caddr_t next;
Philippe De Muytercf664a62006-01-09 15:24:59 -020047};
48
Hans Verkuild1f81da2008-10-22 00:04:45 -030049struct v4l2_window32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -020050 struct v4l2_rect w;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +010051 __u32 field; /* enum v4l2_field */
Philippe De Muytercf664a62006-01-09 15:24:59 -020052 __u32 chromakey;
53 compat_caddr_t clips; /* actually struct v4l2_clip32 * */
54 __u32 clipcount;
55 compat_caddr_t bitmap;
Daniel Mentz55e3f3e2018-02-14 12:48:26 +010056 __u8 global_alpha;
Philippe De Muytercf664a62006-01-09 15:24:59 -020057};
58
Daniel Mentzf2d4bed2018-02-14 12:48:30 +010059static int get_v4l2_window32(struct v4l2_window __user *kp,
60 struct v4l2_window32 __user *up,
61 void __user *aux_buf, u32 aux_space)
Philippe De Muytercf664a62006-01-09 15:24:59 -020062{
Hans Verkuil30ac343c2018-02-14 12:48:27 +010063 struct v4l2_clip32 __user *uclips;
64 struct v4l2_clip __user *kclips;
65 compat_caddr_t p;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +010066 u32 clipcount;
Hans Verkuil30ac343c2018-02-14 12:48:27 +010067
Hans Verkuildaff4d02018-02-14 12:48:22 +010068 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +010069 copy_in_user(&kp->w, &up->w, sizeof(up->w)) ||
70 assign_in_user(&kp->field, &up->field) ||
71 assign_in_user(&kp->chromakey, &up->chromakey) ||
72 assign_in_user(&kp->global_alpha, &up->global_alpha) ||
73 get_user(clipcount, &up->clipcount) ||
74 put_user(clipcount, &kp->clipcount))
Hans Verkuil02129c92018-02-14 12:48:20 +010075 return -EFAULT;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +010076 if (clipcount > 2048)
Philippe De Muytercf664a62006-01-09 15:24:59 -020077 return -EINVAL;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +010078 if (!clipcount)
79 return put_user(NULL, &kp->clips);
Philippe De Muytercf664a62006-01-09 15:24:59 -020080
Hans Verkuil30ac343c2018-02-14 12:48:27 +010081 if (get_user(p, &up->clips))
82 return -EFAULT;
83 uclips = compat_ptr(p);
Daniel Mentzf2d4bed2018-02-14 12:48:30 +010084 if (aux_space < clipcount * sizeof(*kclips))
85 return -EFAULT;
86 kclips = aux_buf;
87 if (put_user(kclips, &kp->clips))
88 return -EFAULT;
89
90 while (clipcount--) {
Hans Verkuil30ac343c2018-02-14 12:48:27 +010091 if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
Al Viro5b1a43d2006-02-01 05:24:20 -050092 return -EFAULT;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +010093 if (put_user(clipcount ? kclips + 1 : NULL, &kclips->next))
Guy Martina113bc72006-01-11 23:40:51 -020094 return -EFAULT;
Hans Verkuil30ac343c2018-02-14 12:48:27 +010095 uclips++;
96 kclips++;
97 }
Philippe De Muytercf664a62006-01-09 15:24:59 -020098 return 0;
99}
100
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100101static int put_v4l2_window32(struct v4l2_window __user *kp,
102 struct v4l2_window32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200103{
Mauro Carvalho Chehab394a9a72018-03-28 13:59:22 -0400104 struct v4l2_clip __user *kclips;
Hans Verkuil30ac343c2018-02-14 12:48:27 +0100105 struct v4l2_clip32 __user *uclips;
Hans Verkuil30ac343c2018-02-14 12:48:27 +0100106 compat_caddr_t p;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100107 u32 clipcount;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200108
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100109 if (copy_in_user(&up->w, &kp->w, sizeof(kp->w)) ||
110 assign_in_user(&up->field, &kp->field) ||
111 assign_in_user(&up->chromakey, &kp->chromakey) ||
112 assign_in_user(&up->global_alpha, &kp->global_alpha) ||
113 get_user(clipcount, &kp->clipcount) ||
114 put_user(clipcount, &up->clipcount))
Pawel Osciak52a30822010-07-29 14:56:47 -0300115 return -EFAULT;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100116 if (!clipcount)
Hans Verkuil30ac343c2018-02-14 12:48:27 +0100117 return 0;
Pawel Osciak52a30822010-07-29 14:56:47 -0300118
Mauro Carvalho Chehab394a9a72018-03-28 13:59:22 -0400119 if (get_user(kclips, &kp->clips))
120 return -EFAULT;
Hans Verkuil30ac343c2018-02-14 12:48:27 +0100121 if (get_user(p, &up->clips))
Al Viro5b1a43d2006-02-01 05:24:20 -0500122 return -EFAULT;
Hans Verkuil30ac343c2018-02-14 12:48:27 +0100123 uclips = compat_ptr(p);
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100124 while (clipcount--) {
Hans Verkuil30ac343c2018-02-14 12:48:27 +0100125 if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c)))
126 return -EFAULT;
127 uclips++;
128 kclips++;
129 }
Hans Verkuild5beb672015-09-17 06:46:04 -0300130 return 0;
131}
132
Hans Verkuild1f81da2008-10-22 00:04:45 -0300133struct v4l2_format32 {
Sakari Ailus6016af82012-05-10 02:02:07 -0300134 __u32 type; /* enum v4l2_buf_type */
Hans Verkuild1f81da2008-10-22 00:04:45 -0300135 union {
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300136 struct v4l2_pix_format pix;
Pawel Osciak52a30822010-07-29 14:56:47 -0300137 struct v4l2_pix_format_mplane pix_mp;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300138 struct v4l2_window32 win;
139 struct v4l2_vbi_format vbi;
140 struct v4l2_sliced_vbi_format sliced;
Hans Verkuild5beb672015-09-17 06:46:04 -0300141 struct v4l2_sdr_format sdr;
Hans Verkuild1f81da2008-10-22 00:04:45 -0300142 __u8 raw_data[200]; /* user-defined */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200143 } fmt;
144};
145
Guennadi Liakhovetski09362ec2011-09-07 18:07:23 -0300146/**
147 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
148 * @index: on return, index of the first created buffer
149 * @count: entry: number of requested buffers,
150 * return: number of created buffers
151 * @memory: buffer memory type
152 * @format: frame format, for which buffers are requested
153 * @reserved: future extensions
154 */
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300155struct v4l2_create_buffers32 {
Guennadi Liakhovetski09362ec2011-09-07 18:07:23 -0300156 __u32 index;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300157 __u32 count;
Sakari Ailus6016af82012-05-10 02:02:07 -0300158 __u32 memory; /* enum v4l2_memory */
Guennadi Liakhovetski09362ec2011-09-07 18:07:23 -0300159 struct v4l2_format32 format;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300160 __u32 reserved[8];
161};
162
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100163static int __bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200164{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100165 u32 type;
166
167 if (get_user(type, &up->type))
Guennadi Liakhovetskiec775812014-04-26 12:51:31 -0300168 return -EFAULT;
169
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100170 switch (type) {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200171 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100172 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
173 u32 clipcount;
174
175 if (get_user(clipcount, &up->fmt.win.clipcount))
176 return -EFAULT;
177 if (clipcount > 2048)
178 return -EINVAL;
179 *size = clipcount * sizeof(struct v4l2_clip);
180 return 0;
181 }
Philippe De Muytercf664a62006-01-09 15:24:59 -0200182 default:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100183 *size = 0;
184 return 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200185 }
186}
187
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100188static int bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200189{
Hans Verkuildaff4d02018-02-14 12:48:22 +0100190 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
Guennadi Liakhovetskiec775812014-04-26 12:51:31 -0300191 return -EFAULT;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100192 return __bufsize_v4l2_format(up, size);
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300193}
194
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100195static int __get_v4l2_format32(struct v4l2_format __user *kp,
196 struct v4l2_format32 __user *up,
197 void __user *aux_buf, u32 aux_space)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300198{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100199 u32 type;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300200
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100201 if (get_user(type, &up->type) || put_user(type, &kp->type))
Guennadi Liakhovetski6ed9b282014-05-30 20:26:38 -0300202 return -EFAULT;
203
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100204 switch (type) {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200205 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
206 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100207 return copy_in_user(&kp->fmt.pix, &up->fmt.pix,
Hans Verkuil81e0acf2018-02-14 12:48:21 +0100208 sizeof(kp->fmt.pix)) ? -EFAULT : 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200209 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
210 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100211 return copy_in_user(&kp->fmt.pix_mp, &up->fmt.pix_mp,
Hans Verkuil81e0acf2018-02-14 12:48:21 +0100212 sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200213 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
214 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100215 return get_v4l2_window32(&kp->fmt.win, &up->fmt.win,
216 aux_buf, aux_space);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200217 case V4L2_BUF_TYPE_VBI_CAPTURE:
218 case V4L2_BUF_TYPE_VBI_OUTPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100219 return copy_in_user(&kp->fmt.vbi, &up->fmt.vbi,
Hans Verkuil81e0acf2018-02-14 12:48:21 +0100220 sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200221 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
222 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100223 return copy_in_user(&kp->fmt.sliced, &up->fmt.sliced,
Hans Verkuil81e0acf2018-02-14 12:48:21 +0100224 sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200225 case V4L2_BUF_TYPE_SDR_CAPTURE:
226 case V4L2_BUF_TYPE_SDR_OUTPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100227 return copy_in_user(&kp->fmt.sdr, &up->fmt.sdr,
Hans Verkuil81e0acf2018-02-14 12:48:21 +0100228 sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200229 default:
Philippe De Muytercf664a62006-01-09 15:24:59 -0200230 return -EINVAL;
231 }
232}
233
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100234static int get_v4l2_format32(struct v4l2_format __user *kp,
235 struct v4l2_format32 __user *up,
236 void __user *aux_buf, u32 aux_space)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200237{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100238 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300239 return -EFAULT;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100240 return __get_v4l2_format32(kp, up, aux_buf, aux_space);
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300241}
242
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100243static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user *up,
244 u32 *size)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300245{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100246 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300247 return -EFAULT;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100248 return __bufsize_v4l2_format(&up->format, size);
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300249}
250
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100251static int get_v4l2_create32(struct v4l2_create_buffers __user *kp,
252 struct v4l2_create_buffers32 __user *up,
253 void __user *aux_buf, u32 aux_space)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300254{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100255 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
256 copy_in_user(kp, up,
257 offsetof(struct v4l2_create_buffers32, format)))
258 return -EFAULT;
259 return __get_v4l2_format32(&kp->format, &up->format,
260 aux_buf, aux_space);
261}
262
263static int __put_v4l2_format32(struct v4l2_format __user *kp,
264 struct v4l2_format32 __user *up)
265{
266 u32 type;
267
268 if (get_user(type, &kp->type))
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300269 return -EFAULT;
270
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100271 switch (type) {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200272 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300273 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100274 return copy_in_user(&up->fmt.pix, &kp->fmt.pix,
275 sizeof(kp->fmt.pix)) ? -EFAULT : 0;
Pawel Osciak52a30822010-07-29 14:56:47 -0300276 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
277 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100278 return copy_in_user(&up->fmt.pix_mp, &kp->fmt.pix_mp,
279 sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200280 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300281 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Philippe De Muytercf664a62006-01-09 15:24:59 -0200282 return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
283 case V4L2_BUF_TYPE_VBI_CAPTURE:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300284 case V4L2_BUF_TYPE_VBI_OUTPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100285 return copy_in_user(&up->fmt.vbi, &kp->fmt.vbi,
286 sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300287 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
288 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100289 return copy_in_user(&up->fmt.sliced, &kp->fmt.sliced,
290 sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
Hans Verkuild5beb672015-09-17 06:46:04 -0300291 case V4L2_BUF_TYPE_SDR_CAPTURE:
Antti Palosaari9effc722015-10-10 13:51:00 -0300292 case V4L2_BUF_TYPE_SDR_OUTPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100293 return copy_in_user(&up->fmt.sdr, &kp->fmt.sdr,
294 sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200295 default:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300296 return -EINVAL;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200297 }
298}
299
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100300static int put_v4l2_format32(struct v4l2_format __user *kp,
301 struct v4l2_format32 __user *up)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300302{
Hans Verkuildaff4d02018-02-14 12:48:22 +0100303 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300304 return -EFAULT;
305 return __put_v4l2_format32(kp, up);
306}
307
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100308static int put_v4l2_create32(struct v4l2_create_buffers __user *kp,
309 struct v4l2_create_buffers32 __user *up)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300310{
Hans Verkuildaff4d02018-02-14 12:48:22 +0100311 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100312 copy_in_user(up, kp,
313 offsetof(struct v4l2_create_buffers32, format)) ||
314 copy_in_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
Guennadi Liakhovetski6ed9b282014-05-30 20:26:38 -0300315 return -EFAULT;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300316 return __put_v4l2_format32(&kp->format, &up->format);
317}
318
Hans Verkuild1f81da2008-10-22 00:04:45 -0300319struct v4l2_standard32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200320 __u32 index;
Andrzej Hajda655e9782015-08-31 08:56:15 -0300321 compat_u64 id;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200322 __u8 name[24];
323 struct v4l2_fract frameperiod; /* Frames, not fields */
324 __u32 framelines;
325 __u32 reserved[4];
326};
327
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100328static int get_v4l2_standard32(struct v4l2_standard __user *kp,
329 struct v4l2_standard32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200330{
331 /* other fields are not set by the user, nor used by the driver */
Hans Verkuildaff4d02018-02-14 12:48:22 +0100332 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100333 assign_in_user(&kp->index, &up->index))
Guy Martina113bc72006-01-11 23:40:51 -0200334 return -EFAULT;
335 return 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200336}
337
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100338static int put_v4l2_standard32(struct v4l2_standard __user *kp,
339 struct v4l2_standard32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200340{
Hans Verkuildaff4d02018-02-14 12:48:22 +0100341 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100342 assign_in_user(&up->index, &kp->index) ||
343 assign_in_user(&up->id, &kp->id) ||
344 copy_in_user(up->name, kp->name, sizeof(up->name)) ||
345 copy_in_user(&up->frameperiod, &kp->frameperiod,
346 sizeof(up->frameperiod)) ||
347 assign_in_user(&up->framelines, &kp->framelines) ||
348 copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
Hans Verkuil02129c92018-02-14 12:48:20 +0100349 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200350 return 0;
351}
352
Pawel Osciak52a30822010-07-29 14:56:47 -0300353struct v4l2_plane32 {
354 __u32 bytesused;
355 __u32 length;
356 union {
357 __u32 mem_offset;
358 compat_long_t userptr;
Sumit Semwal051c7782012-06-14 10:37:35 -0300359 __s32 fd;
Pawel Osciak52a30822010-07-29 14:56:47 -0300360 } m;
361 __u32 data_offset;
362 __u32 reserved[11];
363};
364
Hans Verkuild1f81da2008-10-22 00:04:45 -0300365struct v4l2_buffer32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200366 __u32 index;
Sakari Ailus6016af82012-05-10 02:02:07 -0300367 __u32 type; /* enum v4l2_buf_type */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200368 __u32 bytesused;
369 __u32 flags;
Sakari Ailus6016af82012-05-10 02:02:07 -0300370 __u32 field; /* enum v4l2_field */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200371 struct compat_timeval timestamp;
372 struct v4l2_timecode timecode;
373 __u32 sequence;
374
375 /* memory location */
Sakari Ailus6016af82012-05-10 02:02:07 -0300376 __u32 memory; /* enum v4l2_memory */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200377 union {
378 __u32 offset;
379 compat_long_t userptr;
Pawel Osciak52a30822010-07-29 14:56:47 -0300380 compat_caddr_t planes;
Sumit Semwal051c7782012-06-14 10:37:35 -0300381 __s32 fd;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200382 } m;
383 __u32 length;
Sakari Ailus2b719d72012-05-02 09:40:03 -0300384 __u32 reserved2;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200385 __u32 reserved;
386};
387
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100388static int get_v4l2_plane32(struct v4l2_plane __user *up,
389 struct v4l2_plane32 __user *up32,
Hans Verkuil02129c92018-02-14 12:48:20 +0100390 enum v4l2_memory memory)
Pawel Osciak52a30822010-07-29 14:56:47 -0300391{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100392 compat_ulong_t p;
Pawel Osciak52a30822010-07-29 14:56:47 -0300393
394 if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
Hans Verkuil02129c92018-02-14 12:48:20 +0100395 copy_in_user(&up->data_offset, &up32->data_offset,
Blagovest Kolenichev82ccf832018-02-22 03:25:47 -0800396 sizeof(up->data_offset)) ||
397 copy_in_user(up->reserved, up32->reserved,
398 sizeof(up->reserved)) ||
399 copy_in_user(&up->length, &up32->length,
400 sizeof(up->length)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300401 return -EFAULT;
402
Hans Verkuileec95542018-02-14 12:48:23 +0100403 switch (memory) {
404 case V4L2_MEMORY_MMAP:
405 case V4L2_MEMORY_OVERLAY:
Pawel Osciak52a30822010-07-29 14:56:47 -0300406 if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
Hans Verkuileec95542018-02-14 12:48:23 +0100407 sizeof(up32->m.mem_offset)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300408 return -EFAULT;
Hans Verkuileec95542018-02-14 12:48:23 +0100409 break;
410 case V4L2_MEMORY_USERPTR:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100411 if (get_user(p, &up32->m.userptr) ||
412 put_user((unsigned long)compat_ptr(p), &up->m.userptr))
Pawel Osciak52a30822010-07-29 14:56:47 -0300413 return -EFAULT;
Hans Verkuileec95542018-02-14 12:48:23 +0100414 break;
415 case V4L2_MEMORY_DMABUF:
Hans Verkuildaff4d02018-02-14 12:48:22 +0100416 if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(up32->m.fd)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300417 return -EFAULT;
Hans Verkuileec95542018-02-14 12:48:23 +0100418 break;
Pawel Osciak52a30822010-07-29 14:56:47 -0300419 }
420
421 return 0;
422}
423
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100424static int put_v4l2_plane32(struct v4l2_plane __user *up,
425 struct v4l2_plane32 __user *up32,
Hans Verkuil02129c92018-02-14 12:48:20 +0100426 enum v4l2_memory memory)
Pawel Osciak52a30822010-07-29 14:56:47 -0300427{
Hans Verkuileec95542018-02-14 12:48:23 +0100428 unsigned long p;
429
Pawel Osciak52a30822010-07-29 14:56:47 -0300430 if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
Hans Verkuil02129c92018-02-14 12:48:20 +0100431 copy_in_user(&up32->data_offset, &up->data_offset,
Blagovest Kolenichev82ccf832018-02-22 03:25:47 -0800432 sizeof(up->data_offset)) ||
433 copy_in_user(up32->reserved, up->reserved,
434 sizeof(up32->reserved)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300435 return -EFAULT;
436
Hans Verkuileec95542018-02-14 12:48:23 +0100437 switch (memory) {
438 case V4L2_MEMORY_MMAP:
439 case V4L2_MEMORY_OVERLAY:
Pawel Osciak52a30822010-07-29 14:56:47 -0300440 if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
Hans Verkuildaff4d02018-02-14 12:48:22 +0100441 sizeof(up->m.mem_offset)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300442 return -EFAULT;
Hans Verkuileec95542018-02-14 12:48:23 +0100443 break;
444 case V4L2_MEMORY_USERPTR:
445 if (get_user(p, &up->m.userptr) ||
446 put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
447 &up32->m.userptr))
Sumit Semwal051c7782012-06-14 10:37:35 -0300448 return -EFAULT;
Hans Verkuileec95542018-02-14 12:48:23 +0100449 break;
450 case V4L2_MEMORY_DMABUF:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100451 if (copy_in_user(&up32->m.fd, &up->m.fd, sizeof(up->m.fd)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300452 return -EFAULT;
Hans Verkuileec95542018-02-14 12:48:23 +0100453 break;
454 }
Pawel Osciak52a30822010-07-29 14:56:47 -0300455
456 return 0;
457}
458
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100459static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user *up, u32 *size)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200460{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100461 u32 type;
462 u32 length;
463
464 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
465 get_user(type, &up->type) ||
466 get_user(length, &up->length))
467 return -EFAULT;
468
469 if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
470 if (length > VIDEO_MAX_PLANES)
471 return -EINVAL;
472
473 /*
474 * We don't really care if userspace decides to kill itself
475 * by passing a very big length value
476 */
477 *size = length * sizeof(struct v4l2_plane);
478 } else {
479 *size = 0;
480 }
481 return 0;
482}
483
484static int get_v4l2_buffer32(struct v4l2_buffer __user *kp,
485 struct v4l2_buffer32 __user *up,
486 void __user *aux_buf, u32 aux_space)
487{
488 u32 type;
489 u32 length;
490 enum v4l2_memory memory;
Pawel Osciak52a30822010-07-29 14:56:47 -0300491 struct v4l2_plane32 __user *uplane32;
492 struct v4l2_plane __user *uplane;
493 compat_caddr_t p;
Pawel Osciak52a30822010-07-29 14:56:47 -0300494 int ret;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200495
Hans Verkuildaff4d02018-02-14 12:48:22 +0100496 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100497 assign_in_user(&kp->index, &up->index) ||
498 get_user(type, &up->type) ||
499 put_user(type, &kp->type) ||
500 assign_in_user(&kp->flags, &up->flags) ||
501 get_user(memory, &up->memory) ||
502 put_user(memory, &kp->memory) ||
503 get_user(length, &up->length) ||
504 put_user(length, &kp->length))
Hans Verkuil02129c92018-02-14 12:48:20 +0100505 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200506
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100507 if (V4L2_TYPE_IS_OUTPUT(type))
508 if (assign_in_user(&kp->bytesused, &up->bytesused) ||
509 assign_in_user(&kp->field, &up->field) ||
510 assign_in_user(&kp->timestamp.tv_sec,
511 &up->timestamp.tv_sec) ||
512 assign_in_user(&kp->timestamp.tv_usec,
513 &up->timestamp.tv_usec))
Philippe De Muytercf664a62006-01-09 15:24:59 -0200514 return -EFAULT;
515
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100516 if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
517 u32 num_planes = length;
Al Viro5b1a43d2006-02-01 05:24:20 -0500518
Pawel Osciak52a30822010-07-29 14:56:47 -0300519 if (num_planes == 0) {
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100520 /*
521 * num_planes == 0 is legal, e.g. when userspace doesn't
522 * need planes array on DQBUF
523 */
524 return put_user(NULL, &kp->m.planes);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200525 }
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100526 if (num_planes > VIDEO_MAX_PLANES)
527 return -EINVAL;
Pawel Osciak52a30822010-07-29 14:56:47 -0300528
529 if (get_user(p, &up->m.planes))
Guy Martina113bc72006-01-11 23:40:51 -0200530 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300531
532 uplane32 = compat_ptr(p);
533 if (!access_ok(VERIFY_READ, uplane32,
Hans Verkuildaff4d02018-02-14 12:48:22 +0100534 num_planes * sizeof(*uplane32)))
Pawel Osciak52a30822010-07-29 14:56:47 -0300535 return -EFAULT;
536
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100537 /*
538 * We don't really care if userspace decides to kill itself
539 * by passing a very big num_planes value
540 */
541 if (aux_space < num_planes * sizeof(*uplane))
542 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300543
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100544 uplane = aux_buf;
545 if (put_user((__force struct v4l2_plane *)uplane,
546 &kp->m.planes))
547 return -EFAULT;
548
549 while (num_planes--) {
550 ret = get_v4l2_plane32(uplane, uplane32, memory);
Pawel Osciak52a30822010-07-29 14:56:47 -0300551 if (ret)
552 return ret;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100553 uplane++;
554 uplane32++;
Pawel Osciak52a30822010-07-29 14:56:47 -0300555 }
556 } else {
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100557 switch (memory) {
Pawel Osciak52a30822010-07-29 14:56:47 -0300558 case V4L2_MEMORY_MMAP:
Pawel Osciak52a30822010-07-29 14:56:47 -0300559 case V4L2_MEMORY_OVERLAY:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100560 if (assign_in_user(&kp->m.offset, &up->m.offset))
Pawel Osciak52a30822010-07-29 14:56:47 -0300561 return -EFAULT;
562 break;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100563 case V4L2_MEMORY_USERPTR: {
564 compat_ulong_t userptr;
Pawel Osciak52a30822010-07-29 14:56:47 -0300565
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100566 if (get_user(userptr, &up->m.userptr) ||
567 put_user((unsigned long)compat_ptr(userptr),
568 &kp->m.userptr))
569 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300570 break;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100571 }
Sumit Semwal051c7782012-06-14 10:37:35 -0300572 case V4L2_MEMORY_DMABUF:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100573 if (assign_in_user(&kp->m.fd, &up->m.fd))
Sumit Semwal051c7782012-06-14 10:37:35 -0300574 return -EFAULT;
575 break;
Pawel Osciak52a30822010-07-29 14:56:47 -0300576 }
Philippe De Muytercf664a62006-01-09 15:24:59 -0200577 }
Pawel Osciak52a30822010-07-29 14:56:47 -0300578
Philippe De Muytercf664a62006-01-09 15:24:59 -0200579 return 0;
580}
581
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100582static int put_v4l2_buffer32(struct v4l2_buffer __user *kp,
583 struct v4l2_buffer32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200584{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100585 u32 type;
586 u32 length;
587 enum v4l2_memory memory;
Pawel Osciak52a30822010-07-29 14:56:47 -0300588 struct v4l2_plane32 __user *uplane32;
589 struct v4l2_plane __user *uplane;
590 compat_caddr_t p;
Pawel Osciak52a30822010-07-29 14:56:47 -0300591 int ret;
592
Hans Verkuildaff4d02018-02-14 12:48:22 +0100593 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100594 assign_in_user(&up->index, &kp->index) ||
595 get_user(type, &kp->type) ||
596 put_user(type, &up->type) ||
597 assign_in_user(&up->flags, &kp->flags) ||
598 get_user(memory, &kp->memory) ||
599 put_user(memory, &up->memory))
Hans Verkuil02129c92018-02-14 12:48:20 +0100600 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300601
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100602 if (assign_in_user(&up->bytesused, &kp->bytesused) ||
603 assign_in_user(&up->field, &kp->field) ||
604 assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
605 assign_in_user(&up->timestamp.tv_usec, &kp->timestamp.tv_usec) ||
606 copy_in_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) ||
607 assign_in_user(&up->sequence, &kp->sequence) ||
608 assign_in_user(&up->reserved2, &kp->reserved2) ||
609 assign_in_user(&up->reserved, &kp->reserved) ||
610 get_user(length, &kp->length) ||
611 put_user(length, &up->length))
Hans Verkuil02129c92018-02-14 12:48:20 +0100612 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300613
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100614 if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
615 u32 num_planes = length;
616
Pawel Osciak52a30822010-07-29 14:56:47 -0300617 if (num_planes == 0)
618 return 0;
619
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100620 if (get_user(uplane, ((__force struct v4l2_plane __user **)&kp->m.planes)))
621 return -EFAULT;
Pawel Osciak52a30822010-07-29 14:56:47 -0300622 if (get_user(p, &up->m.planes))
623 return -EFAULT;
624 uplane32 = compat_ptr(p);
625
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100626 while (num_planes--) {
627 ret = put_v4l2_plane32(uplane, uplane32, memory);
Pawel Osciak52a30822010-07-29 14:56:47 -0300628 if (ret)
629 return ret;
630 ++uplane;
631 ++uplane32;
632 }
633 } else {
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100634 switch (memory) {
Pawel Osciak52a30822010-07-29 14:56:47 -0300635 case V4L2_MEMORY_MMAP:
Hans Verkuileec95542018-02-14 12:48:23 +0100636 case V4L2_MEMORY_OVERLAY:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100637 if (assign_in_user(&up->m.offset, &kp->m.offset))
Pawel Osciak52a30822010-07-29 14:56:47 -0300638 return -EFAULT;
639 break;
640 case V4L2_MEMORY_USERPTR:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100641 if (assign_in_user(&up->m.userptr, &kp->m.userptr))
Pawel Osciak52a30822010-07-29 14:56:47 -0300642 return -EFAULT;
643 break;
Sumit Semwal051c7782012-06-14 10:37:35 -0300644 case V4L2_MEMORY_DMABUF:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100645 if (assign_in_user(&up->m.fd, &kp->m.fd))
Sumit Semwal051c7782012-06-14 10:37:35 -0300646 return -EFAULT;
647 break;
Pawel Osciak52a30822010-07-29 14:56:47 -0300648 }
649 }
650
Philippe De Muytercf664a62006-01-09 15:24:59 -0200651 return 0;
652}
653
Hans Verkuild1f81da2008-10-22 00:04:45 -0300654struct v4l2_framebuffer32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200655 __u32 capability;
656 __u32 flags;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100657 compat_caddr_t base;
Laurent Pinchartd52e2382014-05-27 09:41:05 -0300658 struct {
659 __u32 width;
660 __u32 height;
661 __u32 pixelformat;
662 __u32 field;
663 __u32 bytesperline;
664 __u32 sizeimage;
665 __u32 colorspace;
666 __u32 priv;
667 } fmt;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200668};
669
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100670static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
671 struct v4l2_framebuffer32 __user *up)
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200672{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100673 compat_caddr_t tmp;
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200674
Hans Verkuildaff4d02018-02-14 12:48:22 +0100675 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Hans Verkuil02129c92018-02-14 12:48:20 +0100676 get_user(tmp, &up->base) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100677 put_user((__force void *)compat_ptr(tmp), &kp->base) ||
678 assign_in_user(&kp->capability, &up->capability) ||
679 assign_in_user(&kp->flags, &up->flags) ||
680 copy_in_user(&kp->fmt, &up->fmt, sizeof(kp->fmt)))
Hans Verkuil02129c92018-02-14 12:48:20 +0100681 return -EFAULT;
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200682 return 0;
683}
684
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100685static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
686 struct v4l2_framebuffer32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200687{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100688 void *base;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200689
Hans Verkuildaff4d02018-02-14 12:48:22 +0100690 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100691 get_user(base, &kp->base) ||
692 put_user(ptr_to_compat(base), &up->base) ||
693 assign_in_user(&up->capability, &kp->capability) ||
694 assign_in_user(&up->flags, &kp->flags) ||
695 copy_in_user(&up->fmt, &kp->fmt, sizeof(kp->fmt)))
Hans Verkuil02129c92018-02-14 12:48:20 +0100696 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200697 return 0;
698}
699
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300700struct v4l2_input32 {
701 __u32 index; /* Which input */
702 __u8 name[32]; /* Label */
703 __u32 type; /* Type of input */
704 __u32 audioset; /* Associated audios (bitfield) */
705 __u32 tuner; /* Associated tuner */
Andrzej Hajda655e9782015-08-31 08:56:15 -0300706 compat_u64 std;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300707 __u32 status;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100708 __u32 capabilities;
709 __u32 reserved[3];
Andrzej Hajda655e9782015-08-31 08:56:15 -0300710};
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300711
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100712/*
713 * The 64-bit v4l2_input struct has extra padding at the end of the struct.
714 * Otherwise it is identical to the 32-bit version.
715 */
716static inline int get_v4l2_input32(struct v4l2_input __user *kp,
717 struct v4l2_input32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200718{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100719 if (copy_in_user(kp, up, sizeof(*up)))
Al Viro5b1a43d2006-02-01 05:24:20 -0500720 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200721 return 0;
722}
723
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100724static inline int put_v4l2_input32(struct v4l2_input __user *kp,
725 struct v4l2_input32 __user *up)
Guy Martina113bc72006-01-11 23:40:51 -0200726{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100727 if (copy_in_user(up, kp, sizeof(*up)))
Al Viro5b1a43d2006-02-01 05:24:20 -0500728 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200729 return 0;
730}
731
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300732struct v4l2_ext_controls32 {
Ricardo Ribalda0f8017b2015-10-29 08:10:28 -0200733 __u32 which;
Ricardo Ribalda28c50292015-08-21 10:19:22 -0300734 __u32 count;
735 __u32 error_idx;
736 __u32 reserved[2];
737 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300738};
739
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300740struct v4l2_ext_control32 {
741 __u32 id;
742 __u32 size;
743 __u32 reserved2[1];
744 union {
745 __s32 value;
746 __s64 value64;
747 compat_caddr_t string; /* actually char * */
748 };
749} __attribute__ ((packed));
750
Hans Verkuil9a7cd412018-02-14 12:48:24 +0100751/* Return true if this control is a pointer type. */
752static inline bool ctrl_is_pointer(struct file *file, u32 id)
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300753{
Hans Verkuil9a7cd412018-02-14 12:48:24 +0100754 struct video_device *vdev = video_devdata(file);
755 struct v4l2_fh *fh = NULL;
756 struct v4l2_ctrl_handler *hdl = NULL;
757 struct v4l2_query_ext_ctrl qec = { id };
758 const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
759
760 if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
761 fh = file->private_data;
762
763 if (fh && fh->ctrl_handler)
764 hdl = fh->ctrl_handler;
765 else if (vdev->ctrl_handler)
766 hdl = vdev->ctrl_handler;
767
768 if (hdl) {
769 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
770
771 return ctrl && ctrl->is_ptr;
Eduardo Valentinfdf82dc2009-08-11 18:49:12 -0300772 }
Hans Verkuil9a7cd412018-02-14 12:48:24 +0100773
Hans Verkuil84656572018-02-14 12:48:25 +0100774 if (!ops || !ops->vidioc_query_ext_ctrl)
Hans Verkuil9a7cd412018-02-14 12:48:24 +0100775 return false;
776
777 return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
778 (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300779}
780
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100781static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user *up,
782 u32 *size)
783{
784 u32 count;
785
786 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
787 get_user(count, &up->count))
788 return -EFAULT;
789 if (count > V4L2_CID_MAX_CTRLS)
790 return -EINVAL;
791 *size = count * sizeof(struct v4l2_ext_control);
792 return 0;
793}
794
Hans Verkuil9a7cd412018-02-14 12:48:24 +0100795static int get_v4l2_ext_controls32(struct file *file,
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100796 struct v4l2_ext_controls __user *kp,
797 struct v4l2_ext_controls32 __user *up,
798 void __user *aux_buf, u32 aux_space)
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300799{
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300800 struct v4l2_ext_control32 __user *ucontrols;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300801 struct v4l2_ext_control __user *kcontrols;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100802 u32 count;
803 u32 n;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300804 compat_caddr_t p;
805
Hans Verkuildaff4d02018-02-14 12:48:22 +0100806 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100807 assign_in_user(&kp->which, &up->which) ||
808 get_user(count, &up->count) ||
809 put_user(count, &kp->count) ||
810 assign_in_user(&kp->error_idx, &up->error_idx) ||
811 copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
Hans Verkuil02129c92018-02-14 12:48:20 +0100812 return -EFAULT;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100813
814 if (count == 0)
815 return put_user(NULL, &kp->controls);
816 if (count > V4L2_CID_MAX_CTRLS)
817 return -EINVAL;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300818 if (get_user(p, &up->controls))
819 return -EFAULT;
820 ucontrols = compat_ptr(p);
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100821 if (!access_ok(VERIFY_READ, ucontrols, count * sizeof(*ucontrols)))
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300822 return -EFAULT;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100823 if (aux_space < count * sizeof(*kcontrols))
824 return -EFAULT;
825 kcontrols = aux_buf;
826 if (put_user((__force struct v4l2_ext_control *)kcontrols,
827 &kp->controls))
828 return -EFAULT;
829
830 for (n = 0; n < count; n++) {
Hans Verkuil8ae632b2014-08-21 17:07:21 -0300831 u32 id;
832
Pawel Osciak52a30822010-07-29 14:56:47 -0300833 if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300834 return -EFAULT;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100835
Hans Verkuil8ae632b2014-08-21 17:07:21 -0300836 if (get_user(id, &kcontrols->id))
837 return -EFAULT;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100838
Hans Verkuil9a7cd412018-02-14 12:48:24 +0100839 if (ctrl_is_pointer(file, id)) {
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300840 void __user *s;
841
842 if (get_user(p, &ucontrols->string))
843 return -EFAULT;
844 s = compat_ptr(p);
845 if (put_user(s, &kcontrols->string))
846 return -EFAULT;
847 }
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300848 ucontrols++;
849 kcontrols++;
850 }
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300851 return 0;
852}
853
Hans Verkuil9a7cd412018-02-14 12:48:24 +0100854static int put_v4l2_ext_controls32(struct file *file,
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100855 struct v4l2_ext_controls __user *kp,
Hans Verkuil9a7cd412018-02-14 12:48:24 +0100856 struct v4l2_ext_controls32 __user *up)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200857{
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300858 struct v4l2_ext_control32 __user *ucontrols;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100859 struct v4l2_ext_control __user *kcontrols;
860 u32 count;
861 u32 n;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300862 compat_caddr_t p;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200863
Hans Verkuildaff4d02018-02-14 12:48:22 +0100864 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100865 assign_in_user(&up->which, &kp->which) ||
866 get_user(count, &kp->count) ||
867 put_user(count, &up->count) ||
868 assign_in_user(&up->error_idx, &kp->error_idx) ||
869 copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)) ||
870 get_user(kcontrols, &kp->controls))
Hans Verkuil02129c92018-02-14 12:48:20 +0100871 return -EFAULT;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300872
Mauro Carvalho Chehab1e6b50b2018-04-11 11:47:32 -0400873 if (!count || count > (U32_MAX/sizeof(*ucontrols)))
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100874 return 0;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300875 if (get_user(p, &up->controls))
876 return -EFAULT;
877 ucontrols = compat_ptr(p);
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100878 if (!access_ok(VERIFY_WRITE, ucontrols, count * sizeof(*ucontrols)))
Guy Martina113bc72006-01-11 23:40:51 -0200879 return -EFAULT;
880
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100881 for (n = 0; n < count; n++) {
882 unsigned int size = sizeof(*ucontrols);
Hans Verkuil8ae632b2014-08-21 17:07:21 -0300883 u32 id;
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300884
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100885 if (get_user(id, &kcontrols->id) ||
886 put_user(id, &ucontrols->id) ||
887 assign_in_user(&ucontrols->size, &kcontrols->size) ||
888 copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
889 sizeof(ucontrols->reserved2)))
Hans Verkuil8ae632b2014-08-21 17:07:21 -0300890 return -EFAULT;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100891
892 /*
893 * Do not modify the pointer when copying a pointer control.
894 * The contents of the pointer was changed, not the pointer
895 * itself.
896 */
Hans Verkuil9a7cd412018-02-14 12:48:24 +0100897 if (ctrl_is_pointer(file, id))
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300898 size -= sizeof(ucontrols->value64);
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100899
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300900 if (copy_in_user(ucontrols, kcontrols, size))
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300901 return -EFAULT;
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100902
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300903 ucontrols++;
904 kcontrols++;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200905 }
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300906 return 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200907}
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300908
Hans Verkuil2330fb82011-06-07 11:43:57 -0300909struct v4l2_event32 {
910 __u32 type;
911 union {
Andrzej Hajda655e9782015-08-31 08:56:15 -0300912 compat_s64 value64;
Hans Verkuil2330fb82011-06-07 11:43:57 -0300913 __u8 data[64];
914 } u;
915 __u32 pending;
916 __u32 sequence;
917 struct compat_timespec timestamp;
918 __u32 id;
919 __u32 reserved[8];
920};
921
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100922static int put_v4l2_event32(struct v4l2_event __user *kp,
923 struct v4l2_event32 __user *up)
Hans Verkuil2330fb82011-06-07 11:43:57 -0300924{
Hans Verkuildaff4d02018-02-14 12:48:22 +0100925 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100926 assign_in_user(&up->type, &kp->type) ||
927 copy_in_user(&up->u, &kp->u, sizeof(kp->u)) ||
928 assign_in_user(&up->pending, &kp->pending) ||
929 assign_in_user(&up->sequence, &kp->sequence) ||
930 assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
931 assign_in_user(&up->timestamp.tv_nsec, &kp->timestamp.tv_nsec) ||
932 assign_in_user(&up->id, &kp->id) ||
933 copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
Hans Verkuil02129c92018-02-14 12:48:20 +0100934 return -EFAULT;
Hans Verkuil2330fb82011-06-07 11:43:57 -0300935 return 0;
936}
937
Hans Verkuildd519bb2014-03-07 07:18:37 -0300938struct v4l2_edid32 {
Hans Verkuiled45ce22012-08-10 06:07:12 -0300939 __u32 pad;
940 __u32 start_block;
941 __u32 blocks;
942 __u32 reserved[5];
943 compat_caddr_t edid;
944};
945
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100946static int get_v4l2_edid32(struct v4l2_edid __user *kp,
947 struct v4l2_edid32 __user *up)
Hans Verkuiled45ce22012-08-10 06:07:12 -0300948{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100949 compat_uptr_t tmp;
Hans Verkuiled45ce22012-08-10 06:07:12 -0300950
Hans Verkuildaff4d02018-02-14 12:48:22 +0100951 if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100952 assign_in_user(&kp->pad, &up->pad) ||
953 assign_in_user(&kp->start_block, &up->start_block) ||
954 assign_in_user(&kp->blocks, &up->blocks) ||
Hans Verkuil02129c92018-02-14 12:48:20 +0100955 get_user(tmp, &up->edid) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100956 put_user(compat_ptr(tmp), &kp->edid) ||
957 copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
Hans Verkuil02129c92018-02-14 12:48:20 +0100958 return -EFAULT;
Hans Verkuiled45ce22012-08-10 06:07:12 -0300959 return 0;
960}
961
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100962static int put_v4l2_edid32(struct v4l2_edid __user *kp,
963 struct v4l2_edid32 __user *up)
Hans Verkuiled45ce22012-08-10 06:07:12 -0300964{
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100965 void *edid;
Hans Verkuiled45ce22012-08-10 06:07:12 -0300966
Hans Verkuildaff4d02018-02-14 12:48:22 +0100967 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100968 assign_in_user(&up->pad, &kp->pad) ||
969 assign_in_user(&up->start_block, &kp->start_block) ||
970 assign_in_user(&up->blocks, &kp->blocks) ||
971 get_user(edid, &kp->edid) ||
972 put_user(ptr_to_compat(edid), &up->edid) ||
973 copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
Hans Verkuil02129c92018-02-14 12:48:20 +0100974 return -EFAULT;
Hans Verkuiled45ce22012-08-10 06:07:12 -0300975 return 0;
976}
977
978
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300979#define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32)
980#define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32)
981#define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32)
982#define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
983#define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
984#define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32)
985#define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32)
986#define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32)
987#define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
Hans Verkuildd519bb2014-03-07 07:18:37 -0300988#define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32)
989#define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32)
Daniel Mentzf2d4bed2018-02-14 12:48:30 +0100990#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300991#define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
992#define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
993#define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
Hans Verkuil2330fb82011-06-07 11:43:57 -0300994#define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32)
Guennadi Liakhovetski21501582011-09-28 11:34:06 -0300995#define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32)
996#define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32)
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300997
998#define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300999#define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
1000#define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32)
1001#define VIDIOC_G_INPUT32 _IOR ('V', 38, s32)
1002#define VIDIOC_S_INPUT32 _IOWR('V', 39, s32)
1003#define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
1004#define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001005
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001006static int alloc_userspace(unsigned int size, u32 aux_space,
1007 void __user **up_native)
1008{
1009 *up_native = compat_alloc_user_space(size + aux_space);
1010 if (!*up_native)
1011 return -ENOMEM;
1012 if (clear_user(*up_native, size))
1013 return -EFAULT;
1014 return 0;
1015}
1016
Hans Verkuil069b7472008-12-30 07:04:34 -03001017static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001018{
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001019 void __user *up = compat_ptr(arg);
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001020 void __user *up_native = NULL;
1021 void __user *aux_buf;
1022 u32 aux_space;
Philippe De Muytercf664a62006-01-09 15:24:59 -02001023 int compatible_arg = 1;
Hans Verkuil069b7472008-12-30 07:04:34 -03001024 long err = 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001025
1026 /* First, convert the command. */
Hans Verkuild1f81da2008-10-22 00:04:45 -03001027 switch (cmd) {
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001028 case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
1029 case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
1030 case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
1031 case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
1032 case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
1033 case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
1034 case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
1035 case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break;
1036 case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break;
1037 case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
1038 case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break;
1039 case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
1040 case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
Hans Verkuil2330fb82011-06-07 11:43:57 -03001041 case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001042 case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001043 case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
1044 case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
1045 case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
1046 case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
1047 case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
1048 case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001049 case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
1050 case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
Hans Verkuildd519bb2014-03-07 07:18:37 -03001051 case VIDIOC_G_EDID32: cmd = VIDIOC_G_EDID; break;
1052 case VIDIOC_S_EDID32: cmd = VIDIOC_S_EDID; break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001053 }
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001054
Hans Verkuild1f81da2008-10-22 00:04:45 -03001055 switch (cmd) {
Philippe De Muytercf664a62006-01-09 15:24:59 -02001056 case VIDIOC_OVERLAY:
Philippe De Muyter13d133b2006-01-09 15:25:00 -02001057 case VIDIOC_STREAMON:
1058 case VIDIOC_STREAMOFF:
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001059 case VIDIOC_S_INPUT:
1060 case VIDIOC_S_OUTPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001061 err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
1062 if (!err && assign_in_user((unsigned int __user *)up_native,
1063 (compat_uint_t __user *)up))
1064 err = -EFAULT;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001065 compatible_arg = 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001066 break;
Philippe De Muyter13d133b2006-01-09 15:25:00 -02001067
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001068 case VIDIOC_G_INPUT:
1069 case VIDIOC_G_OUTPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001070 err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
Philippe De Muyter13d133b2006-01-09 15:25:00 -02001071 compatible_arg = 0;
1072 break;
Philippe De Muytercf664a62006-01-09 15:24:59 -02001073
Hans Verkuildd519bb2014-03-07 07:18:37 -03001074 case VIDIOC_G_EDID:
1075 case VIDIOC_S_EDID:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001076 err = alloc_userspace(sizeof(struct v4l2_edid), 0, &up_native);
1077 if (!err)
1078 err = get_v4l2_edid32(up_native, up);
Hans Verkuiled45ce22012-08-10 06:07:12 -03001079 compatible_arg = 0;
1080 break;
1081
Philippe De Muytercf664a62006-01-09 15:24:59 -02001082 case VIDIOC_G_FMT:
1083 case VIDIOC_S_FMT:
1084 case VIDIOC_TRY_FMT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001085 err = bufsize_v4l2_format(up, &aux_space);
1086 if (!err)
1087 err = alloc_userspace(sizeof(struct v4l2_format),
1088 aux_space, &up_native);
1089 if (!err) {
1090 aux_buf = up_native + sizeof(struct v4l2_format);
1091 err = get_v4l2_format32(up_native, up,
1092 aux_buf, aux_space);
1093 }
Philippe De Muytercf664a62006-01-09 15:24:59 -02001094 compatible_arg = 0;
1095 break;
1096
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001097 case VIDIOC_CREATE_BUFS:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001098 err = bufsize_v4l2_create(up, &aux_space);
1099 if (!err)
1100 err = alloc_userspace(sizeof(struct v4l2_create_buffers),
1101 aux_space, &up_native);
1102 if (!err) {
1103 aux_buf = up_native + sizeof(struct v4l2_create_buffers);
1104 err = get_v4l2_create32(up_native, up,
1105 aux_buf, aux_space);
1106 }
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001107 compatible_arg = 0;
1108 break;
1109
1110 case VIDIOC_PREPARE_BUF:
Philippe De Muytercf664a62006-01-09 15:24:59 -02001111 case VIDIOC_QUERYBUF:
1112 case VIDIOC_QBUF:
1113 case VIDIOC_DQBUF:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001114 err = bufsize_v4l2_buffer(up, &aux_space);
1115 if (!err)
1116 err = alloc_userspace(sizeof(struct v4l2_buffer),
1117 aux_space, &up_native);
1118 if (!err) {
1119 aux_buf = up_native + sizeof(struct v4l2_buffer);
1120 err = get_v4l2_buffer32(up_native, up,
1121 aux_buf, aux_space);
1122 }
Philippe De Muytercf664a62006-01-09 15:24:59 -02001123 compatible_arg = 0;
1124 break;
1125
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001126 case VIDIOC_S_FBUF:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001127 err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
1128 &up_native);
1129 if (!err)
1130 err = get_v4l2_framebuffer32(up_native, up);
Guy Martina113bc72006-01-11 23:40:51 -02001131 compatible_arg = 0;
1132 break;
1133
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001134 case VIDIOC_G_FBUF:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001135 err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
1136 &up_native);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001137 compatible_arg = 0;
1138 break;
1139
1140 case VIDIOC_ENUMSTD:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001141 err = alloc_userspace(sizeof(struct v4l2_standard), 0,
1142 &up_native);
1143 if (!err)
1144 err = get_v4l2_standard32(up_native, up);
Philippe De Muytercf664a62006-01-09 15:24:59 -02001145 compatible_arg = 0;
1146 break;
1147
Guy Martina113bc72006-01-11 23:40:51 -02001148 case VIDIOC_ENUMINPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001149 err = alloc_userspace(sizeof(struct v4l2_input), 0, &up_native);
1150 if (!err)
1151 err = get_v4l2_input32(up_native, up);
Guy Martina113bc72006-01-11 23:40:51 -02001152 compatible_arg = 0;
1153 break;
1154
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001155 case VIDIOC_G_EXT_CTRLS:
1156 case VIDIOC_S_EXT_CTRLS:
1157 case VIDIOC_TRY_EXT_CTRLS:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001158 err = bufsize_v4l2_ext_controls(up, &aux_space);
1159 if (!err)
1160 err = alloc_userspace(sizeof(struct v4l2_ext_controls),
1161 aux_space, &up_native);
1162 if (!err) {
1163 aux_buf = up_native + sizeof(struct v4l2_ext_controls);
1164 err = get_v4l2_ext_controls32(file, up_native, up,
1165 aux_buf, aux_space);
1166 }
Guy Martina113bc72006-01-11 23:40:51 -02001167 compatible_arg = 0;
1168 break;
Hans Verkuil2330fb82011-06-07 11:43:57 -03001169 case VIDIOC_DQEVENT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001170 err = alloc_userspace(sizeof(struct v4l2_event), 0, &up_native);
Hans Verkuil2330fb82011-06-07 11:43:57 -03001171 compatible_arg = 0;
1172 break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001173 }
Hans Verkuild1f81da2008-10-22 00:04:45 -03001174 if (err)
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001175 return err;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001176
Hans Verkuild1f81da2008-10-22 00:04:45 -03001177 if (compatible_arg)
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001178 err = native_ioctl(file, cmd, (unsigned long)up);
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001179 else
1180 err = native_ioctl(file, cmd, (unsigned long)up_native);
Blagovest Kolenichev8c745432018-02-26 04:59:56 -08001181
Hans Verkuil437c4ec2018-02-14 12:48:29 +01001182 if (err == -ENOTTY)
1183 return err;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001184
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001185 /*
1186 * Special case: even after an error we need to put the
1187 * results back for these ioctls since the error_idx will
1188 * contain information on which control failed.
1189 */
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001190 switch (cmd) {
1191 case VIDIOC_G_EXT_CTRLS:
1192 case VIDIOC_S_EXT_CTRLS:
1193 case VIDIOC_TRY_EXT_CTRLS:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001194 if (put_v4l2_ext_controls32(file, up_native, up))
1195 err = -EFAULT;
1196 break;
1197 case VIDIOC_S_EDID:
1198 if (put_v4l2_edid32(up_native, up))
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001199 err = -EFAULT;
1200 break;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001201 }
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001202 if (err)
1203 return err;
1204
1205 switch (cmd) {
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001206 case VIDIOC_S_INPUT:
1207 case VIDIOC_S_OUTPUT:
1208 case VIDIOC_G_INPUT:
1209 case VIDIOC_G_OUTPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001210 if (assign_in_user((compat_uint_t __user *)up,
1211 ((unsigned int __user *)up_native)))
1212 err = -EFAULT;
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001213 break;
1214
1215 case VIDIOC_G_FBUF:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001216 err = put_v4l2_framebuffer32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001217 break;
1218
Hans Verkuil2330fb82011-06-07 11:43:57 -03001219 case VIDIOC_DQEVENT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001220 err = put_v4l2_event32(up_native, up);
Hans Verkuil2330fb82011-06-07 11:43:57 -03001221 break;
1222
Hans Verkuildd519bb2014-03-07 07:18:37 -03001223 case VIDIOC_G_EDID:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001224 err = put_v4l2_edid32(up_native, up);
Hans Verkuiled45ce22012-08-10 06:07:12 -03001225 break;
1226
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001227 case VIDIOC_G_FMT:
1228 case VIDIOC_S_FMT:
1229 case VIDIOC_TRY_FMT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001230 err = put_v4l2_format32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001231 break;
1232
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001233 case VIDIOC_CREATE_BUFS:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001234 err = put_v4l2_create32(up_native, up);
Guennadi Liakhovetski21501582011-09-28 11:34:06 -03001235 break;
1236
Hans Verkuilf2945482018-02-14 12:48:19 +01001237 case VIDIOC_PREPARE_BUF:
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001238 case VIDIOC_QUERYBUF:
1239 case VIDIOC_QBUF:
1240 case VIDIOC_DQBUF:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001241 err = put_v4l2_buffer32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001242 break;
1243
1244 case VIDIOC_ENUMSTD:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001245 err = put_v4l2_standard32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001246 break;
1247
1248 case VIDIOC_ENUMINPUT:
Daniel Mentzf2d4bed2018-02-14 12:48:30 +01001249 err = put_v4l2_input32(up_native, up);
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001250 break;
1251 }
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001252 return err;
1253}
1254
Hans Verkuil9bb7cde2008-12-30 06:42:40 -03001255long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001256{
Laurent Pinchartb9d0aa62011-12-18 20:41:19 -03001257 struct video_device *vdev = video_devdata(file);
Hans Verkuil069b7472008-12-30 07:04:34 -03001258 long ret = -ENOIOCTLCMD;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001259
Frederic Weisbeckerc6d7ba82010-08-13 22:29:03 +02001260 if (!file->f_op->unlocked_ioctl)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001261 return ret;
1262
Hans Verkuilab58a302014-02-10 08:08:44 -03001263 if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001264 ret = do_video_ioctl(file, cmd, arg);
Hans Verkuilab58a302014-02-10 08:08:44 -03001265 else if (vdev->fops->compat_ioctl32)
1266 ret = vdev->fops->compat_ioctl32(file, cmd, arg);
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001267
Hans Verkuilab58a302014-02-10 08:08:44 -03001268 if (ret == -ENOIOCTLCMD)
Hans Verkuil9ec32cc2015-09-09 03:40:39 -03001269 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1270 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
Hans Verkuile8efb712006-01-09 15:24:59 -02001271 return ret;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001272}
Hans Verkuil9bb7cde2008-12-30 06:42:40 -03001273EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);