aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/uvc/uvc_video.c
diff options
context:
space:
mode:
authorOleksij Rempel <linux@rempel-privat.de>2014-02-16 04:59:32 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-03-05 14:57:46 -0500
commitb1e43f232698274871e1358c276d7b0242a7d607 (patch)
tree9a59a93a6763d58b412683ea4b63db2572805b68 /drivers/media/usb/uvc/uvc_video.c
parentbfd0306462fdbc5e0a8c6999aef9dde0f9745399 (diff)
[media] uvcvideo: Do not use usb_set_interface on bulk EP
The UVC specification uses alternate setting selection to notify devices of stream start/stop. This breaks when using bulk-based devices, as the video streaming interface has a single alternate setting in that case, making video stream start and video stream stop events to appear identical to the device. Bulk-based devices are thus not well supported by UVC. The webcam built in the Asus Zenbook UX302LA ignores the set interface request and will keep the video stream enabled when the driver tries to stop it. If USB autosuspend is enabled the device will then be suspended and will crash, requiring a cold reboot. USB trace capture showed that Windows sends a CLEAR_FEATURE(HALT) request to the bulk endpoint when stopping the stream instead of selecting alternate setting 0. The camera then behaves correctly, and thus seems to require that behaviour. Replace selection of alternate setting 0 with clearing of the endpoint halt feature at video stream stop for bulk-based devices. Let's refrain from blaming Microsoft this time, as it's not clear whether this Windows-specific but USB-compliant behaviour was specifically developed to handle bulkd-based UVC devices, or if the camera just took advantage of it. CC: stable@vger.kernel.org Signed-off-by: Oleksij Rempel <linux@rempel-privat.de> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/usb/uvc/uvc_video.c')
-rw-r--r--drivers/media/usb/uvc/uvc_video.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 103cd4e91855..8d52baf5952b 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1850,7 +1850,25 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
1850 1850
1851 if (!enable) { 1851 if (!enable) {
1852 uvc_uninit_video(stream, 1); 1852 uvc_uninit_video(stream, 1);
1853 usb_set_interface(stream->dev->udev, stream->intfnum, 0); 1853 if (stream->intf->num_altsetting > 1) {
1854 usb_set_interface(stream->dev->udev,
1855 stream->intfnum, 0);
1856 } else {
1857 /* UVC doesn't specify how to inform a bulk-based device
1858 * when the video stream is stopped. Windows sends a
1859 * CLEAR_FEATURE(HALT) request to the video streaming
1860 * bulk endpoint, mimic the same behaviour.
1861 */
1862 unsigned int epnum = stream->header.bEndpointAddress
1863 & USB_ENDPOINT_NUMBER_MASK;
1864 unsigned int dir = stream->header.bEndpointAddress
1865 & USB_ENDPOINT_DIR_MASK;
1866 unsigned int pipe;
1867
1868 pipe = usb_sndbulkpipe(stream->dev->udev, epnum) | dir;
1869 usb_clear_halt(stream->dev->udev, pipe);
1870 }
1871
1854 uvc_queue_enable(&stream->queue, 0); 1872 uvc_queue_enable(&stream->queue, 0);
1855 uvc_video_clock_cleanup(stream); 1873 uvc_video_clock_cleanup(stream);
1856 return 0; 1874 return 0;