diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2012-04-20 12:33:30 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2012-04-26 12:21:17 +0200 |
commit | 9d55d1adc848a3dc1d2431c4ec4e7e4ea37fa0ee (patch) | |
tree | 4552a8c6548d345bfca57364072329f073af3fc4 /hw/usb/desc.c | |
parent | b15cf49b78edb74dc783a7cacbc8391cbc728edc (diff) |
usb: add serial number generator
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>
Diffstat (limited to 'hw/usb/desc.c')
-rw-r--r-- | hw/usb/desc.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/hw/usb/desc.c b/hw/usb/desc.c index 3c77368cb0..e8a3c6af3d 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -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; |