aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/pl2303.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/pl2303.c')
-rw-r--r--drivers/usb/serial/pl2303.c47
1 files changed, 28 insertions, 19 deletions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 440b99c15435..8dd1c4a0aefd 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -31,6 +31,9 @@
31#include <asm/unaligned.h> 31#include <asm/unaligned.h>
32#include "pl2303.h" 32#include "pl2303.h"
33 33
34
35#define PL2303_QUIRK_UART_STATE_IDX0 BIT(0)
36
34static const struct usb_device_id id_table[] = { 37static const struct usb_device_id id_table[] = {
35 { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, 38 { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) },
36 { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, 39 { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) },
@@ -58,9 +61,12 @@ static const struct usb_device_id id_table[] = {
58 { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, 61 { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
59 { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, 62 { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) },
60 { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, 63 { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
61 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) }, 64 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1),
62 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, 65 .driver_info = PL2303_QUIRK_UART_STATE_IDX0 },
63 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) }, 66 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65),
67 .driver_info = PL2303_QUIRK_UART_STATE_IDX0 },
68 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75),
69 .driver_info = PL2303_QUIRK_UART_STATE_IDX0 },
64 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) }, 70 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) },
65 { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */ 71 { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */
66 { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, 72 { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
@@ -110,7 +116,7 @@ MODULE_DEVICE_TABLE(usb, id_table);
110#define VENDOR_READ_REQUEST_TYPE 0xc0 116#define VENDOR_READ_REQUEST_TYPE 0xc0
111#define VENDOR_READ_REQUEST 0x01 117#define VENDOR_READ_REQUEST 0x01
112 118
113#define UART_STATE 0x08 119#define UART_STATE_INDEX 8
114#define UART_STATE_TRANSIENT_MASK 0x74 120#define UART_STATE_TRANSIENT_MASK 0x74
115#define UART_DCD 0x01 121#define UART_DCD 0x01
116#define UART_DSR 0x02 122#define UART_DSR 0x02
@@ -130,6 +136,7 @@ enum pl2303_type {
130 136
131struct pl2303_serial_private { 137struct pl2303_serial_private {
132 enum pl2303_type type; 138 enum pl2303_type type;
139 unsigned long quirks;
133}; 140};
134 141
135struct pl2303_private { 142struct pl2303_private {
@@ -182,6 +189,14 @@ static int pl2303_vendor_write(struct usb_serial *serial, u16 value, u16 index)
182 return 0; 189 return 0;
183} 190}
184 191
192static int pl2303_probe(struct usb_serial *serial,
193 const struct usb_device_id *id)
194{
195 usb_set_serial_data(serial, (void *)id->driver_info);
196
197 return 0;
198}
199
185static int pl2303_startup(struct usb_serial *serial) 200static int pl2303_startup(struct usb_serial *serial)
186{ 201{
187 struct pl2303_serial_private *spriv; 202 struct pl2303_serial_private *spriv;
@@ -209,6 +224,8 @@ static int pl2303_startup(struct usb_serial *serial)
209 dev_dbg(&serial->interface->dev, "device type: %d\n", type); 224 dev_dbg(&serial->interface->dev, "device type: %d\n", type);
210 225
211 spriv->type = type; 226 spriv->type = type;
227 spriv->quirks = (unsigned long)usb_get_serial_data(serial);
228
212 usb_set_serial_data(serial, spriv); 229 usb_set_serial_data(serial, spriv);
213 230
214 pl2303_vendor_read(serial, 0x8484, buf); 231 pl2303_vendor_read(serial, 0x8484, buf);
@@ -739,27 +756,18 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
739 unsigned char *data, 756 unsigned char *data,
740 unsigned int actual_length) 757 unsigned int actual_length)
741{ 758{
759 struct usb_serial *serial = port->serial;
760 struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
742 struct pl2303_private *priv = usb_get_serial_port_data(port); 761 struct pl2303_private *priv = usb_get_serial_port_data(port);
743 struct tty_struct *tty; 762 struct tty_struct *tty;
744 unsigned long flags; 763 unsigned long flags;
745 u8 status_idx = UART_STATE; 764 unsigned int status_idx = UART_STATE_INDEX;
746 u8 length = UART_STATE + 1;
747 u8 prev_line_status; 765 u8 prev_line_status;
748 u16 idv, idp;
749 766
750 idv = le16_to_cpu(port->serial->dev->descriptor.idVendor); 767 if (spriv->quirks & PL2303_QUIRK_UART_STATE_IDX0)
751 idp = le16_to_cpu(port->serial->dev->descriptor.idProduct); 768 status_idx = 0;
752
753 if (idv == SIEMENS_VENDOR_ID) {
754 if (idp == SIEMENS_PRODUCT_ID_X65 ||
755 idp == SIEMENS_PRODUCT_ID_SX1 ||
756 idp == SIEMENS_PRODUCT_ID_X75) {
757 length = 1;
758 status_idx = 0;
759 }
760 }
761 769
762 if (actual_length < length) 770 if (actual_length < status_idx + 1)
763 return; 771 return;
764 772
765 /* Save off the uart status for others to look at */ 773 /* Save off the uart status for others to look at */
@@ -892,6 +900,7 @@ static struct usb_serial_driver pl2303_device = {
892 .tiocmiwait = pl2303_tiocmiwait, 900 .tiocmiwait = pl2303_tiocmiwait,
893 .process_read_urb = pl2303_process_read_urb, 901 .process_read_urb = pl2303_process_read_urb,
894 .read_int_callback = pl2303_read_int_callback, 902 .read_int_callback = pl2303_read_int_callback,
903 .probe = pl2303_probe,
895 .attach = pl2303_startup, 904 .attach = pl2303_startup,
896 .release = pl2303_release, 905 .release = pl2303_release,
897 .port_probe = pl2303_port_probe, 906 .port_probe = pl2303_port_probe,