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