diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-14 07:22:22 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-14 07:22:22 +0400 |
commit | d8c532c40721f7507896d202b8cae3b3642d2b0d (patch) | |
tree | 42b1ce76671eb85324281ed93491432f4523f983 /drivers/media/usb/uvc/uvc_v4l2.c | |
parent | e777d192ffb9f2929d547a2f8a5f65b7db7a9552 (diff) | |
parent | 77c53d0b56264a8fc5844e087ad15fffe20c299d (diff) | |
download | linux-d8c532c40721f7507896d202b8cae3b3642d2b0d.tar.xz |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- Missing MAINTAINERS entries were added for several drivers
- Adds V4L2 support for DMABUF handling, allowing zero-copy buffer
sharing between V4L2 devices and GPU
- Got rid of all warnings when compiling with W=1 on x86
- Add a new driver for Exynos hardware (s3c-camif)
- Several bug fixes, cleanups and driver improvements
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (243 commits)
[media] omap3isp: Replace cpu_is_omap3630() with ISP revision check
[media] omap3isp: Prepare/unprepare clocks before/after enable/disable
[media] omap3isp: preview: Add support for 8-bit formats at the sink pad
[media] omap3isp: Replace printk with dev_*
[media] omap3isp: Find source pad from external entity
[media] omap3isp: Configure CSI-2 phy based on platform data
[media] omap3isp: Add PHY routing configuration
[media] omap3isp: Add CSI configuration registers from control block to ISP resources
[media] omap3isp: Remove unneeded module memory address definitions
[media] omap3isp: Use monotonic timestamps for statistics buffers
[media] uvcvideo: Fix control value clamping for unsigned integer controls
[media] uvcvideo: Mark first output terminal as default video node
[media] uvcvideo: Add VIDIOC_[GS]_PRIORITY support
[media] uvcvideo: Return -ENOTTY for unsupported ioctls
[media] uvcvideo: Set device_caps in VIDIOC_QUERYCAP
[media] uvcvideo: Don't fail when an unsupported format is requested
[media] uvcvideo: Return -EACCES when trying to access a read/write-only control
[media] uvcvideo: Set error_idx properly for extended controls API failures
[media] rtl28xxu: add NOXON DAB/DAB+ USB dongle rev 2
[media] fc2580: write some registers conditionally
...
Diffstat (limited to 'drivers/media/usb/uvc/uvc_v4l2.c')
-rw-r--r-- | drivers/media/usb/uvc/uvc_v4l2.c | 89 |
1 files changed, 71 insertions, 18 deletions
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index f00db3060e0e..8e056046bc20 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -165,17 +165,18 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, fcc[0], fcc[1], fcc[2], fcc[3], fmt->fmt.pix.width, fmt->fmt.pix.height); - /* Check if the hardware supports the requested format. */ + /* Check if the hardware supports the requested format, use the default + * format otherwise. + */ for (i = 0; i < stream->nformats; ++i) { format = &stream->format[i]; if (format->fcc == fmt->fmt.pix.pixelformat) break; } - if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) { - uvc_trace(UVC_TRACE_FORMAT, "Unsupported format 0x%08x.\n", - fmt->fmt.pix.pixelformat); - return -EINVAL; + if (i == stream->nformats) { + format = stream->def_format; + fmt->fmt.pix.pixelformat = format->fcc; } /* Find the closest image size. The distance between image sizes is @@ -564,15 +565,30 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->version = LINUX_VERSION_CODE; + cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING + | chain->caps; if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE - | V4L2_CAP_STREAMING; + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE + | V4L2_CAP_STREAMING; else - cap->capabilities = V4L2_CAP_VIDEO_OUTPUT - | V4L2_CAP_STREAMING; + cap->device_caps = V4L2_CAP_VIDEO_OUTPUT + | V4L2_CAP_STREAMING; break; } + /* Priority */ + case VIDIOC_G_PRIORITY: + *(u32 *)arg = v4l2_prio_max(vdev->prio); + break; + + case VIDIOC_S_PRIORITY: + ret = v4l2_prio_check(vdev->prio, handle->vfh.prio); + if (ret < 0) + return ret; + + return v4l2_prio_change(vdev->prio, &handle->vfh.prio, + *(u32 *)arg); + /* Get, Set & Query control */ case VIDIOC_QUERYCTRL: return uvc_query_v4l2_ctrl(chain, arg); @@ -591,8 +607,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) ret = uvc_ctrl_get(chain, &xctrl); uvc_ctrl_rollback(handle); - if (ret >= 0) - ctrl->value = xctrl.value; + if (ret < 0) + return ret == -ENOENT ? -EINVAL : ret; + + ctrl->value = xctrl.value; break; } @@ -601,6 +619,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_control *ctrl = arg; struct v4l2_ext_control xctrl; + ret = v4l2_prio_check(vdev->prio, handle->vfh.prio); + if (ret < 0) + return ret; + memset(&xctrl, 0, sizeof xctrl); xctrl.id = ctrl->id; xctrl.value = ctrl->value; @@ -612,7 +634,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) ret = uvc_ctrl_set(chain, &xctrl); if (ret < 0) { uvc_ctrl_rollback(handle); - return ret; + return ret == -ENOENT ? -EINVAL : ret; } ret = uvc_ctrl_commit(handle, &xctrl, 1); if (ret == 0) @@ -637,8 +659,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) ret = uvc_ctrl_get(chain, ctrl); if (ret < 0) { uvc_ctrl_rollback(handle); - ctrls->error_idx = i; - return ret; + ctrls->error_idx = ret == -ENOENT + ? ctrls->count : i; + return ret == -ENOENT ? -EINVAL : ret; } } ctrls->error_idx = 0; @@ -647,6 +670,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) } case VIDIOC_S_EXT_CTRLS: + ret = v4l2_prio_check(vdev->prio, handle->vfh.prio); + if (ret < 0) + return ret; + /* Fall through */ case VIDIOC_TRY_EXT_CTRLS: { struct v4l2_ext_controls *ctrls = arg; @@ -661,8 +688,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) ret = uvc_ctrl_set(chain, ctrl); if (ret < 0) { uvc_ctrl_rollback(handle); - ctrls->error_idx = i; - return ret; + ctrls->error_idx = (ret == -ENOENT && + cmd == VIDIOC_S_EXT_CTRLS) + ? ctrls->count : i; + return ret == -ENOENT ? -EINVAL : ret; } } @@ -739,6 +768,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { u32 input = *(u32 *)arg + 1; + ret = v4l2_prio_check(vdev->prio, handle->vfh.prio); + if (ret < 0) + return ret; + if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; @@ -792,6 +825,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) } case VIDIOC_S_FMT: + ret = v4l2_prio_check(vdev->prio, handle->vfh.prio); + if (ret < 0) + return ret; + if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; @@ -894,6 +931,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) return uvc_v4l2_get_streamparm(stream, arg); case VIDIOC_S_PARM: + ret = v4l2_prio_check(vdev->prio, handle->vfh.prio); + if (ret < 0) + return ret; + if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; @@ -924,10 +965,14 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_G_CROP: case VIDIOC_S_CROP: - return -EINVAL; + return -ENOTTY; /* Buffers & streaming */ case VIDIOC_REQBUFS: + ret = v4l2_prio_check(vdev->prio, handle->vfh.prio); + if (ret < 0) + return ret; + if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; @@ -973,6 +1018,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (*type != stream->type) return -EINVAL; + ret = v4l2_prio_check(vdev->prio, handle->vfh.prio); + if (ret < 0) + return ret; + if (!uvc_has_privileges(handle)) return -EBUSY; @@ -991,6 +1040,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (*type != stream->type) return -EINVAL; + ret = v4l2_prio_check(vdev->prio, handle->vfh.prio); + if (ret < 0) + return ret; + if (!uvc_has_privileges(handle)) return -EBUSY; @@ -1030,7 +1083,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_ENUMOUTPUT: uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd); - return -EINVAL; + return -ENOTTY; case UVCIOC_CTRL_MAP: return uvc_ioctl_ctrl_map(chain, arg); |