aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/pl2303.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-02-01 22:28:57 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-02-01 22:28:57 -0500
commitb6cf160c4b788a31f6a4017a469b956ca77febf4 (patch)
treed4d525000e283fe08905385d91dd0170454eae9a /drivers/usb/serial/pl2303.c
parented50d6cbc394cd0966469d3e249353c9dd1d38b9 (diff)
parent2c044a4803804708984931bcbd03314732e995d5 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (128 commits) USB: fix codingstyle issues in drivers/usb/core/*.c USB: fix codingstyle issues in drivers/usb/core/message.c USB: fix codingstyle issues in drivers/usb/core/hcd-pci.c USB: fix codingstyle issues in drivers/usb/core/devio.c USB: fix codingstyle issues in drivers/usb/core/devices.c USB: fix codingstyle issues in drivers/usb/core/*.h USB: fix codingstyle issues in include/linux/usb/ USB: fix codingstyle issues in include/linux/usb.h USB: mark USB drivers as being GPL only USB: use a real vendor and product id for root hubs USB: mount options: fix usbfs USB: Fix usb_serial_driver structure for Kobil cardreader driver. usb: ehci should use u16 for isochronous intervals usb: ehci, remove false clear-reset path USB: Use menuconfig objects usb: ohci-sm501 driver usb: dma bounce buffer support USB: last abuses of intfdata in close for usb-serial drivers USB: kl5kusb105 don't flush to logically disconnected devices USB: oti6858: cleanup ...
Diffstat (limited to 'drivers/usb/serial/pl2303.c')
-rw-r--r--drivers/usb/serial/pl2303.c112
1 files changed, 58 insertions, 54 deletions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 0da1df9c79bf..ae3ec1a64008 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -65,6 +65,7 @@ static struct usb_device_id id_table [] = {
65 { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) }, 65 { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) },
66 { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, 66 { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
67 { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, 67 { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
68 { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
68 { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, 69 { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
69 { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, 70 { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
70 { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, 71 { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
@@ -84,9 +85,10 @@ static struct usb_device_id id_table [] = {
84 { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, 85 { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
85 { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, 86 { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
86 { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, 87 { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
87 { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
88 { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, 88 { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
89 { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, 89 { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) },
90 { USB_DEVICE(HL340_VENDOR_ID, HL340_PRODUCT_ID) },
91 { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
90 { } /* Terminating entry */ 92 { } /* Terminating entry */
91}; 93};
92 94
@@ -97,7 +99,10 @@ static struct usb_driver pl2303_driver = {
97 .probe = usb_serial_probe, 99 .probe = usb_serial_probe,
98 .disconnect = usb_serial_disconnect, 100 .disconnect = usb_serial_disconnect,
99 .id_table = id_table, 101 .id_table = id_table,
102 .suspend = usb_serial_suspend,
103 .resume = usb_serial_resume,
100 .no_dynamic_id = 1, 104 .no_dynamic_id = 1,
105 .supports_autosuspend = 1,
101}; 106};
102 107
103#define SET_LINE_REQUEST_TYPE 0x21 108#define SET_LINE_REQUEST_TYPE 0x21
@@ -310,12 +315,39 @@ static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
310 return count; 315 return count;
311} 316}
312 317
318static int pl2303_vendor_read(__u16 value, __u16 index,
319 struct usb_serial *serial, unsigned char *buf)
320{
321 int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
322 VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE,
323 value, index, buf, 1, 100);
324 dbg("0x%x:0x%x:0x%x:0x%x %d - %x", VENDOR_READ_REQUEST_TYPE,
325 VENDOR_READ_REQUEST, value, index, res, buf[0]);
326 return res;
327}
328
329static int pl2303_vendor_write(__u16 value, __u16 index,
330 struct usb_serial *serial)
331{
332 int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
333 VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,
334 value, index, NULL, 0, 100);
335 dbg("0x%x:0x%x:0x%x:0x%x %d", VENDOR_WRITE_REQUEST_TYPE,
336 VENDOR_WRITE_REQUEST, value, index, res);
337 return res;
338}
339
313static int pl2303_startup(struct usb_serial *serial) 340static int pl2303_startup(struct usb_serial *serial)
314{ 341{
315 struct pl2303_private *priv; 342 struct pl2303_private *priv;
316 enum pl2303_type type = type_0; 343 enum pl2303_type type = type_0;
344 unsigned char *buf;
317 int i; 345 int i;
318 346
347 buf = kmalloc(10, GFP_KERNEL);
348 if (buf == NULL)
349 return -ENOMEM;
350
319 if (serial->dev->descriptor.bDeviceClass == 0x02) 351 if (serial->dev->descriptor.bDeviceClass == 0x02)
320 type = type_0; 352 type = type_0;
321 else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) 353 else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
@@ -340,9 +372,27 @@ static int pl2303_startup(struct usb_serial *serial)
340 priv->type = type; 372 priv->type = type;
341 usb_set_serial_port_data(serial->port[i], priv); 373 usb_set_serial_port_data(serial->port[i], priv);
342 } 374 }
375
376 pl2303_vendor_read(0x8484, 0, serial, buf);
377 pl2303_vendor_write(0x0404, 0, serial);
378 pl2303_vendor_read(0x8484, 0, serial, buf);
379 pl2303_vendor_read(0x8383, 0, serial, buf);
380 pl2303_vendor_read(0x8484, 0, serial, buf);
381 pl2303_vendor_write(0x0404, 1, serial);
382 pl2303_vendor_read(0x8484, 0, serial, buf);
383 pl2303_vendor_read(0x8383, 0, serial, buf);
384 pl2303_vendor_write(0, 1, serial);
385 pl2303_vendor_write(1, 0, serial);
386 if (type == HX)
387 pl2303_vendor_write(2, 0x44, serial);
388 else
389 pl2303_vendor_write(2, 0x24, serial);
390
391 kfree(buf);
343 return 0; 392 return 0;
344 393
345cleanup: 394cleanup:
395 kfree(buf);
346 for (--i; i>=0; --i) { 396 for (--i; i>=0; --i) {
347 priv = usb_get_serial_port_data(serial->port[i]); 397 priv = usb_get_serial_port_data(serial->port[i]);
348 pl2303_buf_free(priv->buf); 398 pl2303_buf_free(priv->buf);
@@ -582,24 +632,12 @@ static void pl2303_set_termios(struct usb_serial_port *port,
582 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); 632 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
583 633
584 if (cflag & CRTSCTS) { 634 if (cflag & CRTSCTS) {
585 __u16 index;
586 if (priv->type == HX) 635 if (priv->type == HX)
587 index = 0x61; 636 pl2303_vendor_write(0x0, 0x61, serial);
588 else 637 else
589 index = 0x41; 638 pl2303_vendor_write(0x0, 0x41, serial);
590 i = usb_control_msg(serial->dev,
591 usb_sndctrlpipe(serial->dev, 0),
592 VENDOR_WRITE_REQUEST,
593 VENDOR_WRITE_REQUEST_TYPE,
594 0x0, index, NULL, 0, 100);
595 dbg("0x40:0x1:0x0:0x%x %d", index, i);
596 } else { 639 } else {
597 i = usb_control_msg(serial->dev, 640 pl2303_vendor_write(0x0, 0x0, serial);
598 usb_sndctrlpipe(serial->dev, 0),
599 VENDOR_WRITE_REQUEST,
600 VENDOR_WRITE_REQUEST_TYPE,
601 0x0, 0x0, NULL, 0, 100);
602 dbg ("0x40:0x1:0x0:0x0 %d", i);
603 } 641 }
604 642
605 /* FIXME: Need to read back resulting baud rate */ 643 /* FIXME: Need to read back resulting baud rate */
@@ -629,7 +667,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
629 set_current_state(TASK_INTERRUPTIBLE); 667 set_current_state(TASK_INTERRUPTIBLE);
630 if (pl2303_buf_data_avail(priv->buf) == 0 || 668 if (pl2303_buf_data_avail(priv->buf) == 0 ||
631 timeout == 0 || signal_pending(current) || 669 timeout == 0 || signal_pending(current) ||
632 !usb_get_intfdata(port->serial->interface)) /* disconnect */ 670 port->serial->disconnected)
633 break; 671 break;
634 spin_unlock_irqrestore(&priv->lock, flags); 672 spin_unlock_irqrestore(&priv->lock, flags);
635 timeout = schedule_timeout(timeout); 673 timeout = schedule_timeout(timeout);
@@ -678,7 +716,6 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
678 struct ktermios tmp_termios; 716 struct ktermios tmp_termios;
679 struct usb_serial *serial = port->serial; 717 struct usb_serial *serial = port->serial;
680 struct pl2303_private *priv = usb_get_serial_port_data(port); 718 struct pl2303_private *priv = usb_get_serial_port_data(port);
681 unsigned char *buf;
682 int result; 719 int result;
683 720
684 dbg("%s - port %d", __FUNCTION__, port->number); 721 dbg("%s - port %d", __FUNCTION__, port->number);
@@ -686,45 +723,12 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
686 if (priv->type != HX) { 723 if (priv->type != HX) {
687 usb_clear_halt(serial->dev, port->write_urb->pipe); 724 usb_clear_halt(serial->dev, port->write_urb->pipe);
688 usb_clear_halt(serial->dev, port->read_urb->pipe); 725 usb_clear_halt(serial->dev, port->read_urb->pipe);
689 }
690
691 buf = kmalloc(10, GFP_KERNEL);
692 if (buf==NULL)
693 return -ENOMEM;
694
695#define FISH(a,b,c,d) \
696 result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \
697 b, a, c, d, buf, 1, 100); \
698 dbg("0x%x:0x%x:0x%x:0x%x %d - %x",a,b,c,d,result,buf[0]);
699
700#define SOUP(a,b,c,d) \
701 result=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0), \
702 b, a, c, d, NULL, 0, 100); \
703 dbg("0x%x:0x%x:0x%x:0x%x %d",a,b,c,d,result);
704
705 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
706 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 0);
707 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
708 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
709 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
710 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1);
711 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
712 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
713 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1);
714 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0);
715
716 if (priv->type == HX) {
717 /* HX chip */
718 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44);
719 /* reset upstream data pipes */
720 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 8, 0);
721 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 9, 0);
722 } else { 726 } else {
723 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x24); 727 /* reset upstream data pipes */
728 pl2303_vendor_write(8, 0, serial);
729 pl2303_vendor_write(9, 0, serial);
724 } 730 }
725 731
726 kfree(buf);
727
728 /* Setup termios */ 732 /* Setup termios */
729 if (port->tty) { 733 if (port->tty) {
730 pl2303_set_termios(port, &tmp_termios); 734 pl2303_set_termios(port, &tmp_termios);