aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/v4l2-ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/v4l2-ioctl.c')
-rw-r--r--drivers/media/video/v4l2-ioctl.c669
1 files changed, 482 insertions, 187 deletions
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index f51327ef6757..a01ed39e6c16 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -17,7 +17,6 @@
17#include <linux/types.h> 17#include <linux/types.h>
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19 19
20#define __OLD_VIDIOC_ /* To allow fixing old calls */
21#include <linux/videodev2.h> 20#include <linux/videodev2.h>
22 21
23#include <media/v4l2-common.h> 22#include <media/v4l2-common.h>
@@ -25,6 +24,7 @@
25#include <media/v4l2-ctrls.h> 24#include <media/v4l2-ctrls.h>
26#include <media/v4l2-fh.h> 25#include <media/v4l2-fh.h>
27#include <media/v4l2-event.h> 26#include <media/v4l2-event.h>
27#include <media/v4l2-device.h>
28#include <media/v4l2-chip-ident.h> 28#include <media/v4l2-chip-ident.h>
29 29
30#define dbgarg(cmd, fmt, arg...) \ 30#define dbgarg(cmd, fmt, arg...) \
@@ -165,6 +165,8 @@ const char *v4l2_type_names[] = {
165 [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap", 165 [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
166 [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out", 166 [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out",
167 [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay", 167 [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
168 [V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE] = "vid-cap-mplane",
169 [V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
168}; 170};
169EXPORT_SYMBOL(v4l2_type_names); 171EXPORT_SYMBOL(v4l2_type_names);
170 172
@@ -293,153 +295,37 @@ void v4l_printk_ioctl(unsigned int cmd)
293} 295}
294EXPORT_SYMBOL(v4l_printk_ioctl); 296EXPORT_SYMBOL(v4l_printk_ioctl);
295 297
296/*
297 * helper function -- handles userspace copying for ioctl arguments
298 */
299
300#ifdef __OLD_VIDIOC_
301static unsigned int
302video_fix_command(unsigned int cmd)
303{
304 switch (cmd) {
305 case VIDIOC_OVERLAY_OLD:
306 cmd = VIDIOC_OVERLAY;
307 break;
308 case VIDIOC_S_PARM_OLD:
309 cmd = VIDIOC_S_PARM;
310 break;
311 case VIDIOC_S_CTRL_OLD:
312 cmd = VIDIOC_S_CTRL;
313 break;
314 case VIDIOC_G_AUDIO_OLD:
315 cmd = VIDIOC_G_AUDIO;
316 break;
317 case VIDIOC_G_AUDOUT_OLD:
318 cmd = VIDIOC_G_AUDOUT;
319 break;
320 case VIDIOC_CROPCAP_OLD:
321 cmd = VIDIOC_CROPCAP;
322 break;
323 }
324 return cmd;
325}
326#endif
327
328/*
329 * Obsolete usercopy function - Should be removed soon
330 */
331long
332video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
333 v4l2_kioctl func)
334{
335 char sbuf[128];
336 void *mbuf = NULL;
337 void *parg = NULL;
338 long err = -EINVAL;
339 int is_ext_ctrl;
340 size_t ctrls_size = 0;
341 void __user *user_ptr = NULL;
342
343#ifdef __OLD_VIDIOC_
344 cmd = video_fix_command(cmd);
345#endif
346 is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
347 cmd == VIDIOC_TRY_EXT_CTRLS);
348
349 /* Copy arguments into temp kernel buffer */
350 switch (_IOC_DIR(cmd)) {
351 case _IOC_NONE:
352 parg = NULL;
353 break;
354 case _IOC_READ:
355 case _IOC_WRITE:
356 case (_IOC_WRITE | _IOC_READ):
357 if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
358 parg = sbuf;
359 } else {
360 /* too big to allocate from stack */
361 mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
362 if (NULL == mbuf)
363 return -ENOMEM;
364 parg = mbuf;
365 }
366
367 err = -EFAULT;
368 if (_IOC_DIR(cmd) & _IOC_WRITE)
369 if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
370 goto out;
371 break;
372 }
373 if (is_ext_ctrl) {
374 struct v4l2_ext_controls *p = parg;
375
376 /* In case of an error, tell the caller that it wasn't
377 a specific control that caused it. */
378 p->error_idx = p->count;
379 user_ptr = (void __user *)p->controls;
380 if (p->count) {
381 ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
382 /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
383 mbuf = kmalloc(ctrls_size, GFP_KERNEL);
384 err = -ENOMEM;
385 if (NULL == mbuf)
386 goto out_ext_ctrl;
387 err = -EFAULT;
388 if (copy_from_user(mbuf, user_ptr, ctrls_size))
389 goto out_ext_ctrl;
390 p->controls = mbuf;
391 }
392 }
393
394 /* call driver */
395 err = func(file, cmd, parg);
396 if (err == -ENOIOCTLCMD)
397 err = -EINVAL;
398 if (is_ext_ctrl) {
399 struct v4l2_ext_controls *p = parg;
400
401 p->controls = (void *)user_ptr;
402 if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
403 err = -EFAULT;
404 goto out_ext_ctrl;
405 }
406 if (err < 0)
407 goto out;
408
409out_ext_ctrl:
410 /* Copy results into user buffer */
411 switch (_IOC_DIR(cmd)) {
412 case _IOC_READ:
413 case (_IOC_WRITE | _IOC_READ):
414 if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
415 err = -EFAULT;
416 break;
417 }
418
419out:
420 kfree(mbuf);
421 return err;
422}
423EXPORT_SYMBOL(video_usercopy);
424
425static void dbgbuf(unsigned int cmd, struct video_device *vfd, 298static void dbgbuf(unsigned int cmd, struct video_device *vfd,
426 struct v4l2_buffer *p) 299 struct v4l2_buffer *p)
427{ 300{
428 struct v4l2_timecode *tc = &p->timecode; 301 struct v4l2_timecode *tc = &p->timecode;
302 struct v4l2_plane *plane;
303 int i;
429 304
430 dbgarg(cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " 305 dbgarg(cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
431 "bytesused=%d, flags=0x%08d, " 306 "flags=0x%08d, field=%0d, sequence=%d, memory=%s\n",
432 "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n",
433 p->timestamp.tv_sec / 3600, 307 p->timestamp.tv_sec / 3600,
434 (int)(p->timestamp.tv_sec / 60) % 60, 308 (int)(p->timestamp.tv_sec / 60) % 60,
435 (int)(p->timestamp.tv_sec % 60), 309 (int)(p->timestamp.tv_sec % 60),
436 (long)p->timestamp.tv_usec, 310 (long)p->timestamp.tv_usec,
437 p->index, 311 p->index,
438 prt_names(p->type, v4l2_type_names), 312 prt_names(p->type, v4l2_type_names),
439 p->bytesused, p->flags, 313 p->flags, p->field, p->sequence,
440 p->field, p->sequence, 314 prt_names(p->memory, v4l2_memory_names));
441 prt_names(p->memory, v4l2_memory_names), 315
442 p->m.userptr, p->length); 316 if (V4L2_TYPE_IS_MULTIPLANAR(p->type) && p->m.planes) {
317 for (i = 0; i < p->length; ++i) {
318 plane = &p->m.planes[i];
319 dbgarg2("plane %d: bytesused=%d, data_offset=0x%08x "
320 "offset/userptr=0x%08lx, length=%d\n",
321 i, plane->bytesused, plane->data_offset,
322 plane->m.userptr, plane->length);
323 }
324 } else {
325 dbgarg2("bytesused=%d, offset/userptr=0x%08lx, length=%d\n",
326 p->bytesused, p->m.userptr, p->length);
327 }
328
443 dbgarg2("timecode=%02d:%02d:%02d type=%d, " 329 dbgarg2("timecode=%02d:%02d:%02d type=%d, "
444 "flags=0x%08d, frames=%d, userbits=0x%08x\n", 330 "flags=0x%08d, frames=%d, userbits=0x%08x\n",
445 tc->hours, tc->minutes, tc->seconds, 331 tc->hours, tc->minutes, tc->seconds,
@@ -467,6 +353,27 @@ static inline void v4l_print_pix_fmt(struct video_device *vfd,
467 fmt->bytesperline, fmt->sizeimage, fmt->colorspace); 353 fmt->bytesperline, fmt->sizeimage, fmt->colorspace);
468}; 354};
469 355
356static inline void v4l_print_pix_fmt_mplane(struct video_device *vfd,
357 struct v4l2_pix_format_mplane *fmt)
358{
359 int i;
360
361 dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, "
362 "colorspace=%d, num_planes=%d\n",
363 fmt->width, fmt->height,
364 (fmt->pixelformat & 0xff),
365 (fmt->pixelformat >> 8) & 0xff,
366 (fmt->pixelformat >> 16) & 0xff,
367 (fmt->pixelformat >> 24) & 0xff,
368 prt_names(fmt->field, v4l2_field_names),
369 fmt->colorspace, fmt->num_planes);
370
371 for (i = 0; i < fmt->num_planes; ++i)
372 dbgarg2("plane %d: bytesperline=%d sizeimage=%d\n", i,
373 fmt->plane_fmt[i].bytesperline,
374 fmt->plane_fmt[i].sizeimage);
375}
376
470static inline void v4l_print_ext_ctrls(unsigned int cmd, 377static inline void v4l_print_ext_ctrls(unsigned int cmd,
471 struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals) 378 struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals)
472{ 379{
@@ -520,7 +427,12 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
520 427
521 switch (type) { 428 switch (type) {
522 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 429 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
523 if (ops->vidioc_g_fmt_vid_cap) 430 if (ops->vidioc_g_fmt_vid_cap ||
431 ops->vidioc_g_fmt_vid_cap_mplane)
432 return 0;
433 break;
434 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
435 if (ops->vidioc_g_fmt_vid_cap_mplane)
524 return 0; 436 return 0;
525 break; 437 break;
526 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 438 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
@@ -528,7 +440,12 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
528 return 0; 440 return 0;
529 break; 441 break;
530 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 442 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
531 if (ops->vidioc_g_fmt_vid_out) 443 if (ops->vidioc_g_fmt_vid_out ||
444 ops->vidioc_g_fmt_vid_out_mplane)
445 return 0;
446 break;
447 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
448 if (ops->vidioc_g_fmt_vid_out_mplane)
532 return 0; 449 return 0;
533 break; 450 break;
534 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 451 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
@@ -559,12 +476,72 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
559 return -EINVAL; 476 return -EINVAL;
560} 477}
561 478
479/**
480 * fmt_sp_to_mp() - Convert a single-plane format to its multi-planar 1-plane
481 * equivalent
482 */
483static int fmt_sp_to_mp(const struct v4l2_format *f_sp,
484 struct v4l2_format *f_mp)
485{
486 struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
487 const struct v4l2_pix_format *pix = &f_sp->fmt.pix;
488
489 if (f_sp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
490 f_mp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
491 else if (f_sp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
492 f_mp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
493 else
494 return -EINVAL;
495
496 pix_mp->width = pix->width;
497 pix_mp->height = pix->height;
498 pix_mp->pixelformat = pix->pixelformat;
499 pix_mp->field = pix->field;
500 pix_mp->colorspace = pix->colorspace;
501 pix_mp->num_planes = 1;
502 pix_mp->plane_fmt[0].sizeimage = pix->sizeimage;
503 pix_mp->plane_fmt[0].bytesperline = pix->bytesperline;
504
505 return 0;
506}
507
508/**
509 * fmt_mp_to_sp() - Convert a multi-planar 1-plane format to its single-planar
510 * equivalent
511 */
512static int fmt_mp_to_sp(const struct v4l2_format *f_mp,
513 struct v4l2_format *f_sp)
514{
515 const struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
516 struct v4l2_pix_format *pix = &f_sp->fmt.pix;
517
518 if (f_mp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
519 f_sp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
520 else if (f_mp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
521 f_sp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
522 else
523 return -EINVAL;
524
525 pix->width = pix_mp->width;
526 pix->height = pix_mp->height;
527 pix->pixelformat = pix_mp->pixelformat;
528 pix->field = pix_mp->field;
529 pix->colorspace = pix_mp->colorspace;
530 pix->sizeimage = pix_mp->plane_fmt[0].sizeimage;
531 pix->bytesperline = pix_mp->plane_fmt[0].bytesperline;
532
533 return 0;
534}
535
562static long __video_do_ioctl(struct file *file, 536static long __video_do_ioctl(struct file *file,
563 unsigned int cmd, void *arg) 537 unsigned int cmd, void *arg)
564{ 538{
565 struct video_device *vfd = video_devdata(file); 539 struct video_device *vfd = video_devdata(file);
566 const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; 540 const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
567 void *fh = file->private_data; 541 void *fh = file->private_data;
542 struct v4l2_fh *vfh = NULL;
543 struct v4l2_format f_copy;
544 int use_fh_prio = 0;
568 long ret = -EINVAL; 545 long ret = -EINVAL;
569 546
570 if (ops == NULL) { 547 if (ops == NULL) {
@@ -579,6 +556,45 @@ static long __video_do_ioctl(struct file *file,
579 printk(KERN_CONT "\n"); 556 printk(KERN_CONT "\n");
580 } 557 }
581 558
559 if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
560 vfh = file->private_data;
561 use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
562 }
563
564 if (use_fh_prio) {
565 switch (cmd) {
566 case VIDIOC_S_CTRL:
567 case VIDIOC_S_STD:
568 case VIDIOC_S_INPUT:
569 case VIDIOC_S_OUTPUT:
570 case VIDIOC_S_TUNER:
571 case VIDIOC_S_FREQUENCY:
572 case VIDIOC_S_FMT:
573 case VIDIOC_S_CROP:
574 case VIDIOC_S_AUDIO:
575 case VIDIOC_S_AUDOUT:
576 case VIDIOC_S_EXT_CTRLS:
577 case VIDIOC_S_FBUF:
578 case VIDIOC_S_PRIORITY:
579 case VIDIOC_S_DV_PRESET:
580 case VIDIOC_S_DV_TIMINGS:
581 case VIDIOC_S_JPEGCOMP:
582 case VIDIOC_S_MODULATOR:
583 case VIDIOC_S_PARM:
584 case VIDIOC_S_HW_FREQ_SEEK:
585 case VIDIOC_ENCODER_CMD:
586 case VIDIOC_OVERLAY:
587 case VIDIOC_REQBUFS:
588 case VIDIOC_STREAMON:
589 case VIDIOC_STREAMOFF:
590 ret = v4l2_prio_check(vfd->prio, vfh->prio);
591 if (ret)
592 goto exit_prio;
593 ret = -EINVAL;
594 break;
595 }
596 }
597
582 switch (cmd) { 598 switch (cmd) {
583 599
584 /* --- capabilities ------------------------------------------ */ 600 /* --- capabilities ------------------------------------------ */
@@ -605,9 +621,12 @@ static long __video_do_ioctl(struct file *file,
605 { 621 {
606 enum v4l2_priority *p = arg; 622 enum v4l2_priority *p = arg;
607 623
608 if (!ops->vidioc_g_priority) 624 if (ops->vidioc_g_priority) {
609 break; 625 ret = ops->vidioc_g_priority(file, fh, p);
610 ret = ops->vidioc_g_priority(file, fh, p); 626 } else if (use_fh_prio) {
627 *p = v4l2_prio_max(&vfd->v4l2_dev->prio);
628 ret = 0;
629 }
611 if (!ret) 630 if (!ret)
612 dbgarg(cmd, "priority is %d\n", *p); 631 dbgarg(cmd, "priority is %d\n", *p);
613 break; 632 break;
@@ -616,10 +635,13 @@ static long __video_do_ioctl(struct file *file,
616 { 635 {
617 enum v4l2_priority *p = arg; 636 enum v4l2_priority *p = arg;
618 637
619 if (!ops->vidioc_s_priority) 638 if (!ops->vidioc_s_priority && !use_fh_prio)
620 break; 639 break;
621 dbgarg(cmd, "setting priority to %d\n", *p); 640 dbgarg(cmd, "setting priority to %d\n", *p);
622 ret = ops->vidioc_s_priority(file, fh, *p); 641 if (ops->vidioc_s_priority)
642 ret = ops->vidioc_s_priority(file, fh, *p);
643 else
644 ret = v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);
623 break; 645 break;
624 } 646 }
625 647
@@ -633,6 +655,11 @@ static long __video_do_ioctl(struct file *file,
633 if (ops->vidioc_enum_fmt_vid_cap) 655 if (ops->vidioc_enum_fmt_vid_cap)
634 ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f); 656 ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);
635 break; 657 break;
658 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
659 if (ops->vidioc_enum_fmt_vid_cap_mplane)
660 ret = ops->vidioc_enum_fmt_vid_cap_mplane(file,
661 fh, f);
662 break;
636 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 663 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
637 if (ops->vidioc_enum_fmt_vid_overlay) 664 if (ops->vidioc_enum_fmt_vid_overlay)
638 ret = ops->vidioc_enum_fmt_vid_overlay(file, 665 ret = ops->vidioc_enum_fmt_vid_overlay(file,
@@ -642,6 +669,11 @@ static long __video_do_ioctl(struct file *file,
642 if (ops->vidioc_enum_fmt_vid_out) 669 if (ops->vidioc_enum_fmt_vid_out)
643 ret = ops->vidioc_enum_fmt_vid_out(file, fh, f); 670 ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
644 break; 671 break;
672 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
673 if (ops->vidioc_enum_fmt_vid_out_mplane)
674 ret = ops->vidioc_enum_fmt_vid_out_mplane(file,
675 fh, f);
676 break;
645 case V4L2_BUF_TYPE_PRIVATE: 677 case V4L2_BUF_TYPE_PRIVATE:
646 if (ops->vidioc_enum_fmt_type_private) 678 if (ops->vidioc_enum_fmt_type_private)
647 ret = ops->vidioc_enum_fmt_type_private(file, 679 ret = ops->vidioc_enum_fmt_type_private(file,
@@ -670,22 +702,90 @@ static long __video_do_ioctl(struct file *file,
670 702
671 switch (f->type) { 703 switch (f->type) {
672 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 704 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
673 if (ops->vidioc_g_fmt_vid_cap) 705 if (ops->vidioc_g_fmt_vid_cap) {
674 ret = ops->vidioc_g_fmt_vid_cap(file, fh, f); 706 ret = ops->vidioc_g_fmt_vid_cap(file, fh, f);
707 } else if (ops->vidioc_g_fmt_vid_cap_mplane) {
708 if (fmt_sp_to_mp(f, &f_copy))
709 break;
710 ret = ops->vidioc_g_fmt_vid_cap_mplane(file, fh,
711 &f_copy);
712 if (ret)
713 break;
714
715 /* Driver is currently in multi-planar format,
716 * we can't return it in single-planar API*/
717 if (f_copy.fmt.pix_mp.num_planes > 1) {
718 ret = -EBUSY;
719 break;
720 }
721
722 ret = fmt_mp_to_sp(&f_copy, f);
723 }
675 if (!ret) 724 if (!ret)
676 v4l_print_pix_fmt(vfd, &f->fmt.pix); 725 v4l_print_pix_fmt(vfd, &f->fmt.pix);
677 break; 726 break;
727 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
728 if (ops->vidioc_g_fmt_vid_cap_mplane) {
729 ret = ops->vidioc_g_fmt_vid_cap_mplane(file,
730 fh, f);
731 } else if (ops->vidioc_g_fmt_vid_cap) {
732 if (fmt_mp_to_sp(f, &f_copy))
733 break;
734 ret = ops->vidioc_g_fmt_vid_cap(file,
735 fh, &f_copy);
736 if (ret)
737 break;
738
739 ret = fmt_sp_to_mp(&f_copy, f);
740 }
741 if (!ret)
742 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
743 break;
678 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 744 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
679 if (ops->vidioc_g_fmt_vid_overlay) 745 if (ops->vidioc_g_fmt_vid_overlay)
680 ret = ops->vidioc_g_fmt_vid_overlay(file, 746 ret = ops->vidioc_g_fmt_vid_overlay(file,
681 fh, f); 747 fh, f);
682 break; 748 break;
683 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 749 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
684 if (ops->vidioc_g_fmt_vid_out) 750 if (ops->vidioc_g_fmt_vid_out) {
685 ret = ops->vidioc_g_fmt_vid_out(file, fh, f); 751 ret = ops->vidioc_g_fmt_vid_out(file, fh, f);
752 } else if (ops->vidioc_g_fmt_vid_out_mplane) {
753 if (fmt_sp_to_mp(f, &f_copy))
754 break;
755 ret = ops->vidioc_g_fmt_vid_out_mplane(file, fh,
756 &f_copy);
757 if (ret)
758 break;
759
760 /* Driver is currently in multi-planar format,
761 * we can't return it in single-planar API*/
762 if (f_copy.fmt.pix_mp.num_planes > 1) {
763 ret = -EBUSY;
764 break;
765 }
766
767 ret = fmt_mp_to_sp(&f_copy, f);
768 }
686 if (!ret) 769 if (!ret)
687 v4l_print_pix_fmt(vfd, &f->fmt.pix); 770 v4l_print_pix_fmt(vfd, &f->fmt.pix);
688 break; 771 break;
772 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
773 if (ops->vidioc_g_fmt_vid_out_mplane) {
774 ret = ops->vidioc_g_fmt_vid_out_mplane(file,
775 fh, f);
776 } else if (ops->vidioc_g_fmt_vid_out) {
777 if (fmt_mp_to_sp(f, &f_copy))
778 break;
779 ret = ops->vidioc_g_fmt_vid_out(file,
780 fh, &f_copy);
781 if (ret)
782 break;
783
784 ret = fmt_sp_to_mp(&f_copy, f);
785 }
786 if (!ret)
787 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
788 break;
689 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 789 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
690 if (ops->vidioc_g_fmt_vid_out_overlay) 790 if (ops->vidioc_g_fmt_vid_out_overlay)
691 ret = ops->vidioc_g_fmt_vid_out_overlay(file, 791 ret = ops->vidioc_g_fmt_vid_out_overlay(file,
@@ -729,8 +829,44 @@ static long __video_do_ioctl(struct file *file,
729 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 829 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
730 CLEAR_AFTER_FIELD(f, fmt.pix); 830 CLEAR_AFTER_FIELD(f, fmt.pix);
731 v4l_print_pix_fmt(vfd, &f->fmt.pix); 831 v4l_print_pix_fmt(vfd, &f->fmt.pix);
732 if (ops->vidioc_s_fmt_vid_cap) 832 if (ops->vidioc_s_fmt_vid_cap) {
733 ret = ops->vidioc_s_fmt_vid_cap(file, fh, f); 833 ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
834 } else if (ops->vidioc_s_fmt_vid_cap_mplane) {
835 if (fmt_sp_to_mp(f, &f_copy))
836 break;
837 ret = ops->vidioc_s_fmt_vid_cap_mplane(file, fh,
838 &f_copy);
839 if (ret)
840 break;
841
842 if (f_copy.fmt.pix_mp.num_planes > 1) {
843 /* Drivers shouldn't adjust from 1-plane
844 * to more than 1-plane formats */
845 ret = -EBUSY;
846 WARN_ON(1);
847 break;
848 }
849
850 ret = fmt_mp_to_sp(&f_copy, f);
851 }
852 break;
853 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
854 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
855 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
856 if (ops->vidioc_s_fmt_vid_cap_mplane) {
857 ret = ops->vidioc_s_fmt_vid_cap_mplane(file,
858 fh, f);
859 } else if (ops->vidioc_s_fmt_vid_cap &&
860 f->fmt.pix_mp.num_planes == 1) {
861 if (fmt_mp_to_sp(f, &f_copy))
862 break;
863 ret = ops->vidioc_s_fmt_vid_cap(file,
864 fh, &f_copy);
865 if (ret)
866 break;
867
868 ret = fmt_sp_to_mp(&f_copy, f);
869 }
734 break; 870 break;
735 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 871 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
736 CLEAR_AFTER_FIELD(f, fmt.win); 872 CLEAR_AFTER_FIELD(f, fmt.win);
@@ -741,8 +877,44 @@ static long __video_do_ioctl(struct file *file,
741 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 877 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
742 CLEAR_AFTER_FIELD(f, fmt.pix); 878 CLEAR_AFTER_FIELD(f, fmt.pix);
743 v4l_print_pix_fmt(vfd, &f->fmt.pix); 879 v4l_print_pix_fmt(vfd, &f->fmt.pix);
744 if (ops->vidioc_s_fmt_vid_out) 880 if (ops->vidioc_s_fmt_vid_out) {
745 ret = ops->vidioc_s_fmt_vid_out(file, fh, f); 881 ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
882 } else if (ops->vidioc_s_fmt_vid_out_mplane) {
883 if (fmt_sp_to_mp(f, &f_copy))
884 break;
885 ret = ops->vidioc_s_fmt_vid_out_mplane(file, fh,
886 &f_copy);
887 if (ret)
888 break;
889
890 if (f_copy.fmt.pix_mp.num_planes > 1) {
891 /* Drivers shouldn't adjust from 1-plane
892 * to more than 1-plane formats */
893 ret = -EBUSY;
894 WARN_ON(1);
895 break;
896 }
897
898 ret = fmt_mp_to_sp(&f_copy, f);
899 }
900 break;
901 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
902 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
903 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
904 if (ops->vidioc_s_fmt_vid_out_mplane) {
905 ret = ops->vidioc_s_fmt_vid_out_mplane(file,
906 fh, f);
907 } else if (ops->vidioc_s_fmt_vid_out &&
908 f->fmt.pix_mp.num_planes == 1) {
909 if (fmt_mp_to_sp(f, &f_copy))
910 break;
911 ret = ops->vidioc_s_fmt_vid_out(file,
912 fh, &f_copy);
913 if (ret)
914 break;
915
916 ret = fmt_mp_to_sp(&f_copy, f);
917 }
746 break; 918 break;
747 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 919 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
748 CLEAR_AFTER_FIELD(f, fmt.win); 920 CLEAR_AFTER_FIELD(f, fmt.win);
@@ -791,11 +963,47 @@ static long __video_do_ioctl(struct file *file,
791 switch (f->type) { 963 switch (f->type) {
792 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 964 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
793 CLEAR_AFTER_FIELD(f, fmt.pix); 965 CLEAR_AFTER_FIELD(f, fmt.pix);
794 if (ops->vidioc_try_fmt_vid_cap) 966 if (ops->vidioc_try_fmt_vid_cap) {
795 ret = ops->vidioc_try_fmt_vid_cap(file, fh, f); 967 ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
968 } else if (ops->vidioc_try_fmt_vid_cap_mplane) {
969 if (fmt_sp_to_mp(f, &f_copy))
970 break;
971 ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
972 fh, &f_copy);
973 if (ret)
974 break;
975
976 if (f_copy.fmt.pix_mp.num_planes > 1) {
977 /* Drivers shouldn't adjust from 1-plane
978 * to more than 1-plane formats */
979 ret = -EBUSY;
980 WARN_ON(1);
981 break;
982 }
983 ret = fmt_mp_to_sp(&f_copy, f);
984 }
796 if (!ret) 985 if (!ret)
797 v4l_print_pix_fmt(vfd, &f->fmt.pix); 986 v4l_print_pix_fmt(vfd, &f->fmt.pix);
798 break; 987 break;
988 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
989 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
990 if (ops->vidioc_try_fmt_vid_cap_mplane) {
991 ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
992 fh, f);
993 } else if (ops->vidioc_try_fmt_vid_cap &&
994 f->fmt.pix_mp.num_planes == 1) {
995 if (fmt_mp_to_sp(f, &f_copy))
996 break;
997 ret = ops->vidioc_try_fmt_vid_cap(file,
998 fh, &f_copy);
999 if (ret)
1000 break;
1001
1002 ret = fmt_sp_to_mp(&f_copy, f);
1003 }
1004 if (!ret)
1005 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
1006 break;
799 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 1007 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
800 CLEAR_AFTER_FIELD(f, fmt.win); 1008 CLEAR_AFTER_FIELD(f, fmt.win);
801 if (ops->vidioc_try_fmt_vid_overlay) 1009 if (ops->vidioc_try_fmt_vid_overlay)
@@ -804,11 +1012,47 @@ static long __video_do_ioctl(struct file *file,
804 break; 1012 break;
805 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 1013 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
806 CLEAR_AFTER_FIELD(f, fmt.pix); 1014 CLEAR_AFTER_FIELD(f, fmt.pix);
807 if (ops->vidioc_try_fmt_vid_out) 1015 if (ops->vidioc_try_fmt_vid_out) {
808 ret = ops->vidioc_try_fmt_vid_out(file, fh, f); 1016 ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
1017 } else if (ops->vidioc_try_fmt_vid_out_mplane) {
1018 if (fmt_sp_to_mp(f, &f_copy))
1019 break;
1020 ret = ops->vidioc_try_fmt_vid_out_mplane(file,
1021 fh, &f_copy);
1022 if (ret)
1023 break;
1024
1025 if (f_copy.fmt.pix_mp.num_planes > 1) {
1026 /* Drivers shouldn't adjust from 1-plane
1027 * to more than 1-plane formats */
1028 ret = -EBUSY;
1029 WARN_ON(1);
1030 break;
1031 }
1032 ret = fmt_mp_to_sp(&f_copy, f);
1033 }
809 if (!ret) 1034 if (!ret)
810 v4l_print_pix_fmt(vfd, &f->fmt.pix); 1035 v4l_print_pix_fmt(vfd, &f->fmt.pix);
811 break; 1036 break;
1037 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1038 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
1039 if (ops->vidioc_try_fmt_vid_out_mplane) {
1040 ret = ops->vidioc_try_fmt_vid_out_mplane(file,
1041 fh, f);
1042 } else if (ops->vidioc_try_fmt_vid_out &&
1043 f->fmt.pix_mp.num_planes == 1) {
1044 if (fmt_mp_to_sp(f, &f_copy))
1045 break;
1046 ret = ops->vidioc_try_fmt_vid_out(file,
1047 fh, &f_copy);
1048 if (ret)
1049 break;
1050
1051 ret = fmt_sp_to_mp(&f_copy, f);
1052 }
1053 if (!ret)
1054 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
1055 break;
812 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 1056 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
813 CLEAR_AFTER_FIELD(f, fmt.win); 1057 CLEAR_AFTER_FIELD(f, fmt.win);
814 if (ops->vidioc_try_fmt_vid_out_overlay) 1058 if (ops->vidioc_try_fmt_vid_out_overlay)
@@ -1942,13 +2186,18 @@ static long __video_do_ioctl(struct file *file,
1942 } 2186 }
1943 default: 2187 default:
1944 { 2188 {
2189 bool valid_prio = true;
2190
1945 if (!ops->vidioc_default) 2191 if (!ops->vidioc_default)
1946 break; 2192 break;
1947 ret = ops->vidioc_default(file, fh, cmd, arg); 2193 if (use_fh_prio)
2194 valid_prio = v4l2_prio_check(vfd->prio, vfh->prio) >= 0;
2195 ret = ops->vidioc_default(file, fh, valid_prio, cmd, arg);
1948 break; 2196 break;
1949 } 2197 }
1950 } /* switch */ 2198 } /* switch */
1951 2199
2200exit_prio:
1952 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { 2201 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
1953 if (ret < 0) { 2202 if (ret < 0) {
1954 v4l_print_ioctl(vfd->name, cmd); 2203 v4l_print_ioctl(vfd->name, cmd);
@@ -1973,7 +2222,7 @@ static unsigned long cmd_input_size(unsigned int cmd)
1973 switch (cmd) { 2222 switch (cmd) {
1974 CMDINSIZE(ENUM_FMT, fmtdesc, type); 2223 CMDINSIZE(ENUM_FMT, fmtdesc, type);
1975 CMDINSIZE(G_FMT, format, type); 2224 CMDINSIZE(G_FMT, format, type);
1976 CMDINSIZE(QUERYBUF, buffer, type); 2225 CMDINSIZE(QUERYBUF, buffer, length);
1977 CMDINSIZE(G_PARM, streamparm, type); 2226 CMDINSIZE(G_PARM, streamparm, type);
1978 CMDINSIZE(ENUMSTD, standard, index); 2227 CMDINSIZE(ENUMSTD, standard, index);
1979 CMDINSIZE(ENUMINPUT, input, index); 2228 CMDINSIZE(ENUMINPUT, input, index);
@@ -1998,22 +2247,61 @@ static unsigned long cmd_input_size(unsigned int cmd)
1998 } 2247 }
1999} 2248}
2000 2249
2001long video_ioctl2(struct file *file, 2250static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
2002 unsigned int cmd, unsigned long arg) 2251 void * __user *user_ptr, void ***kernel_ptr)
2252{
2253 int ret = 0;
2254
2255 switch (cmd) {
2256 case VIDIOC_QUERYBUF:
2257 case VIDIOC_QBUF:
2258 case VIDIOC_DQBUF: {
2259 struct v4l2_buffer *buf = parg;
2260
2261 if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && buf->length > 0) {
2262 if (buf->length > VIDEO_MAX_PLANES) {
2263 ret = -EINVAL;
2264 break;
2265 }
2266 *user_ptr = (void __user *)buf->m.planes;
2267 *kernel_ptr = (void **)&buf->m.planes;
2268 *array_size = sizeof(struct v4l2_plane) * buf->length;
2269 ret = 1;
2270 }
2271 break;
2272 }
2273
2274 case VIDIOC_S_EXT_CTRLS:
2275 case VIDIOC_G_EXT_CTRLS:
2276 case VIDIOC_TRY_EXT_CTRLS: {
2277 struct v4l2_ext_controls *ctrls = parg;
2278
2279 if (ctrls->count != 0) {
2280 *user_ptr = (void __user *)ctrls->controls;
2281 *kernel_ptr = (void **)&ctrls->controls;
2282 *array_size = sizeof(struct v4l2_ext_control)
2283 * ctrls->count;
2284 ret = 1;
2285 }
2286 break;
2287 }
2288 }
2289
2290 return ret;
2291}
2292
2293long
2294video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
2295 v4l2_kioctl func)
2003{ 2296{
2004 char sbuf[128]; 2297 char sbuf[128];
2005 void *mbuf = NULL; 2298 void *mbuf = NULL;
2006 void *parg = (void *)arg; 2299 void *parg = (void *)arg;
2007 long err = -EINVAL; 2300 long err = -EINVAL;
2008 int is_ext_ctrl; 2301 bool has_array_args;
2009 size_t ctrls_size = 0; 2302 size_t array_size = 0;
2010 void __user *user_ptr = NULL; 2303 void __user *user_ptr = NULL;
2011 2304 void **kernel_ptr = NULL;
2012#ifdef __OLD_VIDIOC_
2013 cmd = video_fix_command(cmd);
2014#endif
2015 is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
2016 cmd == VIDIOC_TRY_EXT_CTRLS);
2017 2305
2018 /* Copy arguments into temp kernel buffer */ 2306 /* Copy arguments into temp kernel buffer */
2019 if (_IOC_DIR(cmd) != _IOC_NONE) { 2307 if (_IOC_DIR(cmd) != _IOC_NONE) {
@@ -2043,43 +2331,43 @@ long video_ioctl2(struct file *file,
2043 } 2331 }
2044 } 2332 }
2045 2333
2046 if (is_ext_ctrl) { 2334 err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr);
2047 struct v4l2_ext_controls *p = parg; 2335 if (err < 0)
2336 goto out;
2337 has_array_args = err;
2048 2338
2049 /* In case of an error, tell the caller that it wasn't 2339 if (has_array_args) {
2050 a specific control that caused it. */ 2340 /*
2051 p->error_idx = p->count; 2341 * When adding new types of array args, make sure that the
2052 user_ptr = (void __user *)p->controls; 2342 * parent argument to ioctl (which contains the pointer to the
2053 if (p->count) { 2343 * array) fits into sbuf (so that mbuf will still remain
2054 ctrls_size = sizeof(struct v4l2_ext_control) * p->count; 2344 * unused up to here).
2055 /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */ 2345 */
2056 mbuf = kmalloc(ctrls_size, GFP_KERNEL); 2346 mbuf = kmalloc(array_size, GFP_KERNEL);
2057 err = -ENOMEM; 2347 err = -ENOMEM;
2058 if (NULL == mbuf) 2348 if (NULL == mbuf)
2059 goto out_ext_ctrl; 2349 goto out_array_args;
2060 err = -EFAULT; 2350 err = -EFAULT;
2061 if (copy_from_user(mbuf, user_ptr, ctrls_size)) 2351 if (copy_from_user(mbuf, user_ptr, array_size))
2062 goto out_ext_ctrl; 2352 goto out_array_args;
2063 p->controls = mbuf; 2353 *kernel_ptr = mbuf;
2064 }
2065 } 2354 }
2066 2355
2067 /* Handles IOCTL */ 2356 /* Handles IOCTL */
2068 err = __video_do_ioctl(file, cmd, parg); 2357 err = func(file, cmd, parg);
2069 if (err == -ENOIOCTLCMD) 2358 if (err == -ENOIOCTLCMD)
2070 err = -EINVAL; 2359 err = -EINVAL;
2071 if (is_ext_ctrl) {
2072 struct v4l2_ext_controls *p = parg;
2073 2360
2074 p->controls = (void *)user_ptr; 2361 if (has_array_args) {
2075 if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size)) 2362 *kernel_ptr = user_ptr;
2363 if (copy_to_user(user_ptr, mbuf, array_size))
2076 err = -EFAULT; 2364 err = -EFAULT;
2077 goto out_ext_ctrl; 2365 goto out_array_args;
2078 } 2366 }
2079 if (err < 0) 2367 if (err < 0)
2080 goto out; 2368 goto out;
2081 2369
2082out_ext_ctrl: 2370out_array_args:
2083 /* Copy results into user buffer */ 2371 /* Copy results into user buffer */
2084 switch (_IOC_DIR(cmd)) { 2372 switch (_IOC_DIR(cmd)) {
2085 case _IOC_READ: 2373 case _IOC_READ:
@@ -2093,4 +2381,11 @@ out:
2093 kfree(mbuf); 2381 kfree(mbuf);
2094 return err; 2382 return err;
2095} 2383}
2384EXPORT_SYMBOL(video_usercopy);
2385
2386long video_ioctl2(struct file *file,
2387 unsigned int cmd, unsigned long arg)
2388{
2389 return video_usercopy(file, cmd, arg, __video_do_ioctl);
2390}
2096EXPORT_SYMBOL(video_ioctl2); 2391EXPORT_SYMBOL(video_ioctl2);