diff mbox

uvcvideo: add fix suspend/resume quirk for Microdia camera

Message ID CACVXFVM=P7dongW660zmcSdapyqYz3Yr0R4DUGbQtQEKUG_tcw@mail.gmail.com (mailing list archive)
State Superseded
Headers show

Commit Message

Ming Lei July 15, 2011, 1:53 p.m. UTC
Hi,

On Thu, Jul 14, 2011 at 11:03 PM, Alan Stern <stern@rowland.harvard.edu> wrote:

> More likely, the reset erases some device setting that uvcvideo
> installed while binding.  Evidently uvcvideo does not re-install the
> setting during reset-resume; this is probably a bug in the driver.

Alan, you are right.

I think I have found the root cause. Given many devices can't
handle set_interface(0) if the interfaces were already in altsetting 0,
usb_reset_and_verify_device does not run set_interface(0). So we
need to do it in .reset_resume handler of uvc driver and it is always
safe for uvc devices.

I have tested the below patch, and it can make the uvc device work
well after rpm resume and system resume(reset resume), both in
streaming on and off case.

Alan, Laurent, if you have no objections, I will submit a formal one.

 	uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "



thanks,

Comments

Ming Lei July 15, 2011, 2:44 p.m. UTC | #1
Hi,

On Fri, Jul 15, 2011 at 10:27 PM, Alan Stern <stern@rowland.harvard.edu> wrote:

> This is fine with me.  However, it is strange that the Set-Interface
> request is necessary.  After being reset, the device should
> automatically be in altsetting 0 for all interfaces.

For uvc devices, seems it is not strange, see uvc_video_init(), which
is called in .probe path and executes Set-Interface 0 first, then starts
to get/set video control.

thanks,
diff mbox

Patch

diff --git a/drivers/media/video/uvc/uvc_driver.c
b/drivers/media/video/uvc/uvc_driver.c
index b6eae48..4055dfc 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -1959,8 +1959,12 @@  static int __uvc_resume(struct usb_interface
*intf, int reset)
 	}

 	list_for_each_entry(stream, &dev->streams, list) {
-		if (stream->intf == intf)
+		if (stream->intf == intf) {
+			if (reset)
+				usb_set_interface(stream->dev->udev,
+					stream->intfnum, 0);
 			return uvc_video_resume(stream);
+		}
 	}