chegewara / EspTinyUSB

ESP32S2 native USB library. Implemented few common classes, like MIDI, CDC, HID or DFU (update).
MIT License
475 stars 70 forks source link

WebUSB on windows #46

Closed xtrinch closed 2 years ago

xtrinch commented 2 years ago

Hi,

I have a rather strange problem with my webusb + CDC setup. Below are the usb descriptors generated with this library.

The web usb part is working without issues on Linux (Ubuntu 20.04), I can connect to it, send it characters, receive characters, the whole thing. On windows however, I can see it in chrome and can connect to it, but cannot claim the webusb interface. (Note that I am testing with the same website on linux/windows). Below is the code I am using. I'd be inclined to think I'm doing something wrong in javascript, if the exact same code wasn't working fine on Linux. I even tested with the nightly build of chrome to see if it is some random chrome bug. The code just stalls at claimInterface and never returns. No errors, just never returns.

What could possibly be the cause of this?

Javascript code:

public async connect() {
    await this.device_.open();
    if (this.device_.configuration === null) {
      this.device_.selectConfiguration(1);
    }

    // find the interface which has 0xff interface class as its alternate and its interface number is 2
    this.interface = (this.device_.configuration.interfaces || []).find(
      (c) =>
        !!c.alternates.find((a) => a.interfaceClass === 0xff) &&
        c.interfaceNumber === 2
    );
    if (!this.interface) {
      throw new Error("Interface not found");
    }
    const alternate = this.interface.alternates[0];

    this.endpointIn = alternate.endpoints.find((e) => e.direction === "in");
    this.endpointOut = alternate.endpoints.find((e) => e.direction === "out");

    if (!this.endpointIn || !this.endpointOut) {
      throw new Error("Endpoints not found");
    }

    **------------> THIS IS THE LINE THAT NEVER RETURNS**
    await this.device_.claimInterface(this.interface.interfaceNumber);

    await this.device_.selectAlternateInterface(
      this.interface.interfaceNumber,
      0
    );

    await this.device_.controlTransferOut({
      requestType: "class",
      recipient: "interface",
      request: 0x22,
      value: 0x01,
      index: this.interface.interfaceNumber,
    });
  }

USB descriptors:

Bus 001 Device 010: ID 2341:0002 Arduino SA ESP32S2 arduino device
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.10
  bDeviceClass          239 Miscellaneous Device
  bDeviceSubClass         2 
  bDeviceProtocol         1 Interface Association
  bMaxPacketSize0        64
  idVendor           0x2341 Arduino SA
  idProduct          0x0002 
  bcdDevice            1.00
  iManufacturer           1 Espressif
  iProduct                2 ESP32S2 arduino device
  iSerial                 3 1234-5678
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0062
    bNumInterfaces          3
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              500mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass       2 Abstract (modem)
      bFunctionProtocol       0 
      iFunction               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      0 
      iInterface              4 CDC class
      CDC Header:
        bcdCDC               1.20
      CDC Call Management:
        bmCapabilities       0x00
        bDataInterface          1
      CDC ACM:
        bmCapabilities       0x02
          line coding and serial state
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              16
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              7 Vendor class (webUSB)
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
Binary Object Store Descriptor:
  bLength                 5
  bDescriptorType        15
  wTotalLength       0x0039
  bNumDeviceCaps          2
  Platform Device Capability:
    bLength                24
    bDescriptorType        16
    bDevCapabilityType      5
    bReserved               0
    PlatformCapabilityUUID    {3408b638-09a9-47a0-8bfd-a0768815b665}
      WebUSB:
        bcdVersion    1.00
        bVendorCode      1
        iLandingPage     1 http://iotfreezer.com
  Platform Device Capability:
    bLength                28
    bDescriptorType        16
    bDevCapabilityType      5
    bReserved               0
    PlatformCapabilityUUID    {d8dd60df-4589-4cc7-9cd2-659d9e648a9f}
    CapabilityData[0]    0x00
    CapabilityData[1]    0x00
    CapabilityData[2]    0x03
    CapabilityData[3]    0x06
    CapabilityData[4]    0xb2
    CapabilityData[5]    0x00
    CapabilityData[6]    0x02
    CapabilityData[7]    0x00
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0000
  (Bus Powered)
xtrinch commented 2 years ago

Okay, so I manually assigned the winusb driver to the vendor class interface (it was ofcourse not recognizing it on its own), then I downgraded the winusb driver: From: WINUSB (v10.0.19041.1) To: WinUSB (v6.1.7600.16385) With Zadig tool,

and now it magically works.

What could possibly go wrong with the latest driver?

chegewara commented 2 years ago

I dont know what can be wrong with that. WinUSB should work without need to use zadig or change any drivers. The only problem with winusb is that i had to use it together with CDC. Without CDC windows wont recognize it and adding CDC magically fixing it. There is one more thing that i am not sure, but ive heard that windows has issue with MSC + CDC when adding endpoints order is wrong (but that may be related to arduino-esp32 endpoints numbers).