PERFORCE change 117258 for review

Hans Petter Selasky hselasky at FreeBSD.org
Tue Apr 3 08:27:41 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=117258

Change 117258 by hselasky at hselasky_mini_itx on 2007/04/03 08:26:40

	Updated ugensa to handle multiple interfaces.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/ugensa.c#4 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/ugensa.c#4 (text+ko) ====

@@ -62,18 +62,25 @@
 #define UGENSA_N_TRANSFER	4 /* units */
 #define UGENSA_CONFIG_INDEX	0
 #define UGENSA_IFACE_INDEX	0
+#define UGENSA_IFACE_MAX	8 /* exclusivly */
 
-struct ugensa_softc {
-	struct ucom_super_softc	sc_super_ucom;
-	struct ucom_softc	sc_ucom;
+struct ugensa_sub_softc {
+ 	struct ucom_softc	*sc_ucom_ptr;
+ 	struct usbd_xfer	*sc_xfer[UGENSA_N_TRANSFER];
 
-	struct usbd_xfer 	*sc_xfer[UGENSA_N_TRANSFER];
-
 	uint8_t			sc_flags;
 #define UGENSA_FLAG_BULK_READ_STALL	0x01
 #define UGENSA_FLAG_BULK_WRITE_STALL	0x02
 };
 
+struct ugensa_softc {
+	struct ucom_super_softc	sc_super_ucom;
+	struct ucom_softc	sc_ucom[UGENSA_IFACE_MAX];
+	struct ugensa_sub_softc	sc_sub[UGENSA_IFACE_MAX];
+
+ 	uint8_t			sc_ifaces;
+};
+
 /* prototypes */
 
 static device_probe_t ugensa_probe;
@@ -161,11 +168,11 @@
 
 static const struct usb_devno ugensa_devs[] = {
 	{ USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_PC5220 },
+	{ USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CDMA_MODEM1 },
 	{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_FLEXPACKGPS },
+	{ USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_CDMA_MODEM },
 	{ USB_VENDOR_QUALCOMM_K, USB_PRODUCT_QUALCOMM_K_CDMA_MSM_K },
 	{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580 },
-	{ USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_CDMA_MODEM },
-	{ USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CDMA_MODEM1 },
 };
 
 #define ugensa_lookup(v, p) usb_lookup(ugensa_devs, v, p)
@@ -179,7 +186,8 @@
 	    return UMATCH_NONE;
 	}
 
-	return (ugensa_lookup(uaa->vendor, uaa->product) ? UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
+	return (ugensa_lookup(uaa->vendor, uaa->product) ?
+		UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
 }
 
 static int
@@ -187,7 +195,9 @@
 {
 	struct usb_attach_arg *uaa = device_get_ivars(dev);
 	struct ugensa_softc *sc = device_get_softc(dev);
+	struct ugensa_sub_softc *ssc;
 	int32_t error;
+	uint8_t x;
 
 	if (sc == NULL) {
 	    return ENOMEM;
@@ -203,22 +213,49 @@
 	    goto detach;
 	}
 
-	error = usbd_transfer_setup
-	  (uaa->device, UGENSA_IFACE_INDEX,
-	   sc->sc_xfer, ugensa_xfer_config, UGENSA_N_TRANSFER,
-	   sc, &Giant);
+	/* Figure out how many interfaces this device has got */
+	for (x = 0; x < UGENSA_IFACE_MAX; x++) {
+	    if ((usbd_get_pipe(uaa->device, x, ugensa_xfer_config+0) == NULL) ||
+		(usbd_get_pipe(uaa->device, x, ugensa_xfer_config+1) == NULL)) {
+	        /* we have reached the end */
+	        break;
+	    }
+	}
 
-	if (error) {
-	    device_printf(dev, "allocating control USB "
-			  "transfers failed!\n");
+	if (x == 0) {
+	    device_printf(dev, "No interfaces!\n");
 	    goto detach;
+	} else {
+	    device_printf(dev, "Found %d interfaces.\n", x);
+	    sc->sc_ifaces = x;
 	}
 
-	/* clear stall at first run */
-	sc->sc_flags |= (UGENSA_FLAG_BULK_WRITE_STALL|
-			 UGENSA_FLAG_BULK_READ_STALL);
+	for (x = 0; x < sc->sc_ifaces; x++) {
+
+	    ssc = sc->sc_sub + x;
+
+	    ssc->sc_ucom_ptr = sc->sc_ucom + x;
+
+	    error = usbd_transfer_setup
+	      (uaa->device, UGENSA_IFACE_INDEX + x,
+	       ssc->sc_xfer, ugensa_xfer_config, UGENSA_N_TRANSFER,
+	       ssc, &Giant);
+
+	    if (error) {
+	        device_printf(dev, "allocating USB "
+			      "transfers failed!\n");
+		goto detach;
+	    }
+
+	    /* clear stall at first run */
+	    ssc->sc_flags |= (UGENSA_FLAG_BULK_WRITE_STALL|
+			      UGENSA_FLAG_BULK_READ_STALL);
+
+	    /* initialize port number */
+	    ssc->sc_ucom_ptr->sc_portno = x;
+	}
 
-        error = ucom_attach(&(sc->sc_super_ucom), &(sc->sc_ucom), 1, sc,
+        error = ucom_attach(&(sc->sc_super_ucom), sc->sc_ucom, sc->sc_ifaces, sc,
 			    &ugensa_callback, &Giant);
         if (error) {
             DPRINTF(0, "ucom_attach failed\n");
@@ -236,10 +273,13 @@
 ugensa_detach(device_t dev)
 {
 	struct ugensa_softc *sc = device_get_softc(dev);
+	uint8_t x;
 
-        ucom_detach(&(sc->sc_super_ucom), &(sc->sc_ucom), 1);
+	ucom_detach(&(sc->sc_super_ucom), sc->sc_ucom, sc->sc_ifaces);
 
-        usbd_transfer_unsetup(sc->sc_xfer, UGENSA_N_TRANSFER);
+	for (x = 0; x < sc->sc_ifaces; x++) {
+	    usbd_transfer_unsetup(sc->sc_sub[x].sc_xfer, UGENSA_N_TRANSFER);
+	}
 
 	return 0;
 }
@@ -247,26 +287,26 @@
 static void
 ugensa_bulk_write_callback(struct usbd_xfer *xfer)
 {
-	struct ugensa_softc *sc = xfer->priv_sc;
+	struct ugensa_sub_softc *ssc = xfer->priv_sc;
 	u_int32_t actlen;
 
 	USBD_CHECK_STATUS(xfer);
 
 tr_error:
 	if (xfer->error != USBD_CANCELLED) {
-	    sc->sc_flags |= UGENSA_FLAG_BULK_WRITE_STALL;
-	    usbd_transfer_start(sc->sc_xfer[2]);
+	    ssc->sc_flags |= UGENSA_FLAG_BULK_WRITE_STALL;
+	    usbd_transfer_start(ssc->sc_xfer[2]);
 	}
 	return;
 
 tr_setup:
 tr_transferred:
-	if (sc->sc_flags & UGENSA_FLAG_BULK_WRITE_STALL) {
-	    usbd_transfer_start(sc->sc_xfer[2]);
+	if (ssc->sc_flags & UGENSA_FLAG_BULK_WRITE_STALL) {
+	    usbd_transfer_start(ssc->sc_xfer[2]);
 	    return;
 	}
 
-	if (ucom_get_data(&(sc->sc_ucom), xfer->buffer, 
+	if (ucom_get_data(ssc->sc_ucom_ptr, xfer->buffer, 
 			  UGENSA_BUF_SIZE, &actlen)) {
 	    xfer->length = actlen;
 	    usbd_start_hardware(xfer);
@@ -277,8 +317,8 @@
 static void
 ugensa_bulk_write_clear_stall_callback(struct usbd_xfer *xfer)
 {
-	struct ugensa_softc *sc = xfer->priv_sc;
-	struct usbd_xfer *xfer_other = sc->sc_xfer[0];
+	struct ugensa_sub_softc *ssc = xfer->priv_sc;
+	struct usbd_xfer *xfer_other = ssc->sc_xfer[0];
 
 	USBD_CHECK_STATUS(xfer);
 
@@ -289,12 +329,12 @@
 
  tr_transferred:
 	usbd_clear_stall_tr_transferred(xfer, xfer_other);
-	sc->sc_flags &= ~UGENSA_FLAG_BULK_WRITE_STALL;
+	ssc->sc_flags &= ~UGENSA_FLAG_BULK_WRITE_STALL;
 	usbd_transfer_start(xfer_other);
 	return;
 
  tr_error:
-	sc->sc_flags &= ~UGENSA_FLAG_BULK_WRITE_STALL;
+	ssc->sc_flags &= ~UGENSA_FLAG_BULK_WRITE_STALL;
 	DPRINTF(sc, 0, "clear stall failed, error=%s\n",
 		usbd_errstr(xfer->error));
 	return;
@@ -303,24 +343,24 @@
 static void
 ugensa_bulk_read_callback(struct usbd_xfer *xfer)
 {
-	struct ugensa_softc *sc = xfer->priv_sc;
+	struct ugensa_sub_softc *ssc = xfer->priv_sc;
 
 	USBD_CHECK_STATUS(xfer);
 
  tr_error:
 	if (xfer->error != USBD_CANCELLED) {
-	    sc->sc_flags |= UGENSA_FLAG_BULK_READ_STALL;
-	    usbd_transfer_start(sc->sc_xfer[3]);
+	    ssc->sc_flags |= UGENSA_FLAG_BULK_READ_STALL;
+	    usbd_transfer_start(ssc->sc_xfer[3]);
 	}
 	return;
 
  tr_transferred:
-	ucom_put_data(&(sc->sc_ucom), xfer->buffer, 
+	ucom_put_data(ssc->sc_ucom_ptr, xfer->buffer, 
 		      xfer->actlen);
 
  tr_setup:
-	if (sc->sc_flags & UGENSA_FLAG_BULK_READ_STALL) {
-	    usbd_transfer_start(sc->sc_xfer[3]);
+	if (ssc->sc_flags & UGENSA_FLAG_BULK_READ_STALL) {
+	    usbd_transfer_start(ssc->sc_xfer[3]);
 	} else {
 	    usbd_start_hardware(xfer);
 	}
@@ -330,8 +370,8 @@
 static void
 ugensa_bulk_read_clear_stall_callback(struct usbd_xfer *xfer)
 {
-	struct ugensa_softc *sc = xfer->priv_sc;
-	struct usbd_xfer *xfer_other = sc->sc_xfer[1];
+	struct ugensa_sub_softc *ssc = xfer->priv_sc;
+	struct usbd_xfer *xfer_other = ssc->sc_xfer[1];
 
 	USBD_CHECK_STATUS(xfer);
 
@@ -342,12 +382,12 @@
 
  tr_transferred:
 	usbd_clear_stall_tr_transferred(xfer, xfer_other);
-	sc->sc_flags &= ~UGENSA_FLAG_BULK_READ_STALL;
+	ssc->sc_flags &= ~UGENSA_FLAG_BULK_READ_STALL;
 	usbd_transfer_start(xfer_other);
 	return;
 
  tr_error:
-	sc->sc_flags &= ~UGENSA_FLAG_BULK_READ_STALL;
+	ssc->sc_flags &= ~UGENSA_FLAG_BULK_READ_STALL;
 	DPRINTF(sc, 0, "clear stall failed, error=%s\n",
 		usbd_errstr(xfer->error));
 	return;
@@ -356,33 +396,37 @@
 static void
 ugensa_start_read(struct ucom_softc *ucom)
 {
-        struct ugensa_softc *sc = ucom->sc_parent;
-	usbd_transfer_start(sc->sc_xfer[1]);
-        return;
+	struct ugensa_softc *sc = ucom->sc_parent;
+	struct ugensa_sub_softc *ssc = sc->sc_sub + ucom->sc_portno;
+	usbd_transfer_start(ssc->sc_xfer[1]);
+	return;
 }
 
 static void
 ugensa_stop_read(struct ucom_softc *ucom)
 {
-        struct ugensa_softc *sc = ucom->sc_parent;
-	usbd_transfer_stop(sc->sc_xfer[3]);
-	usbd_transfer_stop(sc->sc_xfer[1]);
-        return;
+	struct ugensa_softc *sc = ucom->sc_parent;
+	struct ugensa_sub_softc *ssc = sc->sc_sub + ucom->sc_portno;
+	usbd_transfer_stop(ssc->sc_xfer[3]);
+	usbd_transfer_stop(ssc->sc_xfer[1]);
+	return;
 }
 
 static void
 ugensa_start_write(struct ucom_softc *ucom)
 {
-        struct ugensa_softc *sc = ucom->sc_parent;
-	usbd_transfer_start(sc->sc_xfer[0]);
-        return;
+	struct ugensa_softc *sc = ucom->sc_parent;
+	struct ugensa_sub_softc *ssc = sc->sc_sub + ucom->sc_portno;
+	usbd_transfer_start(ssc->sc_xfer[0]);
+	return;
 }
 
 static void
 ugensa_stop_write(struct ucom_softc *ucom)
 {
-        struct ugensa_softc *sc = ucom->sc_parent;
-	usbd_transfer_stop(sc->sc_xfer[2]);
-	usbd_transfer_stop(sc->sc_xfer[0]);
-        return;
+	struct ugensa_softc *sc = ucom->sc_parent;
+	struct ugensa_sub_softc *ssc = sc->sc_sub + ucom->sc_portno;
+	usbd_transfer_stop(ssc->sc_xfer[2]);
+	usbd_transfer_stop(ssc->sc_xfer[0]);
+	return;
 }


More information about the p4-projects mailing list