diff options
Diffstat (limited to 'drivers/media/video/videodev.c')
-rw-r--r-- | drivers/media/video/videodev.c | 173 |
1 files changed, 113 insertions, 60 deletions
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 41ec0c4b35a2..6a0e8ca72948 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c | |||
@@ -342,7 +342,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd, | |||
342 | 342 | ||
343 | dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " | 343 | dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, " |
344 | "bytesused=%d, flags=0x%08d, " | 344 | "bytesused=%d, flags=0x%08d, " |
345 | "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n", | 345 | "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n", |
346 | (p->timestamp.tv_sec/3600), | 346 | (p->timestamp.tv_sec/3600), |
347 | (int)(p->timestamp.tv_sec/60)%60, | 347 | (int)(p->timestamp.tv_sec/60)%60, |
348 | (int)(p->timestamp.tv_sec%60), | 348 | (int)(p->timestamp.tv_sec%60), |
@@ -352,7 +352,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd, | |||
352 | p->bytesused,p->flags, | 352 | p->bytesused,p->flags, |
353 | p->field,p->sequence, | 353 | p->field,p->sequence, |
354 | prt_names(p->memory,v4l2_memory_names), | 354 | prt_names(p->memory,v4l2_memory_names), |
355 | p->m.userptr); | 355 | p->m.userptr, p->length); |
356 | dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " | 356 | dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " |
357 | "flags=0x%08d, frames=%d, userbits=0x%08x\n", | 357 | "flags=0x%08d, frames=%d, userbits=0x%08x\n", |
358 | tc->hours,tc->minutes,tc->seconds, | 358 | tc->hours,tc->minutes,tc->seconds, |
@@ -369,9 +369,13 @@ static inline void dbgrect(struct video_device *vfd, char *s, | |||
369 | static inline void v4l_print_pix_fmt (struct video_device *vfd, | 369 | static inline void v4l_print_pix_fmt (struct video_device *vfd, |
370 | struct v4l2_pix_format *fmt) | 370 | struct v4l2_pix_format *fmt) |
371 | { | 371 | { |
372 | dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, " | 372 | dbgarg2 ("width=%d, height=%d, format=%c%c%c%c, field=%s, " |
373 | "bytesperline=%d sizeimage=%d, colorspace=%d\n", | 373 | "bytesperline=%d sizeimage=%d, colorspace=%d\n", |
374 | fmt->width,fmt->height,fmt->pixelformat, | 374 | fmt->width,fmt->height, |
375 | (fmt->pixelformat & 0xff), | ||
376 | (fmt->pixelformat >> 8) & 0xff, | ||
377 | (fmt->pixelformat >> 16) & 0xff, | ||
378 | (fmt->pixelformat >> 24) & 0xff, | ||
375 | prt_names(fmt->field,v4l2_field_names_FIXME), | 379 | prt_names(fmt->field,v4l2_field_names_FIXME), |
376 | fmt->bytesperline,fmt->sizeimage,fmt->colorspace); | 380 | fmt->bytesperline,fmt->sizeimage,fmt->colorspace); |
377 | }; | 381 | }; |
@@ -428,6 +432,10 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
428 | v4l_print_ioctl(vfd->name, cmd); | 432 | v4l_print_ioctl(vfd->name, cmd); |
429 | } | 433 | } |
430 | 434 | ||
435 | if (_IOC_TYPE(cmd)=='v') | ||
436 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, | ||
437 | __video_do_ioctl); | ||
438 | |||
431 | switch(cmd) { | 439 | switch(cmd) { |
432 | /* --- capabilities ------------------------------------------ */ | 440 | /* --- capabilities ------------------------------------------ */ |
433 | case VIDIOC_QUERYCAP: | 441 | case VIDIOC_QUERYCAP: |
@@ -526,12 +534,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
526 | } | 534 | } |
527 | if (!ret) | 535 | if (!ret) |
528 | dbgarg (cmd, "index=%d, type=%d, flags=%d, " | 536 | dbgarg (cmd, "index=%d, type=%d, flags=%d, " |
529 | "description=%s," | 537 | "pixelformat=%c%c%c%c, description='%s'\n", |
530 | " pixelformat=0x%8x\n", | ||
531 | f->index, f->type, f->flags, | 538 | f->index, f->type, f->flags, |
532 | f->description, | 539 | (f->pixelformat & 0xff), |
533 | f->pixelformat); | 540 | (f->pixelformat >> 8) & 0xff, |
534 | 541 | (f->pixelformat >> 16) & 0xff, | |
542 | (f->pixelformat >> 24) & 0xff, | ||
543 | f->description); | ||
535 | break; | 544 | break; |
536 | } | 545 | } |
537 | case VIDIOC_G_FMT: | 546 | case VIDIOC_G_FMT: |
@@ -829,20 +838,85 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
829 | case VIDIOC_ENUMSTD: | 838 | case VIDIOC_ENUMSTD: |
830 | { | 839 | { |
831 | struct v4l2_standard *p = arg; | 840 | struct v4l2_standard *p = arg; |
832 | unsigned int index = p->index; | 841 | v4l2_std_id id = vfd->tvnorms,curr_id=0; |
842 | unsigned int index = p->index,i; | ||
833 | 843 | ||
834 | if (!vfd->tvnormsize) { | 844 | if (index<0) { |
835 | printk (KERN_WARNING "%s: no TV norms defined!\n", | 845 | ret=-EINVAL; |
836 | vfd->name); | ||
837 | break; | 846 | break; |
838 | } | 847 | } |
839 | 848 | ||
840 | if (index<0 || index >= vfd->tvnormsize) { | 849 | /* Return norm array on a canonical way */ |
841 | ret=-EINVAL; | 850 | for (i=0;i<= index && id; i++) { |
842 | break; | 851 | if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) { |
852 | curr_id = V4L2_STD_PAL; | ||
853 | } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) { | ||
854 | curr_id = V4L2_STD_PAL_BG; | ||
855 | } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) { | ||
856 | curr_id = V4L2_STD_PAL_DK; | ||
857 | } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) { | ||
858 | curr_id = V4L2_STD_PAL_B; | ||
859 | } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) { | ||
860 | curr_id = V4L2_STD_PAL_B1; | ||
861 | } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) { | ||
862 | curr_id = V4L2_STD_PAL_G; | ||
863 | } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) { | ||
864 | curr_id = V4L2_STD_PAL_H; | ||
865 | } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) { | ||
866 | curr_id = V4L2_STD_PAL_I; | ||
867 | } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) { | ||
868 | curr_id = V4L2_STD_PAL_D; | ||
869 | } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) { | ||
870 | curr_id = V4L2_STD_PAL_D1; | ||
871 | } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) { | ||
872 | curr_id = V4L2_STD_PAL_K; | ||
873 | } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) { | ||
874 | curr_id = V4L2_STD_PAL_M; | ||
875 | } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) { | ||
876 | curr_id = V4L2_STD_PAL_N; | ||
877 | } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) { | ||
878 | curr_id = V4L2_STD_PAL_Nc; | ||
879 | } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) { | ||
880 | curr_id = V4L2_STD_PAL_60; | ||
881 | } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) { | ||
882 | curr_id = V4L2_STD_NTSC; | ||
883 | } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) { | ||
884 | curr_id = V4L2_STD_NTSC_M; | ||
885 | } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) { | ||
886 | curr_id = V4L2_STD_NTSC_M_JP; | ||
887 | } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) { | ||
888 | curr_id = V4L2_STD_NTSC_443; | ||
889 | } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) { | ||
890 | curr_id = V4L2_STD_NTSC_M_KR; | ||
891 | } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) { | ||
892 | curr_id = V4L2_STD_SECAM; | ||
893 | } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) { | ||
894 | curr_id = V4L2_STD_SECAM_DK; | ||
895 | } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) { | ||
896 | curr_id = V4L2_STD_SECAM_B; | ||
897 | } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) { | ||
898 | curr_id = V4L2_STD_SECAM_D; | ||
899 | } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) { | ||
900 | curr_id = V4L2_STD_SECAM_G; | ||
901 | } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) { | ||
902 | curr_id = V4L2_STD_SECAM_H; | ||
903 | } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) { | ||
904 | curr_id = V4L2_STD_SECAM_K; | ||
905 | } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) { | ||
906 | curr_id = V4L2_STD_SECAM_K1; | ||
907 | } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) { | ||
908 | curr_id = V4L2_STD_SECAM_L; | ||
909 | } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) { | ||
910 | curr_id = V4L2_STD_SECAM_LC; | ||
911 | } else { | ||
912 | break; | ||
913 | } | ||
914 | id &= ~curr_id; | ||
843 | } | 915 | } |
844 | v4l2_video_std_construct(p, vfd->tvnorms[p->index].id, | 916 | if (i<=index) |
845 | vfd->tvnorms[p->index].name); | 917 | return -EINVAL; |
918 | |||
919 | v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id)); | ||
846 | p->index = index; | 920 | p->index = index; |
847 | 921 | ||
848 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " | 922 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " |
@@ -868,39 +942,23 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
868 | } | 942 | } |
869 | case VIDIOC_S_STD: | 943 | case VIDIOC_S_STD: |
870 | { | 944 | { |
871 | v4l2_std_id *id = arg; | 945 | v4l2_std_id *id = arg,norm; |
872 | unsigned int i; | ||
873 | |||
874 | if (!vfd->tvnormsize) { | ||
875 | printk (KERN_WARNING "%s: no TV norms defined!\n", | ||
876 | vfd->name); | ||
877 | break; | ||
878 | } | ||
879 | 946 | ||
880 | dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); | 947 | dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); |
881 | 948 | ||
882 | /* First search for exact match */ | 949 | norm = (*id) & vfd->tvnorms; |
883 | for (i = 0; i < vfd->tvnormsize; i++) | 950 | if ( vfd->tvnorms && !norm) /* Check if std is supported */ |
884 | if (*id == vfd->tvnorms[i].id) | ||
885 | break; | ||
886 | /* Then for a generic video std that contains desired std */ | ||
887 | if (i == vfd->tvnormsize) | ||
888 | for (i = 0; i < vfd->tvnormsize; i++) | ||
889 | if (*id & vfd->tvnorms[i].id) | ||
890 | break; | ||
891 | if (i == vfd->tvnormsize) { | ||
892 | break; | 951 | break; |
893 | } | ||
894 | 952 | ||
895 | /* Calls the specific handler */ | 953 | /* Calls the specific handler */ |
896 | if (vfd->vidioc_s_std) | 954 | if (vfd->vidioc_s_std) |
897 | ret=vfd->vidioc_s_std(file, fh, i); | 955 | ret=vfd->vidioc_s_std(file, fh, &norm); |
898 | else | 956 | else |
899 | ret=-EINVAL; | 957 | ret=-EINVAL; |
900 | 958 | ||
901 | /* Updates standard information */ | 959 | /* Updates standard information */ |
902 | if (!ret) | 960 | if (ret>=0) |
903 | vfd->current_norm=*id; | 961 | vfd->current_norm=norm; |
904 | 962 | ||
905 | break; | 963 | break; |
906 | } | 964 | } |
@@ -1088,9 +1146,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1088 | case VIDIOC_G_AUDIO: | 1146 | case VIDIOC_G_AUDIO: |
1089 | { | 1147 | { |
1090 | struct v4l2_audio *p=arg; | 1148 | struct v4l2_audio *p=arg; |
1149 | __u32 index=p->index; | ||
1091 | 1150 | ||
1092 | if (!vfd->vidioc_g_audio) | 1151 | if (!vfd->vidioc_g_audio) |
1093 | break; | 1152 | break; |
1153 | |||
1154 | memset(p,0,sizeof(*p)); | ||
1155 | p->index=index; | ||
1094 | dbgarg(cmd, "Get for index=%d\n", p->index); | 1156 | dbgarg(cmd, "Get for index=%d\n", p->index); |
1095 | ret=vfd->vidioc_g_audio(file, fh, p); | 1157 | ret=vfd->vidioc_g_audio(file, fh, p); |
1096 | if (!ret) | 1158 | if (!ret) |
@@ -1288,25 +1350,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1288 | ret=vfd->vidioc_g_parm(file, fh, p); | 1350 | ret=vfd->vidioc_g_parm(file, fh, p); |
1289 | } else { | 1351 | } else { |
1290 | struct v4l2_standard s; | 1352 | struct v4l2_standard s; |
1291 | int i; | ||
1292 | |||
1293 | if (!vfd->tvnormsize) { | ||
1294 | printk (KERN_WARNING "%s: no TV norms defined!\n", | ||
1295 | vfd->name); | ||
1296 | break; | ||
1297 | } | ||
1298 | 1353 | ||
1299 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1354 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1300 | return -EINVAL; | 1355 | return -EINVAL; |
1301 | 1356 | ||
1302 | for (i = 0; i < vfd->tvnormsize; i++) | ||
1303 | if (vfd->tvnorms[i].id == vfd->current_norm) | ||
1304 | break; | ||
1305 | if (i >= vfd->tvnormsize) | ||
1306 | return -EINVAL; | ||
1307 | |||
1308 | v4l2_video_std_construct(&s, vfd->current_norm, | 1357 | v4l2_video_std_construct(&s, vfd->current_norm, |
1309 | vfd->tvnorms[i].name); | 1358 | v4l2_norm_to_name(vfd->current_norm)); |
1310 | 1359 | ||
1311 | memset(p,0,sizeof(*p)); | 1360 | memset(p,0,sizeof(*p)); |
1312 | 1361 | ||
@@ -1329,8 +1378,14 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1329 | case VIDIOC_G_TUNER: | 1378 | case VIDIOC_G_TUNER: |
1330 | { | 1379 | { |
1331 | struct v4l2_tuner *p=arg; | 1380 | struct v4l2_tuner *p=arg; |
1381 | __u32 index=p->index; | ||
1382 | |||
1332 | if (!vfd->vidioc_g_tuner) | 1383 | if (!vfd->vidioc_g_tuner) |
1333 | break; | 1384 | break; |
1385 | |||
1386 | memset(p,0,sizeof(*p)); | ||
1387 | p->index=index; | ||
1388 | |||
1334 | ret=vfd->vidioc_g_tuner(file, fh, p); | 1389 | ret=vfd->vidioc_g_tuner(file, fh, p); |
1335 | if (!ret) | 1390 | if (!ret) |
1336 | dbgarg (cmd, "index=%d, name=%s, type=%d, " | 1391 | dbgarg (cmd, "index=%d, name=%s, type=%d, " |
@@ -1363,6 +1418,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1363 | struct v4l2_frequency *p=arg; | 1418 | struct v4l2_frequency *p=arg; |
1364 | if (!vfd->vidioc_g_frequency) | 1419 | if (!vfd->vidioc_g_frequency) |
1365 | break; | 1420 | break; |
1421 | |||
1422 | memset(p,0,sizeof(*p)); | ||
1423 | |||
1366 | ret=vfd->vidioc_g_frequency(file, fh, p); | 1424 | ret=vfd->vidioc_g_frequency(file, fh, p); |
1367 | if (!ret) | 1425 | if (!ret) |
1368 | dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", | 1426 | dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", |
@@ -1396,12 +1454,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1396 | ret=vfd->vidioc_log_status(file, fh); | 1454 | ret=vfd->vidioc_log_status(file, fh); |
1397 | break; | 1455 | break; |
1398 | } | 1456 | } |
1399 | 1457 | } /* switch */ | |
1400 | /* --- Others --------------------------------------------- */ | ||
1401 | |||
1402 | default: | ||
1403 | ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl); | ||
1404 | } | ||
1405 | 1458 | ||
1406 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { | 1459 | if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { |
1407 | if (ret<0) { | 1460 | if (ret<0) { |