From patchwork Wed Oct 24 16:14:17 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 193857 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id DBE822C0180 for ; Thu, 25 Oct 2012 03:48:32 +1100 (EST) Received: from localhost ([::1]:44061 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TR486-0005Nk-Vq for incoming@patchwork.ozlabs.org; Wed, 24 Oct 2012 12:48:30 -0400 Received: from eggs.gnu.org ([208.118.235.92]:34408) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TR47r-0005Ig-WC for qemu-devel@nongnu.org; Wed, 24 Oct 2012 12:48:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TR47l-0007tW-PQ for qemu-devel@nongnu.org; Wed, 24 Oct 2012 12:48:15 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56670) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TR47l-0007t0-GJ for qemu-devel@nongnu.org; Wed, 24 Oct 2012 12:48: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 q9OGm5wZ001857 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 24 Oct 2012 12:48:08 -0400 Received: from shalem.localdomain.com (vpn1-6-4.ams2.redhat.com [10.36.6.4]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q9OGCYjt008030; Wed, 24 Oct 2012 12:13:03 -0400 From: Hans de Goede To: Gerd Hoffmann Date: Wed, 24 Oct 2012 18:14:17 +0200 Message-Id: <1351095258-5579-22-git-send-email-hdegoede@redhat.com> In-Reply-To: <1351095258-5579-1-git-send-email-hdegoede@redhat.com> References: <1351095258-5579-1-git-send-email-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: Jan Kiszka , qemu-devel@nongnu.org, Hans de Goede Subject: [Qemu-devel] [PATCH 21/22] usb-redir: Allow to attach USB 2.0 devices to 1.1 host controller X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Jan Kiszka This follows the logic of host-linux: If a 2.0 device has no ISO endpoint and no interrupt endpoint with a packet size > 64, we can attach it also to an 1.1 host controller. In case the redir server does not report endpoint sizes, play safe and remove the 1.1 compatibility as well. Moreover, if we detect a conflicting change in the configuration after the device was already attached, it will be disconnected immediately. HdG: Several small cleanups and fixes Signed-off-by: Jan Kiszka Signed-off-by: Hans de Goede --- hw/usb/redirect.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index b1fc7ef..d2859b7 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -106,6 +106,7 @@ struct USBRedirDevice { struct usb_redir_interface_info_header interface_info; struct usbredirfilter_rule *filter_rules; int filter_rules_count; + int compatible_speedmask; }; static void usbredir_hello(void *priv, struct usb_redir_hello_header *h); @@ -974,6 +975,7 @@ static void usbredir_do_attach(void *opaque) } if (usb_device_attach(&dev->dev) != 0) { + WARNING("rejecting device due to speed mismatch\n"); usbredir_reject_device(dev); } } @@ -1094,6 +1096,9 @@ static int usbredir_initfn(USBDevice *udev) /* We'll do the attach once we receive the speed from the usb-host */ udev->auto_attach = 0; + /* Will be cleared during setup when we find conflicts */ + dev->compatible_speedmask = USB_SPEED_MASK_FULL; + /* Let the backend know we are ready */ qemu_chr_fe_open(dev->cs); qemu_chr_add_handlers(dev->cs, &usbredir_chr_handlers, dev); @@ -1233,6 +1238,7 @@ static void usbredir_device_connect(void *priv, case usb_redir_speed_low: speed = "low speed"; dev->dev.speed = USB_SPEED_LOW; + dev->compatible_speedmask &= ~USB_SPEED_MASK_FULL; break; case usb_redir_speed_full: speed = "full speed"; @@ -1266,7 +1272,7 @@ static void usbredir_device_connect(void *priv, device_connect->device_class); } - dev->dev.speedmask = (1 << dev->dev.speed); + dev->dev.speedmask = (1 << dev->dev.speed) | dev->compatible_speedmask; dev->device_info = *device_connect; if (usbredir_check_filter(dev)) { @@ -1306,6 +1312,7 @@ static void usbredir_device_disconnect(void *priv) dev->interface_info.interface_count = NO_INTERFACE_INFO; dev->dev.addr = 0; dev->dev.speed = 0; + dev->compatible_speedmask = USB_SPEED_MASK_FULL; } static void usbredir_interface_info(void *priv, @@ -1327,6 +1334,12 @@ static void usbredir_interface_info(void *priv, } } +static void usbredir_mark_speed_incompatible(USBRedirDevice *dev, int speed) +{ + dev->compatible_speedmask &= ~(1 << speed); + dev->dev.speedmask = (1 << dev->dev.speed) | dev->compatible_speedmask; +} + static void usbredir_set_pipeline(USBRedirDevice *dev, struct USBEndpoint *uep) { if (uep->type != USB_ENDPOINT_XFER_BULK) { @@ -1375,7 +1388,14 @@ static void usbredir_ep_info(void *priv, case usb_redir_type_invalid: break; case usb_redir_type_iso: + usbredir_mark_speed_incompatible(dev, USB_SPEED_FULL); + /* Fall through */ case usb_redir_type_interrupt: + if (!usbredirparser_peer_has_cap(dev->parser, + usb_redir_cap_ep_info_max_packet_size) || + ep_info->max_packet_size[i] > 64) { + usbredir_mark_speed_incompatible(dev, USB_SPEED_FULL); + } if (dev->endpoint[i].interval == 0) { ERROR("Received 0 interval for isoc or irq endpoint\n"); usbredir_reject_device(dev); @@ -1393,6 +1413,14 @@ static void usbredir_ep_info(void *priv, return; } } + /* The new ep info may have caused a speed incompatibility, recheck */ + if (dev->dev.attached && + !(dev->dev.port->speedmask & dev->dev.speedmask)) { + ERROR("Device no longer matches speed after endpoint info change, " + "disconnecting!\n"); + usbredir_reject_device(dev); + return; + } usbredir_setup_usb_eps(dev); }