diff options
Diffstat (limited to 'drivers/usb/serial/pl2303.c')
-rw-r--r-- | drivers/usb/serial/pl2303.c | 112 |
1 files changed, 58 insertions, 54 deletions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 0da1df9c79b..ae3ec1a6400 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -65,6 +65,7 @@ static struct usb_device_id id_table [] = { { 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(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, @@ -84,9 +85,10 @@ static struct usb_device_id id_table [] = { { 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) }, + { USB_DEVICE(HL340_VENDOR_ID, HL340_PRODUCT_ID) }, + { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -97,7 +99,10 @@ static struct usb_driver pl2303_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, .no_dynamic_id = 1, + .supports_autosuspend = 1, }; #define SET_LINE_REQUEST_TYPE 0x21 @@ -310,12 +315,39 @@ static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, return count; } +static int pl2303_vendor_read(__u16 value, __u16 index, + struct usb_serial *serial, unsigned char *buf) +{ + int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE, + value, index, buf, 1, 100); + dbg("0x%x:0x%x:0x%x:0x%x %d - %x", VENDOR_READ_REQUEST_TYPE, + VENDOR_READ_REQUEST, value, index, res, buf[0]); + return res; +} + +static int pl2303_vendor_write(__u16 value, __u16 index, + struct usb_serial *serial) +{ + int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, + value, index, NULL, 0, 100); + dbg("0x%x:0x%x:0x%x:0x%x %d", VENDOR_WRITE_REQUEST_TYPE, + VENDOR_WRITE_REQUEST, value, index, res); + return res; +} + static int pl2303_startup(struct usb_serial *serial) { struct pl2303_private *priv; enum pl2303_type type = type_0; + unsigned char *buf; int i; + buf = kmalloc(10, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + if (serial->dev->descriptor.bDeviceClass == 0x02) type = type_0; else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) @@ -340,9 +372,27 @@ static int pl2303_startup(struct usb_serial *serial) priv->type = type; usb_set_serial_port_data(serial->port[i], priv); } + + pl2303_vendor_read(0x8484, 0, serial, buf); + pl2303_vendor_write(0x0404, 0, serial); + pl2303_vendor_read(0x8484, 0, serial, buf); + pl2303_vendor_read(0x8383, 0, serial, buf); + pl2303_vendor_read(0x8484, 0, serial, buf); + pl2303_vendor_write(0x0404, 1, serial); + pl2303_vendor_read(0x8484, 0, serial, buf); + pl2303_vendor_read(0x8383, 0, serial, buf); + pl2303_vendor_write(0, 1, serial); + pl2303_vendor_write(1, 0, serial); + if (type == HX) + pl2303_vendor_write(2, 0x44, serial); + else + pl2303_vendor_write(2, 0x24, serial); + + kfree(buf); return 0; cleanup: + kfree(buf); for (--i; i>=0; --i) { priv = usb_get_serial_port_data(serial->port[i]); pl2303_buf_free(priv->buf); @@ -582,24 +632,12 @@ static void pl2303_set_termios(struct usb_serial_port *port, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); if (cflag & CRTSCTS) { - __u16 index; if (priv->type == HX) - index = 0x61; + pl2303_vendor_write(0x0, 0x61, serial); 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); + pl2303_vendor_write(0x0, 0x41, serial); } else { - i = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - VENDOR_WRITE_REQUEST, - VENDOR_WRITE_REQUEST_TYPE, - 0x0, 0x0, NULL, 0, 100); - dbg ("0x40:0x1:0x0:0x0 %d", i); + pl2303_vendor_write(0x0, 0x0, serial); } /* FIXME: Need to read back resulting baud rate */ @@ -629,7 +667,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp) set_current_state(TASK_INTERRUPTIBLE); if (pl2303_buf_data_avail(priv->buf) == 0 || timeout == 0 || signal_pending(current) || - !usb_get_intfdata(port->serial->interface)) /* disconnect */ + port->serial->disconnected) break; spin_unlock_irqrestore(&priv->lock, flags); timeout = schedule_timeout(timeout); @@ -678,7 +716,6 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp) struct ktermios tmp_termios; struct usb_serial *serial = port->serial; struct pl2303_private *priv = usb_get_serial_port_data(port); - unsigned char *buf; int result; dbg("%s - port %d", __FUNCTION__, port->number); @@ -686,45 +723,12 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp) if (priv->type != HX) { usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); - } - - buf = kmalloc(10, GFP_KERNEL); - if (buf==NULL) - return -ENOMEM; - -#define FISH(a,b,c,d) \ - result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \ - b, a, c, d, buf, 1, 100); \ - dbg("0x%x:0x%x:0x%x:0x%x %d - %x",a,b,c,d,result,buf[0]); - -#define SOUP(a,b,c,d) \ - result=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0), \ - b, a, c, d, NULL, 0, 100); \ - dbg("0x%x:0x%x:0x%x:0x%x %d",a,b,c,d,result); - - FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); - SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 0); - FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); - FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0); - FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); - 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); + /* reset upstream data pipes */ + pl2303_vendor_write(8, 0, serial); + pl2303_vendor_write(9, 0, serial); } - kfree(buf); - /* Setup termios */ if (port->tty) { pl2303_set_termios(port, &tmp_termios); |