Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4326ed0b authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

USB: address-0 handling during device initialization



This patch (as947) changes the device initialization and enumeration
code in hub.c; now udev->devnum will be set to 0 while the device is
being accessed at address 0.  Until now this wasn't needed because the
address value was passed as part of urb->pipe; without that field the
device address must be stored elsewhere.

Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 5e60a161
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -1481,6 +1481,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
		case 0:
			/* TRSTRCY = 10 ms; plus some extra */
			msleep(10 + 40);
		  	udev->devnum = 0;	/* Device now at address 0 */
			/* FALL THROUGH */
		case -ENOTCONN:
		case -ENODEV:
@@ -2005,20 +2006,21 @@ static void ep0_reinit(struct usb_device *udev)
#define usb_sndaddr0pipe()	(PIPE_CONTROL << 30)
#define usb_rcvaddr0pipe()	((PIPE_CONTROL << 30) | USB_DIR_IN)

static int hub_set_address(struct usb_device *udev)
static int hub_set_address(struct usb_device *udev, int devnum)
{
	int retval;

	if (udev->devnum == 0)
	if (devnum <= 1)
		return -EINVAL;
	if (udev->state == USB_STATE_ADDRESS)
		return 0;
	if (udev->state != USB_STATE_DEFAULT)
		return -EINVAL;
	retval = usb_control_msg(udev, usb_sndaddr0pipe(),
		USB_REQ_SET_ADDRESS, 0, udev->devnum, 0,
		USB_REQ_SET_ADDRESS, 0, devnum, 0,
		NULL, 0, USB_CTRL_SET_TIMEOUT);
	if (retval == 0) {
		udev->devnum = devnum;	/* Device now using proper address */
		usb_set_device_state(udev, USB_STATE_ADDRESS);
		ep0_reinit(udev);
	}
@@ -2045,6 +2047,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
	unsigned		delay = HUB_SHORT_RESET_TIME;
	enum usb_device_speed	oldspeed = udev->speed;
	char 			*speed, *type;
	int			devnum = udev->devnum;

	/* root hub ports have a slightly longer reset period
	 * (from USB 2.0 spec, section 7.1.7.5)
@@ -2115,7 +2118,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
	dev_info (&udev->dev,
		  "%s %s speed %sUSB device using %s and address %d\n",
		  (udev->config) ? "reset" : "new", speed, type,
		  udev->bus->controller->driver->name, udev->devnum);
		  udev->bus->controller->driver->name, devnum);

	/* Set up TT records, if needed  */
	if (hdev->tt) {
@@ -2202,7 +2205,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
		}

		for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
			retval = hub_set_address(udev);
			retval = hub_set_address(udev, devnum);
			if (retval >= 0)
				break;
			msleep(200);
@@ -2210,7 +2213,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
		if (retval < 0) {
			dev_err(&udev->dev,
				"device not accepting address %d, error %d\n",
				udev->devnum, retval);
				devnum, retval);
			goto fail;
		}
 
@@ -2263,8 +2266,10 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
	retval = 0;

fail:
	if (retval)
	if (retval) {
		hub_port_disable(hub, port1, 0);
		udev->devnum = devnum;	/* for disconnect processing */
	}
	mutex_unlock(&usb_address0_mutex);
	return retval;
}
+1 −3
Original line number Diff line number Diff line
@@ -284,9 +284,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)

	if (!urb || urb->hcpriv || !urb->complete)
		return -EINVAL;
	if (!(dev = urb->dev) ||
	    (dev->state < USB_STATE_DEFAULT) ||
	    (!dev->bus) || (dev->devnum <= 0))
	if (!(dev = urb->dev) || dev->state < USB_STATE_DEFAULT)
		return -ENODEV;
	if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
			|| dev->state == USB_STATE_SUSPENDED)