aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/v4l2-compat-ioctl32.c
diff options
context:
space:
mode:
authorPawel Osciak <p.osciak@samsung.com>2010-07-29 13:56:47 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-21 19:31:33 -0400
commit52a3082fea41ffe77003be76ac1496d60bb7908e (patch)
tree77724c1a8e010237369c39eb55e3677dcc3dec67 /drivers/media/video/v4l2-compat-ioctl32.c
parentd14e6d76ebf740fd0d0bd296933993a555938896 (diff)
[media] v4l: Add compat functions for the multi-planar API
Add multi-planar ioctl handling to the 32bit compatibility layer. [mchehab@redhat.com: Merged with a fixup patch from Pawel] Signed-off-by: Pawel Osciak <p.osciak@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-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.c229
1 files changed, 195 insertions, 34 deletions
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index dc82eb83c1d..c19208a07b4 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -97,6 +97,14 @@ static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pi
97 return 0; 97 return 0;
98} 98}
99 99
100static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
101 struct v4l2_pix_format_mplane __user *up)
102{
103 if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
104 return -EFAULT;
105 return 0;
106}
107
100static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 108static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
101{ 109{
102 if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) 110 if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
@@ -104,6 +112,14 @@ static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pi
104 return 0; 112 return 0;
105} 113}
106 114
115static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
116 struct v4l2_pix_format_mplane __user *up)
117{
118 if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
119 return -EFAULT;
120 return 0;
121}
122
107static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 123static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
108{ 124{
109 if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) 125 if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
@@ -136,6 +152,7 @@ struct v4l2_format32 {
136 enum v4l2_buf_type type; 152 enum v4l2_buf_type type;
137 union { 153 union {
138 struct v4l2_pix_format pix; 154 struct v4l2_pix_format pix;
155 struct v4l2_pix_format_mplane pix_mp;
139 struct v4l2_window32 win; 156 struct v4l2_window32 win;
140 struct v4l2_vbi_format vbi; 157 struct v4l2_vbi_format vbi;
141 struct v4l2_sliced_vbi_format sliced; 158 struct v4l2_sliced_vbi_format sliced;
@@ -152,6 +169,10 @@ static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
152 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 169 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
153 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 170 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
154 return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); 171 return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
172 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
173 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
174 return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
175 &up->fmt.pix_mp);
155 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 176 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
156 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 177 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
157 return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); 178 return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
@@ -181,6 +202,10 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
181 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 202 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
182 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 203 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
183 return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); 204 return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
205 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
206 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
207 return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
208 &up->fmt.pix_mp);
184 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 209 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
185 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 210 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
186 return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); 211 return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
@@ -232,6 +257,17 @@ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32
232 return 0; 257 return 0;
233} 258}
234 259
260struct v4l2_plane32 {
261 __u32 bytesused;
262 __u32 length;
263 union {
264 __u32 mem_offset;
265 compat_long_t userptr;
266 } m;
267 __u32 data_offset;
268 __u32 reserved[11];
269};
270
235struct v4l2_buffer32 { 271struct v4l2_buffer32 {
236 __u32 index; 272 __u32 index;
237 enum v4l2_buf_type type; 273 enum v4l2_buf_type type;
@@ -247,14 +283,64 @@ struct v4l2_buffer32 {
247 union { 283 union {
248 __u32 offset; 284 __u32 offset;
249 compat_long_t userptr; 285 compat_long_t userptr;
286 compat_caddr_t planes;
250 } m; 287 } m;
251 __u32 length; 288 __u32 length;
252 __u32 input; 289 __u32 input;
253 __u32 reserved; 290 __u32 reserved;
254}; 291};
255 292
293static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
294 enum v4l2_memory memory)
295{
296 void __user *up_pln;
297 compat_long_t p;
298
299 if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
300 copy_in_user(&up->data_offset, &up32->data_offset,
301 sizeof(__u32)))
302 return -EFAULT;
303
304 if (memory == V4L2_MEMORY_USERPTR) {
305 if (get_user(p, &up32->m.userptr))
306 return -EFAULT;
307 up_pln = compat_ptr(p);
308 if (put_user((unsigned long)up_pln, &up->m.userptr))
309 return -EFAULT;
310 } else {
311 if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
312 sizeof(__u32)))
313 return -EFAULT;
314 }
315
316 return 0;
317}
318
319static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
320 enum v4l2_memory memory)
321{
322 if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
323 copy_in_user(&up32->data_offset, &up->data_offset,
324 sizeof(__u32)))
325 return -EFAULT;
326
327 /* For MMAP, driver might've set up the offset, so copy it back.
328 * USERPTR stays the same (was userspace-provided), so no copying. */
329 if (memory == V4L2_MEMORY_MMAP)
330 if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
331 sizeof(__u32)))
332 return -EFAULT;
333
334 return 0;
335}
336
256static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 337static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
257{ 338{
339 struct v4l2_plane32 __user *uplane32;
340 struct v4l2_plane __user *uplane;
341 compat_caddr_t p;
342 int num_planes;
343 int ret;
258 344
259 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || 345 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
260 get_user(kp->index, &up->index) || 346 get_user(kp->index, &up->index) ||
@@ -263,33 +349,84 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
263 get_user(kp->memory, &up->memory) || 349 get_user(kp->memory, &up->memory) ||
264 get_user(kp->input, &up->input)) 350 get_user(kp->input, &up->input))
265 return -EFAULT; 351 return -EFAULT;
266 switch (kp->memory) { 352
267 case V4L2_MEMORY_MMAP: 353 if (V4L2_TYPE_IS_OUTPUT(kp->type))
268 if (get_user(kp->length, &up->length) || 354 if (get_user(kp->bytesused, &up->bytesused) ||
269 get_user(kp->m.offset, &up->m.offset)) 355 get_user(kp->field, &up->field) ||
356 get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
357 get_user(kp->timestamp.tv_usec,
358 &up->timestamp.tv_usec))
270 return -EFAULT; 359 return -EFAULT;
271 break;
272 case V4L2_MEMORY_USERPTR:
273 {
274 compat_long_t tmp;
275 360
276 if (get_user(kp->length, &up->length) || 361 if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
277 get_user(tmp, &up->m.userptr)) 362 if (get_user(kp->length, &up->length))
278 return -EFAULT; 363 return -EFAULT;
279 364
280 kp->m.userptr = (unsigned long)compat_ptr(tmp); 365 num_planes = kp->length;
366 if (num_planes == 0) {
367 kp->m.planes = NULL;
368 /* num_planes == 0 is legal, e.g. when userspace doesn't
369 * need planes array on DQBUF*/
370 return 0;
281 } 371 }
282 break; 372
283 case V4L2_MEMORY_OVERLAY: 373 if (get_user(p, &up->m.planes))
284 if (get_user(kp->m.offset, &up->m.offset))
285 return -EFAULT; 374 return -EFAULT;
286 break; 375
376 uplane32 = compat_ptr(p);
377 if (!access_ok(VERIFY_READ, uplane32,
378 num_planes * sizeof(struct v4l2_plane32)))
379 return -EFAULT;
380
381 /* We don't really care if userspace decides to kill itself
382 * by passing a very big num_planes value */
383 uplane = compat_alloc_user_space(num_planes *
384 sizeof(struct v4l2_plane));
385 kp->m.planes = uplane;
386
387 while (--num_planes >= 0) {
388 ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
389 if (ret)
390 return ret;
391 ++uplane;
392 ++uplane32;
393 }
394 } else {
395 switch (kp->memory) {
396 case V4L2_MEMORY_MMAP:
397 if (get_user(kp->length, &up->length) ||
398 get_user(kp->m.offset, &up->m.offset))
399 return -EFAULT;
400 break;
401 case V4L2_MEMORY_USERPTR:
402 {
403 compat_long_t tmp;
404
405 if (get_user(kp->length, &up->length) ||
406 get_user(tmp, &up->m.userptr))
407 return -EFAULT;
408
409 kp->m.userptr = (unsigned long)compat_ptr(tmp);
410 }
411 break;
412 case V4L2_MEMORY_OVERLAY:
413 if (get_user(kp->m.offset, &up->m.offset))
414 return -EFAULT;
415 break;
416 }
287 } 417 }
418
288 return 0; 419 return 0;
289} 420}
290 421
291static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 422static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
292{ 423{
424 struct v4l2_plane32 __user *uplane32;
425 struct v4l2_plane __user *uplane;
426 compat_caddr_t p;
427 int num_planes;
428 int ret;
429
293 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) || 430 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
294 put_user(kp->index, &up->index) || 431 put_user(kp->index, &up->index) ||
295 put_user(kp->type, &up->type) || 432 put_user(kp->type, &up->type) ||
@@ -297,22 +434,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
297 put_user(kp->memory, &up->memory) || 434 put_user(kp->memory, &up->memory) ||
298 put_user(kp->input, &up->input)) 435 put_user(kp->input, &up->input))
299 return -EFAULT; 436 return -EFAULT;
300 switch (kp->memory) { 437
301 case V4L2_MEMORY_MMAP:
302 if (put_user(kp->length, &up->length) ||
303 put_user(kp->m.offset, &up->m.offset))
304 return -EFAULT;
305 break;
306 case V4L2_MEMORY_USERPTR:
307 if (put_user(kp->length, &up->length) ||
308 put_user(kp->m.userptr, &up->m.userptr))
309 return -EFAULT;
310 break;
311 case V4L2_MEMORY_OVERLAY:
312 if (put_user(kp->m.offset, &up->m.offset))
313 return -EFAULT;
314 break;
315 }
316 if (put_user(kp->bytesused, &up->bytesused) || 438 if (put_user(kp->bytesused, &up->bytesused) ||
317 put_user(kp->field, &up->field) || 439 put_user(kp->field, &up->field) ||
318 put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || 440 put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
@@ -321,6 +443,43 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
321 put_user(kp->sequence, &up->sequence) || 443 put_user(kp->sequence, &up->sequence) ||
322 put_user(kp->reserved, &up->reserved)) 444 put_user(kp->reserved, &up->reserved))
323 return -EFAULT; 445 return -EFAULT;
446
447 if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
448 num_planes = kp->length;
449 if (num_planes == 0)
450 return 0;
451
452 uplane = kp->m.planes;
453 if (get_user(p, &up->m.planes))
454 return -EFAULT;
455 uplane32 = compat_ptr(p);
456
457 while (--num_planes >= 0) {
458 ret = put_v4l2_plane32(uplane, uplane32, kp->memory);
459 if (ret)
460 return ret;
461 ++uplane;
462 ++uplane32;
463 }
464 } else {
465 switch (kp->memory) {
466 case V4L2_MEMORY_MMAP:
467 if (put_user(kp->length, &up->length) ||
468 put_user(kp->m.offset, &up->m.offset))
469 return -EFAULT;
470 break;
471 case V4L2_MEMORY_USERPTR:
472 if (put_user(kp->length, &up->length) ||
473 put_user(kp->m.userptr, &up->m.userptr))
474 return -EFAULT;
475 break;
476 case V4L2_MEMORY_OVERLAY:
477 if (put_user(kp->m.offset, &up->m.offset))
478 return -EFAULT;
479 break;
480 }
481 }
482
324 return 0; 483 return 0;
325} 484}
326 485
@@ -442,12 +601,13 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
442 if (get_user(p, &up->controls)) 601 if (get_user(p, &up->controls))
443 return -EFAULT; 602 return -EFAULT;
444 ucontrols = compat_ptr(p); 603 ucontrols = compat_ptr(p);
445 if (!access_ok(VERIFY_READ, ucontrols, n * sizeof(struct v4l2_ext_control))) 604 if (!access_ok(VERIFY_READ, ucontrols,
605 n * sizeof(struct v4l2_ext_control32)))
446 return -EFAULT; 606 return -EFAULT;
447 kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); 607 kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
448 kp->controls = kcontrols; 608 kp->controls = kcontrols;
449 while (--n >= 0) { 609 while (--n >= 0) {
450 if (copy_in_user(kcontrols, ucontrols, sizeof(*kcontrols))) 610 if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
451 return -EFAULT; 611 return -EFAULT;
452 if (ctrl_is_pointer(kcontrols->id)) { 612 if (ctrl_is_pointer(kcontrols->id)) {
453 void __user *s; 613 void __user *s;
@@ -483,7 +643,8 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
483 if (get_user(p, &up->controls)) 643 if (get_user(p, &up->controls))
484 return -EFAULT; 644 return -EFAULT;
485 ucontrols = compat_ptr(p); 645 ucontrols = compat_ptr(p);
486 if (!access_ok(VERIFY_WRITE, ucontrols, n * sizeof(struct v4l2_ext_control))) 646 if (!access_ok(VERIFY_WRITE, ucontrols,
647 n * sizeof(struct v4l2_ext_control32)))
487 return -EFAULT; 648 return -EFAULT;
488 649
489 while (--n >= 0) { 650 while (--n >= 0) {