diff options
Diffstat (limited to 'drivers/media/video/v4l2-ioctl.c')
-rw-r--r-- | drivers/media/video/v4l2-ioctl.c | 103 |
1 files changed, 81 insertions, 22 deletions
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 7d59c107f13b..0eeceae50329 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #endif | 26 | #endif |
27 | #include <media/v4l2-common.h> | 27 | #include <media/v4l2-common.h> |
28 | #include <media/v4l2-ioctl.h> | 28 | #include <media/v4l2-ioctl.h> |
29 | #include <media/v4l2-fh.h> | ||
30 | #include <media/v4l2-event.h> | ||
29 | #include <media/v4l2-chip-ident.h> | 31 | #include <media/v4l2-chip-ident.h> |
30 | 32 | ||
31 | #define dbgarg(cmd, fmt, arg...) \ | 33 | #define dbgarg(cmd, fmt, arg...) \ |
@@ -291,6 +293,9 @@ static const char *v4l2_ioctls[] = { | |||
291 | [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET", | 293 | [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET", |
292 | [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS", | 294 | [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS", |
293 | [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS", | 295 | [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS", |
296 | [_IOC_NR(VIDIOC_DQEVENT)] = "VIDIOC_DQEVENT", | ||
297 | [_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)] = "VIDIOC_SUBSCRIBE_EVENT", | ||
298 | [_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT", | ||
294 | }; | 299 | }; |
295 | #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) | 300 | #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) |
296 | 301 | ||
@@ -610,17 +615,33 @@ static long __video_do_ioctl(struct file *file, | |||
610 | void *fh = file->private_data; | 615 | void *fh = file->private_data; |
611 | long ret = -EINVAL; | 616 | long ret = -EINVAL; |
612 | 617 | ||
618 | if (ops == NULL) { | ||
619 | printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n", | ||
620 | vfd->name); | ||
621 | return -EINVAL; | ||
622 | } | ||
623 | |||
624 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
625 | /******************************************************** | ||
626 | All other V4L1 calls are handled by v4l1_compat module. | ||
627 | Those calls will be translated into V4L2 calls, and | ||
628 | __video_do_ioctl will be called again, with one or more | ||
629 | V4L2 ioctls. | ||
630 | ********************************************************/ | ||
631 | if (_IOC_TYPE(cmd) == 'v' && cmd != VIDIOCGMBUF && | ||
632 | _IOC_NR(cmd) < BASE_VIDIOCPRIVATE) { | ||
633 | return v4l_compat_translate_ioctl(file, cmd, arg, | ||
634 | __video_do_ioctl); | ||
635 | } | ||
636 | #endif | ||
637 | |||
613 | if ((vfd->debug & V4L2_DEBUG_IOCTL) && | 638 | if ((vfd->debug & V4L2_DEBUG_IOCTL) && |
614 | !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { | 639 | !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { |
615 | v4l_print_ioctl(vfd->name, cmd); | 640 | v4l_print_ioctl(vfd->name, cmd); |
616 | printk(KERN_CONT "\n"); | 641 | printk(KERN_CONT "\n"); |
617 | } | 642 | } |
618 | 643 | ||
619 | if (ops == NULL) { | 644 | switch (cmd) { |
620 | printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n", | ||
621 | vfd->name); | ||
622 | return -EINVAL; | ||
623 | } | ||
624 | 645 | ||
625 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 646 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
626 | /*********************************************************** | 647 | /*********************************************************** |
@@ -630,31 +651,21 @@ static long __video_do_ioctl(struct file *file, | |||
630 | ***********************************************************/ | 651 | ***********************************************************/ |
631 | 652 | ||
632 | /* --- streaming capture ------------------------------------- */ | 653 | /* --- streaming capture ------------------------------------- */ |
633 | if (cmd == VIDIOCGMBUF) { | 654 | case VIDIOCGMBUF: |
655 | { | ||
634 | struct video_mbuf *p = arg; | 656 | struct video_mbuf *p = arg; |
635 | 657 | ||
636 | if (!ops->vidiocgmbuf) | 658 | if (!ops->vidiocgmbuf) |
637 | return ret; | 659 | break; |
638 | ret = ops->vidiocgmbuf(file, fh, p); | 660 | ret = ops->vidiocgmbuf(file, fh, p); |
639 | if (!ret) | 661 | if (!ret) |
640 | dbgarg(cmd, "size=%d, frames=%d, offsets=0x%08lx\n", | 662 | dbgarg(cmd, "size=%d, frames=%d, offsets=0x%08lx\n", |
641 | p->size, p->frames, | 663 | p->size, p->frames, |
642 | (unsigned long)p->offsets); | 664 | (unsigned long)p->offsets); |
643 | return ret; | 665 | break; |
644 | } | 666 | } |
645 | |||
646 | /******************************************************** | ||
647 | All other V4L1 calls are handled by v4l1_compat module. | ||
648 | Those calls will be translated into V4L2 calls, and | ||
649 | __video_do_ioctl will be called again, with one or more | ||
650 | V4L2 ioctls. | ||
651 | ********************************************************/ | ||
652 | if (_IOC_TYPE(cmd) == 'v' && _IOC_NR(cmd) < BASE_VIDIOCPRIVATE) | ||
653 | return v4l_compat_translate_ioctl(file, cmd, arg, | ||
654 | __video_do_ioctl); | ||
655 | #endif | 667 | #endif |
656 | 668 | ||
657 | switch (cmd) { | ||
658 | /* --- capabilities ------------------------------------------ */ | 669 | /* --- capabilities ------------------------------------------ */ |
659 | case VIDIOC_QUERYCAP: | 670 | case VIDIOC_QUERYCAP: |
660 | { | 671 | { |
@@ -1072,7 +1083,7 @@ static long __video_do_ioctl(struct file *file, | |||
1072 | id &= ~curr_id; | 1083 | id &= ~curr_id; |
1073 | } | 1084 | } |
1074 | if (i <= index) | 1085 | if (i <= index) |
1075 | return -EINVAL; | 1086 | break; |
1076 | 1087 | ||
1077 | v4l2_video_std_construct(p, curr_id, descr); | 1088 | v4l2_video_std_construct(p, curr_id, descr); |
1078 | 1089 | ||
@@ -1597,7 +1608,7 @@ static long __video_do_ioctl(struct file *file, | |||
1597 | v4l2_std_id std = vfd->current_norm; | 1608 | v4l2_std_id std = vfd->current_norm; |
1598 | 1609 | ||
1599 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1610 | if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1600 | return -EINVAL; | 1611 | break; |
1601 | 1612 | ||
1602 | ret = 0; | 1613 | ret = 0; |
1603 | if (ops->vidioc_g_std) | 1614 | if (ops->vidioc_g_std) |
@@ -1942,7 +1953,55 @@ static long __video_do_ioctl(struct file *file, | |||
1942 | } | 1953 | } |
1943 | break; | 1954 | break; |
1944 | } | 1955 | } |
1956 | case VIDIOC_DQEVENT: | ||
1957 | { | ||
1958 | struct v4l2_event *ev = arg; | ||
1959 | |||
1960 | if (!ops->vidioc_subscribe_event) | ||
1961 | break; | ||
1945 | 1962 | ||
1963 | ret = v4l2_event_dequeue(fh, ev, file->f_flags & O_NONBLOCK); | ||
1964 | if (ret < 0) { | ||
1965 | dbgarg(cmd, "no pending events?"); | ||
1966 | break; | ||
1967 | } | ||
1968 | dbgarg(cmd, | ||
1969 | "pending=%d, type=0x%8.8x, sequence=%d, " | ||
1970 | "timestamp=%lu.%9.9lu ", | ||
1971 | ev->pending, ev->type, ev->sequence, | ||
1972 | ev->timestamp.tv_sec, ev->timestamp.tv_nsec); | ||
1973 | break; | ||
1974 | } | ||
1975 | case VIDIOC_SUBSCRIBE_EVENT: | ||
1976 | { | ||
1977 | struct v4l2_event_subscription *sub = arg; | ||
1978 | |||
1979 | if (!ops->vidioc_subscribe_event) | ||
1980 | break; | ||
1981 | |||
1982 | ret = ops->vidioc_subscribe_event(fh, sub); | ||
1983 | if (ret < 0) { | ||
1984 | dbgarg(cmd, "failed, ret=%ld", ret); | ||
1985 | break; | ||
1986 | } | ||
1987 | dbgarg(cmd, "type=0x%8.8x", sub->type); | ||
1988 | break; | ||
1989 | } | ||
1990 | case VIDIOC_UNSUBSCRIBE_EVENT: | ||
1991 | { | ||
1992 | struct v4l2_event_subscription *sub = arg; | ||
1993 | |||
1994 | if (!ops->vidioc_unsubscribe_event) | ||
1995 | break; | ||
1996 | |||
1997 | ret = ops->vidioc_unsubscribe_event(fh, sub); | ||
1998 | if (ret < 0) { | ||
1999 | dbgarg(cmd, "failed, ret=%ld", ret); | ||
2000 | break; | ||
2001 | } | ||
2002 | dbgarg(cmd, "type=0x%8.8x", sub->type); | ||
2003 | break; | ||
2004 | } | ||
1946 | default: | 2005 | default: |
1947 | { | 2006 | { |
1948 | if (!ops->vidioc_default) | 2007 | if (!ops->vidioc_default) |
@@ -2006,7 +2065,7 @@ long video_ioctl2(struct file *file, | |||
2006 | { | 2065 | { |
2007 | char sbuf[128]; | 2066 | char sbuf[128]; |
2008 | void *mbuf = NULL; | 2067 | void *mbuf = NULL; |
2009 | void *parg = NULL; | 2068 | void *parg = (void *)arg; |
2010 | long err = -EINVAL; | 2069 | long err = -EINVAL; |
2011 | int is_ext_ctrl; | 2070 | int is_ext_ctrl; |
2012 | size_t ctrls_size = 0; | 2071 | size_t ctrls_size = 0; |