summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2005-01-16 05:56:56 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2005-01-16 05:56:56 +0000
commit2c3df4c3c7b34574293caab08c184c1881bab6a4 (patch)
treea85bf848a349bfac27e3e9235927fb69fb8d5d3a
parent52970e1252c7d01f033b194c526b0d6fd9597a60 (diff)
add support for the HX variant of the pl2303 from Pedro la Peu via
Waldemar Brodkorb.
-rw-r--r--sys/dev/usb/uplcom.c66
1 files changed, 64 insertions, 2 deletions
diff --git a/sys/dev/usb/uplcom.c b/sys/dev/usb/uplcom.c
index edc8b213ffb..192cedc4f16 100644
--- a/sys/dev/usb/uplcom.c
+++ b/sys/dev/usb/uplcom.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uplcom.c,v 1.18 2005/01/10 12:05:08 dlg Exp $ */
+/* $OpenBSD: uplcom.c,v 1.19 2005/01/16 05:56:55 dlg Exp $ */
/* $NetBSD: uplcom.c,v 1.29 2002/09/23 05:51:23 simonb Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -83,6 +83,7 @@ int uplcomdebug = 0;
#define UPLCOM_SET_REQUEST 0x01
#define UPLCOM_SET_CRTSCTS 0x41
+#define UPLCOM_HX_SET_CRTSCTS 0x61
#define RSAQ_STATUS_CTS 0x80
#define RSAQ_STATUS_DSR 0x02
#define RSAQ_STATUS_DCD 0x01
@@ -118,6 +119,7 @@ struct uplcom_softc {
u_char sc_lsr; /* Local status register */
u_char sc_msr; /* uplcom status register */
+ int sc_type_hx; /* HX variant */
};
/*
@@ -210,6 +212,7 @@ USB_ATTACH(uplcom)
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;
@@ -251,6 +254,25 @@ USB_ATTACH(uplcom)
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 suggest this will only be true for the HX
+ * variants. The datasheets disagree.
+ */
+ if (ddesc->bMaxPacketSize = 0x40) {
+ DPRINTF(("%s: Assuming HX variant\n", USBDEVNAME(sc->sc_dev)));
+ 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);
@@ -547,7 +569,8 @@ uplcom_set_crtscts(struct uplcom_softc *sc)
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 ? UPLCOM_HX_SET_CRTSCTS : UPLCOM_SET_CRTSCTS));
USETW(req.wLength, 0);
err = usbd_do_request(sc->sc_udev, &req, 0);
@@ -653,6 +676,8 @@ int
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)
@@ -673,6 +698,43 @@ uplcom_open(void *addr, int portno)
}
}
+ 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);
}