Date: Fri, 17 May 2013 19:13:31 +0000 (UTC) From: Gavin Atkinson <gavin@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r250749 - head/sys/dev/usb/serial Message-ID: <201305171913.r4HJDVXK082459@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: gavin Date: Fri May 17 19:13:31 2013 New Revision: 250749 URL: http://svnweb.freebsd.org/changeset/base/250749 Log: o Retrive the part number (CP2103 etc) from the hardware on attach. o The CP2101 and CP2102 do not support GPIO pin use at all, enforce this. o Support reading the GPIO status on the second port of the CP2105. More work is needed before the CP2105 GPIO pins can be used as outputs. Hardware donated by: Silicon Labs MFC after: 3 weeks Modified: head/sys/dev/usb/serial/uslcom.c Modified: head/sys/dev/usb/serial/uslcom.c ============================================================================== --- head/sys/dev/usb/serial/uslcom.c Fri May 17 19:02:36 2013 (r250748) +++ head/sys/dev/usb/serial/uslcom.c Fri May 17 19:13:31 2013 (r250749) @@ -119,9 +119,17 @@ SYSCTL_INT(_hw_usb_uslcom, OID_AUTO, deb #define USLCOM_FLOW_RTS_HS 0x00000080 /* RTS handshake */ /* USLCOM_VENDOR_SPECIFIC values */ +#define USLCOM_GET_PARTNUM 0x370B #define USLCOM_WRITE_LATCH 0x37E1 #define USLCOM_READ_LATCH 0x00C2 +/* USLCOM_GET_PARTNUM values from hardware */ +#define USLCOM_PARTNUM_CP2101 1 +#define USLCOM_PARTNUM_CP2102 2 +#define USLCOM_PARTNUM_CP2103 3 +#define USLCOM_PARTNUM_CP2104 4 +#define USLCOM_PARTNUM_CP2105 5 + enum { USLCOM_BULK_DT_WR, USLCOM_BULK_DT_RD, @@ -141,6 +149,7 @@ struct uslcom_softc { uint8_t sc_msr; uint8_t sc_lsr; uint8_t sc_iface_no; + uint8_t sc_partnum; }; static device_probe_t uslcom_probe; @@ -155,6 +164,7 @@ static usb_callback_t uslcom_control_cal static void uslcom_free(struct ucom_softc *); static void uslcom_open(struct ucom_softc *); static void uslcom_close(struct ucom_softc *); +static uint8_t uslcom_get_partnum(struct uslcom_softc *); static void uslcom_set_dtr(struct ucom_softc *, uint8_t); static void uslcom_set_rts(struct ucom_softc *, uint8_t); static void uslcom_set_break(struct ucom_softc *, uint8_t); @@ -408,6 +418,8 @@ uslcom_attach(device_t dev) usbd_xfer_set_stall(sc->sc_xfer[USLCOM_BULK_DT_RD]); mtx_unlock(&sc->sc_mtx); + sc->sc_partnum = uslcom_get_partnum(sc); + error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, &uslcom_callback, &sc->sc_mtx); if (error) { @@ -500,6 +512,28 @@ uslcom_close(struct ucom_softc *ucom) } } +static uint8_t +uslcom_get_partnum(struct uslcom_softc *sc) +{ + struct usb_device_request req; + uint8_t partnum; + + /* Find specific chip type */ + partnum = 0; + req.bmRequestType = USLCOM_READ; + req.bRequest = USLCOM_VENDOR_SPECIFIC; + USETW(req.wValue, USLCOM_GET_PARTNUM); + USETW(req.wIndex, sc->sc_iface_no); + USETW(req.wLength, sizeof(partnum)); + + if (usbd_do_request_flags(sc->sc_udev, NULL, + &req, &partnum, 0, NULL, 1000)) { + DPRINTF("GET_PARTNUM failed\n"); + } + + return(partnum); +} + static void uslcom_set_dtr(struct ucom_softc *ucom, uint8_t onoff) { @@ -679,10 +713,14 @@ uslcom_ioctl(struct ucom_softc *ucom, ui switch (cmd) { case USB_GET_GPIO: + if (sc->sc_partnum < USLCOM_PARTNUM_CP2103) { + error = ENODEV; + break; + } req.bmRequestType = USLCOM_READ; req.bRequest = USLCOM_VENDOR_SPECIFIC; USETW(req.wValue, USLCOM_READ_LATCH); - USETW(req.wIndex, 0); + USETW(req.wIndex, sc->sc_iface_no); USETW(req.wLength, sizeof(latch)); if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, @@ -694,17 +732,23 @@ uslcom_ioctl(struct ucom_softc *ucom, ui break; case USB_SET_GPIO: - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_VENDOR_SPECIFIC; - USETW(req.wValue, USLCOM_WRITE_LATCH); - USETW(req.wIndex, (*(int *)data)); - USETW(req.wLength, 0); - - if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, - &req, NULL, 0, 1000)) { - DPRINTF("Set LATCH failed\n"); - error = EIO; - } + if (sc->sc_partnum < USLCOM_PARTNUM_CP2103) + error = ENODEV; + else if ((sc->sc_partnum == USLCOM_PARTNUM_CP2103) || + (sc->sc_partnum == USLCOM_PARTNUM_CP2104)) { + req.bmRequestType = USLCOM_WRITE; + req.bRequest = USLCOM_VENDOR_SPECIFIC; + USETW(req.wValue, USLCOM_WRITE_LATCH); + USETW(req.wIndex, (*(int *)data)); + USETW(req.wLength, 0); + + if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, + &req, NULL, 0, 1000)) { + DPRINTF("Set LATCH failed\n"); + error = EIO; + } + } else + error = ENODEV; /* Not yet */ break; default:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201305171913.r4HJDVXK082459>