diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2013-11-20 07:32:31 +0100 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2014-01-16 12:59:59 +0100 |
commit | 5319dc7b42610575cbd3a33f4340c1fb4f19b939 (patch) | |
tree | 5f43fc075e28b242bee3696cfa245c468feb26f1 /hw/usb/desc.c | |
parent | 1cf892ca2689c84960b4ce4d2723b6bee453711c (diff) |
usb: add support for microsoft os descriptors
This patch adds support for special usb descriptors used by microsoft
windows. They allow more fine-grained control over driver binding and
adding entries to the registry for configuration.
As this is a guest-visible change the "msos-desc" compat property
has been added to turn this off for 1.7 + older
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'hw/usb/desc.c')
-rw-r--r-- | hw/usb/desc.c | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/hw/usb/desc.c b/hw/usb/desc.c index f18a043500..f133ddb9db 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -7,7 +7,7 @@ /* ------------------------------------------------------------------ */ int usb_desc_device(const USBDescID *id, const USBDescDevice *dev, - uint8_t *dest, size_t len) + bool msos, uint8_t *dest, size_t len) { uint8_t bLength = 0x12; USBDescriptor *d = (void *)dest; @@ -19,8 +19,18 @@ int usb_desc_device(const USBDescID *id, const USBDescDevice *dev, d->bLength = bLength; d->bDescriptorType = USB_DT_DEVICE; - d->u.device.bcdUSB_lo = usb_lo(dev->bcdUSB); - d->u.device.bcdUSB_hi = usb_hi(dev->bcdUSB); + if (msos && dev->bcdUSB < 0x0200) { + /* + * Version 2.0+ required for microsoft os descriptors to work. + * Done this way so msos-desc compat property will handle both + * the version and the new descriptors being present. + */ + d->u.device.bcdUSB_lo = usb_lo(0x0200); + d->u.device.bcdUSB_hi = usb_hi(0x0200); + } else { + d->u.device.bcdUSB_lo = usb_lo(dev->bcdUSB); + d->u.device.bcdUSB_hi = usb_hi(dev->bcdUSB); + } d->u.device.bDeviceClass = dev->bDeviceClass; d->u.device.bDeviceSubClass = dev->bDeviceSubClass; d->u.device.bDeviceProtocol = dev->bDeviceProtocol; @@ -499,6 +509,10 @@ void usb_desc_init(USBDevice *dev) if (desc->super) { dev->speedmask |= USB_SPEED_MASK_SUPER; } + if (desc->msos && (dev->flags & (1 << USB_DEV_FLAG_MSOS_DESC_ENABLE))) { + dev->flags |= (1 << USB_DEV_FLAG_MSOS_DESC_IN_USE); + usb_desc_set_string(dev, 0xee, "MSFT100Q"); + } usb_desc_setdefaults(dev); } @@ -626,6 +640,7 @@ int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len) int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p, int value, uint8_t *dest, size_t len) { + bool msos = (dev->flags & (1 << USB_DEV_FLAG_MSOS_DESC_IN_USE)); const USBDesc *desc = usb_device_get_usb_desc(dev); const USBDescDevice *other_dev; uint8_t buf[256]; @@ -646,7 +661,7 @@ int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p, switch(type) { case USB_DT_DEVICE: - ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf)); + ret = usb_desc_device(&desc->id, dev->device, msos, buf, sizeof(buf)); trace_usb_desc_device(dev->addr, len, ret); break; case USB_DT_CONFIG: @@ -703,6 +718,7 @@ int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p, int usb_desc_handle_control(USBDevice *dev, USBPacket *p, int request, int value, int index, int length, uint8_t *data) { + bool msos = (dev->flags & (1 << USB_DEV_FLAG_MSOS_DESC_IN_USE)); const USBDesc *desc = usb_device_get_usb_desc(dev); int ret = -1; @@ -782,6 +798,19 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, trace_usb_set_interface(dev->addr, index, value, ret); break; + case VendorDeviceRequest | 'Q': + if (msos) { + ret = usb_desc_msos(desc, p, index, data, length); + trace_usb_desc_msos(dev->addr, index, length, ret); + } + break; + case VendorInterfaceRequest | 'Q': + if (msos) { + ret = usb_desc_msos(desc, p, index, data, length); + trace_usb_desc_msos(dev->addr, index, length, ret); + } + break; + } return ret; } |