PERFORCE change 131971 for review

Hans Petter Selasky hselasky at FreeBSD.org
Sat Dec 29 09:05:07 PST 2007


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

Change 131971 by hselasky at hselasky_laptop001 on 2007/12/29 17:04:28

	
	This commit is device side related.
	
	o Fix support for Suspend and Resume.
	
	o Make "udev->flags.self_powered" read only
	  in Device Side Mode.
	
	o Fix support for Remote Wakeup.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/at9100_dci.c#10 edit
.. //depot/projects/usb/src/sys/dev/usb/if_cdce.c#42 edit
.. //depot/projects/usb/src/sys/dev/usb/uhub.c#31 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#81 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#90 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_template.c#12 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#97 edit

Differences ...

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

@@ -270,7 +270,30 @@
 	if (!(temp & AT91_UDP_GSTATE_ESR)) {
 		return;
 	}
-	temp |= AT91_UDP_GSTATE_ESR;
+	AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, temp);
+
+	return;
+}
+
+static void
+at9100_dci_rem_wakeup_set(struct usbd_device *udev, uint8_t is_on)
+{
+	struct at9100_dci_softc *sc;
+	uint32_t temp;
+
+	DPRINTFN(4, "is_on=%u\n", is_on);
+
+	mtx_assert(&(udev->bus->mtx), MA_OWNED);
+
+	sc = AT9100_DCI_BUS2SC(udev->bus);
+
+	temp = AT91_UDP_READ_4(sc, AT91_UDP_GSTATE);
+
+	if (is_on) {
+		temp |= AT91_UDP_GSTATE_ESR;
+	} else {
+		temp &= ~AT91_UDP_GSTATE_ESR;
+	}
 
 	AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, temp);
 
@@ -2542,4 +2565,5 @@
 	.set_stall = &at9100_dci_set_stall,
 	.clear_stall = &at9100_dci_clear_stall,
 	.vbus_interrupt = &at9100_dci_vbus_interrupt,
+	.rem_wakeup_set = &at9100_dci_rem_wakeup_set,
 };

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

@@ -73,6 +73,8 @@
 static device_attach_t cdce_attach;
 static device_detach_t cdce_detach;
 static device_shutdown_t cdce_shutdown;
+static device_suspend_t cdce_suspend;
+static device_resume_t cdce_resume;
 static usb_handle_request_t cdce_handle_request;
 
 static usbd_callback_t cdce_bulk_write_clear_stall_callback;
@@ -774,6 +776,20 @@
 }
 
 static int
+cdce_suspend(device_t dev)
+{
+	device_printf(dev, "Suspending\n");
+	return 0;
+}
+
+static int
+cdce_resume(device_t dev)
+{
+	device_printf(dev, "Resuming\n");
+	return 0;
+}
+
+static int
 cdce_ioctl_cb(struct ifnet *ifp, u_long command, caddr_t data)
 {
 	struct cdce_softc *sc = ifp->if_softc;

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

@@ -434,6 +434,57 @@
 }
 
 /*------------------------------------------------------------------------*
+ *	uhub_suspend_resume_port
+ *
+ * Returns:
+ *    0: Success
+ * Else: A control transaction failed
+ *------------------------------------------------------------------------*/
+static usbd_status_t
+uhub_suspend_resume_port(struct uhub_softc *sc, uint8_t portno)
+{
+	struct usbd_device *child;
+	struct usbd_device *udev;
+	uint8_t is_suspend;
+	usbd_status_t err;
+
+	DPRINTF(sc, 0, "port %d\n", portno);
+
+	udev = sc->sc_udev;
+	child = usbd_bus_port_get_device(udev->bus,
+	    udev->hub->ports + portno - 1);
+
+	/* first clear the port suspend change bit */
+
+	err = usbreq_clear_port_feature
+	    (udev, &usb_global_lock, portno, UHF_C_PORT_SUSPEND);
+
+	if (err) {
+		goto done;
+	}
+	/* get fresh status */
+
+	err = uhub_read_port_status(sc, portno);
+	if (err) {
+		goto done;
+	}
+	/* get current state */
+
+	if (sc->sc_st.port_status & UPS_SUSPEND) {
+		is_suspend = 1;
+	} else {
+		is_suspend = 0;
+	}
+	/* do the suspend or resume */
+
+	if (child) {
+		err = usbd_suspend_resume(child, is_suspend);
+	}
+done:
+	return (err);
+}
+
+/*------------------------------------------------------------------------*
  *	uhub_explore
  *
  * Returns:
@@ -502,6 +553,13 @@
 				break;
 			}
 		}
+		if (sc->sc_st.port_change & UPS_C_SUSPEND) {
+			err = uhub_suspend_resume_port(sc, portno);
+			if (err) {
+				/* most likely the HUB is gone */
+				break;
+			}
+		}
 		err = uhub_explore_sub(sc, up);
 		if (err) {
 			/* no device(s) present */

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

@@ -888,7 +888,8 @@
 	/* Figure out if the device is self or bus powered. */
 	selfpowered = 0;
 	if (!(udev->quirks->uq_flags & UQ_BUS_POWERED) &&
-	    (cdp->bmAttributes & UC_SELF_POWERED)) {
+	    (cdp->bmAttributes & UC_SELF_POWERED) &&
+	    (udev->flags.usb_mode == USB_MODE_HOST)) {
 		/* May be self powered. */
 		if (cdp->bmAttributes & UC_BUS_POWERED) {
 			/* Must ask device. */
@@ -953,8 +954,11 @@
 		err = USBD_NO_POWER;
 		goto error;
 	}
+	/* Only update "self_powered" in USB Host Mode */
+	if (udev->flags.usb_mode == USB_MODE_HOST) {
+		udev->flags.self_powered = selfpowered;
+	}
 	udev->power = power;
-	udev->flags.self_powered = selfpowered;
 	udev->curr_config_no = cdp->bConfigurationValue;
 
 	/* Set the actual configuration value. */
@@ -1455,6 +1459,9 @@
 	if (dev == NULL) {
 		return;
 	}
+	if (!device_is_attached(dev)) {
+		return;
+	}
 	if (do_suspend) {
 		err = DEVICE_SUSPEND(dev);
 	} else {
@@ -1482,7 +1489,7 @@
 		/* nothing to do */
 		return (0);
 	}
-	PRINTFN(3, ("udev=%p\n", udev));
+	PRINTFN(3, ("udev=%p do_suspend=%d\n", udev, do_suspend));
 
 	mtx_lock(&(udev->bus->mtx));
 	if (udev->flags.suspended == do_suspend) {
@@ -1671,6 +1678,8 @@
 		/* allow device time to set new address */
 		usbd_delay_ms(udev, USB_SET_ADDRESS_SETTLE);
 	} else {
+		/* We are not self powered */
+		udev->flags.self_powered = 0;
 
 		/*
 	         * TODO: Make some kind of command that lets the user choose
@@ -1757,7 +1766,6 @@
 
 	/* assume 100mA bus powered for now. Changed when configured. */
 	udev->power = USB_MIN_POWER;
-	udev->flags.self_powered = 0;
 
 	/* get serial number string */
 	err = usbreq_get_string_any

==== //depot/projects/usb/src/sys/dev/usb/usb_subr.h#90 (text+ko) ====

@@ -153,6 +153,7 @@
 	void   *buf;
 	uint32_t size;
 	uint8_t	usb_speed;
+	uint8_t	self_powered;
 	uint8_t	bNumEndpoints;
 	uint8_t	bInterfaceNumber;
 	uint8_t	bAlternateSetting;
@@ -179,6 +180,7 @@
 	void    (*get_hw_ep_profile) (struct usbd_device *udev, const struct usbd_hw_ep_profile **ppf, uint8_t ep_addr);
 	void    (*set_stall) (struct usbd_device *udev, struct usbd_xfer *xfer, struct usbd_pipe *pipe);
 	void    (*clear_stall) (struct usbd_device *udev, struct usbd_pipe *pipe);
+	void    (*rem_wakeup_set) (struct usbd_device *udev, uint8_t is_on);
 
 	/* USB Device mode only - Optional */
 	void    (*vbus_interrupt) (struct usbd_bus *, uint8_t is_on);
@@ -414,7 +416,8 @@
 	uint8_t	no_strings:1;		/* set if USB device does not support
 					 * strings */
 	uint8_t	detaching:1;		/* set if USB device is detaching */
-	uint8_t	unused:3;
+	uint8_t	remote_wakeup:1;	/* set if remote wakeup is enabled */
+	uint8_t	unused:2;
 };
 
 struct usbd_device {

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

@@ -286,6 +286,13 @@
 		cd->iConfiguration = tcd->iConfiguration;
 		cd->bmAttributes = tcd->bmAttributes;
 		cd->bMaxPower = tcd->bMaxPower;
+		cd->bmAttributes |= (UC_REMOTE_WAKEUP | UC_BUS_POWERED);
+
+		if (temp->self_powered) {
+			cd->bmAttributes |= UC_SELF_POWERED;
+		} else {
+			cd->bmAttributes &= ~UC_SELF_POWERED;
+		}
 	}
 	return;
 }
@@ -1043,6 +1050,7 @@
 	bzero(uts, sizeof(*uts));
 
 	uts->usb_speed = udev->speed;
+	uts->self_powered = udev->flags.self_powered;
 
 	/* first pass */
 

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

@@ -3008,14 +3008,27 @@
  *	usbd_handle_remote_wakeup
  *------------------------------------------------------------------------*/
 static usbd_status_t
-usbd_handle_remote_wakeup(struct usbd_xfer *xfer, uint8_t do_suspend)
+usbd_handle_remote_wakeup(struct usbd_xfer *xfer, uint8_t is_on)
 {
-	usbd_status_t err;
+	struct usbd_device *udev;
+	struct usbd_bus *bus;
+
+	udev = xfer->udev;
+	bus = udev->bus;
+
+	mtx_lock(&(bus->mtx));
+
+	if (is_on) {
+		udev->flags.remote_wakeup = 1;
+	} else {
+		udev->flags.remote_wakeup = 0;
+	}
+
+	(bus->methods->rem_wakeup_set) (xfer->udev, is_on);
+
+	mtx_unlock(&(bus->mtx));
 
-	mtx_unlock(xfer->priv_mtx);
-	err = usbd_suspend_resume(xfer->udev, do_suspend);
-	mtx_lock(xfer->priv_mtx);
-	return (err);
+	return (0);			/* success */
 }
 
 /*------------------------------------------------------------------------*
@@ -3148,6 +3161,22 @@
 			goto tr_handle_set_address;
 		case UR_SET_CONFIG:
 			goto tr_handle_set_config;
+		case UR_CLEAR_FEATURE:
+			switch (wValue) {
+			case UF_DEVICE_REMOTE_WAKEUP:
+				goto tr_handle_clear_wakeup;
+			default:
+				goto tr_stalled;
+			}
+			break;
+		case UR_SET_FEATURE:
+			switch (wValue) {
+			case UF_DEVICE_REMOTE_WAKEUP:
+				goto tr_handle_set_wakeup;
+			default:
+				goto tr_stalled;
+			}
+			break;
 		default:
 			goto tr_stalled;
 		}
@@ -3159,19 +3188,14 @@
 			switch (wValue) {
 			case UF_ENDPOINT_HALT:
 				goto tr_handle_clear_halt;
-			case UF_DEVICE_REMOTE_WAKEUP:
-				goto tr_handle_clear_wakeup;
 			default:
 				goto tr_stalled;
 			}
 			break;
-
 		case UR_SET_FEATURE:
 			switch (wValue) {
 			case UF_ENDPOINT_HALT:
 				goto tr_handle_set_halt;
-			case UF_DEVICE_REMOTE_WAKEUP:
-				goto tr_handle_set_wakeup;
 			default:
 				goto tr_stalled;
 			}
@@ -3214,8 +3238,19 @@
 	goto tr_valid;
 
 tr_handle_get_status:
-	/* XXX FIXME */
-	USETW(temp.wStatus, UDS_SELF_POWERED);
+
+	wValue = 0;
+
+	mtx_lock(&(udev->bus->mtx));
+	if (udev->flags.remote_wakeup) {
+		wValue |= UDS_REMOTE_WAKEUP;
+	}
+	if (udev->flags.self_powered) {
+		wValue |= UDS_SELF_POWERED;
+	}
+	mtx_unlock(&(udev->bus->mtx));
+
+	USETW(temp.wStatus, wValue);
 	src_mcopy = temp.wStatus;
 	max_len = sizeof(temp.wStatus);
 	goto tr_valid;


More information about the p4-projects mailing list