diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2010-11-26 12:25:32 +0100 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2011-01-11 15:56:00 +0100 |
commit | 132a3f55f05dff4eedde0d23d844ecdedef8ba68 (patch) | |
tree | 8176c0595559cd176b778b3298b047969ae4421b | |
parent | 062651c7e750a0c06a693d336c2b9edb893a2c94 (diff) |
usb descriptors: add settable strings.
This patch allows to set usb descriptor strings per device instance.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r-- | hw/usb-bus.c | 1 | ||||
-rw-r--r-- | hw/usb-desc.c | 52 | ||||
-rw-r--r-- | hw/usb-desc.h | 4 | ||||
-rw-r--r-- | hw/usb.h | 9 |
4 files changed, 57 insertions, 9 deletions
diff --git a/hw/usb-bus.c b/hw/usb-bus.c index 8b4583c1e6..af537c238f 100644 --- a/hw/usb-bus.c +++ b/hw/usb-bus.c @@ -48,6 +48,7 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base) pstrcpy(dev->product_desc, sizeof(dev->product_desc), info->product_desc); dev->info = info; dev->auto_attach = 1; + QLIST_INIT(&dev->strings); rc = dev->info->init(dev); if (rc == 0 && dev->auto_attach) usb_device_attach(dev); diff --git a/hw/usb-desc.c b/hw/usb-desc.c index 559ced78b9..69ab207703 100644 --- a/hw/usb-desc.c +++ b/hw/usb-desc.c @@ -151,9 +151,42 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len) return bLength; } -int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len) +/* ------------------------------------------------------------------ */ + +void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str) +{ + USBDescString *s; + + QLIST_FOREACH(s, &dev->strings, next) { + if (s->index == index) { + break; + } + } + if (s == NULL) { + s = qemu_mallocz(sizeof(*s)); + s->index = index; + QLIST_INSERT_HEAD(&dev->strings, s, next); + } + qemu_free(s->str); + s->str = qemu_strdup(str); +} + +const char *usb_desc_get_string(USBDevice *dev, uint8_t index) +{ + USBDescString *s; + + QLIST_FOREACH(s, &dev->strings, next) { + if (s->index == index) { + return s->str; + } + } + return NULL; +} + +int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len) { uint8_t bLength, pos, i; + const char *str; if (len < 4) { return -1; @@ -168,22 +201,25 @@ int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len return 4; } - if (str[index] == NULL) { - return 0; + str = usb_desc_get_string(dev, index); + if (str == NULL) { + str = dev->info->usb_desc->str[index]; + if (str == NULL) { + return 0; + } } - bLength = strlen(str[index]) * 2 + 2; + + bLength = strlen(str) * 2 + 2; dest[0] = bLength; dest[1] = USB_DT_STRING; i = 0; pos = 2; while (pos+1 < bLength && pos+1 < len) { - dest[pos++] = str[index][i++]; + dest[pos++] = str[i++]; dest[pos++] = 0; } return pos; } -/* ------------------------------------------------------------------ */ - int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len) { const USBDesc *desc = dev->info->usb_desc; @@ -204,7 +240,7 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len trace_usb_desc_config(dev->addr, index, len, ret); break; case USB_DT_STRING: - ret = usb_desc_string(desc->str, index, buf, sizeof(buf)); + ret = usb_desc_string(dev, index, buf, sizeof(buf)); trace_usb_desc_string(dev->addr, index, len, ret); break; default: diff --git a/hw/usb-desc.h b/hw/usb-desc.h index d80efdb24f..20fc4006c0 100644 --- a/hw/usb-desc.h +++ b/hw/usb-desc.h @@ -76,9 +76,11 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len); int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len); int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len); int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len); -int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len); /* control message emulation helpers */ +void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str); +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); int usb_desc_handle_control(USBDevice *dev, int request, int value, int index, int length, uint8_t *data); @@ -135,6 +135,13 @@ typedef struct USBDescConfig USBDescConfig; typedef struct USBDescIface USBDescIface; typedef struct USBDescEndpoint USBDescEndpoint; typedef struct USBDescOther USBDescOther; +typedef struct USBDescString USBDescString; + +struct USBDescString { + uint8_t index; + char *str; + QLIST_ENTRY(USBDescString) next; +}; /* definition of a USB device */ struct USBDevice { @@ -155,6 +162,8 @@ struct USBDevice { int setup_state; int setup_len; int setup_index; + + QLIST_HEAD(, USBDescString) strings; }; struct USBDeviceInfo { |