Am Freitag, 19. Januar 2007 16:31 schrieb Alan Stern:
> On Fri, 19 Jan 2007, Oliver Neukum wrote:
> 
> > Hi,
> > 
> > I did the dirty deed. Could you please tell me which quirky devices
> > you know of? I am afraid this list needs to be populated and there
> > are outstanding regressions in Adrian's list.
> 
> I'll get back to you on the devices.
> 
> I think this patch could be generalized.  We may have other quirks to 
> worry about besides PM/autosuspend.  This should become a general USB 
> blacklist mechanism.

If you want the grand solution, you shall get it.

> One example that comes up immediately is the HP scanner which crashes 
> when we try to read the string descriptors.  Others may crop up in the 
> future.

Do you have the ID? Searching hasn't yielded what I need.
 
> > --- a/include/linux/usb.h   2007-01-18 13:15:25.000000000 +0100
> > +++ b/include/linux/usb.h   2007-01-19 12:12:07.000000000 +0100
> > @@ -387,6 +387,7 @@
> >     struct usb_device *children[USB_MAXCHILDREN];
> >  
> >     int pm_usage_cnt;               /* usage counter for autosuspend */
> > +   int pm_quirks;                  /* quirks of power management */
> 
> So this could simply be "quirks", not "pm_quirks", with a corresponding 
> change to the comment.

Yes.
 
> > +/* Power management quirks */
> > +#define USB_PM_DISCONNECT  1 /* devices which disconnect when resuming */
> 
> Make the name USB_QUIRK_NO_AUTOSUSPEND.  We don't really care that the
> device disconnects when resuming; the only important part is that we
> should never try to autosuspend it.

This seems contradictory. If you want a generic blacklisting, you cannot
limit the information to autosuspending. The device won't care why it
is suspended. Such devices should be treated differently under certain
situations. Either refuse to suspend or disconnect when asked to suspend.
 
> The list of quirk flag definitions doesn't belong in include/linux/usb.h.  
> We could put it in drivers/usb/core/usb.h or drivers/usb/core/quirks.h.  
> Or if you think that some USB drivers might eventually want to use a
> quirk, you could put the definitions in include/linux/usb/quirks.h.

OK.

> 
> I dislike seeing this in hub.c.  That file is already too big, and anyway
> managing a blacklist has nothing to do with being a hub driver.  You
> should create a new source file: drivers/usb/core/quirks.c.  Put both the
> search routine and the initializer for the quirks array in the new file.

OK. It seems better to me to seperate code, quirk types and the
blacklist itself.

        Regards
                Oliver

Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>
----

--- /dev/null   2007-01-15 18:37:01.000000000 +0100
+++ b/include/linux/usb/quirks.h        2007-01-24 18:44:42.000000000 +0100
@@ -0,0 +1,8 @@
+/*
+ * This file holds the definitions of quirks found in devices
+ * Only quirks that affect the whole device, not an interface,
+ * belong here
+ */
+
+#define USB_QUIRK_AUTOSUSPEND_DISCONNECT       1 /* devices which disconnect 
when resuming */
+#define USB_QUIRK_STRING_FETCH_CRASH           2 /* devices which crash when 
string descriptors are fetched */
--- /dev/null   2007-01-15 18:37:01.000000000 +0100
+++ b/drivers/usb/core/quirks.c 2007-01-24 17:42:18.000000000 +0100
@@ -0,0 +1,45 @@
+/*
+ * drivers/usb/core/quirks.c
+ *
+ * (c) Copyright Oliver Neukum 2007
+ */
+
+#include <linux/usb.h>
+#include <linux/usb/quirks.h>
+#include "usb.h"
+#include "quirky_devices.h"
+
+static int usb_autosuspend_search_quirk(struct usb_device *udev)
+{
+       u16 vendor = le16_to_cpu(udev->descriptor.idVendor);
+       u16 product = le16_to_cpu(udev->descriptor.idProduct);
+       u16 version = le16_to_cpu(udev->descriptor.bcdDevice);
+
+       const struct usb_blacklist *blentry = usb_blacklist;
+
+       while (blentry->idVendor) {
+               if (blentry->idVendor == vendor &&
+                       blentry->idProduct == product &&
+                       blentry->bcdVersionMin <= version &&
+                       blentry->bcdVersionMax >= version)
+                               return blentry->quirks;
+               blentry++;
+       }
+
+       return 0;
+}
+
+/*
+ * detect any quirks the device as opposed to the interfaces the device has
+ */
+
+void usb_detect_quirks(struct usb_device *udev)
+{
+       udev->quirks = usb_autosuspend_search_quirk(udev);
+
+       if (udev->quirks & USB_QUIRK_AUTOSUSPEND_DISCONNECT) {
+               /* unbalanced resume that'll prevent autosuspension */
+               usb_autoresume_device(udev);
+               dev_dbg(&udev->dev, "USB power management quirks: %d\n", 
udev->quirks);
+       }
+}
--- /dev/null   2007-01-15 18:37:01.000000000 +0100
+++ b/drivers/usb/core/quirky_devices.h 2007-01-24 18:51:14.000000000 +0100
@@ -0,0 +1,22 @@
+/*
+ * This is a list of USB devices which are quirky
+ * Keep this list ordered by
+ * 1. Vendor
+ * 2. Product
+ * 3. Version, the most specific first
+ */
+
+
+static const struct usb_blacklist {
+       u16     idVendor; /* vendor id of the quirky device */
+       u16     idProduct; /* product id of the quirky device */
+       u16     bcdVersionMin; /* minimum version id of the afflicted devices */
+       u16     bcdVersionMax; /* maximum version id of the afflicted devices */
+       int     quirks; /* the actual qirks, several to be joined with binary 
or */
+} usb_blacklist[] = {
+       /* Elsa MicroLink 56k (V.250) */
+       {0x05cc, 0x2267, 0x0100, 0x0100, USB_QUIRK_AUTOSUSPEND_DISCONNECT},
+       {0, 0, 0, 0, 0} /* keep this last */
+};
--- a/drivers/usb/core/usb.h    2007-01-23 15:16:33.000000000 +0100
+++ b/drivers/usb/core/usb.h    2007-01-24 17:39:42.000000000 +0100
@@ -13,6 +13,7 @@
                struct usb_interface *intf);
 extern void usb_release_interface_cache(struct kref *ref);
 extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
+extern void usb_detect_quirks(struct usb_device *udev);
 
 extern int usb_get_device_descriptor(struct usb_device *dev,
                unsigned int size);
--- a/drivers/usb/core/Makefile 2007-01-23 15:15:04.000000000 +0100
+++ b/drivers/usb/core/Makefile 2007-01-24 10:51:45.000000000 +0100
@@ -4,7 +4,7 @@
 
 usbcore-objs   := usb.o hub.o hcd.o urb.o message.o driver.o \
                        config.o file.o buffer.o sysfs.o endpoint.o \
-                       devio.o notify.o generic.o
+                       devio.o notify.o generic.o quirks.o
 
 ifeq ($(CONFIG_PCI),y)
        usbcore-objs    += hcd-pci.o
--- a/drivers/usb/core/hub.c    2007-01-23 15:16:33.000000000 +0100
+++ b/drivers/usb/core/hub.c    2007-01-24 10:09:14.000000000 +0100
@@ -1278,6 +1278,9 @@
        if (!try_module_get(THIS_MODULE))
                return -EINVAL;
 
+       /* Determine quirks */
+       usb_detect_quirks(udev);
+
        err = usb_get_configuration(udev);
        if (err < 0) {
                dev_err(&udev->dev, "can't read configurations, error %d\n",
--- a/drivers/usb/core/message.c        2007-01-23 15:16:33.000000000 +0100
+++ b/drivers/usb/core/message.c        2007-01-25 10:30:21.000000000 +0100
@@ -11,6 +11,7 @@
 #include <linux/timer.h>
 #include <linux/ctype.h>
 #include <linux/device.h>
+#include <linux/usb/quirks.h>
 #include <asm/byteorder.h>
 #include <asm/scatterlist.h>
 
@@ -810,6 +811,8 @@
        char *smallbuf = NULL;
        int len;
 
+       if (udev->quirks & USB_QUIRK_STRING_FETCH_CRASH)
+               return NULL;
        if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) {
                if ((len = usb_string(udev, index, buf, 256)) > 0) {
                        if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL)
--- a/include/linux/usb.h       2007-01-23 15:16:33.000000000 +0100
+++ b/include/linux/usb.h       2007-01-24 10:12:25.000000000 +0100
@@ -388,6 +388,7 @@
        struct usb_device *children[USB_MAXCHILDREN];
 
        int pm_usage_cnt;               /* usage counter for autosuspend */
+       int quirks;                     /* quirks of the whole device */
 #ifdef CONFIG_PM
        struct delayed_work autosuspend; /* for delayed autosuspends */
        struct mutex pm_mutex;          /* protects PM operations */
@@ -1485,3 +1486,4 @@
 #endif  /* __KERNEL__ */
 
 #endif
+

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to