diff mbox

[4/9] qdev/usb: make qemu aware of usb busses.

Message ID 1251721445-17824-5-git-send-email-kraxel@redhat.com
State Superseded
Headers show

Commit Message

Gerd Hoffmann Aug. 31, 2009, 12:24 p.m. UTC
Move usb code from vl.c to usb-bus.c and make it use the new data
structures added by qdev conversion.  qemu usb core should be able
to handle multiple USB busses just fine now (untested though).

Kill some usb_*_init() legacy functions, use usb_create_simple()
instead.

Kill some FIXMEs added by the first qdev/usb patch.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/bt-hid.c      |    3 +-
 hw/usb-bus.c     |  140 +++++++++++++++++++++++++++++++++++++++++++++++--
 hw/usb-hid.c     |   15 -----
 hw/usb-hub.c     |    8 +--
 hw/usb-musb.c    |    4 +-
 hw/usb-ohci.c    |    4 +-
 hw/usb-uhci.c    |    7 ++-
 hw/usb-wacom.c   |    5 --
 hw/usb.h         |   28 +++++-----
 pc-bios/bios.bin |  Bin 131072 -> 131072 bytes
 usb-linux.c      |   12 ++--
 vl.c             |  154 +++++++++++++-----------------------------------------
 12 files changed, 206 insertions(+), 174 deletions(-)

Comments

Gerd Hoffmann Aug. 31, 2009, 1:31 p.m. UTC | #1
On 08/31/09 14:45, Juan Quintela wrote:
>>   pc-bios/bios.bin |  Bin 131072 ->  131072 bytes
>
> Do you really wanted to include this?

Oops, no.  Probably committed by mistake via 'git commit -a'

>> +static struct {
>> +    const char *name;
>> +    const char *qdev;
>> +} usbdevs[] = {
>> +    {
>> +        .name = "mouse",
>> +        .qdev = "QEMU USB Mouse",
>> +    },{
>> +        .name = "tablet",
>> +        .qdev = "QEMU USB Tablet",

> We don't want this table here, we want to be able to compile out
> table/mouse/disk/...  And to get that compiled out, vl.c shouldn't have
> any knowled of what goes here.

Hmm.  That isn't easy to do for the -usbdevice legacy handling ...

>> +    /* simple devices which don't need extra care */
>> +    for (i = 0; i<  ARRAY_SIZE(usbdevs); i++) {
>> +        if (strcmp(devname, usbdevs[i].name) != 0)
>> +            continue;
>
> This function should be take care in global function.

parse error. --verbose please.

> I think we really need a way to pass the extra parameters to
> usb_create_simple

No.  Cases where usb_create_simple() doesn't work are handled via

   usb_create();
   /* set properties here */
   qdev_init();

in the -usbdevice legacy path.  When creating devices via -device you'll 
specify the properties directly on the command line instead.  Last patch 
of the series shows this for usb-msd.

There are some usb devices which are not yet fully converted, i.e. 
parameters can't be passed via properties.  This needs more work.

cheers,
   Gerd
diff mbox

Patch

diff --git a/hw/bt-hid.c b/hw/bt-hid.c
index 6f37705..020176e 100644
--- a/hw/bt-hid.c
+++ b/hw/bt-hid.c
@@ -566,5 +566,6 @@  static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net,
 
 struct bt_device_s *bt_keyboard_init(struct bt_scatternet_s *net)
 {
-    return bt_hid_init(net, usb_keyboard_init(), class_keyboard);
+    USBDevice *dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Keyboard");
+    return bt_hid_init(net, dev, class_keyboard);
 }
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index c695a37..169fb2f 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -1,10 +1,15 @@ 
 #include "hw.h"
 #include "usb.h"
 #include "qdev.h"
+#include "sysemu.h"
+#include "monitor.h"
+
+static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
 
 static struct BusInfo usb_bus_info = {
-    .name  = "USB",
-    .size  = sizeof(USBBus),
+    .name      = "USB",
+    .size      = sizeof(USBBus),
+    .print_dev = usb_bus_dev_print,
 };
 static int next_usb_bus = 0;
 static TAILQ_HEAD(, USBBus) busses = TAILQ_HEAD_INITIALIZER(busses);
@@ -43,6 +48,8 @@  static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
     pstrcpy(dev->devname, sizeof(dev->devname), qdev->info->name);
     dev->info = info;
     rc = dev->info->init(dev);
+    if (rc == 0)
+        usb_device_attach(dev);
     return rc;
 }
 
@@ -61,7 +68,7 @@  void usb_qdev_register_many(USBDeviceInfo *info)
     }
 }
 
-USBDevice *usb_create_simple(USBBus *bus, const char *name)
+USBDevice *usb_create(USBBus *bus, const char *name)
 {
     DeviceState *dev;
 
@@ -77,6 +84,131 @@  USBDevice *usb_create_simple(USBBus *bus, const char *name)
 #endif
 
     dev = qdev_create(&bus->qbus, name);
-    qdev_init(dev);
     return DO_UPCAST(USBDevice, qdev, dev);
 }
+
+USBDevice *usb_create_simple(USBBus *bus, const char *name)
+{
+    USBDevice *dev = usb_create(bus, name);
+    qdev_init(&dev->qdev);
+    return dev;
+}
+
+void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
+                       usb_attachfn attach)
+{
+    port->opaque = opaque;
+    port->index = index;
+    port->attach = attach;
+    TAILQ_INSERT_TAIL(&bus->free, port, next);
+    bus->nfree++;
+}
+
+static void do_attach(USBDevice *dev)
+{
+    USBBus *bus = usb_bus_from_device(dev);
+    USBPort *port;
+
+    if (dev->attached) {
+        fprintf(stderr, "Warning: tried to attach usb device %s twice\n",
+                dev->devname);
+        return;
+    }
+    dev->attached++;
+
+    port = TAILQ_FIRST(&bus->free);
+    TAILQ_REMOVE(&bus->free, port, next);
+    bus->nfree--;
+
+    usb_attach(port, dev);
+
+    TAILQ_INSERT_TAIL(&bus->used, port, next);
+    bus->nused++;
+}
+
+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, "QEMU USB Hub");
+    }
+    do_attach(dev);
+    return 0;
+}
+
+int usb_device_delete_addr(int busnr, int addr)
+{
+    USBBus *bus;
+    USBPort *port;
+    USBDevice *dev;
+
+    bus = usb_bus_find(busnr);
+    if (!bus)
+        return -1;
+
+    TAILQ_FOREACH(port, &bus->used, next) {
+        if (port->dev->addr == addr)
+            break;
+    }
+    if (!port)
+        return -1;
+
+    dev = port->dev;
+    TAILQ_REMOVE(&bus->used, port, next);
+    bus->nused--;
+
+    usb_attach(port, NULL);
+    dev->info->handle_destroy(dev);
+
+    TAILQ_INSERT_TAIL(&bus->free, port, next);
+    bus->nfree++;
+    return 0;
+}
+
+static const char *usb_speed(unsigned int speed)
+{
+    static const char *txt[] = {
+        [ USB_SPEED_LOW  ] = "1.5",
+        [ USB_SPEED_FULL ] = "12",
+        [ USB_SPEED_HIGH ] = "480",
+    };
+    if (speed >= ARRAY_SIZE(txt))
+        return "?";
+    return txt[speed];
+}
+
+static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
+{
+    USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+    USBBus *bus = usb_bus_from_device(dev);
+
+    monitor_printf(mon, "%*saddr %d.%d, speed %s, name %s\n", indent, "",
+                   bus->busnr, dev->addr,
+                   usb_speed(dev->speed), dev->devname);
+}
+
+void usb_info(Monitor *mon)
+{
+    USBBus *bus;
+    USBDevice *dev;
+    USBPort *port;
+
+    if (TAILQ_EMPTY(&busses)) {
+        monitor_printf(mon, "USB support not enabled\n");
+        return;
+    }
+
+    TAILQ_FOREACH(bus, &busses, next) {
+        TAILQ_FOREACH(port, &bus->used, next) {
+            dev = port->dev;
+            if (!dev)
+                continue;
+            monitor_printf(mon, "  Device %d.%d, Speed %s Mb/s, Product %s\n",
+                           bus->busnr, dev->addr, usb_speed(dev->speed), dev->devname);
+        }
+    }
+}
+
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index c8b6ee7..0837ec1 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -871,21 +871,6 @@  static int usb_keyboard_initfn(USBDevice *dev)
     return usb_hid_initfn(dev, USB_KEYBOARD);
 }
 
-USBDevice *usb_tablet_init(void)
-{
-    return usb_create_simple(NULL /* FIXME */, "QEMU USB Tablet");
-}
-
-USBDevice *usb_mouse_init(void)
-{
-    return usb_create_simple(NULL /* FIXME */, "QEMU USB Mouse");
-}
-
-USBDevice *usb_keyboard_init(void)
-{
-    return usb_create_simple(NULL /* FIXME */, "QEMU USB Keyboard");
-}
-
 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
 {
     USBHIDState *s = (USBHIDState *)dev;
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 116b1d2..0a39986 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -531,18 +531,14 @@  static int usb_hub_initfn(USBDevice *dev)
     s->nb_ports = MAX_PORTS; /* FIXME: make configurable */
     for (i = 0; i < s->nb_ports; i++) {
         port = &s->ports[i];
-        qemu_register_usb_port(&port->port, s, i, usb_hub_attach);
+        usb_register_port(usb_bus_from_device(dev),
+                          &port->port, s, i, usb_hub_attach);
         port->wPortStatus = PORT_STAT_POWER;
         port->wPortChange = 0;
     }
     return 0;
 }
 
-USBDevice *usb_hub_init(int nb_ports)
-{
-    return usb_create_simple(NULL /* FIXME */, "QEMU USB Hub");
-}
-
 static struct USBDeviceInfo hub_info = {
     .qdev.name      = "QEMU USB Hub",
     .qdev.size      = sizeof(USBHubState),
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index b23ed3f..8fba84d 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -281,6 +281,7 @@  typedef struct {
 
 struct MUSBState {
     qemu_irq *irqs;
+    USBBus *bus;
     USBPort port;
 
     int idx;
@@ -330,7 +331,8 @@  struct MUSBState {
         s->ep[i].epnum = i;
     }
 
-    qemu_register_usb_port(&s->port, s, 0, musb_attach);
+    s->bus = usb_bus_new(NULL /* FIXME */);
+    usb_register_port(s->bus, &s->port, s, 0, musb_attach);
 
     return s;
 }
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index e725e97..7f620c7 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -65,6 +65,7 @@  enum ohci_type {
 };
 
 typedef struct {
+    USBBus *bus;
     qemu_irq irq;
     enum ohci_type type;
     int mem;
@@ -1688,9 +1689,10 @@  static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn,
     ohci->irq = irq;
     ohci->type = type;
 
+    ohci->bus = usb_bus_new(NULL /* FIXME */);
     ohci->num_ports = num_ports;
     for (i = 0; i < num_ports; i++) {
-        qemu_register_usb_port(&ohci->rhport[i].port, ohci, i, ohci_attach);
+        usb_register_port(ohci->bus, &ohci->rhport[i].port, ohci, i, ohci_attach);
     }
 
     ohci->async_td = 0;
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index a112a69..2ff287b 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -122,6 +122,7 @@  typedef struct UHCIPort {
 
 typedef struct UHCIState {
     PCIDevice dev;
+    USBBus *bus;
     uint16_t cmd; /* cmd register */
     uint16_t status;
     uint16_t intr; /* interrupt enable register */
@@ -1089,8 +1090,9 @@  void usb_uhci_piix3_init(PCIBus *bus, int devfn)
     pci_conf[0x3d] = 4; // interrupt pin 3
     pci_conf[0x60] = 0x10; // release number
 
+    s->bus = usb_bus_new(NULL /* FIXME */);
     for(i = 0; i < NB_PORTS; i++) {
-        qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
+        usb_register_port(s->bus, &s->ports[i].port, s, i, uhci_attach);
     }
     s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
 
@@ -1124,8 +1126,9 @@  void usb_uhci_piix4_init(PCIBus *bus, int devfn)
     pci_conf[0x3d] = 4; // interrupt pin 3
     pci_conf[0x60] = 0x10; // release number
 
+    s->bus = usb_bus_new(NULL /* FIXME */);
     for(i = 0; i < NB_PORTS; i++) {
-        qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
+        usb_register_port(s->bus, &s->ports[i].port, s, i, uhci_attach);
     }
     s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
 
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index a5abb98..4007e0f 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -399,11 +399,6 @@  static int usb_wacom_initfn(USBDevice *dev)
     return 0;
 }
 
-USBDevice *usb_wacom_init(void)
-{
-    return usb_create_simple(NULL /* FIXME */, "QEMU PenPartner Tablet");
-}
-
 static struct USBDeviceInfo wacom_info = {
     .qdev.name      = "QEMU PenPartner Tablet",
     .qdev.size      = sizeof(USBWacomState),
diff --git a/hw/usb.h b/hw/usb.h
index dea5718..3632639 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -24,6 +24,7 @@ 
 
 #include "block.h"
 #include "qdev.h"
+#include "sys-queue.h"
 
 #define USB_TOKEN_SETUP 0x2d
 #define USB_TOKEN_IN    0x69 /* device -> host */
@@ -132,6 +133,7 @@  struct USBDevice {
     int speed;
     uint8_t addr;
     char devname[32];
+    int attached;
 
     int state;
     uint8_t setup_buf[8];
@@ -191,7 +193,7 @@  struct USBPort {
     usb_attachfn attach;
     void *opaque;
     int index; /* internal port index, may be used with the opaque */
-    struct USBPort *next; /* Used internally by qemu.  */
+    TAILQ_ENTRY(USBPort) next;
 };
 
 typedef void USBCallback(USBPacket * packet, void *opaque);
@@ -236,25 +238,17 @@  static inline void usb_cancel_packet(USBPacket * p)
     p->cancel_cb(p, p->cancel_opaque);
 }
 
-int usb_device_add_dev(USBDevice *dev);
-int usb_device_del_addr(int bus_num, int addr);
 void usb_attach(USBPort *port, USBDevice *dev);
 int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
 int set_usb_string(uint8_t *buf, const char *str);
 void usb_send_msg(USBDevice *dev, int msg);
 
-/* usb hub */
-USBDevice *usb_hub_init(int nb_ports);
-
 /* usb-linux.c */
 USBDevice *usb_host_device_open(const char *devname);
 int usb_host_device_close(const char *devname);
 void usb_host_info(Monitor *mon);
 
 /* usb-hid.c */
-USBDevice *usb_mouse_init(void);
-USBDevice *usb_tablet_init(void);
-USBDevice *usb_keyboard_init(void);
 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *));
 
 /* usb-msd.c */
@@ -267,17 +261,11 @@  USBDevice *usb_net_init(NICInfo *nd);
 /* usb-bt.c */
 USBDevice *usb_bt_init(HCIInfo *hci);
 
-/* usb-wacom.c */
-USBDevice *usb_wacom_init(void);
-
 /* usb-serial.c */
 USBDevice *usb_serial_init(const char *filename);
 
 /* usb ports of the VM */
 
-void qemu_register_usb_port(USBPort *port, void *opaque, int index,
-                            usb_attachfn attach);
-
 #define VM_USB_HUB_SIZE 8
 
 /* usb-musb.c */
@@ -319,4 +307,14 @@  USBBus *usb_bus_new(DeviceState *host);
 USBBus *usb_bus_find(int busnr);
 void usb_qdev_register(USBDeviceInfo *info);
 void usb_qdev_register_many(USBDeviceInfo *info);
+USBDevice *usb_create(USBBus *bus, const char *name);
 USBDevice *usb_create_simple(USBBus *bus, const char *name);
+void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
+                       usb_attachfn attach);
+int usb_device_attach(USBDevice *dev);
+int usb_device_delete_addr(int busnr, int addr);
+
+static inline USBBus *usb_bus_from_device(USBDevice *d)
+{
+    return DO_UPCAST(USBBus, qbus, d->qdev.parent_bus);
+}
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index dc7d3825ec59a33f065ea005014ffcf3a8b1b632..542beddc6fa9c267893283c919158be28f61cb05 100644
GIT binary patch
delta 18738
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
Dg%aIO

delta 13343
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

diff --git a/usb-linux.c b/usb-linux.c
index 0130b71..df3d54d 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -252,7 +252,7 @@  static void async_complete(void *opaque)
 
             if (errno == ENODEV && !s->closing) {
                 printf("husb: device %d.%d disconnected\n", s->bus_num, s->addr);
-	        usb_device_del_addr(0, s->dev.addr);
+	        usb_device_delete_addr(s->bus_num, s->dev.addr);
                 return;
             }
 
@@ -909,7 +909,7 @@  static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *p
     }
     dprintf("husb: opened %s\n", buf);
 
-    d = usb_create_simple(NULL /* FIXME */, "USB Host Device");
+    d = usb_create(NULL /* FIXME */, "USB Host Device");
     dev = DO_UPCAST(USBHostDevice, dev, d);
 
     dev->bus_num = bus_num;
@@ -1039,16 +1039,16 @@  int usb_host_device_close(const char *devname)
     if (usb_host_find_device(&bus_num, &addr, product_name, sizeof(product_name),
                              devname) < 0)
         return -1;
- 
+
     s = hostdev_find(bus_num, addr);
     if (s) {
-        usb_device_del_addr(0, s->dev.addr);
+        usb_device_delete_addr(s->bus_num, s->dev.addr);
         return 0;
     }
 
     return -1;
 }
- 
+
 static int get_tag_value(char *buf, int buf_size,
                          const char *str, const char *tag,
                          const char *stopchars)
@@ -1387,7 +1387,7 @@  static int usb_host_auto_scan(void *opaque, int bus_num, int addr,
 
 	dev = usb_host_device_open_addr(bus_num, addr, product_name);
 	if (dev)
-	    usb_device_add_dev(dev);
+            qdev_init(&dev->qdev);
     }
 
     return 0;
diff --git a/vl.c b/vl.c
index c362d1f..72f7dd6 100644
--- a/vl.c
+++ b/vl.c
@@ -2430,72 +2430,56 @@  static void smp_parse(const char *optarg)
 /***********************************************************/
 /* USB devices */
 
-static USBPort *used_usb_ports;
-static USBPort *free_usb_ports;
-
-/* ??? Maybe change this to register a hub to keep track of the topology.  */
-void qemu_register_usb_port(USBPort *port, void *opaque, int index,
-                            usb_attachfn attach)
-{
-    port->opaque = opaque;
-    port->index = index;
-    port->attach = attach;
-    port->next = free_usb_ports;
-    free_usb_ports = port;
-}
-
-int usb_device_add_dev(USBDevice *dev)
-{
-    USBPort *port;
-
-    /* Find a USB port to add the device to.  */
-    port = free_usb_ports;
-    if (!port->next) {
-        USBDevice *hub;
-
-        /* Create a new hub and chain it on.  */
-        free_usb_ports = NULL;
-        port->next = used_usb_ports;
-        used_usb_ports = port;
-
-        hub = usb_hub_init(VM_USB_HUB_SIZE);
-        usb_attach(port, hub);
-        port = free_usb_ports;
-    }
-
-    free_usb_ports = port->next;
-    port->next = used_usb_ports;
-    used_usb_ports = port;
-    usb_attach(port, dev);
-    return 0;
-}
-
 static void usb_msd_password_cb(void *opaque, int err)
 {
     USBDevice *dev = opaque;
 
     if (!err)
-        usb_device_add_dev(dev);
+        usb_device_attach(dev);
     else
         dev->info->handle_destroy(dev);
 }
 
+static struct {
+    const char *name;
+    const char *qdev;
+} usbdevs[] = {
+    {
+        .name = "mouse",
+        .qdev = "QEMU USB Mouse",
+    },{
+        .name = "tablet",
+        .qdev = "QEMU USB Tablet",
+    },{
+        .name = "keyboard",
+        .qdev = "QEMU USB Keyboard",
+    },{
+        .name = "wacom-tablet",
+        .qdev = "QEMU PenPartner Tablet",
+    }
+};
+
 static int usb_device_add(const char *devname, int is_hotplug)
 {
     const char *p;
-    USBDevice *dev;
+    USBBus *bus = usb_bus_find(-1 /* any */);
+    USBDevice *dev = NULL;
+    int i;
 
-    if (!free_usb_ports)
+    if (!usb_enabled)
         return -1;
 
+    /* simple devices which don't need extra care */
+    for (i = 0; i < ARRAY_SIZE(usbdevs); i++) {
+        if (strcmp(devname, usbdevs[i].name) != 0)
+            continue;
+        dev = usb_create_simple(bus, usbdevs[i].qdev);
+        goto done;
+    }
+
+    /* the other ones */
     if (strstart(devname, "host:", &p)) {
         dev = usb_host_device_open(p);
-    } else if (!strcmp(devname, "mouse")) {
-        dev = usb_mouse_init();
-    } else if (!strcmp(devname, "tablet")) {
-        dev = usb_tablet_init();
-    } else if (!strcmp(devname, "keyboard")) {
-        dev = usb_keyboard_init();
     } else if (strstart(devname, "disk:", &p)) {
         BlockDriverState *bs;
 
@@ -2511,8 +2495,6 @@  static int usb_device_add(const char *devname, int is_hotplug)
                 return 0;
             }
         }
-    } else if (!strcmp(devname, "wacom-tablet")) {
-        dev = usb_wacom_init();
     } else if (strstart(devname, "serial:", &p)) {
         dev = usb_serial_init(p);
 #ifdef CONFIG_BRLAPI
@@ -2535,37 +2517,7 @@  static int usb_device_add(const char *devname, int is_hotplug)
     if (!dev)
         return -1;
 
-    return usb_device_add_dev(dev);
-}
-
-int usb_device_del_addr(int bus_num, int addr)
-{
-    USBPort *port;
-    USBPort **lastp;
-    USBDevice *dev;
-
-    if (!used_usb_ports)
-        return -1;
-
-    if (bus_num != 0)
-        return -1;
-
-    lastp = &used_usb_ports;
-    port = used_usb_ports;
-    while (port && port->dev->addr != addr) {
-        lastp = &port->next;
-        port = port->next;
-    }
-
-    if (!port)
-        return -1;
-
-    dev = port->dev;
-    *lastp = port->next;
-    usb_attach(port, NULL);
-    dev->info->handle_destroy(dev);
-    port->next = free_usb_ports;
-    free_usb_ports = port;
+done:
     return 0;
 }
 
@@ -2577,7 +2529,7 @@  static int usb_device_del(const char *devname)
     if (strstart(devname, "host:", &p))
         return usb_host_device_close(p);
 
-    if (!used_usb_ports)
+    if (!usb_enabled)
         return -1;
 
     p = strchr(devname, '.');
@@ -2586,7 +2538,7 @@  static int usb_device_del(const char *devname)
     bus_num = strtoul(devname, NULL, 0);
     addr = strtoul(p + 1, NULL, 0);
 
-    return usb_device_del_addr(bus_num, addr);
+    return usb_device_delete_addr(bus_num, addr);
 }
 
 static int usb_parse(const char *cmdline)
@@ -2604,40 +2556,6 @@  void do_usb_del(Monitor *mon, const char *devname)
     usb_device_del(devname);
 }
 
-void usb_info(Monitor *mon)
-{
-    USBDevice *dev;
-    USBPort *port;
-    const char *speed_str;
-
-    if (!usb_enabled) {
-        monitor_printf(mon, "USB support not enabled\n");
-        return;
-    }
-
-    for (port = used_usb_ports; port; port = port->next) {
-        dev = port->dev;
-        if (!dev)
-            continue;
-        switch(dev->speed) {
-        case USB_SPEED_LOW:
-            speed_str = "1.5";
-            break;
-        case USB_SPEED_FULL:
-            speed_str = "12";
-            break;
-        case USB_SPEED_HIGH:
-            speed_str = "480";
-            break;
-        default:
-            speed_str = "?";
-            break;
-        }
-        monitor_printf(mon, "  Device %d.%d, Speed %s Mb/s, Product %s\n",
-                       0, dev->addr, speed_str, dev->devname);
-    }
-}
-
 /***********************************************************/
 /* PCMCIA/Cardbus */