rppicomidi / usb_midi_host

An application level TinyUSB USB MIDI Host driver for the RP2040
MIT License
70 stars 9 forks source link

Arturia Beat Step Pro no data #14

Open ctag-fh-kiel opened 3 months ago

ctag-fh-kiel commented 3 months ago

Describe the bug Tried the C-Example usb_midi_host and connected a Beat Step Pro, the device is recognized with 2 Midi Cables, but no midi data is received

To Reproduce Steps to reproduce the behavior:

  1. Use example and connect Beat Step Pro

Screenshots Logs: Pico MIDI Host Example MIDI opening Interface 1 (addr = 1) MIDI opening Interface 1 (addr = 1) MIDI descriptor parsed successfully MIDI device address = 1, IN endpoint 1 has 2 cables, OUT endpoint 2 has 2 cables

What is your setup like?

ctag-fh-kiel commented 3 months ago

Here is a screenshot of the logs, left side working with Novation Launchpad, right side stuck with Beat Step Pro Beat Step Pro allocates bulk endpoint, Launchpad allocates int endpoint, does this mean anything to you?

image
rppicomidi commented 3 months ago

@ctag-fh-kiel Thank you for taking the time to report this issue.

To help you with this issue, I need some more data.

To answer your question about the bulk vs. interrupt endpoint, USB data connections within a device are called endpoints. Each endpoint type has different characteristics. The important thing here is that USB MIDI 1.0 class spec says to use Bulk endpoints for data transfer; the Beat Step Pro is doing this correctly, so that is not the issue. Some implementations erroneously use Interrupt endpoints, but my driver supports both.

In the meantime, I will try my Arturia KeyLab Essential 88 again to make sure I have not introduced a bug by accident.

ctag-fh-kiel commented 3 months ago

@rppicomidi Thanks a lot for getting back!

Arturia-BSPro-ErrorLog.txt Arturia-BSPro-USB.txt ElektronDigitoneLog.txt NovationLPMiniLog.txt

rppicomidi commented 3 months ago

@ctag-fh-kiel Thank you for the data. I am puzzled. As I read the configuration descriptor from BSPro error log and from the device info in the BSPro file, the BSPro has the same USB descriptors as my Arturia Keylab Essential 88 keyboard except for the device descriptor product ID. My keyboard works fine with the example code. On my keyboard, the LEDs behind the transport controls turn on and off one after the other as expected and the terminal outputs the correct MIDI data in response to key presses.

For your reference, the output of the command lsusb -d 1c75:02ca -v is attached (from a Linux PC. I was sure Mac Homebrew has a version of the lsusb command that produces the same output). KeylabEssential88_USB_descriptor.txt

I would like to try to debug one thing at a time.

First, there may be a power issue. May I ask you try again by connecting the BSPro via a powered USB hub? If that does not work, please try the other devices you have that are known good. If they work and the BSPro does not, then I believe we can rule out electrical issues.

Second, the BSPro may not like receiving the note messages the code sends. Please disable the MIDI messages sent to the BSPro by commenting out line 127:

send_next_note(connected);

Then rebuild and see if the example code reacts to any of the drum pad taps, knob turns, or button presses.

If that does not work, may I ask if CTAG have a USB analyzer of any sort? If so, a trace of what is going on may be telling.

If not, I will see if anyone I know has a BSPro they could lend me. That will be a longer route because I am traveling soon and won't return until July.

ctag-fh-kiel commented 3 months ago

@rppicomidi Thanks again for testing. I have checked the power situation with a 2A supply, should be fine.

Attached another dump from lsusb this time from linux, somehow homebrew lsusb did not work correctly. The descriptor seems to be a bit longer than the one from your Keylab. I tried commenting out L.127 no success either, attached the log from that experiment.

I don't have access to a usb analyzer unfortunately.

Thanks for your help! :)

BSPro-no-send-next-note-log.txt BSPro_USB-2.txt

rppicomidi commented 3 months ago

@ctag-fh-kiel Thank you for the new data. Short answer. I do not believe descriptor parsing is the problem. Also, there is nothing in the Error Log that you sent that looks unusual to me. Can you confirm that the BSPro is it running the latest firmware? If so, I will need a USB trace to investigate further (to compare a working version with a Mac, PC or Linux computer vs. this TinyUSB driver).

Longer answer:

The descriptors for the BSPro and the KeyLab are the same length. The only differences between the descriptors are in the device descriptor (the BSPro uses 500mA max power and the Keylab on 100mA) and the MIDIStreaming Interface descriptors (the BSPro has the jack descriptors in a different order from the Keylab and the BSPro has an error in the MIDIStreaming Interface Descriptor header (the wTotalLength field is off by 2 for some reason). However, the usb_midi_host driver ignores the MIDIStreaming Interface descriptors unless you enable the jack string support, and it also ignores the wTotalLength field in the MIDIStreaming Interface Descriptor header; it relies on the wTotalLength field in the Configuration Descriptor instead (0x85 = 133 bytes).

ctag-fh-kiel commented 3 months ago

Hi there,

Yes, I updated my BSPro to test if that is the issue, it runs on the latest firmware.

Thanks for further investigations :)

On Mon, Jun 17, 2024 at 8:11 PM rppicomidi @.***> wrote:

@ctag-fh-kiel https://github.com/ctag-fh-kiel Thank you for the new data. Short answer. I do not believe descriptor parsing is the problem. Also, there is nothing in the Error Log that you sent that looks unusual to me. Can you confirm that the BSPro is it running the latest firmware? If so, I will need a USB trace to investigate further (to compare a working version with a Mac, PC or Linux computer vs. this TinyUSB driver).

Longer answer:

The descriptors for the BSPro and the KeyLab are the same length. The only differences between the descriptors are in the device descriptor (the BSPro uses 500mA max power and the Keylab on 100mA) and the MIDIStreaming Interface descriptors (the BSPro has the jack descriptors in a different order from the Keylab and the BSPro has an error in the MIDIStreaming Interface Descriptor header (the wTotalLength field is off by 2 for some reason). However, the usb_midi_host driver ignores the MIDIStreaming Interface descriptors unless you enable the jack string support, and it also ignores the wTotalLength field in the MIDIStreaming Interface Descriptor header; it relies on the wTotalLength field in the Configuration Descriptor instead (0x85 = 133 bytes).

— Reply to this email directly, view it on GitHub https://github.com/rppicomidi/usb_midi_host/issues/14#issuecomment-2174025903, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZMGRUW4K7UDSP2ISQJUGDZH4RFTAVCNFSM6AAAAABJKAVBHSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNZUGAZDKOJQGM . You are receiving this because you were mentioned.Message ID: @.***>

ctag-fh-kiel commented 3 months ago

I have been able to get a hold of a USB analyzer, attached both traces (Launchpad and BSPro) edit attached new BSPro trace, where after 1.39s only bursts with the same data are sent. I used the same cable, which works when directly connected to the PC for both controllers. USB-Traces2.zip

ctag-fh-kiel commented 3 months ago

Attached some screen captures of the acquisitions, interestingly the BSPro goes into some sort of a burst mode after 1.3s or so, not following a 1ms frame pattern. Whereas LP Mini stays in sending frames every 1ms. USB-Traces-ScreenCaps.zip

rppicomidi commented 3 months ago

@ctag-fh-kiel I have returned from my travels. To make sure I understand, your BSPro runs the latest firmware and yet usb_midi_host still fails to work.

Also, what software are you using to generate the traces? I can read CSV data into a spreadsheet, but it is nicer if the software can decode data packets into USB requests, descriptors, and so forth. For example, if you used PulseView, the raw traces would be useful to me because I also have that software and could apply the USB Request protocol decoder.

ctag-fh-kiel commented 3 months ago

Hi there, yes, BSPro latest firmware and usb_midi_host still fails. I have used PicoScope. I could provide you with the raw data as well, but it will be huge. Let me know if needed.

rppicomidi commented 3 months ago

@ctag-fh-kiel Ah, I see the request decoder is already there. My mistake. No need to send raw data.

Would you please include a CSV trace where the BSPro successfully connects to a computer and transmits MIDI data to the computer? It may give a clue to the difference.

The decoded trace you sent shows a normal enumeration sequence and at time 1.14987083692566, a normal set configuration packet. The BSPro seems to always NAK IN requests from the host on endpoint 1, which should mean the BSPro is not ready to send data. All of that looks normal on first glance. It looks like the "burst mode" after 1.3 seconds is the host repeatedly trying to start a bulk IN transfer and the BSPro repeatedly sending NAK to indicate it has nothing to send.

rppicomidi commented 3 months ago

@ctag-fh-kiel I am also this week going to try out some USB packet sniffers based on a Raspberry Pi Pico board. https://github.com/tana/pico_usb_sniffer and https://github.com/ataradov/usb-sniffer-lite. I suspect those will be simpler to use than the analyzer you are using. I will let you know what I find.

ctag-fh-kiel commented 3 months ago

Attached a trace when BSPro is connected to Mac and works fine, the data looks different. I think it seems more normal similar to the Launchpad (which worked with usb_midi_host). BSPro-mac-usb.csv

ctag-fh-kiel commented 3 months ago

All traces are without actually sending Midi data, they are all from power on to ready to send/rcv...

ctag-fh-kiel commented 3 months ago

@ctag-fh-kiel Ah, I see the request decoder is already there. My mistake. No need to send raw data.

Would you please include a CSV trace where the BSPro successfully connects to a computer and transmits MIDI data to the computer? It may give a clue to the difference.

The decoded trace you sent shows a normal enumeration sequence and at time 1.14987083692566, a normal set configuration packet. The BSPro seems to always NAK IN requests from the host on endpoint 1, which should mean the BSPro is not ready to send data. All of that looks normal on first glance. It looks like the "burst mode" after 1.3 seconds is the host repeatedly trying to start a bulk IN transfer and the BSPro repeatedly sending NAK to indicate it has nothing to send.

I am not sure if you looked at the right trace since I updated the post. The BSPro with usb_midi_host repeatedly sends the same data package. Trace attached again. BSPro-USB.csv

rppicomidi commented 3 months ago

@ctag-fh-kiel Yes, I see the repeating data package you mean. I do know that the RP2040 is not sending ACK in response to the data package, which means the host controller thinks it must have some sort of error in it. I will compare the crazy BSPro trace with the Mac BSPro trace. You can skip the next paragraph if you wish.

The Mac reads the device descriptor, then reads the product name string descriptor, then the manufacturer name string descriptor, then the configuration descriptor, then it selects configuration 1 on the BSPro, and then the BSPro returns what appears to be a similar 64 bytes of gibberish, followed by 16 MIDI clock messages, followed by the Mac sending a NULL sysex message (0xF0 0xF7), followed by the BSPro sending another 16 MIDI clock messages, followed by the Mac requesting the language ID string descriptor from the BSPro, followed by the BSPro returning US English, followed by the Mac sending ACK and a zero-length packet to the BSPro. All seems well.

Now my suspicion I thought the first bulk IN transfer starts with a DATA0 packet, and that might be what is confusing the RP2040 USB engine. To confirm my suspicion, please take a trace of your LP Mini and press a LP Mini button while you are recording a trace. The first Bulk IN packet should be a DATA0 packet, I believe. If that is the case, fixing this issue would require a patch to TinyUSB, but it may not be possible unless the USB hardware in the RP2040 lets you fix it. If I am wrong, then I am baffled unless your trace program detects a CRC error or other error on the 64 byte gibberish packet. The trace you sent had nothing in the error columns.

Please let me know.

rppicomidi commented 3 months ago

@ctag-fh-kiel Please do not try any other measurements yourself on my account. I just got a sniffer setup working and I am doubting my suspicion in my last post. Will look again in the morning.

ctag-fh-kiel commented 3 months ago

Sounds great, was just gearing up for another one :)

rppicomidi commented 3 months ago

@ctag-fh-kiel I now have pretty good confidence the problem is a data sequence error. It may be worth proving this to yourself by looking at the trace for the LP Mini button presses as described above. You should see the first endpoint 1 IN transaction that does not respond with NAK as DATA0 followed by some multiple of data 4 bytes.

Sadly, I do not believe there is a way to disable data sequence checking in RP2040 native USB host hardware. However, if you are able to try the usb_midi_host_pio_example program with the host port wired to GP16 and GP17, then you can try a work-around for the issue by making a single line change to file pico-sdk/lib/tinyusb/hw/mcu/raspberry_pi/Pico-PIO-USB/src/pio_usb_host.c. If you do this, please let me know how it goes.

static int __no_inline_not_in_flash_func(usb_in_transaction)(pio_port_t *pp,
                                                             endpoint_t *ep) {
  int res = 0;
  uint8_t expect_pid = (ep->data_id == 1) ? USB_PID_DATA1 : USB_PID_DATA0;

  pio_usb_bus_prepare_receive(pp);
  pio_usb_bus_send_token(pp, USB_PID_IN, ep->dev_addr, ep->ep_num);
  pio_usb_bus_start_receive(pp);

  int receive_len = pio_usb_bus_receive_packet_and_handshake(pp, USB_PID_ACK);
  uint8_t const receive_pid = pp->usb_rx_buffer[1];

  if (receive_len >= 0) {
    if (/*receive_pid == expect_pid*/ 1) { // <== This is the line to change to disable the data sequence checking.
      memcpy(ep->app_buf, &pp->usb_rx_buffer[2], receive_len);
      pio_usb_ll_transfer_continue(ep, receive_len);
    } else {
      // DATA0/1 mismatched, 0 for re-try next frame
    }
ctag-fh-kiel commented 3 months ago

Ok, just that we understand correctly: The LP Mini works with usb_midi_host (tested from my end) -> although it doesn't have a correct sequence? The BSPro does NOT work with usb_midi_host -> is there a sequence error as well? Thx for a clarification.

rppicomidi commented 3 months ago

@ctag-fh-kiel I am sorry if I was not clear.

Yes, we understand correctly. I mention taking the LP Mini trace in case you want to see for yourself the correct DATA0 DATA1 Bulk IN transaction sequence. No need to test if you do not want to.

If you are able to build the PIO USB hardware (requires wiring a USB connector to two GPIO pins, +5V and ground), then you can run the usb_midi_host_pio_example with the above minor modification with the BSPro. I believe that should work.

If you are not able to build the PIO USB hardware, then I am sorry, but I do not believe I can make the BSPro work with the RP2040's built-in USB host hardware.

I hope this is more clear.

ctag-fh-kiel commented 3 months ago

@rppicomidi now I have a funny finding, the BSPro works with the usb_midi_host_pio_example without any changes to the code. Whereas the LaunchPadMini does not.

Would it help if I send USB analyzer traces of both again?

Cheers :)

rppicomidi commented 3 months ago

What version is your Pico-PIO-USB library? Version 0.6 has known issues. If you are using it, please downgrade. That said, it would indeed help to send traces of both again. I may be slow to respond for the remainder of the week.

ctag-fh-kiel commented 2 months ago

I have used Pico-PIO-USB 0.5.3. Attached USB protocol traces for (including ones where "SOF" is filtered out):

@rppicomidi I'm curious what you think :)

BSPro traces: BSPro-PIO-working-noSOF.csv BSPro-PIO-working.csv BSPro-USB-not-working-noSOF.csv BSPro-USB-not-working.csv

LPMini traces: LPMini-PIO-not-working-noSOF.csv LPMini-PIO-not-working.csv LPMini-USB-working-noSOF.csv LPMini-USB-working.csv

rppicomidi commented 2 months ago

@ctag-fh-kiel Thank you for the great data. As we have discussed, I believe the regular USB examples have an explanation: the LPMini properly sends the first bulk transfer with the DATA0 PID; the BSPro improperly starts with the DATA1 PID.

I have no explanation for the behavior you are observing with the PIO-USB code. For the LPMini SYNC error: have you ruled out electrical issues? I have found that with some USB cables, I can get better results if the I connect the PIO USB port through a powered hub.

That said, unless there is some memory corruption going on, I do not understand how the BSPro USB-PIO code is working. I will investigate.

ctag-fh-kiel commented 2 months ago

So the BSPro USB issue is within the USB peripherals state machine and can't be fixed, or is this something one can address from the TinyUSB side?

I will try attaching a USB hub in both setups, maybe that changes something. For the LPMini PIO, I have also the feeling it could be an electrical issue, though I have tested already with multiple USB cables of different length.

Thanks for still being involved with the issue :)

ctag-fh-kiel commented 2 months ago

Same results both with USB and PIO when using a USB hub in between...

rppicomidi commented 2 months ago

@ctag-fh-kiel Yes, it is my belief that the BSPro issue is with the BSPro's USB state machine. I am 90% sure this cannot be fixed in the TinyUSB RP2040 host driver. I have reached out for help in the TinyUSB discussions

I am baffled by the PIO USB results you report. I am currently using the the PIO example myself without issue. Perhaps the difference is software versions. usb_midi_host version 1.1.1<==you already confirmed this is the same pico-sdk: develop branch commit 6ff3e4fab27441de19fd53c0eb5aacbe83a18221. pico-sdk/lib/TinyUSB commit ccc7a36043e055ded1f478a979a303e694123187. pico-sdk/lib/tinyusb/hw/mcu/raspberry_pi/Pico-PIO-USB commit 0f747aaa0c16f750bdfa2ba37ec25d6c8e1bc117

ctag-fh-kiel commented 2 months ago

@rppicomidi Yes, I can confirm all the right commit versions.

Which MIDI devices are you using to test PIO mode?

Thanks for reaching out in the TinyUSB community.

rppicomidi commented 2 months ago

Devices I am testing:

ctag-fh-kiel commented 2 months ago

Do you think the issue with the USB stack is captured in the rp2040 errata, pg. 633ff? rp2040 datasheet

rppicomidi commented 2 months ago

To which issue with the USB stack are your referring? Also, which errata are you asking about? If I recall correctly, RP2040-E3 and RP2040-E4 are addressed in the TinyUSB stack. Double buffering is not used host mode. The other issues with the USB hardware are with the device mode.

ctag-fh-kiel commented 2 months ago

Ah ok, I didn't parse the errata with great detail, just thought, maybe you had checked them out. Thx :)

rppicomidi commented 2 months ago

@ctag-fh-kiel I have more information about this issue, but I unfortunately do not have a fix for the native USB Host hardware. I gave you wrong information before about the correct behavior of the USB host when it receives a packet with DATA1 PID when it expects DATA0, or vice versa. According to the USB 2.0 specification section 8.6.4, in this situation, the Host is supposed to send ACK to the Device anyway; however, the Host will ignore the data. I carefully looked at the Pico PIO USB host code and determined that it implements this behavior correctly. That would explain why the unmodified Pico PIO USB host code works correctly with the Arturia Beatstep Pro. That the Beatstep Pro does not work with the RP2040 native USB Host hardware suggests there is an undocumented Erratum in the chip.

rppicomidi commented 1 month ago

@ctag-fh-kiel I want to thank you again for finding this issue. It is not unique to your setup or the Beatstep Pro. I was able to duplicate this issue with a $12 STM32F072B-Discovery board. I am pretty convinced it is a chip bug. Check out raspberrypi/pico-feedback#394 if you are interested in the experiment. STM32F0 chip is a handy test tool because you can easily control the USB data toggle bit in software.

Now that I have a test tool, I can see if I can come up with a software work-around. My operating assumption for a workaround is that the Finite State Machine that controls the RP2040 EPx endpoint in host mode is different from the auto-polled collection of endpoints. Please let me know if this is still of interest to you, or if you have moved on.

ctag-fh-kiel commented 1 month ago

Hi there, thanks for getting into this! It seems like a non trivial issue. And yes, a workaround or fix would be great!

Thanks a lot!

rppicomidi commented 1 month ago

@ctag-fh-kiel OK. It may be some weeks before I can get to this, but I will. Right now I am trying to bring the new pico-sdk 2.0 into my code base. After that, I need to finish up some work on BLE MIDI. After that, I will revisit this. As you say, it is maybe non-trivial.

rppicomidi commented 1 month ago

@ctag-fh-kiel I have a temporary workaround for you. You will have to apply two patches to the source code.

cd ${PICO_SDK_PATH}/lib/tinyusb
unzip tinyusb_data_seq_patch.zip
git apply 0001-Use-known-bad-device-list-to-fix-init-IN-data-seq-is.patch

cd ${The directory where you are storing the usb_midi_host_library}
unzip usb_midi_host_data_seq_patch.zip
git apply 0001-Test-workaround-for-RP2040-initial-IN-edpt-data-seq-.patch

Then rebuild the C-code usb_midi_host_example project and test it with the Beatstep Pro. I think it should work. Please let me know. usb_midi_host_data_seq_patch.zip tinyusb_data_seq_patch.zip

The longer term fix is a ways out, unfortunately.

ctag-fh-kiel commented 1 month ago

Will try soon and get back, thx for your effort :)

ctag-fh-kiel commented 1 month ago

I can report that the BSPro works with the patches :) I have used version 1.1.3 of usb_midi_host. Any chances this will go into the next release? Thanks a lot ! ! !

rppicomidi commented 1 month ago

@ctag-fh-kiel Thank you for working with me on this. I do appreciate it. I am reluctant to release this patch as a way of doing business in usb_midi_host. The right way to fix this bug is to rewrite the hcd. I will see where the TinyUSB people stand on this bug. If they are not anxious to write a new host controller driver, and if they will agree to merge the TinyUSB part of the patch, then I will release the usb_midi_host library.

rppicomidi commented 1 week ago

@ctag-fh-kiel If you have some time to try out a new RP2040 USB Host driver, https://github.com/hathach/tinyusb/pull/2814, I believe it will fix your issue without requiring the application to list known bad devices. Hopefully the TinyUSB project will accept the pull request or something like it.

ctag-fh-kiel commented 1 week ago

Yes, your tinyusb pull request works with the BSPro. Great job! Hope it'll be merged asap.

Thanks again!

rppicomidi commented 1 week ago

Perfect. I will close this issue when TinyUSB merges my pull request or something like it.