]> git.proxmox.com Git - qemu.git/blobdiff - hw/usb-bus.c
usb: Add a usb_fill_port helper function
[qemu.git] / hw / usb-bus.c
index 874c253f765acaff57878a1d27b89f2b2b819229..776974e6cfea15b7f47f57b00d07dc55a8775dde 100644 (file)
@@ -75,7 +75,7 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
     QLIST_INIT(&dev->strings);
     rc = dev->info->init(dev);
     if (rc == 0 && dev->auto_attach)
-        usb_device_attach(dev);
+        rc = usb_device_attach(dev);
     return rc;
 }
 
@@ -84,7 +84,9 @@ static int usb_qdev_exit(DeviceState *qdev)
     USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
     USBBus *bus = usb_bus_from_device(dev);
 
-    usb_device_detach(dev);
+    if (dev->attached) {
+        usb_device_detach(dev);
+    }
     bus->ops->device_destroy(bus, dev);
     if (dev->info->handle_destroy) {
         dev->info->handle_destroy(dev);
@@ -119,7 +121,7 @@ USBDevice *usb_create(USBBus *bus, const char *name)
         bus = usb_bus_find(-1);
         if (!bus)
             return NULL;
-        fprintf(stderr, "%s: no bus specified, using \"%s\" for \"%s\"\n",
+        error_report("%s: no bus specified, using \"%s\" for \"%s\"\n",
                 __FUNCTION__, bus->qbus.name, name);
     }
 #endif
@@ -138,8 +140,8 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
     return dev;
 }
 
-void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-                       USBPortOps *ops, int speedmask)
+static void usb_fill_port(USBPort *port, void *opaque, int index,
+                          USBPortOps *ops, int speedmask)
 {
     port->opaque = opaque;
     port->index = index;
@@ -147,6 +149,12 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
     port->index = index;
     port->ops = ops;
     port->speedmask = speedmask;
+}
+
+void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
+                       USBPortOps *ops, int speedmask)
+{
+    usb_fill_port(port, opaque, index, ops, speedmask);
     QTAILQ_INSERT_TAIL(&bus->free, port, next);
     bus->nfree++;
 }
@@ -169,15 +177,20 @@ void usb_unregister_port(USBBus *bus, USBPort *port)
     bus->nfree--;
 }
 
-static void do_attach(USBDevice *dev)
+static int 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",
+        error_report("Error: tried to attach usb device %s twice\n",
                 dev->product_desc);
-        return;
+        return -1;
+    }
+    if (bus->nfree == 0) {
+        error_report("Error: tried to attach usb device %s to a bus with no free ports\n",
+                dev->product_desc);
+        return -1;
     }
     if (dev->port_path) {
         QTAILQ_FOREACH(port, &bus->free, next) {
@@ -186,13 +199,18 @@ static void do_attach(USBDevice *dev)
             }
         }
         if (port == NULL) {
-            fprintf(stderr, "Warning: usb port %s (bus %s) not found\n",
+            error_report("Error: usb port %s (bus %s) not found\n",
                     dev->port_path, bus->qbus.name);
-            return;
+            return -1;
         }
     } else {
         port = QTAILQ_FIRST(&bus->free);
     }
+    if (!(port->speedmask & dev->speedmask)) {
+        error_report("Warning: speed mismatch trying to attach usb device %s to bus %s\n",
+                dev->product_desc, bus->qbus.name);
+        return -1;
+    }
 
     dev->attached++;
     QTAILQ_REMOVE(&bus->free, port, next);
@@ -202,6 +220,8 @@ static void do_attach(USBDevice *dev)
 
     QTAILQ_INSERT_TAIL(&bus->used, port, next);
     bus->nused++;
+
+    return 0;
 }
 
 int usb_device_attach(USBDevice *dev)
@@ -213,8 +233,7 @@ int usb_device_attach(USBDevice *dev)
            (unless a physical port location is specified). */
         usb_create_simple(bus, "usb-hub");
     }
-    do_attach(dev);
-    return 0;
+    return do_attach(dev);
 }
 
 int usb_device_detach(USBDevice *dev)
@@ -223,7 +242,7 @@ int usb_device_detach(USBDevice *dev)
     USBPort *port;
 
     if (!dev->attached) {
-        fprintf(stderr, "Warning: tried to detach unattached usb device %s\n",
+        error_report("Error: tried to detach unattached usb device %s\n",
                 dev->product_desc);
         return -1;
     }
@@ -273,6 +292,7 @@ static const char *usb_speed(unsigned int speed)
         [ USB_SPEED_LOW  ] = "1.5",
         [ USB_SPEED_FULL ] = "12",
         [ USB_SPEED_HIGH ] = "480",
+        [ USB_SPEED_SUPER ] = "5000",
     };
     if (speed >= ARRAY_SIZE(txt))
         return "?";