|
@@ -4,11 +4,6 @@
|
|
|
* Copyright (C) 2001-2007 Greg Kroah-Hartman (greg@kroah.com)
|
|
|
* Copyright (C) 2003 IBM Corp.
|
|
|
*
|
|
|
- * Copyright (C) 2009, 2013 Frank Schäfer <fschaefer.oss@googlemail.com>
|
|
|
- * - fixes, improvements and documentation for the baud rate encoding methods
|
|
|
- * Copyright (C) 2013 Reinhard Max <max@suse.de>
|
|
|
- * - fixes and improvements for the divisor based baud rate encoding method
|
|
|
- *
|
|
|
* Original driver for 2.2.x by anonymous
|
|
|
*
|
|
|
* This program is free software; you can redistribute it and/or
|
|
@@ -134,18 +129,10 @@ MODULE_DEVICE_TABLE(usb, id_table);
|
|
|
|
|
|
|
|
|
enum pl2303_type {
|
|
|
- type_0, /* H version ? */
|
|
|
- type_1, /* H version ? */
|
|
|
- HX_TA, /* HX(A) / X(A) / TA version */ /* TODO: improve */
|
|
|
- HXD_EA_RA_SA, /* HXD / EA / RA / SA version */ /* TODO: improve */
|
|
|
- TB, /* TB version */
|
|
|
- HX_CLONE, /* Cheap and less functional clone of the HX chip */
|
|
|
+ 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 */
|
|
|
};
|
|
|
-/*
|
|
|
- * NOTE: don't know the difference between type 0 and type 1,
|
|
|
- * until someone from Prolific tells us...
|
|
|
- * TODO: distinguish between X/HX, TA and HXD, EA, RA, SA variants
|
|
|
- */
|
|
|
|
|
|
struct pl2303_serial_private {
|
|
|
enum pl2303_type type;
|
|
@@ -185,7 +172,6 @@ static int pl2303_startup(struct usb_serial *serial)
|
|
|
{
|
|
|
struct pl2303_serial_private *spriv;
|
|
|
enum pl2303_type type = type_0;
|
|
|
- char *type_str = "unknown (treating as type_0)";
|
|
|
unsigned char *buf;
|
|
|
|
|
|
spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
|
|
@@ -198,53 +184,15 @@ static int pl2303_startup(struct usb_serial *serial)
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
- if (serial->dev->descriptor.bDeviceClass == 0x02) {
|
|
|
+ if (serial->dev->descriptor.bDeviceClass == 0x02)
|
|
|
type = type_0;
|
|
|
- type_str = "type_0";
|
|
|
- } else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) {
|
|
|
- /*
|
|
|
- * NOTE: The bcdDevice version is the only difference between
|
|
|
- * the device descriptors of the X/HX, HXD, EA, RA, SA, TA, TB
|
|
|
- */
|
|
|
- if (le16_to_cpu(serial->dev->descriptor.bcdDevice) == 0x300) {
|
|
|
- /* Check if the device is a clone */
|
|
|
- pl2303_vendor_read(0x9494, 0, serial, buf);
|
|
|
- /*
|
|
|
- * NOTE: Not sure if this read is really needed.
|
|
|
- * The HX returns 0x00, the clone 0x02, but the Windows
|
|
|
- * driver seems to ignore the value and continues.
|
|
|
- */
|
|
|
- pl2303_vendor_write(0x0606, 0xaa, serial);
|
|
|
- pl2303_vendor_read(0x8686, 0, serial, buf);
|
|
|
- if (buf[0] != 0xaa) {
|
|
|
- type = HX_CLONE;
|
|
|
- type_str = "X/HX clone (limited functionality)";
|
|
|
- } else {
|
|
|
- type = HX_TA;
|
|
|
- type_str = "X/HX/TA";
|
|
|
- }
|
|
|
- pl2303_vendor_write(0x0606, 0x00, serial);
|
|
|
- } else if (le16_to_cpu(serial->dev->descriptor.bcdDevice)
|
|
|
- == 0x400) {
|
|
|
- type = HXD_EA_RA_SA;
|
|
|
- type_str = "HXD/EA/RA/SA";
|
|
|
- } else if (le16_to_cpu(serial->dev->descriptor.bcdDevice)
|
|
|
- == 0x500) {
|
|
|
- type = TB;
|
|
|
- type_str = "TB";
|
|
|
- } else {
|
|
|
- dev_info(&serial->interface->dev,
|
|
|
- "unknown/unsupported device type\n");
|
|
|
- kfree(spriv);
|
|
|
- kfree(buf);
|
|
|
- return -ENODEV;
|
|
|
- }
|
|
|
- } else if (serial->dev->descriptor.bDeviceClass == 0x00
|
|
|
- || serial->dev->descriptor.bDeviceClass == 0xFF) {
|
|
|
+ else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
|
|
|
+ type = HX;
|
|
|
+ else if (serial->dev->descriptor.bDeviceClass == 0x00)
|
|
|
type = type_1;
|
|
|
- type_str = "type_1";
|
|
|
- }
|
|
|
- dev_dbg(&serial->interface->dev, "device type: %s\n", type_str);
|
|
|
+ else if (serial->dev->descriptor.bDeviceClass == 0xFF)
|
|
|
+ type = type_1;
|
|
|
+ dev_dbg(&serial->interface->dev, "device type: %d\n", type);
|
|
|
|
|
|
spriv->type = type;
|
|
|
usb_set_serial_data(serial, spriv);
|
|
@@ -259,10 +207,10 @@ static int pl2303_startup(struct usb_serial *serial)
|
|
|
pl2303_vendor_read(0x8383, 0, serial, buf);
|
|
|
pl2303_vendor_write(0, 1, serial);
|
|
|
pl2303_vendor_write(1, 0, serial);
|
|
|
- if (type == type_0 || type == type_1)
|
|
|
- pl2303_vendor_write(2, 0x24, serial);
|
|
|
- else
|
|
|
+ if (type == HX)
|
|
|
pl2303_vendor_write(2, 0x44, serial);
|
|
|
+ else
|
|
|
+ pl2303_vendor_write(2, 0x24, serial);
|
|
|
|
|
|
kfree(buf);
|
|
|
return 0;
|
|
@@ -316,174 +264,65 @@ static int pl2303_set_control_lines(struct usb_serial_port *port, u8 value)
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
-static int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type,
|
|
|
- u8 buf[4])
|
|
|
+static void pl2303_encode_baudrate(struct tty_struct *tty,
|
|
|
+ struct usb_serial_port *port,
|
|
|
+ u8 buf[4])
|
|
|
{
|
|
|
- /*
|
|
|
- * NOTE: Only the values defined in baud_sup are supported !
|
|
|
- * => if unsupported values are set, the PL2303 uses 9600 baud instead
|
|
|
- * => HX clones just don't work at unsupported baud rates < 115200 baud,
|
|
|
- * for baud rates > 115200 they run at 115200 baud
|
|
|
- */
|
|
|
const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600,
|
|
|
- 4800, 7200, 9600, 14400, 19200, 28800, 38400,
|
|
|
- 57600, 115200, 230400, 460800, 614400, 921600,
|
|
|
- 1228800, 2457600, 3000000, 6000000, 12000000 };
|
|
|
+ 4800, 7200, 9600, 14400, 19200, 28800, 38400,
|
|
|
+ 57600, 115200, 230400, 460800, 500000, 614400,
|
|
|
+ 921600, 1228800, 2457600, 3000000, 6000000 };
|
|
|
+
|
|
|
+ struct usb_serial *serial = port->serial;
|
|
|
+ struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
|
|
|
+ int baud;
|
|
|
+ int i;
|
|
|
+
|
|
|
/*
|
|
|
- * NOTE: With the exception of type_0/1 devices, the following
|
|
|
- * additional baud rates are supported (tested with HX rev. 3A only):
|
|
|
- * 110*, 56000*, 128000, 134400, 161280, 201600, 256000*, 268800,
|
|
|
- * 403200, 806400. (*: not HX and HX clones)
|
|
|
- *
|
|
|
- * Maximum values: HXD, TB: 12000000; HX, TA: 6000000;
|
|
|
- * type_0+1: 1228800; RA: 921600; HX clones, SA: 115200
|
|
|
- *
|
|
|
- * As long as we are not using this encoding method for anything else
|
|
|
- * than the type_0+1, HX and HX clone chips, there is no point in
|
|
|
- * complicating the code to support them.
|
|
|
+ * NOTE: Only the values defined in baud_sup are supported!
|
|
|
+ * => if unsupported values are set, the PL2303 seems to use
|
|
|
+ * 9600 baud (at least my PL2303X always does)
|
|
|
*/
|
|
|
- int i;
|
|
|
+ baud = tty_get_baud_rate(tty);
|
|
|
+ dev_dbg(&port->dev, "baud requested = %d\n", baud);
|
|
|
+ if (!baud)
|
|
|
+ return;
|
|
|
|
|
|
/* Set baudrate to nearest supported value */
|
|
|
for (i = 0; i < ARRAY_SIZE(baud_sup); ++i) {
|
|
|
if (baud_sup[i] > baud)
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
if (i == ARRAY_SIZE(baud_sup))
|
|
|
baud = baud_sup[i - 1];
|
|
|
else if (i > 0 && (baud_sup[i] - baud) > (baud - baud_sup[i - 1]))
|
|
|
baud = baud_sup[i - 1];
|
|
|
else
|
|
|
baud = baud_sup[i];
|
|
|
- /* Respect the chip type specific baud rate limits */
|
|
|
- /*
|
|
|
- * FIXME: as long as we don't know how to distinguish between the
|
|
|
- * HXD, EA, RA, and SA chip variants, allow the max. value of 12M.
|
|
|
- */
|
|
|
- if (type == HX_TA)
|
|
|
- baud = min_t(int, baud, 6000000);
|
|
|
- else if (type == type_0 || type == type_1)
|
|
|
- baud = min_t(int, baud, 1228800);
|
|
|
- else if (type == HX_CLONE)
|
|
|
- baud = min_t(int, baud, 115200);
|
|
|
- /* Direct (standard) baud rate encoding method */
|
|
|
- put_unaligned_le32(baud, buf);
|
|
|
-
|
|
|
- return baud;
|
|
|
-}
|
|
|
|
|
|
-static int pl2303_baudrate_encode_divisor(int baud, enum pl2303_type type,
|
|
|
- u8 buf[4])
|
|
|
-{
|
|
|
- /*
|
|
|
- * Divisor based baud rate encoding method
|
|
|
- *
|
|
|
- * NOTE: HX clones do NOT support this method.
|
|
|
- * It's not clear if the type_0/1 chips support it.
|
|
|
- *
|
|
|
- * divisor = 12MHz * 32 / baudrate = 2^A * B
|
|
|
- *
|
|
|
- * with
|
|
|
- *
|
|
|
- * A = buf[1] & 0x0e
|
|
|
- * B = buf[0] + (buf[1] & 0x01) << 8
|
|
|
- *
|
|
|
- * Special cases:
|
|
|
- * => 8 < B < 16: device seems to work not properly
|
|
|
- * => B <= 8: device uses the max. value B = 512 instead
|
|
|
- */
|
|
|
- unsigned int A, B;
|
|
|
+ /* type_0, type_1 only support up to 1228800 baud */
|
|
|
+ if (spriv->type != HX)
|
|
|
+ baud = min_t(int, baud, 1228800);
|
|
|
|
|
|
- /*
|
|
|
- * NOTE: The Windows driver allows maximum baud rates of 110% of the
|
|
|
- * specified maximium value.
|
|
|
- * Quick tests with early (2004) HX (rev. A) chips suggest, that even
|
|
|
- * higher baud rates (up to the maximum of 24M baud !) are working fine,
|
|
|
- * but that should really be tested carefully in "real life" scenarios
|
|
|
- * before removing the upper limit completely.
|
|
|
- * Baud rates smaller than the specified 75 baud are definitely working
|
|
|
- * fine.
|
|
|
- */
|
|
|
- if (type == type_0 || type == type_1)
|
|
|
- baud = min_t(int, baud, 1228800 * 1.1);
|
|
|
- else if (type == HX_TA)
|
|
|
- baud = min_t(int, baud, 6000000 * 1.1);
|
|
|
- else if (type == HXD_EA_RA_SA)
|
|
|
- /* HXD, EA: 12Mbps; RA: 1Mbps; SA: 115200 bps */
|
|
|
- /*
|
|
|
- * FIXME: as long as we don't know how to distinguish between
|
|
|
- * these chip variants, allow the max. of these values
|
|
|
- */
|
|
|
- baud = min_t(int, baud, 12000000 * 1.1);
|
|
|
- else if (type == TB)
|
|
|
- baud = min_t(int, baud, 12000000 * 1.1);
|
|
|
- /* Determine factors A and B */
|
|
|
- A = 0;
|
|
|
- B = 12000000 * 32 / baud; /* 12MHz */
|
|
|
- B <<= 1; /* Add one bit for rounding */
|
|
|
- while (B > (512 << 1) && A <= 14) {
|
|
|
- A += 2;
|
|
|
- B >>= 2;
|
|
|
- }
|
|
|
- if (A > 14) { /* max. divisor = min. baudrate reached */
|
|
|
- A = 14;
|
|
|
- B = 512;
|
|
|
- /* => ~45.78 baud */
|
|
|
+ if (baud <= 115200) {
|
|
|
+ put_unaligned_le32(baud, buf);
|
|
|
} else {
|
|
|
- B = (B + 1) >> 1; /* Round the last bit */
|
|
|
- }
|
|
|
- /* Handle special cases */
|
|
|
- if (B == 512)
|
|
|
- B = 0; /* also: 1 to 8 */
|
|
|
- else if (B < 16)
|
|
|
/*
|
|
|
- * NOTE: With the current algorithm this happens
|
|
|
- * only for A=0 and means that the min. divisor
|
|
|
- * (respectively: the max. baudrate) is reached.
|
|
|
+ * Apparently the formula for higher speeds is:
|
|
|
+ * baudrate = 12M * 32 / (2^buf[1]) / buf[0]
|
|
|
*/
|
|
|
- B = 16; /* => 24 MBaud */
|
|
|
- /* Encode the baud rate */
|
|
|
- buf[3] = 0x80; /* Select divisor encoding method */
|
|
|
- buf[2] = 0;
|
|
|
- buf[1] = (A & 0x0e); /* A */
|
|
|
- buf[1] |= ((B & 0x100) >> 8); /* MSB of B */
|
|
|
- buf[0] = B & 0xff; /* 8 LSBs of B */
|
|
|
- /* Calculate the actual/resulting baud rate */
|
|
|
- if (B <= 8)
|
|
|
- B = 512;
|
|
|
- baud = 12000000 * 32 / ((1 << A) * B);
|
|
|
-
|
|
|
- return baud;
|
|
|
-}
|
|
|
-
|
|
|
-static void pl2303_encode_baudrate(struct tty_struct *tty,
|
|
|
- struct usb_serial_port *port,
|
|
|
- enum pl2303_type type,
|
|
|
- u8 buf[4])
|
|
|
-{
|
|
|
- int baud;
|
|
|
+ unsigned tmp = 12000000 * 32 / baud;
|
|
|
+ buf[3] = 0x80;
|
|
|
+ buf[2] = 0;
|
|
|
+ buf[1] = (tmp >= 256);
|
|
|
+ while (tmp >= 256) {
|
|
|
+ tmp >>= 2;
|
|
|
+ buf[1] <<= 1;
|
|
|
+ }
|
|
|
+ buf[0] = tmp;
|
|
|
+ }
|
|
|
|
|
|
- baud = tty_get_baud_rate(tty);
|
|
|
- dev_dbg(&port->dev, "baud requested = %d\n", baud);
|
|
|
- if (!baud)
|
|
|
- return;
|
|
|
- /*
|
|
|
- * There are two methods for setting/encoding the baud rate
|
|
|
- * 1) Direct method: encodes the baud rate value directly
|
|
|
- * => supported by all chip types
|
|
|
- * 2) Divisor based method: encodes a divisor to a base value (12MHz*32)
|
|
|
- * => not supported by HX clones (and likely type_0/1 chips)
|
|
|
- *
|
|
|
- * NOTE: Although the divisor based baud rate encoding method is much
|
|
|
- * more flexible, some of the standard baud rate values can not be
|
|
|
- * realized exactly. But the difference is very small (max. 0.2%) and
|
|
|
- * the device likely uses the same baud rate generator for both methods
|
|
|
- * so that there is likley no difference.
|
|
|
- */
|
|
|
- if (type == type_0 || type == type_1 || type == HX_CLONE)
|
|
|
- baud = pl2303_baudrate_encode_direct(baud, type, buf);
|
|
|
- else
|
|
|
- baud = pl2303_baudrate_encode_divisor(baud, type, buf);
|
|
|
/* Save resulting baud rate */
|
|
|
tty_encode_baud_rate(tty, baud, baud);
|
|
|
dev_dbg(&port->dev, "baud set = %d\n", baud);
|
|
@@ -540,8 +379,8 @@ static void pl2303_set_termios(struct tty_struct *tty,
|
|
|
dev_dbg(&port->dev, "data bits = %d\n", buf[6]);
|
|
|
}
|
|
|
|
|
|
- /* For reference: buf[0]:buf[3] baud rate value */
|
|
|
- pl2303_encode_baudrate(tty, port, spriv->type, buf);
|
|
|
+ /* For reference buf[0]:buf[3] baud rate value */
|
|
|
+ pl2303_encode_baudrate(tty, port, &buf[0]);
|
|
|
|
|
|
/* For reference buf[4]=0 is 1 stop bits */
|
|
|
/* For reference buf[4]=1 is 1.5 stop bits */
|
|
@@ -618,10 +457,10 @@ static void pl2303_set_termios(struct tty_struct *tty,
|
|
|
dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf);
|
|
|
|
|
|
if (C_CRTSCTS(tty)) {
|
|
|
- if (spriv->type == type_0 || spriv->type == type_1)
|
|
|
- pl2303_vendor_write(0x0, 0x41, serial);
|
|
|
- else
|
|
|
+ if (spriv->type == HX)
|
|
|
pl2303_vendor_write(0x0, 0x61, serial);
|
|
|
+ else
|
|
|
+ pl2303_vendor_write(0x0, 0x41, serial);
|
|
|
} else {
|
|
|
pl2303_vendor_write(0x0, 0x0, serial);
|
|
|
}
|
|
@@ -658,7 +497,7 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|
|
struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
|
|
|
int result;
|
|
|
|
|
|
- if (spriv->type == type_0 || spriv->type == type_1) {
|
|
|
+ if (spriv->type != HX) {
|
|
|
usb_clear_halt(serial->dev, port->write_urb->pipe);
|
|
|
usb_clear_halt(serial->dev, port->read_urb->pipe);
|
|
|
} else {
|
|
@@ -833,7 +672,6 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
|
|
|
result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
|
|
|
BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
|
|
|
0, NULL, 0, 100);
|
|
|
- /* NOTE: HX clones don't support sending breaks, -EPIPE is returned */
|
|
|
if (result)
|
|
|
dev_err(&port->dev, "error sending break = %d\n", result);
|
|
|
}
|