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