usb: add port property.

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>
This commit is contained in:
Gerd Hoffmann 2010-12-10 11:43:35 +01:00
parent c7a2196a4f
commit 5f69076b8d
2 changed files with 23 additions and 4 deletions

View File

@ -15,6 +15,10 @@ static struct BusInfo usb_bus_info = {
.print_dev = usb_bus_dev_print, .print_dev = usb_bus_dev_print,
.get_dev_path = usb_get_dev_path, .get_dev_path = usb_get_dev_path,
.get_fw_dev_path = usbbus_get_fw_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 int next_usb_bus = 0;
static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses); static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
@ -157,9 +161,22 @@ static void do_attach(USBDevice *dev)
dev->product_desc); dev->product_desc);
return; 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); QTAILQ_REMOVE(&bus->free, port, next);
bus->nfree--; bus->nfree--;
@ -173,8 +190,9 @@ int usb_device_attach(USBDevice *dev)
{ {
USBBus *bus = usb_bus_from_device(dev); USBBus *bus = usb_bus_from_device(dev);
if (bus->nfree == 1) { if (bus->nfree == 1 && dev->port_path == NULL) {
/* Create a new hub and chain it on. */ /* Create a new hub and chain it on
(unless a physical port location is specified). */
usb_create_simple(bus, "usb-hub"); usb_create_simple(bus, "usb-hub");
} }
do_attach(dev); do_attach(dev);

View File

@ -156,6 +156,7 @@ struct USBDevice {
DeviceState qdev; DeviceState qdev;
USBDeviceInfo *info; USBDeviceInfo *info;
USBPort *port; USBPort *port;
char *port_path;
void *opaque; void *opaque;
int speed; int speed;