From 169ba82cb69d81587329e96d7732e3e9d116e0e1 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Thu, 23 Jun 2011 12:41:15 -0300
Subject: [RHEL6 qemu-kvm PATCH 042/115] usb: add port property.

RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1308832951-8995-40-git-send-email-kraxel@redhat.com>
Patchwork-id: 27876
O-Subject: [RHEL-6.2 kvm PATCH 039/115] usb: add port property.
Bugzilla: 561414 632299 645351 711354
RH-Acked-by: Hans de Goede <hdegoede@redhat.com>
RH-Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>

This allows to explictily set the physical port where you want to
plug the usb device.  Example:

  -device usb-tablet,bus=usb.0,port=2

With explicit port addressing qemu can and will not automagically add
USB Hubs.  This means that:

  (a) You can plug two devices of your choice into the two uhci
      root ports.
  (b) If you want plug in more that two devices you have to care
      about adding a hub yourself.

Plugging a hub works this way:

  -device usb-hub,bus=usb.0,port=1

Use this to add a device to the hub:

  -device usb-tablet,bus=usb.0,port=1.1

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 5f69076b8dda325dcbbc87bdb00e04ffac0f6137)

Conflicts:

	hw/usb-bus.c
---
 hw/usb-bus.c |   29 +++++++++++++++++++++++------
 hw/usb.h     |    1 +
 2 files changed, 24 insertions(+), 6 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 hw/usb-bus.c |   29 +++++++++++++++++++++++------
 hw/usb.h     |    1 +
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 5901959..8888732 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -15,6 +15,10 @@ static struct BusInfo usb_bus_info = {
     .print_dev = usb_bus_dev_print,
     .get_dev_path = usb_get_dev_path,
     .get_fw_dev_path = usbbus_get_fw_dev_path,
+    .props      = (Property[]) {
+        DEFINE_PROP_STRING("port", USBDevice, port_path),
+        DEFINE_PROP_END_OF_LIST()
+    },
 };
 static int next_usb_bus = 0;
 static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
@@ -154,9 +158,22 @@ static void do_attach(USBDevice *dev)
                 dev->product_desc);
         return;
     }
-    dev->attached++;
+    if (dev->port_path) {
+        QTAILQ_FOREACH(port, &bus->free, next) {
+            if (strcmp(port->path, dev->port_path) == 0) {
+                break;
+            }
+        }
+        if (port == NULL) {
+            fprintf(stderr, "Warning: usb port %s (bus %s) not found\n",
+                    dev->port_path, bus->qbus.name);
+            return;
+        }
+    } else {
+        port = QTAILQ_FIRST(&bus->free);
+    }
 
-    port = QTAILQ_FIRST(&bus->free);
+    dev->attached++;
     QTAILQ_REMOVE(&bus->free, port, next);
     bus->nfree--;
 
@@ -169,11 +186,11 @@ static void do_attach(USBDevice *dev)
 int usb_device_attach(USBDevice *dev)
 {
     USBBus *bus = usb_bus_from_device(dev);
-    USBDevice *hub;
 
-    if (bus->nfree == 1) {
-        /* Create a new hub and chain it on.  */
-        hub = usb_create_simple(bus, "usb-hub");
+    if (bus->nfree == 1 && dev->port_path == NULL) {
+        /* Create a new hub and chain it on
+           (unless a physical port location is specified). */
+        usb_create_simple(bus, "usb-hub");
     }
     do_attach(dev);
     return 0;
diff --git a/hw/usb.h b/hw/usb.h
index 21b417b..4a095ab 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -152,6 +152,7 @@ struct USBDevice {
     DeviceState qdev;
     USBDeviceInfo *info;
     USBPort *port;
+    char *port_path;
     void *opaque;
 
     int speed;
-- 
1.7.3.2