47f19c0eed
When an attempt is made to read the interface strings of the Artisman Watchdog USB dongle (idVendor:idProduct 04b4:0526) an error is written to the dmesg log (uhci_result_common: failed with status 440000) and the dongle resets itself, resulting in a disconnect/reconnect loop. Adding the dongle to the list of devices in quirks.c, with the same quirk Alan Stern's previous patch for the Saitek Cyborg Gold 3D joystick, stops the device from resetting and allows it to be used with no problems. Signed-off-by: Paul Mortier <mortier@btinternet.com> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
143 lines
4 KiB
C
143 lines
4 KiB
C
/*
|
|
* USB device quirk handling logic and table
|
|
*
|
|
* Copyright (c) 2007 Oliver Neukum
|
|
* Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de>
|
|
*
|
|
* 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[] = {
|
|
/* CBM - Flash disk */
|
|
{ USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
|
/* HP 5300/5370C scanner */
|
|
{ USB_DEVICE(0x03f0, 0x0701), .driver_info =
|
|
USB_QUIRK_STRING_FETCH_255 },
|
|
|
|
/* Creative SB Audigy 2 NX */
|
|
{ USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
|
/* Philips PSC805 audio device */
|
|
{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
|
/* Artisman Watchdog Dongle */
|
|
{ USB_DEVICE(0x04b4, 0x0526), .driver_info =
|
|
USB_QUIRK_CONFIG_INTF_STRINGS },
|
|
|
|
/* Roland SC-8820 */
|
|
{ USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
|
/* Edirol SD-20 */
|
|
{ USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
|
/* appletouch */
|
|
{ USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
|
/* Avision AV600U */
|
|
{ USB_DEVICE(0x0638, 0x0a13), .driver_info =
|
|
USB_QUIRK_STRING_FETCH_255 },
|
|
|
|
/* Saitek Cyborg Gold Joystick */
|
|
{ USB_DEVICE(0x06a3, 0x0006), .driver_info =
|
|
USB_QUIRK_CONFIG_INTF_STRINGS },
|
|
|
|
/* M-Systems Flash Disk Pioneers */
|
|
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
|
/* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */
|
|
{ USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF },
|
|
|
|
/* Action Semiconductor flash disk */
|
|
{ USB_DEVICE(0x10d6, 0x2200), .driver_info =
|
|
USB_QUIRK_STRING_FETCH_255 },
|
|
|
|
/* SKYMEDI USB_DRIVE */
|
|
{ USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
|
/* BUILDWIN Photo Frame */
|
|
{ USB_DEVICE(0x1908, 0x1315), .driver_info =
|
|
USB_QUIRK_HONOR_BNUMINTERFACES },
|
|
|
|
/* INTEL VALUE SSD */
|
|
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
|
{ } /* terminating entry must be last */
|
|
};
|
|
|
|
static const struct usb_device_id *find_id(struct usb_device *udev)
|
|
{
|
|
const struct usb_device_id *id = usb_quirk_list;
|
|
|
|
for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
|
|
id->driver_info; id++) {
|
|
if (usb_match_device(udev, id))
|
|
return id;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Detect any quirks the device has, and do any housekeeping for it if needed.
|
|
*/
|
|
void usb_detect_quirks(struct usb_device *udev)
|
|
{
|
|
const struct usb_device_id *id = usb_quirk_list;
|
|
|
|
id = find_id(udev);
|
|
if (id)
|
|
udev->quirks = (u32)(id->driver_info);
|
|
if (udev->quirks)
|
|
dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
|
|
udev->quirks);
|
|
|
|
#ifdef CONFIG_USB_SUSPEND
|
|
|
|
/* By default, disable autosuspend for all devices. The hub driver
|
|
* will enable it for hubs.
|
|
*/
|
|
usb_disable_autosuspend(udev);
|
|
|
|
/* Autosuspend can also be disabled if the initial autosuspend_delay
|
|
* is negative.
|
|
*/
|
|
if (udev->autosuspend_delay < 0)
|
|
usb_autoresume_device(udev);
|
|
|
|
#endif
|
|
|
|
/* For the present, all devices default to USB-PERSIST enabled */
|
|
#if 0 /* was: #ifdef CONFIG_PM */
|
|
/* Hubs are automatically enabled for USB-PERSIST */
|
|
if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
|
|
udev->persist_enabled = 1;
|
|
|
|
#else
|
|
/* In the absence of PM, we can safely enable USB-PERSIST
|
|
* for all devices. It will affect things like hub resets
|
|
* and EMF-related port disables.
|
|
*/
|
|
if (!(udev->quirks & USB_QUIRK_RESET_MORPHS))
|
|
udev->persist_enabled = 1;
|
|
#endif /* CONFIG_PM */
|
|
}
|