PERFORCE change 131619 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Tue Dec 25 13:09:57 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=131619
Change 131619 by hselasky at hselasky_laptop001 on 2007/12/25 21:09:50
This commit adds the following to the "if_cdce" driver:
o Interrupt endpoint support.
o Full Device Side Mode support.
o Debug prints.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/if_cdce.c#37 edit
.. //depot/projects/usb/src/sys/dev/usb/if_cdcereg.h#14 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/if_cdce.c#37 (text+ko) ====
@@ -73,11 +73,15 @@
static device_attach_t cdce_attach;
static device_detach_t cdce_detach;
static device_shutdown_t cdce_shutdown;
+static usb_handle_request_t cdce_handle_request;
static usbd_callback_t cdce_bulk_write_clear_stall_callback;
static usbd_callback_t cdce_bulk_write_callback;
static usbd_callback_t cdce_bulk_read_clear_stall_callback;
static usbd_callback_t cdce_bulk_read_callback;
+static usbd_callback_t cdce_intr_read_clear_stall_callback;
+static usbd_callback_t cdce_intr_read_callback;
+static usbd_callback_t cdce_intr_write_callback;
static void cdce_start_cb(struct ifnet *ifp);
static void cdce_start_transfers(struct cdce_softc *sc);
@@ -88,18 +92,37 @@
static int cdce_ifmedia_upd_cb(struct ifnet *ifp);
static void cdce_ifmedia_sts_cb(struct ifnet *const ifp, struct ifmediareq *req);
+#ifdef USB_DEBUG
+#define DPRINTF(sc,n,fmt,...) \
+ do { if (cdce_debug > (n)) { \
+ printf("%s:%s: " fmt, (sc)->sc_name, \
+ __FUNCTION__,## __VA_ARGS__); } } while (0)
+
+static int cdce_debug = 0;
+
+SYSCTL_NODE(_hw_usb, OID_AUTO, cdce, CTLFLAG_RW, 0, "USB cdce");
+SYSCTL_INT(_hw_usb_cdce, OID_AUTO, debug, CTLFLAG_RW, &cdce_debug, 0,
+ "cdce debug level");
+#else
#define DPRINTF(...)
+#endif
-static const struct usbd_config cdce_config[CDCE_ENDPT_MAX] = {
+static const struct usbd_config cdce_config[CDCE_N_TRANSFER] = {
[0] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = (MCLBYTES + 4),
+ .if_index = 0,
+ /* Host Mode */
.mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
.mh.callback = &cdce_bulk_write_callback,
.mh.timeout = 10000, /* 10 seconds */
+ /* Device Mode */
+ .md.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .md.callback = &cdce_bulk_read_callback,
+ .md.timeout = 0, /* no timeout */
},
[1] = {
@@ -107,8 +130,15 @@
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = (MCLBYTES + 4),
+ .if_index = 0,
+ /* Host Mode */
.mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
.mh.callback = &cdce_bulk_read_callback,
+ .mh.timeout = 0, /* no timeout */
+ /* Device Mode */
+ .md.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .md.callback = &cdce_bulk_write_callback,
+ .md.timeout = 10000, /* 10 seconds */
},
[2] = {
@@ -116,10 +146,12 @@
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
.bufsize = sizeof(usb_device_request_t),
+ .interval = 50, /* 50ms */
+ .if_index = 0,
+ /* Host Mode Only */
.mh.flags = {},
.mh.callback = &cdce_bulk_write_clear_stall_callback,
.mh.timeout = 1000, /* 1 second */
- .interval = 50, /* 50ms */
},
[3] = {
@@ -127,14 +159,48 @@
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
.bufsize = sizeof(usb_device_request_t),
+ .interval = 50, /* 50ms */
+ .if_index = 0,
+ /* Host Mode Only */
.mh.flags = {},
.mh.callback = &cdce_bulk_read_clear_stall_callback,
.mh.timeout = 1000, /* 1 second */
+ },
+
+ [4] = {
+ .type = UE_INTERRUPT,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_IN,
+ .bufsize = CDCE_IND_SIZE_MAX,
+ .if_index = 1,
+ /* Host Mode */
+ .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
+ .mh.callback = &cdce_intr_read_callback,
+ .mh.timeout = 0,
+ /* Device Mode */
+ .md.flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,},
+ .md.callback = &cdce_intr_write_callback,
+ .md.timeout = 10000, /* 10 seconds */
+ },
+
+ [5] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = UE_DIR_ANY,
+ .bufsize = sizeof(usb_device_request_t),
.interval = 50, /* 50ms */
+ .if_index = 1,
+ /* Host Mode Only */
+ .mh.flags = {},
+ .mh.callback = &cdce_intr_read_clear_stall_callback,
+ .mh.timeout = 1000, /* 1 second */
},
};
static device_method_t cdce_methods[] = {
+ /* USB interface */
+ DEVMETHOD(usb_handle_request, cdce_handle_request),
+
/* Device interface */
DEVMETHOD(device_probe, cdce_probe),
DEVMETHOD(device_attach, cdce_attach),
@@ -181,9 +247,6 @@
struct usb_attach_arg *uaa = device_get_ivars(dev);
usb_interface_descriptor_t *id;
- if (uaa->usb_mode != USB_MODE_HOST) {
- return (UMATCH_NONE);
- }
if (uaa->iface == NULL) {
return (UMATCH_NONE);
}
@@ -237,7 +300,8 @@
mtx_init(&(sc->sc_mtx), "cdce lock", NULL, MTX_DEF | MTX_RECURSE);
if (sc->sc_flags & CDCE_FLAG_NO_UNION) {
- sc->sc_data_iface_index = uaa->iface_index;
+ sc->sc_ifaces_index[0] = uaa->iface_index;
+ sc->sc_ifaces_index[1] = uaa->iface_index;
sc->sc_data_iface_no = 0; /* not used */
goto alloc_transfers;
}
@@ -261,7 +325,8 @@
if (id && (id->bInterfaceNumber ==
sc->sc_data_iface_no)) {
- sc->sc_data_iface_index = i;
+ sc->sc_ifaces_index[0] = i;
+ sc->sc_ifaces_index[1] = uaa->iface_index;
USBD_SET_IFACE_NO_PROBE(uaa->device, i);
break;
}
@@ -295,7 +360,7 @@
for (i = 0; i < 32; i++) {
error = usbd_set_alt_interface_index
- (uaa->device, sc->sc_data_iface_index, i);
+ (uaa->device, sc->sc_ifaces_index[0], i);
if (error) {
device_printf(dev, "no valid alternate "
@@ -303,8 +368,8 @@
goto detach;
}
error = usbd_transfer_setup
- (uaa->device, &(sc->sc_data_iface_index),
- sc->sc_xfer, cdce_config, CDCE_ENDPT_MAX,
+ (uaa->device, sc->sc_ifaces_index,
+ sc->sc_xfer, cdce_config, CDCE_N_TRANSFER,
sc, &(sc->sc_mtx));
if (error == 0) {
@@ -389,6 +454,11 @@
ether_ifattach(ifp, eaddr);
+ /* start the interrupt transfer, if any */
+ mtx_lock(&(sc->sc_mtx));
+ usbd_transfer_start(sc->sc_xfer[4]);
+ mtx_unlock(&(sc->sc_mtx));
+
return (0); /* success */
detach:
@@ -411,7 +481,7 @@
mtx_unlock(&(sc->sc_mtx));
/* stop all USB transfers first */
- usbd_transfer_unsetup(sc->sc_xfer, CDCE_ENDPT_MAX);
+ usbd_transfer_unsetup(sc->sc_xfer, CDCE_N_TRANSFER);
/* get rid of any late children */
bus_generic_detach(dev);
@@ -463,7 +533,6 @@
if (usbd_clear_stall_callback(xfer, xfer_other)) {
DPRINTF(sc, 0, "stall cleared\n");
- sc->sc_flags &= ~CDCE_FLAG_WRITE_STALL;
usbd_transfer_start(xfer_other);
}
return;
@@ -484,8 +553,9 @@
ifp->if_opackets++;
case USBD_ST_SETUP:
-
- if (sc->sc_flags & CDCE_FLAG_WRITE_STALL) {
+tr_setup:
+ if (xfer->flags.stall_pipe &&
+ (xfer->flags_int.usb_mode == USB_MODE_HOST)) {
usbd_transfer_start(sc->sc_xfer[2]);
goto done;
}
@@ -531,8 +601,8 @@
if (xfer->error != USBD_CANCELLED) {
/* try to clear stall first */
- sc->sc_flags |= CDCE_FLAG_WRITE_STALL;
- usbd_transfer_start(sc->sc_xfer[2]);
+ xfer->flags.stall_pipe = 1;
+ goto tr_setup;
}
ifp->if_oerrors++;
return;
@@ -653,11 +723,16 @@
ifp->if_drv_flags |= IFF_DRV_RUNNING;
- sc->sc_flags |= (CDCE_FLAG_READ_STALL |
- CDCE_FLAG_WRITE_STALL |
+ sc->sc_flags |= (
CDCE_FLAG_LL_READY |
CDCE_FLAG_HL_READY);
+ if (sc->sc_xfer[0]) {
+ sc->sc_xfer[0]->flags.stall_pipe = 1;
+ }
+ if (sc->sc_xfer[1]) {
+ sc->sc_xfer[1]->flags.stall_pipe = 1;
+ }
cdce_start_transfers(sc);
mtx_unlock(&(sc->sc_mtx));
@@ -673,7 +748,6 @@
if (usbd_clear_stall_callback(xfer, xfer_other)) {
DPRINTF(sc, 0, "stall cleared\n");
- sc->sc_flags &= ~CDCE_FLAG_READ_STALL;
usbd_transfer_start(xfer_other);
}
return;
@@ -716,8 +790,8 @@
case USBD_ST_SETUP:
tr_setup:
-
- if (sc->sc_flags & CDCE_FLAG_READ_STALL) {
+ if (xfer->flags.stall_pipe &&
+ (xfer->flags_int.usb_mode == USB_MODE_HOST)) {
usbd_transfer_start(sc->sc_xfer[3]);
} else {
xfer->frlengths[0] = xfer->max_data_length;
@@ -739,8 +813,8 @@
default: /* Error */
if (xfer->error != USBD_CANCELLED) {
/* try to clear stall first */
- sc->sc_flags |= CDCE_FLAG_READ_STALL;
- usbd_transfer_start(sc->sc_xfer[3]);
+ xfer->flags.stall_pipe = 1;
+ goto tr_setup;
}
DPRINTF(sc, 0, "bulk read error, %s\n",
usbd_errstr(xfer->error));
@@ -752,7 +826,6 @@
static int
cdce_ifmedia_upd_cb(struct ifnet *ifp)
{
-
/* no-op, cdce has only 1 possible media type */
return (0);
}
@@ -764,3 +837,97 @@
req->ifm_status = IFM_AVALID | IFM_ACTIVE;
req->ifm_active = IFM_ETHER | IFM_10_T;
}
+
+static void
+cdce_intr_read_clear_stall_callback(struct usbd_xfer *xfer)
+{
+ struct cdce_softc *sc = xfer->priv_sc;
+ struct usbd_xfer *xfer_other = sc->sc_xfer[4];
+
+ if (usbd_clear_stall_callback(xfer, xfer_other)) {
+ DPRINTF(sc, 0, "stall cleared\n");
+ usbd_transfer_start(xfer_other);
+ }
+ return;
+}
+
+static void
+cdce_intr_read_callback(struct usbd_xfer *xfer)
+{
+ struct cdce_softc *sc = xfer->priv_sc;
+
+ switch (USBD_GET_STATE(xfer)) {
+ case USBD_ST_TRANSFERRED:
+
+ DPRINTF(sc, 0, "Received %d bytes\n",
+ xfer->actlen);
+
+ /* TODO: decode some indications */
+
+ case USBD_ST_SETUP:
+tr_setup:
+ if (xfer->flags.stall_pipe &&
+ (xfer->flags_int.usb_mode == USB_MODE_HOST)) {
+ usbd_transfer_start(sc->sc_xfer[5]);
+ } else {
+ xfer->frlengths[0] = xfer->max_data_length;
+ usbd_start_hardware(xfer);
+ }
+ break;
+
+ default: /* Error */
+ if (xfer->error != USBD_CANCELLED) {
+ /* start clear stall */
+ xfer->flags.stall_pipe = 1;
+ goto tr_setup;
+ }
+ break;
+ }
+ return;
+}
+
+static void
+cdce_intr_write_callback(struct usbd_xfer *xfer)
+{
+ struct cdce_softc *sc = xfer->priv_sc;
+
+ switch (USBD_GET_STATE(xfer)) {
+ case USBD_ST_TRANSFERRED:
+
+ DPRINTF(sc, 0, "Transferred %d bytes\n", xfer->actlen);
+
+ case USBD_ST_SETUP:
+tr_setup:
+ if (xfer->flags.stall_pipe &&
+ (xfer->flags_int.usb_mode == USB_MODE_HOST)) {
+ usbd_transfer_start(sc->sc_xfer[5]);
+ } else {
+#if 0
+ xfer->frlengths[0] = XXX;
+ usbd_start_hardware(xfer);
+#endif
+ }
+ break;
+
+ default: /* Error */
+ if (xfer->error != USBD_CANCELLED) {
+ /* start clear stall */
+ xfer->flags.stall_pipe = 1;
+ goto tr_setup;
+ }
+ break;
+ }
+ return;
+}
+
+static int
+cdce_handle_request(device_t dev, const void *req, void **pptr,
+ uint16_t *plen, uint16_t offset, uint8_t is_complete)
+{
+#ifdef USB_DEBUG
+ struct cdce_softc *sc = device_get_softc(dev);
+
+ DPRINTF(sc, 0, "\n");
+#endif
+ return (ENXIO); /* use builtin handling */
+}
==== //depot/projects/usb/src/sys/dev/usb/if_cdcereg.h#14 (text+ko) ====
@@ -35,7 +35,8 @@
#ifndef _USB_IF_CDCEREG_H_
#define _USB_IF_CDCEREG_H_
-#define CDCE_ENDPT_MAX 4
+#define CDCE_N_TRANSFER 6
+#define CDCE_IND_SIZE_MAX 32 /* bytes */
struct cdce_type {
struct usb_devno cdce_dev;
@@ -49,7 +50,7 @@
struct mtx sc_mtx;
struct ifnet *sc_ifp;
- struct usbd_xfer *sc_xfer[CDCE_ENDPT_MAX];
+ struct usbd_xfer *sc_xfer[CDCE_N_TRANSFER];
struct usbd_device *sc_udev;
device_t sc_dev;
@@ -60,12 +61,10 @@
#define CDCE_FLAG_NO_UNION 0x0002
#define CDCE_FLAG_LL_READY 0x0004
#define CDCE_FLAG_HL_READY 0x0008
-#define CDCE_FLAG_WRITE_STALL 0x0010
-#define CDCE_FLAG_READ_STALL 0x0020
uint8_t sc_name[16];
uint8_t sc_data_iface_no;
- uint8_t sc_data_iface_index;
+ uint8_t sc_ifaces_index[2];
};
#endif /* _USB_IF_CDCEREG_H_ */
More information about the p4-projects
mailing list