espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.76k stars 7.3k forks source link

usb_host_lib example gets stuck trying to connect Novation LaunchPAD MK2 (IDFGH-10358) #11616

Closed mdroberts1243 closed 1 year ago

mdroberts1243 commented 1 year ago

Originally posted to esp32.com forum: https://esp32.com/viewtopic.php?f=13&t=34001

I'm using the example unmodified except for additional ESP_ LOGI statements.

I've successfully connected keyboards (Keychron K2) and other MIDI controller (Arturia KeyStep) but when I connect the Novation LaunchPAD MK2 it either hangs at "HUB: Stage done: GET_SHORT_DEV_DESC" or more typically with a "Bad transfer status 1" like below:

I (829) DAEMON: Installing USB Host Library V (829) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): checking args V (839) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): Args okay. Resulting flags 0x802 D (849) intr_alloc: Connected src 48 to int 12 (cpu 0) I (879) CLASS: Registering Client I (879) CLASS: In while loop I (879) CLASS: driver_obj.actions == 0 D (2479) HUB: Root port reset D (2479) HUB: Stage done: START D (2479) HUB: Stage done: GET_SHORT_DEV_DESC E (2479) HUB: Bad transfer status 1: CHECK_SHORT_DEV_DESC E (2479) HUB: Stage failed: CHECK_SHORT_DEV_DESC D (2489) HUB: Stage done: CLEANUP_FAILED

The LaunchPAD MK2 works fine on Windows and Linux machines. The output of the Linux lsusb is as follows:

$ sudo lsusb -D /dev/bus/usb/003/002 [sudo] password for mark: Device: ID 1235:0069 Focusrite-Novation Launchpad MK2 iInterface 3 Launchpad MK2 AudioControl Interface Descriptor: bLength 9 bDescriptorType 36 bDescriptorSubtype 1 (HEADER) bcdADC 1.00 wTotalLength 0x0009 bInCollection 1 baInterfaceNr(0) 1 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 1 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 1 Audio bInterfaceSubClass 3 MIDI Streaming bInterfaceProtocol 0 iInterface 3 Launchpad MK2 MIDIStreaming Interface Descriptor: bLength 7 bDescriptorType 36 bDescriptorSubtype 1 (HEADER) bcdADC 1.00 wTotalLength 0x002e MIDIStreaming Interface Descriptor: bLength 6 bDescriptorType 36 bDescriptorSubtype 2 (MIDI_IN_JACK) bJackType 1 Embedded bJackID 1 iJack 0 MIDIStreaming Interface Descriptor: bLength 9 bDescriptorType 36 bDescriptorSubtype 3 (MIDI_OUT_JACK) bJackType 1 Embedded bJackID 2 bNrInputPins 1 baSourceID( 0) 1 BaSourcePin( 0) 1 iJack 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 1 MIDIStreaming Endpoint Descriptor: bLength 5 bDescriptorType 37 bDescriptorSubtype 1 (GENERAL) bNumEmbMIDIJack 1 baAssocJackID( 0) 2 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 1 MIDIStreaming Endpoint Descriptor: bLength 5 bDescriptorType 37 bDescriptorSubtype 1 (GENERAL) bNumEmbMIDIJack 1 baAssocJackID( 0) 1 Device Status: 0x0000 (Bus Powered)

I'm willing to debug further with some guidance... I've already increased all the HUB timers, etc. and set debug level output.

Thanks, -mark.

roma-jam commented 1 year ago

Hi @mdroberts1243 , Thank you for the information.

Before everything, let me please clarify some moments.

  1. Which esp board/esp module do you use?
  2. How implemented a connection of the USB device to the ESP32 host? By wires/length of wires e.t.c
  3. What is the power characteristics of the contactable USB device? Is it powered by USB only or has an external power supply adapter also?
  4. You said that all the HUB times was already increased. May I ask to specify which one exactly and how much?

Thanks

mdroberts1243 commented 1 year ago

@roma-jam

roma-jam commented 1 year ago

Hi @mdroberts1243, Thanks for the extra information.

May I ask you more about the way how the USB device is powered.

What is the source of 5V VBus to the Type A side on the modified micro-USB adapter? Is it an external power supply or is it comes from the esp32s3 dev module? If it is comes from the module, may I ask what pin is used?

mdroberts1243 commented 1 year ago

Hi @roma-jam,

I have tried powering two ways. From the 5V pin of the DevKit and from an external USB supply. Both power the Launchpad (and other tested devices) fine. I prefer to use the 5V pin on the DevKit though for simplicity. As explained, the adapter was modified so I could inject the power to the A-type connector that feeds the USB MIDI devices.

roma-jam commented 1 year ago

@mdroberts1243, Thanks for the quick reply.

Let me ask then the question in a more strict way: is the problem with enumeration is still there when you powered the attachable USB device with an external 5V power supply with a possible max current not less than 500 mA?

mdroberts1243 commented 1 year ago

Yes, the problem exists when powered from either method.

Here's the setup: image

mdroberts1243 commented 1 year ago

With the Launchpad connected: image

roma-jam commented 1 year ago

@mdroberts1243,

Thanks for the quick response and for the photos.

I would recommend to be a little bit careful with a power supply:

  1. Try to use shorter USB wires. If the second wire (with a green logo) is also long, the voltage on the Launchpad can be drastically lower than 4.5 during the power up. That can be a cause of enumeration failure.
  2. If it is possible, try to use different power sources (use external USB power supply to get stable 5V on the Launchpad).

Meanwhile, I will verify few theories and return as soon as I can.

mdroberts1243 commented 1 year ago

@roma-jam Noted.

mdroberts1243 commented 1 year ago

I decided to insert a USB power measurement device before the launchpad to confirm voltages and currents (both o.k. and well within limits).

To my surprise the enumeration now works most of the time:

I (803) cpu_start: Starting scheduler on PRO CPU. D (809) heap_init: New heap initialised at 0x3fffc000 V (809) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): checking args V (819) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): Args okay. Resulting flags 0xE D (819) intr_alloc: Connected src 17 to int 9 (cpu 0) I (829) DAEMON: Installing USB Host Library V (829) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): checking args V (839) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): Args okay. Resulting flags 0x802 D (849) intr_alloc: Connected src 48 to int 12 (cpu 0) I (879) CLASS: Registering Client I (879) CLASS: driver_obj.actions == 0 D (9349) HUB: Root port reset D (9349) HUB: Stage done: START D (9349) HUB: Stage done: GET_SHORT_DEV_DESC D (9349) HUB: Stage done: CHECK_SHORT_DEV_DESC D (9409) HUB: Stage done: SECOND_RESET D (9409) HUB: Stage done: SET_ADDR D (9409) HUB: Stage done: CHECK_ADDR D (9419) HUB: Stage done: SET_ADDR_RECOVERY D (9419) HUB: Stage done: GET_FULL_DEV_DESC D (9419) HUB: Stage done: CHECK_FULL_DEV_DESC D (9419) HUB: Stage done: GET_SHORT_CONFIG_DESC D (9419) HUB: Stage done: CHECK_SHORT_CONFIG_DESC D (9429) HUB: Stage done: GET_FULL_CONFIG_DESC D (9429) HUB: Stage done: CHECK_FULL_CONFIG_DESC D (9439) HUB: Stage done: SET_CONFIG D (9439) HUB: Stage done: CHECK_CONFIG D (9439) HUB: Stage done: GET_SHORT_LANGID_TABLE D (9449) HUB: Stage done: CHECK_SHORT_LANGID_TABLE D (9449) HUB: Stage done: GET_FULL_LANGID_TABLE D (9459) HUB: Stage done: CHECK_FULL_LANGID_TABLE D (9459) HUB: Stage done: GET_SHORT_MANU_STR_DESC D (9469) HUB: Stage done: CHECK_SHORT_MANU_STR_DESC D (9469) HUB: Stage done: GET_FULL_MANU_STR_DESC D (9479) HUB: Stage done: CHECK_FULL_MANU_STR_DESC D (9479) HUB: Stage done: GET_SHORT_PROD_STR_DESC D (9489) HUB: Stage done: CHECK_SHORT_PROD_STR_DESC D (9489) HUB: Stage done: GET_FULL_PROD_STR_DESC D (9499) HUB: Stage done: CHECK_FULL_PROD_STR_DESC D (9499) HUB: Stage done: CLEANUP D (9509) USBH: Processing actions 0x100 D (9509) USBH: New device 1 I (9509) CLASS: Opening device at address 1 I (9519) CLASS: Getting device information I (9519) CLASS: Full speed I (9519) CLASS: bConfigurationValue 1 I (9529) CLASS: Getting device descriptor Device descriptor bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0x0 bDeviceSubClass 0x0 bDeviceProtocol 0x0 bMaxPacketSize0 64 idVendor 0x1235 idProduct 0x69 bcdDevice 0.00 iManufacturer 1 iProduct 2 iSerialNumber 0 bNumConfigurations 1 I (9559) CLASS: Getting config descriptor Configuration descriptor bLength 9 bDescriptorType 2 wTotalLength 82 bNumInterfaces 2 bConfigurationValue 1 iConfiguration 0 bmAttributes 0x80 bMaxPower 500mA Interface descriptor bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 0 bInterfaceClass 0x1 bInterfaceSubClass 0x1 bInterfaceProtocol 0x0 iInterface 3 Interface descriptor bLength 9 bDescriptorType 4 bInterfaceNumber 1 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 0x1 bInterfaceSubClass 0x3 bInterfaceProtocol 0x0 iInterface 3 Endpoint descriptor bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 0x2 BULK wMaxPacketSize 64 bInterval 1 Endpoint descriptor bLength 7 bDescriptorType 5 bEndpointAddress 0x2 EP 2 OUT bmAttributes 0x2 BULK wMaxPacketSize 64 bInterval 1 I (9639) CLASS: Getting Manufacturer string descriptor Focusrite A.E. Ltd I (9649) CLASS: Getting Product string descriptor Launchpad MK2 I (9659) CLASS: driver_obj.actions == 0

So I don't know what to do next. Must be a timing problem in the software or perhaps inrush current from the power supply. I can try putting some bulk capacitance on the power.

mdroberts1243 commented 1 year ago

Adding an electrolytic and film capacitor in parallel right at the power pins didn't really help the situation... but putting the USB Meter inline with the Launchpad clears things up right away. Inrush current really didn't make sense anyway since the problem existed even if the Launchpad was already plugged in and the ESP32 just reset.

Something about the USB Meter helps get the Launchpad past the enumeration.

roma-jam commented 1 year ago

@mdroberts1243,

Thanks for the update. Which USB Meter do you use?

If it helps to process the enumeration, then it seems that the problem is not on a software side. Otherwise, adding an external hardware device would not help.

Which nominal have the capacitor you have tried to add?

Probably, that the capacitance value was not enough.

I would recommend to do the following:

  1. Find an electronic scheme of USB Meter and understand how it "changes" the USB Supply circuit for Launchpad. Verify all the capacitors and get an average additional nominal value.
  2. Try to add a capacitor to the Vbus circuit with a nominal value from step 1.
  3. If it is possible, try to get a Vbus voltage diagram to verify that the capacitance is enough. In other words, during power on and enumeration process there could be a voltage glitching and current spike due to the poor Vbus connection and bad supply voltage.
mdroberts1243 commented 1 year ago

I have tried a more-than-reasonable amount of capacitance with both large electrolytic and film caps in parallel to handle any spikes in current, etc.

I plan to look at the USB Power Meter further to see what else it can be doing to the interface. Hopefully I can find a schematic. Perhaps the DevKit USB implementation is sub-standard, I'll look at that as well. I may try to find another ESP32 design as an alternative to the DevKit that would let me try different hardware, but I don't think I have boards with both USB ports... I may have to use the JTAG interface for programming.

I disagree about the conclusion it can't be software... if it is a timing issue than perhaps the USB Power Meter affects that enough to let the software successfully enumerate.

Bottom-line is that the Launchpad works without problems on any PC USB port I've tried, both Linux and Windows. It only has issues with the ESP32 DevKit and the IDF implementation of TinyUSB.

roma-jam commented 1 year ago

Hi @mdroberts1243 , Thanks for the additional information and reasonable questions!

That is sounds fair and I am totally agreed that maybe it is to soon to eliminate software problem.

The reasons why it is important to fix power supply and other electric characteristic are simple:

  1. An external hardware device (in our case USB Meter) which fix the way of working should not add or influence of the delays in the transport level. It can be easily checked with the USB Meter device schematic. If the D+, D- lines connects straight through the USB Meter, so it can be only parasite capacitance then. Otherwise ... it is better to check USB Meter schematic anyway
  2. Comparison between enumeration process on any PC with esp32 is not fair enough, because in case of any PC the connection is made via the port which is placed closer to the motherboard, so the influence of parasite capacitance and power instability are minimal

So to keep going further is is better when there is no doubt that hardware part can cause the error.

The way that I would suggest is a combination of following steps:

Do you have any possibility to use or access to measurement equipment (logic analyzer or oscilloscope) to see what is happening on lines from the electrical point of view?

Meanwhile, I'll check the HW design of the Dev board.

Thanks for the cooperation.

mdroberts1243 commented 1 year ago

I will look at the D+/D- lines differentially on an oscilloscope with both configurations to see if there is anything obvious there. Away from the office today but should be o.k. tomorrow.

mdroberts1243 commented 1 year ago

The USB Power Meter that improves things is: UM34(C) manual is at: http://www.mediafire.com/folder/5c877rc21tp1p/UM34

I haven't found a definitive schematic but the device might have small serial resistors and/or pulldown resistors on the data lines... TBD.

roma-jam commented 1 year ago

Hi @mdroberts1243,

Unfortunately, I am also haven't found any schematic to that Meter.

Meanwhile, I have some additional information, probably it can helps.

  1. Speaking of influence of USB Meter there can be two options then: additional capacitance or resistance. Probably, there is a chance that in USB Meter has resistors on D+/D- lines (small one, from 22 Om to 33 Om) which creates an RC-filter with parasitic capacitance. That can be easily checked with adding them instead of USB Meter. But anyway, the best answer will be achieved only with a measurement procedure.

  2. Win and Linux have an option to try device enumeration couple of times if first one was unsuccessful. In usb_host we don't do that, the enumeration process done only once. In that case, output of dmesg from Linux during the device enumeration can help to recognize a problem.

Thanks

Dazza0 commented 1 year ago

@mdroberts1243 In addition to the oscilloscope capture of the D+//D- lines (to rule out any power issues), you also provide a logic analyzer capture of the D+/D- lines for the entire enumeration process. We've run into a couple of device before that would successfully enumerate of windows/linux because those OS will retry enumeration a multiple times on failure, so we would want to rule that out as well.

roma-jam commented 1 year ago

@mdroberts1243 Closing this issue as there it is more likely hardware problem with a power supply to the connected device. Feel free to reopen it, if it's not.

HenryckeBSchenberk commented 1 year ago

I'm having a similar issue when trying to use ESP32S3-DevKit as a host as well. Using the official example via VSCODE/ESP-IDF and a USB adapter on pins 19 and 20 according to the documentation I get: "E (17253) HUB: Bad transfer status 1: CHECK_SHORT_DEV_DESC E (17253) HUB: Stage failed: CHECK_SHORT_DEV_DESC" continuously when I plug in my keyboard. Power is also external using a 5V2A supply on pins 5vin and GND and tapping to the adapter.

roma-jam commented 1 year ago

Hi @HenryckeBSchenberk,

Thank you for reporting that. May I ask you a couple of things that can help to distinguish the problem.

  1. Is there only one keyboard, that has such behavior or all available USB devices that you can connect to esp dev board have the same bad transfer error?
  2. If there is only one device, is that possible to get USB descriptor of this device? If the usb_host_lib example cannot be used for that, probably it is better to use any other software to get USB descriptor of the device.
  3. If there is no chance to get descriptor, please provide any information about the keyboard (manufacturer, name, e.t.c)

Thanks for your help and contribution.

copych commented 7 months ago

Please, any further ideas on these issues? I have quite an old keyboard Keystation mini32 by M-Audio. It's quite a cranky device, and it's already a bit modded (just changed mini- to micro-USB, as most mini-USB cables refused to work already). Still, it's working with PC's, but won't run with both S2 and S3 boards. Same as above issue:

HUB: Bad transfer status 1: CHECK_SHORT_DEV_DESC
HUB: Stage failed: CHECK_SHORT_DEV_DESC

Here's what it looks like in USB Tree View: https://gist.github.com/copych/31ba1ddfcc8f2c814d93a5dda84a753b I have tried different powering variants, but no luck. Being neither an experienced engineer, nor having an oscilloscope or logical analyzer, yet I am ready to experiment with this keyboard ))). Maybe it's just a matter of improper logical levels on data lines? Then it should be possible to find suitable resistance to pull the levels to the right voltages...

From USB OTG specs:
...
When an A-device is idle or acting as Host, it shall activate pull-down resistors on both the D+ and D- lines. 
These resistors shall be within the range of 14.25 kΩ to 24.8 kΩ (RPD)
...
When a dual-role B-device is acting as a Peripheral, it shall disable the pull-down on the D+ line 
but shall not disable the pull-down on the D- line.

Owners of Novation LaunchPad MK2 or Keystation MINI32, or any other devices that gives errors on USB-OTG enumeration, please, help finding the way to connect our devices to ESP32s. PS As I've found, Keystation MINI32 has 100 Ohms serial resistance on both data lines. I have tried adding 22 Ohms both in serial and in parallel which gives 122 and 18 Ohms respectively. No change in output.

roma-jam commented 7 months ago

Hi @copych,

  1. Have you tried to enable debug output? (levels debug or verbose)?
  2. If not, may I ask you to slow down the state machine and verify the result. That means to add a delay in hub.c, function enum_set_next_stage . Something like:
static void enum_set_next_stage(enum_ctrl_t *enum_ctrl, bool last_stage_pass)
{
    vTaskDelay(pdMS_TO_TICKS(50));

    // Set next stage
    if (last_stage_pass) {

You can start from 50 ms, and if it helps, decrease the value to 10 ms then.

copych commented 7 months ago

I'll turn on verbose as you stated and report on that later. On slowing down the state machine, please, forgive my ignorance, should I do that in ESP-IDF only, or can I can I effectively change hub.c in Arduino IDE (or is it precompiled when using Arduino)?

roma-jam commented 7 months ago

@copych,

Better would be in esp-idf example.

if you have a device, that doesn’t work, it is possible to verify it on the basic example for usb_host: https://github.com/espressif/esp-idf/tree/master/examples/peripherals/usb/host/usb_host_lib

Thanks

copych commented 6 months ago

I am a newbie, so it took me awhile to install ESP-IDF and an IDE for it. I must admit that I gave up trying make it run under Eclipse which I thought is native for ESP, then I switched to VSCode with ESP-IDF 4.4.7 and failed to compile the example. Finally in 5.2.1 I can build this example ) So here are the results.

without a delay:

D (1684) HUB: Root port reset
D (1684) HUB: Stage done: START
D (1684) HUB: Stage done: GET_SHORT_DEV_DESC
D (1684) HUB: Stage done: CHECK_SHORT_DEV_DESC
D (1744) HUB: Stage done: SECOND_RESET
D (1744) HUB: Stage done: SET_ADDR
E (1744) HUB: Bad transfer status 1: CHECK_ADDR
E (1744) HUB: Stage failed: CHECK_ADDR
D (1744) HUB: Stage done: CLEANUP_FAILED

with 50 ms delay:

D (8774) HUB: Root port reset
D (8774) HUB: Stage done: START
D (8824) HUB: Stage done: GET_SHORT_DEV_DESC
D (8874) HUB: Stage done: CHECK_SHORT_DEV_DESC
D (8984) HUB: Stage done: SECOND_RESET
D (9034) HUB: Stage done: SET_ADDR
D (9084) HUB: Stage done: CHECK_ADDR
D (9144) HUB: Stage done: SET_ADDR_RECOVERY
D (9194) HUB: Stage done: GET_FULL_DEV_DESC
D (9244) HUB: Stage done: CHECK_FULL_DEV_DESC
D (9294) HUB: Stage done: GET_SHORT_CONFIG_DESC

no further activity in both cases, which probably is expected behavior ...or not.

roma-jam commented 6 months ago

Hi @copych, Thanks for the efforts and sharing the log.

Log without a delay contain the issue and has one stage failed during enumeration. Log with a delay doesn't have it and looks like a normal log. But there should be the following information, when enumeration process finishes the configuration and shows information about the attached device. To see, you can try any usb device and compare the result of debug output for usb_host_lib example. There should be a further activity.

Could you try any other usb device to be sure, that the example works correctly? You should see the usb information about connected device (such as Device/Configuration/Interface and Endpoint descriptors).

Thanks a lot.

copych commented 6 months ago

@roma-jam, Yes, I have tried a USB wireless mouse receiver, and it showed some further actions, I can't reproduce logs right now, but in general, there were messages telling that the device1 is connected, and some details including its recognized name etc.

copych commented 6 months ago

@roma-jam, as the May holidays is over may I ask you to investigate a bit into the issue? Can you please re-check https://gist.github.com/copych/31ba1ddfcc8f2c814d93a5dda84a753b , it's a windows usb-tree report. Maybe, the keyboard is totally incompatible with the Espressif OTG ?

copych commented 5 months ago

@roma-jam , some additional info. I have tested this very keyboard with RP2040, and it worked fine, using this library https://github.com/rppicomidi/EZ_USB_MIDI_HOST based on TinyUSB.

roma-jam commented 5 months ago

@copych,

thanks for the additional information. It should be compatible and based on the last output with a delay (when the interaction stucked in the middle of enumeration process) it seems that there is some specific, which not so easy to find without a hardware.

Currently, we are in the middle of the process of refactoring usb_host library and enumerations process to support Hubs, so we have some changes (and we add some debug as well), which could help in your case.

The plan is to finish the first version till the June, so I‘ll return to this issue after that.

If there is anything, feel free to report.

emanuelelaface commented 5 months ago

Somehow I have the same issue with a SNES generic joypad controller. I say somehow because sometime it does not start at all with the same error about Bad transfer status 1: CHECK_SHORT_DEV_DESC, but if I try to reboot several times, sometime it starts and works for a while, then it hangs. I have another controller that looks identical and works fine. I opened the two controllers and inside are quite different, the one that works always has a crystal inside, the other not. Of course the two controllers work fine on a PC, I tried multiple times and are both perfect.

Dazza0 commented 5 months ago

During enumeration, GET_SHORT_DEV_DESC/CHECK_SHORT_DEV_DESC is the first transfer sent to the device immediately after reset. If Bad transfer status 1, it means the transfer status ;was USB_TRANSFER_STATUS_ERROR, typically meaning the device did not respond at all.

@emanuelelaface Any chance you could hook up a logic analyzer and see what's happening on the bus when the joypad is being enumerated. Also, could you please open a new GitHub issue so we could track this separately.