From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:45157) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R49xO-0007Tk-CX for qemu-devel@nongnu.org; Thu, 15 Sep 2011 07:18:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1R49xJ-0007Ok-Qv for qemu-devel@nongnu.org; Thu, 15 Sep 2011 07:18:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38636) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R49xJ-0007OX-HZ for qemu-devel@nongnu.org; Thu, 15 Sep 2011 07:18:09 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p8FBI8EB021613 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 15 Sep 2011 07:18:08 -0400 From: Gerd Hoffmann Date: Thu, 15 Sep 2011 13:18:01 +0200 Message-Id: <1316085482-27569-6-git-send-email-kraxel@redhat.com> In-Reply-To: <1316085482-27569-1-git-send-email-kraxel@redhat.com> References: <1316085482-27569-1-git-send-email-kraxel@redhat.com> Subject: [Qemu-devel] [PATCH 5/6] usb-host: handle USBDEVFS_SETCONFIGURATION returning EBUSY List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Gerd Hoffmann In case the host uses the usb device usbfs will refuse to set the configuration due to the device being busy. Handle this case by disconnection the interfaces, then trying again. Signed-off-by: Gerd Hoffmann --- usb-linux.c | 36 +++++++++++++++++++++++++++++++++++- 1 files changed, 35 insertions(+), 1 deletions(-) diff --git a/usb-linux.c b/usb-linux.c index ff1a29c..7d4d1d7 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -485,6 +485,26 @@ static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces) return 0; } +static int usb_linux_get_num_interfaces(USBHostDevice *s) +{ + char device_name[64], line[1024]; + int num_interfaces = 0; + + if (usb_fs_type != USB_FS_SYS) { + return -1; + } + + sprintf(device_name, "%d-%s", s->bus_num, s->port); + if (!usb_host_read_file(line, sizeof(line), "bNumInterfaces", + device_name)) { + return -1; + } + if (sscanf(line, "%d", &num_interfaces) != 1) { + return -1; + } + return num_interfaces; +} + static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration) { const char *op = NULL; @@ -901,14 +921,28 @@ static int usb_host_set_address(USBHostDevice *s, int addr) static int usb_host_set_config(USBHostDevice *s, int config) { + int ret, first = 1; + trace_usb_host_set_config(s->bus_num, s->addr, config); usb_host_release_interfaces(s); - int ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config); +again: + ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config); DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno); + if (ret < 0 && errno == EBUSY && first) { + /* happens if usb device is in use by host drivers */ + int count = usb_linux_get_num_interfaces(s); + if (count > 0) { + DPRINTF("husb: busy -> disconnecting %d interfaces\n", count); + usb_host_disconnect_ifaces(s, count); + first = 0; + goto again; + } + } + if (ret < 0) { return ctrl_error(); } -- 1.7.1