svn commit: r250749 - head/sys/dev/usb/serial
Gavin Atkinson
gavin at FreeBSD.org
Fri May 17 19:13:32 UTC 2013
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:
More information about the svn-src-head
mailing list