From 6da9c99059bf24fb1faae6b9613bae64ea50c05e Mon Sep 17 00:00:00 2001
From: David Vrabel <david.vrabel@csr.com>
Date: Wed, 18 Feb 2009 14:43:47 +0000
Subject: [PATCH] USB: allow libusb to talk to unauthenticated WUSB devices

To permit a userspace application to associate with WUSB devices
using numeric association, control transfers to unauthenticated WUSB
devices must be allowed.

This requires that wusbcore correctly sets the device state to
UNAUTHENTICATED, DEFAULT and ADDRESS and that control transfers can be
performed to UNAUTHENTICATED devices.

Signed-off-by: David Vrabel <david.vrabel@csr.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/usb/core/devio.c          | 3 ++-
 drivers/usb/core/hub.c            | 1 +
 drivers/usb/core/urb.c            | 2 +-
 drivers/usb/wusbcore/devconnect.c | 2 ++
 drivers/usb/wusbcore/security.c   | 2 ++
 include/linux/usb/ch9.h           | 2 +-
 6 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 6585f527e3817a..8f022af2fd7ad8 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -525,7 +525,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
 {
 	int ret = 0;
 
-	if (ps->dev->state != USB_STATE_ADDRESS
+	if (ps->dev->state != USB_STATE_UNAUTHENTICATED
+	 && ps->dev->state != USB_STATE_ADDRESS
 	 && ps->dev->state != USB_STATE_CONFIGURED)
 		return -EHOSTUNREACH;
 	if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype))
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 7e33d63ab92f74..f17d9ebc44af16 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1305,6 +1305,7 @@ void usb_set_device_state(struct usb_device *udev,
 		recursively_mark_NOTATTACHED(udev);
 	spin_unlock_irqrestore(&device_state_lock, flags);
 }
+EXPORT_SYMBOL_GPL(usb_set_device_state);
 
 /*
  * WUSB devices are simple: they have no hubs behind, so the mapping
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 58bc5e3c25603d..7025d801f23a71 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -295,7 +295,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 	if (!urb || urb->hcpriv || !urb->complete)
 		return -EINVAL;
 	dev = urb->dev;
-	if ((!dev) || (dev->state < USB_STATE_DEFAULT))
+	if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
 		return -ENODEV;
 
 	/* For now, get the endpoint from the pipe.  Eventually drivers
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c
index 8e18141bb2e08d..f0aac0cf315a5c 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -889,6 +889,8 @@ static void wusb_dev_add_ncb(struct usb_device *usb_dev)
 	if (usb_dev->wusb == 0 || usb_dev->devnum == 1)
 		return;		/* skip non wusb and wusb RHs */
 
+	usb_set_device_state(usb_dev, USB_STATE_UNAUTHENTICATED);
+
 	wusbhc = wusbhc_get_by_usb_dev(usb_dev);
 	if (wusbhc == NULL)
 		goto error_nodev;
diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c
index f4aa28eca70d44..8118db7f1d8ddd 100644
--- a/drivers/usb/wusbcore/security.c
+++ b/drivers/usb/wusbcore/security.c
@@ -312,6 +312,7 @@ int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
 	result = wusb_set_dev_addr(wusbhc, wusb_dev, 0);
 	if (result < 0)
 		goto error_addr0;
+	usb_set_device_state(usb_dev, USB_STATE_DEFAULT);
 	usb_ep0_reinit(usb_dev);
 
 	/* Set new (authenticated) address. */
@@ -327,6 +328,7 @@ int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
 	result = wusb_set_dev_addr(wusbhc, wusb_dev, new_address);
 	if (result < 0)
 		goto error_addr;
+	usb_set_device_state(usb_dev, USB_STATE_ADDRESS);
 	usb_ep0_reinit(usb_dev);
 	usb_dev->authenticated = 1;
 error_addr:
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index fa777db7f7eb71..d9d54803dbcb8b 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -763,8 +763,8 @@ enum usb_device_state {
 	/* chapter 9 and authentication (wireless) device states */
 	USB_STATE_ATTACHED,
 	USB_STATE_POWERED,			/* wired */
-	USB_STATE_UNAUTHENTICATED,		/* auth */
 	USB_STATE_RECONNECTING,			/* auth */
+	USB_STATE_UNAUTHENTICATED,		/* auth */
 	USB_STATE_DEFAULT,			/* limited function */
 	USB_STATE_ADDRESS,
 	USB_STATE_CONFIGURED,			/* most functions */
-- 
GitLab