>From b9fd71c64d4d0d939a7a27e08a74d81f960ff5ea Mon Sep 17 00:00:00 2001 From: Charles Yeh <charlesyeh522@xxxxxxxxx> Date: Sat, 15 Dec 2018 07:10:17 +0800 Subject: [PATCH] Add Proliic new chip: PL2303TB & PL2303N(G) Add new PID to support PL2303TB Add mew PID to support PL2303(N)GC/GB/GS/GT/GL/GE Add new request to support PL2303N(G) Signed-off-by: Charles Yeh <charlesyeh522@xxxxxxxxx> --- drivers/usb/serial/pl2303.c | 106 +++++++++++++++++++++++++++++------- drivers/usb/serial/pl2303.h | 11 ++++ 2 files changed, 97 insertions(+), 20 deletions(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index a4e0d13fc121..0001b527f07f 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -31,6 +31,8 @@ #define PL2303_QUIRK_UART_STATE_IDX0 BIT(0) #define PL2303_QUIRK_LEGACY BIT(1) #define PL2303_QUIRK_ENDPOINT_HACK BIT(2) +#define PL2303_QUIRK_LEGACY_HX BIT(3) /* old IC type */ +#define PL2303_QUIRK_LEGACY_N BIT(4) /* new IC type */ static const struct usb_device_id id_table[] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID), @@ -46,6 +48,13 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_TB) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303G_PRODUCT_ID_GC) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303G_PRODUCT_ID_GB) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303G_PRODUCT_ID_GT) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303G_PRODUCT_ID_GL) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303G_PRODUCT_ID_GE) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303G_PRODUCT_ID_GS) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID), @@ -123,9 +132,11 @@ MODULE_DEVICE_TABLE(usb, id_table); #define VENDOR_WRITE_REQUEST_TYPE 0x40 #define VENDOR_WRITE_REQUEST 0x01 +#define VENDOR_WRITE_NREQUEST 0x80 #define VENDOR_READ_REQUEST_TYPE 0xc0 #define VENDOR_READ_REQUEST 0x01 +#define VENDOR_READ_NREQUEST 0x81 #define UART_STATE_INDEX 8 #define UART_STATE_MSR_MASK 0x8b @@ -144,6 +155,7 @@ static void pl2303_set_break(struct usb_serial_port *port, bool enable); enum pl2303_type { TYPE_01, /* Type 0 and 1 (difference unknown) */ TYPE_HX, /* HX version of the pl2303 chip */ + TYPE_HXN, /* HXN version of the pl2303 chip */ TYPE_COUNT }; @@ -172,6 +184,11 @@ static const struct pl2303_type_data pl2303_type_data[TYPE_COUNT] = { }, [TYPE_HX] = { .max_baud_rate = 12000000, + .quirks = PL2303_QUIRK_LEGACY_HX, /* old chip type */ + }, + [TYPE_HXN] = { + .max_baud_rate = 12000000, + .quirks = PL2303_QUIRK_LEGACY_N, /* New chip type */ }, }; @@ -179,10 +196,16 @@ static int pl2303_vendor_read(struct usb_serial *serial, u16 value, unsigned char buf[1]) { struct device *dev = &serial->interface->dev; + struct pl2303_serial_private *spriv = usb_get_serial_data(serial); int res; + __u8 request; + + /* old / new read request ?*/ + if (spriv->quirks & PL2303_QUIRK_LEGACY_N) request= VENDOR_READ_NREQUEST; + else request= VENDOR_READ_REQUEST; res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE, + request, VENDOR_READ_REQUEST_TYPE, value, 0, buf, 1, 100); if (res != 1) { dev_err(dev, "%s - failed to read [%04x]: %d\n", __func__, @@ -201,12 +224,18 @@ static int pl2303_vendor_read(struct usb_serial *serial, u16 value, static int pl2303_vendor_write(struct usb_serial *serial, u16 value, u16 index) { struct device *dev = &serial->interface->dev; + struct pl2303_serial_private *spriv = usb_get_serial_data(serial); int res; + __u8 request; dev_dbg(dev, "%s - [%04x] = %02x\n", __func__, value, index); + /* old / new write request ? */ + if (spriv->quirks & PL2303_QUIRK_LEGACY_N) request= VENDOR_WRITE_NREQUEST; + else request= VENDOR_WRITE_REQUEST; + res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, + request, VENDOR_WRITE_REQUEST_TYPE, value, index, NULL, 0, 100); if (res) { dev_err(dev, "%s - failed to write [%04x]: %d\n", __func__, @@ -286,6 +315,7 @@ static int pl2303_startup(struct usb_serial *serial) struct pl2303_serial_private *spriv; enum pl2303_type type = TYPE_01; unsigned char *buf; + int res; spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); if (!spriv) @@ -307,26 +337,38 @@ static int pl2303_startup(struct usb_serial *serial) type = TYPE_01; /* type 1 */ dev_dbg(&serial->interface->dev, "device type: %d\n", type); + /* new chip ? */ + if(serial->dev->descriptor.bcdUSB == 0x0200) { + res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE, + 0x8484, 0, buf, 1, 100); + if (res != 1) { + type = TYPE_HXN; /* type 2 */ + } + } + spriv->type = &pl2303_type_data[type]; spriv->quirks = (unsigned long)usb_get_serial_data(serial); spriv->quirks |= spriv->type->quirks; usb_set_serial_data(serial, spriv); - pl2303_vendor_read(serial, 0x8484, buf); - pl2303_vendor_write(serial, 0x0404, 0); - pl2303_vendor_read(serial, 0x8484, buf); - pl2303_vendor_read(serial, 0x8383, buf); - pl2303_vendor_read(serial, 0x8484, buf); - pl2303_vendor_write(serial, 0x0404, 1); - pl2303_vendor_read(serial, 0x8484, buf); - pl2303_vendor_read(serial, 0x8383, buf); - pl2303_vendor_write(serial, 0, 1); - pl2303_vendor_write(serial, 1, 0); - if (spriv->quirks & PL2303_QUIRK_LEGACY) - pl2303_vendor_write(serial, 2, 0x24); - else - pl2303_vendor_write(serial, 2, 0x44); + if(type != TYPE_HXN) { + pl2303_vendor_read(serial, 0x8484, buf); + pl2303_vendor_write(serial, 0x0404, 0); + pl2303_vendor_read(serial, 0x8484, buf); + pl2303_vendor_read(serial, 0x8383, buf); + pl2303_vendor_read(serial, 0x8484, buf); + pl2303_vendor_write(serial, 0x0404, 1); + pl2303_vendor_read(serial, 0x8484, buf); + pl2303_vendor_read(serial, 0x8383, buf); + pl2303_vendor_write(serial, 0, 1); + pl2303_vendor_write(serial, 1, 0); + if (spriv->quirks & PL2303_QUIRK_LEGACY) + pl2303_vendor_write(serial, 2, 0x24); + else + pl2303_vendor_write(serial, 2, 0x44); + } kfree(buf); @@ -673,13 +715,33 @@ static void pl2303_set_termios(struct tty_struct *tty, if (C_CRTSCTS(tty)) { if (spriv->quirks & PL2303_QUIRK_LEGACY) pl2303_vendor_write(serial, 0x0, 0x41); + else if(spriv->quirks & PL2303_QUIRK_LEGACY_N) + pl2303_vendor_write(serial, 0x0A, 0xFA); /* New chip */ else pl2303_vendor_write(serial, 0x0, 0x61); } else if (I_IXON(tty) && !I_IXANY(tty) && START_CHAR(tty) == 0x11 && STOP_CHAR(tty) == 0x13) { - pl2303_vendor_write(serial, 0x0, 0xc0); + if(spriv->quirks & PL2303_QUIRK_LEGACY_N) + pl2303_vendor_write(serial, 0x0A, 0xEE); /* New chip */ + else + pl2303_vendor_write(serial, 0x0, 0xc0); } else { - pl2303_vendor_write(serial, 0x0, 0x0); + if(spriv->quirks & PL2303_QUIRK_LEGACY_N) + pl2303_vendor_write(serial, 0x0A, 0xFF); /* New chip */ + else + pl2303_vendor_write(serial, 0x0, 0x0); + } + + /* Old chip, External Pull-Up Mode */ + if(spriv->quirks & PL2303_QUIRK_LEGACY_HX){ + pl2303_vendor_read(serial, 0x8484, buf); + pl2303_vendor_write(serial, 0x0404, 0x09); + pl2303_vendor_read(serial, 0x8484, buf); + pl2303_vendor_read(serial, 0x8383, buf); + if((u16)*buf & 0x08){ + pl2303_vendor_write(serial, 0x0, 0x31); + pl2303_vendor_write(serial, 0x1, 0x01); + } } kfree(buf); @@ -720,8 +782,12 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) usb_clear_halt(serial->dev, port->read_urb->pipe); } else { /* reset upstream data pipes */ - pl2303_vendor_write(serial, 8, 0); - pl2303_vendor_write(serial, 9, 0); + if(spriv->quirks & PL2303_QUIRK_LEGACY_N) + pl2303_vendor_write(serial, 7, 0); /* reset new chip */ + else { + pl2303_vendor_write(serial, 8, 0); + pl2303_vendor_write(serial, 9, 0); + } } /* Setup termios */ diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 26965cc23c17..686f1cfca564 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -20,6 +20,17 @@ #define PL2303_PRODUCT_ID_MOTOROLA 0x0307 #define PL2303_PRODUCT_ID_ZTEK 0xe1f1 +/* PL2303TB */ +#define PL2303_PRODUCT_ID_TB 0x2304 + +/* PL2303N */ +#define PL2303G_PRODUCT_ID_GC 0x23A3 +#define PL2303G_PRODUCT_ID_GB 0x23B3 +#define PL2303G_PRODUCT_ID_GT 0x23C3 +#define PL2303G_PRODUCT_ID_GL 0x23D3 +#define PL2303G_PRODUCT_ID_GE 0x23E3 +#define PL2303G_PRODUCT_ID_GS 0x23F3 + #define ATEN_VENDOR_ID 0x0557 #define ATEN_VENDOR_ID2 0x0547 #define ATEN_PRODUCT_ID 0x2008 -- 2.19.1 Charles Yeh <charlesyeh522@xxxxxxxxx> 於 2018年12月14日 週五 下午4:44寫道: > > Hi Geeg, > > Finally.. I feel very close to submit patch.. > I will look at "scripts/checkpatch.pl" > > Thanks! > > Charles > > Greg KH <gregkh@xxxxxxxxxxxxxxxxxxx> 於 2018年12月14日 週五 下午4:22寫道: > > > > On Fri, Dec 14, 2018 at 03:41:26PM +0800, Charles Yeh wrote: > > > Hi Greg, > > > The new patch file is attached: > > > 0001-Add-Proliic-new-chip-PL2303TB-PL2303N-G.patch > > > Please you kindly check... > > > > Much better, thanks. > > > > But no need to send this as an attachment, just send it all directly as > > a single email. > > > > Also, please run your patch through scripts/checkpatch.pl before sending > > it out. It will point out a number of coding style issues that the > > patch has (look at the if() statement formatting) that needs to be > > resolved before this can be accepted. > > > > Almost there! > > > > thanks, > > > > greg k-h