Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Oct 2014 09:07:31 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r273729 - stable/10/sys/dev/usb
Message-ID:  <201410270907.s9R97Vpq071240@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Mon Oct 27 09:07:30 2014
New Revision: 273729
URL: https://svnweb.freebsd.org/changeset/base/273729

Log:
  MFC r272733, r272807 and r272822:
  Add support for disabling USB enumeration or USB port power
  in general or on selected USB HUBs.

Modified:
  stable/10/sys/dev/usb/usb_freebsd.h
  stable/10/sys/dev/usb/usb_freebsd_loader.h
  stable/10/sys/dev/usb/usb_hub.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/usb/usb_freebsd.h
==============================================================================
--- stable/10/sys/dev/usb/usb_freebsd.h	Mon Oct 27 07:51:26 2014	(r273728)
+++ stable/10/sys/dev/usb/usb_freebsd.h	Mon Oct 27 09:07:30 2014	(r273729)
@@ -49,6 +49,7 @@
 #define	USB_HAVE_FIXED_IFACE 0
 #define	USB_HAVE_FIXED_CONFIG 0
 #define	USB_HAVE_FIXED_PORT 0
+#define	USB_HAVE_DISABLE_ENUM 1
 
 /* define zero ticks callout value */
 #define	USB_CALLOUT_ZERO_TICKS 1

Modified: stable/10/sys/dev/usb/usb_freebsd_loader.h
==============================================================================
--- stable/10/sys/dev/usb/usb_freebsd_loader.h	Mon Oct 27 07:51:26 2014	(r273728)
+++ stable/10/sys/dev/usb/usb_freebsd_loader.h	Mon Oct 27 09:07:30 2014	(r273729)
@@ -49,6 +49,7 @@
 #define	USB_HAVE_FIXED_IFACE 0
 #define	USB_HAVE_FIXED_CONFIG 0
 #define	USB_HAVE_FIXED_PORT 0
+#define	USB_HAVE_DISABLE_ENUM 0
 
 #define	USB_CALLOUT_ZERO_TICKS 1
 

Modified: stable/10/sys/dev/usb/usb_hub.c
==============================================================================
--- stable/10/sys/dev/usb/usb_hub.c	Mon Oct 27 07:51:26 2014	(r273728)
+++ stable/10/sys/dev/usb/usb_hub.c	Mon Oct 27 09:07:30 2014	(r273729)
@@ -98,6 +98,18 @@ SYSCTL_INT(_hw_usb, OID_AUTO, power_time
     &usb_power_timeout, 0, "USB power timeout");
 #endif
 
+#if USB_HAVE_DISABLE_ENUM
+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.");
+TUNABLE_INT("hw.usb.disable_enumeration", &usb_disable_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.");
+TUNABLE_INT("hw.usb.disable_port_power", &usb_disable_port_power);
+#endif
+
 struct uhub_current_state {
 	uint16_t port_change;
 	uint16_t port_status;
@@ -112,6 +124,10 @@ struct uhub_softc {
 	struct mtx sc_mtx;		/* our mutex */
 	struct usb_device *sc_udev;	/* USB device */
 	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
 };
@@ -619,9 +635,9 @@ repeat:
 	err = usbd_req_clear_port_feature(udev, NULL,
 	    portno, UHF_C_PORT_CONNECTION);
 
-	if (err) {
+	if (err)
 		goto error;
-	}
+
 	/* check if there is a child */
 
 	if (child != NULL) {
@@ -634,14 +650,22 @@ repeat:
 	/* get fresh status */
 
 	err = uhub_read_port_status(sc, portno);
-	if (err) {
+	if (err)
+		goto error;
+
+#if USB_HAVE_DISABLE_ENUM
+	/* check if we should skip enumeration from this USB HUB */
+	if (usb_disable_enumeration != 0 ||
+	    sc->sc_disable_enumeration != 0) {
+		DPRINTF("Enumeration is disabled!\n");
 		goto error;
 	}
+#endif
 	/* check if nothing is connected to the port */
 
-	if (!(sc->sc_st.port_status & UPS_CURRENT_CONNECT_STATUS)) {
+	if (!(sc->sc_st.port_status & UPS_CURRENT_CONNECT_STATUS))
 		goto error;
-	}
+
 	/* check if there is no power on the port and print a warning */
 
 	switch (udev->speed) {
@@ -1189,6 +1213,10 @@ uhub_attach(device_t dev)
 	struct usb_hub *hub;
 	struct usb_hub_descriptor hubdesc20;
 	struct usb_hub_ss_descriptor hubdesc30;
+#if USB_HAVE_DISABLE_ENUM
+	struct sysctl_ctx_list *sysctl_ctx;
+	struct sysctl_oid *sysctl_tree;
+#endif
 	uint16_t pwrdly;
 	uint16_t nports;
 	uint8_t x;
@@ -1386,6 +1414,34 @@ 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) {
+		char path[128];
+
+		snprintf(path, sizeof(path), "dev.uhub.%d.disable_enumeration",
+		    device_get_unit(dev));
+		TUNABLE_INT_FETCH(path, &sc->sc_disable_enumeration);
+
+		(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.");
+
+		snprintf(path, sizeof(path), "dev.uhub.%d.disable_port_power",
+		    device_get_unit(dev));
+		TUNABLE_INT_FETCH(path, &sc->sc_disable_port_power);
+
+		(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
@@ -1440,13 +1496,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",



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410270907.s9R97Vpq071240>