[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Uplcom(4) diff for PL-2303HX.
- To: tech_(_at_)_openbsd_(_dot_)_org
- Subject: Uplcom(4) diff for PL-2303HX.
- From: Pedro la Peu <pedro_(_at_)_am-gen_(_dot_)_org>
- Date: Sat, 18 Dec 2004 03:52:55 +0000
- Reply-to: pedro_(_at_)_am-gen_(_dot_)_org
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