From 15ce7ce355b3cfb5ec8bc2d51528b08f02f4648b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 6 Dec 2015 23:22:37 +0000 Subject: [usb] Use port->disconnected to check for disconnected devices The usb_message() and usb_stream() functions currently check for port->speed==USB_SPEED_NONE to determine whether or not a device has been unplugged. This test will give a false negative result if a new device has been plugged in before the hotplug mechanism has finished handling the removal of the old device. Fix by checking instead the port->disconnected flag, which is now cleared only after completing the removal of the old device. Signed-off-by: Michael Brown --- src/drivers/bus/usb.c | 19 ++++++++++--------- src/drivers/usb/usbhub.c | 3 ++- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c index 63a7e46a..53501b46 100644 --- a/src/drivers/bus/usb.c +++ b/src/drivers/bus/usb.c @@ -485,7 +485,7 @@ int usb_message ( struct usb_endpoint *ep, unsigned int request, assert ( iob_headroom ( iobuf ) >= sizeof ( *packet ) ); /* Fail immediately if device has been unplugged */ - if ( port->speed == USB_SPEED_NONE ) + if ( port->disconnected ) return -ENODEV; /* Reset endpoint if required */ @@ -534,7 +534,7 @@ int usb_stream ( struct usb_endpoint *ep, struct io_buffer *iobuf, int rc; /* Fail immediately if device has been unplugged */ - if ( port->speed == USB_SPEED_NONE ) + if ( port->disconnected ) return -ENODEV; /* Reset endpoint if required */ @@ -1717,23 +1717,24 @@ static int usb_hotplugged ( struct usb_port *port ) { if ( ( rc = hub->driver->speed ( hub, port ) ) != 0 ) { DBGC ( hub, "USB hub %s port %d could not get speed: %s\n", hub->name, port->address, strerror ( rc ) ); - goto err_speed; + /* Treat as a disconnection */ + port->disconnected = 1; + port->speed = USB_SPEED_NONE; } /* Detach device, if applicable */ if ( port->attached && ( port->disconnected || ! port->speed ) ) usb_detached ( port ); + /* Clear any recorded disconnections */ + port->disconnected = 0; + /* Attach device, if applicable */ if ( port->speed && ( ! port->attached ) && ( ( rc = usb_attached ( port ) ) != 0 ) ) - goto err_attached; + return rc; - err_attached: - err_speed: - /* Clear any recorded disconnections */ - port->disconnected = 0; - return rc; + return 0; } /****************************************************************************** diff --git a/src/drivers/usb/usbhub.c b/src/drivers/usb/usbhub.c index 5cfc4052..a3e7bc00 100644 --- a/src/drivers/usb/usbhub.c +++ b/src/drivers/usb/usbhub.c @@ -496,9 +496,10 @@ static void hub_remove ( struct usb_function *func ) { unsigned int i; /* If hub has been unplugged, mark all ports as unplugged */ - if ( usb->port->speed == USB_SPEED_NONE ) { + if ( usb->port->disconnected ) { for ( i = 1 ; i <= hub->ports ; i++ ) { port = usb_port ( hub, i ); + port->disconnected = 1; port->speed = USB_SPEED_NONE; } } -- cgit v1.2.3-55-g7522