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