Hi,

this is the newest version of the patch to introduce a blacklist.

- It handles autosuspend oddities and problems with string descriptors
- It exports the detected quirks through sysfs

It compiles and detects quirky devices.

        Regards
                Oliver

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

--- /dev/null   2007-01-15 18:37:01.000000000 +0100
+++ linux-blacklist/include/linux/usb/quirks.h  2007-01-26 13:49:08.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_NO_AUTOSUSPEND               1 /* devices which must not be 
autosuspended */
+#define USB_QUIRK_STRING_FETCH                 2 /* devices which crash when 
string descriptors are fetched */
--- linux-2.6.20-rc6/include/linux/usb.h        2007-01-25 11:37:53.000000000 
+0100
+++ linux-blacklist/include/linux/usb.h 2007-01-26 09:02:37.000000000 +0100
@@ -387,6 +387,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 */
@@ -1460,3 +1461,4 @@
 #endif  /* __KERNEL__ */
 
 #endif
+
--- linux-2.6.20-rc6/drivers/usb/core/hub.c     2007-01-25 11:37:42.000000000 
+0100
+++ linux-blacklist/drivers/usb/core/hub.c      2007-01-26 09:02:37.000000000 
+0100
@@ -1267,6 +1267,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",
--- linux-2.6.20-rc6/drivers/usb/core/message.c 2007-01-25 11:37:42.000000000 
+0100
+++ linux-blacklist/drivers/usb/core/message.c  2007-01-26 09:42:15.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)
+               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)
--- linux-2.6.20-rc6/drivers/usb/core/sysfs.c   2007-01-25 11:36:31.000000000 
+0100
+++ linux-blacklist/drivers/usb/core/sysfs.c    2007-01-26 09:36:23.000000000 
+0100
@@ -148,6 +148,16 @@
 }
 static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
 
+static ssize_t
+show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct usb_device *udev;
+
+       udev = to_usb_device(dev);
+       return sprintf(buf, "%d\n", udev->quirks);
+}
+static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
+
 /* Descriptor fields */
 #define usb_descriptor_attr_le16(field, format_string)                 \
 static ssize_t                                                         \
@@ -204,6 +214,7 @@
        &dev_attr_devnum.attr,
        &dev_attr_version.attr,
        &dev_attr_maxchild.attr,
+       &dev_attr_quirks.attr,
        NULL,
 };
 static struct attribute_group dev_attr_grp = {
--- linux-2.6.20-rc6/drivers/usb/core/usb.h     2007-01-25 11:37:42.000000000 
+0100
+++ linux-blacklist/drivers/usb/core/usb.h      2007-01-26 09:02:37.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);
--- linux-2.6.20-rc6/drivers/usb/core/Makefile  2007-01-25 11:36:31.000000000 
+0100
+++ linux-blacklist/drivers/usb/core/Makefile   2007-01-26 09:02:37.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
--- /dev/null   2007-01-15 18:37:01.000000000 +0100
+++ linux-blacklist/drivers/usb/core/quirks.c   2007-01-26 09:41:28.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_NO_AUTOSUSPEND) {
+               /* 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
+++ linux-blacklist/drivers/usb/core/quirky_devices.h   2007-01-26 
10:02:45.000000000 +0100
@@ -0,0 +1,29 @@
+/*
+ * 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[] = {
+
+       /* HP 5300/5370C scanner */
+       {0x03f0, 0x0701, 0x0001, 0x0001, USB_QUIRK_STRING_FETCH},
+
+       /* Seiko Epson Corp. Perfection 1250 */
+       {0x04b8, 0x010f, 0x0100, 0x0100, USB_QUIRK_NO_AUTOSUSPEND},
+
+       /* Elsa MicroLink 56k (V.250) */
+       {0x05cc, 0x2267, 0x0100, 0x0100, USB_QUIRK_NO_AUTOSUSPEND},
+
+       {0, 0, 0, 0, 0} /* keep this last */
+};
+

-------------------------------------------------------------------------
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