Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Feb 2021 09:32:44 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 671c393854a5 - stable/11 - MFC ea0efc370416: Add support for PL2303HXN to uplcom(4).
Message-ID:  <202102010932.1119Wiob051502@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/11 has been updated by hselasky:

URL: https://cgit.FreeBSD.org/src/commit/?id=671c393854a5ae60369beadfb74007e240bb18ab

commit 671c393854a5ae60369beadfb74007e240bb18ab
Author:     Hans Petter Selasky <hselasky@FreeBSD.org>
AuthorDate: 2021-01-07 14:34:26 +0000
Commit:     Hans Petter Selasky <hselasky@FreeBSD.org>
CommitDate: 2021-02-01 09:31:58 +0000

    MFC ea0efc370416:
    Add support for PL2303HXN to uplcom(4).
    
    Code changes in this commit were obtained from straight from OpenBSD's
    uplcom.c with almost no modification, the list of chip names and USB
    IDs was obtained from Linux.
    
    Differential Revision: https://reviews.freebsd.org/D27952
    Submitted by: tomli_tomli.me (Yifeng Li)
    Sponsored by: Mellanox Technologies // NVIDIA Networking
    
    (cherry picked from commit ea0efc37041640686fbfb226e80ee60e58cb17f1)
---
 share/man/man4/uplcom.4     |  4 +-
 sys/dev/usb/serial/uplcom.c | 94 +++++++++++++++++++++++++++++++++++++++------
 sys/dev/usb/usbdevs         |  6 +++
 3 files changed, 92 insertions(+), 12 deletions(-)

diff --git a/share/man/man4/uplcom.4 b/share/man/man4/uplcom.4
index b3f1fbb3ff18..ca29ee8d454d 100644
--- a/share/man/man4/uplcom.4
+++ b/share/man/man4/uplcom.4
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd April 26, 2017
+.Dd January 7, 2021
 .Dt UPLCOM 4
 .Os
 .Sh NAME
@@ -132,6 +132,8 @@ PLANEX USB-RS232 URS-03
 .It
 Prolific Generic USB-Serial Adapters
 .It
+Prolific Generic USB-Serial Adapters (HXN)
+.It
 Prolific Pharos USB-Serial Adapter
 .It
 RATOC REX-USB60
diff --git a/sys/dev/usb/serial/uplcom.c b/sys/dev/usb/serial/uplcom.c
index 27858af68692..0913cc7890d4 100644
--- a/sys/dev/usb/serial/uplcom.c
+++ b/sys/dev/usb/serial/uplcom.c
@@ -129,8 +129,13 @@ SYSCTL_INT(_hw_usb_uplcom, OID_AUTO, debug, CTLFLAG_RWTUN,
 #define	UPLCOM_BULK_BUF_SIZE 1024	/* bytes */
 
 #define	UPLCOM_SET_REQUEST		0x01
+#define	UPLCOM_SET_REQUEST_PL2303HXN	0x80
 #define	UPLCOM_SET_CRTSCTS		0x41
 #define	UPLCOM_SET_CRTSCTS_PL2303X	0x61
+#define	UPLCOM_SET_CRTSCTS_PL2303HXN	0xFA
+#define	UPLCOM_CLEAR_CRTSCTS_PL2303HXN	0xFF
+#define	UPLCOM_CRTSCTS_REG_PL2303HXN	0x0A
+#define	UPLCOM_STATUS_REG_PL2303HX	0x8080
 #define	RSAQ_STATUS_CTS			0x80
 #define	RSAQ_STATUS_OVERRUN_ERROR	0x40
 #define	RSAQ_STATUS_PARITY_ERROR	0x20 
@@ -143,6 +148,7 @@ SYSCTL_INT(_hw_usb_uplcom, OID_AUTO, debug, CTLFLAG_RWTUN,
 #define	TYPE_PL2303			0
 #define	TYPE_PL2303HX			1
 #define	TYPE_PL2303HXD			2
+#define	TYPE_PL2303HXN			3
 
 #define	UPLCOM_STATE_INDEX		8
 
@@ -286,6 +292,12 @@ static const STRUCT_USB_HOST_ID uplcom_devs[] = {
 	UPLCOM_DEV(PROLIFIC, MOTOROLA),		/* Motorola cable */
 	UPLCOM_DEV(PROLIFIC, PHAROS),		/* Prolific Pharos */
 	UPLCOM_DEV(PROLIFIC, PL2303),		/* Generic adapter */
+	UPLCOM_DEV(PROLIFIC, PL2303GC),		/* Generic adapter (PL2303HXN, type GC) */
+	UPLCOM_DEV(PROLIFIC, PL2303GB),		/* Generic adapter (PL2303HXN, type GB) */
+	UPLCOM_DEV(PROLIFIC, PL2303GT),		/* Generic adapter (PL2303HXN, type GT) */
+	UPLCOM_DEV(PROLIFIC, PL2303GL),		/* Generic adapter (PL2303HXN, type GL) */
+	UPLCOM_DEV(PROLIFIC, PL2303GE),		/* Generic adapter (PL2303HXN, type GE) */
+	UPLCOM_DEV(PROLIFIC, PL2303GS),		/* Generic adapter (PL2303HXN, type GS) */
 	UPLCOM_DEV(PROLIFIC, RSAQ2),		/* I/O DATA USB-RSAQ2 */
 	UPLCOM_DEV(PROLIFIC, RSAQ3),		/* I/O DATA USB-RSAQ3 */
 	UPLCOM_DEV(PROLIFIC, UIC_MSR206),	/* UIC MSR206 Card Reader */
@@ -365,6 +377,10 @@ uplcom_attach(device_t dev)
 	struct usb_device_descriptor *dd;
 	int error;
 
+	struct usb_device_request req;
+	usb_error_t err;
+	uint8_t buf[4];
+
 	DPRINTFN(11, "\n");
 
 	device_set_usb_desc(dev);
@@ -404,6 +420,25 @@ uplcom_attach(device_t dev)
 		break;
 	}
 
+	/*
+	 * The new chip revision PL2303HXN is only compatible with the new
+	 * UPLCOM_SET_REQUEST_PL2303HXN command. Issuing the old command
+	 * UPLCOM_SET_REQUEST to the new chip raises an error. Thus, PL2303HX
+	 * and PL2303HXN can be distinguished by issuing an old-style request
+	 * (on a status register) to the new chip and checking the error.
+	 */
+	if (sc->sc_chiptype == TYPE_PL2303HX) {
+		req.bmRequestType = UT_READ_VENDOR_DEVICE;
+		req.bRequest = UPLCOM_SET_REQUEST;
+		USETW(req.wValue, UPLCOM_STATUS_REG_PL2303HX);
+		req.wIndex[0] = sc->sc_data_iface_no;
+		req.wIndex[1] = 0;
+		USETW(req.wLength, 1);
+		err = usbd_do_request(sc->sc_udev, NULL, &req, buf);
+		if (err)
+			sc->sc_chiptype = TYPE_PL2303HXN;
+	}
+
 	switch (sc->sc_chiptype) {
 	case TYPE_PL2303:
 		DPRINTF("chiptype: 2303\n");
@@ -411,6 +446,9 @@ uplcom_attach(device_t dev)
 	case TYPE_PL2303HX:
 		DPRINTF("chiptype: 2303HX/TA\n");
 		break;
+	case TYPE_PL2303HXN:
+		DPRINTF("chiptype: 2303HXN\n");
+		break;
 	case TYPE_PL2303HXD:
 		DPRINTF("chiptype: 2303HXD/TB/RA/EA\n");
 		break;
@@ -472,7 +510,8 @@ uplcom_attach(device_t dev)
 		usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]);
 		usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]);
 		mtx_unlock(&sc->sc_mtx);
-	} else {
+	} else if (sc->sc_chiptype == TYPE_PL2303HX ||
+		   sc->sc_chiptype == TYPE_PL2303HXD) {
 		/* reset upstream data pipes */
 		if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE,
 		    UPLCOM_SET_REQUEST, 8, 0, 0) ||
@@ -480,6 +519,12 @@ uplcom_attach(device_t dev)
 		    UPLCOM_SET_REQUEST, 9, 0, 0)) {
 			goto detach;
 		}
+	} else if (sc->sc_chiptype == TYPE_PL2303HXN) {
+		/* reset upstream data pipes */
+		if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE,
+		    UPLCOM_SET_REQUEST_PL2303HXN, 0x07, 0x03, 0)) {
+			goto detach;
+		}
 	}
 
 	error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
@@ -543,6 +588,11 @@ uplcom_reset(struct uplcom_softc *sc, struct usb_device *udev)
 {
 	struct usb_device_request req;
 
+	if (sc->sc_chiptype == TYPE_PL2303HXN) {
+		/* PL2303HXN doesn't need this reset sequence */
+		return (0);
+	}
+
 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
 	req.bRequest = UPLCOM_SET_REQUEST;
 	USETW(req.wValue, 0);
@@ -580,6 +630,11 @@ uplcom_pl2303_init(struct usb_device *udev, uint8_t chiptype)
 {
 	int err;
 
+	if (chiptype == TYPE_PL2303HXN) {
+		/* PL2303HXN doesn't need this initialization sequence */
+		return (0);
+	}
+
 	if (uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1)
 	    || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 0, 0)
 	    || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1)
@@ -726,7 +781,7 @@ uplcom_pre_param(struct ucom_softc *ucom, struct termios *t)
 	 *
 	 * The PL2303 can only set specific baud rates, up to 1228800 baud.
 	 * The PL2303HX can set any baud rate up to 6Mb.
-	 * The PL2303HX rev. D can set any baud rate up to 12Mb.
+	 * The PL2303HX rev. D and PL2303HXN can set any baud rate up to 12Mb.
 	 *
 	 */
 
@@ -734,6 +789,10 @@ uplcom_pre_param(struct ucom_softc *ucom, struct termios *t)
 	if (t->c_ospeed & 0x80000000)
 		return 0;
 	switch (sc->sc_chiptype) {
+		case TYPE_PL2303HXN:
+			if (t->c_ospeed <= 12000000)
+				return (0);
+			break;
 		case TYPE_PL2303HXD:
 			if (t->c_ospeed <= 12000000)
 				return (0);
@@ -871,21 +930,34 @@ uplcom_cfg_param(struct ucom_softc *ucom, struct termios *t)
 		DPRINTF("crtscts = on\n");
 
 		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
-		req.bRequest = UPLCOM_SET_REQUEST;
-		USETW(req.wValue, 0);
-		if (sc->sc_chiptype != TYPE_PL2303)
-			USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X);
-		else
-			USETW(req.wIndex, UPLCOM_SET_CRTSCTS);
+		if (sc->sc_chiptype == TYPE_PL2303HXN) {
+			req.bRequest = UPLCOM_SET_REQUEST_PL2303HXN;
+			USETW(req.wValue, UPLCOM_CRTSCTS_REG_PL2303HXN);
+			USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303HXN);
+		} else {
+			req.bRequest = UPLCOM_SET_REQUEST;
+			USETW(req.wValue, 0);
+			if (sc->sc_chiptype != TYPE_PL2303)
+				USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X);
+			else
+				USETW(req.wIndex, UPLCOM_SET_CRTSCTS);
+		}
 		USETW(req.wLength, 0);
 
 		ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
 		    &req, NULL, 0, 1000);
 	} else {
 		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
-		req.bRequest = UPLCOM_SET_REQUEST;
-		USETW(req.wValue, 0);
-		USETW(req.wIndex, 0);
+		if (sc->sc_chiptype == TYPE_PL2303HXN) {
+			req.bRequest = UPLCOM_SET_REQUEST_PL2303HXN;
+			USETW(req.wValue, UPLCOM_CRTSCTS_REG_PL2303HXN);
+			USETW(req.wIndex, UPLCOM_CLEAR_CRTSCTS_PL2303HXN);
+		}
+		else {
+			req.bRequest = UPLCOM_SET_REQUEST;
+			USETW(req.wValue, 0);
+			USETW(req.wIndex, 0);
+		}
 		USETW(req.wLength, 0);
 		ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
 		    &req, NULL, 0, 1000);
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 5d52ff0f7217..2bb5e05035f6 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -3654,6 +3654,12 @@ product PROLIFIC MICROMAX_610U	0x0612	Micromax 610U
 product PROLIFIC DCU11		0x1234	DCU-11 Phone Cable
 product PROLIFIC UIC_MSR206	0x206a	UIC MSR206 Card Reader
 product PROLIFIC PL2303		0x2303	PL2303 Serial (ATEN/IOGEAR UC232A)
+product PROLIFIC PL2303GC	0x23a3	PL2303HXN Serial, type GC
+product PROLIFIC PL2303GB	0x23b3	PL2303HXN Serial, type GB
+product PROLIFIC PL2303GT	0x23c3	PL2303HXN Serial, type GT
+product PROLIFIC PL2303GL	0x23d3	PL2303HXN Serial, type GL
+product PROLIFIC PL2303GE	0x23e3	PL2303HXN Serial, type GE
+product PROLIFIC PL2303GS	0x23f3	PL2303HXN Serial, type GS
 product PROLIFIC PL2305		0x2305	Parallel printer
 product PROLIFIC ATAPI4		0x2307	ATAPI-4 Controller
 product PROLIFIC PL2501		0x2501	PL2501 Host-Host interface



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202102010932.1119Wiob051502>