From patchwork Fri Jun 3 09:12:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 629734 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3rLdhL4fsbz9t6k for ; Fri, 3 Jun 2016 19:14:26 +1000 (AEST) Received: from localhost ([::1]:53543 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b8lBQ-0005SH-AN for incoming@patchwork.ozlabs.org; Fri, 03 Jun 2016 05:14:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60901) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b8lA5-0003fu-Kv for qemu-devel@nongnu.org; Fri, 03 Jun 2016 05:13:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b8lA4-0007Zo-Ev for qemu-devel@nongnu.org; Fri, 03 Jun 2016 05:13:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48509) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b8lA4-0007Zi-6s for qemu-devel@nongnu.org; Fri, 03 Jun 2016 05:13:00 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BA84F64D33 for ; Fri, 3 Jun 2016 09:12:59 +0000 (UTC) Received: from nilsson.home.kraxel.org (ovpn-116-36.ams2.redhat.com [10.36.116.36]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u539CwxQ004538; Fri, 3 Jun 2016 05:12:59 -0400 Received: by nilsson.home.kraxel.org (Postfix, from userid 500) id 3323C818B0; Fri, 3 Jun 2016 11:12:58 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Fri, 3 Jun 2016 11:12:55 +0200 Message-Id: <1464945175-28939-1-git-send-email-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 03 Jun 2016 09:12:59 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v2] usb-host: add special case for bus+addr X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This patch changes usb-host behavior in case we hostbus= and hostaddr= properties are used to identify the usb device in question. Instead of adding the device to the hotplug watchlist we try to open directly using the given bus number and device address. Putting a device specified by hostaddr to the hotplug watchlist isn't a great idea as the address isn't a fixed property. It changes every time the device is plugged in. So considering this case as "use the device at bus:addr _now_" is more sane. Also usb-host will throw errors in case it can't initialize the host device. Note: For devices on the hotplug watchlist (hostport or vendorid or productid specified) qemu continues to ignore errors and keeps monitoring the usb bus to see if the device eventually shows up. Signed-off-by: Gerd Hoffmann --- hw/usb/host-libusb.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index 8b774f4..da59c29 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -81,6 +81,7 @@ struct USBHostDevice { uint32_t iso_urb_frames; uint32_t options; uint32_t loglevel; + bool needs_autoscan; /* state */ QTAILQ_ENTRY(USBHostDevice) next; @@ -974,9 +975,32 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data) } } +static libusb_device *usb_host_find_ref(int bus, int addr) +{ + libusb_device **devs = NULL; + libusb_device *ret = NULL; + int i, n; + + if (usb_host_init() != 0) { + return NULL; + } + n = libusb_get_device_list(ctx, &devs); + for (i = 0; i < n; i++) { + if (libusb_get_bus_number(devs[i]) == bus && + libusb_get_device_address(devs[i]) == addr) { + ret = libusb_ref_device(devs[i]); + break; + } + } + libusb_free_device_list(devs, 1); + return ret; +} + static void usb_host_realize(USBDevice *udev, Error **errp) { USBHostDevice *s = USB_HOST_DEVICE(udev); + libusb_device *ldev; + int rc; if (s->match.vendor_id > 0xffff) { error_setg(errp, "vendorid out of range"); @@ -997,11 +1021,33 @@ static void usb_host_realize(USBDevice *udev, Error **errp) QTAILQ_INIT(&s->requests); QTAILQ_INIT(&s->isorings); + if (s->match.addr && s->match.bus_num && + !s->match.vendor_id && + !s->match.product_id && + !s->match.port) { + s->needs_autoscan = false; + ldev = usb_host_find_ref(s->match.bus_num, + s->match.addr); + if (!ldev) { + error_setg(errp, "failed to find host usb device %d:%d", + s->match.bus_num, s->match.addr); + return; + } + rc = usb_host_open(s, ldev); + libusb_unref_device(ldev); + if (rc < 0) { + error_setg(errp, "failed to open host usb device %d:%d", + s->match.bus_num, s->match.addr); + return; + } + } else { + s->needs_autoscan = true; + QTAILQ_INSERT_TAIL(&hostdevs, s, next); + usb_host_auto_check(NULL); + } + s->exit.notify = usb_host_exit_notifier; qemu_add_exit_notifier(&s->exit); - - QTAILQ_INSERT_TAIL(&hostdevs, s, next); - usb_host_auto_check(NULL); } static void usb_host_instance_init(Object *obj) @@ -1019,7 +1065,9 @@ static void usb_host_handle_destroy(USBDevice *udev) USBHostDevice *s = USB_HOST_DEVICE(udev); qemu_remove_exit_notifier(&s->exit); - QTAILQ_REMOVE(&hostdevs, s, next); + if (s->needs_autoscan) { + QTAILQ_REMOVE(&hostdevs, s, next); + } usb_host_close(s); }