OSDN Git Service

usb: hook unplug into qdev, cleanups + fixes.
authorGerd Hoffmann <kraxel@redhat.com>
Fri, 25 Sep 2009 19:42:39 +0000 (21:42 +0200)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 5 Oct 2009 14:32:48 +0000 (09:32 -0500)
Hook into DeviceInfo->exit().

handle_destroy() must not free the state struct, this is handled
by the new usb_qdev_exit() function now.

qdev_free(usb_device) works now.

Fix usb hub to qdev_free() all connected devices on unplug.
Unplugging a usb hub works now.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
hw/usb-bt.c
hw/usb-bus.c
hw/usb-hid.c
hw/usb-hub.c
hw/usb-msd.c
hw/usb-serial.c
hw/usb-wacom.c
hw/usb.h

index 70fd4dd..18d7a98 100644 (file)
@@ -614,7 +614,6 @@ static void usb_bt_handle_destroy(USBDevice *dev)
     s->hci->opaque = NULL;
     s->hci->evt_recv = NULL;
     s->hci->acl_recv = NULL;
-    qemu_free(s);
 }
 
 static int usb_bt_initfn(USBDevice *dev)
index 2cac1e8..d0b59dd 100644 (file)
@@ -50,10 +50,22 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
     return rc;
 }
 
+static int usb_qdev_exit(DeviceState *qdev)
+{
+    USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+
+    usb_device_detach(dev);
+    if (dev->info->handle_destroy) {
+        dev->info->handle_destroy(dev);
+    }
+    return 0;
+}
+
 void usb_qdev_register(USBDeviceInfo *info)
 {
     info->qdev.bus_info = &usb_bus_info;
     info->qdev.init     = usb_qdev_init;
+    info->qdev.exit     = usb_qdev_exit;
     qdev_register(&info->qdev);
 }
 
@@ -101,6 +113,14 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
     bus->nfree++;
 }
 
+void usb_unregister_port(USBBus *bus, USBPort *port)
+{
+    if (port->dev)
+        qdev_free(&port->dev->qdev);
+    QTAILQ_REMOVE(&bus->free, port, next);
+    bus->nfree--;
+}
+
 static void do_attach(USBDevice *dev)
 {
     USBBus *bus = usb_bus_from_device(dev);
@@ -136,6 +156,34 @@ int usb_device_attach(USBDevice *dev)
     return 0;
 }
 
+int usb_device_detach(USBDevice *dev)
+{
+    USBBus *bus = usb_bus_from_device(dev);
+    USBPort *port;
+
+    if (!dev->attached) {
+        fprintf(stderr, "Warning: tried to detach unattached usb device %s\n",
+                dev->devname);
+        return -1;
+    }
+    dev->attached--;
+
+    QTAILQ_FOREACH(port, &bus->used, next) {
+        if (port->dev == dev)
+            break;
+    }
+    assert(port != NULL);
+
+    QTAILQ_REMOVE(&bus->used, port, next);
+    bus->nused--;
+
+    usb_attach(port, NULL);
+
+    QTAILQ_INSERT_TAIL(&bus->free, port, next);
+    bus->nfree++;
+    return 0;
+}
+
 int usb_device_delete_addr(int busnr, int addr)
 {
     USBBus *bus;
@@ -152,16 +200,9 @@ int usb_device_delete_addr(int busnr, int addr)
     }
     if (!port)
         return -1;
-
     dev = port->dev;
-    QTAILQ_REMOVE(&bus->used, port, next);
-    bus->nused--;
-
-    usb_attach(port, NULL);
-    dev->info->handle_destroy(dev);
 
-    QTAILQ_INSERT_TAIL(&bus->free, port, next);
-    bus->nfree++;
+    qdev_free(&dev->qdev);
     return 0;
 }
 
index 3bf06fa..d1cc45e 100644 (file)
@@ -843,7 +843,6 @@ static void usb_hid_handle_destroy(USBDevice *dev)
     if (s->kind != USB_KEYBOARD)
         qemu_remove_mouse_event_handler(s->ptr.eh_entry);
     /* TODO: else */
-    qemu_free(s);
 }
 
 static int usb_hid_initfn(USBDevice *dev, int kind)
index 0a39986..e5a0938 100644 (file)
@@ -517,8 +517,12 @@ static int usb_hub_handle_packet(USBDevice *dev, USBPacket *p)
 static void usb_hub_handle_destroy(USBDevice *dev)
 {
     USBHubState *s = (USBHubState *)dev;
+    int i;
 
-    qemu_free(s);
+    for (i = 0; i < s->nb_ports; i++) {
+        usb_unregister_port(usb_bus_from_device(dev),
+                            &s->ports[i].port);
+    }
 }
 
 static int usb_hub_initfn(USBDevice *dev)
index 6b9c8a5..843a22f 100644 (file)
@@ -512,9 +512,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
 {
     MSDState *s = (MSDState *)dev;
 
-    s->scsi_dev->info->destroy(s->scsi_dev);
     drive_uninit(s->dinfo->bdrv);
-    qemu_free(s);
 }
 
 static int usb_msd_initfn(USBDevice *dev)
index 091ab2c..e2379c4 100644 (file)
@@ -486,7 +486,6 @@ static void usb_serial_handle_destroy(USBDevice *dev)
     USBSerialState *s = (USBSerialState *)dev;
 
     qemu_chr_close(s->cs);
-    qemu_free(s);
 }
 
 static int usb_serial_can_read(void *opaque)
index 55f06bf..3ea7241 100644 (file)
@@ -389,7 +389,6 @@ static void usb_wacom_handle_destroy(USBDevice *dev)
     USBWacomState *s = (USBWacomState *) dev;
 
     qemu_remove_mouse_event_handler(s->eh_entry);
-    qemu_free(s);
 }
 
 static int usb_wacom_initfn(USBDevice *dev)
index 467cddb..be4fcf6 100644 (file)
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -311,7 +311,9 @@ 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);
+void usb_unregister_port(USBBus *bus, USBPort *port);
 int usb_device_attach(USBDevice *dev);
+int usb_device_detach(USBDevice *dev);
 int usb_device_delete_addr(int busnr, int addr);
 
 static inline USBBus *usb_bus_from_device(USBDevice *d)