--- sys/dev/usb/uplcom.c Fri Jan 21 10:49:09 2005 +++ sys/dev/usb/uplcom.c Fri Jan 21 11:01:33 2005 @@ -96,10 +96,13 @@ #include #include +#include + #include #include #include +#include #include #include "usbdevs.h" #include @@ -112,29 +115,34 @@ SYSCTL_INT(_hw_usb_uplcom, OID_AUTO, debug, CTLFLAG_RW, &uplcomdebug, 0, "uplcom debug level"); -#define DPRINTFN(n, x) do { \ +#define DPRINTFN(n, x) do { \ if (uplcomdebug > (n)) \ logprintf x; \ } while (0) #else -#define DPRINTFN(n, x) +#define DPRINTFN(n, x) #endif -#define DPRINTF(x) DPRINTFN(0, x) +#define DPRINTF(x) DPRINTFN(0, x) -#define UPLCOM_MODVER 1 /* module version */ +#define UPLCOM_MODVER 1 /* module version */ #define UPLCOM_CONFIG_INDEX 0 #define UPLCOM_IFACE_INDEX 0 #define UPLCOM_SECOND_IFACE_INDEX 1 #ifndef UPLCOM_INTR_INTERVAL -#define UPLCOM_INTR_INTERVAL 100 /* ms */ +#define UPLCOM_INTR_INTERVAL 100 /* ms */ #endif #define UPLCOM_SET_REQUEST 0x01 #define UPLCOM_SET_CRTSCTS 0x41 -#define RSAQ_STATUS_DSR 0x02 -#define RSAQ_STATUS_DCD 0x01 +#define UPLCOM_SET_CRTSCTS_2303X 0x61 +#define RSAQ_STATUS_CTS 0x80 +#define RSAQ_STATUS_DSR 0x02 +#define RSAQ_STATUS_DCD 0x01 + +#define CHIPTYPE_PL2303 0 +#define CHIPTYPE_PL2303X 1 struct uplcom_softc { struct ucom_softc sc_ucom; @@ -154,14 +162,15 @@ u_char sc_lsr; /* Local status register */ u_char sc_msr; /* uplcom status register */ + int sc_chiptype; }; /* * These are the maximum number of bytes transferred per frame. * The output buffer size cannot be increased due to the size encoding. */ -#define UPLCOMIBUFSIZE 256 -#define UPLCOMOBUFSIZE 256 +#define UPLCOMIBUFSIZE 256 +#define UPLCOMOBUFSIZE 256 Static usbd_status uplcom_reset(struct uplcom_softc *); Static usbd_status uplcom_set_line_coding(struct uplcom_softc *, @@ -297,6 +306,7 @@ char *devinfo; const char *devname; usbd_status err; + usb_device_descriptor_t *udd; int i; devinfo = malloc(1024, M_USBDEV, M_WAITOK); @@ -372,7 +382,14 @@ sc->sc_isize = UGETW(ed->wMaxPacketSize); } } - + udd = &dev->ddesc; + if (UGETW(udd->bcdDevice) == 0x300) { + DPRINTF(("chiptype 2303X\n")); + sc->sc_chiptype = CHIPTYPE_PL2303X; + } else { + DPRINTF(("chiptype 2303\n")); + sc->sc_chiptype = CHIPTYPE_PL2303; + } if (sc->sc_intr_number == -1) { printf("%s: Could not find interrupt in\n", USBDEVNAME(ucom->sc_dev)); @@ -615,7 +632,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_chiptype == CHIPTYPE_PL2303X) + USETW(req.wIndex, UPLCOM_SET_CRTSCTS_2303X); + else + USETW(req.wIndex, UPLCOM_SET_CRTSCTS); USETW(req.wLength, 0); err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); @@ -711,6 +731,43 @@ return (0); } +#define DO_REQ(type, reQ, wVal, wInd) do { \ + req.bmRequestType = (type); \ + req.bRequest = (reQ); \ + USETW(req.wValue, (wVal)); \ + USETW(req.wIndex, (wInd)); \ + USETW(req.wLength, 0); \ + err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); \ + if (err) { /* XXX - shouldn't happen */ \ + printf("%s: uplcom_initPL2303X_%d: %s\n", \ + USBDEVNAME(sc->sc_ucom.sc_dev), i++, usbd_errstr(err)); \ + return (EIO); \ + } \ + } while (0); + +Static usbd_status +uplcom_initPL2303X(struct uplcom_softc *sc) +{ + usb_device_request_t req; + usbd_status err; + int i = 0; + + DO_REQ(0xc0, 0x1, 0x8484, 0); + DO_REQ(0x40, 0x1, 0x0404, 0); + DO_REQ(0xc0, 0x1, 0x8484, 0); + DO_REQ(0xc0, 0x1, 0x8383, 0); + DO_REQ(0xc0, 0x1, 0x8484, 0); + DO_REQ(0x40, 0x1, 0x0404, 1); + DO_REQ(0xc0, 0x1, 0x8484, 0); + DO_REQ(0xc0, 0x1, 0x8383, 0); + DO_REQ(0x40, 0x1, 0x0000, 1); + DO_REQ(0x40, 0x1, 0x0001, 0); + DO_REQ(0x40, 0x1, 0x0002, 0x44); + return (0); +} + +#undef DO_REQ + Static int uplcom_open(void *addr, int portno) { @@ -741,7 +798,8 @@ return (EIO); } } - + if (sc->sc_chiptype == CHIPTYPE_PL2303X) + return (uplcom_initPL2303X(sc)); return (0); }