blob: 5084773d4f102866d20a31b054f34779bdf786b4 [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
8 * Copyright (C) 2003 Pavel Machek (pavel@suse.cz)
9 * 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>
Hans Verkuil92f45ba2008-12-21 10:35:25 -030017#define __OLD_VIDIOC_ /* To allow fixing old calls*/
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020018#include <linux/videodev.h>
Philippe De Muytercf664a62006-01-09 15:24:59 -020019#include <linux/videodev2.h>
Nickolay V. Shmyrev133b7352006-01-09 15:24:58 -020020#include <linux/module.h>
Hans Verkuile8efb712006-01-09 15:24:59 -020021#include <linux/smp_lock.h>
Mauro Carvalho Chehab28644622008-07-20 20:26:54 -030022#include <media/v4l2-ioctl.h>
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020023
24#ifdef CONFIG_COMPAT
Guy Martina113bc72006-01-11 23:40:51 -020025
Mauro Carvalho Chehab5bdd6cc2006-07-25 16:17:54 -030026#ifdef CONFIG_VIDEO_V4L1_COMPAT
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020027struct video_tuner32 {
28 compat_int_t tuner;
29 char name[32];
30 compat_ulong_t rangelow, rangehigh;
31 u32 flags; /* It is really u32 in videodev.h */
32 u16 mode, signal;
33};
34
35static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
36{
Hans Verkuild1f81da2008-10-22 00:04:45 -030037 if (!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) ||
Guy Martina113bc72006-01-11 23:40:51 -020038 get_user(kp->tuner, &up->tuner) ||
39 copy_from_user(kp->name, up->name, 32) ||
40 get_user(kp->rangelow, &up->rangelow) ||
41 get_user(kp->rangehigh, &up->rangehigh) ||
42 get_user(kp->flags, &up->flags) ||
43 get_user(kp->mode, &up->mode) ||
44 get_user(kp->signal, &up->signal))
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020045 return -EFAULT;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020046 return 0;
47}
48
49static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
50{
Hans Verkuild1f81da2008-10-22 00:04:45 -030051 if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) ||
Guy Martina113bc72006-01-11 23:40:51 -020052 put_user(kp->tuner, &up->tuner) ||
53 copy_to_user(up->name, kp->name, 32) ||
54 put_user(kp->rangelow, &up->rangelow) ||
55 put_user(kp->rangehigh, &up->rangehigh) ||
56 put_user(kp->flags, &up->flags) ||
57 put_user(kp->mode, &up->mode) ||
58 put_user(kp->signal, &up->signal))
59 return -EFAULT;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020060 return 0;
61}
62
63struct video_buffer32 {
64 compat_caddr_t base;
65 compat_int_t height, width, depth, bytesperline;
66};
67
68static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
69{
70 u32 tmp;
71
Guy Martina113bc72006-01-11 23:40:51 -020072 if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) ||
73 get_user(tmp, &up->base) ||
74 get_user(kp->height, &up->height) ||
75 get_user(kp->width, &up->width) ||
76 get_user(kp->depth, &up->depth) ||
77 get_user(kp->bytesperline, &up->bytesperline))
78 return -EFAULT;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020079
80 /* This is actually a physical address stored
81 * as a void pointer.
82 */
83 kp->base = (void *)(unsigned long) tmp;
84
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020085 return 0;
86}
87
88static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
89{
90 u32 tmp = (u32)((unsigned long)kp->base);
91
Hans Verkuild1f81da2008-10-22 00:04:45 -030092 if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) ||
Guy Martina113bc72006-01-11 23:40:51 -020093 put_user(tmp, &up->base) ||
94 put_user(kp->height, &up->height) ||
95 put_user(kp->width, &up->width) ||
96 put_user(kp->depth, &up->depth) ||
97 put_user(kp->bytesperline, &up->bytesperline))
98 return -EFAULT;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -020099 return 0;
100}
101
102struct video_clip32 {
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300103 s32 x, y, width, height; /* It's really s32 in videodev.h */
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200104 compat_caddr_t next;
105};
106
107struct video_window32 {
108 u32 x, y, width, height, chromakey, flags;
109 compat_caddr_t clips;
110 compat_int_t clipcount;
111};
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300112
113static int get_video_window32(struct video_window *kp, struct video_window32 __user *up)
114{
115 struct video_clip __user *uclips;
116 struct video_clip __user *kclips;
117 compat_caddr_t p;
118 int nclips;
119
120 if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)))
121 return -EFAULT;
122
123 if (get_user(nclips, &up->clipcount))
124 return -EFAULT;
125
126 if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)) ||
127 get_user(kp->x, &up->x) ||
128 get_user(kp->y, &up->y) ||
129 get_user(kp->width, &up->width) ||
130 get_user(kp->height, &up->height) ||
131 get_user(kp->chromakey, &up->chromakey) ||
132 get_user(kp->flags, &up->flags) ||
133 get_user(kp->clipcount, &up->clipcount))
134 return -EFAULT;
135
136 nclips = kp->clipcount;
137 kp->clips = NULL;
138
139 if (nclips == 0)
140 return 0;
141 if (get_user(p, &up->clips))
142 return -EFAULT;
143 uclips = compat_ptr(p);
144
145 /* If nclips < 0, then it is a clipping bitmap of size
146 VIDEO_CLIPMAP_SIZE */
147 if (nclips < 0) {
148 if (!access_ok(VERIFY_READ, uclips, VIDEO_CLIPMAP_SIZE))
149 return -EFAULT;
150 kp->clips = compat_alloc_user_space(VIDEO_CLIPMAP_SIZE);
151 if (copy_in_user(kp->clips, uclips, VIDEO_CLIPMAP_SIZE))
152 return -EFAULT;
153 return 0;
154 }
155
156 /* Otherwise it is an array of video_clip structs. */
157 if (!access_ok(VERIFY_READ, uclips, nclips * sizeof(struct video_clip)))
158 return -EFAULT;
159
160 kp->clips = compat_alloc_user_space(nclips * sizeof(struct video_clip));
161 kclips = kp->clips;
162 while (nclips--) {
163 int err;
164
165 err = copy_in_user(&kclips->x, &uclips->x, sizeof(kclips->x));
166 err |= copy_in_user(&kclips->y, &uclips->y, sizeof(kclips->y));
167 err |= copy_in_user(&kclips->width, &uclips->width, sizeof(kclips->width));
168 err |= copy_in_user(&kclips->height, &uclips->height, sizeof(kclips->height));
169 kclips->next = NULL;
170 if (err)
171 return -EFAULT;
172 kclips++;
173 uclips++;
174 }
175 return 0;
176}
177
178/* You get back everything except the clips... */
179static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
180{
181 if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) ||
182 put_user(kp->x, &up->x) ||
183 put_user(kp->y, &up->y) ||
184 put_user(kp->width, &up->width) ||
185 put_user(kp->height, &up->height) ||
186 put_user(kp->chromakey, &up->chromakey) ||
187 put_user(kp->flags, &up->flags) ||
188 put_user(kp->clipcount, &up->clipcount))
189 return -EFAULT;
190 return 0;
191}
192
193struct video_code32 {
194 char loadwhat[16]; /* name or tag of file being passed */
195 compat_int_t datasize;
196 unsigned char *data;
197};
198
199static int get_microcode32(struct video_code *kp, struct video_code32 __user *up)
200{
201 if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
202 copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
203 get_user(kp->datasize, &up->datasize) ||
204 copy_from_user(kp->data, up->data, up->datasize))
205 return -EFAULT;
206 return 0;
207}
208
209#define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32)
210#define VIDIOCSTUNER32 _IOW('v', 5, struct video_tuner32)
211#define VIDIOCGWIN32 _IOR('v', 9, struct video_window32)
212#define VIDIOCSWIN32 _IOW('v', 10, struct video_window32)
213#define VIDIOCGFBUF32 _IOR('v', 11, struct video_buffer32)
214#define VIDIOCSFBUF32 _IOW('v', 12, struct video_buffer32)
215#define VIDIOCGFREQ32 _IOR('v', 14, u32)
216#define VIDIOCSFREQ32 _IOW('v', 15, u32)
217#define VIDIOCSMICROCODE32 _IOW('v', 27, struct video_code32)
218
219#define VIDIOCCAPTURE32 _IOW('v', 8, s32)
220#define VIDIOCSYNC32 _IOW('v', 18, s32)
221#define VIDIOCSWRITEMODE32 _IOW('v', 25, s32)
222
Mauro Carvalho Chehab5bdd6cc2006-07-25 16:17:54 -0300223#endif
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200224
225static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
226{
227 int ret = -ENOIOCTLCMD;
228
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200229 if (file->f_op->unlocked_ioctl)
230 ret = file->f_op->unlocked_ioctl(file, cmd, arg);
231 else if (file->f_op->ioctl) {
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200232 lock_kernel();
Josef Sipek723731b2006-12-08 02:37:47 -0800233 ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200234 unlock_kernel();
235 }
236
237 return ret;
238}
239
240
Hans Verkuild1f81da2008-10-22 00:04:45 -0300241struct v4l2_clip32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200242 struct v4l2_rect c;
243 compat_caddr_t next;
244};
245
Hans Verkuild1f81da2008-10-22 00:04:45 -0300246struct v4l2_window32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200247 struct v4l2_rect w;
248 enum v4l2_field field;
249 __u32 chromakey;
250 compat_caddr_t clips; /* actually struct v4l2_clip32 * */
251 __u32 clipcount;
252 compat_caddr_t bitmap;
253};
254
255static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
256{
Guy Martina113bc72006-01-11 23:40:51 -0200257 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
258 copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
259 get_user(kp->field, &up->field) ||
260 get_user(kp->chromakey, &up->chromakey) ||
261 get_user(kp->clipcount, &up->clipcount))
262 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200263 if (kp->clipcount > 2048)
264 return -EINVAL;
265 if (kp->clipcount) {
Al Viro5b1a43d2006-02-01 05:24:20 -0500266 struct v4l2_clip32 __user *uclips;
267 struct v4l2_clip __user *kclips;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200268 int n = kp->clipcount;
Al Viro5b1a43d2006-02-01 05:24:20 -0500269 compat_caddr_t p;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200270
Al Viro5b1a43d2006-02-01 05:24:20 -0500271 if (get_user(p, &up->clips))
272 return -EFAULT;
273 uclips = compat_ptr(p);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200274 kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
275 kp->clips = kclips;
276 while (--n >= 0) {
Al Viro5b1a43d2006-02-01 05:24:20 -0500277 if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
Guy Martina113bc72006-01-11 23:40:51 -0200278 return -EFAULT;
Al Viro5b1a43d2006-02-01 05:24:20 -0500279 if (put_user(n ? kclips + 1 : NULL, &kclips->next))
280 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200281 uclips += 1;
282 kclips += 1;
283 }
284 } else
Al Viro5b1a43d2006-02-01 05:24:20 -0500285 kp->clips = NULL;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200286 return 0;
287}
288
289static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
290{
Al Viro5b1a43d2006-02-01 05:24:20 -0500291 if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) ||
Guy Martina113bc72006-01-11 23:40:51 -0200292 put_user(kp->field, &up->field) ||
293 put_user(kp->chromakey, &up->chromakey) ||
294 put_user(kp->clipcount, &up->clipcount))
295 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200296 return 0;
297}
298
299static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
300{
Al Viro5b1a43d2006-02-01 05:24:20 -0500301 if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
302 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200303 return 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200304}
305
306static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
307{
Al Viro5b1a43d2006-02-01 05:24:20 -0500308 if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
309 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200310 return 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200311}
312
313static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
314{
Al Viro5b1a43d2006-02-01 05:24:20 -0500315 if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
316 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200317 return 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200318}
319
320static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
321{
Al Viro5b1a43d2006-02-01 05:24:20 -0500322 if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
323 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200324 return 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200325}
326
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300327static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
328{
329 if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
330 return -EFAULT;
331 return 0;
332}
333
334static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
335{
336 if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
337 return -EFAULT;
338 return 0;
339}
340
Hans Verkuild1f81da2008-10-22 00:04:45 -0300341struct v4l2_format32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200342 enum v4l2_buf_type type;
Hans Verkuild1f81da2008-10-22 00:04:45 -0300343 union {
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300344 struct v4l2_pix_format pix;
345 struct v4l2_window32 win;
346 struct v4l2_vbi_format vbi;
347 struct v4l2_sliced_vbi_format sliced;
Hans Verkuild1f81da2008-10-22 00:04:45 -0300348 __u8 raw_data[200]; /* user-defined */
Philippe De Muytercf664a62006-01-09 15:24:59 -0200349 } fmt;
350};
351
352static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
353{
Guy Martina113bc72006-01-11 23:40:51 -0200354 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
355 get_user(kp->type, &up->type))
356 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200357 switch (kp->type) {
358 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300359 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Philippe De Muytercf664a62006-01-09 15:24:59 -0200360 return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
361 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300362 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Philippe De Muytercf664a62006-01-09 15:24:59 -0200363 return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
364 case V4L2_BUF_TYPE_VBI_CAPTURE:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300365 case V4L2_BUF_TYPE_VBI_OUTPUT:
Philippe De Muytercf664a62006-01-09 15:24:59 -0200366 return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300367 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
368 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
369 return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
370 case V4L2_BUF_TYPE_PRIVATE:
371 if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data)))
372 return -EFAULT;
373 return 0;
374 case 0:
375 return -EINVAL;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200376 default:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300377 printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
Philippe De Muytercf664a62006-01-09 15:24:59 -0200378 kp->type);
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300379 return -EINVAL;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200380 }
381}
382
383static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
384{
Hans Verkuild1f81da2008-10-22 00:04:45 -0300385 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
Guy Martina113bc72006-01-11 23:40:51 -0200386 put_user(kp->type, &up->type))
Philippe De Muytercf664a62006-01-09 15:24:59 -0200387 return -EFAULT;
388 switch (kp->type) {
389 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300390 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Philippe De Muytercf664a62006-01-09 15:24:59 -0200391 return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
392 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300393 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Philippe De Muytercf664a62006-01-09 15:24:59 -0200394 return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
395 case V4L2_BUF_TYPE_VBI_CAPTURE:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300396 case V4L2_BUF_TYPE_VBI_OUTPUT:
Philippe De Muytercf664a62006-01-09 15:24:59 -0200397 return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300398 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
399 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
400 return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
401 case V4L2_BUF_TYPE_PRIVATE:
402 if (copy_to_user(up, kp, sizeof(up->fmt.raw_data)))
403 return -EFAULT;
404 return 0;
405 case 0:
406 return -EINVAL;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200407 default:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300408 printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
409 kp->type);
410 return -EINVAL;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200411 }
412}
413
Hans Verkuild1f81da2008-10-22 00:04:45 -0300414struct v4l2_standard32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200415 __u32 index;
416 __u32 id[2]; /* __u64 would get the alignment wrong */
417 __u8 name[24];
418 struct v4l2_fract frameperiod; /* Frames, not fields */
419 __u32 framelines;
420 __u32 reserved[4];
421};
422
423static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
424{
425 /* other fields are not set by the user, nor used by the driver */
Guy Martina113bc72006-01-11 23:40:51 -0200426 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
427 get_user(kp->index, &up->index))
428 return -EFAULT;
429 return 0;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200430}
431
432static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
433{
Hans Verkuild1f81da2008-10-22 00:04:45 -0300434 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
Guy Martina113bc72006-01-11 23:40:51 -0200435 put_user(kp->index, &up->index) ||
436 copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
437 copy_to_user(up->name, kp->name, 24) ||
438 copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
439 put_user(kp->framelines, &up->framelines) ||
440 copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
441 return -EFAULT;
442 return 0;
443}
444
Hans Verkuild1f81da2008-10-22 00:04:45 -0300445struct v4l2_buffer32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200446 __u32 index;
447 enum v4l2_buf_type type;
448 __u32 bytesused;
449 __u32 flags;
450 enum v4l2_field field;
451 struct compat_timeval timestamp;
452 struct v4l2_timecode timecode;
453 __u32 sequence;
454
455 /* memory location */
456 enum v4l2_memory memory;
457 union {
458 __u32 offset;
459 compat_long_t userptr;
460 } m;
461 __u32 length;
462 __u32 input;
463 __u32 reserved;
464};
465
466static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
467{
468
Guy Martina113bc72006-01-11 23:40:51 -0200469 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
470 get_user(kp->index, &up->index) ||
471 get_user(kp->type, &up->type) ||
472 get_user(kp->flags, &up->flags) ||
473 get_user(kp->memory, &up->memory) ||
474 get_user(kp->input, &up->input))
475 return -EFAULT;
Hans Verkuild1f81da2008-10-22 00:04:45 -0300476 switch (kp->memory) {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200477 case V4L2_MEMORY_MMAP:
478 break;
479 case V4L2_MEMORY_USERPTR:
480 {
Al Viro5b1a43d2006-02-01 05:24:20 -0500481 compat_long_t tmp;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200482
Al Viro5b1a43d2006-02-01 05:24:20 -0500483 if (get_user(kp->length, &up->length) ||
484 get_user(tmp, &up->m.userptr))
485 return -EFAULT;
486
487 kp->m.userptr = (unsigned long)compat_ptr(tmp);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200488 }
489 break;
490 case V4L2_MEMORY_OVERLAY:
Hans Verkuild1f81da2008-10-22 00:04:45 -0300491 if (get_user(kp->m.offset, &up->m.offset))
Guy Martina113bc72006-01-11 23:40:51 -0200492 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200493 break;
494 }
495 return 0;
496}
497
498static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
499{
Guy Martina113bc72006-01-11 23:40:51 -0200500 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
501 put_user(kp->index, &up->index) ||
502 put_user(kp->type, &up->type) ||
503 put_user(kp->flags, &up->flags) ||
504 put_user(kp->memory, &up->memory) ||
505 put_user(kp->input, &up->input))
506 return -EFAULT;
Hans Verkuild1f81da2008-10-22 00:04:45 -0300507 switch (kp->memory) {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200508 case V4L2_MEMORY_MMAP:
Guy Martina113bc72006-01-11 23:40:51 -0200509 if (put_user(kp->length, &up->length) ||
510 put_user(kp->m.offset, &up->m.offset))
511 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200512 break;
513 case V4L2_MEMORY_USERPTR:
Guy Martina113bc72006-01-11 23:40:51 -0200514 if (put_user(kp->length, &up->length) ||
515 put_user(kp->m.userptr, &up->m.userptr))
516 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200517 break;
518 case V4L2_MEMORY_OVERLAY:
Guy Martina113bc72006-01-11 23:40:51 -0200519 if (put_user(kp->m.offset, &up->m.offset))
520 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200521 break;
522 }
Guy Martina113bc72006-01-11 23:40:51 -0200523 if (put_user(kp->bytesused, &up->bytesused) ||
524 put_user(kp->field, &up->field) ||
525 put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
526 put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
527 copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
528 put_user(kp->sequence, &up->sequence) ||
529 put_user(kp->reserved, &up->reserved))
530 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200531 return 0;
532}
533
Hans Verkuild1f81da2008-10-22 00:04:45 -0300534struct v4l2_framebuffer32 {
Philippe De Muytercf664a62006-01-09 15:24:59 -0200535 __u32 capability;
536 __u32 flags;
537 compat_caddr_t base;
538 struct v4l2_pix_format fmt;
539};
540
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200541static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
542{
543 u32 tmp;
544
Guy Martina113bc72006-01-11 23:40:51 -0200545 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
546 get_user(tmp, &up->base) ||
547 get_user(kp->capability, &up->capability) ||
548 get_user(kp->flags, &up->flags))
549 return -EFAULT;
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200550 kp->base = compat_ptr(tmp);
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200551 get_v4l2_pix_format(&kp->fmt, &up->fmt);
552 return 0;
553}
554
Philippe De Muytercf664a62006-01-09 15:24:59 -0200555static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
556{
557 u32 tmp = (u32)((unsigned long)kp->base);
558
Hans Verkuild1f81da2008-10-22 00:04:45 -0300559 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
Guy Martina113bc72006-01-11 23:40:51 -0200560 put_user(tmp, &up->base) ||
561 put_user(kp->capability, &up->capability) ||
562 put_user(kp->flags, &up->flags))
563 return -EFAULT;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200564 put_v4l2_pix_format(&kp->fmt, &up->fmt);
565 return 0;
566}
567
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300568struct v4l2_input32 {
569 __u32 index; /* Which input */
570 __u8 name[32]; /* Label */
571 __u32 type; /* Type of input */
572 __u32 audioset; /* Associated audios (bitfield) */
573 __u32 tuner; /* Associated tuner */
574 v4l2_std_id std;
575 __u32 status;
576 __u32 reserved[4];
577} __attribute__ ((packed));
578
579/* The 64-bit v4l2_input struct has extra padding at the end of the struct.
580 Otherwise it is identical to the 32-bit version. */
581static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
Philippe De Muytercf664a62006-01-09 15:24:59 -0200582{
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300583 if (copy_from_user(kp, up, sizeof(struct v4l2_input32)))
Al Viro5b1a43d2006-02-01 05:24:20 -0500584 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200585 return 0;
586}
587
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300588static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
Guy Martina113bc72006-01-11 23:40:51 -0200589{
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300590 if (copy_to_user(up, kp, sizeof(struct v4l2_input32)))
Al Viro5b1a43d2006-02-01 05:24:20 -0500591 return -EFAULT;
Guy Martina113bc72006-01-11 23:40:51 -0200592 return 0;
593}
594
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300595struct v4l2_ext_controls32 {
596 __u32 ctrl_class;
597 __u32 count;
598 __u32 error_idx;
599 __u32 reserved[2];
600 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300601};
602
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300603static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300604{
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300605 struct v4l2_ext_control __user *ucontrols;
606 struct v4l2_ext_control __user *kcontrols;
607 int n;
608 compat_caddr_t p;
609
610 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
611 get_user(kp->ctrl_class, &up->ctrl_class) ||
612 get_user(kp->count, &up->count) ||
613 get_user(kp->error_idx, &up->error_idx) ||
614 copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300615 return -EFAULT;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300616 n = kp->count;
617 if (n == 0) {
618 kp->controls = NULL;
619 return 0;
620 }
621 if (get_user(p, &up->controls))
622 return -EFAULT;
623 ucontrols = compat_ptr(p);
624 if (!access_ok(VERIFY_READ, ucontrols, n * sizeof(struct v4l2_ext_control)))
625 return -EFAULT;
626 kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
627 kp->controls = kcontrols;
628 while (--n >= 0) {
629 if (copy_in_user(&kcontrols->id, &ucontrols->id, sizeof(__u32)))
630 return -EFAULT;
631 if (copy_in_user(&kcontrols->reserved2, &ucontrols->reserved2, sizeof(ucontrols->reserved2)))
632 return -EFAULT;
633 /* Note: if the void * part of the union ever becomes relevant
634 then we need to know the type of the control in order to do
635 the right thing here. Luckily, that is not yet an issue. */
636 if (copy_in_user(&kcontrols->value, &ucontrols->value, sizeof(ucontrols->value)))
637 return -EFAULT;
638 ucontrols++;
639 kcontrols++;
640 }
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300641 return 0;
642}
643
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300644static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200645{
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300646 struct v4l2_ext_control __user *ucontrols;
647 struct v4l2_ext_control __user *kcontrols = kp->controls;
648 int n = kp->count;
649 compat_caddr_t p;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200650
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300651 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) ||
652 put_user(kp->ctrl_class, &up->ctrl_class) ||
653 put_user(kp->count, &up->count) ||
654 put_user(kp->error_idx, &up->error_idx) ||
655 copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
656 return -EFAULT;
657 if (!kp->count)
658 return 0;
659
660 if (get_user(p, &up->controls))
661 return -EFAULT;
662 ucontrols = compat_ptr(p);
663 if (!access_ok(VERIFY_WRITE, ucontrols, n * sizeof(struct v4l2_ext_control)))
Guy Martina113bc72006-01-11 23:40:51 -0200664 return -EFAULT;
665
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300666 while (--n >= 0) {
667 if (copy_in_user(&ucontrols->id, &kcontrols->id, sizeof(__u32)))
668 return -EFAULT;
669 if (copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
670 sizeof(ucontrols->reserved2)))
671 return -EFAULT;
672 /* Note: if the void * part of the union ever becomes relevant
673 then we need to know the type of the control in order to do
674 the right thing here. Luckily, that is not yet an issue. */
675 if (copy_in_user(&ucontrols->value, &kcontrols->value, sizeof(ucontrols->value)))
676 return -EFAULT;
677 ucontrols++;
678 kcontrols++;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200679 }
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300680 return 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200681}
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300682
683#define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32)
684#define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32)
685#define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32)
686#define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
687#define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
688#define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32)
689#define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32)
690#define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32)
691#define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
692#define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
693#define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
694#define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
695#define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
696
697#define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
698#define VIDIOC_OVERLAY32_OLD _IOWR('V', 14, s32)
699#define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
700#define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32)
701#define VIDIOC_G_INPUT32 _IOR ('V', 38, s32)
702#define VIDIOC_S_INPUT32 _IOWR('V', 39, s32)
703#define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
704#define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200705
706static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
707{
708 union {
Mauro Carvalho Chehab5bdd6cc2006-07-25 16:17:54 -0300709#ifdef CONFIG_VIDEO_V4L1_COMPAT
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200710 struct video_tuner vt;
711 struct video_buffer vb;
712 struct video_window vw;
Mauro Carvalho Chehabeb4eecc2006-07-21 18:53:23 -0300713 struct video_code vc;
Mauro Carvalho Chehab8a36ecf2006-08-06 10:16:27 -0300714 struct video_audio va;
Mauro Carvalho Chehab5bdd6cc2006-07-25 16:17:54 -0300715#endif
Philippe De Muytercf664a62006-01-09 15:24:59 -0200716 struct v4l2_format v2f;
717 struct v4l2_buffer v2b;
718 struct v4l2_framebuffer v2fb;
Guy Martina113bc72006-01-11 23:40:51 -0200719 struct v4l2_input v2i;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300720 struct v4l2_standard v2s;
721 struct v4l2_ext_controls v2ecs;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200722 unsigned long vx;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300723 int vi;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200724 } karg;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200725 void __user *up = compat_ptr(arg);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200726 int compatible_arg = 1;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200727 int err = 0;
728
729 /* First, convert the command. */
Hans Verkuild1f81da2008-10-22 00:04:45 -0300730 switch (cmd) {
Mauro Carvalho Chehab5bdd6cc2006-07-25 16:17:54 -0300731#ifdef CONFIG_VIDEO_V4L1_COMPAT
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300732 case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
733 case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
734 case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
735 case VIDIOCSWIN32: cmd = VIDIOCSWIN; break;
736 case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
737 case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
738 case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
739 case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
740 case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break;
Mauro Carvalho Chehab5bdd6cc2006-07-25 16:17:54 -0300741#endif
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300742 case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
743 case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
744 case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
745 case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
746 case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
747 case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
748 case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
749 case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break;
750 case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break;
751 case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
752 case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break;
753 case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
754 case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
755 case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
756 case VIDIOC_OVERLAY32_OLD: cmd = VIDIOC_OVERLAY; break;
757 case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
758 case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
759 case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
760 case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
761 case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
762 case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
763 }
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200764
Hans Verkuild1f81da2008-10-22 00:04:45 -0300765 switch (cmd) {
Mauro Carvalho Chehab5bdd6cc2006-07-25 16:17:54 -0300766#ifdef CONFIG_VIDEO_V4L1_COMPAT
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200767 case VIDIOCSTUNER:
768 case VIDIOCGTUNER:
769 err = get_video_tuner32(&karg.vt, up);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200770 compatible_arg = 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200771 break;
772
773 case VIDIOCSFBUF:
774 err = get_video_buffer32(&karg.vb, up);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200775 compatible_arg = 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200776 break;
777
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300778 case VIDIOCSWIN:
779 err = get_video_window32(&karg.vw, up);
780 compatible_arg = 0;
781 break;
782
783 case VIDIOCGWIN:
784 case VIDIOCGFBUF:
785 case VIDIOCGFREQ:
786 compatible_arg = 0;
787 break;
788
789 case VIDIOCSMICROCODE:
790 err = get_microcode32(&karg.vc, up);
791 compatible_arg = 0;
792 break;
Mauro Carvalho Chehab8a36ecf2006-08-06 10:16:27 -0300793
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200794 case VIDIOCSFREQ:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300795 err = get_user(karg.vx, (u32 __user *)up);
796 compatible_arg = 0;
797 break;
798
799 case VIDIOCCAPTURE:
800 case VIDIOCSYNC:
801 case VIDIOCSWRITEMODE:
Mauro Carvalho Chehab5bdd6cc2006-07-25 16:17:54 -0300802#endif
Philippe De Muytercf664a62006-01-09 15:24:59 -0200803 case VIDIOC_OVERLAY:
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200804 case VIDIOC_STREAMON:
805 case VIDIOC_STREAMOFF:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300806 case VIDIOC_S_INPUT:
807 case VIDIOC_S_OUTPUT:
808 err = get_user(karg.vi, (s32 __user *)up);
809 compatible_arg = 0;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200810 break;
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200811
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300812 case VIDIOC_G_INPUT:
813 case VIDIOC_G_OUTPUT:
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200814 compatible_arg = 0;
815 break;
Philippe De Muytercf664a62006-01-09 15:24:59 -0200816
817 case VIDIOC_G_FMT:
818 case VIDIOC_S_FMT:
819 case VIDIOC_TRY_FMT:
820 err = get_v4l2_format32(&karg.v2f, up);
821 compatible_arg = 0;
822 break;
823
824 case VIDIOC_QUERYBUF:
825 case VIDIOC_QBUF:
826 case VIDIOC_DQBUF:
827 err = get_v4l2_buffer32(&karg.v2b, up);
828 compatible_arg = 0;
829 break;
830
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300831 case VIDIOC_S_FBUF:
832 err = get_v4l2_framebuffer32(&karg.v2fb, up);
Guy Martina113bc72006-01-11 23:40:51 -0200833 compatible_arg = 0;
834 break;
835
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300836 case VIDIOC_G_FBUF:
837 compatible_arg = 0;
838 break;
839
840 case VIDIOC_ENUMSTD:
Philippe De Muytercf664a62006-01-09 15:24:59 -0200841 err = get_v4l2_standard32(&karg.v2s, up);
842 compatible_arg = 0;
843 break;
844
Guy Martina113bc72006-01-11 23:40:51 -0200845 case VIDIOC_ENUMINPUT:
Guy Martina113bc72006-01-11 23:40:51 -0200846 err = get_v4l2_input32(&karg.v2i, up);
847 compatible_arg = 0;
848 break;
849
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300850 case VIDIOC_G_EXT_CTRLS:
851 case VIDIOC_S_EXT_CTRLS:
852 case VIDIOC_TRY_EXT_CTRLS:
853 err = get_v4l2_ext_controls32(&karg.v2ecs, up);
Guy Martina113bc72006-01-11 23:40:51 -0200854 compatible_arg = 0;
855 break;
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300856 }
Hans Verkuild1f81da2008-10-22 00:04:45 -0300857 if (err)
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300858 return err;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200859
Hans Verkuild1f81da2008-10-22 00:04:45 -0300860 if (compatible_arg)
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300861 err = native_ioctl(file, cmd, (unsigned long)up);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200862 else {
863 mm_segment_t old_fs = get_fs();
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200864
Philippe De Muytercf664a62006-01-09 15:24:59 -0200865 set_fs(KERNEL_DS);
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300866 err = native_ioctl(file, cmd, (unsigned long)&karg);
Philippe De Muytercf664a62006-01-09 15:24:59 -0200867 set_fs(old_fs);
868 }
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200869
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300870 /* Special case: even after an error we need to put the
871 results back for these ioctls since the error_idx will
872 contain information on which control failed. */
873 switch (cmd) {
874 case VIDIOC_G_EXT_CTRLS:
875 case VIDIOC_S_EXT_CTRLS:
876 case VIDIOC_TRY_EXT_CTRLS:
877 if (put_v4l2_ext_controls32(&karg.v2ecs, up))
878 err = -EFAULT;
879 break;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200880 }
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300881 if (err)
882 return err;
883
884 switch (cmd) {
885#ifdef CONFIG_VIDEO_V4L1_COMPAT
886 case VIDIOCGTUNER:
887 err = put_video_tuner32(&karg.vt, up);
888 break;
889
890 case VIDIOCGWIN:
891 err = put_video_window32(&karg.vw, up);
892 break;
893
894 case VIDIOCGFBUF:
895 err = put_video_buffer32(&karg.vb, up);
896 break;
897
898 case VIDIOCGFREQ:
899 err = put_user(((u32)karg.vx), (u32 __user *)up);
900 break;
901#endif
902 case VIDIOC_S_INPUT:
903 case VIDIOC_S_OUTPUT:
904 case VIDIOC_G_INPUT:
905 case VIDIOC_G_OUTPUT:
906 err = put_user(((s32)karg.vi), (s32 __user *)up);
907 break;
908
909 case VIDIOC_G_FBUF:
910 err = put_v4l2_framebuffer32(&karg.v2fb, up);
911 break;
912
913 case VIDIOC_G_FMT:
914 case VIDIOC_S_FMT:
915 case VIDIOC_TRY_FMT:
916 err = put_v4l2_format32(&karg.v2f, up);
917 break;
918
919 case VIDIOC_QUERYBUF:
920 case VIDIOC_QBUF:
921 case VIDIOC_DQBUF:
922 err = put_v4l2_buffer32(&karg.v2b, up);
923 break;
924
925 case VIDIOC_ENUMSTD:
926 err = put_v4l2_standard32(&karg.v2s, up);
927 break;
928
929 case VIDIOC_ENUMINPUT:
930 err = put_v4l2_input32(&karg.v2i, up);
931 break;
932 }
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200933 return err;
934}
935
936long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
937{
938 int ret = -ENOIOCTLCMD;
939
Hans Verkuil3ca81a52008-12-16 08:32:37 -0300940 if (!file->f_op->ioctl && !file->f_op->unlocked_ioctl)
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200941 return ret;
942
943 switch (cmd) {
Mauro Carvalho Chehab5bdd6cc2006-07-25 16:17:54 -0300944#ifdef CONFIG_VIDEO_V4L1_COMPAT
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300945 case VIDIOCGCAP:
946 case VIDIOCGCHAN:
947 case VIDIOCSCHAN:
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200948 case VIDIOCGTUNER32:
949 case VIDIOCSTUNER32:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300950 case VIDIOCGPICT:
951 case VIDIOCSPICT:
952 case VIDIOCCAPTURE32:
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200953 case VIDIOCGWIN32:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300954 case VIDIOCSWIN32:
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200955 case VIDIOCGFBUF32:
956 case VIDIOCSFBUF32:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300957 case VIDIOCKEY:
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -0200958 case VIDIOCGFREQ32:
Nickolay V. Shmyrev133b7352006-01-09 15:24:58 -0200959 case VIDIOCSFREQ32:
Mauro Carvalho Chehab8a36ecf2006-08-06 10:16:27 -0300960 case VIDIOCGAUDIO:
961 case VIDIOCSAUDIO:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300962 case VIDIOCSYNC32:
963 case VIDIOCMCAPTURE:
964 case VIDIOCGMBUF:
965 case VIDIOCGUNIT:
966 case VIDIOCGCAPTURE:
967 case VIDIOCSCAPTURE:
968 case VIDIOCSPLAYMODE:
969 case VIDIOCSWRITEMODE32:
970 case VIDIOCGPLAYINFO:
971 case VIDIOCSMICROCODE32:
Steven Walter7963fa42007-08-09 11:36:35 -0300972 case VIDIOCGVBIFMT:
973 case VIDIOCSVBIFMT:
Mauro Carvalho Chehab5bdd6cc2006-07-25 16:17:54 -0300974#endif
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300975#ifdef __OLD_VIDIOC_
976 case VIDIOC_OVERLAY32_OLD:
977 case VIDIOC_S_PARM_OLD:
978 case VIDIOC_S_CTRL_OLD:
979 case VIDIOC_G_AUDIO_OLD:
980 case VIDIOC_G_AUDOUT_OLD:
981 case VIDIOC_CROPCAP_OLD:
982#endif
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200983 case VIDIOC_QUERYCAP:
Hans Verkuil92f45ba2008-12-21 10:35:25 -0300984 case VIDIOC_RESERVED:
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200985 case VIDIOC_ENUM_FMT:
986 case VIDIOC_G_FMT32:
987 case VIDIOC_S_FMT32:
988 case VIDIOC_REQBUFS:
989 case VIDIOC_QUERYBUF32:
990 case VIDIOC_G_FBUF32:
991 case VIDIOC_S_FBUF32:
992 case VIDIOC_OVERLAY32:
993 case VIDIOC_QBUF32:
994 case VIDIOC_DQBUF32:
995 case VIDIOC_STREAMON32:
996 case VIDIOC_STREAMOFF32:
997 case VIDIOC_G_PARM:
Gregor Jasnyc7f09db2008-10-23 09:55:22 -0300998 case VIDIOC_S_PARM:
Philippe De Muyter13d133b2006-01-09 15:25:00 -0200999 case VIDIOC_G_STD:
1000 case VIDIOC_S_STD:
1001 case VIDIOC_ENUMSTD32:
1002 case VIDIOC_ENUMINPUT32:
1003 case VIDIOC_G_CTRL:
Steven Walter7963fa42007-08-09 11:36:35 -03001004 case VIDIOC_S_CTRL:
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001005 case VIDIOC_G_TUNER:
1006 case VIDIOC_S_TUNER:
1007 case VIDIOC_G_AUDIO:
1008 case VIDIOC_S_AUDIO:
Philippe De Muyter13d133b2006-01-09 15:25:00 -02001009 case VIDIOC_QUERYCTRL:
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001010 case VIDIOC_QUERYMENU:
Philippe De Muyter13d133b2006-01-09 15:25:00 -02001011 case VIDIOC_G_INPUT32:
1012 case VIDIOC_S_INPUT32:
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001013 case VIDIOC_G_OUTPUT32:
1014 case VIDIOC_S_OUTPUT32:
1015 case VIDIOC_ENUMOUTPUT:
1016 case VIDIOC_G_AUDOUT:
1017 case VIDIOC_S_AUDOUT:
1018 case VIDIOC_G_MODULATOR:
1019 case VIDIOC_S_MODULATOR:
1020 case VIDIOC_S_FREQUENCY:
1021 case VIDIOC_G_FREQUENCY:
1022 case VIDIOC_CROPCAP:
1023 case VIDIOC_G_CROP:
1024 case VIDIOC_S_CROP:
1025 case VIDIOC_G_JPEGCOMP:
1026 case VIDIOC_S_JPEGCOMP:
1027 case VIDIOC_QUERYSTD:
Philippe De Muyter13d133b2006-01-09 15:25:00 -02001028 case VIDIOC_TRY_FMT32:
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001029 case VIDIOC_ENUMAUDIO:
1030 case VIDIOC_ENUMAUDOUT:
1031 case VIDIOC_G_PRIORITY:
1032 case VIDIOC_S_PRIORITY:
1033 case VIDIOC_G_SLICED_VBI_CAP:
1034 case VIDIOC_LOG_STATUS:
1035 case VIDIOC_G_EXT_CTRLS32:
1036 case VIDIOC_S_EXT_CTRLS32:
1037 case VIDIOC_TRY_EXT_CTRLS32:
Gregor Jasnyc7f09db2008-10-23 09:55:22 -03001038 case VIDIOC_ENUM_FRAMESIZES:
1039 case VIDIOC_ENUM_FRAMEINTERVALS:
Hans Verkuil92f45ba2008-12-21 10:35:25 -03001040 case VIDIOC_G_ENC_INDEX:
1041 case VIDIOC_ENCODER_CMD:
1042 case VIDIOC_TRY_ENCODER_CMD:
1043 case VIDIOC_DBG_S_REGISTER:
1044 case VIDIOC_DBG_G_REGISTER:
1045 case VIDIOC_G_CHIP_IDENT:
1046 case VIDIOC_S_HW_FREQ_SEEK:
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001047 ret = do_video_ioctl(file, cmd, arg);
1048 break;
1049
Mauro Carvalho Chehab5bdd6cc2006-07-25 16:17:54 -03001050#ifdef CONFIG_VIDEO_V4L1_COMPAT
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001051 /* BTTV specific... */
1052 case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]):
1053 case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]):
1054 case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int):
1055 case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */
1056 case _IOR('v' , BASE_VIDIOCPRIVATE+4, int):
1057 case _IOR('v' , BASE_VIDIOCPRIVATE+5, int):
1058 case _IOR('v' , BASE_VIDIOCPRIVATE+6, int):
1059 case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
1060 ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
1061 break;
Mauro Carvalho Chehab5bdd6cc2006-07-25 16:17:54 -03001062#endif
Guy Martina113bc72006-01-11 23:40:51 -02001063 default:
1064 v4l_print_ioctl("compat_ioctl32", cmd);
Hans Verkuil7d4f0b82008-12-15 07:19:20 -03001065 printk(KERN_CONT "\n");
1066 break;
MishalĂ… Pytasz97e2a012006-01-09 15:24:59 -02001067 }
Hans Verkuile8efb712006-01-09 15:24:59 -02001068 return ret;
Arnd Bergmann0d0fbf82006-01-09 15:24:57 -02001069}
1070#else
1071long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
1072{
1073 return -ENOIOCTLCMD;
1074}
1075#endif
1076EXPORT_SYMBOL_GPL(v4l_compat_ioctl32);
Ricardo Cerqueira925e6992006-01-09 15:24:57 -02001077
1078MODULE_LICENSE("GPL");