summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2014-10-09 14:43:43 +0000
committerhselasky <hselasky@FreeBSD.org>2014-10-09 14:43:43 +0000
commit53ec9839eefdeb35848c51966595f92eb4f8fc19 (patch)
tree4273bdf7cee6ab4569e9e8f91460b59f885525bc /sys/dev/usb
parentafe30bff57647805e6b0295dfe0927d23ce1d3ce (diff)
downloadFreeBSD-src-53ec9839eefdeb35848c51966595f92eb4f8fc19.zip
FreeBSD-src-53ec9839eefdeb35848c51966595f92eb4f8fc19.tar.gz
Add sysctl knob to disable port power on a specific USB HUB. You need
to reset the USB HUB using "usbconfig -d X.Y reset" or boot having the setting in /boot/loader.conf before it activates.
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/usb_hub.c62
1 files changed, 43 insertions, 19 deletions
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c
index e9280bc..6d79327 100644
--- a/sys/dev/usb/usb_hub.c
+++ b/sys/dev/usb/usb_hub.c
@@ -101,6 +101,10 @@ SYSCTL_INT(_hw_usb, OID_AUTO, power_timeout, CTLFLAG_RW,
static int usb_disable_enumeration = 0;
SYSCTL_INT(_hw_usb, OID_AUTO, disable_enumeration, CTLFLAG_RWTUN,
&usb_disable_enumeration, 0, "Set to disable all USB device enumeration.");
+
+static int usb_disable_port_power = 0;
+SYSCTL_INT(_hw_usb, OID_AUTO, disable_port_power, CTLFLAG_RWTUN,
+ &usb_disable_port_power, 0, "Set to disable all USB port power.");
#endif
struct uhub_current_state {
@@ -119,6 +123,7 @@ struct uhub_softc {
struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */
#if USB_HAVE_DISABLE_ENUM
int sc_disable_enumeration;
+ int sc_disable_port_power;
#endif
uint8_t sc_flags;
#define UHUB_FLAG_DID_EXPLORE 0x01
@@ -1406,6 +1411,24 @@ uhub_attach(device_t dev)
/* wait with power off for a while */
usb_pause_mtx(NULL, USB_MS_TO_TICKS(USB_POWER_DOWN_TIME));
+#if USB_HAVE_DISABLE_ENUM
+ /* Add device sysctls */
+
+ sysctl_ctx = device_get_sysctl_ctx(dev);
+ sysctl_tree = device_get_sysctl_tree(dev);
+
+ if (sysctl_ctx != NULL && sysctl_tree != NULL) {
+ (void) SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "disable_enumeration", CTLFLAG_RWTUN,
+ &sc->sc_disable_enumeration, 0,
+ "Set to disable enumeration on this USB HUB.");
+
+ (void) SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+ OID_AUTO, "disable_port_power", CTLFLAG_RWTUN,
+ &sc->sc_disable_port_power, 0,
+ "Set to disable USB port power on this USB HUB.");
+ }
+#endif
/*
* To have the best chance of success we do things in the exact same
* order as Windoze98. This should not be necessary, but some
@@ -1460,13 +1483,27 @@ uhub_attach(device_t dev)
removable++;
break;
}
- if (!err) {
- /* turn the power on */
- err = usbd_req_set_port_feature(udev, NULL,
- portno, UHF_PORT_POWER);
+ if (err == 0) {
+#if USB_HAVE_DISABLE_ENUM
+ /* check if we should disable USB port power or not */
+ if (usb_disable_port_power != 0 ||
+ sc->sc_disable_port_power != 0) {
+ /* turn the power off */
+ DPRINTFN(0, "Turning port %d power off\n", portno);
+ err = usbd_req_clear_port_feature(udev, NULL,
+ portno, UHF_PORT_POWER);
+ } else {
+#endif
+ /* turn the power on */
+ DPRINTFN(0, "Turning port %d power on\n", portno);
+ err = usbd_req_set_port_feature(udev, NULL,
+ portno, UHF_PORT_POWER);
+#if USB_HAVE_DISABLE_ENUM
+ }
+#endif
}
- if (err) {
- DPRINTFN(0, "port %d power on failed, %s\n",
+ if (err != 0) {
+ DPRINTFN(0, "port %d power on or off failed, %s\n",
portno, usbd_errstr(err));
}
DPRINTF("turn on port %d power\n",
@@ -1490,19 +1527,6 @@ uhub_attach(device_t dev)
usbd_set_power_mode(udev, USB_POWER_MODE_SAVE);
-#if USB_HAVE_DISABLE_ENUM
- /* Add device sysctls */
-
- sysctl_ctx = device_get_sysctl_ctx(dev);
- sysctl_tree = device_get_sysctl_tree(dev);
-
- if (sysctl_ctx != NULL && sysctl_tree != NULL) {
- (void) SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
- OID_AUTO, "disable_enumeration", CTLFLAG_RWTUN,
- &sc->sc_disable_enumeration, 0,
- "Set to disable enumeration on this USB HUB.");
- }
-#endif
return (0);
error:
OpenPOWER on IntegriCloud