diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index 7dde3d1206..354713a77d 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -836,7 +836,7 @@ static void usb_host_ep_update(USBHostDevice *s) struct libusb_ss_endpoint_companion_descriptor *endp_ss_comp; #endif uint8_t devep, type; - int pid, ep; + int pid, ep, alt; int rc, i, e; usb_ep_reset(udev); @@ -848,8 +848,20 @@ static void usb_host_ep_update(USBHostDevice *s) conf->bConfigurationValue, true); for (i = 0; i < conf->bNumInterfaces; i++) { - assert(udev->altsetting[i] < conf->interface[i].num_altsetting); - intf = &conf->interface[i].altsetting[udev->altsetting[i]]; + /* + * The udev->altsetting array indexes alternate settings + * by the interface number. Get the 0th alternate setting + * first so that we can grab the interface number, and + * then correct the alternate setting value if necessary. + */ + intf = &conf->interface[i].altsetting[0]; + alt = udev->altsetting[intf->bInterfaceNumber]; + + if (alt != 0) { + assert(alt < conf->interface[i].num_altsetting); + intf = &conf->interface[i].altsetting[alt]; + } + trace_usb_host_parse_interface(s->bus_num, s->addr, intf->bInterfaceNumber, intf->bAlternateSetting, true);