Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arturia Beat Step Pro no data #14

Open
ctag-fh-kiel opened this issue Jun 14, 2024 · 45 comments
Open

Arturia Beat Step Pro no data #14

ctag-fh-kiel opened this issue Jun 14, 2024 · 45 comments

Comments

@ctag-fh-kiel
Copy link

ctag-fh-kiel commented Jun 14, 2024

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?

  • C
  • What build machine OS and version: MacOS 14.5
  • Version of this library : master
  • Version of build software pico-sdk 1.5.1, tinyusb master
  • How are you loading build images to the target: debug_probe
@ctag-fh-kiel
Copy link
Author

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
Copy link
Owner

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

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

  • Which C example are you running (usb_midi_host_example) or ('usb_midi_host_pio_example`)?
  • What version of the usb_midi_host code are you using?
  • Instead of screenshots, please attach text files with the log output. I have to look at my issue template. Screenshot is probably not what should be there.
  • Please attach a text file dump of the USB descriptors for the device that does not work. In MacOS homebrew you can use the command lsusb to find the vid:pid numbers and then lsusb -d vid:pid -v to get the full descriptor
  • Is there any indication that transmission to the Beat Step Pro is working? How about to the Launchpad?
  • Please describe the hardware that is running the test program.
  • What are you doing on the Beat Step Pro to send 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
Copy link
Author

@rppicomidi Thanks a lot for getting back!

  • I have been using usb_midi_host_example
  • Using usb_midi_host 1.1.1
  • Log files are attached (including a log from Elektron Digitone (working))
  • USB descriptor of the Beatstep Pro is attached
  • I can't say if the Beatstep Pro receives data from usb_midi_host_example, I would have to see how I could check that, as it can't produce a sound by itself
  • For the Launchpad I can say that send/receive works, same for an Elektron Digitone no problems (both logs attached)
  • I am using a custom PCB based on a standard rp2040 setup, using the the USB lines attached to a USB-A jack
  • Starting the sequencer on the BSPro and pressing the trigger pads + rotating the controls to send midi data, I have checked the CC mappings (Arturia Midi Controll Center) and the BSPro should send messages, cross checked this with the BSPro in Ableton, where it works fine

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

@rppicomidi
Copy link
Owner

@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
Copy link
Author

@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
Copy link
Owner

@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
Copy link
Author

ctag-fh-kiel commented Jun 17, 2024 via email

@ctag-fh-kiel
Copy link
Author

ctag-fh-kiel commented Jul 1, 2024

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
Copy link
Author

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
Copy link
Owner

@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
Copy link
Author

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
Copy link
Owner

@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
Copy link
Owner

@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
Copy link
Author

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
Copy link
Author

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

@ctag-fh-kiel
Copy link
Author

@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
Copy link
Owner

@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
Copy link
Owner

@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
Copy link
Author

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

@rppicomidi
Copy link
Owner

@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
Copy link
Author

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
Copy link
Owner

@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
Copy link
Author

ctag-fh-kiel commented Jul 3, 2024

@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
Copy link
Owner

rppicomidi commented Jul 4, 2024

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
Copy link
Author

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

  • BSPro USB (not working) -> gets stuck when a DATA1, IN package is not acknowledged and is indefinitely resent
  • BSPro PIO (working) -> ends up in IN / NAK cycles just like the LPMini with USB -> seems all ok
  • LPMini USB (working) ->ends up in IN / NAK cycles just like the BSPro with PIO -> seems all ok
  • LPMini PIO (not working) -> gets stuck after an invalid sync -> different pattern than BSPro USB not working

@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
Copy link
Owner

@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
Copy link
Author

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
Copy link
Author

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

@rppicomidi
Copy link
Owner

@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
Copy link
Author

@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
Copy link
Owner

Devices I am testing:

  • Korg nanoKONTROL2
  • Korg nanoKONTROL Studio
  • Yamaha Reface CS
  • Arturia KeyLab 88

@ctag-fh-kiel
Copy link
Author

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

@rppicomidi
Copy link
Owner

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
Copy link
Author

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

@rppicomidi
Copy link
Owner

@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
Copy link
Owner

@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
Copy link
Author

ctag-fh-kiel commented Aug 11, 2024 via email

@rppicomidi
Copy link
Owner

@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
Copy link
Owner

@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
Copy link
Author

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

@ctag-fh-kiel
Copy link
Author

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
Copy link
Owner

@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 added a commit to rppicomidi/tinyusb that referenced this issue Sep 24, 2024
This commit fixes issue hathach#2776
hathach#2776.
The HCD now routes all USB transfers through the EPx
endpoint. It no longer uses the "interrupt" endpoint
hardware to handle INTERRUPT and BULK endpoints. The
fix avoids the data sequence error handling bug in
the RP2040 USB IP's "interrupt" endpoint hardware
and allows the host to correctly drop the IN packet
with the error without locking up. That fixes
rppicomidi/usb_midi_host#14

This fix requires the CPU to handle the SOF interrupt
(every ms). That might be an issue for some systems.

A benefit of this fix is that BULK transfers are
more than 2x faster. There is an opportunity to speed
them up further by forcing BULK transfer to begin
immediately instead of waiting for the next SOF interrupt.

This code has been tested with MSC flash drives, HID
devices, and USB Hubs. It works with full speed and low
speed HID devices connected at the same time through a hub.
With the usb_midi_host application host driver, 4 MIDI
devices plugged to a hub can send messages to each other
(see the midi2usbhub project).
@rppicomidi
Copy link
Owner

@ctag-fh-kiel If you have some time to try out a new RP2040 USB Host driver, hathach/tinyusb#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
Copy link
Author

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

Thanks again!

@rppicomidi
Copy link
Owner

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants