aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawel Osciak <p.osciak@samsung.com>2010-12-23 02:15:27 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-21 19:31:33 -0400
commitd14e6d76ebf740fd0d0bd296933993a555938896 (patch)
treed6b922de6d8849e379eea61f7d56bc67ed645126
parentf8f3914cf922f5f9e1d60e9e10f6fb92742907ad (diff)
[media] v4l: Add multi-planar ioctl handling code
Add multi-planar API core ioctl handling and conversion functions. [mchehab@redhat.com: CondingStyle fixup] Signed-off-by: Pawel Osciak <p.osciak@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Marek Szyprowski <m.szyprowski@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>
-rw-r--r--drivers/media/video/v4l2-ioctl.c453
-rw-r--r--include/media/v4l2-ioctl.h16
2 files changed, 425 insertions, 44 deletions
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 1a9d90ab666b..8360ed2d933a 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -428,20 +428,33 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
428 struct v4l2_buffer *p) 428 struct v4l2_buffer *p)
429{ 429{
430 struct v4l2_timecode *tc = &p->timecode; 430 struct v4l2_timecode *tc = &p->timecode;
431 struct v4l2_plane *plane;
432 int i;
431 433
432 dbgarg(cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " 434 dbgarg(cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
433 "bytesused=%d, flags=0x%08d, " 435 "flags=0x%08d, field=%0d, sequence=%d, memory=%s\n",
434 "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n",
435 p->timestamp.tv_sec / 3600, 436 p->timestamp.tv_sec / 3600,
436 (int)(p->timestamp.tv_sec / 60) % 60, 437 (int)(p->timestamp.tv_sec / 60) % 60,
437 (int)(p->timestamp.tv_sec % 60), 438 (int)(p->timestamp.tv_sec % 60),
438 (long)p->timestamp.tv_usec, 439 (long)p->timestamp.tv_usec,
439 p->index, 440 p->index,
440 prt_names(p->type, v4l2_type_names), 441 prt_names(p->type, v4l2_type_names),
441 p->bytesused, p->flags, 442 p->flags, p->field, p->sequence,
442 p->field, p->sequence, 443 prt_names(p->memory, v4l2_memory_names));
443 prt_names(p->memory, v4l2_memory_names), 444
444 p->m.userptr, p->length); 445 if (V4L2_TYPE_IS_MULTIPLANAR(p->type) && p->m.planes) {
446 for (i = 0; i < p->length; ++i) {
447 plane = &p->m.planes[i];
448 dbgarg2("plane %d: bytesused=%d, data_offset=0x%08x "
449 "offset/userptr=0x%08lx, length=%d\n",
450 i, plane->bytesused, plane->data_offset,
451 plane->m.userptr, plane->length);
452 }
453 } else {
454 dbgarg2("bytesused=%d, offset/userptr=0x%08lx, length=%d\n",
455 p->bytesused, p->m.userptr, p->length);
456 }
457
445 dbgarg2("timecode=%02d:%02d:%02d type=%d, " 458 dbgarg2("timecode=%02d:%02d:%02d type=%d, "
446 "flags=0x%08d, frames=%d, userbits=0x%08x\n", 459 "flags=0x%08d, frames=%d, userbits=0x%08x\n",
447 tc->hours, tc->minutes, tc->seconds, 460 tc->hours, tc->minutes, tc->seconds,
@@ -469,6 +482,27 @@ static inline void v4l_print_pix_fmt(struct video_device *vfd,
469 fmt->bytesperline, fmt->sizeimage, fmt->colorspace); 482 fmt->bytesperline, fmt->sizeimage, fmt->colorspace);
470}; 483};
471 484
485static inline void v4l_print_pix_fmt_mplane(struct video_device *vfd,
486 struct v4l2_pix_format_mplane *fmt)
487{
488 int i;
489
490 dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, "
491 "colorspace=%d, num_planes=%d\n",
492 fmt->width, fmt->height,
493 (fmt->pixelformat & 0xff),
494 (fmt->pixelformat >> 8) & 0xff,
495 (fmt->pixelformat >> 16) & 0xff,
496 (fmt->pixelformat >> 24) & 0xff,
497 prt_names(fmt->field, v4l2_field_names),
498 fmt->colorspace, fmt->num_planes);
499
500 for (i = 0; i < fmt->num_planes; ++i)
501 dbgarg2("plane %d: bytesperline=%d sizeimage=%d\n", i,
502 fmt->plane_fmt[i].bytesperline,
503 fmt->plane_fmt[i].sizeimage);
504}
505
472static inline void v4l_print_ext_ctrls(unsigned int cmd, 506static inline void v4l_print_ext_ctrls(unsigned int cmd,
473 struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals) 507 struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals)
474{ 508{
@@ -522,7 +556,12 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
522 556
523 switch (type) { 557 switch (type) {
524 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 558 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
525 if (ops->vidioc_g_fmt_vid_cap) 559 if (ops->vidioc_g_fmt_vid_cap ||
560 ops->vidioc_g_fmt_vid_cap_mplane)
561 return 0;
562 break;
563 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
564 if (ops->vidioc_g_fmt_vid_cap_mplane)
526 return 0; 565 return 0;
527 break; 566 break;
528 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 567 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
@@ -530,7 +569,12 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
530 return 0; 569 return 0;
531 break; 570 break;
532 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 571 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
533 if (ops->vidioc_g_fmt_vid_out) 572 if (ops->vidioc_g_fmt_vid_out ||
573 ops->vidioc_g_fmt_vid_out_mplane)
574 return 0;
575 break;
576 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
577 if (ops->vidioc_g_fmt_vid_out_mplane)
534 return 0; 578 return 0;
535 break; 579 break;
536 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 580 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
@@ -561,12 +605,70 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
561 return -EINVAL; 605 return -EINVAL;
562} 606}
563 607
608/**
609 * fmt_sp_to_mp() - Convert a single-plane format to its multi-planar 1-plane
610 * equivalent
611 */
612static int fmt_sp_to_mp(const struct v4l2_format *f_sp,
613 struct v4l2_format *f_mp)
614{
615 struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
616 const struct v4l2_pix_format *pix = &f_sp->fmt.pix;
617
618 if (f_sp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
619 f_mp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
620 else if (f_sp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
621 f_mp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
622 else
623 return -EINVAL;
624
625 pix_mp->width = pix->width;
626 pix_mp->height = pix->height;
627 pix_mp->pixelformat = pix->pixelformat;
628 pix_mp->field = pix->field;
629 pix_mp->colorspace = pix->colorspace;
630 pix_mp->num_planes = 1;
631 pix_mp->plane_fmt[0].sizeimage = pix->sizeimage;
632 pix_mp->plane_fmt[0].bytesperline = pix->bytesperline;
633
634 return 0;
635}
636
637/**
638 * fmt_mp_to_sp() - Convert a multi-planar 1-plane format to its single-planar
639 * equivalent
640 */
641static int fmt_mp_to_sp(const struct v4l2_format *f_mp,
642 struct v4l2_format *f_sp)
643{
644 const struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
645 struct v4l2_pix_format *pix = &f_sp->fmt.pix;
646
647 if (f_mp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
648 f_sp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
649 else if (f_mp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
650 f_sp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
651 else
652 return -EINVAL;
653
654 pix->width = pix_mp->width;
655 pix->height = pix_mp->height;
656 pix->pixelformat = pix_mp->pixelformat;
657 pix->field = pix_mp->field;
658 pix->colorspace = pix_mp->colorspace;
659 pix->sizeimage = pix_mp->plane_fmt[0].sizeimage;
660 pix->bytesperline = pix_mp->plane_fmt[0].bytesperline;
661
662 return 0;
663}
664
564static long __video_do_ioctl(struct file *file, 665static long __video_do_ioctl(struct file *file,
565 unsigned int cmd, void *arg) 666 unsigned int cmd, void *arg)
566{ 667{
567 struct video_device *vfd = video_devdata(file); 668 struct video_device *vfd = video_devdata(file);
568 const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; 669 const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
569 void *fh = file->private_data; 670 void *fh = file->private_data;
671 struct v4l2_format f_copy;
570 long ret = -EINVAL; 672 long ret = -EINVAL;
571 673
572 if (ops == NULL) { 674 if (ops == NULL) {
@@ -635,6 +737,11 @@ static long __video_do_ioctl(struct file *file,
635 if (ops->vidioc_enum_fmt_vid_cap) 737 if (ops->vidioc_enum_fmt_vid_cap)
636 ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f); 738 ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);
637 break; 739 break;
740 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
741 if (ops->vidioc_enum_fmt_vid_cap_mplane)
742 ret = ops->vidioc_enum_fmt_vid_cap_mplane(file,
743 fh, f);
744 break;
638 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 745 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
639 if (ops->vidioc_enum_fmt_vid_overlay) 746 if (ops->vidioc_enum_fmt_vid_overlay)
640 ret = ops->vidioc_enum_fmt_vid_overlay(file, 747 ret = ops->vidioc_enum_fmt_vid_overlay(file,
@@ -644,6 +751,11 @@ static long __video_do_ioctl(struct file *file,
644 if (ops->vidioc_enum_fmt_vid_out) 751 if (ops->vidioc_enum_fmt_vid_out)
645 ret = ops->vidioc_enum_fmt_vid_out(file, fh, f); 752 ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
646 break; 753 break;
754 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
755 if (ops->vidioc_enum_fmt_vid_out_mplane)
756 ret = ops->vidioc_enum_fmt_vid_out_mplane(file,
757 fh, f);
758 break;
647 case V4L2_BUF_TYPE_PRIVATE: 759 case V4L2_BUF_TYPE_PRIVATE:
648 if (ops->vidioc_enum_fmt_type_private) 760 if (ops->vidioc_enum_fmt_type_private)
649 ret = ops->vidioc_enum_fmt_type_private(file, 761 ret = ops->vidioc_enum_fmt_type_private(file,
@@ -672,22 +784,90 @@ static long __video_do_ioctl(struct file *file,
672 784
673 switch (f->type) { 785 switch (f->type) {
674 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 786 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
675 if (ops->vidioc_g_fmt_vid_cap) 787 if (ops->vidioc_g_fmt_vid_cap) {
676 ret = ops->vidioc_g_fmt_vid_cap(file, fh, f); 788 ret = ops->vidioc_g_fmt_vid_cap(file, fh, f);
789 } else if (ops->vidioc_g_fmt_vid_cap_mplane) {
790 if (fmt_sp_to_mp(f, &f_copy))
791 break;
792 ret = ops->vidioc_g_fmt_vid_cap_mplane(file, fh,
793 &f_copy);
794 if (ret)
795 break;
796
797 /* Driver is currently in multi-planar format,
798 * we can't return it in single-planar API*/
799 if (f_copy.fmt.pix_mp.num_planes > 1) {
800 ret = -EBUSY;
801 break;
802 }
803
804 ret = fmt_mp_to_sp(&f_copy, f);
805 }
677 if (!ret) 806 if (!ret)
678 v4l_print_pix_fmt(vfd, &f->fmt.pix); 807 v4l_print_pix_fmt(vfd, &f->fmt.pix);
679 break; 808 break;
809 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
810 if (ops->vidioc_g_fmt_vid_cap_mplane) {
811 ret = ops->vidioc_g_fmt_vid_cap_mplane(file,
812 fh, f);
813 } else if (ops->vidioc_g_fmt_vid_cap) {
814 if (fmt_mp_to_sp(f, &f_copy))
815 break;
816 ret = ops->vidioc_g_fmt_vid_cap(file,
817 fh, &f_copy);
818 if (ret)
819 break;
820
821 ret = fmt_sp_to_mp(&f_copy, f);
822 }
823 if (!ret)
824 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
825 break;
680 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 826 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
681 if (ops->vidioc_g_fmt_vid_overlay) 827 if (ops->vidioc_g_fmt_vid_overlay)
682 ret = ops->vidioc_g_fmt_vid_overlay(file, 828 ret = ops->vidioc_g_fmt_vid_overlay(file,
683 fh, f); 829 fh, f);
684 break; 830 break;
685 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 831 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
686 if (ops->vidioc_g_fmt_vid_out) 832 if (ops->vidioc_g_fmt_vid_out) {
687 ret = ops->vidioc_g_fmt_vid_out(file, fh, f); 833 ret = ops->vidioc_g_fmt_vid_out(file, fh, f);
834 } else if (ops->vidioc_g_fmt_vid_out_mplane) {
835 if (fmt_sp_to_mp(f, &f_copy))
836 break;
837 ret = ops->vidioc_g_fmt_vid_out_mplane(file, fh,
838 &f_copy);
839 if (ret)
840 break;
841
842 /* Driver is currently in multi-planar format,
843 * we can't return it in single-planar API*/
844 if (f_copy.fmt.pix_mp.num_planes > 1) {
845 ret = -EBUSY;
846 break;
847 }
848
849 ret = fmt_mp_to_sp(&f_copy, f);
850 }
688 if (!ret) 851 if (!ret)
689 v4l_print_pix_fmt(vfd, &f->fmt.pix); 852 v4l_print_pix_fmt(vfd, &f->fmt.pix);
690 break; 853 break;
854 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
855 if (ops->vidioc_g_fmt_vid_out_mplane) {
856 ret = ops->vidioc_g_fmt_vid_out_mplane(file,
857 fh, f);
858 } else if (ops->vidioc_g_fmt_vid_out) {
859 if (fmt_mp_to_sp(f, &f_copy))
860 break;
861 ret = ops->vidioc_g_fmt_vid_out(file,
862 fh, &f_copy);
863 if (ret)
864 break;
865
866 ret = fmt_sp_to_mp(&f_copy, f);
867 }
868 if (!ret)
869 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
870 break;
691 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 871 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
692 if (ops->vidioc_g_fmt_vid_out_overlay) 872 if (ops->vidioc_g_fmt_vid_out_overlay)
693 ret = ops->vidioc_g_fmt_vid_out_overlay(file, 873 ret = ops->vidioc_g_fmt_vid_out_overlay(file,
@@ -731,8 +911,44 @@ static long __video_do_ioctl(struct file *file,
731 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 911 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
732 CLEAR_AFTER_FIELD(f, fmt.pix); 912 CLEAR_AFTER_FIELD(f, fmt.pix);
733 v4l_print_pix_fmt(vfd, &f->fmt.pix); 913 v4l_print_pix_fmt(vfd, &f->fmt.pix);
734 if (ops->vidioc_s_fmt_vid_cap) 914 if (ops->vidioc_s_fmt_vid_cap) {
735 ret = ops->vidioc_s_fmt_vid_cap(file, fh, f); 915 ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
916 } else if (ops->vidioc_s_fmt_vid_cap_mplane) {
917 if (fmt_sp_to_mp(f, &f_copy))
918 break;
919 ret = ops->vidioc_s_fmt_vid_cap_mplane(file, fh,
920 &f_copy);
921 if (ret)
922 break;
923
924 if (f_copy.fmt.pix_mp.num_planes > 1) {
925 /* Drivers shouldn't adjust from 1-plane
926 * to more than 1-plane formats */
927 ret = -EBUSY;
928 WARN_ON(1);
929 break;
930 }
931
932 ret = fmt_mp_to_sp(&f_copy, f);
933 }
934 break;
935 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
936 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
937 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
938 if (ops->vidioc_s_fmt_vid_cap_mplane) {
939 ret = ops->vidioc_s_fmt_vid_cap_mplane(file,
940 fh, f);
941 } else if (ops->vidioc_s_fmt_vid_cap &&
942 f->fmt.pix_mp.num_planes == 1) {
943 if (fmt_mp_to_sp(f, &f_copy))
944 break;
945 ret = ops->vidioc_s_fmt_vid_cap(file,
946 fh, &f_copy);
947 if (ret)
948 break;
949
950 ret = fmt_sp_to_mp(&f_copy, f);
951 }
736 break; 952 break;
737 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 953 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
738 CLEAR_AFTER_FIELD(f, fmt.win); 954 CLEAR_AFTER_FIELD(f, fmt.win);
@@ -743,8 +959,44 @@ static long __video_do_ioctl(struct file *file,
743 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 959 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
744 CLEAR_AFTER_FIELD(f, fmt.pix); 960 CLEAR_AFTER_FIELD(f, fmt.pix);
745 v4l_print_pix_fmt(vfd, &f->fmt.pix); 961 v4l_print_pix_fmt(vfd, &f->fmt.pix);
746 if (ops->vidioc_s_fmt_vid_out) 962 if (ops->vidioc_s_fmt_vid_out) {
747 ret = ops->vidioc_s_fmt_vid_out(file, fh, f); 963 ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
964 } else if (ops->vidioc_s_fmt_vid_out_mplane) {
965 if (fmt_sp_to_mp(f, &f_copy))
966 break;
967 ret = ops->vidioc_s_fmt_vid_out_mplane(file, fh,
968 &f_copy);
969 if (ret)
970 break;
971
972 if (f_copy.fmt.pix_mp.num_planes > 1) {
973 /* Drivers shouldn't adjust from 1-plane
974 * to more than 1-plane formats */
975 ret = -EBUSY;
976 WARN_ON(1);
977 break;
978 }
979
980 ret = fmt_mp_to_sp(&f_copy, f);
981 }
982 break;
983 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
984 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
985 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
986 if (ops->vidioc_s_fmt_vid_out_mplane) {
987 ret = ops->vidioc_s_fmt_vid_out_mplane(file,
988 fh, f);
989 } else if (ops->vidioc_s_fmt_vid_out &&
990 f->fmt.pix_mp.num_planes == 1) {
991 if (fmt_mp_to_sp(f, &f_copy))
992 break;
993 ret = ops->vidioc_s_fmt_vid_out(file,
994 fh, &f_copy);
995 if (ret)
996 break;
997
998 ret = fmt_mp_to_sp(&f_copy, f);
999 }
748 break; 1000 break;
749 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 1001 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
750 CLEAR_AFTER_FIELD(f, fmt.win); 1002 CLEAR_AFTER_FIELD(f, fmt.win);
@@ -793,11 +1045,47 @@ static long __video_do_ioctl(struct file *file,
793 switch (f->type) { 1045 switch (f->type) {
794 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1046 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
795 CLEAR_AFTER_FIELD(f, fmt.pix); 1047 CLEAR_AFTER_FIELD(f, fmt.pix);
796 if (ops->vidioc_try_fmt_vid_cap) 1048 if (ops->vidioc_try_fmt_vid_cap) {
797 ret = ops->vidioc_try_fmt_vid_cap(file, fh, f); 1049 ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
1050 } else if (ops->vidioc_try_fmt_vid_cap_mplane) {
1051 if (fmt_sp_to_mp(f, &f_copy))
1052 break;
1053 ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
1054 fh, &f_copy);
1055 if (ret)
1056 break;
1057
1058 if (f_copy.fmt.pix_mp.num_planes > 1) {
1059 /* Drivers shouldn't adjust from 1-plane
1060 * to more than 1-plane formats */
1061 ret = -EBUSY;
1062 WARN_ON(1);
1063 break;
1064 }
1065 ret = fmt_mp_to_sp(&f_copy, f);
1066 }
798 if (!ret) 1067 if (!ret)
799 v4l_print_pix_fmt(vfd, &f->fmt.pix); 1068 v4l_print_pix_fmt(vfd, &f->fmt.pix);
800 break; 1069 break;
1070 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1071 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
1072 if (ops->vidioc_try_fmt_vid_cap_mplane) {
1073 ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
1074 fh, f);
1075 } else if (ops->vidioc_try_fmt_vid_cap &&
1076 f->fmt.pix_mp.num_planes == 1) {
1077 if (fmt_mp_to_sp(f, &f_copy))
1078 break;
1079 ret = ops->vidioc_try_fmt_vid_cap(file,
1080 fh, &f_copy);
1081 if (ret)
1082 break;
1083
1084 ret = fmt_sp_to_mp(&f_copy, f);
1085 }
1086 if (!ret)
1087 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
1088 break;
801 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 1089 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
802 CLEAR_AFTER_FIELD(f, fmt.win); 1090 CLEAR_AFTER_FIELD(f, fmt.win);
803 if (ops->vidioc_try_fmt_vid_overlay) 1091 if (ops->vidioc_try_fmt_vid_overlay)
@@ -806,11 +1094,47 @@ static long __video_do_ioctl(struct file *file,
806 break; 1094 break;
807 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 1095 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
808 CLEAR_AFTER_FIELD(f, fmt.pix); 1096 CLEAR_AFTER_FIELD(f, fmt.pix);
809 if (ops->vidioc_try_fmt_vid_out) 1097 if (ops->vidioc_try_fmt_vid_out) {
810 ret = ops->vidioc_try_fmt_vid_out(file, fh, f); 1098 ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
1099 } else if (ops->vidioc_try_fmt_vid_out_mplane) {
1100 if (fmt_sp_to_mp(f, &f_copy))
1101 break;
1102 ret = ops->vidioc_try_fmt_vid_out_mplane(file,
1103 fh, &f_copy);
1104 if (ret)
1105 break;
1106
1107 if (f_copy.fmt.pix_mp.num_planes > 1) {
1108 /* Drivers shouldn't adjust from 1-plane
1109 * to more than 1-plane formats */
1110 ret = -EBUSY;
1111 WARN_ON(1);
1112 break;
1113 }
1114 ret = fmt_mp_to_sp(&f_copy, f);
1115 }
811 if (!ret) 1116 if (!ret)
812 v4l_print_pix_fmt(vfd, &f->fmt.pix); 1117 v4l_print_pix_fmt(vfd, &f->fmt.pix);
813 break; 1118 break;
1119 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1120 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
1121 if (ops->vidioc_try_fmt_vid_out_mplane) {
1122 ret = ops->vidioc_try_fmt_vid_out_mplane(file,
1123 fh, f);
1124 } else if (ops->vidioc_try_fmt_vid_out &&
1125 f->fmt.pix_mp.num_planes == 1) {
1126 if (fmt_mp_to_sp(f, &f_copy))
1127 break;
1128 ret = ops->vidioc_try_fmt_vid_out(file,
1129 fh, &f_copy);
1130 if (ret)
1131 break;
1132
1133 ret = fmt_sp_to_mp(&f_copy, f);
1134 }
1135 if (!ret)
1136 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
1137 break;
814 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 1138 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
815 CLEAR_AFTER_FIELD(f, fmt.win); 1139 CLEAR_AFTER_FIELD(f, fmt.win);
816 if (ops->vidioc_try_fmt_vid_out_overlay) 1140 if (ops->vidioc_try_fmt_vid_out_overlay)
@@ -1975,7 +2299,7 @@ static unsigned long cmd_input_size(unsigned int cmd)
1975 switch (cmd) { 2299 switch (cmd) {
1976 CMDINSIZE(ENUM_FMT, fmtdesc, type); 2300 CMDINSIZE(ENUM_FMT, fmtdesc, type);
1977 CMDINSIZE(G_FMT, format, type); 2301 CMDINSIZE(G_FMT, format, type);
1978 CMDINSIZE(QUERYBUF, buffer, type); 2302 CMDINSIZE(QUERYBUF, buffer, length);
1979 CMDINSIZE(G_PARM, streamparm, type); 2303 CMDINSIZE(G_PARM, streamparm, type);
1980 CMDINSIZE(ENUMSTD, standard, index); 2304 CMDINSIZE(ENUMSTD, standard, index);
1981 CMDINSIZE(ENUMINPUT, input, index); 2305 CMDINSIZE(ENUMINPUT, input, index);
@@ -2000,6 +2324,49 @@ static unsigned long cmd_input_size(unsigned int cmd)
2000 } 2324 }
2001} 2325}
2002 2326
2327static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
2328 void * __user *user_ptr, void ***kernel_ptr)
2329{
2330 int ret = 0;
2331
2332 switch (cmd) {
2333 case VIDIOC_QUERYBUF:
2334 case VIDIOC_QBUF:
2335 case VIDIOC_DQBUF: {
2336 struct v4l2_buffer *buf = parg;
2337
2338 if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && buf->length > 0) {
2339 if (buf->length > VIDEO_MAX_PLANES) {
2340 ret = -EINVAL;
2341 break;
2342 }
2343 *user_ptr = (void __user *)buf->m.planes;
2344 *kernel_ptr = (void **)&buf->m.planes;
2345 *array_size = sizeof(struct v4l2_plane) * buf->length;
2346 ret = 1;
2347 }
2348 break;
2349 }
2350
2351 case VIDIOC_S_EXT_CTRLS:
2352 case VIDIOC_G_EXT_CTRLS:
2353 case VIDIOC_TRY_EXT_CTRLS: {
2354 struct v4l2_ext_controls *ctrls = parg;
2355
2356 if (ctrls->count != 0) {
2357 *user_ptr = (void __user *)ctrls->controls;
2358 *kernel_ptr = (void **)&ctrls->controls;
2359 *array_size = sizeof(struct v4l2_ext_control)
2360 * ctrls->count;
2361 ret = 1;
2362 }
2363 break;
2364 }
2365 }
2366
2367 return ret;
2368}
2369
2003long video_ioctl2(struct file *file, 2370long video_ioctl2(struct file *file,
2004 unsigned int cmd, unsigned long arg) 2371 unsigned int cmd, unsigned long arg)
2005{ 2372{
@@ -2007,16 +2374,14 @@ long video_ioctl2(struct file *file,
2007 void *mbuf = NULL; 2374 void *mbuf = NULL;
2008 void *parg = (void *)arg; 2375 void *parg = (void *)arg;
2009 long err = -EINVAL; 2376 long err = -EINVAL;
2010 int is_ext_ctrl; 2377 bool has_array_args;
2011 size_t ctrls_size = 0; 2378 size_t array_size = 0;
2012 void __user *user_ptr = NULL; 2379 void __user *user_ptr = NULL;
2380 void **kernel_ptr = NULL;
2013 2381
2014#ifdef __OLD_VIDIOC_ 2382#ifdef __OLD_VIDIOC_
2015 cmd = video_fix_command(cmd); 2383 cmd = video_fix_command(cmd);
2016#endif 2384#endif
2017 is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
2018 cmd == VIDIOC_TRY_EXT_CTRLS);
2019
2020 /* Copy arguments into temp kernel buffer */ 2385 /* Copy arguments into temp kernel buffer */
2021 if (_IOC_DIR(cmd) != _IOC_NONE) { 2386 if (_IOC_DIR(cmd) != _IOC_NONE) {
2022 if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { 2387 if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
@@ -2045,43 +2410,43 @@ long video_ioctl2(struct file *file,
2045 } 2410 }
2046 } 2411 }
2047 2412
2048 if (is_ext_ctrl) { 2413 err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr);
2049 struct v4l2_ext_controls *p = parg; 2414 if (err < 0)
2415 goto out;
2416 has_array_args = err;
2050 2417
2051 /* In case of an error, tell the caller that it wasn't 2418 if (has_array_args) {
2052 a specific control that caused it. */ 2419 /*
2053 p->error_idx = p->count; 2420 * When adding new types of array args, make sure that the
2054 user_ptr = (void __user *)p->controls; 2421 * parent argument to ioctl (which contains the pointer to the
2055 if (p->count) { 2422 * array) fits into sbuf (so that mbuf will still remain
2056 ctrls_size = sizeof(struct v4l2_ext_control) * p->count; 2423 * unused up to here).
2057 /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */ 2424 */
2058 mbuf = kmalloc(ctrls_size, GFP_KERNEL); 2425 mbuf = kmalloc(array_size, GFP_KERNEL);
2059 err = -ENOMEM; 2426 err = -ENOMEM;
2060 if (NULL == mbuf) 2427 if (NULL == mbuf)
2061 goto out_ext_ctrl; 2428 goto out_array_args;
2062 err = -EFAULT; 2429 err = -EFAULT;
2063 if (copy_from_user(mbuf, user_ptr, ctrls_size)) 2430 if (copy_from_user(mbuf, user_ptr, array_size))
2064 goto out_ext_ctrl; 2431 goto out_array_args;
2065 p->controls = mbuf; 2432 *kernel_ptr = mbuf;
2066 }
2067 } 2433 }
2068 2434
2069 /* Handles IOCTL */ 2435 /* Handles IOCTL */
2070 err = __video_do_ioctl(file, cmd, parg); 2436 err = __video_do_ioctl(file, cmd, parg);
2071 if (err == -ENOIOCTLCMD) 2437 if (err == -ENOIOCTLCMD)
2072 err = -EINVAL; 2438 err = -EINVAL;
2073 if (is_ext_ctrl) {
2074 struct v4l2_ext_controls *p = parg;
2075 2439
2076 p->controls = (void *)user_ptr; 2440 if (has_array_args) {
2077 if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size)) 2441 *kernel_ptr = user_ptr;
2442 if (copy_to_user(user_ptr, mbuf, array_size))
2078 err = -EFAULT; 2443 err = -EFAULT;
2079 goto out_ext_ctrl; 2444 goto out_array_args;
2080 } 2445 }
2081 if (err < 0) 2446 if (err < 0)
2082 goto out; 2447 goto out;
2083 2448
2084out_ext_ctrl: 2449out_array_args:
2085 /* Copy results into user buffer */ 2450 /* Copy results into user buffer */
2086 switch (_IOC_DIR(cmd)) { 2451 switch (_IOC_DIR(cmd)) {
2087 case _IOC_READ: 2452 case _IOC_READ:
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 67df37542c68..1572c7f25777 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -37,6 +37,10 @@ struct v4l2_ioctl_ops {
37 struct v4l2_fmtdesc *f); 37 struct v4l2_fmtdesc *f);
38 int (*vidioc_enum_fmt_vid_out) (struct file *file, void *fh, 38 int (*vidioc_enum_fmt_vid_out) (struct file *file, void *fh,
39 struct v4l2_fmtdesc *f); 39 struct v4l2_fmtdesc *f);
40 int (*vidioc_enum_fmt_vid_cap_mplane)(struct file *file, void *fh,
41 struct v4l2_fmtdesc *f);
42 int (*vidioc_enum_fmt_vid_out_mplane)(struct file *file, void *fh,
43 struct v4l2_fmtdesc *f);
40 int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh, 44 int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh,
41 struct v4l2_fmtdesc *f); 45 struct v4l2_fmtdesc *f);
42 46
@@ -57,6 +61,10 @@ struct v4l2_ioctl_ops {
57 struct v4l2_format *f); 61 struct v4l2_format *f);
58 int (*vidioc_g_fmt_sliced_vbi_out)(struct file *file, void *fh, 62 int (*vidioc_g_fmt_sliced_vbi_out)(struct file *file, void *fh,
59 struct v4l2_format *f); 63 struct v4l2_format *f);
64 int (*vidioc_g_fmt_vid_cap_mplane)(struct file *file, void *fh,
65 struct v4l2_format *f);
66 int (*vidioc_g_fmt_vid_out_mplane)(struct file *file, void *fh,
67 struct v4l2_format *f);
60 int (*vidioc_g_fmt_type_private)(struct file *file, void *fh, 68 int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,
61 struct v4l2_format *f); 69 struct v4l2_format *f);
62 70
@@ -77,6 +85,10 @@ struct v4l2_ioctl_ops {
77 struct v4l2_format *f); 85 struct v4l2_format *f);
78 int (*vidioc_s_fmt_sliced_vbi_out)(struct file *file, void *fh, 86 int (*vidioc_s_fmt_sliced_vbi_out)(struct file *file, void *fh,
79 struct v4l2_format *f); 87 struct v4l2_format *f);
88 int (*vidioc_s_fmt_vid_cap_mplane)(struct file *file, void *fh,
89 struct v4l2_format *f);
90 int (*vidioc_s_fmt_vid_out_mplane)(struct file *file, void *fh,
91 struct v4l2_format *f);
80 int (*vidioc_s_fmt_type_private)(struct file *file, void *fh, 92 int (*vidioc_s_fmt_type_private)(struct file *file, void *fh,
81 struct v4l2_format *f); 93 struct v4l2_format *f);
82 94
@@ -97,6 +109,10 @@ struct v4l2_ioctl_ops {
97 struct v4l2_format *f); 109 struct v4l2_format *f);
98 int (*vidioc_try_fmt_sliced_vbi_out)(struct file *file, void *fh, 110 int (*vidioc_try_fmt_sliced_vbi_out)(struct file *file, void *fh,
99 struct v4l2_format *f); 111 struct v4l2_format *f);
112 int (*vidioc_try_fmt_vid_cap_mplane)(struct file *file, void *fh,
113 struct v4l2_format *f);
114 int (*vidioc_try_fmt_vid_out_mplane)(struct file *file, void *fh,
115 struct v4l2_format *f);
100 int (*vidioc_try_fmt_type_private)(struct file *file, void *fh, 116 int (*vidioc_try_fmt_type_private)(struct file *file, void *fh,
101 struct v4l2_format *f); 117 struct v4l2_format *f);
102 118