diff mbox

usb: selective endpoint initialization

Message ID 1341245761-30942-1-git-send-email-kraxel@redhat.com
State New
Headers show

Commit Message

Gerd Hoffmann July 2, 2012, 4:16 p.m. UTC
Add support for (re-)initializing endpoints which belong to a specific
interface only.  Use this in usb-host when changing altsetting for an
interface, so other interfaces are not disturbed.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb.h            |    2 +-
 hw/usb/bus.c        |    2 +-
 hw/usb/core.c       |   48 +++++++++++++++++++++++++++---------------------
 hw/usb/desc.c       |    2 +-
 hw/usb/host-linux.c |   16 ++++++++--------
 hw/usb/redirect.c   |    2 +-
 6 files changed, 39 insertions(+), 33 deletions(-)

Comments

Jan Kiszka July 3, 2012, 7:47 a.m. UTC | #1
On 2012-07-02 18:16, Gerd Hoffmann wrote:
> Add support for (re-)initializing endpoints which belong to a specific
> interface only.  Use this in usb-host when changing altsetting for an
> interface, so other interfaces are not disturbed.
> 

qemu-system-x86_64: /data/qemu/hw/usb/host-linux.c:1220:
usb_linux_update_endp_table: Assertion `usb_ep_get_type(&s->dev, pid,
ep) == 255' failed.

Do you need a trace again?

Thanks,
Jan

PS: The device used here is this one:

Bus 001 Device 060: ID 047f:c247 Plantronics, Inc.
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x047f Plantronics, Inc.
  idProduct          0xc247
  bcdDevice            0.27
  iManufacturer           1 Plantronics
  iProduct                2 HW121N-USB
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength          286
    bNumInterfaces          4
    bConfigurationValue     1
    iConfiguration          3 v18M6
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol      0
      iInterface              0
      AudioControl Interface Descriptor:
        bLength                10
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength          115
        bInCollection           2
        baInterfaceNr( 0)       1
        baInterfaceNr( 1)       2
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID            13
        wTerminalType      0x0201 Microphone
        bAssocTerminal          0
        bNrChannels             1
        wChannelConfig     0x0000
        iChannelNames           0
        iTerminal               0
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 6
        bSourceID              13
        bControlSize            1
        bmaControls( 0)      0x03
          Mute Control
          Volume Control
        bmaControls( 1)      0x00
        iFeature                0
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID            12
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bNrChannels             2
        wChannelConfig     0x0003
          Left Front (L)
          Right Front (R)
        iChannelNames           0
        iTerminal               0
      AudioControl Interface Descriptor:
        bLength                13
        bDescriptorType        36
        bDescriptorSubtype      4 (MIXER_UNIT)
        bUnitID                 9
        bNrInPins               2
        baSourceID( 0)         12
        baSourceID( 1)          6
        bNrChannels             2
        wChannelConfig     0x0003
          Left Front (L)
          Right Front (R)
        iChannelNames           0
        bmControls         0x00
        iMixer                  0
      AudioControl Interface Descriptor:
        bLength                13
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 1
        bSourceID               9
        bControlSize            2
        bmaControls( 0)      0x15
        bmaControls( 0)      0x00
          Mute Control
          Bass Control
          Treble Control
        bmaControls( 1)      0x02
        bmaControls( 1)      0x00
          Volume Control
        bmaControls( 2)      0x02
        bmaControls( 2)      0x00
          Volume Control
        iFeature                0
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID            14
        wTerminalType      0x0301 Speaker
        bAssocTerminal         11
        bSourceID               1
        iTerminal               0
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID            11
        wTerminalType      0x0201 Microphone
        bAssocTerminal         14
        bNrChannels             1
        wChannelConfig     0x0000
        iChannelNames           0
        iTerminal               0
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 2
        bSourceID              11
        bControlSize            1
        bmaControls( 0)      0x03
          Mute Control
          Volume Control
        bmaControls( 1)      0x00
        iFeature                0
      AudioControl Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      5 (SELECTOR_UNIT)
        bUnitID                 8
        bNrInPins               1
        baSource( 0)            2
        iSelector               0
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID            10
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bSourceID               8
        iTerminal               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0
      iInterface              0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       1
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0
      iInterface              0
      AudioStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink          12
        bDelay                  0 frames
        wFormatTag              1 PCM
      AudioStreaming Interface Descriptor:
        bLength                23
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             2
        bSubframeSize           2
        bBitResolution         16
        bSamFreqType            5 Discrete
        tSamFreq[ 0]         8000
        tSamFreq[ 1]        16000
        tSamFreq[ 2]        32000
        tSamFreq[ 3]        44100
        tSamFreq[ 4]        48000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes           13
          Transfer Type            Isochronous
          Synch Type               Synchronous
          Usage Type               Data
        wMaxPacketSize     0x00c0  1x 192 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        AudioControl Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x01
            Sampling Frequency
          bLockDelayUnits         2 Decoded PCM samples
          wLockDelay              1 Decoded PCM samples
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0
      iInterface              0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       1
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0
      iInterface              0
      AudioStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink          10
        bDelay                  0 frames
        wFormatTag              1 PCM
      AudioStreaming Interface Descriptor:
        bLength                23
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             1
        bSubframeSize           2
        bBitResolution         16
        bSamFreqType            5 Discrete
        tSamFreq[ 0]         8000
        tSamFreq[ 1]        16000
        tSamFreq[ 2]        32000
        tSamFreq[ 3]        44100
        tSamFreq[ 4]        48000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x84  EP 4 IN
        bmAttributes           13
          Transfer Type            Isochronous
          Synch Type               Synchronous
          Usage Type               Data
        wMaxPacketSize     0x0060  1x 96 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        AudioControl Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x01
            Sampling Frequency
          bLockDelayUnits         2 Decoded PCM samples
          wLockDelay              1 Decoded PCM samples
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.00
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     115
          Report Descriptor: (length is 115)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Global): Usage Page, data= [ 0x0c ] 12
                            Consumer
            Item(Local ): Usage, data= [ 0x01 ] 1
                            Consumer Control
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Global): Report ID, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x06 ] 6
            Item(Main  ): Input, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0xea ] 234
                            Volume Decrement
            Item(Local ): Usage, data= [ 0xe9 ] 233
                            Volume Increment
            Item(Global): Report Count, data= [ 0x02 ] 2
            Item(Main  ): Input, data= [ 0x06 ] 6
                            Data Variable Relative No_Wrap Linear
                            Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x08 ] 8
            Item(Main  ): Input, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Global): Usage Page, data= [ 0xa0 0xff ] 65440
                            (null)
            Item(Global): Report ID, data= [ 0x10 ] 16
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Local ): Usage, data= [ 0x98 ] 152
                            (null)
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Main  ): Output, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x07 ] 7
            Item(Main  ): Output, data= [ 0x01 ] 1
                            Constant Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Global): Usage Page, data= [ 0x0b ] 11
                            Telephony
            Item(Local ): Usage, data= [ 0x05 ] 5
                            Headset
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Global): Report ID, data= [ 0x02 ] 2
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x03 ] 3
            Item(Main  ): Input, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x2f ] 47
                            Phone Mute
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x21 ] 33
                            Flash
            Item(Main  ): Input, data= [ 0x06 ] 6
                            Data Variable Relative No_Wrap Linear
                            Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x20 ] 32
                            Hook Switch
            Item(Main  ): Input, data= [ 0x22 ] 34
                            Data Variable Absolute No_Wrap Linear
                            No_Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x0a ] 10
            Item(Main  ): Input, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Global): Usage Page, data= [ 0x08 ] 8
                            LEDs
            Item(Global): Report ID, data= [ 0x18 ] 24
            Item(Local ): Usage, data= [ 0x18 ] 24
                            Ring
            Item(Global): Report Count, data= [ 0x08 ] 8
            Item(Main  ): Output, data= [ 0x22 ] 34
                            Data Variable Absolute No_Wrap Linear
                            No_Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Global): Report ID, data= [ 0x17 ] 23
            Item(Local ): Usage, data= [ 0x17 ] 23
                            Off-Hook
            Item(Main  ): Output, data= [ 0x22 ] 34
                            Data Variable Absolute No_Wrap Linear
                            No_Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Global): Report ID, data= [ 0x1e ] 30
            Item(Local ): Usage, data= [ 0x1e ] 30
                            Speaker
            Item(Main  ): Output, data= [ 0x22 ] 34
                            Data Variable Absolute No_Wrap Linear
                            No_Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Global): Report ID, data= [ 0x09 ] 9
            Item(Local ): Usage, data= [ 0x09 ] 9
                            Mute
            Item(Main  ): Output, data= [ 0x22 ] 34
                            Data Variable Absolute No_Wrap Linear
                            No_Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Global): Report ID, data= [ 0x2a ] 42
            Item(Local ): Usage, data= [ 0x2a ] 42
                            On-Line
            Item(Main  ): Output, data= [ 0x22 ] 34
                            Data Variable Absolute No_Wrap Linear
                            No_Preferred_State No_Null_Position
Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0003  1x 3 bytes
        bInterval               2
Device Status:     0x0000
  (Bus Powered)
Erik Rull July 4, 2012, 8:09 a.m. UTC | #2
Gerd Hoffmann wrote:
> Add support for (re-)initializing endpoints which belong to a specific
> interface only.  Use this in usb-host when changing altsetting for an
> interface, so other interfaces are not disturbed.
>

Hi Gerd,

I tested it on my AMD test system where the issue didn't appear with the 
same USB hardware (also before this patch!) - so the final test on my Intel 
test system is pending until next week where it happened.

Best regards,

Erik
Erik Rull July 10, 2012, 6:57 p.m. UTC | #3
Erik Rull wrote:
> Gerd Hoffmann wrote:
>> Add support for (re-)initializing endpoints which belong to a specific
>> interface only.  Use this in usb-host when changing altsetting for an
>> interface, so other interfaces are not disturbed.
>>
>
> Hi Gerd,
>
> I tested it on my AMD test system where the issue didn't appear with the
> same USB hardware (also before this patch!) - so the final test on my Intel
> test system is pending until next week where it happened.
>
> Best regards,
>
> Erik
>
>

Hi Gerd,

sorry for the delays, I tested the latest pulled patch queue and it's now 
fine on my Intel board, too. The dongle gets detected again without 
assertions. Thanks for your work.

Still remaining are the multiple usb resets on host side before the dongle 
gets finally detected / usable on the guest.

Best regards,

Erik
diff mbox

Patch

diff --git a/hw/usb.h b/hw/usb.h
index a5623d3..b6d7052 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -362,7 +362,7 @@  int usb_handle_packet(USBDevice *dev, USBPacket *p);
 void usb_packet_complete(USBDevice *dev, USBPacket *p);
 void usb_cancel_packet(USBPacket * p);
 
-void usb_ep_init(USBDevice *dev);
+void usb_ep_init(USBDevice *dev, int interface);
 void usb_ep_dump(USBDevice *dev);
 struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep);
 uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep);
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index b649360..ad1daaf 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -190,7 +190,7 @@  static int usb_qdev_init(DeviceState *qdev)
             usb_device_get_product_desc(dev));
     dev->auto_attach = 1;
     QLIST_INIT(&dev->strings);
-    usb_ep_init(dev);
+    usb_ep_init(dev, 0);
     rc = usb_claim_port(dev);
     if (rc != 0) {
         return rc;
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 0e02da7..94c3c1a 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -550,31 +550,37 @@  void usb_packet_cleanup(USBPacket *p)
     qemu_iovec_destroy(&p->iov);
 }
 
-void usb_ep_init(USBDevice *dev)
+void usb_ep_init(USBDevice *dev, int interface)
 {
     int ep;
 
-    dev->ep_ctl.nr = 0;
-    dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
-    dev->ep_ctl.ifnum = 0;
-    dev->ep_ctl.dev = dev;
-    dev->ep_ctl.pipeline = false;
-    QTAILQ_INIT(&dev->ep_ctl.queue);
+    if (interface == 0) {
+        dev->ep_ctl.nr = 0;
+        dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
+        dev->ep_ctl.ifnum = 0;
+        dev->ep_ctl.dev = dev;
+        dev->ep_ctl.pipeline = false;
+        QTAILQ_INIT(&dev->ep_ctl.queue);
+    }
     for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
-        dev->ep_in[ep].nr = ep + 1;
-        dev->ep_out[ep].nr = ep + 1;
-        dev->ep_in[ep].pid = USB_TOKEN_IN;
-        dev->ep_out[ep].pid = USB_TOKEN_OUT;
-        dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID;
-        dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID;
-        dev->ep_in[ep].ifnum = 0;
-        dev->ep_out[ep].ifnum = 0;
-        dev->ep_in[ep].dev = dev;
-        dev->ep_out[ep].dev = dev;
-        dev->ep_in[ep].pipeline = false;
-        dev->ep_out[ep].pipeline = false;
-        QTAILQ_INIT(&dev->ep_in[ep].queue);
-        QTAILQ_INIT(&dev->ep_out[ep].queue);
+        if (interface == 0 || interface == dev->ep_in[ep].ifnum) {
+            dev->ep_in[ep].nr = ep + 1;
+            dev->ep_in[ep].pid = USB_TOKEN_IN;
+            dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID;
+            dev->ep_in[ep].ifnum = 0;
+            dev->ep_in[ep].dev = dev;
+            dev->ep_in[ep].pipeline = false;
+            QTAILQ_INIT(&dev->ep_in[ep].queue);
+        }
+        if (interface == 0 || interface == dev->ep_out[ep].ifnum) {
+            dev->ep_out[ep].nr = ep + 1;
+            dev->ep_out[ep].pid = USB_TOKEN_OUT;
+            dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID;
+            dev->ep_out[ep].ifnum = 0;
+            dev->ep_out[ep].dev = dev;
+            dev->ep_out[ep].pipeline = false;
+            QTAILQ_INIT(&dev->ep_out[ep].queue);
+        }
     }
 }
 
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
index 0a9d3c9..f010755 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -246,7 +246,7 @@  static void usb_desc_ep_init(USBDevice *dev)
     const USBDescIface *iface;
     int i, e, pid, ep;
 
-    usb_ep_init(dev);
+    usb_ep_init(dev, 0);
     for (i = 0; i < dev->ninterfaces; i++) {
         iface = dev->ifaces[i];
         if (iface == NULL) {
diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index 5479fb5..8e5d1be 100644
--- a/hw/usb/host-linux.c
+++ b/hw/usb/host-linux.c
@@ -135,7 +135,7 @@  static int parse_filter(const char *spec, struct USBAutoFilter *f);
 static void usb_host_auto_check(void *unused);
 static int usb_host_read_file(char *line, size_t line_size,
                             const char *device_file, const char *device_name);
-static int usb_linux_update_endp_table(USBHostDevice *s);
+static int usb_linux_update_endp_table(USBHostDevice *s, int ifnum);
 
 static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p)
 {
@@ -648,7 +648,7 @@  static void usb_host_handle_reset(USBDevice *dev)
     usb_host_do_reset(s);;
 
     usb_host_claim_interfaces(s, 0);
-    usb_linux_update_endp_table(s);
+    usb_linux_update_endp_table(s, 0);
 }
 
 static void usb_host_handle_destroy(USBDevice *dev)
@@ -988,7 +988,7 @@  again:
         return ctrl_error();
     }
     usb_host_claim_interfaces(s, config);
-    usb_linux_update_endp_table(s);
+    usb_linux_update_endp_table(s, 0);
     return 0;
 }
 
@@ -1024,7 +1024,7 @@  static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
     }
 
     s->dev.altsetting[iface] = alt;
-    usb_linux_update_endp_table(s);
+    usb_linux_update_endp_table(s, iface);
     return 0;
 }
 
@@ -1120,7 +1120,7 @@  static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
 }
 
 /* returns 1 on problem encountered or 0 for success */
-static int usb_linux_update_endp_table(USBHostDevice *s)
+static int usb_linux_update_endp_table(USBHostDevice *s, int ifnum)
 {
     static const char *tname[] = {
         [USB_ENDPOINT_XFER_CONTROL] = "control",
@@ -1136,7 +1136,7 @@  static int usb_linux_update_endp_table(USBHostDevice *s)
     USBDescriptor *d;
     bool active = false;
 
-    usb_ep_init(&s->dev);
+    usb_ep_init(&s->dev, ifnum);
 
     for (i = 0;; i += d->bLength) {
         if (i+2 >= s->descr_len) {
@@ -1239,7 +1239,7 @@  static int usb_linux_update_endp_table(USBHostDevice *s)
     return 0;
 
 error:
-    usb_ep_init(&s->dev);
+    usb_ep_init(&s->dev, 0);
     return 1;
 }
 
@@ -1326,7 +1326,7 @@  static int usb_host_open(USBHostDevice *dev, int bus_num,
         goto fail;
     }
 
-    ret = usb_linux_update_endp_table(dev);
+    ret = usb_linux_update_endp_table(dev, 0);
     if (ret) {
         goto fail;
     }
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index d949f04..4afa9c2 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1136,7 +1136,7 @@  static void usbredir_device_disconnect(void *priv)
     for (i = 0; i < MAX_ENDPOINTS; i++) {
         QTAILQ_INIT(&dev->endpoint[i].bufpq);
     }
-    usb_ep_init(&dev->dev);
+    usb_ep_init(&dev->dev, 0);
     dev->interface_info.interface_count = NO_INTERFACE_INFO;
     dev->dev.addr = 0;
     dev->dev.speed = 0;