Hello community,
here is the log from the commit of package uvcvideo
checked in at Fri Jun 6 17:52:20 CEST 2008.
--------
--- uvcvideo/uvcvideo.changes 2008-05-30 02:31:39.000000000 +0200
+++ /mounts/work_src_done/STABLE/STABLE/uvcvideo/uvcvideo.changes 2008-06-05 19:34:29.841461000 +0200
@@ -1,0 +2,5 @@
+Thu Jun 5 19:34:18 CEST 2008 - bphilips@suse.de
+
+- Improved fix for bnc#387876
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ uvcvideo.spec ++++++
--- /var/tmp/diff_new_pack.GH3243/_old 2008-06-06 17:52:14.000000000 +0200
+++ /var/tmp/diff_new_pack.GH3243/_new 2008-06-06 17:52:14.000000000 +0200
@@ -18,7 +18,7 @@
AutoReqProv: on
Summary: USB Video Class (UVC) webcam driver
Version: r200
-Release: 2
+Release: 3
Source: %name-%version.tar.bz2
Source1: preamble
Url: http://linux-uvc.berlios.de/
@@ -95,6 +95,8 @@
rm -rf $RPM_BUILD_ROOT
%changelog
+* Thu Jun 05 2008 bphilips@suse.de
+- Improved fix for bnc#387876
* Fri May 30 2008 bphilips@suse.de
- Add fix for bnc#387876 uvcvideo breaks suspend to ram
* Tue Apr 08 2008 bphilips@suse.de
++++++ uvcvideo-fix-release-interface.patch ++++++
--- /var/tmp/diff_new_pack.GH3243/_old 2008-06-06 17:52:14.000000000 +0200
+++ /var/tmp/diff_new_pack.GH3243/_new 2008-06-06 17:52:14.000000000 +0200
@@ -1,48 +1,231 @@
+From: Laurent Pinchart
Subject: [PATCH] uvc: release streaming interface to fix suspend to RAM
+Improved patch by Laurent.
+
Bug report: https://bugzilla.novell.com/show_bug.cgi?id=387876
If probe fails the UVC driver may still be bound to a streaming interface.
This interface must be released with usb_driver_release_interface() otherwise
-the interface will continue to be bound later causing suspend operations to
-fail.
-
-Tested using this little hack:
-> +++ uvc_video.c
-> @@ -870,6 +870,8 @@ int uvc_video_init(st
-> if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 &&
-> (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0)
-> return ret;
-> +
-> + return -EIO;
->
+the interface will continue to be bound causing suspend operations to fail.
+> Tested using this little hack:
+> > +++ uvc_video.c
+> > @@ -870,6 +870,8 @@ int uvc_video_init(st
+> > if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 &&
+> > (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0)
+> > return ret;
+> > +
+> > + return -EIO;
Signed-off-by: Brandon Philips
---
- uvc_driver.c | 4 ++++
- 1 file changed, 4 insertions(+)
+ uvc_driver.c | 101 ++++++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 52 insertions(+), 49 deletions(-)
-Index: uvc/uvc_driver.c
+Index: uvcvideo-r200/uvc_driver.c
===================================================================
---- uvc.orig/uvc_driver.c
-+++ uvc/uvc_driver.c
-@@ -886,6 +886,8 @@ static int uvc_parse_control(struct uvc_
-
- if (uvc_parse_streaming(dev, streaming) < 0) {
- usb_put_intf(intf);
-+ usb_driver_release_interface(&uvc_driver.driver,
-+ intf);
- kfree(streaming->format);
- kfree(streaming->header.bmaControls);
- kfree(streaming);
-@@ -1511,6 +1513,8 @@ void uvc_delete(struct kref *kref)
+--- uvcvideo-r200.orig/uvc_driver.c
++++ uvcvideo-r200/uvc_driver.c
+@@ -531,11 +531,11 @@ static int uvc_parse_format(struct uvc_d
+ }
+
+ static int uvc_parse_streaming(struct uvc_device *dev,
+- struct uvc_streaming *streaming)
++ struct usb_interface *intf)
+ {
++ struct uvc_streaming *streaming = NULL;
+ struct uvc_format *format;
+ struct uvc_frame *frame;
+- struct usb_interface *intf = streaming->intf;
+ struct usb_host_interface *alts = &intf->altsetting[0];
+ unsigned char *_buffer, *buffer = alts->extra;
+ int _buflen, buflen = alts->extralen;
+@@ -545,6 +545,31 @@ static int uvc_parse_streaming(struct uv
+ __u16 psize;
+ int ret;
+
++ if (intf->cur_altsetting->desc.bInterfaceSubClass
++ != SC_VIDEOSTREAMING) {
++ uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a "
++ "video streaming interface\n", dev->udev->devnum,
++ intf->altsetting[0].desc.bInterfaceNumber);
++ return -EINVAL;
++ }
++
++ if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) {
++ uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already "
++ "claimed\n", dev->udev->devnum,
++ intf->altsetting[0].desc.bInterfaceNumber);
++ return -EINVAL;
++ }
++
++ streaming = kzalloc(sizeof *streaming, GFP_KERNEL);
++ if (streaming == NULL) {
++ usb_driver_release_interface(&uvc_driver.driver, intf);
++ return -EINVAL;
++ }
++
++ mutex_init(&streaming->mutex);
++ streaming->intf = usb_get_intf(intf);
++ streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
++
+ /* The Pico iMage webcam has its class-specific interface descriptors
+ * after the endpoint descriptors.
+ */
+@@ -574,7 +599,7 @@ static int uvc_parse_streaming(struct uv
+ if (buflen <= 2) {
+ uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming "
+ "interface descriptors found.\n");
+- return -EINVAL;
++ goto error;
+ }
+
+ /* Parse the header descriptor. */
+@@ -582,7 +607,7 @@ static int uvc_parse_streaming(struct uv
+ uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
+ "%d OUTPUT HEADER descriptor is not supported.\n",
+ dev->udev->devnum, alts->desc.bInterfaceNumber);
+- return -EINVAL;
++ goto error;
+ }
+ else if (buffer[2] == VS_INPUT_HEADER) {
+ p = buflen >= 5 ? buffer[3] : 0;
+@@ -593,7 +618,7 @@ static int uvc_parse_streaming(struct uv
+ "interface %d INPUT HEADER descriptor is "
+ "invalid.\n", dev->udev->devnum,
+ alts->desc.bInterfaceNumber);
+- return -EINVAL;
++ goto error;
+ }
+
+ streaming->header.bNumFormats = p;
+@@ -606,16 +631,17 @@ static int uvc_parse_streaming(struct uv
+ streaming->header.bControlSize = n;
+
+ streaming->header.bmaControls = kmalloc(p*n, GFP_KERNEL);
+- if (streaming->header.bmaControls == NULL)
+- return -ENOMEM;
++ if (streaming->header.bmaControls == NULL) {
++ ret = -ENOMEM;
++ goto error;
++ }
+
+ memcpy(streaming->header.bmaControls, &buffer[13], p*n);
+- }
+- else {
++ } else {
+ uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
+ "%d HEADER descriptor not found.\n", dev->udev->devnum,
+ alts->desc.bInterfaceNumber);
+- return -EINVAL;
++ goto error;
+ }
+
+ buflen -= buffer[0];
+@@ -672,14 +698,16 @@ static int uvc_parse_streaming(struct uv
+ uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
+ "%d has no supported formats defined.\n",
+ dev->udev->devnum, alts->desc.bInterfaceNumber);
+- return -EINVAL;
++ goto error;
+ }
+
+ size = nformats * sizeof *format + nframes * sizeof *frame
+ + nintervals * sizeof *interval;
+ format = kzalloc(size, GFP_KERNEL);
+- if (format == NULL)
+- return -ENOMEM;
++ if (format == NULL) {
++ ret = -ENOMEM;
++ goto error;
++ }
+
+ frame = (struct uvc_frame*)&format[nformats];
+ interval = (__u32*)&frame[nframes];
+@@ -698,7 +726,7 @@ static int uvc_parse_streaming(struct uv
+ ret = uvc_parse_format(dev, streaming, format,
+ &interval, buffer, buflen);
+ if (ret < 0)
+- return ret;
++ goto error;
+
+ frame += format->nframes;
+ format++;
+@@ -730,7 +758,16 @@ static int uvc_parse_streaming(struct uv
+ streaming->maxpsize = psize;
+ }
+
++ list_add_tail(&streaming->list, &dev->streaming);
+ return 0;
++
++error:
++ usb_driver_release_interface(&uvc_driver.driver, intf);
++ usb_put_intf(intf);
++ kfree(streaming->format);
++ kfree(streaming->header.bmaControls);
++ kfree(streaming);
++ return ret;
+ }
+
+ /* Parse vendor-specific extensions. */
+@@ -815,7 +852,6 @@ static int uvc_parse_vendor_control(stru
+ static int uvc_parse_control(struct uvc_device *dev)
+ {
+ struct usb_device *udev = dev->udev;
+- struct uvc_streaming *streaming;
+ struct uvc_entity *unit, *term;
+ struct usb_interface *intf;
+ struct usb_host_interface *alts = dev->intf->cur_altsetting;
+@@ -858,41 +894,7 @@ static int uvc_parse_control(struct uvc_
+ continue;
+ }
+
+- if (intf->cur_altsetting->desc.bInterfaceSubClass
+- != SC_VIDEOSTREAMING) {
+- uvc_trace(UVC_TRACE_DESCR, "device %d "
+- "interface %d isn't a video "
+- "streaming interface\n",
+- udev->devnum, i);
+- continue;
+- }
+-
+- if (usb_interface_claimed(intf)) {
+- uvc_trace(UVC_TRACE_DESCR, "device %d "
+- "interface %d is already claimed\n",
+- udev->devnum, i);
+- continue;
+- }
+-
+- usb_driver_claim_interface(&uvc_driver.driver, intf, dev);
+-
+- streaming = kzalloc(sizeof *streaming, GFP_KERNEL);
+- if (streaming == NULL)
+- continue;
+- mutex_init(&streaming->mutex);
+- streaming->intf = usb_get_intf(intf);
+- streaming->intfnum =
+- intf->cur_altsetting->desc.bInterfaceNumber;
+-
+- if (uvc_parse_streaming(dev, streaming) < 0) {
+- usb_put_intf(intf);
+- kfree(streaming->format);
+- kfree(streaming->header.bmaControls);
+- kfree(streaming);
+- continue;
+- }
+-
+- list_add_tail(&streaming->list, &dev->streaming);
++ uvc_parse_streaming(dev, intf);
+ }
+ break;
+
+@@ -1510,6 +1512,7 @@ void uvc_delete(struct kref *kref)
+ list_for_each_safe(p, n, &dev->streaming) {
struct uvc_streaming *streaming;
streaming = list_entry(p, struct uvc_streaming, list);
++ usb_driver_release_interface(&uvc_driver.driver, streaming->intf);
usb_put_intf(streaming->intf);
-+ usb_driver_release_interface(&uvc_driver.driver,
-+ streaming->intf);
kfree(streaming->format);
kfree(streaming->header.bmaControls);
- kfree(streaming);
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Remember to have fun...
---------------------------------------------------------------------
To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org
For additional commands, e-mail: opensuse-commit+help@opensuse.org