diff options
Diffstat (limited to 'drivers/media/video/videodev.c')
-rw-r--r-- | drivers/media/video/videodev.c | 126 |
1 files changed, 81 insertions, 45 deletions
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index ad42deebdc47..1be712757e4d 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c | |||
@@ -833,20 +833,85 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
833 | case VIDIOC_ENUMSTD: | 833 | case VIDIOC_ENUMSTD: |
834 | { | 834 | { |
835 | struct v4l2_standard *p = arg; | 835 | struct v4l2_standard *p = arg; |
836 | unsigned int index = p->index; | 836 | v4l2_std_id id = vfd->tvnorms,curr_id=0; |
837 | unsigned int index = p->index,i; | ||
837 | 838 | ||
838 | if (!vfd->tvnormsize) { | 839 | if (index<0) { |
839 | printk (KERN_WARNING "%s: no TV norms defined!\n", | 840 | ret=-EINVAL; |
840 | vfd->name); | ||
841 | break; | 841 | break; |
842 | } | 842 | } |
843 | 843 | ||
844 | if (index<0 || index >= vfd->tvnormsize) { | 844 | /* Return norm array on a canonical way */ |
845 | ret=-EINVAL; | 845 | for (i=0;i<= index && id; i++) { |
846 | break; | 846 | if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) { |
847 | curr_id = V4L2_STD_PAL; | ||
848 | } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) { | ||
849 | curr_id = V4L2_STD_PAL_BG; | ||
850 | } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) { | ||
851 | curr_id = V4L2_STD_PAL_DK; | ||
852 | } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) { | ||
853 | curr_id = V4L2_STD_PAL_B; | ||
854 | } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) { | ||
855 | curr_id = V4L2_STD_PAL_B1; | ||
856 | } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) { | ||
857 | curr_id = V4L2_STD_PAL_G; | ||
858 | } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) { | ||
859 | curr_id = V4L2_STD_PAL_H; | ||
860 | } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) { | ||
861 | curr_id = V4L2_STD_PAL_I; | ||
862 | } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) { | ||
863 | curr_id = V4L2_STD_PAL_D; | ||
864 | } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) { | ||
865 | curr_id = V4L2_STD_PAL_D1; | ||
866 | } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) { | ||
867 | curr_id = V4L2_STD_PAL_K; | ||
868 | } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) { | ||
869 | curr_id = V4L2_STD_PAL_M; | ||
870 | } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) { | ||
871 | curr_id = V4L2_STD_PAL_N; | ||
872 | } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) { | ||
873 | curr_id = V4L2_STD_PAL_Nc; | ||
874 | } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) { | ||
875 | curr_id = V4L2_STD_PAL_60; | ||
876 | } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) { | ||
877 | curr_id = V4L2_STD_NTSC; | ||
878 | } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) { | ||
879 | curr_id = V4L2_STD_NTSC_M; | ||
880 | } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) { | ||
881 | curr_id = V4L2_STD_NTSC_M_JP; | ||
882 | } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) { | ||
883 | curr_id = V4L2_STD_NTSC_443; | ||
884 | } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) { | ||
885 | curr_id = V4L2_STD_NTSC_M_KR; | ||
886 | } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) { | ||
887 | curr_id = V4L2_STD_SECAM; | ||
888 | } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) { | ||
889 | curr_id = V4L2_STD_SECAM_DK; | ||
890 | } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) { | ||
891 | curr_id = V4L2_STD_SECAM_B; | ||
892 | } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) { | ||
893 | curr_id = V4L2_STD_SECAM_D; | ||
894 | } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) { | ||
895 | curr_id = V4L2_STD_SECAM_G; | ||
896 | } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) { | ||
897 | curr_id = V4L2_STD_SECAM_H; | ||
898 | } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) { | ||
899 | curr_id = V4L2_STD_SECAM_K; | ||
900 | } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) { | ||
901 | curr_id = V4L2_STD_SECAM_K1; | ||
902 | } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) { | ||
903 | curr_id = V4L2_STD_SECAM_L; | ||
904 | } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) { | ||
905 | curr_id = V4L2_STD_SECAM_LC; | ||
906 | } else { | ||
907 | break; | ||
908 | } | ||
909 | id &= ~curr_id; | ||
847 | } | 910 | } |
848 | v4l2_video_std_construct(p, vfd->tvnorms[p->index].id, | 911 | if (i<=index) |
849 | vfd->tvnorms[p->index].name); | 912 | return -EINVAL; |
913 | |||
914 | v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id)); | ||
850 | p->index = index; | 915 | p->index = index; |
851 | 916 | ||
852 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " | 917 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " |
@@ -872,39 +937,23 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
872 | } | 937 | } |
873 | case VIDIOC_S_STD: | 938 | case VIDIOC_S_STD: |
874 | { | 939 | { |
875 | v4l2_std_id *id = arg; | 940 | v4l2_std_id *id = arg,norm; |
876 | unsigned int i; | ||
877 | |||
878 | if (!vfd->tvnormsize) { | ||
879 | printk (KERN_WARNING "%s: no TV norms defined!\n", | ||
880 | vfd->name); | ||
881 | break; | ||
882 | } | ||
883 | 941 | ||
884 | dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); | 942 | dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); |
885 | 943 | ||
886 | /* First search for exact match */ | 944 | norm = (*id) & vfd->tvnorms; |
887 | for (i = 0; i < vfd->tvnormsize; i++) | 945 | if ( vfd->tvnorms && !norm) /* Check if std is supported */ |
888 | if (*id == vfd->tvnorms[i].id) | ||
889 | break; | ||
890 | /* Then for a generic video std that contains desired std */ | ||
891 | if (i == vfd->tvnormsize) | ||
892 | for (i = 0; i < vfd->tvnormsize; i++) | ||
893 | if (*id & vfd->tvnorms[i].id) | ||
894 | break; | ||
895 | if (i == vfd->tvnormsize) { | ||
896 | break; | 946 | break; |
897 | } | ||
898 | 947 | ||
899 | /* Calls the specific handler */ | 948 | /* Calls the specific handler */ |
900 | if (vfd->vidioc_s_std) | 949 | if (vfd->vidioc_s_std) |
901 | ret=vfd->vidioc_s_std(file, fh, i); | 950 | ret=vfd->vidioc_s_std(file, fh, &norm); |
902 | else | 951 | else |
903 | ret=-EINVAL; | 952 | ret=-EINVAL; |
904 | 953 | ||
905 | /* Updates standard information */ | 954 | /* Updates standard information */ |
906 | if (!ret) | 955 | if (ret>=0) |
907 | vfd->current_norm=*id; | 956 | vfd->current_norm=norm; |
908 | 957 | ||
909 | break; | 958 | break; |
910 | } | 959 | } |
@@ -1296,25 +1345,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1296 | ret=vfd->vidioc_g_parm(file, fh, p); | 1345 | ret=vfd->vidioc_g_parm(file, fh, p); |
1297 | } else { | 1346 | } else { |
1298 | struct v4l2_standard s; | 1347 | struct v4l2_standard s; |
1299 | int i; | ||
1300 | |||
1301 | if (!vfd->tvnormsize) { | ||
1302 | printk (KERN_WARNING "%s: no TV norms defined!\n", | ||
1303 | vfd->name); | ||
1304 | break; | ||
1305 | } | ||
1306 | 1348 | ||
1307 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1349 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1308 | return -EINVAL; | 1350 | return -EINVAL; |
1309 | 1351 | ||
1310 | for (i = 0; i < vfd->tvnormsize; i++) | ||
1311 | if (vfd->tvnorms[i].id == vfd->current_norm) | ||
1312 | break; | ||
1313 | if (i >= vfd->tvnormsize) | ||
1314 | return -EINVAL; | ||
1315 | |||
1316 | v4l2_video_std_construct(&s, vfd->current_norm, | 1352 | v4l2_video_std_construct(&s, vfd->current_norm, |
1317 | vfd->tvnorms[i].name); | 1353 | v4l2_norm_to_name(vfd->current_norm)); |
1318 | 1354 | ||
1319 | memset(p,0,sizeof(*p)); | 1355 | memset(p,0,sizeof(*p)); |
1320 | 1356 | ||