* Alan Stern <[EMAIL PROTECTED]> [070525 14:09]:
> On Fri, 25 May 2007, David Brownell wrote:
> 
> > You omitted the "(except as noted in Section 3.8)", which says
> > that a second connector is allowed iff it's a Mini-A connector.
> > That's a trivial counter-example...
> > 
> > But in any case, section 3 is only talking about connectors,
> > not links that may be used internally on a mainboard and which
> > would not be externally visible.  The example I gave was for
> > an on-mainboard device.  (I've seen similar products using
> > SDIO to access modem chips.  Again, nothing visible to the end
> > users; just boards leveraging volume pricing for parts using
> > a wire-efficient I/O bus.)
> 
> Okay.  Then does this patch look good?

Here's an experimental related patch that makes two N800's work
with HNP, not yet verified with OPT. It also remove some of the
nestedness. The mdelay(4) should be redone though...

Regards,

Tony
>From 0417568cbc57d6683c197f756acf9fcc235e168a Mon Sep 17 00:00:00 2001
From: Tony Lindgren <[EMAIL PROTECTED]>
Date: Mon, 14 May 2007 18:14:36 -0700
Subject: [PATCH] USB: Fix OTG HNP for hub.c

This patch makes makes OTG Host Negotiation Protocol (HNP)
to behave.

Signed-off-by: Tony Lindgren <[EMAIL PROTECTED]>

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index caaa46f..3947449 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1252,6 +1252,81 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
 #ifdef	CONFIG_USB_OTG
 #include "otg_whitelist.h"
 static int __usb_port_suspend(struct usb_device *, int port1);
+
+/*
+ * OTG-aware devices on OTG-capable root hubs may be able to use SRP,
+ * to wake us after we've powered off VBUS; and HNP, switching roles
+ * "host" to "peripheral".  The OTG descriptor helps figure this out.
+ */
+static int usb_new_device_offer_hnp(struct usb_device *udev)
+{
+	struct usb_bus			*bus = udev->bus;
+	unsigned			port1 = udev->portnum;
+	struct usb_otg_descriptor	*desc = 0;
+	int				err;
+
+	if (udev->bus->is_b_host || !udev->config
+			|| udev->parent != udev->bus->root_hub)
+		return 0;
+
+	/* Descriptor may appear anywhere in config */
+	err = __usb_get_extra_descriptor(udev->rawdescriptors[0],
+				le16_to_cpu(udev->config[0].desc.wTotalLength),
+				USB_DT_OTG, (void **) &desc);
+	if (err < 0)
+		return 0;
+
+	if (!(desc->bmAttributes & USB_OTG_HNP))
+		return 0;
+
+	dev_info(&udev->dev, "Dual-Role OTG device on %sHNP port\n",
+				(port1 == bus->otg_port) ? "" : "non-");
+
+	/* Tell B-device if we support HNP */
+	if (port1 == bus->otg_port)
+		bus->b_hnp_enable = 1;
+	err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			USB_REQ_SET_FEATURE, 0,
+			bus->b_hnp_enable ? USB_DEVICE_B_HNP_ENABLE
+			: USB_DEVICE_A_ALT_HNP_SUPPORT,
+			0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+	if (err < 0) {
+		/*
+		 * OTG MESSAGE: report errors here, customize to match your
+		 * product.
+		 */
+		dev_err(&udev->dev, "can't set HNP mode; %d\n", err);
+		bus->b_hnp_enable = 0;
+		return 0;
+	}
+
+	/* If B-device wants to do HNP, it will do it after we suspend */
+	if (bus->b_hnp_enable) {
+		dev_err(&udev->dev, "trying HNP, suspending bus\n");
+		err = __usb_port_suspend(udev, udev->bus->otg_port);
+		if (err < 0) {
+			dev_err(&udev->dev, "suspend for HNP failed\n");
+			return -ENODEV;
+		}
+
+		/* TB_ASE0_BRST, minimum 3.125 ms */
+		mdelay(4);
+
+		/* Failed resume means B-device took over the bus with HNP */
+		err = usb_port_resume(udev);
+		if (err < 0) {
+			dev_err(&udev->dev, "HNP success\n");
+			return -ENODEV;
+		}
+	}
+
+	/* HNP failed. Reject B-devices not in our whitelist */
+	if (!is_targeted(udev))
+		return -ENODEV;
+
+	return 0;
+}
+
 #endif
 
 /**
@@ -1305,63 +1380,8 @@ int usb_new_device(struct usb_device *udev)
 	show_string(udev, "SerialNumber", udev->serial);
 
 #ifdef	CONFIG_USB_OTG
-	/*
-	 * OTG-aware devices on OTG-capable root hubs may be able to use SRP,
-	 * to wake us after we've powered off VBUS; and HNP, switching roles
-	 * "host" to "peripheral".  The OTG descriptor helps figure this out.
-	 */
-	if (!udev->bus->is_b_host
-			&& udev->config
-			&& udev->parent == udev->bus->root_hub) {
-		struct usb_otg_descriptor	*desc = 0;
-		struct usb_bus			*bus = udev->bus;
-
-		/* descriptor may appear anywhere in config */
-		if (__usb_get_extra_descriptor (udev->rawdescriptors[0],
-					le16_to_cpu(udev->config[0].desc.wTotalLength),
-					USB_DT_OTG, (void **) &desc) == 0) {
-			if (desc->bmAttributes & USB_OTG_HNP) {
-				unsigned		port1 = udev->portnum;
-
-				dev_info(&udev->dev,
-					"Dual-Role OTG device on %sHNP port\n",
-					(port1 == bus->otg_port)
-						? "" : "non-");
-
-				/* enable HNP before suspend, it's simpler */
-				if (port1 == bus->otg_port)
-					bus->b_hnp_enable = 1;
-				err = usb_control_msg(udev,
-					usb_sndctrlpipe(udev, 0),
-					USB_REQ_SET_FEATURE, 0,
-					bus->b_hnp_enable
-						? USB_DEVICE_B_HNP_ENABLE
-						: USB_DEVICE_A_ALT_HNP_SUPPORT,
-					0, NULL, 0, USB_CTRL_SET_TIMEOUT);
-				if (err < 0) {
-					/* OTG MESSAGE: report errors here,
-					 * customize to match your product.
-					 */
-					dev_info(&udev->dev,
-						"can't set HNP mode; %d\n",
-						err);
-					bus->b_hnp_enable = 0;
-				}
-			}
-		}
-	}
-
-	if (!is_targeted(udev)) {
-
-		/* Maybe it can talk to us, though we can't talk to it.
-		 * (Includes HNP test device.)
-		 */
-		if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
-			err = __usb_port_suspend(udev, udev->bus->otg_port);
-			if (err < 0)
-				dev_dbg(&udev->dev, "HNP fail, %d\n", err);
-		}
-		err = -ENODEV;
+	err = usb_new_device_offer_hnp(udev);
+	if (err < 0) {
 		goto fail;
 	}
 #endif
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to