Re: [Linux-uvc-devel] QC fusion almost working in kopete
Linux UVC driver and tools
Brought to you by:
pinchartl
|
From: Alexandre B. <di...@fr...> - 2006-02-13 23:05:48
|
On Monday 13 February 2006 18:30, Nick Wiltshire wrote:
> Alexandre - could you do a similar patch for r19 ? I'd really like to see
> if it works.
Index: uvcvideo.c
===================================================================
--- uvcvideo.c (revision 19)
+++ uvcvideo.c (working copy)
@@ -320,6 +320,7 @@
enum uvc_device_state {
UVC_DEV_DISCONNECTED = 1,
+ UVC_DEV_IOERROR = 2,
};
struct uvc_device {
@@ -1346,6 +1347,29 @@
* UVC Controls
*/
+static 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;
+}
+
static int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
__u8 intfnum, __u8 cs, void *data, __u16 size)
{
@@ -1363,6 +1387,7 @@
if (ret != size) {
uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u "
"(unit %u) : %d.\n", query, cs, unit, ret);
+ dev->state |= UVC_DEV_IOERROR;
return -EIO;
}
@@ -1577,6 +1602,25 @@
* Video device
*/
+/*
+ * Reset and Re-Initialize video device
+ */
+static 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;
+}
+
/*
* Initialize the UVC video device.
*
@@ -1971,6 +2015,10 @@
uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to free buffers.\n");
up(&video->queue.lock);
+ /* leave usb device in a clean state */
+ if (video->dev->state & UVC_DEV_IOERROR)
+ uvc_video_reinit(video);
+
atomic_inc(&video->count);
kref_put(&video->dev->kref, uvc_delete);
return 0;
@@ -3117,9 +3165,18 @@
* 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. */
--
Alexandre
|