]> git.proxmox.com Git - mirror_qemu.git/commitdiff
usb: add serial number generator
authorGerd Hoffmann <kraxel@redhat.com>
Fri, 20 Apr 2012 10:33:30 +0000 (12:33 +0200)
committerGerd Hoffmann <kraxel@redhat.com>
Thu, 26 Apr 2012 10:21:17 +0000 (12:21 +0200)
This patch adds a function which creates unique serial numbers for usb
devices and puts it into use.  Windows guests tend to become unhappy if
they find two identical usb devices in the system.  Effects range from
non-functional devices (with yellow exclamation mark in device manager)
to BSODs.  Handing out unique serial numbers to devices fixes this.

With this patch applied almost all emulated devices get a generated,
unique serial number.  There are two exceptions:

 * usb-storage devices will prefer a user-specified serial number
   and will only get a generated number in case the serial property
   is unset.
 * usb-hid devices keep the fixed serial number "42" as it is used
   to signal "remote wakeup actually works".
   See commit 7b074a22dab4bdda9864b933f1bc811a3db42845

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
hw/usb/desc.c
hw/usb/desc.h
hw/usb/dev-audio.c
hw/usb/dev-bluetooth.c
hw/usb/dev-hub.c
hw/usb/dev-network.c
hw/usb/dev-serial.c
hw/usb/dev-smartcard-reader.c
hw/usb/dev-storage.c
hw/usb/dev-wacom.c

index 3c77368cb056df4fe316e347dcb68be68a607310..e8a3c6af3da68f0e95253fbd5fc8f37797c98f00 100644 (file)
@@ -1,3 +1,5 @@
+#include <ctype.h>
+
 #include "hw/usb.h"
 #include "hw/usb/desc.h"
 #include "trace.h"
@@ -412,6 +414,36 @@ void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
     s->str = g_strdup(str);
 }
 
+/*
+ * This function creates a serial number for a usb device.
+ * The serial number should:
+ *   (a) Be unique within the virtual machine.
+ *   (b) Be constant, so you don't get a new one each
+ *       time the guest is started.
+ * So we are using the physical location to generate a serial number
+ * from it.  It has three pieces:  First a fixed, device-specific
+ * prefix.  Second the device path of the host controller (which is
+ * the pci address in most cases).  Third the physical port path.
+ * Results in serial numbers like this: "314159-0000:00:1d.7-3".
+ */
+void usb_desc_create_serial(USBDevice *dev)
+{
+    DeviceState *hcd = dev->qdev.parent_bus->parent;
+    const USBDesc *desc = usb_device_get_usb_desc(dev);
+    int index = desc->id.iSerialNumber;
+    char serial[64];
+    int dst;
+
+    assert(index != 0 && desc->str[index] != NULL);
+    dst = snprintf(serial, sizeof(serial), "%s", desc->str[index]);
+    if (hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) {
+        char *path = hcd->parent_bus->info->get_dev_path(hcd);
+        dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", path);
+    }
+    dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", dev->port->path);
+    usb_desc_set_string(dev, index, serial);
+}
+
 const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
 {
     USBDescString *s;
index d164e8f891799356535f8d8fa2a2e280cedfcb63..7cf54429459bbe86f0aa57fbeb613ea07fc26af0 100644 (file)
@@ -171,6 +171,7 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
 void usb_desc_init(USBDevice *dev);
 void usb_desc_attach(USBDevice *dev);
 void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
+void usb_desc_create_serial(USBDevice *dev);
 const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
 int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
 int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len);
index 426b95c82b8438281c4f19b350a62841383fe875..79b75fb628c9c5aae83976bc589146faaa2d7a1f 100644 (file)
@@ -648,6 +648,7 @@ static int usb_audio_initfn(USBDevice *dev)
 {
     USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
 
+    usb_desc_create_serial(dev);
     usb_desc_init(dev);
     s->dev.opaque = s;
     AUD_register_card("usb-audio", &s->card);
index 195370c24a9029c2308720d25c417e9e38260b1d..6b74eff4ad1e5e78bf3b5dfc9b76ca591a5f98ae 100644 (file)
@@ -494,6 +494,7 @@ static void usb_bt_handle_destroy(USBDevice *dev)
 
 static int usb_bt_initfn(USBDevice *dev)
 {
+    usb_desc_create_serial(dev);
     usb_desc_init(dev);
     return 0;
 }
index 9c9166551e501eb3816370794e8f6a36615ba9d4..b5962da72adbe0e850a63385d27c799dc9162ec4 100644 (file)
@@ -520,6 +520,7 @@ static int usb_hub_initfn(USBDevice *dev)
     USBHubPort *port;
     int i;
 
+    usb_desc_create_serial(dev);
     usb_desc_init(dev);
     s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
     for (i = 0; i < NUM_PORTS; i++) {
index cff55f223e5584f26c921f771d4abf4eb951cece..b238a0973d6b34b0bb4cdbec38c724b1b5ab0984 100644 (file)
@@ -1324,6 +1324,7 @@ static int usb_net_initfn(USBDevice *dev)
 {
     USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
 
+    usb_desc_create_serial(dev);
     usb_desc_init(dev);
 
     s->rndis_state = RNDIS_UNINITIALIZED;
index 8dcac8bc88731682d6dda497a82738e98a99b3db..56743ee020ffa247536ba00603615aa636201ce8 100644 (file)
@@ -479,6 +479,7 @@ static int usb_serial_initfn(USBDevice *dev)
 {
     USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
 
+    usb_desc_create_serial(dev);
     usb_desc_init(dev);
 
     if (!s->cs) {
index 8e66675d86692827bfda41317c647171e0d7d762..3b7604e8b1391387ece8284ff27483fb0e0f56f8 100644 (file)
@@ -1189,6 +1189,7 @@ static int ccid_initfn(USBDevice *dev)
 {
     USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
 
+    usb_desc_create_serial(dev);
     usb_desc_init(dev);
     qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
     s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
index 3d2f2441271c73be8def8328a72b49069fafe7b5..ae22fb1c97bca41d05c00ebae7600aaaa01b1251 100644 (file)
@@ -546,6 +546,8 @@ static int usb_msd_initfn(USBDevice *dev)
     }
     if (s->serial) {
         usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial);
+    } else {
+        usb_desc_create_serial(dev);
     }
 
     usb_desc_init(dev);
index c1cfd7440356ec004b1f52e497137afdabc838b7..3b51d458f47d094f27decdb963153346582057a2 100644 (file)
@@ -339,6 +339,7 @@ static void usb_wacom_handle_destroy(USBDevice *dev)
 static int usb_wacom_initfn(USBDevice *dev)
 {
     USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
+    usb_desc_create_serial(dev);
     usb_desc_init(dev);
     s->changed = 1;
     return 0;