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