[PATCH] USB: Add HX type pl2303
Linux Kernel Mailing List <[email protected]> Sat, 30 Apr 2005 13:33:00 +0000
| Newsgroups | gmane.linux.kernel.commits.2-4 |
|---|---|
| Message-ID | <[email protected]> |
ChangeSet 1.1510, 2005/04/30 10:33:00-03:00, [email protected] [PATCH] USB: Add HX type pl2303 This adds so-called "HX" with a backport from 2.6. We ship this with RHEL 3, so I thought I would post it for great justice, in case someone needs it. The failure symptom is that adapter gets recognized fine, receive works fine, but transmit doesn't. pl2303.c | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 44 insertions(+), 5 deletions(-) diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c --- a/drivers/usb/serial/pl2303.c 2005-04-30 12:17:18 -07:00 +++ b/drivers/usb/serial/pl2303.c 2005-04-30 12:17:18 -07:00 @@ -59,7 +59,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.10" +#define DRIVER_VERSION "v0.10.1" /* Takes from 2.6's */ #define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver" @@ -156,20 +156,38 @@ .shutdown = pl2303_shutdown, }; +enum pl2303_type { + type_0, /* don't know the difference between type 0 and */ + type_1, /* type 1, until someone from prolific tells us... */ + HX, /* HX version of the pl2303 chip */ +}; + struct pl2303_private { spinlock_t lock; wait_queue_head_t delta_msr_wait; u8 line_control; u8 line_status; u8 termios_initialized; + enum pl2303_type type; }; static int pl2303_startup (struct usb_serial *serial) { struct pl2303_private *priv; + enum pl2303_type type = type_0; int i; + if (serial->dev->descriptor.bDeviceClass == 0x02) + type = type_0; + else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) + type = HX; + else if (serial->dev->descriptor.bDeviceClass == 0x00) + type = type_1; + else if (serial->dev->descriptor.bDeviceClass == 0xFF) + type = type_1; + dbg("device type: %d", type); + for (i = 0; i < serial->num_ports; ++i) { priv = kmalloc (sizeof (struct pl2303_private), GFP_KERNEL); if (!priv) @@ -178,6 +196,7 @@ spin_lock_init(&priv->lock); init_waitqueue_head(&priv->delta_msr_wait); usb_set_serial_port_data(&serial->port[i], priv); + priv->type = type; } return 0; } @@ -380,10 +399,17 @@ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); if (cflag & CRTSCTS) { - i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), - VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, - 0x0, 0x41, NULL, 0, 100); - dbg ("0x40:0x1:0x0:0x41 %d", i); + __u16 index; + if (priv->type == HX) + index = 0x61; + else + index = 0x41; + i = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + VENDOR_WRITE_REQUEST, + VENDOR_WRITE_REQUEST_TYPE, + 0x0, index, NULL, 0, 100); + dbg ("0x40:0x1:0x0:0x%x %d", index, i); } kfree (buf); @@ -395,6 +421,7 @@ struct termios tmp_termios; struct usb_serial *serial = port->serial; unsigned char *buf; + struct pl2303_private *priv = port->private; int result; if (port_paranoia_check (port, __FUNCTION__)) @@ -427,6 +454,18 @@ SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1); FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0); + SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1); + SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0); + + if (priv->type == HX) { + /* HX chip */ + SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44); + /* reset upstream data pipes */ + SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 8, 0); + SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 9, 0); + } else { + SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x24); + } kfree(buf);