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 + #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; diff --git a/hw/usb/desc.h b/hw/usb/desc.h index d164e8f891..7cf5442945 100644 --- a/hw/usb/desc.h +++ b/hw/usb/desc.h @@ -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); diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 426b95c82b..79b75fb628 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -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); diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c index 195370c24a..6b74eff4ad 100644 --- a/hw/usb/dev-bluetooth.c +++ b/hw/usb/dev-bluetooth.c @@ -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; } diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 9c9166551e..b5962da72a 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -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++) { diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index cff55f223e..b238a0973d 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -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; diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 8dcac8bc88..56743ee020 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -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) { diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 8e66675d86..3b7604e8b1 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -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); diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 3d2f244127..ae22fb1c97 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -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); diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c index c1cfd74403..3b51d458f4 100644 --- a/hw/usb/dev-wacom.c +++ b/hw/usb/dev-wacom.c @@ -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;