midi2cpp | Host MIDI 2.0
USB MIDI 2.0 host on the Waveshare ESP32-P4-WIFI6-DEV-KIT. Plug an upstream MIDI 2.0 device into either of the two USB-A jacks (UTMI PHY, OTG_HS controller at 480 Mbps, routed through the onboard CH334F USB hub), routes UMP through m2host, prints decoded device topology + live UMP stream on the UART console (CH343 USB-Serial-JTAG bridge on the ToUART USB-C jack). ESP-IDF v5.4 build, no Arduino IDE.
Built against the TinyUSB
experiment/midi-coexistencebranch on top of upstream master. The branch adds an alt-walkbcdMSCdefer that letsCFG_TUH_MIDI=1andCFG_TUH_MIDI2=1coexist (each driver claims only its matching protocol version). Staged as a follow-up PR upstream.
Host-only role: no USB VID / PID consumed. The host plays MIDI-CI Initiator: it transmits Discovery Inquiry on every device mount and stores remote MUIDs in m2host::identity(idx).ciMuid.
| Field | Value |
|---|---|
| MIDI-CI Manufacturer ID | {0x7D, 0x00, 0x00} |
| Host MUID | seeded at boot from esp_random(), masked to 28 bits |
Requires ESP-IDF v5.4+ with . $IDF_PATH/export.sh sourced and the RISC-V toolchain installed ($IDF_PATH/install.sh esp32p4 once on a fresh IDF).
cd idf
./scripts/fetch_tinyusb.sh # one-off, ~36 MB clone of the experiment branch
. $IDF_PATH/export.sh
idf.py set-target esp32p4
idf.py build
idf.py -p /dev/ttyACM0 flash monitor # ToUART jackThe CH343 USB-Serial-JTAG bridge (VID 1a86:55d3) on the ToUART USB-C jack binds to cdc_acm (/dev/ttyACM0). Real DTR / RTS, so idf.py flash auto-resets without a button press.
To override TinyUSB with a local working copy: ln -sfn /path/to/your/tinyusb idf/external/tinyusb && idf.py reconfigure.
| Connector / Pin | Use |
|---|---|
| USB-A jacks (×2) | UTMI host PHY (OTG_HS, 480 Mbps), routed through onboard CH334F USB hub. Plug upstream MIDI 2.0 devices here. |
| USB-C ToUART | CH343 USB-Serial-JTAG bridge, console stdio @ 115200 8N1, flashing |
| USB-C USB-Device | INT device PHY (OTG_FS), not used in this host-only recipe |
| BOOT button | Hold during reset to enter download mode (rarely needed; CH343 auto-reset handles it) |
| RESET button | Reboot |
The CH334F hub allows up to MIDI2CPP_HOST_MAX_DEVICES (default 4) MIDI 2.0 devices simultaneously, addressed by idx.
Plug any USB MIDI 2.0 device into either USB-A jack. The UART console should print [host] device idx=N connected, alt=A, an [ep] block with the device's Endpoint Info / Name / Product Instance ID, and one event line per UMP packet.
Tier A host. The ESP32-P4's 768 KB SRAM and high-speed UTMI PHY support multi-device hub topology end to end.
| UMP MT | Direction | Spec | Notes |
|---|---|---|---|
| 0x0 Utility | RX | M2-104-UM §3 | JR Timestamp tracked |
| 0x4 MIDI 2.0 Channel Voice | RX | M2-104-UM §7 | NoteOn/Off (16-bit velocity), CC (32-bit), Pitch Bend (32-bit), all surfaced |
| 0xF UMP Stream | RX | M2-104-UM §11 | full Endpoint + FB Discovery, Endpoint Name notification surfaced |
MIDI-CI: Discovery Initiator only (auto-fired on mount). Replies populate m2host::identity(idx).ciMuid.
Boot log:
[boot] esp32-p4-devkit-host-midi2-monitor
Host UTMI PHY ready (rhport 1)
[host] waiting for device on USB-A jacks...
Per device mount, console prints one line per event:
| Event | Console line |
|---|---|
| Mount | [host] device idx=N connected, alt=A (UMP|byte-stream) |
| Endpoint Info notification | [ep] idx=N UMP vM.m, F FB, MIDI2=1 |
| Endpoint Name notification | [ep] idx=N Endpoint Name: <product> |
| NoteOn | [in idxN] NoteOn ch=C note=N vel=0xVVVV |
| NoteOff | [in idxN] NoteOff ch=C note=N vel=0xVVVV |
| CC (32-bit) | [in idxN] CC ch=C #I val=0xVVVVVVVV |
| Pitch Bend (32-bit) | [in idxN] PitchBend ch=C val=0xVVVVVVVV |
| Disconnect | [host] device idx=N disconnected |
MIT, inherits parent midi2cpp LICENSE.

