diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2013-05-06 13:12:16 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2013-05-07 11:34:02 +0200 |
commit | c3268cc1135f41264cd26bcb269b3414d3c11453 (patch) | |
tree | a1b19fe74bcacccb4aecab0cf3f6a491c7a076e0 /hw/usb | |
parent | 95efb20c714800de7eaf991f19dab6e7a29d5364 (diff) | |
download | qemu-c3268cc1135f41264cd26bcb269b3414d3c11453.tar.gz qemu-c3268cc1135f41264cd26bcb269b3414d3c11453.tar.bz2 qemu-c3268cc1135f41264cd26bcb269b3414d3c11453.zip |
usb-host: add usb_host_full_speed_compat
Alloes to pass through usb2 devices on usb1 host controllers if possible.
Brings the libusb implementation to feature-parity with the linux usbfs
code, so the usb-host implementation in 1.5 (libusb) doesn't regress
compared to 1.4 (usbfs).
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'hw/usb')
-rw-r--r-- | hw/usb/host-libusb.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index ee67c4c23e..f3de4591fd 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -667,6 +667,42 @@ static void usb_host_iso_data_out(USBHostDevice *s, USBPacket *p) /* ------------------------------------------------------------------------ */ +static bool usb_host_full_speed_compat(USBHostDevice *s) +{ + struct libusb_config_descriptor *conf; + const struct libusb_interface_descriptor *intf; + const struct libusb_endpoint_descriptor *endp; + uint8_t type; + int rc, c, i, a, e; + + for (c = 0;; c++) { + rc = libusb_get_config_descriptor(s->dev, c, &conf); + if (rc != 0) { + break; + } + for (i = 0; i < conf->bNumInterfaces; i++) { + for (a = 0; a < conf->interface[i].num_altsetting; a++) { + intf = &conf->interface[i].altsetting[a]; + for (e = 0; e < intf->bNumEndpoints; e++) { + endp = &intf->endpoint[e]; + type = endp->bmAttributes & 0x3; + switch (type) { + case 0x01: /* ISO */ + return false; + case 0x03: /* INTERRUPT */ + if (endp->wMaxPacketSize > 64) { + return false; + } + break; + } + } + } + } + libusb_free_config_descriptor(conf); + } + return true; +} + static void usb_host_ep_update(USBHostDevice *s) { static const char *tname[] = { @@ -758,11 +794,9 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev) udev->speed = speed_map[libusb_get_device_speed(dev)]; udev->speedmask = (1 << udev->speed); -#if 0 - if (udev->speed == USB_SPEED_HIGH && usb_linux_full_speed_compat(dev)) { + if (udev->speed == USB_SPEED_HIGH && usb_host_full_speed_compat(s)) { udev->speedmask |= USB_SPEED_MASK_FULL; } -#endif if (s->ddesc.iProduct) { libusb_get_string_descriptor_ascii(s->dh, s->ddesc.iProduct, |