[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Uplcom(4) diff for PL-2303HX.



Adds support for the PL-2303HX. I am not certain that the detection 
method is sound. I don't have an older PL-2303 and Prolific has not 
provided the needed info.

If anyone has a uplcom(4) device (presently working or not) please test. 
I'm particularly interested if previous variants are incorrectly 
detected as the "HX" variant.


Index: sys/dev/usb/uplcom.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uplcom.c,v
retrieving revision 1.16
diff -u -r1.16 uplcom.c
--- sys/dev/usb/uplcom.c	26 Oct 2004 00:37:07 -0000	1.16
+++ sys/dev/usb/uplcom.c	18 Dec 2004 03:20:35 -0000
@@ -83,6 +83,7 @@
 
 #define	UPLCOM_SET_REQUEST	0x01
 #define	UPLCOM_SET_CRTSCTS	0x41
+#define	UPLCOM_HX_SET_CRTSCTS 0x61
 #define RSAQ_STATUS_DSR		0x02
 #define RSAQ_STATUS_DCD		0x01
 
@@ -109,6 +110,7 @@
 
 	u_char			sc_lsr;		/* Local status register */
 	u_char			sc_msr;		/* uplcom status register */
+	int			sc_type_hx;		/* HX variant */
 };
 
 /*
@@ -201,6 +203,7 @@
 	USB_ATTACH_START(uplcom, sc, uaa);
 	usbd_device_handle dev = uaa->device;
 	usb_config_descriptor_t *cdesc;
+	usb_device_descriptor_t *ddesc;
 	usb_interface_descriptor_t *id;
 	usb_endpoint_descriptor_t *ed;
 
@@ -242,6 +245,27 @@
 		USB_ATTACH_ERROR_RETURN;
 	}
 
+	/* get the device descriptor */
+	ddesc = usbd_get_device_descriptor(sc->sc_udev);
+
+	if (ddesc == NULL) {
+		printf("%s: failed to get device descriptor\n",
+			USBDEVNAME(sc->sc_dev));
+		sc->sc_dying = 1;
+		USB_ATTACH_ERROR_RETURN;
+	}
+
+	/*
+	 * The Linux driver suggests this will only be true for the
+	 * HX variants. The datasheets disagree.
+	 */
+	if (ddesc->bMaxPacketSize == 0x40) {
+		printf("%s: Assuming HX variant\n", devname);
+		sc->sc_type_hx = 1;
+	} else {
+		sc->sc_type_hx = 0;
+	}
+        
 	/* get the (first/common) interface */
 	err = usbd_device2interface_handle(dev, UPLCOM_IFACE_INDEX,
 							&sc->sc_iface);
@@ -529,7 +553,8 @@
 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
 	req.bRequest = UPLCOM_SET_REQUEST;
 	USETW(req.wValue, 0);
-	USETW(req.wIndex, UPLCOM_SET_CRTSCTS);
+	USETW(req.wIndex, (sc->sc_type_hx == 1) ? UPLCOM_HX_SET_CRTSCTS :
+		UPLCOM_SET_CRTSCTS);
 	USETW(req.wLength, 0);
 
 	err = usbd_do_request(sc->sc_udev, &req, 0);
@@ -632,6 +657,8 @@
 uplcom_open(void *addr, int portno)
 {
 	struct uplcom_softc *sc = addr;
+	usb_device_request_t req;
+	usbd_status uerr;
 	int err;
 
 	if (sc->sc_dying)
@@ -653,6 +680,44 @@
 		}
 	}
 
+	if (sc->sc_type_hx == 1) {
+		
+		/* 
+		* Undocumented (vendor unresponsive) - possibly changes
+		* flow control semantics. It is needed for HX variant devices.
+		*/
+		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+		req.bRequest = UPLCOM_SET_REQUEST;
+		USETW(req.wValue, 2);
+		USETW(req.wIndex, 0x44);
+		USETW(req.wLength, 0);
+ 
+		uerr = usbd_do_request(sc->sc_udev, &req, 0);
+		if (uerr)
+			return (EIO);
+	
+		/* Reset upstream data pipes */
+		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+		req.bRequest = UPLCOM_SET_REQUEST;
+		USETW(req.wValue, 8);
+		USETW(req.wIndex, 0);
+		USETW(req.wLength, 0);
+
+		uerr = usbd_do_request(sc->sc_udev, &req, 0);
+		if (uerr)
+			return (EIO);
+
+		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+		req.bRequest = UPLCOM_SET_REQUEST;
+		USETW(req.wValue, 9);
+		USETW(req.wIndex, 0);
+		USETW(req.wLength, 0);
+
+		uerr = usbd_do_request(sc->sc_udev, &req, 0);
+		if (uerr)
+			return (EIO);
+ 	}
+        
 	return (0);
 }



Visit your host, monkey.org