On Fri, Jan 26, 2007 at 02:26:21PM +0100, Oliver Neukum wrote:
> 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.

Here's a revised patch based on yours.  I used the existing structure we
have for describing usb devices, as it can handle any type we want to
throw at it.  This also lets us re-use the logic of matching an id to a
device.

It simplified the code a bit too.

I moved the table into the .c file, as data shouldn't be in a .h file.

Changed the quirk to be a 32bit value, to be safe on all platforms.

And added the blackberry to the list, so I can test this out.

I'll work on the sysfs interface next, as we need a way to set these
quirks from userspace somehow...

thanks,

greg k-h

---
 drivers/usb/core/Makefile  |    2 -
 drivers/usb/core/hub.c     |    3 +
 drivers/usb/core/message.c |    3 +
 drivers/usb/core/quirks.c  |   69 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/core/sysfs.c   |   11 +++++++
 drivers/usb/core/usb.h     |    1 
 include/linux/usb.h        |    1 
 include/linux/usb/quirks.h |   11 +++++++
 8 files changed, 100 insertions(+), 1 deletion(-)

--- gregkh-2.6.orig/drivers/usb/core/Makefile
+++ gregkh-2.6/drivers/usb/core/Makefile
@@ -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
--- gregkh-2.6.orig/drivers/usb/core/hub.c
+++ gregkh-2.6/drivers/usb/core/hub.c
@@ -1278,6 +1278,9 @@ int usb_new_device(struct usb_device *ud
        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",
--- gregkh-2.6.orig/drivers/usb/core/message.c
+++ gregkh-2.6/drivers/usb/core/message.c
@@ -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 *usb_cache_string(struct usb_device
        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)
--- /dev/null
+++ gregkh-2.6/drivers/usb/core/quirks.c
@@ -0,0 +1,69 @@
+/*
+ * USB device quirk handling logic and table
+ *
+ * Copyright (c) 2007 Oliver Neukum
+ * Copyright (c) 2007 Greg Kroah-Hartman <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, version 2.
+ *
+ *
+ */
+
+#include <linux/usb.h>
+#include <linux/usb/quirks.h>
+#include "usb.h"
+
+/* List of quirky USB devices.  Please keep this list ordered by:
+ *     1) Vendor ID
+ *     2) Product ID
+ *     3) Class ID
+ *
+ * as we want specific devices to be overridden first, and only after that, any
+ * class specific quirks.
+ *
+ * Right now the logic aborts if it finds a valid device in the table, we might
+ * want to change that in the future if it turns out that a whole class of
+ * devices is broken...
+ */
+static const struct usb_device_id usb_quirk_list[] = {
+       /* HP 5300/5370C scanner */
+       { USB_DEVICE(0x03f0, 0x0701), USB_QUIRK_STRING_FETCH },
+
+       /* Seiko Epson Corp. Perfection 1250 */
+       { USB_DEVICE(0x04b8, 0x010f), USB_QUIRK_NO_AUTOSUSPEND },
+
+       /* Elsa MicroLink 56k (V.250) */
+       { USB_DEVICE(0x05cc, 0x2267), USB_QUIRK_NO_AUTOSUSPEND },
+
+       /* USB Blackberry devices */
+       { USB_DEVICE(0x0fca, 0x0001), USB_QUIRK_NO_AUTOSUSPEND },
+
+       { }  /* terminating entry must be last */
+};
+
+static void usb_autosuspend_quirk(struct usb_device *udev)
+{
+       /* unbalanced resume that will prevent autosuspension */
+       usb_autoresume_device(udev);
+}
+
+/*
+ * Detect any quirks the device has, and do any housekeeping for it if needed.
+ */
+void usb_detect_quirks(struct usb_device *udev)
+{
+       struct usb_interface *intf = udev->config->interface[0];
+       const struct usb_device_id *id;
+
+       id = usb_match_id(intf, usb_quirk_list);
+       if (id)
+               udev->quirks = (u32)(id->driver_info);
+
+       dev_dbg(&udev->dev, "USB quirks for this device: %x\n", udev->quirks);
+
+       /* do any special quirk handling here if needed */
+       if (udev->quirks & USB_QUIRK_NO_AUTOSUSPEND)
+               usb_autosuspend_quirk(udev);
+}
--- gregkh-2.6.orig/drivers/usb/core/sysfs.c
+++ gregkh-2.6/drivers/usb/core/sysfs.c
@@ -148,6 +148,16 @@ show_maxchild(struct device *dev, struct
 }
 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 @@ static struct attribute *dev_attrs[] = {
        &dev_attr_devnum.attr,
        &dev_attr_version.attr,
        &dev_attr_maxchild.attr,
+       &dev_attr_quirks.attr,
        NULL,
 };
 static struct attribute_group dev_attr_grp = {
--- gregkh-2.6.orig/drivers/usb/core/usb.h
+++ gregkh-2.6/drivers/usb/core/usb.h
@@ -13,6 +13,7 @@ extern void usb_disable_interface (struc
                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);
--- gregkh-2.6.orig/include/linux/usb.h
+++ gregkh-2.6/include/linux/usb.h
@@ -388,6 +388,7 @@ struct usb_device {
        struct usb_device *children[USB_MAXCHILDREN];
 
        int pm_usage_cnt;               /* usage counter for autosuspend */
+       u32 quirks;                     /* quirks of the whole device */
 #ifdef CONFIG_PM
        struct delayed_work autosuspend; /* for delayed autosuspends */
        struct mutex pm_mutex;          /* protects PM operations */
--- /dev/null
+++ gregkh-2.6/include/linux/usb/quirks.h
@@ -0,0 +1,11 @@
+/*
+ * This file holds the definitions of quirks found in USB devices
+ * Only quirks that affect the whole device, not an interface,
+ * belong here
+ */
+
+/* devices which must not be autosuspended */
+#define USB_QUIRK_NO_AUTOSUSPEND       0x00000001
+
+/* devices which crash when string descriptors are fetched */
+#define USB_QUIRK_STRING_FETCH         0x00000002

-------------------------------------------------------------------------
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
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to