From: Stephen Rothwell Date: Wed, 25 Jul 2012 00:14:02 +0000 (+1000) Subject: Merge remote-tracking branch 'v4l-dvb/master' X-Git-Tag: next-20120725~72 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=72290830573f4499d0c29d83f245a8f25e88125e;p=karo-tx-linux.git Merge remote-tracking branch 'v4l-dvb/master' Conflicts: Documentation/feature-removal-schedule.txt --- 72290830573f4499d0c29d83f245a8f25e88125e diff --cc Documentation/feature-removal-schedule.txt index 59581f58686c,eb1091196309..b8104b8578a7 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@@ -609,13 -613,18 +609,29 @@@ Why: Unsupported/unmaintained/unused si ---------------------------- +What: OMAP private DMA implementation +When: 2013 +Why: We have a DMA engine implementation; all users should be updated + to use this rather than persisting with the old APIs. The old APIs + block merging the old DMA engine implementation into the DMA + engine driver. +Who: Russell King , + Santosh Shilimkar + +---------------------------- ++ + What: V4L2 selections API target rectangle and flags unification, the + following definitions will be removed: V4L2_SEL_TGT_CROP_ACTIVE, + V4L2_SEL_TGT_COMPOSE_ACTIVE, V4L2_SUBDEV_SEL_*, V4L2_SUBDEV_SEL_FLAG_* + in favor of common V4L2_SEL_TGT_* and V4L2_SEL_FLAG_* definitions. + For more details see include/linux/v4l2-common.h. + When: 3.8 + Why: The regular V4L2 selections and the subdev selection API originally + defined distinct names for the target rectangles and flags - V4L2_SEL_* + and V4L2_SUBDEV_SEL_*. Although, it turned out that the meaning of these + target rectangles is virtually identical and the APIs were consolidated + to use single set of names - V4L2_SEL_*. This didn't involve any ABI + changes. Alias definitions were created for the original ones to avoid + any instabilities in the user space interface. After few cycles these + backward compatibility definitions will be removed. + Who: Sylwester Nawrocki diff --cc drivers/media/video/v4l2-ioctl.c index d7fa8962d8b3,70e0efb127a6..812beb0ef0a6 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@@ -536,1570 -922,1153 +922,1153 @@@ static int check_fmt(const struct v4l2_ return -EINVAL; } - static long __video_do_ioctl(struct file *file, - unsigned int cmd, void *arg) + static int v4l_querycap(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) { - struct video_device *vfd = video_devdata(file); - const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; - void *fh = file->private_data; - struct v4l2_fh *vfh = NULL; - int use_fh_prio = 0; - long ret = -ENOTTY; + struct v4l2_capability *cap = (struct v4l2_capability *)arg; - if (ops == NULL) { - printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n", - vfd->name); - return ret; - } - - if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { - vfh = file->private_data; - use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); - } + cap->version = LINUX_VERSION_CODE; + return ops->vidioc_querycap(file, fh, cap); + } - if (v4l2_is_known_ioctl(cmd)) { - struct v4l2_ioctl_info *info = &v4l2_ioctls[_IOC_NR(cmd)]; + static int v4l_s_input(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + return ops->vidioc_s_input(file, fh, *(unsigned int *)arg); + } - if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) && - !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler)) - return -ENOTTY; + static int v4l_s_output(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + return ops->vidioc_s_output(file, fh, *(unsigned int *)arg); + } - if (use_fh_prio && (info->flags & INFO_FL_PRIO)) { - ret = v4l2_prio_check(vfd->prio, vfh->prio); - if (ret) - return ret; - } - } + static int v4l_g_priority(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd; + u32 *p = arg; - if ((vfd->debug & V4L2_DEBUG_IOCTL) && - !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { - v4l_print_ioctl(vfd->name, cmd); - printk(KERN_CONT "\n"); - } + if (ops->vidioc_g_priority) + return ops->vidioc_g_priority(file, fh, arg); + vfd = video_devdata(file); + *p = v4l2_prio_max(&vfd->v4l2_dev->prio); + return 0; + } - switch (cmd) { + static int v4l_s_priority(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd; + struct v4l2_fh *vfh; + u32 *p = arg; + + if (ops->vidioc_s_priority) + return ops->vidioc_s_priority(file, fh, *p); + vfd = video_devdata(file); + vfh = file->private_data; + return v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p); + } - /* --- capabilities ------------------------------------------ */ - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = (struct v4l2_capability *)arg; - - cap->version = LINUX_VERSION_CODE; - ret = ops->vidioc_querycap(file, fh, cap); - if (!ret) - dbgarg(cmd, "driver=%s, card=%s, bus=%s, " - "version=0x%08x, " - "capabilities=0x%08x, " - "device_caps=0x%08x\n", - cap->driver, cap->card, cap->bus_info, - cap->version, - cap->capabilities, - cap->device_caps); - break; - } + static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_input *p = arg; - /* --- priority ------------------------------------------ */ - case VIDIOC_G_PRIORITY: - { - enum v4l2_priority *p = arg; + /* + * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & + * CAP_STD here based on ioctl handler provided by the + * driver. If the driver doesn't support these + * for a specific input, it must override these flags. + */ + if (ops->vidioc_s_std) + p->capabilities |= V4L2_IN_CAP_STD; + if (ops->vidioc_s_dv_preset) + p->capabilities |= V4L2_IN_CAP_PRESETS; + if (ops->vidioc_s_dv_timings) + p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS; + + return ops->vidioc_enum_input(file, fh, p); + } - if (ops->vidioc_g_priority) { - ret = ops->vidioc_g_priority(file, fh, p); - } else if (use_fh_prio) { - *p = v4l2_prio_max(&vfd->v4l2_dev->prio); - ret = 0; - } - if (!ret) - dbgarg(cmd, "priority is %d\n", *p); - break; - } - case VIDIOC_S_PRIORITY: - { - enum v4l2_priority *p = arg; + static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_output *p = arg; - dbgarg(cmd, "setting priority to %d\n", *p); - if (ops->vidioc_s_priority) - ret = ops->vidioc_s_priority(file, fh, *p); - else - ret = v4l2_prio_change(&vfd->v4l2_dev->prio, - &vfh->prio, *p); - break; - } + /* + * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & + * CAP_STD here based on ioctl handler provided by the + * driver. If the driver doesn't support these + * for a specific output, it must override these flags. + */ + if (ops->vidioc_s_std) + p->capabilities |= V4L2_OUT_CAP_STD; + if (ops->vidioc_s_dv_preset) + p->capabilities |= V4L2_OUT_CAP_PRESETS; + if (ops->vidioc_s_dv_timings) + p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS; + + return ops->vidioc_enum_output(file, fh, p); + } - /* --- capture ioctls ---------------------------------------- */ - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *f = arg; + static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_fmtdesc *p = arg; - ret = -EINVAL; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (likely(ops->vidioc_enum_fmt_vid_cap)) - ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f); - break; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (likely(ops->vidioc_enum_fmt_vid_cap_mplane)) - ret = ops->vidioc_enum_fmt_vid_cap_mplane(file, - fh, f); + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (unlikely(!ops->vidioc_enum_fmt_vid_cap)) break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (likely(ops->vidioc_enum_fmt_vid_overlay)) - ret = ops->vidioc_enum_fmt_vid_overlay(file, - fh, f); + return ops->vidioc_enum_fmt_vid_cap(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (unlikely(!ops->vidioc_enum_fmt_vid_cap_mplane)) break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (likely(ops->vidioc_enum_fmt_vid_out)) - ret = ops->vidioc_enum_fmt_vid_out(file, fh, f); + return ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (unlikely(!ops->vidioc_enum_fmt_vid_overlay)) break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (likely(ops->vidioc_enum_fmt_vid_out_mplane)) - ret = ops->vidioc_enum_fmt_vid_out_mplane(file, - fh, f); + return ops->vidioc_enum_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (unlikely(!ops->vidioc_enum_fmt_vid_out)) break; - case V4L2_BUF_TYPE_PRIVATE: - if (likely(ops->vidioc_enum_fmt_type_private)) - ret = ops->vidioc_enum_fmt_type_private(file, - fh, f); + return ops->vidioc_enum_fmt_vid_out(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (unlikely(!ops->vidioc_enum_fmt_vid_out_mplane)) break; - default: + return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg); + case V4L2_BUF_TYPE_PRIVATE: + if (unlikely(!ops->vidioc_enum_fmt_type_private)) break; - } - if (likely(!ret)) - dbgarg(cmd, "index=%d, type=%d, flags=%d, " - "pixelformat=%c%c%c%c, description='%s'\n", - f->index, f->type, f->flags, - (f->pixelformat & 0xff), - (f->pixelformat >> 8) & 0xff, - (f->pixelformat >> 16) & 0xff, - (f->pixelformat >> 24) & 0xff, - f->description); - break; + return ops->vidioc_enum_fmt_type_private(file, fh, arg); } - case VIDIOC_G_FMT: - { - struct v4l2_format *f = (struct v4l2_format *)arg; - - /* FIXME: Should be one dump per type */ - dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names)); - - ret = -EINVAL; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (ops->vidioc_g_fmt_vid_cap) - ret = ops->vidioc_g_fmt_vid_cap(file, fh, f); - if (!ret) - v4l_print_pix_fmt(vfd, &f->fmt.pix); + return -EINVAL; + } + + static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_format *p = arg; + + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (unlikely(!ops->vidioc_g_fmt_vid_cap)) break; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (ops->vidioc_g_fmt_vid_cap_mplane) - ret = ops->vidioc_g_fmt_vid_cap_mplane(file, - fh, f); - if (!ret) - v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp); + return ops->vidioc_g_fmt_vid_cap(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (unlikely(!ops->vidioc_g_fmt_vid_cap_mplane)) break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (likely(ops->vidioc_g_fmt_vid_overlay)) - ret = ops->vidioc_g_fmt_vid_overlay(file, - fh, f); + return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (unlikely(!ops->vidioc_g_fmt_vid_overlay)) break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (ops->vidioc_g_fmt_vid_out) - ret = ops->vidioc_g_fmt_vid_out(file, fh, f); - if (!ret) - v4l_print_pix_fmt(vfd, &f->fmt.pix); + return ops->vidioc_g_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (unlikely(!ops->vidioc_g_fmt_vid_out)) break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - if (ops->vidioc_g_fmt_vid_out_mplane) - ret = ops->vidioc_g_fmt_vid_out_mplane(file, - fh, f); - if (!ret) - v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp); + return ops->vidioc_g_fmt_vid_out(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (unlikely(!ops->vidioc_g_fmt_vid_out_mplane)) break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - if (likely(ops->vidioc_g_fmt_vid_out_overlay)) - ret = ops->vidioc_g_fmt_vid_out_overlay(file, - fh, f); + return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + if (unlikely(!ops->vidioc_g_fmt_vid_out_overlay)) break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - if (likely(ops->vidioc_g_fmt_vbi_cap)) - ret = ops->vidioc_g_fmt_vbi_cap(file, fh, f); + return ops->vidioc_g_fmt_vid_out_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (unlikely(!ops->vidioc_g_fmt_vbi_cap)) break; - case V4L2_BUF_TYPE_VBI_OUTPUT: - if (likely(ops->vidioc_g_fmt_vbi_out)) - ret = ops->vidioc_g_fmt_vbi_out(file, fh, f); + return ops->vidioc_g_fmt_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_VBI_OUTPUT: + if (unlikely(!ops->vidioc_g_fmt_vbi_out)) break; - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - if (likely(ops->vidioc_g_fmt_sliced_vbi_cap)) - ret = ops->vidioc_g_fmt_sliced_vbi_cap(file, - fh, f); + return ops->vidioc_g_fmt_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (unlikely(!ops->vidioc_g_fmt_sliced_vbi_cap)) break; - case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - if (likely(ops->vidioc_g_fmt_sliced_vbi_out)) - ret = ops->vidioc_g_fmt_sliced_vbi_out(file, - fh, f); + return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + if (unlikely(!ops->vidioc_g_fmt_sliced_vbi_out)) break; - case V4L2_BUF_TYPE_PRIVATE: - if (likely(ops->vidioc_g_fmt_type_private)) - ret = ops->vidioc_g_fmt_type_private(file, - fh, f); + return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_PRIVATE: + if (unlikely(!ops->vidioc_g_fmt_type_private)) break; - } - break; + return ops->vidioc_g_fmt_type_private(file, fh, arg); } - case VIDIOC_S_FMT: - { - struct v4l2_format *f = (struct v4l2_format *)arg; - - ret = -EINVAL; + return -EINVAL; + } - /* FIXME: Should be one dump per type */ - dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names)); + static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_format *p = arg; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - CLEAR_AFTER_FIELD(f, fmt.pix); - v4l_print_pix_fmt(vfd, &f->fmt.pix); - if (ops->vidioc_s_fmt_vid_cap) - ret = ops->vidioc_s_fmt_vid_cap(file, fh, f); + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (unlikely(!ops->vidioc_s_fmt_vid_cap)) break; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - CLEAR_AFTER_FIELD(f, fmt.pix_mp); - v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp); - if (ops->vidioc_s_fmt_vid_cap_mplane) - ret = ops->vidioc_s_fmt_vid_cap_mplane(file, - fh, f); + CLEAR_AFTER_FIELD(p, fmt.pix); + return ops->vidioc_s_fmt_vid_cap(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (unlikely(!ops->vidioc_s_fmt_vid_cap_mplane)) break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - CLEAR_AFTER_FIELD(f, fmt.win); - if (ops->vidioc_s_fmt_vid_overlay) - ret = ops->vidioc_s_fmt_vid_overlay(file, - fh, f); + CLEAR_AFTER_FIELD(p, fmt.pix_mp); + return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (unlikely(!ops->vidioc_s_fmt_vid_overlay)) break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - CLEAR_AFTER_FIELD(f, fmt.pix); - v4l_print_pix_fmt(vfd, &f->fmt.pix); - if (ops->vidioc_s_fmt_vid_out) - ret = ops->vidioc_s_fmt_vid_out(file, fh, f); + CLEAR_AFTER_FIELD(p, fmt.win); + return ops->vidioc_s_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (unlikely(!ops->vidioc_s_fmt_vid_out)) break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - CLEAR_AFTER_FIELD(f, fmt.pix_mp); - v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp); - if (ops->vidioc_s_fmt_vid_out_mplane) - ret = ops->vidioc_s_fmt_vid_out_mplane(file, - fh, f); + CLEAR_AFTER_FIELD(p, fmt.pix); + return ops->vidioc_s_fmt_vid_out(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (unlikely(!ops->vidioc_s_fmt_vid_out_mplane)) break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - CLEAR_AFTER_FIELD(f, fmt.win); - if (ops->vidioc_s_fmt_vid_out_overlay) - ret = ops->vidioc_s_fmt_vid_out_overlay(file, - fh, f); + CLEAR_AFTER_FIELD(p, fmt.pix_mp); + return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay)) break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - CLEAR_AFTER_FIELD(f, fmt.vbi); - if (likely(ops->vidioc_s_fmt_vbi_cap)) - ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f); + CLEAR_AFTER_FIELD(p, fmt.win); + return ops->vidioc_s_fmt_vid_out_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (unlikely(!ops->vidioc_s_fmt_vbi_cap)) break; - case V4L2_BUF_TYPE_VBI_OUTPUT: - CLEAR_AFTER_FIELD(f, fmt.vbi); - if (likely(ops->vidioc_s_fmt_vbi_out)) - ret = ops->vidioc_s_fmt_vbi_out(file, fh, f); + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_s_fmt_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_VBI_OUTPUT: + if (unlikely(!ops->vidioc_s_fmt_vbi_out)) break; - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - CLEAR_AFTER_FIELD(f, fmt.sliced); - if (likely(ops->vidioc_s_fmt_sliced_vbi_cap)) - ret = ops->vidioc_s_fmt_sliced_vbi_cap(file, - fh, f); + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_s_fmt_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_cap)) break; - case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - CLEAR_AFTER_FIELD(f, fmt.sliced); - if (likely(ops->vidioc_s_fmt_sliced_vbi_out)) - ret = ops->vidioc_s_fmt_sliced_vbi_out(file, - fh, f); - + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_out)) break; - case V4L2_BUF_TYPE_PRIVATE: - /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */ - if (likely(ops->vidioc_s_fmt_type_private)) - ret = ops->vidioc_s_fmt_type_private(file, - fh, f); + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_PRIVATE: + if (unlikely(!ops->vidioc_s_fmt_type_private)) break; - } - break; + return ops->vidioc_s_fmt_type_private(file, fh, arg); } - case VIDIOC_TRY_FMT: - { - struct v4l2_format *f = (struct v4l2_format *)arg; - - /* FIXME: Should be one dump per type */ - dbgarg(cmd, "type=%s\n", prt_names(f->type, - v4l2_type_names)); - ret = -EINVAL; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - CLEAR_AFTER_FIELD(f, fmt.pix); - if (ops->vidioc_try_fmt_vid_cap) - ret = ops->vidioc_try_fmt_vid_cap(file, fh, f); - if (!ret) - v4l_print_pix_fmt(vfd, &f->fmt.pix); + return -EINVAL; + } + + static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_format *p = arg; + + switch (p->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (unlikely(!ops->vidioc_try_fmt_vid_cap)) break; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - CLEAR_AFTER_FIELD(f, fmt.pix_mp); - if (ops->vidioc_try_fmt_vid_cap_mplane) - ret = ops->vidioc_try_fmt_vid_cap_mplane(file, - fh, f); - if (!ret) - v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp); + CLEAR_AFTER_FIELD(p, fmt.pix); + return ops->vidioc_try_fmt_vid_cap(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane)) break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - CLEAR_AFTER_FIELD(f, fmt.win); - if (likely(ops->vidioc_try_fmt_vid_overlay)) - ret = ops->vidioc_try_fmt_vid_overlay(file, - fh, f); + CLEAR_AFTER_FIELD(p, fmt.pix_mp); + return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OVERLAY: + if (unlikely(!ops->vidioc_try_fmt_vid_overlay)) break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - CLEAR_AFTER_FIELD(f, fmt.pix); - if (ops->vidioc_try_fmt_vid_out) - ret = ops->vidioc_try_fmt_vid_out(file, fh, f); - if (!ret) - v4l_print_pix_fmt(vfd, &f->fmt.pix); + CLEAR_AFTER_FIELD(p, fmt.win); + return ops->vidioc_try_fmt_vid_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + if (unlikely(!ops->vidioc_try_fmt_vid_out)) break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - CLEAR_AFTER_FIELD(f, fmt.pix_mp); - if (ops->vidioc_try_fmt_vid_out_mplane) - ret = ops->vidioc_try_fmt_vid_out_mplane(file, - fh, f); - if (!ret) - v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp); + CLEAR_AFTER_FIELD(p, fmt.pix); + return ops->vidioc_try_fmt_vid_out(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + if (unlikely(!ops->vidioc_try_fmt_vid_out_mplane)) break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - CLEAR_AFTER_FIELD(f, fmt.win); - if (likely(ops->vidioc_try_fmt_vid_out_overlay)) - ret = ops->vidioc_try_fmt_vid_out_overlay(file, - fh, f); + CLEAR_AFTER_FIELD(p, fmt.pix_mp); + return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg); + case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay)) break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - CLEAR_AFTER_FIELD(f, fmt.vbi); - if (likely(ops->vidioc_try_fmt_vbi_cap)) - ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f); + CLEAR_AFTER_FIELD(p, fmt.win); + return ops->vidioc_try_fmt_vid_out_overlay(file, fh, arg); + case V4L2_BUF_TYPE_VBI_CAPTURE: + if (unlikely(!ops->vidioc_try_fmt_vbi_cap)) break; - case V4L2_BUF_TYPE_VBI_OUTPUT: - CLEAR_AFTER_FIELD(f, fmt.vbi); - if (likely(ops->vidioc_try_fmt_vbi_out)) - ret = ops->vidioc_try_fmt_vbi_out(file, fh, f); + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_try_fmt_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_VBI_OUTPUT: + if (unlikely(!ops->vidioc_try_fmt_vbi_out)) break; - case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - CLEAR_AFTER_FIELD(f, fmt.sliced); - if (likely(ops->vidioc_try_fmt_sliced_vbi_cap)) - ret = ops->vidioc_try_fmt_sliced_vbi_cap(file, - fh, f); + CLEAR_AFTER_FIELD(p, fmt.vbi); + return ops->vidioc_try_fmt_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_cap)) break; - case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - CLEAR_AFTER_FIELD(f, fmt.sliced); - if (likely(ops->vidioc_try_fmt_sliced_vbi_out)) - ret = ops->vidioc_try_fmt_sliced_vbi_out(file, - fh, f); + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg); + case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_out)) break; - case V4L2_BUF_TYPE_PRIVATE: - /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */ - if (likely(ops->vidioc_try_fmt_type_private)) - ret = ops->vidioc_try_fmt_type_private(file, - fh, f); + CLEAR_AFTER_FIELD(p, fmt.sliced); + return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg); + case V4L2_BUF_TYPE_PRIVATE: + if (unlikely(!ops->vidioc_try_fmt_type_private)) break; - } - break; + return ops->vidioc_try_fmt_type_private(file, fh, arg); } - /* FIXME: Those buf reqs could be handled here, - with some changes on videobuf to allow its header to be included at - videodev2.h or being merged at videodev2. - */ - case VIDIOC_REQBUFS: - { - struct v4l2_requestbuffers *p = arg; - - ret = check_fmt(ops, p->type); - if (ret) - break; + return -EINVAL; + } - if (p->type < V4L2_BUF_TYPE_PRIVATE) - CLEAR_AFTER_FIELD(p, memory); + static int v4l_streamon(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + return ops->vidioc_streamon(file, fh, *(unsigned int *)arg); + } - ret = ops->vidioc_reqbufs(file, fh, p); - dbgarg(cmd, "count=%d, type=%s, memory=%s\n", - p->count, - prt_names(p->type, v4l2_type_names), - prt_names(p->memory, v4l2_memory_names)); - break; - } - case VIDIOC_QUERYBUF: - { - struct v4l2_buffer *p = arg; + static int v4l_streamoff(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg); + } - ret = check_fmt(ops, p->type); - if (ret) - break; + static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_tuner *p = arg; - ret = ops->vidioc_querybuf(file, fh, p); - if (!ret) - dbgbuf(cmd, vfd, p); - break; - } - case VIDIOC_QBUF: - { - struct v4l2_buffer *p = arg; + p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + return ops->vidioc_g_tuner(file, fh, p); + } - ret = check_fmt(ops, p->type); - if (ret) - break; + static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_tuner *p = arg; - ret = ops->vidioc_qbuf(file, fh, p); - if (!ret) - dbgbuf(cmd, vfd, p); - break; - } - case VIDIOC_DQBUF: - { - struct v4l2_buffer *p = arg; + p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + return ops->vidioc_s_tuner(file, fh, p); + } - ret = check_fmt(ops, p->type); - if (ret) - break; + static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_frequency *p = arg; - ret = ops->vidioc_dqbuf(file, fh, p); - if (!ret) - dbgbuf(cmd, vfd, p); - break; - } - case VIDIOC_OVERLAY: - { - int *i = arg; + p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + return ops->vidioc_g_frequency(file, fh, p); + } - dbgarg(cmd, "value=%d\n", *i); - ret = ops->vidioc_overlay(file, fh, *i); - break; - } - case VIDIOC_G_FBUF: - { - struct v4l2_framebuffer *p = arg; - - ret = ops->vidioc_g_fbuf(file, fh, arg); - if (!ret) { - dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n", - p->capability, p->flags, - (unsigned long)p->base); - v4l_print_pix_fmt(vfd, &p->fmt); - } - break; - } - case VIDIOC_S_FBUF: - { - struct v4l2_framebuffer *p = arg; - - dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n", - p->capability, p->flags, (unsigned long)p->base); - v4l_print_pix_fmt(vfd, &p->fmt); - ret = ops->vidioc_s_fbuf(file, fh, arg); - break; - } - case VIDIOC_STREAMON: - { - enum v4l2_buf_type i = *(int *)arg; + static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_frequency *p = arg; + enum v4l2_tuner_type type; - dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names)); - ret = ops->vidioc_streamon(file, fh, i); - break; - } - case VIDIOC_STREAMOFF: - { - enum v4l2_buf_type i = *(int *)arg; + type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + if (p->type != type) + return -EINVAL; + return ops->vidioc_s_frequency(file, fh, p); + } - dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names)); - ret = ops->vidioc_streamoff(file, fh, i); - break; - } - /* ---------- tv norms ---------- */ - case VIDIOC_ENUMSTD: - { - struct v4l2_standard *p = arg; - v4l2_std_id id = vfd->tvnorms, curr_id = 0; - unsigned int index = p->index, i, j = 0; - const char *descr = ""; - - if (id == 0) - break; - ret = -EINVAL; - - /* Return norm array in a canonical way */ - for (i = 0; i <= index && id; i++) { - /* last std value in the standards array is 0, so this - while always ends there since (id & 0) == 0. */ - while ((id & standards[j].std) != standards[j].std) - j++; - curr_id = standards[j].std; - descr = standards[j].descr; + static int v4l_enumstd(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_standard *p = arg; + v4l2_std_id id = vfd->tvnorms, curr_id = 0; + unsigned int index = p->index, i, j = 0; + const char *descr = ""; + + /* Return norm array in a canonical way */ + for (i = 0; i <= index && id; i++) { + /* last std value in the standards array is 0, so this + while always ends there since (id & 0) == 0. */ + while ((id & standards[j].std) != standards[j].std) j++; - if (curr_id == 0) - break; - if (curr_id != V4L2_STD_PAL && - curr_id != V4L2_STD_SECAM && - curr_id != V4L2_STD_NTSC) - id &= ~curr_id; - } - if (i <= index) + curr_id = standards[j].std; + descr = standards[j].descr; + j++; + if (curr_id == 0) break; - - v4l2_video_std_construct(p, curr_id, descr); - - dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, " - "framelines=%d\n", p->index, - (unsigned long long)p->id, p->name, - p->frameperiod.numerator, - p->frameperiod.denominator, - p->framelines); - - ret = 0; - break; - } - case VIDIOC_G_STD: - { - v4l2_std_id *id = arg; - - /* Calls the specific handler */ - if (ops->vidioc_g_std) - ret = ops->vidioc_g_std(file, fh, id); - else if (vfd->current_norm) { - ret = 0; - *id = vfd->current_norm; - } - - if (likely(!ret)) - dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id); - break; - } - case VIDIOC_S_STD: - { - v4l2_std_id *id = arg, norm; - - dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id); - - ret = -EINVAL; - norm = (*id) & vfd->tvnorms; - if (vfd->tvnorms && !norm) /* Check if std is supported */ - break; - - /* Calls the specific handler */ - ret = ops->vidioc_s_std(file, fh, &norm); - - /* Updates standard information */ - if (ret >= 0) - vfd->current_norm = norm; - break; + if (curr_id != V4L2_STD_PAL && + curr_id != V4L2_STD_SECAM && + curr_id != V4L2_STD_NTSC) + id &= ~curr_id; } - case VIDIOC_QUERYSTD: - { - v4l2_std_id *p = arg; - - /* - * If nothing detected, it should return all supported - * Drivers just need to mask the std argument, in order - * to remove the standards that don't apply from the mask. - * This means that tuners, audio and video decoders can join - * their efforts to improve the standards detection - */ - *p = vfd->tvnorms; - ret = ops->vidioc_querystd(file, fh, arg); - if (!ret) - dbgarg(cmd, "detected std=%08Lx\n", - (unsigned long long)*p); - break; - } - /* ------ input switching ---------- */ - /* FIXME: Inputs can be handled inside videodev2 */ - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *p = arg; + if (i <= index) + return -EINVAL; - /* - * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & - * CAP_STD here based on ioctl handler provided by the - * driver. If the driver doesn't support these - * for a specific input, it must override these flags. - */ - if (ops->vidioc_s_std) - p->capabilities |= V4L2_IN_CAP_STD; - if (ops->vidioc_s_dv_preset) - p->capabilities |= V4L2_IN_CAP_PRESETS; - if (ops->vidioc_s_dv_timings) - p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS; - - ret = ops->vidioc_enum_input(file, fh, p); - if (!ret) - dbgarg(cmd, "index=%d, name=%s, type=%d, " - "audioset=%d, " - "tuner=%d, std=%08Lx, status=%d\n", - p->index, p->name, p->type, p->audioset, - p->tuner, - (unsigned long long)p->std, - p->status); - break; - } - case VIDIOC_G_INPUT: - { - unsigned int *i = arg; + v4l2_video_std_construct(p, curr_id, descr); + return 0; + } - ret = ops->vidioc_g_input(file, fh, i); - if (!ret) - dbgarg(cmd, "value=%d\n", *i); - break; - } - case VIDIOC_S_INPUT: - { - unsigned int *i = arg; + static int v4l_g_std(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + v4l2_std_id *id = arg; - dbgarg(cmd, "value=%d\n", *i); - ret = ops->vidioc_s_input(file, fh, *i); - break; + /* Calls the specific handler */ + if (ops->vidioc_g_std) + return ops->vidioc_g_std(file, fh, arg); + if (vfd->current_norm) { + *id = vfd->current_norm; + return 0; } + return -ENOTTY; + } - /* ------ output switching ---------- */ - case VIDIOC_ENUMOUTPUT: - { - struct v4l2_output *p = arg; - - /* - * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & - * CAP_STD here based on ioctl handler provided by the - * driver. If the driver doesn't support these - * for a specific output, it must override these flags. - */ - if (ops->vidioc_s_std) - p->capabilities |= V4L2_OUT_CAP_STD; - if (ops->vidioc_s_dv_preset) - p->capabilities |= V4L2_OUT_CAP_PRESETS; - if (ops->vidioc_s_dv_timings) - p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS; - - ret = ops->vidioc_enum_output(file, fh, p); - if (!ret) - dbgarg(cmd, "index=%d, name=%s, type=%d, " - "audioset=0x%x, " - "modulator=%d, std=0x%08Lx\n", - p->index, p->name, p->type, p->audioset, - p->modulator, (unsigned long long)p->std); - break; - } - case VIDIOC_G_OUTPUT: - { - unsigned int *i = arg; + static int v4l_s_std(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + v4l2_std_id *id = arg, norm; + int ret; - ret = ops->vidioc_g_output(file, fh, i); - if (!ret) - dbgarg(cmd, "value=%d\n", *i); - break; - } - case VIDIOC_S_OUTPUT: - { - unsigned int *i = arg; + norm = (*id) & vfd->tvnorms; + if (vfd->tvnorms && !norm) /* Check if std is supported */ + return -EINVAL; - dbgarg(cmd, "value=%d\n", *i); - ret = ops->vidioc_s_output(file, fh, *i); - break; - } + /* Calls the specific handler */ + ret = ops->vidioc_s_std(file, fh, &norm); - /* --- controls ---------------------------------------------- */ - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *p = arg; - - if (vfh && vfh->ctrl_handler) - ret = v4l2_queryctrl(vfh->ctrl_handler, p); - else if (vfd->ctrl_handler) - ret = v4l2_queryctrl(vfd->ctrl_handler, p); - else if (ops->vidioc_queryctrl) - ret = ops->vidioc_queryctrl(file, fh, p); - else - break; - if (!ret) - dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, " - "step=%d, default=%d, flags=0x%08x\n", - p->id, p->type, p->name, - p->minimum, p->maximum, - p->step, p->default_value, p->flags); - else - dbgarg(cmd, "id=0x%x\n", p->id); - break; - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *p = arg; - - if (vfh && vfh->ctrl_handler) - ret = v4l2_g_ctrl(vfh->ctrl_handler, p); - else if (vfd->ctrl_handler) - ret = v4l2_g_ctrl(vfd->ctrl_handler, p); - else if (ops->vidioc_g_ctrl) - ret = ops->vidioc_g_ctrl(file, fh, p); - else if (ops->vidioc_g_ext_ctrls) { - struct v4l2_ext_controls ctrls; - struct v4l2_ext_control ctrl; - - ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); - ctrls.count = 1; - ctrls.controls = &ctrl; - ctrl.id = p->id; - ctrl.value = p->value; - if (check_ext_ctrls(&ctrls, 1)) { - ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls); - if (ret == 0) - p->value = ctrl.value; - } - } else - break; - if (!ret) - dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value); - else - dbgarg(cmd, "id=0x%x\n", p->id); - break; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *p = arg; - struct v4l2_ext_controls ctrls; - struct v4l2_ext_control ctrl; - - if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler && - !ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls) - break; + /* Updates standard information */ + if (ret >= 0) + vfd->current_norm = norm; + return ret; + } - dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value); + static int v4l_querystd(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + v4l2_std_id *p = arg; + + /* + * If nothing detected, it should return all supported + * standard. + * Drivers just need to mask the std argument, in order + * to remove the standards that don't apply from the mask. + * This means that tuners, audio and video decoders can join + * their efforts to improve the standards detection. + */ + *p = vfd->tvnorms; + return ops->vidioc_querystd(file, fh, arg); + } - if (vfh && vfh->ctrl_handler) { - ret = v4l2_s_ctrl(vfh, vfh->ctrl_handler, p); - break; - } - if (vfd->ctrl_handler) { - ret = v4l2_s_ctrl(NULL, vfd->ctrl_handler, p); - break; - } - if (ops->vidioc_s_ctrl) { - ret = ops->vidioc_s_ctrl(file, fh, p); - break; - } - if (!ops->vidioc_s_ext_ctrls) - break; + static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_hw_freq_seek *p = arg; + enum v4l2_tuner_type type; - ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); - ctrls.count = 1; - ctrls.controls = &ctrl; - ctrl.id = p->id; - ctrl.value = p->value; - if (check_ext_ctrls(&ctrls, 1)) - ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls); - else - ret = -EINVAL; - break; - } - case VIDIOC_G_EXT_CTRLS: - { - struct v4l2_ext_controls *p = arg; - - p->error_idx = p->count; - if (vfh && vfh->ctrl_handler) - ret = v4l2_g_ext_ctrls(vfh->ctrl_handler, p); - else if (vfd->ctrl_handler) - ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p); - else if (ops->vidioc_g_ext_ctrls) - ret = check_ext_ctrls(p, 0) ? - ops->vidioc_g_ext_ctrls(file, fh, p) : - -EINVAL; - else - break; - v4l_print_ext_ctrls(cmd, vfd, p, !ret); - break; - } - case VIDIOC_S_EXT_CTRLS: - { - struct v4l2_ext_controls *p = arg; + type = (vfd->vfl_type == VFL_TYPE_RADIO) ? + V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + if (p->type != type) + return -EINVAL; + return ops->vidioc_s_hw_freq_seek(file, fh, p); + } - p->error_idx = p->count; - if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler && - !ops->vidioc_s_ext_ctrls) - break; - v4l_print_ext_ctrls(cmd, vfd, p, 1); - if (vfh && vfh->ctrl_handler) - ret = v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p); - else if (vfd->ctrl_handler) - ret = v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p); - else if (check_ext_ctrls(p, 0)) - ret = ops->vidioc_s_ext_ctrls(file, fh, p); - else - ret = -EINVAL; - break; - } - case VIDIOC_TRY_EXT_CTRLS: - { - struct v4l2_ext_controls *p = arg; + static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_requestbuffers *p = arg; + int ret = check_fmt(ops, p->type); - p->error_idx = p->count; - if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler && - !ops->vidioc_try_ext_ctrls) - break; - v4l_print_ext_ctrls(cmd, vfd, p, 1); - if (vfh && vfh->ctrl_handler) - ret = v4l2_try_ext_ctrls(vfh->ctrl_handler, p); - else if (vfd->ctrl_handler) - ret = v4l2_try_ext_ctrls(vfd->ctrl_handler, p); - else if (check_ext_ctrls(p, 0)) - ret = ops->vidioc_try_ext_ctrls(file, fh, p); - else - ret = -EINVAL; - break; - } - case VIDIOC_QUERYMENU: - { - struct v4l2_querymenu *p = arg; - - if (vfh && vfh->ctrl_handler) - ret = v4l2_querymenu(vfh->ctrl_handler, p); - else if (vfd->ctrl_handler) - ret = v4l2_querymenu(vfd->ctrl_handler, p); - else if (ops->vidioc_querymenu) - ret = ops->vidioc_querymenu(file, fh, p); - else - break; - if (!ret) - dbgarg(cmd, "id=0x%x, index=%d, name=%s\n", - p->id, p->index, p->name); - else - dbgarg(cmd, "id=0x%x, index=%d\n", - p->id, p->index); - break; - } - /* --- audio ---------------------------------------------- */ - case VIDIOC_ENUMAUDIO: - { - struct v4l2_audio *p = arg; - - ret = ops->vidioc_enumaudio(file, fh, p); - if (!ret) - dbgarg(cmd, "index=%d, name=%s, capability=0x%x, " - "mode=0x%x\n", p->index, p->name, - p->capability, p->mode); - else - dbgarg(cmd, "index=%d\n", p->index); - break; - } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *p = arg; - - ret = ops->vidioc_g_audio(file, fh, p); - if (!ret) - dbgarg(cmd, "index=%d, name=%s, capability=0x%x, " - "mode=0x%x\n", p->index, - p->name, p->capability, p->mode); - else - dbgarg(cmd, "index=%d\n", p->index); - break; - } - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *p = arg; - - dbgarg(cmd, "index=%d, name=%s, capability=0x%x, " - "mode=0x%x\n", p->index, p->name, - p->capability, p->mode); - ret = ops->vidioc_s_audio(file, fh, p); - break; - } - case VIDIOC_ENUMAUDOUT: - { - struct v4l2_audioout *p = arg; - - dbgarg(cmd, "Enum for index=%d\n", p->index); - ret = ops->vidioc_enumaudout(file, fh, p); - if (!ret) - dbgarg2("index=%d, name=%s, capability=%d, " - "mode=%d\n", p->index, p->name, - p->capability, p->mode); - break; - } - case VIDIOC_G_AUDOUT: - { - struct v4l2_audioout *p = arg; - - ret = ops->vidioc_g_audout(file, fh, p); - if (!ret) - dbgarg2("index=%d, name=%s, capability=%d, " - "mode=%d\n", p->index, p->name, - p->capability, p->mode); - break; - } - case VIDIOC_S_AUDOUT: - { - struct v4l2_audioout *p = arg; + if (ret) + return ret; - dbgarg(cmd, "index=%d, name=%s, capability=%d, " - "mode=%d\n", p->index, p->name, - p->capability, p->mode); + if (p->type < V4L2_BUF_TYPE_PRIVATE) + CLEAR_AFTER_FIELD(p, memory); - ret = ops->vidioc_s_audout(file, fh, p); - break; - } - case VIDIOC_G_MODULATOR: - { - struct v4l2_modulator *p = arg; - - ret = ops->vidioc_g_modulator(file, fh, p); - if (!ret) - dbgarg(cmd, "index=%d, name=%s, " - "capability=%d, rangelow=%d," - " rangehigh=%d, txsubchans=%d\n", - p->index, p->name, p->capability, - p->rangelow, p->rangehigh, - p->txsubchans); - break; - } - case VIDIOC_S_MODULATOR: - { - struct v4l2_modulator *p = arg; - - dbgarg(cmd, "index=%d, name=%s, capability=%d, " - "rangelow=%d, rangehigh=%d, txsubchans=%d\n", - p->index, p->name, p->capability, p->rangelow, - p->rangehigh, p->txsubchans); - ret = ops->vidioc_s_modulator(file, fh, p); - break; - } - case VIDIOC_G_CROP: - { - struct v4l2_crop *p = arg; + return ops->vidioc_reqbufs(file, fh, p); + } - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); + static int v4l_querybuf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_buffer *p = arg; + int ret = check_fmt(ops, p->type); - if (ops->vidioc_g_crop) { - ret = ops->vidioc_g_crop(file, fh, p); - } else { - /* simulate capture crop using selection api */ - struct v4l2_selection s = { - .type = p->type, - }; - - /* crop means compose for output devices */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; - else - s.target = V4L2_SEL_TGT_CROP_ACTIVE; - - ret = ops->vidioc_g_selection(file, fh, &s); - - /* copying results to old structure on success */ - if (!ret) - p->c = s.r; - } + return ret ? ret : ops->vidioc_querybuf(file, fh, p); + } - if (!ret) - dbgrect(vfd, "", &p->c); - break; - } - case VIDIOC_S_CROP: - { - struct v4l2_crop *p = arg; + static int v4l_qbuf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_buffer *p = arg; + int ret = check_fmt(ops, p->type); - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); - dbgrect(vfd, "", &p->c); + return ret ? ret : ops->vidioc_qbuf(file, fh, p); + } - if (ops->vidioc_s_crop) { - ret = ops->vidioc_s_crop(file, fh, p); - } else { - /* simulate capture crop using selection api */ - struct v4l2_selection s = { - .type = p->type, - .r = p->c, - }; - - /* crop means compose for output devices */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; - else - s.target = V4L2_SEL_TGT_CROP_ACTIVE; - - ret = ops->vidioc_s_selection(file, fh, &s); - } - break; - } - case VIDIOC_G_SELECTION: - { - struct v4l2_selection *p = arg; + static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_buffer *p = arg; + int ret = check_fmt(ops, p->type); - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); + return ret ? ret : ops->vidioc_dqbuf(file, fh, p); + } - ret = ops->vidioc_g_selection(file, fh, p); - if (!ret) - dbgrect(vfd, "", &p->r); - break; - } - case VIDIOC_S_SELECTION: - { - struct v4l2_selection *p = arg; + static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_create_buffers *create = arg; + int ret = check_fmt(ops, create->format.type); + return ret ? ret : ops->vidioc_create_bufs(file, fh, create); + } - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); - dbgrect(vfd, "", &p->r); + static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_buffer *b = arg; + int ret = check_fmt(ops, b->type); - ret = ops->vidioc_s_selection(file, fh, p); - break; - } - case VIDIOC_CROPCAP: - { - struct v4l2_cropcap *p = arg; - - /*FIXME: Should also show v4l2_fract pixelaspect */ - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); - if (ops->vidioc_cropcap) { - ret = ops->vidioc_cropcap(file, fh, p); - } else { - struct v4l2_selection s = { .type = p->type }; + return ret ? ret : ops->vidioc_prepare_buf(file, fh, b); + } - /* obtaining bounds */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; - else - s.target = V4L2_SEL_TGT_CROP_BOUNDS; + static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_streamparm *p = arg; + v4l2_std_id std; + int ret = check_fmt(ops, p->type); - ret = ops->vidioc_g_selection(file, fh, &s); - if (ret) - break; - p->bounds = s.r; + if (ret) + return ret; + if (ops->vidioc_g_parm) + return ops->vidioc_g_parm(file, fh, p); + std = vfd->current_norm; + if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + return -EINVAL; + p->parm.capture.readbuffers = 2; + if (ops->vidioc_g_std) + ret = ops->vidioc_g_std(file, fh, &std); + if (ret == 0) + v4l2_video_std_frame_period(std, + &p->parm.capture.timeperframe); + return ret; + } - /* obtaining defrect */ - if (V4L2_TYPE_IS_OUTPUT(p->type)) - s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; - else - s.target = V4L2_SEL_TGT_CROP_DEFAULT; + static int v4l_s_parm(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_streamparm *p = arg; + int ret = check_fmt(ops, p->type); - ret = ops->vidioc_g_selection(file, fh, &s); - if (ret) - break; - p->defrect = s.r; + return ret ? ret : ops->vidioc_s_parm(file, fh, p); + } - /* setting trivial pixelaspect */ - p->pixelaspect.numerator = 1; - p->pixelaspect.denominator = 1; - } + static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_queryctrl *p = arg; + struct v4l2_fh *vfh = fh; + + if (vfh && vfh->ctrl_handler) + return v4l2_queryctrl(vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_queryctrl(vfd->ctrl_handler, p); + if (ops->vidioc_queryctrl) + return ops->vidioc_queryctrl(file, fh, p); + return -ENOTTY; + } - if (!ret) { - dbgrect(vfd, "bounds ", &p->bounds); - dbgrect(vfd, "defrect ", &p->defrect); - } - break; - } - case VIDIOC_G_JPEGCOMP: - { - struct v4l2_jpegcompression *p = arg; - - ret = ops->vidioc_g_jpegcomp(file, fh, p); - if (!ret) - dbgarg(cmd, "quality=%d, APPn=%d, " - "APP_len=%d, COM_len=%d, " - "jpeg_markers=%d\n", - p->quality, p->APPn, p->APP_len, - p->COM_len, p->jpeg_markers); - break; - } - case VIDIOC_S_JPEGCOMP: - { - struct v4l2_jpegcompression *p = arg; - - dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, " - "COM_len=%d, jpeg_markers=%d\n", - p->quality, p->APPn, p->APP_len, - p->COM_len, p->jpeg_markers); - ret = ops->vidioc_s_jpegcomp(file, fh, p); - break; - } - case VIDIOC_G_ENC_INDEX: - { - struct v4l2_enc_idx *p = arg; - - ret = ops->vidioc_g_enc_index(file, fh, p); - if (!ret) - dbgarg(cmd, "entries=%d, entries_cap=%d\n", - p->entries, p->entries_cap); - break; - } - case VIDIOC_ENCODER_CMD: - { - struct v4l2_encoder_cmd *p = arg; + static int v4l_querymenu(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_querymenu *p = arg; + struct v4l2_fh *vfh = fh; + + if (vfh && vfh->ctrl_handler) + return v4l2_querymenu(vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_querymenu(vfd->ctrl_handler, p); + if (ops->vidioc_querymenu) + return ops->vidioc_querymenu(file, fh, p); + return -ENOTTY; + } - ret = ops->vidioc_encoder_cmd(file, fh, p); - if (!ret) - dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); - break; + static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_control *p = arg; + struct v4l2_fh *vfh = fh; + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ctrl; + + if (vfh && vfh->ctrl_handler) + return v4l2_g_ctrl(vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_g_ctrl(vfd->ctrl_handler, p); + if (ops->vidioc_g_ctrl) + return ops->vidioc_g_ctrl(file, fh, p); + if (ops->vidioc_g_ext_ctrls == NULL) + return -ENOTTY; + + ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); + ctrls.count = 1; + ctrls.controls = &ctrl; + ctrl.id = p->id; + ctrl.value = p->value; + if (check_ext_ctrls(&ctrls, 1)) { + int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls); + + if (ret == 0) + p->value = ctrl.value; + return ret; } - case VIDIOC_TRY_ENCODER_CMD: - { - struct v4l2_encoder_cmd *p = arg; + return -EINVAL; + } - ret = ops->vidioc_try_encoder_cmd(file, fh, p); - if (!ret) - dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); - break; - } - case VIDIOC_DECODER_CMD: - { - struct v4l2_decoder_cmd *p = arg; + static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_control *p = arg; + struct v4l2_fh *vfh = fh; + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ctrl; + + if (vfh && vfh->ctrl_handler) + return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_s_ctrl(NULL, vfd->ctrl_handler, p); + if (ops->vidioc_s_ctrl) + return ops->vidioc_s_ctrl(file, fh, p); + if (ops->vidioc_s_ext_ctrls == NULL) + return -ENOTTY; + + ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); + ctrls.count = 1; + ctrls.controls = &ctrl; + ctrl.id = p->id; + ctrl.value = p->value; + if (check_ext_ctrls(&ctrls, 1)) + return ops->vidioc_s_ext_ctrls(file, fh, &ctrls); + return -EINVAL; + } - ret = ops->vidioc_decoder_cmd(file, fh, p); - if (!ret) - dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); - break; - } - case VIDIOC_TRY_DECODER_CMD: - { - struct v4l2_decoder_cmd *p = arg; + static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_ext_controls *p = arg; + struct v4l2_fh *vfh = fh; + + p->error_idx = p->count; + if (vfh && vfh->ctrl_handler) + return v4l2_g_ext_ctrls(vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_g_ext_ctrls(vfd->ctrl_handler, p); + if (ops->vidioc_g_ext_ctrls == NULL) + return -ENOTTY; + return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) : + -EINVAL; + } - ret = ops->vidioc_try_decoder_cmd(file, fh, p); - if (!ret) - dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); - break; - } - case VIDIOC_G_PARM: - { - struct v4l2_streamparm *p = arg; + static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_ext_controls *p = arg; + struct v4l2_fh *vfh = fh; + + p->error_idx = p->count; + if (vfh && vfh->ctrl_handler) + return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p); + if (ops->vidioc_s_ext_ctrls == NULL) + return -ENOTTY; + return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) : + -EINVAL; + } - if (ops->vidioc_g_parm) { - ret = check_fmt(ops, p->type); - if (ret) - break; - ret = ops->vidioc_g_parm(file, fh, p); - } else { - v4l2_std_id std = vfd->current_norm; + static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + struct v4l2_ext_controls *p = arg; + struct v4l2_fh *vfh = fh; + + p->error_idx = p->count; + if (vfh && vfh->ctrl_handler) + return v4l2_try_ext_ctrls(vfh->ctrl_handler, p); + if (vfd->ctrl_handler) + return v4l2_try_ext_ctrls(vfd->ctrl_handler, p); + if (ops->vidioc_try_ext_ctrls == NULL) + return -ENOTTY; + return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) : + -EINVAL; + } - ret = -EINVAL; - if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - break; + static int v4l_g_crop(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_crop *p = arg; + struct v4l2_selection s = { + .type = p->type, + }; + int ret; + + if (ops->vidioc_g_crop) + return ops->vidioc_g_crop(file, fh, p); + /* simulate capture crop using selection api */ + + /* crop means compose for output devices */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; + else + s.target = V4L2_SEL_TGT_CROP_ACTIVE; + + ret = ops->vidioc_g_selection(file, fh, &s); + + /* copying results to old structure on success */ + if (!ret) + p->c = s.r; + return ret; + } - ret = 0; - p->parm.capture.readbuffers = 2; - if (ops->vidioc_g_std) - ret = ops->vidioc_g_std(file, fh, &std); - if (ret == 0) - v4l2_video_std_frame_period(std, - &p->parm.capture.timeperframe); - } + static int v4l_s_crop(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_crop *p = arg; + struct v4l2_selection s = { + .type = p->type, + .r = p->c, + }; + + if (ops->vidioc_s_crop) + return ops->vidioc_s_crop(file, fh, p); + /* simulate capture crop using selection api */ + + /* crop means compose for output devices */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; + else + s.target = V4L2_SEL_TGT_CROP_ACTIVE; + + return ops->vidioc_s_selection(file, fh, &s); + } - dbgarg(cmd, "type=%d\n", p->type); - break; - } - case VIDIOC_S_PARM: - { - struct v4l2_streamparm *p = arg; + static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_cropcap *p = arg; + struct v4l2_selection s = { .type = p->type }; + int ret; - ret = check_fmt(ops, p->type); - if (ret) - break; + if (ops->vidioc_cropcap) + return ops->vidioc_cropcap(file, fh, p); - dbgarg(cmd, "type=%d\n", p->type); - ret = ops->vidioc_s_parm(file, fh, p); - break; - } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *p = arg; + /* obtaining bounds */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; + else + s.target = V4L2_SEL_TGT_CROP_BOUNDS; - p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? - V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - ret = ops->vidioc_g_tuner(file, fh, p); - if (!ret) - dbgarg(cmd, "index=%d, name=%s, type=%d, " - "capability=0x%x, rangelow=%d, " - "rangehigh=%d, signal=%d, afc=%d, " - "rxsubchans=0x%x, audmode=%d\n", - p->index, p->name, p->type, - p->capability, p->rangelow, - p->rangehigh, p->signal, p->afc, - p->rxsubchans, p->audmode); - break; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *p = arg; + ret = ops->vidioc_g_selection(file, fh, &s); + if (ret) + return ret; + p->bounds = s.r; - p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? - V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - dbgarg(cmd, "index=%d, name=%s, type=%d, " - "capability=0x%x, rangelow=%d, " - "rangehigh=%d, signal=%d, afc=%d, " - "rxsubchans=0x%x, audmode=%d\n", - p->index, p->name, p->type, - p->capability, p->rangelow, - p->rangehigh, p->signal, p->afc, - p->rxsubchans, p->audmode); - ret = ops->vidioc_s_tuner(file, fh, p); - break; - } - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *p = arg; + /* obtaining defrect */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) + s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; + else + s.target = V4L2_SEL_TGT_CROP_DEFAULT; - p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? - V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - ret = ops->vidioc_g_frequency(file, fh, p); - if (!ret) - dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n", - p->tuner, p->type, p->frequency); - break; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *p = arg; - enum v4l2_tuner_type type; + ret = ops->vidioc_g_selection(file, fh, &s); + if (ret) + return ret; + p->defrect = s.r; - type = (vfd->vfl_type == VFL_TYPE_RADIO) ? - V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n", - p->tuner, p->type, p->frequency); - if (p->type != type) - ret = -EINVAL; - else - ret = ops->vidioc_s_frequency(file, fh, p); - break; - } - case VIDIOC_G_SLICED_VBI_CAP: - { - struct v4l2_sliced_vbi_cap *p = arg; + /* setting trivial pixelaspect */ + p->pixelaspect.numerator = 1; + p->pixelaspect.denominator = 1; + return 0; + } - /* Clear up to type, everything after type is zerod already */ - memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type)); + static int v4l_log_status(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct video_device *vfd = video_devdata(file); + int ret; + + if (vfd->v4l2_dev) + pr_info("%s: ================= START STATUS =================\n", + vfd->v4l2_dev->name); + ret = ops->vidioc_log_status(file, fh); + if (vfd->v4l2_dev) + pr_info("%s: ================== END STATUS ==================\n", + vfd->v4l2_dev->name); + return ret; + } - dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); - ret = ops->vidioc_g_sliced_vbi_cap(file, fh, p); - if (!ret) - dbgarg2("service_set=%d\n", p->service_set); - break; - } - case VIDIOC_LOG_STATUS: - { - if (vfd->v4l2_dev) - pr_info("%s: ================= START STATUS =================\n", - vfd->v4l2_dev->name); - ret = ops->vidioc_log_status(file, fh); - if (vfd->v4l2_dev) - pr_info("%s: ================== END STATUS ==================\n", - vfd->v4l2_dev->name); - break; - } - case VIDIOC_DBG_G_REGISTER: - { + static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { #ifdef CONFIG_VIDEO_ADV_DEBUG - struct v4l2_dbg_register *p = arg; + struct v4l2_dbg_register *p = arg; - if (!capable(CAP_SYS_ADMIN)) - ret = -EPERM; - else - ret = ops->vidioc_g_register(file, fh, p); + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + return ops->vidioc_g_register(file, fh, p); + #else + return -ENOTTY; #endif - break; - } - case VIDIOC_DBG_S_REGISTER: - { + } + + static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { #ifdef CONFIG_VIDEO_ADV_DEBUG - struct v4l2_dbg_register *p = arg; + struct v4l2_dbg_register *p = arg; - if (!capable(CAP_SYS_ADMIN)) - ret = -EPERM; - else - ret = ops->vidioc_s_register(file, fh, p); + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + return ops->vidioc_s_register(file, fh, p); + #else + return -ENOTTY; #endif - break; - } - case VIDIOC_DBG_G_CHIP_IDENT: - { - struct v4l2_dbg_chip_ident *p = arg; - - p->ident = V4L2_IDENT_NONE; - p->revision = 0; - ret = ops->vidioc_g_chip_ident(file, fh, p); - if (!ret) - dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision); - break; - } - case VIDIOC_S_HW_FREQ_SEEK: - { - struct v4l2_hw_freq_seek *p = arg; - enum v4l2_tuner_type type; + } - type = (vfd->vfl_type == VFL_TYPE_RADIO) ? - V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - dbgarg(cmd, - "tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u\n", - p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing); - if (p->type != type) - ret = -EINVAL; - else - ret = ops->vidioc_s_hw_freq_seek(file, fh, p); - break; - } - case VIDIOC_ENUM_FRAMESIZES: - { - struct v4l2_frmsizeenum *p = arg; + static int v4l_dbg_g_chip_ident(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_dbg_chip_ident *p = arg; - ret = ops->vidioc_enum_framesizes(file, fh, p); - dbgarg(cmd, - "index=%d, pixelformat=%c%c%c%c, type=%d ", - p->index, - (p->pixel_format & 0xff), - (p->pixel_format >> 8) & 0xff, - (p->pixel_format >> 16) & 0xff, - (p->pixel_format >> 24) & 0xff, - p->type); - switch (p->type) { - case V4L2_FRMSIZE_TYPE_DISCRETE: - dbgarg3("width = %d, height=%d\n", - p->discrete.width, p->discrete.height); - break; - case V4L2_FRMSIZE_TYPE_STEPWISE: - dbgarg3("min %dx%d, max %dx%d, step %dx%d\n", - p->stepwise.min_width, p->stepwise.min_height, - p->stepwise.step_width, p->stepwise.step_height, - p->stepwise.max_width, p->stepwise.max_height); - break; - case V4L2_FRMSIZE_TYPE_CONTINUOUS: - dbgarg3("continuous\n"); - break; - default: - dbgarg3("- Unknown type!\n"); - } + p->ident = V4L2_IDENT_NONE; + p->revision = 0; + return ops->vidioc_g_chip_ident(file, fh, p); + } - break; - } - case VIDIOC_ENUM_FRAMEINTERVALS: - { - struct v4l2_frmivalenum *p = arg; - - ret = ops->vidioc_enum_frameintervals(file, fh, p); - dbgarg(cmd, - "index=%d, pixelformat=%d, width=%d, height=%d, type=%d ", - p->index, p->pixel_format, - p->width, p->height, p->type); - switch (p->type) { - case V4L2_FRMIVAL_TYPE_DISCRETE: - dbgarg2("fps=%d/%d\n", - p->discrete.numerator, - p->discrete.denominator); - break; - case V4L2_FRMIVAL_TYPE_STEPWISE: - dbgarg2("min=%d/%d, max=%d/%d, step=%d/%d\n", - p->stepwise.min.numerator, - p->stepwise.min.denominator, - p->stepwise.max.numerator, - p->stepwise.max.denominator, - p->stepwise.step.numerator, - p->stepwise.step.denominator); - break; - case V4L2_FRMIVAL_TYPE_CONTINUOUS: - dbgarg2("continuous\n"); - break; - default: - dbgarg2("- Unknown type!\n"); - } - break; - } - case VIDIOC_ENUM_DV_PRESETS: - { - struct v4l2_dv_enum_preset *p = arg; - - ret = ops->vidioc_enum_dv_presets(file, fh, p); - if (!ret) - dbgarg(cmd, - "index=%d, preset=%d, name=%s, width=%d," - " height=%d ", - p->index, p->preset, p->name, p->width, - p->height); - break; - } - case VIDIOC_S_DV_PRESET: - { - struct v4l2_dv_preset *p = arg; + static int v4l_dqevent(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK); + } - dbgarg(cmd, "preset=%d\n", p->preset); - ret = ops->vidioc_s_dv_preset(file, fh, p); - break; - } - case VIDIOC_G_DV_PRESET: - { - struct v4l2_dv_preset *p = arg; + static int v4l_subscribe_event(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + return ops->vidioc_subscribe_event(fh, arg); + } - ret = ops->vidioc_g_dv_preset(file, fh, p); - if (!ret) - dbgarg(cmd, "preset=%d\n", p->preset); - break; - } - case VIDIOC_QUERY_DV_PRESET: - { - struct v4l2_dv_preset *p = arg; + static int v4l_unsubscribe_event(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + return ops->vidioc_unsubscribe_event(fh, arg); + } - ret = ops->vidioc_query_dv_preset(file, fh, p); - if (!ret) - dbgarg(cmd, "preset=%d\n", p->preset); - break; - } - case VIDIOC_S_DV_TIMINGS: - { - struct v4l2_dv_timings *p = arg; - - dbgtimings(vfd, p); - switch (p->type) { - case V4L2_DV_BT_656_1120: - ret = ops->vidioc_s_dv_timings(file, fh, p); - break; - default: - ret = -EINVAL; - break; - } - break; - } - case VIDIOC_G_DV_TIMINGS: - { - struct v4l2_dv_timings *p = arg; + static int v4l_g_sliced_vbi_cap(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { + struct v4l2_sliced_vbi_cap *p = arg; - ret = ops->vidioc_g_dv_timings(file, fh, p); - if (!ret) - dbgtimings(vfd, p); - break; - } - case VIDIOC_ENUM_DV_TIMINGS: - { - struct v4l2_enum_dv_timings *p = arg; + /* Clear up to type, everything after type is zeroed already */ + memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type)); - if (!ops->vidioc_enum_dv_timings) - break; + return ops->vidioc_g_sliced_vbi_cap(file, fh, p); + } - ret = ops->vidioc_enum_dv_timings(file, fh, p); - if (!ret) { - dbgarg(cmd, "index=%d: ", p->index); - dbgtimings(vfd, &p->timings); - } - break; + struct v4l2_ioctl_info { + unsigned int ioctl; + u32 flags; + const char * const name; + union { + u32 offset; + int (*func)(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *p); - }; ++ } u; + void (*debug)(const void *arg, bool write_only); + }; + + /* This control needs a priority check */ + #define INFO_FL_PRIO (1 << 0) + /* This control can be valid if the filehandle passes a control handler. */ + #define INFO_FL_CTRL (1 << 1) + /* This is a standard ioctl, no need for special code */ + #define INFO_FL_STD (1 << 2) + /* This is ioctl has its own function */ + #define INFO_FL_FUNC (1 << 3) + /* Queuing ioctl */ + #define INFO_FL_QUEUE (1 << 4) + /* Zero struct from after the field to the end */ + #define INFO_FL_CLEAR(v4l2_struct, field) \ + ((offsetof(struct v4l2_struct, field) + \ + sizeof(((struct v4l2_struct *)0)->field)) << 16) + #define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16) + + #define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags) \ + [_IOC_NR(_ioctl)] = { \ + .ioctl = _ioctl, \ + .flags = _flags | INFO_FL_STD, \ + .name = #_ioctl, \ - .offset = offsetof(struct v4l2_ioctl_ops, _vidioc), \ ++ .u.offset = offsetof(struct v4l2_ioctl_ops, _vidioc), \ + .debug = _debug, \ + } + + #define IOCTL_INFO_FNC(_ioctl, _func, _debug, _flags) \ + [_IOC_NR(_ioctl)] = { \ + .ioctl = _ioctl, \ + .flags = _flags | INFO_FL_FUNC, \ + .name = #_ioctl, \ - .func = _func, \ ++ .u.func = _func, \ + .debug = _debug, \ } - case VIDIOC_QUERY_DV_TIMINGS: - { - struct v4l2_dv_timings *p = arg; - if (!ops->vidioc_query_dv_timings) - break; + static struct v4l2_ioctl_info v4l2_ioctls[] = { + IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0), + IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)), + IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, INFO_FL_CLEAR(v4l2_format, type)), + IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE), + IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)), + IOCTL_INFO_STD(VIDIOC_G_FBUF, vidioc_g_fbuf, v4l_print_framebuffer, 0), + IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_OVERLAY, vidioc_overlay, v4l_print_u32, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE), + IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE), + IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), + IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), + IOCTL_INFO_FNC(VIDIOC_G_PARM, v4l_g_parm, v4l_print_streamparm, INFO_FL_CLEAR(v4l2_streamparm, type)), + IOCTL_INFO_FNC(VIDIOC_S_PARM, v4l_s_parm, v4l_print_streamparm, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_G_STD, v4l_g_std, v4l_print_std, 0), + IOCTL_INFO_FNC(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)), + IOCTL_INFO_FNC(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)), + IOCTL_INFO_FNC(VIDIOC_G_CTRL, v4l_g_ctrl, v4l_print_control, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_control, id)), + IOCTL_INFO_FNC(VIDIOC_S_CTRL, v4l_s_ctrl, v4l_print_control, INFO_FL_PRIO | INFO_FL_CTRL), + IOCTL_INFO_FNC(VIDIOC_G_TUNER, v4l_g_tuner, v4l_print_tuner, INFO_FL_CLEAR(v4l2_tuner, index)), + IOCTL_INFO_FNC(VIDIOC_S_TUNER, v4l_s_tuner, v4l_print_tuner, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_AUDIO, vidioc_g_audio, v4l_print_audio, 0), + IOCTL_INFO_STD(VIDIOC_S_AUDIO, vidioc_s_audio, v4l_print_audio, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_QUERYCTRL, v4l_queryctrl, v4l_print_queryctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)), + IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)), + IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0), + IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0), + IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)), + IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0), + IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_MODULATOR, vidioc_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)), + IOCTL_INFO_STD(VIDIOC_S_MODULATOR, vidioc_s_modulator, v4l_print_modulator, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)), + IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)), + IOCTL_INFO_FNC(VIDIOC_G_CROP, v4l_g_crop, v4l_print_crop, INFO_FL_CLEAR(v4l2_crop, type)), + IOCTL_INFO_FNC(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, 0), + IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp, v4l_print_jpegcompression, 0), + IOCTL_INFO_STD(VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp, v4l_print_jpegcompression, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0), + IOCTL_INFO_FNC(VIDIOC_TRY_FMT, v4l_try_fmt, v4l_print_format, 0), + IOCTL_INFO_STD(VIDIOC_ENUMAUDIO, vidioc_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)), + IOCTL_INFO_STD(VIDIOC_ENUMAUDOUT, vidioc_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)), + IOCTL_INFO_FNC(VIDIOC_G_PRIORITY, v4l_g_priority, v4l_print_u32, 0), + IOCTL_INFO_FNC(VIDIOC_S_PRIORITY, v4l_s_priority, v4l_print_u32, INFO_FL_PRIO), + IOCTL_INFO_FNC(VIDIOC_G_SLICED_VBI_CAP, v4l_g_sliced_vbi_cap, v4l_print_sliced_vbi_cap, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)), + IOCTL_INFO_FNC(VIDIOC_LOG_STATUS, v4l_log_status, v4l_print_newline, 0), + IOCTL_INFO_FNC(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL), + IOCTL_INFO_FNC(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL), + IOCTL_INFO_FNC(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, 0), + IOCTL_INFO_STD(VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes, v4l_print_frmsizeenum, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)), + IOCTL_INFO_STD(VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals, v4l_print_frmivalenum, INFO_FL_CLEAR(v4l2_frmivalenum, height)), + IOCTL_INFO_STD(VIDIOC_G_ENC_INDEX, vidioc_g_enc_index, v4l_print_enc_idx, 0), + IOCTL_INFO_STD(VIDIOC_ENCODER_CMD, vidioc_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), + IOCTL_INFO_STD(VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), + IOCTL_INFO_STD(VIDIOC_DECODER_CMD, vidioc_decoder_cmd, v4l_print_decoder_cmd, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd, v4l_print_decoder_cmd, 0), + IOCTL_INFO_FNC(VIDIOC_DBG_S_REGISTER, v4l_dbg_s_register, v4l_print_dbg_register, 0), + IOCTL_INFO_FNC(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0), + IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_IDENT, v4l_dbg_g_chip_ident, v4l_print_dbg_chip_ident, 0), + IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets, v4l_print_dv_enum_presets, 0), + IOCTL_INFO_STD(VIDIOC_S_DV_PRESET, vidioc_s_dv_preset, v4l_print_dv_preset, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_DV_PRESET, vidioc_g_dv_preset, v4l_print_dv_preset, 0), + IOCTL_INFO_STD(VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset, v4l_print_dv_preset, 0), + IOCTL_INFO_STD(VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO), + IOCTL_INFO_STD(VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings, v4l_print_dv_timings, 0), + IOCTL_INFO_FNC(VIDIOC_DQEVENT, v4l_dqevent, v4l_print_event, 0), + IOCTL_INFO_FNC(VIDIOC_SUBSCRIBE_EVENT, v4l_subscribe_event, v4l_print_event_subscription, 0), + IOCTL_INFO_FNC(VIDIOC_UNSUBSCRIBE_EVENT, v4l_unsubscribe_event, v4l_print_event_subscription, 0), + IOCTL_INFO_FNC(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO | INFO_FL_QUEUE), + IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, INFO_FL_QUEUE), + IOCTL_INFO_STD(VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings, v4l_print_enum_dv_timings, 0), + IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, 0), + IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, 0), + }; + #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) - ret = ops->vidioc_query_dv_timings(file, fh, p); - if (!ret) - dbgtimings(vfd, p); - break; - } - case VIDIOC_DV_TIMINGS_CAP: - { - struct v4l2_dv_timings_cap *p = arg; + bool v4l2_is_known_ioctl(unsigned int cmd) + { + if (_IOC_NR(cmd) >= V4L2_IOCTLS) + return false; + return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd; + } - if (!ops->vidioc_dv_timings_cap) - break; + struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, unsigned cmd) + { + if (_IOC_NR(cmd) >= V4L2_IOCTLS) + return vdev->lock; + if (test_bit(_IOC_NR(cmd), vdev->disable_locking)) + return NULL; + if (vdev->queue && vdev->queue->lock && + (v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE)) + return vdev->queue->lock; + return vdev->lock; + } - ret = ops->vidioc_dv_timings_cap(file, fh, p); - if (ret) - break; - switch (p->type) { - case V4L2_DV_BT_656_1120: - dbgarg(cmd, - "type=%d, width=%u-%u, height=%u-%u, " - "pixelclock=%llu-%llu, standards=%x, capabilities=%x ", - p->type, - p->bt.min_width, p->bt.max_width, - p->bt.min_height, p->bt.max_height, - p->bt.min_pixelclock, p->bt.max_pixelclock, - p->bt.standards, p->bt.capabilities); - break; - default: - dbgarg(cmd, "unknown type "); - break; - } - break; - } - case VIDIOC_DQEVENT: - { - struct v4l2_event *ev = arg; + /* Common ioctl debug function. This function can be used by + external ioctl messages as well as internal V4L ioctl */ + void v4l_printk_ioctl(const char *prefix, unsigned int cmd) + { + const char *dir, *type; - ret = v4l2_event_dequeue(fh, ev, file->f_flags & O_NONBLOCK); - if (ret < 0) { - dbgarg(cmd, "no pending events?"); - break; - } - dbgarg(cmd, - "pending=%d, type=0x%8.8x, sequence=%d, " - "timestamp=%lu.%9.9lu ", - ev->pending, ev->type, ev->sequence, - ev->timestamp.tv_sec, ev->timestamp.tv_nsec); - break; - } - case VIDIOC_SUBSCRIBE_EVENT: - { - struct v4l2_event_subscription *sub = arg; + if (prefix) + printk(KERN_DEBUG "%s: ", prefix); - ret = ops->vidioc_subscribe_event(fh, sub); - if (ret < 0) { - dbgarg(cmd, "failed, ret=%ld", ret); - break; - } - dbgarg(cmd, "type=0x%8.8x", sub->type); + switch (_IOC_TYPE(cmd)) { + case 'd': + type = "v4l2_int"; break; - } - case VIDIOC_UNSUBSCRIBE_EVENT: - { - struct v4l2_event_subscription *sub = arg; - - ret = ops->vidioc_unsubscribe_event(fh, sub); - if (ret < 0) { - dbgarg(cmd, "failed, ret=%ld", ret); + case 'V': + if (_IOC_NR(cmd) >= V4L2_IOCTLS) { + type = "v4l2"; break; } - dbgarg(cmd, "type=0x%8.8x", sub->type); + pr_cont("%s", v4l2_ioctls[_IOC_NR(cmd)].name); + return; + default: + type = "unknown"; break; } - case VIDIOC_CREATE_BUFS: - { - struct v4l2_create_buffers *create = arg; - ret = check_fmt(ops, create->format.type); - if (ret) - break; + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: dir = "--"; break; + case _IOC_READ: dir = "r-"; break; + case _IOC_WRITE: dir = "-w"; break; + case _IOC_READ | _IOC_WRITE: dir = "rw"; break; + default: dir = "*ERR*"; break; + } + pr_cont("%s ioctl '%c', dir=%s, #%d (0x%08x)", + type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd); + } + EXPORT_SYMBOL(v4l_printk_ioctl); - ret = ops->vidioc_create_bufs(file, fh, create); + static long __video_do_ioctl(struct file *file, + unsigned int cmd, void *arg) + { + struct video_device *vfd = video_devdata(file); + const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; + bool write_only = false; + struct v4l2_ioctl_info default_info; + const struct v4l2_ioctl_info *info; + void *fh = file->private_data; + struct v4l2_fh *vfh = NULL; + int use_fh_prio = 0; + int debug = vfd->debug; + long ret = -ENOTTY; - dbgarg(cmd, "count=%d @ %d\n", create->count, create->index); - break; + if (ops == NULL) { + pr_warn("%s: has no ioctl_ops.\n", + video_device_node_name(vfd)); + return ret; } - case VIDIOC_PREPARE_BUF: - { - struct v4l2_buffer *b = arg; - ret = check_fmt(ops, b->type); - if (ret) - break; + if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { + vfh = file->private_data; + use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); + } - ret = ops->vidioc_prepare_buf(file, fh, b); + if (v4l2_is_known_ioctl(cmd)) { + info = &v4l2_ioctls[_IOC_NR(cmd)]; - dbgarg(cmd, "index=%d", b->index); - break; - } - default: - if (!ops->vidioc_default) - break; - ret = ops->vidioc_default(file, fh, use_fh_prio ? - v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0, - cmd, arg); - break; - } /* switch */ + if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) && + !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler)) + goto done; - if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { - if (ret < 0) { - v4l_print_ioctl(vfd->name, cmd); - printk(KERN_CONT " error %ld\n", ret); + if (use_fh_prio && (info->flags & INFO_FL_PRIO)) { + ret = v4l2_prio_check(vfd->prio, vfh->prio); + if (ret) + goto done; + } + } else { + default_info.ioctl = cmd; + default_info.flags = 0; + default_info.debug = v4l_print_default; + info = &default_info; + } + + write_only = _IOC_DIR(cmd) == _IOC_WRITE; + if (write_only && debug > V4L2_DEBUG_IOCTL) { + v4l_printk_ioctl(video_device_node_name(vfd), cmd); + pr_cont(": "); + info->debug(arg, write_only); + } + if (info->flags & INFO_FL_STD) { + typedef int (*vidioc_op)(struct file *file, void *fh, void *p); + const void *p = vfd->ioctl_ops; - const vidioc_op *vidioc = p + info->offset; ++ const vidioc_op *vidioc = p + info->u.offset; + + ret = (*vidioc)(file, fh, arg); + } else if (info->flags & INFO_FL_FUNC) { - ret = info->func(ops, file, fh, arg); ++ ret = info->u.func(ops, file, fh, arg); + } else if (!ops->vidioc_default) { + ret = -ENOTTY; + } else { + ret = ops->vidioc_default(file, fh, + use_fh_prio ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0, + cmd, arg); + } + + done: + if (debug) { + if (write_only && debug > V4L2_DEBUG_IOCTL) { + if (ret < 0) + printk(KERN_DEBUG "%s: error %ld\n", + video_device_node_name(vfd), ret); + return ret; + } + v4l_printk_ioctl(video_device_node_name(vfd), cmd); + if (ret < 0) + pr_cont(": error %ld\n", ret); + else if (debug == V4L2_DEBUG_IOCTL) + pr_cont("\n"); + else if (_IOC_DIR(cmd) == _IOC_NONE) + info->debug(arg, write_only); + else { + pr_cont(": "); + info->debug(arg, write_only); } }