From e5fd91f1ef340da553f7a79da9540c3db711c937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Fabian=20Silva=20Delgado?= Date: Tue, 8 Sep 2015 01:01:14 -0300 Subject: Linux-libre 4.2-gnu --- drivers/media/usb/uvc/uvc_driver.c | 2 -- drivers/media/usb/uvc/uvc_queue.c | 12 ++++++++++++ drivers/media/usb/uvc/uvc_v4l2.c | 16 +++++++++++++--- drivers/media/usb/uvc/uvc_video.c | 8 ++++++++ drivers/media/usb/uvc/uvcvideo.h | 7 ++----- 5 files changed, 35 insertions(+), 10 deletions(-) (limited to 'drivers/media/usb/uvc') diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 5970dd6a1..4b5b3e8fb 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1967,8 +1967,6 @@ static void uvc_disconnect(struct usb_interface *intf) UVC_SC_VIDEOSTREAMING) return; - dev->state |= UVC_DEV_DISCONNECTED; - uvc_unregister_video(dev); } diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index 87a19f33e..f16b9b426 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -270,6 +270,18 @@ int uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) return ret; } +int uvc_export_buffer(struct uvc_video_queue *queue, + struct v4l2_exportbuffer *exp) +{ + int ret; + + mutex_lock(&queue->mutex); + ret = vb2_expbuf(&queue->queue, exp); + mutex_unlock(&queue->mutex); + + return ret; +} + int uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf, int nonblocking) { diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index c4b1ac675..2764f4360 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -483,9 +483,6 @@ static int uvc_v4l2_open(struct file *file) uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); stream = video_drvdata(file); - if (stream->dev->state & UVC_DEV_DISCONNECTED) - return -ENODEV; - ret = usb_autopm_get_interface(stream->dev->intf); if (ret < 0) return ret; @@ -723,6 +720,18 @@ static int uvc_ioctl_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) return uvc_queue_buffer(&stream->queue, buf); } +static int uvc_ioctl_expbuf(struct file *file, void *fh, + struct v4l2_exportbuffer *exp) +{ + struct uvc_fh *handle = fh; + struct uvc_streaming *stream = handle->stream; + + if (!uvc_has_privileges(handle)) + return -EBUSY; + + return uvc_export_buffer(&stream->queue, exp); +} + static int uvc_ioctl_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) { struct uvc_fh *handle = fh; @@ -1478,6 +1487,7 @@ const struct v4l2_ioctl_ops uvc_ioctl_ops = { .vidioc_reqbufs = uvc_ioctl_reqbufs, .vidioc_querybuf = uvc_ioctl_querybuf, .vidioc_qbuf = uvc_ioctl_qbuf, + .vidioc_expbuf = uvc_ioctl_expbuf, .vidioc_dqbuf = uvc_ioctl_dqbuf, .vidioc_create_bufs = uvc_ioctl_create_bufs, .vidioc_streamon = uvc_ioctl_streamon, diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 20ccc9d31..f839654ea 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -119,6 +119,14 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, ctrl->dwMaxVideoFrameSize = frame->dwMaxVideoFrameBufferSize; + /* The "TOSHIBA Web Camera - 5M" Chicony device (04f2:b50b) seems to + * compute the bandwidth on 16 bits and erroneously sign-extend it to + * 32 bits, resulting in a huge bandwidth value. Detect and fix that + * condition by setting the 16 MSBs to 0 when they're all equal to 1. + */ + if ((ctrl->dwMaxPayloadTransferSize & 0xffff0000) == 0xffff0000) + ctrl->dwMaxPayloadTransferSize &= ~0xffff0000; + if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) && stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH && stream->intf->num_altsetting > 1) { diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 1b594c203..816dd1a0f 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -517,10 +517,6 @@ struct uvc_streaming { } clock; }; -enum uvc_device_state { - UVC_DEV_DISCONNECTED = 1, -}; - struct uvc_device { struct usb_device *udev; struct usb_interface *intf; @@ -529,7 +525,6 @@ struct uvc_device { int intfnum; char name[32]; - enum uvc_device_state state; struct mutex lock; /* Protects users */ unsigned int users; atomic_t nmappings; @@ -635,6 +630,8 @@ extern int uvc_create_buffers(struct uvc_video_queue *queue, struct v4l2_create_buffers *v4l2_cb); extern int uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf); +extern int uvc_export_buffer(struct uvc_video_queue *queue, + struct v4l2_exportbuffer *exp); extern int uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf, int nonblocking); extern int uvc_queue_streamon(struct uvc_video_queue *queue, -- cgit v1.2.3