On Tue, Dec 04, 2007 at 06:31:20AM -0800, Greg KH wrote:
> On Mon, Dec 03, 2007 at 04:47:37PM -0800, Sarah Sharp wrote:
> > Set the reset resume quirk for all pl2303 chips. Later, remove the
> > quirk if we know it's an HX chip, since that works fine without the
> > reset resume. Tested on ATEN HX and type_1 converters (0557:2008).
> >
> > Signed-off-by: Sarah Sharp <[EMAIL PROTECTED]>
> > ---
> >
> > Please let me know if there is a better way to share the pl2303 device
> > id table.
>
> Hm, putting it in a .h file doesn't seem like the nicest way, it
> duplicates the memory in both places :(
True.
> I almost hate to suggest it, but how about putting it in the usb core
> somewhere, in one location, and export the symbol so that the pl2303
> driver can use it? The quirks file is a good as a place as any, as long
> as we document the thing...
I wrote a patch to put the id table in quirks.c and export the symbol to
the pl2303 driver, but it fails to compile with the following error:
drivers/usb/serial/pl2303.c:54: error: ‘__mod_usb_device_table’ aliased to
undefined symbol ‘pl2303_id_table’
The macro MODULE_DEVICE_TABLE won't work when the id table is defined in
a different C file. If the table is defined in pl2303.c, then I think
the core would have to depend on the pl2303 driver, which seems
completely backwards.
A friend suggested setting the reset-resume quirk for all devices and
then removing it later. However, this seems a little overboard.
Any other suggestions?
Sarah
Set reset resume quirk for all pl2303 chips. Later, remove the quirk if we
know it's an HX chip, since that chip works fine without a reset resume.
Tested on ATEN HX and type_1 converters (0557:2008).
Signed-off-by: Sarah Sharp <[EMAIL PROTECTED]>
---
drivers/usb/core/quirks.c | 55 ++++++++++++++++++++++++++++++++----
drivers/usb/serial/pl2303.c | 66 +++++++++++-------------------------------
drivers/usb/serial/pl2303.h | 2 +
3 files changed, 69 insertions(+), 54 deletions(-)
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index d42c561..9c6f8aa 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -14,6 +14,7 @@
#include <linux/usb.h>
#include <linux/usb/quirks.h>
#include "usb.h"
+#include "../serial/pl2303.h"
/* List of quirky USB devices. Please keep this list ordered by:
* 1) Vendor ID
@@ -48,10 +49,51 @@ static const struct usb_device_id usb_quirk_list[] = {
{ } /* 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;
+/* PL2303 usb to serial adapter IDs. */
+const struct usb_device_id pl2303_id_table [] = {
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID), .driver_info = USB_QUIRK_RESET_RESUME },
+ { } /* Terminating entry */
+};
+EXPORT_SYMBOL(pl2303_id_table);
+static const struct usb_device_id *find_id(struct usb_device *udev, const struct usb_device_id *id)
+{
for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
id->driver_info; id++) {
if (usb_match_device(udev, id))
@@ -65,10 +107,11 @@ static const struct usb_device_id *find_id(struct usb_device *udev)
*/
void usb_detect_quirks(struct usb_device *udev)
{
- const struct usb_device_id *id = usb_quirk_list;
+ const struct usb_device_id *id;
- id = find_id(udev);
- if (id)
+ if ((id = find_id(udev, usb_quirk_list)))
+ udev->quirks = (u32)(id->driver_info);
+ else if ((id = find_id(udev, pl2303_id_table)))
udev->quirks = (u32)(id->driver_info);
if (udev->quirks)
dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index cf8add9..bfbadcb 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -28,6 +28,7 @@
#include <asm/uaccess.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#include <linux/usb/quirks.h>
#include "pl2303.h"
/*
@@ -49,54 +50,17 @@ struct pl2303_buf {
char *buf_put;
};
-static struct usb_device_id id_table [] = {
- { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) },
- { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) },
- { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) },
- { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
- { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
- { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
- { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
- { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
- { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
- { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
- { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) },
- { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) },
- { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) },
- { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
- { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
- { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
- { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
- { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
- { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
- { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) },
- { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
- { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) },
- { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
- { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) },
- { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) },
- { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
- { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) },
- { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) },
- { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) },
- { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
- { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
- { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
- { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
- { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
- { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
- { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
+/* ID table found in usb/core/quirks.c */
+MODULE_DEVICE_TABLE(usb, pl2303_id_table);
static struct usb_driver pl2303_driver = {
.name = "pl2303",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
- .id_table = id_table,
+ .id_table = pl2303_id_table,
+ .suspend = usb_serial_suspend,
+ .resume = usb_serial_resume,
+ .reset_resume = usb_serial_reset_resume,
.no_dynamic_id = 1,
};
@@ -313,18 +277,24 @@ static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
static int pl2303_startup(struct usb_serial *serial)
{
struct pl2303_private *priv;
+ struct usb_device *udev = serial->dev;
enum pl2303_type type = type_0;
int i;
- if (serial->dev->descriptor.bDeviceClass == 0x02)
+ if (udev->descriptor.bDeviceClass == 0x02)
type = type_0;
- else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
+ else if (udev->descriptor.bMaxPacketSize0 == 0x40)
type = HX;
- else if (serial->dev->descriptor.bDeviceClass == 0x00)
+ else if (udev->descriptor.bDeviceClass == 0x00)
type = type_1;
- else if (serial->dev->descriptor.bDeviceClass == 0xFF)
+ else if (udev->descriptor.bDeviceClass == 0xFF)
type = type_1;
+
dbg("device type: %d", type);
+ if (type == HX) {
+ udev->quirks &= !USB_QUIRK_RESET_RESUME;
+ dbg("USB quirks changed for this device: %x", udev->quirks);
+ }
for (i = 0; i < serial->num_ports; ++i) {
priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL);
@@ -1100,7 +1070,7 @@ static struct usb_serial_driver pl2303_device = {
.owner = THIS_MODULE,
.name = "pl2303",
},
- .id_table = id_table,
+ .id_table = pl2303_id_table,
.usb_driver = &pl2303_driver,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index d31f5d2..9cbf22a 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -107,3 +107,5 @@
/* Corega CG-USBRS232R Serial Adapter */
#define COREGA_VENDOR_ID 0x07aa
#define COREGA_PRODUCT_ID 0x002a
+
+extern const struct usb_device_id pl2303_id_table[];
--
1.5.3.4