Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/usb Support for the HX version of the chip.
details: https://anonhg.NetBSD.org/src/rev/5b5a3604ae1a
branches: trunk
changeset: 580860:5b5a3604ae1a
user: augustss <augustss%NetBSD.org@localhost>
date: Wed May 11 20:25:01 2005 +0000
description:
Support for the HX version of the chip.
Contributed by a donor that wishes to remain anonymous.
diffstat:
sys/dev/usb/uplcom.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 68 insertions(+), 6 deletions(-)
diffs (161 lines):
diff -r dae336d09b0b -r 5b5a3604ae1a sys/dev/usb/uplcom.c
--- a/sys/dev/usb/uplcom.c Wed May 11 20:19:24 2005 +0000
+++ b/sys/dev/usb/uplcom.c Wed May 11 20:25:01 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uplcom.c,v 1.42 2005/05/11 10:02:28 augustss Exp $ */
+/* $NetBSD: uplcom.c,v 1.43 2005/05/11 20:25:01 augustss Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uplcom.c,v 1.42 2005/05/11 10:02:28 augustss Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uplcom.c,v 1.43 2005/05/11 20:25:01 augustss Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -80,7 +80,8 @@
#define UPLCOM_SECOND_IFACE_INDEX 1
#define UPLCOM_SET_REQUEST 0x01
-#define UPLCOM_SET_CRTSCTS 0x41
+#define UPLCOM_SET_CRTSCTS_0 0x41
+#define UPLCOM_SET_CRTSCTS_HX 0x61
#define RSAQ_STATUS_DSR 0x02
#define RSAQ_STATUS_DCD 0x01
@@ -93,6 +94,11 @@
#define UPLCOM_FLOW_OUT_XON 0x0080
#define UPLCOM_FLOW_IN_XON 0x0100
+enum pl2303_type {
+ UPLCOM_TYPE_0,
+ UPLCOM_TYPE_HX,
+};
+
struct uplcom_softc {
USBBASEDEVICE sc_dev; /* base device */
usbd_device_handle sc_udev; /* USB device */
@@ -115,6 +121,8 @@
u_char sc_lsr; /* Local status register */
u_char sc_msr; /* uplcom status register */
+
+ enum pl2303_type sc_type; /* PL2303 chip type */
};
/*
@@ -142,6 +150,7 @@
Static int uplcom_param(void *, int, struct termios *);
Static int uplcom_open(void *, int);
Static void uplcom_close(void *, int);
+Static usbd_status uplcom_vendor_control_write(usbd_device_handle, u_int16_t, u_int16_t);
struct ucom_methods uplcom_methods = {
uplcom_get_status,
@@ -206,6 +215,7 @@
{
USB_ATTACH_START(uplcom, sc, uaa);
usbd_device_handle dev = uaa->device;
+ usb_device_descriptor_t *ddesc;
usb_config_descriptor_t *cdesc;
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
@@ -238,6 +248,28 @@
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;
+ }
+
+ /*
+ * NOTE: The Linux driver distinguishes between UPLCOM_TYPE_0
+ * and UPLCOM_TYPE_1 type chips by testing other fields in the
+ * device descriptor. As far as the uplcom driver is
+ * concerned, both types are identical.
+ * The bcdDevice field should also distinguish these versions,
+ * but who knows.
+ */
+ if (UGETW(ddesc->bcdDevice) == 0x0300)
+ sc->sc_type = UPLCOM_TYPE_HX;
+ else
+ sc->sc_type = UPLCOM_TYPE_0;
+
/* get the config descriptor */
cdesc = usbd_get_config_descriptor(sc->sc_udev);
@@ -468,7 +500,6 @@
USETW(req.wLength, 0);
(void)usbd_do_request(sc->sc_udev, &req, 0);
-
}
void
@@ -545,7 +576,10 @@
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = UPLCOM_SET_REQUEST;
USETW(req.wValue, 0);
- USETW(req.wIndex, UPLCOM_SET_CRTSCTS);
+ if (sc->sc_type == UPLCOM_TYPE_HX)
+ USETW(req.wIndex, UPLCOM_SET_CRTSCTS_HX);
+ else
+ USETW(req.wIndex, UPLCOM_SET_CRTSCTS_0);
USETW(req.wLength, 0);
err = usbd_do_request(sc->sc_udev, &req, 0);
@@ -647,17 +681,45 @@
return (0);
}
+Static usbd_status
+uplcom_vendor_control_write(usbd_device_handle dev, u_int16_t value, u_int16_t index)
+{
+ usb_device_request_t req;
+ usbd_status err;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = UPLCOM_SET_REQUEST;
+ USETW(req.wValue, value);
+ USETW(req.wIndex, index);
+ USETW(req.wLength, 0);
+
+ err = usbd_do_request(dev, &req, NULL);
+
+ if (err) {
+ DPRINTF(("uplcom_open: vendor write failed, err=%s (%d)\n",
+ usbd_errstr(err), err));
+ }
+
+ return err;
+}
+
int
uplcom_open(void *addr, int portno)
{
struct uplcom_softc *sc = addr;
- int err;
+ usbd_status err;
if (sc->sc_dying)
return (EIO);
DPRINTF(("uplcom_open: sc=%p\n", sc));
+ /* Some unknown device frobbing. */
+ if (sc->sc_type == UPLCOM_TYPE_HX)
+ uplcom_vendor_control_write(sc->sc_udev, 2, 0x44);
+ else
+ uplcom_vendor_control_write(sc->sc_udev, 2, 0x24);
+
if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
err = usbd_open_pipe_intr(sc->sc_intr_iface, sc->sc_intr_number,
Home |
Main Index |
Thread Index |
Old Index