diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2008-10-21 23:04:45 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-29 14:53:25 -0500 |
commit | d1f81da2361804d62f7ade2703eda68dda6cdb48 (patch) | |
tree | c0c238f22d3fae1c07edfaa15ae26724bd31aee4 /drivers/media/video/v4l2-compat-ioctl32.c | |
parent | da40b59305f373d386435ece69244c570e3954b6 (diff) |
V4L/DVB (9484): v4l: rename compat_ioctl32.c to v4l2-compat-ioctl32.c
All core v4l sources should start with 'v4l2-'
This file was the last one for which this was not the case.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/v4l2-compat-ioctl32.c')
-rw-r--r-- | drivers/media/video/v4l2-compat-ioctl32.c | 927 |
1 files changed, 927 insertions, 0 deletions
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c new file mode 100644 index 000000000000..3b310ab3e3de --- /dev/null +++ b/drivers/media/video/v4l2-compat-ioctl32.c | |||
@@ -0,0 +1,927 @@ | |||
1 | /* | ||
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) | ||
10 | * | ||
11 | * These routines maintain argument size conversion between 32bit and 64bit | ||
12 | * ioctls. | ||
13 | */ | ||
14 | |||
15 | #include <linux/compat.h> | ||
16 | #include <linux/videodev.h> | ||
17 | #include <linux/videodev2.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/smp_lock.h> | ||
20 | #include <media/v4l2-ioctl.h> | ||
21 | |||
22 | #ifdef CONFIG_COMPAT | ||
23 | |||
24 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
25 | struct video_tuner32 { | ||
26 | compat_int_t tuner; | ||
27 | char name[32]; | ||
28 | compat_ulong_t rangelow, rangehigh; | ||
29 | u32 flags; /* It is really u32 in videodev.h */ | ||
30 | u16 mode, signal; | ||
31 | }; | ||
32 | |||
33 | static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) | ||
34 | { | ||
35 | if (!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) || | ||
36 | get_user(kp->tuner, &up->tuner) || | ||
37 | copy_from_user(kp->name, up->name, 32) || | ||
38 | get_user(kp->rangelow, &up->rangelow) || | ||
39 | get_user(kp->rangehigh, &up->rangehigh) || | ||
40 | get_user(kp->flags, &up->flags) || | ||
41 | get_user(kp->mode, &up->mode) || | ||
42 | get_user(kp->signal, &up->signal)) | ||
43 | return -EFAULT; | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) | ||
48 | { | ||
49 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) || | ||
50 | put_user(kp->tuner, &up->tuner) || | ||
51 | copy_to_user(up->name, kp->name, 32) || | ||
52 | put_user(kp->rangelow, &up->rangelow) || | ||
53 | put_user(kp->rangehigh, &up->rangehigh) || | ||
54 | put_user(kp->flags, &up->flags) || | ||
55 | put_user(kp->mode, &up->mode) || | ||
56 | put_user(kp->signal, &up->signal)) | ||
57 | return -EFAULT; | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | |||
62 | struct video_buffer32 { | ||
63 | compat_caddr_t base; | ||
64 | compat_int_t height, width, depth, bytesperline; | ||
65 | }; | ||
66 | |||
67 | static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up) | ||
68 | { | ||
69 | u32 tmp; | ||
70 | |||
71 | if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) || | ||
72 | get_user(tmp, &up->base) || | ||
73 | get_user(kp->height, &up->height) || | ||
74 | get_user(kp->width, &up->width) || | ||
75 | get_user(kp->depth, &up->depth) || | ||
76 | get_user(kp->bytesperline, &up->bytesperline)) | ||
77 | return -EFAULT; | ||
78 | |||
79 | /* This is actually a physical address stored | ||
80 | * as a void pointer. | ||
81 | */ | ||
82 | kp->base = (void *)(unsigned long) tmp; | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up) | ||
88 | { | ||
89 | u32 tmp = (u32)((unsigned long)kp->base); | ||
90 | |||
91 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) || | ||
92 | put_user(tmp, &up->base) || | ||
93 | put_user(kp->height, &up->height) || | ||
94 | put_user(kp->width, &up->width) || | ||
95 | put_user(kp->depth, &up->depth) || | ||
96 | put_user(kp->bytesperline, &up->bytesperline)) | ||
97 | return -EFAULT; | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | struct video_clip32 { | ||
102 | s32 x, y, width, height; /* Its really s32 in videodev.h */ | ||
103 | compat_caddr_t next; | ||
104 | }; | ||
105 | |||
106 | struct video_window32 { | ||
107 | u32 x, y, width, height, chromakey, flags; | ||
108 | compat_caddr_t clips; | ||
109 | compat_int_t clipcount; | ||
110 | }; | ||
111 | #endif | ||
112 | |||
113 | static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
114 | { | ||
115 | int ret = -ENOIOCTLCMD; | ||
116 | |||
117 | if (file->f_op->unlocked_ioctl) | ||
118 | ret = file->f_op->unlocked_ioctl(file, cmd, arg); | ||
119 | else if (file->f_op->ioctl) { | ||
120 | lock_kernel(); | ||
121 | ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg); | ||
122 | unlock_kernel(); | ||
123 | } | ||
124 | |||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | |||
129 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
130 | /* You get back everything except the clips... */ | ||
131 | static int put_video_window32(struct video_window *kp, struct video_window32 __user *up) | ||
132 | { | ||
133 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) || | ||
134 | put_user(kp->x, &up->x) || | ||
135 | put_user(kp->y, &up->y) || | ||
136 | put_user(kp->width, &up->width) || | ||
137 | put_user(kp->height, &up->height) || | ||
138 | put_user(kp->chromakey, &up->chromakey) || | ||
139 | put_user(kp->flags, &up->flags) || | ||
140 | put_user(kp->clipcount, &up->clipcount)) | ||
141 | return -EFAULT; | ||
142 | return 0; | ||
143 | } | ||
144 | #endif | ||
145 | |||
146 | struct v4l2_clip32 { | ||
147 | struct v4l2_rect c; | ||
148 | compat_caddr_t next; | ||
149 | }; | ||
150 | |||
151 | struct v4l2_window32 { | ||
152 | struct v4l2_rect w; | ||
153 | enum v4l2_field field; | ||
154 | __u32 chromakey; | ||
155 | compat_caddr_t clips; /* actually struct v4l2_clip32 * */ | ||
156 | __u32 clipcount; | ||
157 | compat_caddr_t bitmap; | ||
158 | }; | ||
159 | |||
160 | static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) | ||
161 | { | ||
162 | if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) || | ||
163 | copy_from_user(&kp->w, &up->w, sizeof(up->w)) || | ||
164 | get_user(kp->field, &up->field) || | ||
165 | get_user(kp->chromakey, &up->chromakey) || | ||
166 | get_user(kp->clipcount, &up->clipcount)) | ||
167 | return -EFAULT; | ||
168 | if (kp->clipcount > 2048) | ||
169 | return -EINVAL; | ||
170 | if (kp->clipcount) { | ||
171 | struct v4l2_clip32 __user *uclips; | ||
172 | struct v4l2_clip __user *kclips; | ||
173 | int n = kp->clipcount; | ||
174 | compat_caddr_t p; | ||
175 | |||
176 | if (get_user(p, &up->clips)) | ||
177 | return -EFAULT; | ||
178 | uclips = compat_ptr(p); | ||
179 | kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); | ||
180 | kp->clips = kclips; | ||
181 | while (--n >= 0) { | ||
182 | if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) | ||
183 | return -EFAULT; | ||
184 | if (put_user(n ? kclips + 1 : NULL, &kclips->next)) | ||
185 | return -EFAULT; | ||
186 | uclips += 1; | ||
187 | kclips += 1; | ||
188 | } | ||
189 | } else | ||
190 | kp->clips = NULL; | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) | ||
195 | { | ||
196 | if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) || | ||
197 | put_user(kp->field, &up->field) || | ||
198 | put_user(kp->chromakey, &up->chromakey) || | ||
199 | put_user(kp->clipcount, &up->clipcount)) | ||
200 | return -EFAULT; | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) | ||
205 | { | ||
206 | if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) | ||
207 | return -EFAULT; | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) | ||
212 | { | ||
213 | if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) | ||
214 | return -EFAULT; | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) | ||
219 | { | ||
220 | if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) | ||
221 | return -EFAULT; | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) | ||
226 | { | ||
227 | if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) | ||
228 | return -EFAULT; | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | struct v4l2_format32 { | ||
233 | enum v4l2_buf_type type; | ||
234 | union { | ||
235 | struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */ | ||
236 | struct v4l2_window32 win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */ | ||
237 | struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */ | ||
238 | __u8 raw_data[200]; /* user-defined */ | ||
239 | } fmt; | ||
240 | }; | ||
241 | |||
242 | static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) | ||
243 | { | ||
244 | if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) || | ||
245 | get_user(kp->type, &up->type)) | ||
246 | return -EFAULT; | ||
247 | switch (kp->type) { | ||
248 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
249 | return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); | ||
250 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
251 | return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); | ||
252 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
253 | return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); | ||
254 | default: | ||
255 | printk(KERN_INFO "compat_ioctl: unexpected VIDIOC_FMT type %d\n", | ||
256 | kp->type); | ||
257 | return -ENXIO; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) | ||
262 | { | ||
263 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) || | ||
264 | put_user(kp->type, &up->type)) | ||
265 | return -EFAULT; | ||
266 | switch (kp->type) { | ||
267 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
268 | return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); | ||
269 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
270 | return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); | ||
271 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
272 | return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); | ||
273 | default: | ||
274 | return -ENXIO; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) | ||
279 | { | ||
280 | if (copy_from_user(kp, up, sizeof(struct v4l2_standard))) | ||
281 | return -EFAULT; | ||
282 | return 0; | ||
283 | |||
284 | } | ||
285 | |||
286 | static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) | ||
287 | { | ||
288 | if (copy_to_user(up, kp, sizeof(struct v4l2_standard))) | ||
289 | return -EFAULT; | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | struct v4l2_standard32 { | ||
294 | __u32 index; | ||
295 | __u32 id[2]; /* __u64 would get the alignment wrong */ | ||
296 | __u8 name[24]; | ||
297 | struct v4l2_fract frameperiod; /* Frames, not fields */ | ||
298 | __u32 framelines; | ||
299 | __u32 reserved[4]; | ||
300 | }; | ||
301 | |||
302 | static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) | ||
303 | { | ||
304 | /* other fields are not set by the user, nor used by the driver */ | ||
305 | if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) || | ||
306 | get_user(kp->index, &up->index)) | ||
307 | return -EFAULT; | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) | ||
312 | { | ||
313 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || | ||
314 | put_user(kp->index, &up->index) || | ||
315 | copy_to_user(up->id, &kp->id, sizeof(__u64)) || | ||
316 | copy_to_user(up->name, kp->name, 24) || | ||
317 | copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || | ||
318 | put_user(kp->framelines, &up->framelines) || | ||
319 | copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32))) | ||
320 | return -EFAULT; | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) | ||
325 | { | ||
326 | if (copy_from_user(kp, up, sizeof(struct v4l2_tuner))) | ||
327 | return -EFAULT; | ||
328 | return 0; | ||
329 | |||
330 | } | ||
331 | |||
332 | static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) | ||
333 | { | ||
334 | if (copy_to_user(up, kp, sizeof(struct v4l2_tuner))) | ||
335 | return -EFAULT; | ||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | struct v4l2_buffer32 { | ||
340 | __u32 index; | ||
341 | enum v4l2_buf_type type; | ||
342 | __u32 bytesused; | ||
343 | __u32 flags; | ||
344 | enum v4l2_field field; | ||
345 | struct compat_timeval timestamp; | ||
346 | struct v4l2_timecode timecode; | ||
347 | __u32 sequence; | ||
348 | |||
349 | /* memory location */ | ||
350 | enum v4l2_memory memory; | ||
351 | union { | ||
352 | __u32 offset; | ||
353 | compat_long_t userptr; | ||
354 | } m; | ||
355 | __u32 length; | ||
356 | __u32 input; | ||
357 | __u32 reserved; | ||
358 | }; | ||
359 | |||
360 | static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) | ||
361 | { | ||
362 | |||
363 | if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || | ||
364 | get_user(kp->index, &up->index) || | ||
365 | get_user(kp->type, &up->type) || | ||
366 | get_user(kp->flags, &up->flags) || | ||
367 | get_user(kp->memory, &up->memory) || | ||
368 | get_user(kp->input, &up->input)) | ||
369 | return -EFAULT; | ||
370 | switch (kp->memory) { | ||
371 | case V4L2_MEMORY_MMAP: | ||
372 | break; | ||
373 | case V4L2_MEMORY_USERPTR: | ||
374 | { | ||
375 | compat_long_t tmp; | ||
376 | |||
377 | if (get_user(kp->length, &up->length) || | ||
378 | get_user(tmp, &up->m.userptr)) | ||
379 | return -EFAULT; | ||
380 | |||
381 | kp->m.userptr = (unsigned long)compat_ptr(tmp); | ||
382 | } | ||
383 | break; | ||
384 | case V4L2_MEMORY_OVERLAY: | ||
385 | if (get_user(kp->m.offset, &up->m.offset)) | ||
386 | return -EFAULT; | ||
387 | break; | ||
388 | } | ||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) | ||
393 | { | ||
394 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) || | ||
395 | put_user(kp->index, &up->index) || | ||
396 | put_user(kp->type, &up->type) || | ||
397 | put_user(kp->flags, &up->flags) || | ||
398 | put_user(kp->memory, &up->memory) || | ||
399 | put_user(kp->input, &up->input)) | ||
400 | return -EFAULT; | ||
401 | switch (kp->memory) { | ||
402 | case V4L2_MEMORY_MMAP: | ||
403 | if (put_user(kp->length, &up->length) || | ||
404 | put_user(kp->m.offset, &up->m.offset)) | ||
405 | return -EFAULT; | ||
406 | break; | ||
407 | case V4L2_MEMORY_USERPTR: | ||
408 | if (put_user(kp->length, &up->length) || | ||
409 | put_user(kp->m.userptr, &up->m.userptr)) | ||
410 | return -EFAULT; | ||
411 | break; | ||
412 | case V4L2_MEMORY_OVERLAY: | ||
413 | if (put_user(kp->m.offset, &up->m.offset)) | ||
414 | return -EFAULT; | ||
415 | break; | ||
416 | } | ||
417 | if (put_user(kp->bytesused, &up->bytesused) || | ||
418 | put_user(kp->field, &up->field) || | ||
419 | put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || | ||
420 | put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || | ||
421 | copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || | ||
422 | put_user(kp->sequence, &up->sequence) || | ||
423 | put_user(kp->reserved, &up->reserved)) | ||
424 | return -EFAULT; | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | struct v4l2_framebuffer32 { | ||
429 | __u32 capability; | ||
430 | __u32 flags; | ||
431 | compat_caddr_t base; | ||
432 | struct v4l2_pix_format fmt; | ||
433 | }; | ||
434 | |||
435 | static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) | ||
436 | { | ||
437 | u32 tmp; | ||
438 | |||
439 | if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) || | ||
440 | get_user(tmp, &up->base) || | ||
441 | get_user(kp->capability, &up->capability) || | ||
442 | get_user(kp->flags, &up->flags)) | ||
443 | return -EFAULT; | ||
444 | kp->base = compat_ptr(tmp); | ||
445 | get_v4l2_pix_format(&kp->fmt, &up->fmt); | ||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) | ||
450 | { | ||
451 | u32 tmp = (u32)((unsigned long)kp->base); | ||
452 | |||
453 | if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) || | ||
454 | put_user(tmp, &up->base) || | ||
455 | put_user(kp->capability, &up->capability) || | ||
456 | put_user(kp->flags, &up->flags)) | ||
457 | return -EFAULT; | ||
458 | put_v4l2_pix_format(&kp->fmt, &up->fmt); | ||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) | ||
463 | { | ||
464 | if (copy_from_user(kp, up, sizeof(struct v4l2_input) - 4)) | ||
465 | return -EFAULT; | ||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) | ||
470 | { | ||
471 | if (copy_to_user(up, kp, sizeof(struct v4l2_input) - 4)) | ||
472 | return -EFAULT; | ||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) | ||
477 | { | ||
478 | if (copy_from_user(kp, up, sizeof(struct v4l2_input))) | ||
479 | return -EFAULT; | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) | ||
484 | { | ||
485 | if (copy_to_user(up, kp, sizeof(struct v4l2_input))) | ||
486 | return -EFAULT; | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
491 | struct video_code32 { | ||
492 | char loadwhat[16]; /* name or tag of file being passed */ | ||
493 | compat_int_t datasize; | ||
494 | unsigned char *data; | ||
495 | }; | ||
496 | |||
497 | static inline int microcode32(struct video_code *kp, struct video_code32 __user *up) | ||
498 | { | ||
499 | if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) || | ||
500 | copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) || | ||
501 | get_user(kp->datasize, &up->datasize) || | ||
502 | copy_from_user(kp->data, up->data, up->datasize)) | ||
503 | return -EFAULT; | ||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | #define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32) | ||
508 | #define VIDIOCSTUNER32 _IOW('v', 5, struct video_tuner32) | ||
509 | #define VIDIOCGWIN32 _IOR('v', 9, struct video_window32) | ||
510 | #define VIDIOCSWIN32 _IOW('v', 10, struct video_window32) | ||
511 | #define VIDIOCGFBUF32 _IOR('v', 11, struct video_buffer32) | ||
512 | #define VIDIOCSFBUF32 _IOW('v', 12, struct video_buffer32) | ||
513 | #define VIDIOCGFREQ32 _IOR('v', 14, u32) | ||
514 | #define VIDIOCSFREQ32 _IOW('v', 15, u32) | ||
515 | #define VIDIOCSMICROCODE32 _IOW('v', 27, struct video_code32) | ||
516 | |||
517 | #endif | ||
518 | |||
519 | /* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */ | ||
520 | #define VIDIOC_ENUMINPUT32 (VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4)) | ||
521 | #define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32) | ||
522 | #define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32) | ||
523 | #define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32) | ||
524 | #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) | ||
525 | #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) | ||
526 | /* VIDIOC_OVERLAY is now _IOW, but was _IOWR */ | ||
527 | #define VIDIOC_OVERLAY32 _IOWR ('V', 14, compat_int_t) | ||
528 | #define VIDIOC_QBUF32 _IOWR ('V', 15, struct v4l2_buffer32) | ||
529 | #define VIDIOC_DQBUF32 _IOWR ('V', 17, struct v4l2_buffer32) | ||
530 | #define VIDIOC_STREAMON32 _IOW ('V', 18, compat_int_t) | ||
531 | #define VIDIOC_STREAMOFF32 _IOW ('V', 19, compat_int_t) | ||
532 | #define VIDIOC_ENUMSTD32 _IOWR ('V', 25, struct v4l2_standard32) | ||
533 | /* VIDIOC_S_CTRL is now _IOWR, but was _IOW */ | ||
534 | #define VIDIOC_S_CTRL32 _IOW ('V', 28, struct v4l2_control) | ||
535 | #define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t) | ||
536 | #define VIDIOC_S_INPUT32 _IOWR ('V', 39, compat_int_t) | ||
537 | #define VIDIOC_TRY_FMT32 _IOWR ('V', 64, struct v4l2_format32) | ||
538 | |||
539 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
540 | enum { | ||
541 | MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip) | ||
542 | }; | ||
543 | |||
544 | static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg) | ||
545 | { | ||
546 | struct video_window32 __user *up = compat_ptr(arg); | ||
547 | struct video_window __user *vw; | ||
548 | struct video_clip __user *p; | ||
549 | int nclips; | ||
550 | u32 n; | ||
551 | |||
552 | if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32))) | ||
553 | return -EFAULT; | ||
554 | |||
555 | if (get_user(nclips, &up->clipcount)) | ||
556 | return -EFAULT; | ||
557 | |||
558 | /* Peculiar interface... */ | ||
559 | if (nclips < 0) | ||
560 | nclips = VIDEO_CLIPMAP_SIZE; | ||
561 | |||
562 | if (nclips > MaxClips) | ||
563 | return -ENOMEM; | ||
564 | |||
565 | vw = compat_alloc_user_space(sizeof(struct video_window) + | ||
566 | nclips * sizeof(struct video_clip)); | ||
567 | |||
568 | p = nclips ? (struct video_clip __user *)(vw + 1) : NULL; | ||
569 | |||
570 | if (get_user(n, &up->x) || put_user(n, &vw->x) || | ||
571 | get_user(n, &up->y) || put_user(n, &vw->y) || | ||
572 | get_user(n, &up->width) || put_user(n, &vw->width) || | ||
573 | get_user(n, &up->height) || put_user(n, &vw->height) || | ||
574 | get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) || | ||
575 | get_user(n, &up->flags) || put_user(n, &vw->flags) || | ||
576 | get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) || | ||
577 | get_user(n, &up->clips) || put_user(p, &vw->clips)) | ||
578 | return -EFAULT; | ||
579 | |||
580 | if (nclips) { | ||
581 | struct video_clip32 __user *u = compat_ptr(n); | ||
582 | int i; | ||
583 | if (!u) | ||
584 | return -EINVAL; | ||
585 | for (i = 0; i < nclips; i++, u++, p++) { | ||
586 | s32 v; | ||
587 | if (!access_ok(VERIFY_READ, u, sizeof(struct video_clip32)) || | ||
588 | !access_ok(VERIFY_WRITE, p, sizeof(struct video_clip32)) || | ||
589 | get_user(v, &u->x) || | ||
590 | put_user(v, &p->x) || | ||
591 | get_user(v, &u->y) || | ||
592 | put_user(v, &p->y) || | ||
593 | get_user(v, &u->width) || | ||
594 | put_user(v, &p->width) || | ||
595 | get_user(v, &u->height) || | ||
596 | put_user(v, &p->height) || | ||
597 | put_user(NULL, &p->next)) | ||
598 | return -EFAULT; | ||
599 | } | ||
600 | } | ||
601 | |||
602 | return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw); | ||
603 | } | ||
604 | #endif | ||
605 | |||
606 | static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
607 | { | ||
608 | union { | ||
609 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
610 | struct video_tuner vt; | ||
611 | struct video_buffer vb; | ||
612 | struct video_window vw; | ||
613 | struct video_code vc; | ||
614 | struct video_audio va; | ||
615 | #endif | ||
616 | struct v4l2_format v2f; | ||
617 | struct v4l2_buffer v2b; | ||
618 | struct v4l2_framebuffer v2fb; | ||
619 | struct v4l2_standard v2s; | ||
620 | struct v4l2_input v2i; | ||
621 | struct v4l2_tuner v2t; | ||
622 | unsigned long vx; | ||
623 | } karg; | ||
624 | void __user *up = compat_ptr(arg); | ||
625 | int compatible_arg = 1; | ||
626 | int err = 0; | ||
627 | int realcmd = cmd; | ||
628 | |||
629 | /* First, convert the command. */ | ||
630 | switch (cmd) { | ||
631 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
632 | case VIDIOCGTUNER32: realcmd = cmd = VIDIOCGTUNER; break; | ||
633 | case VIDIOCSTUNER32: realcmd = cmd = VIDIOCSTUNER; break; | ||
634 | case VIDIOCGWIN32: realcmd = cmd = VIDIOCGWIN; break; | ||
635 | case VIDIOCGFBUF32: realcmd = cmd = VIDIOCGFBUF; break; | ||
636 | case VIDIOCSFBUF32: realcmd = cmd = VIDIOCSFBUF; break; | ||
637 | case VIDIOCGFREQ32: realcmd = cmd = VIDIOCGFREQ; break; | ||
638 | case VIDIOCSFREQ32: realcmd = cmd = VIDIOCSFREQ; break; | ||
639 | case VIDIOCSMICROCODE32: realcmd = cmd = VIDIOCSMICROCODE; break; | ||
640 | #endif | ||
641 | case VIDIOC_G_FMT32: realcmd = cmd = VIDIOC_G_FMT; break; | ||
642 | case VIDIOC_S_FMT32: realcmd = cmd = VIDIOC_S_FMT; break; | ||
643 | case VIDIOC_QUERYBUF32: realcmd = cmd = VIDIOC_QUERYBUF; break; | ||
644 | case VIDIOC_QBUF32: realcmd = cmd = VIDIOC_QBUF; break; | ||
645 | case VIDIOC_DQBUF32: realcmd = cmd = VIDIOC_DQBUF; break; | ||
646 | case VIDIOC_STREAMON32: realcmd = cmd = VIDIOC_STREAMON; break; | ||
647 | case VIDIOC_STREAMOFF32: realcmd = cmd = VIDIOC_STREAMOFF; break; | ||
648 | case VIDIOC_G_FBUF32: realcmd = cmd = VIDIOC_G_FBUF; break; | ||
649 | case VIDIOC_S_FBUF32: realcmd = cmd = VIDIOC_S_FBUF; break; | ||
650 | case VIDIOC_OVERLAY32: realcmd = cmd = VIDIOC_OVERLAY; break; | ||
651 | case VIDIOC_ENUMSTD32: realcmd = VIDIOC_ENUMSTD; break; | ||
652 | case VIDIOC_ENUMINPUT32: realcmd = VIDIOC_ENUMINPUT; break; | ||
653 | case VIDIOC_S_CTRL32: realcmd = cmd = VIDIOC_S_CTRL; break; | ||
654 | case VIDIOC_G_INPUT32: realcmd = cmd = VIDIOC_G_INPUT; break; | ||
655 | case VIDIOC_S_INPUT32: realcmd = cmd = VIDIOC_S_INPUT; break; | ||
656 | case VIDIOC_TRY_FMT32: realcmd = cmd = VIDIOC_TRY_FMT; break; | ||
657 | }; | ||
658 | |||
659 | switch (cmd) { | ||
660 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
661 | case VIDIOCSTUNER: | ||
662 | case VIDIOCGTUNER: | ||
663 | err = get_video_tuner32(&karg.vt, up); | ||
664 | compatible_arg = 0; | ||
665 | |||
666 | break; | ||
667 | |||
668 | case VIDIOCSFBUF: | ||
669 | err = get_video_buffer32(&karg.vb, up); | ||
670 | compatible_arg = 0; | ||
671 | break; | ||
672 | |||
673 | |||
674 | case VIDIOCSFREQ: | ||
675 | #endif | ||
676 | case VIDIOC_S_INPUT: | ||
677 | case VIDIOC_OVERLAY: | ||
678 | case VIDIOC_STREAMON: | ||
679 | case VIDIOC_STREAMOFF: | ||
680 | err = get_user(karg.vx, (u32 __user *)up); | ||
681 | compatible_arg = 1; | ||
682 | break; | ||
683 | |||
684 | case VIDIOC_S_FBUF: | ||
685 | err = get_v4l2_framebuffer32(&karg.v2fb, up); | ||
686 | compatible_arg = 0; | ||
687 | break; | ||
688 | |||
689 | case VIDIOC_G_FMT: | ||
690 | case VIDIOC_S_FMT: | ||
691 | case VIDIOC_TRY_FMT: | ||
692 | err = get_v4l2_format32(&karg.v2f, up); | ||
693 | compatible_arg = 0; | ||
694 | break; | ||
695 | |||
696 | case VIDIOC_QUERYBUF: | ||
697 | case VIDIOC_QBUF: | ||
698 | case VIDIOC_DQBUF: | ||
699 | err = get_v4l2_buffer32(&karg.v2b, up); | ||
700 | compatible_arg = 0; | ||
701 | break; | ||
702 | |||
703 | case VIDIOC_ENUMSTD: | ||
704 | err = get_v4l2_standard(&karg.v2s, up); | ||
705 | compatible_arg = 0; | ||
706 | break; | ||
707 | |||
708 | case VIDIOC_ENUMSTD32: | ||
709 | err = get_v4l2_standard32(&karg.v2s, up); | ||
710 | compatible_arg = 0; | ||
711 | break; | ||
712 | |||
713 | case VIDIOC_ENUMINPUT: | ||
714 | err = get_v4l2_input(&karg.v2i, up); | ||
715 | compatible_arg = 0; | ||
716 | break; | ||
717 | |||
718 | case VIDIOC_ENUMINPUT32: | ||
719 | err = get_v4l2_input32(&karg.v2i, up); | ||
720 | compatible_arg = 0; | ||
721 | break; | ||
722 | |||
723 | case VIDIOC_G_TUNER: | ||
724 | case VIDIOC_S_TUNER: | ||
725 | err = get_v4l2_tuner(&karg.v2t, up); | ||
726 | compatible_arg = 0; | ||
727 | break; | ||
728 | |||
729 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
730 | case VIDIOCGWIN: | ||
731 | case VIDIOCGFBUF: | ||
732 | case VIDIOCGFREQ: | ||
733 | #endif | ||
734 | case VIDIOC_G_FBUF: | ||
735 | case VIDIOC_G_INPUT: | ||
736 | compatible_arg = 0; | ||
737 | break; | ||
738 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
739 | case VIDIOCSMICROCODE: | ||
740 | err = microcode32(&karg.vc, up); | ||
741 | compatible_arg = 0; | ||
742 | break; | ||
743 | #endif | ||
744 | }; | ||
745 | if (err) | ||
746 | goto out; | ||
747 | |||
748 | if (compatible_arg) | ||
749 | err = native_ioctl(file, realcmd, (unsigned long)up); | ||
750 | else { | ||
751 | mm_segment_t old_fs = get_fs(); | ||
752 | |||
753 | set_fs(KERNEL_DS); | ||
754 | err = native_ioctl(file, realcmd, (unsigned long)&karg); | ||
755 | set_fs(old_fs); | ||
756 | } | ||
757 | if (err == 0) { | ||
758 | switch (cmd) { | ||
759 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
760 | case VIDIOCGTUNER: | ||
761 | err = put_video_tuner32(&karg.vt, up); | ||
762 | break; | ||
763 | |||
764 | case VIDIOCGWIN: | ||
765 | err = put_video_window32(&karg.vw, up); | ||
766 | break; | ||
767 | |||
768 | case VIDIOCGFBUF: | ||
769 | err = put_video_buffer32(&karg.vb, up); | ||
770 | break; | ||
771 | |||
772 | #endif | ||
773 | case VIDIOC_G_FBUF: | ||
774 | err = put_v4l2_framebuffer32(&karg.v2fb, up); | ||
775 | break; | ||
776 | |||
777 | case VIDIOC_G_FMT: | ||
778 | case VIDIOC_S_FMT: | ||
779 | case VIDIOC_TRY_FMT: | ||
780 | err = put_v4l2_format32(&karg.v2f, up); | ||
781 | break; | ||
782 | |||
783 | case VIDIOC_QUERYBUF: | ||
784 | case VIDIOC_QBUF: | ||
785 | case VIDIOC_DQBUF: | ||
786 | err = put_v4l2_buffer32(&karg.v2b, up); | ||
787 | break; | ||
788 | |||
789 | case VIDIOC_ENUMSTD: | ||
790 | err = put_v4l2_standard(&karg.v2s, up); | ||
791 | break; | ||
792 | |||
793 | case VIDIOC_ENUMSTD32: | ||
794 | err = put_v4l2_standard32(&karg.v2s, up); | ||
795 | break; | ||
796 | |||
797 | case VIDIOC_G_TUNER: | ||
798 | case VIDIOC_S_TUNER: | ||
799 | err = put_v4l2_tuner(&karg.v2t, up); | ||
800 | break; | ||
801 | |||
802 | case VIDIOC_ENUMINPUT: | ||
803 | err = put_v4l2_input(&karg.v2i, up); | ||
804 | break; | ||
805 | |||
806 | case VIDIOC_ENUMINPUT32: | ||
807 | err = put_v4l2_input32(&karg.v2i, up); | ||
808 | break; | ||
809 | |||
810 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
811 | case VIDIOCGFREQ: | ||
812 | #endif | ||
813 | case VIDIOC_G_INPUT: | ||
814 | err = put_user(((u32)karg.vx), (u32 __user *)up); | ||
815 | break; | ||
816 | }; | ||
817 | } | ||
818 | out: | ||
819 | return err; | ||
820 | } | ||
821 | |||
822 | long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | ||
823 | { | ||
824 | int ret = -ENOIOCTLCMD; | ||
825 | |||
826 | if (!file->f_op->ioctl && !file->f_op->unlocked_ioctl) | ||
827 | return ret; | ||
828 | |||
829 | switch (cmd) { | ||
830 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
831 | case VIDIOCSWIN32: | ||
832 | ret = do_set_window(file, cmd, arg); | ||
833 | break; | ||
834 | case VIDIOCGTUNER32: | ||
835 | case VIDIOCSTUNER32: | ||
836 | case VIDIOCGWIN32: | ||
837 | case VIDIOCGFBUF32: | ||
838 | case VIDIOCSFBUF32: | ||
839 | case VIDIOCGFREQ32: | ||
840 | case VIDIOCSFREQ32: | ||
841 | case VIDIOCGAUDIO: | ||
842 | case VIDIOCSAUDIO: | ||
843 | case VIDIOCGVBIFMT: | ||
844 | case VIDIOCSVBIFMT: | ||
845 | #endif | ||
846 | case VIDIOC_QUERYCAP: | ||
847 | case VIDIOC_ENUM_FMT: | ||
848 | case VIDIOC_G_FMT32: | ||
849 | case VIDIOC_CROPCAP: | ||
850 | case VIDIOC_S_CROP: | ||
851 | case VIDIOC_S_FMT32: | ||
852 | case VIDIOC_REQBUFS: | ||
853 | case VIDIOC_QUERYBUF32: | ||
854 | case VIDIOC_G_FBUF32: | ||
855 | case VIDIOC_S_FBUF32: | ||
856 | case VIDIOC_OVERLAY32: | ||
857 | case VIDIOC_QBUF32: | ||
858 | case VIDIOC_DQBUF32: | ||
859 | case VIDIOC_STREAMON32: | ||
860 | case VIDIOC_STREAMOFF32: | ||
861 | case VIDIOC_G_PARM: | ||
862 | case VIDIOC_S_PARM: | ||
863 | case VIDIOC_G_STD: | ||
864 | case VIDIOC_S_STD: | ||
865 | case VIDIOC_G_TUNER: | ||
866 | case VIDIOC_S_TUNER: | ||
867 | case VIDIOC_ENUMSTD: | ||
868 | case VIDIOC_ENUMSTD32: | ||
869 | case VIDIOC_ENUMINPUT: | ||
870 | case VIDIOC_ENUMINPUT32: | ||
871 | case VIDIOC_G_CTRL: | ||
872 | case VIDIOC_S_CTRL: | ||
873 | case VIDIOC_S_CTRL32: | ||
874 | case VIDIOC_S_FREQUENCY: | ||
875 | case VIDIOC_G_FREQUENCY: | ||
876 | case VIDIOC_QUERYCTRL: | ||
877 | case VIDIOC_G_INPUT32: | ||
878 | case VIDIOC_S_INPUT32: | ||
879 | case VIDIOC_TRY_FMT32: | ||
880 | case VIDIOC_S_HW_FREQ_SEEK: | ||
881 | case VIDIOC_ENUM_FRAMESIZES: | ||
882 | case VIDIOC_ENUM_FRAMEINTERVALS: | ||
883 | ret = do_video_ioctl(file, cmd, arg); | ||
884 | break; | ||
885 | |||
886 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
887 | /* Little v, the video4linux ioctls (conflict?) */ | ||
888 | case VIDIOCGCAP: | ||
889 | case VIDIOCGCHAN: | ||
890 | case VIDIOCSCHAN: | ||
891 | case VIDIOCGPICT: | ||
892 | case VIDIOCSPICT: | ||
893 | case VIDIOCCAPTURE: | ||
894 | case VIDIOCKEY: | ||
895 | case VIDIOCSYNC: | ||
896 | case VIDIOCMCAPTURE: | ||
897 | case VIDIOCGMBUF: | ||
898 | case VIDIOCGUNIT: | ||
899 | case VIDIOCGCAPTURE: | ||
900 | case VIDIOCSCAPTURE: | ||
901 | |||
902 | /* BTTV specific... */ | ||
903 | case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]): | ||
904 | case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]): | ||
905 | case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int): | ||
906 | case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */ | ||
907 | case _IOR('v' , BASE_VIDIOCPRIVATE+4, int): | ||
908 | case _IOR('v' , BASE_VIDIOCPRIVATE+5, int): | ||
909 | case _IOR('v' , BASE_VIDIOCPRIVATE+6, int): | ||
910 | case _IOR('v' , BASE_VIDIOCPRIVATE+7, int): | ||
911 | ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); | ||
912 | break; | ||
913 | #endif | ||
914 | default: | ||
915 | v4l_print_ioctl("compat_ioctl32", cmd); | ||
916 | } | ||
917 | return ret; | ||
918 | } | ||
919 | #else | ||
920 | long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | ||
921 | { | ||
922 | return -ENOIOCTLCMD; | ||
923 | } | ||
924 | #endif | ||
925 | EXPORT_SYMBOL_GPL(v4l_compat_ioctl32); | ||
926 | |||
927 | MODULE_LICENSE("GPL"); | ||