I'd like to present so-called "reset patch" for revision 64 of split-branch.
Enjoy

diff -u old/uvc_driver.c new/uvc_driver.c
--- old/uvc_driver.c    2006-11-04 22:14:32.000000000 +0300
+++ new/uvc_driver.c    2006-11-04 02:17:08.000000000 +0300
@@ -147,6 +147,52 @@
        return 0;
 }
 
+
+/* 
+ * Reset and Re-Initialize video device
+ */
+int uvc_video_reinit(struct uvc_video_device *video)
+{
+       int ret;
+
+       if ((ret = uvc_usb_reset(video->dev)) < 0)
+               return ret;
+
+       if ((ret = uvc_set_video_ctrl(video, &video->streaming->ctrl, 0)) < 0) {
+               uvc_printk(KERN_DEBUG, "uvc_video_reinit: Unable to commit 
format "
+                          "(%d).\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+
+int uvc_usb_reset(struct uvc_device *dev)
+{
+       int l, ret;
+
+       l = usb_lock_device_for_reset(dev->udev, dev->intf);
+
+       if (l >= 0) {
+               ret = usb_reset_device(dev->udev);
+               if (l)
+                       usb_unlock_device(dev->udev);
+       }
+       else
+               ret = -EBUSY;
+
+       if (ret)
+               uvc_printk(KERN_DEBUG, "uvc_usb_reset: Unable to reset usb 
device"
+                          "(%d).\n", ret);
+       else
+               dev->state &= ~UVC_DEV_IOERROR;
+
+       return ret;
+}
+
+
+
 /* Simplify a fraction using a simple continued fraction decomposition. The
  * idea here is to convert fractions such as 333333/10000000 to 1/30 using
  * 32 bit arithmetic only. The algorithm is not perfect and relies upon two
@@ -1198,9 +1244,19 @@
         * parameters.
         */
        if ((ret = uvc_video_init(&dev->video)) < 0) {
-               uvc_printk(KERN_ERR, "Failed to initialize the device "
-                       "(%d).\n", ret);
-               return ret;
+
+               uvc_printk(KERN_ERR, "Failed to initialize the device, "
+                          "(%d). trying to reset ...\n", ret);
+
+               if ((ret = uvc_usb_reset(dev)))
+                       return ret;
+
+               if ((ret = uvc_video_init(&dev->video)) < 0) {
+                       uvc_printk(KERN_ERR, "Failed to initialize the device "
+                                  "(%d).\n", ret);
+                       return ret;
+               }
+
        }
 
        /* Register the device with V4L. */
diff -u old/uvc_v4l2.c new/uvc_v4l2.c
--- old/uvc_v4l2.c      2006-11-04 22:14:32.000000000 +0300
+++ new/uvc_v4l2.c      2006-11-04 21:30:52.000000000 +0300
@@ -434,6 +434,10 @@
                mutex_unlock(&video->queue.mutex);
        }
 
+       /* leave usb device in a clean state */
+       if (video->dev->state & UVC_DEV_IOERROR)
+               uvc_video_reinit(video);
+
        /* Release the file handle. */
        uvc_dismiss_privileges(handle);
        kfree(handle);
diff -u old/uvc_video.c new/uvc_video.c
--- old/uvc_video.c     2006-11-04 22:14:32.000000000 +0300
+++ new/uvc_video.c     2006-11-04 22:22:42.000000000 +0300
@@ -45,6 +45,7 @@
                uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u "
                        "(unit %u) : %d (exp. %u).\n", query, cs, unit, ret,
                        size);
+               dev->state |= UVC_DEV_IOERROR;
                return -EIO;
        }
 
diff -u old/uvcvideo.h new/uvcvideo.h
--- old/uvcvideo.h      2006-11-04 22:14:32.000000000 +0300
+++ new/uvcvideo.h      2006-11-04 02:16:51.000000000 +0300
@@ -511,6 +511,7 @@
 
 enum uvc_device_state {
        UVC_DEV_DISCONNECTED = 1,
+       UVC_DEV_IOERROR = 2,
 };
 
 struct uvc_device {
@@ -664,6 +665,10 @@
 extern struct usb_host_endpoint *uvc_find_endpoint(
                struct usb_host_interface *alts, __u8 epaddr);
 
+
+extern int uvc_video_reinit(struct uvc_video_device *video);
+extern int uvc_usb_reset(struct uvc_device *dev);
+
 #endif /* __KERNEL__ */
 
 #endif




Regards, Evgeny
_______________________________________________
Linux-uvc-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/linux-uvc-devel

Reply via email to