From patchwork Tue Dec 18 08:46:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Kappner X-Patchwork-Id: 1015523 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=godking.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=godking.net header.i=@godking.net header.b="Me8PfuSA"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 43K4W20154z9s2P for ; Wed, 19 Dec 2018 04:18:53 +1100 (AEDT) Received: from localhost ([::1]:55384 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZJ19-0005dY-F4 for incoming@patchwork.ozlabs.org; Tue, 18 Dec 2018 12:18:51 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33391) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZB2B-000575-Sm for qemu-devel@nongnu.org; Tue, 18 Dec 2018 03:47:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gZB27-0001CX-QF for qemu-devel@nongnu.org; Tue, 18 Dec 2018 03:47:23 -0500 Received: from s18231873.onlinehome-server.info ([217.160.179.168]:48040 helo=godking.net) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gZB27-00019J-CM for qemu-devel@nongnu.org; Tue, 18 Dec 2018 03:47:19 -0500 Received: from KAMPFSAU-V.kappner.info (localhost [IPv6:::1]) by godking.net (Postfix) with ESMTP id A85191D2AE846; Tue, 18 Dec 2018 02:47:14 -0600 (CST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=godking.net; s=mail; t=1545122835; bh=FUDYs0XPQJEyPZaWHnJt80uP7HukC1ug+sbJCv5HwyU=; h=From:To:Cc:Subject:Date:From; b=Me8PfuSAabJ5GQfPGXVZKEeytLSWfe6WDieTDxW4Z231LWB5v/SbHab9nAibT7VAH N2Bsx1kGUsAvsppOBGbeAoZ4CUFVjSiFiEUELwJFUK0yisgGVacAoanxvrfhLZjx3h CqcZJCxbxk13WOn+QFwjgEmqTHAHuRIUTYVUprGv/kjn34eYXgPCkLDS7juIEJqHAb J7k8EIEXeyF91qztLvdl4vnf3n0R1Lh1uIbL2ZS0mvrwfq2Jmbz8YDPNbQNP3A4Q/+ N3WkEVlasucHpNUlGFdFF/UChacONQ/usQLrZdWm/xY3ogVDdqksd5cL7ZXw6vm3u3 Uzn1Fi++/fPMw== From: Alexander Kappner To: qemu-devel@nongnu.org Date: Tue, 18 Dec 2018 00:46:59 -0800 Message-Id: <1545122819-29687-1-git-send-email-agk@godking.net> X-Mailer: git-send-email 2.1.4 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 217.160.179.168 X-Mailman-Approved-At: Tue, 18 Dec 2018 12:18:11 -0500 Subject: [Qemu-devel] [PATCH] Introduce new "no_guest_reset" parameter for usb-host device 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: Alexander Kappner Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" With certain USB devices passed through via usb-host, a guest attempting to reset a usb-host device can trigger a reset loop that renders the USB device unusable. In my use case, the device was an iPhone XR that was passed through to a Mac OS X Mojave guest. Upon connecting the device, the following happens: 1) Guest recognizes new device, sends reset to emulated USB host 2) QEMU's USB host sends reset to host kernel 3) Host kernel resets device 4) After reset, host kernel determines that some part of the device descriptor has changed ("device firmware changed" in dmesg), so host kernel decides to re-enumerate the device. 5) Re-enumeration causes QEMU to disconnect and reconnect the device in the guest. 6) goto 1) Here's from the host kernel (note the "device firmware changed" lines") [3677704.473050] usb 1-1.3: new high-speed USB device number 53 using ehci-pci [3677704.555594] usb 1-1.3: New USB device found, idVendor=05ac, idProduct=12a8, bcdDevice=11.08 [3677704.555599] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [3677704.555602] usb 1-1.3: Product: iPhone [3677704.555605] usb 1-1.3: Manufacturer: Apple Inc. [3677704.555607] usb 1-1.3: SerialNumber: [[removed]] [3677709.401040] usb 1-1.3: reset high-speed USB device number 53 using ehci-pci [3677709.479486] usb 1-1.3: device firmware changed [3677709.479842] usb 1-1.3: USB disconnect, device number 53 [3677709.546039] usb 1-1.3: new high-speed USB device number 54 using ehci-pci [3677709.627471] usb 1-1.3: New USB device found, idVendor=05ac, idProduct=12a8, bcdDevice=11.08 [3677709.627476] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [3677709.627479] usb 1-1.3: Product: iPhone [3677709.627481] usb 1-1.3: Manufacturer: Apple Inc. [3677709.627483] usb 1-1.3: SerialNumber: [[removed]] [3677762.320044] usb 1-1.3: reset high-speed USB device number 54 using ehci-pci [3677762.615630] usb 1-1.3: USB disconnect, device number 54 [3677762.787043] usb 1-1.3: new high-speed USB device number 55 using ehci-pci [3677762.869016] usb 1-1.3: New USB device found, idVendor=05ac, idProduct=12a8, bcdDevice=11.08 [3677762.869024] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [3677762.869028] usb 1-1.3: Product: iPhone [3677762.869032] usb 1-1.3: Manufacturer: Apple Inc. [3677762.869035] usb 1-1.3: SerialNumber: [[removed]] [3677815.662036] usb 1-1.3: reset high-speed USB device number 55 using ehci-pci Here's from QEMU: libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/005/022: No such file or directory libusb: error [udev_hotplug_event] ignoring udev action bind libusb: error [udev_hotplug_event] ignoring udev action bind libusb: error [_open_sysfs_attr] open /sys/bus/usb/devices/5-1/bConfigurationValue failed ret=-1 errno=2 libusb: error [_get_usbfs_fd] File doesn't exist, wait 10 ms and try again libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/005/024: No such file or directory libusb: error [udev_hotplug_event] ignoring udev action bind libusb: error [udev_hotplug_event] ignoring udev action bind libusb: error [_open_sysfs_attr] open /sys/bus/usb/devices/5-1/bConfigurationValue failed ret=-1 errno=2 libusb: error [_get_usbfs_fd] File doesn't exist, wait 10 ms and try again libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/005/026: No such file or directory The result of this is that the device remains permanently unusable in the guest. The same problem has been previously reported for an iPad: https://stackoverflow.com/questions/52617634/how-do-i-get-qemu-usb-passthrough-to-work-for-ipad-iphone This problem can be elegantly solved by interrupting step 2) above. Instead of passing through the reset, QEMU simply ignores it. To allow this to be configured on a per-device level, a new parameter "no_guest_reset" is introduced for the usb-host device. I can confirm that the configuration described above (iPhone XS + Mojave guest) works flawlessly with no_guest_reset=True specified. Working command line for my scenario: device_add usb-host,vendorid=0x05ac,productid=0x12a8,no_guest_reset=True,id=iphone Best regards Alexander Signed-off-by: Alexander Kappner --- hw/usb/host-libusb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index 833250a..1b5e655 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -82,7 +82,7 @@ struct USBHostDevice { uint32_t options; uint32_t loglevel; bool needs_autoscan; - + bool no_guest_reset; /* state */ QTAILQ_ENTRY(USBHostDevice) next; int seen, errcount; @@ -1456,6 +1456,10 @@ static void usb_host_handle_reset(USBDevice *udev) USBHostDevice *s = USB_HOST_DEVICE(udev); int rc; + if (s->no_guest_reset) { + return; + } + trace_usb_host_reset(s->bus_num, s->addr); rc = libusb_reset_device(s->dh); @@ -1573,6 +1577,7 @@ static Property usb_host_dev_properties[] = { DEFINE_PROP_UINT32("productid", USBHostDevice, match.product_id, 0), DEFINE_PROP_UINT32("isobufs", USBHostDevice, iso_urb_count, 4), DEFINE_PROP_UINT32("isobsize", USBHostDevice, iso_urb_frames, 32), + DEFINE_PROP_BOOL("no_guest_reset", USBHostDevice, no_guest_reset, FALSE), DEFINE_PROP_UINT32("loglevel", USBHostDevice, loglevel, LIBUSB_LOG_LEVEL_WARNING), DEFINE_PROP_BIT("pipeline", USBHostDevice, options,