Raspberry Pi USB MIDI Gadget on Trixie: Setup and Troubleshooting¶
A Raspberry Pi with a USB device-mode port can appear to a computer as a class-compliant MIDI endpoint. This guide uses the kernel's single-function g_midi module, verifies the ALSA port, and sends a controlled test note from Python.
Do not combine gadget managers
g_midi, rpi-usb-gadget, and a ConfigFS gadget are alternative ways to claim the same USB Device Controller. Disable the active Ethernet or composite gadget before enabling g_midi. See the USB Gadget Mode comparison before changing an existing setup.
What you need¶
- A Raspberry Pi with a device-mode/OTG-capable port. The Zero, Zero W, and Zero 2 W are common manual gadget targets; Pi 4 uses its USB-C dual-role port. Confirm other models against their hardware documentation and current kernel support.
- A known data-capable USB cable. On a Pi Zero, connect it to the port labelled
USB, notPWR IN. - Raspberry Pi OS Trixie and a separate SSH, serial, or local-console recovery path.
- A host computer with a DAW, MIDI monitor, or software synthesizer.
The official Trixie rpi-usb-gadget package supports a broader model list for its managed Ethernet function. That list must not be treated as proof that this manual g_midi recipe works identically on every board.
1. Record the current state¶
Before editing boot settings, check the OS, architecture, controller, and competing gadget configuration:
If an existing gadget owns the UDC, disable it using that setup's documented procedure and reboot before continuing.
2. Enable the device-mode controller¶
Back up the boot configuration, then edit it:
Add this line once:
The explicit dr_mode=peripheral prevents ambiguity about which role the dual-role controller should use. Do not change cmdline.txt for this procedure.
3. Load the MIDI gadget¶
Test the module manually before making it persistent:
If that succeeds, add one line to /etc/modules:
Reboot, connect the data cable to the correct device-mode port, and check the host's USB device list.
Optional device strings¶
Create /etc/modprobe.d/g_midi.conf only if you need recognizable strings during testing:
Avoid copying arbitrary USB vendor/product IDs from examples. Shipping a product requires identifiers and descriptors appropriate to that product.
4. Verify ALSA before opening a DAW¶
Install the packaged tools and Python libraries from Trixie:
Using Debian packages avoids modifying the system Python environment with a global pip install. The gadget port commonly contains MIDI Gadget or f_midi, but do not assume its numeric ALSA address will always be hw:0,0.
Use a raw monitor on the host while sending a known message. This separates USB/ALSA detection from DAW track routing, plugins, audio devices, and speakers.
5. Send a one-second test note with Python¶
Save this as midi_send.py:
Run it without sudo first:
If permissions block access, inspect the device ownership and your audio-group/session configuration instead of routinely running an application as root.
Host and application checklist¶
| Layer | Proof to collect | If it fails |
|---|---|---|
| USB enumeration | Gadget appears in the host USB device list | Check cable, port, power, UDC, and Pi kernel log |
| Host MIDI subsystem | Gadget appears in Audio MIDI Setup, Device Manager/app list, or ALSA | Reconnect once and inspect the host system log |
| Raspberry Pi ALSA | amidi -l lists the gadget endpoint |
Check g_midi, dwc2, and competing gadgets |
| DAW input/output | Correct gadget port is enabled on the intended track | Check monitoring, channel, and MIDI routing |
| Audio output | Synth receives note events and an audio device is selected | Test with a MIDI monitor before changing gadget settings |
Troubleshooting¶
The Pi powers on but the host sees no USB device¶
Replace the cable with a verified data cable and use the correct port. Then collect:
modprobe g_midi reports that the device is busy¶
Another gadget probably owns the UDC. Disable rpi-usb-gadget, a ConfigFS service, or another legacy g_* module rather than trying to load several independent gadget drivers.
MIDI appears in the OS but not in the DAW¶
Restart the DAW after connecting the gadget, explicitly enable the port in its MIDI preferences, and select it on the track. Confirm events with a MIDI monitor before investigating audio latency.
Notes stick on the synthesizer¶
Always send matching note-off messages, handle application shutdown, and provide a local “all notes off” control. A cable disconnect can occur between note-on and note-off.
Latency varies¶
Measure end-to-end latency with a loopback or timestamped physical event. Record the host OS, DAW buffer, audio interface, sample rate, CPU load, and number of runs. Do not change the CPU governor or overclock until the measurement identifies a Raspberry Pi scheduling problem.
FAQ¶
Is USB MIDI audio?¶
No. MIDI carries musical events such as notes and controller values. A synthesizer and audio output are still required to produce sound.
Can the Pi be MIDI and USB Ethernet simultaneously?¶
Yes, but only as a deliberately constructed composite ConfigFS gadget with compatible descriptors and host drivers. Independent g_midi and g_ether modules should not be loaded together.
Does this require a custom driver on the host?¶
The kernel function is intended to expose a standard USB MIDI device. Actual recognition still depends on the host OS, descriptors, cable, and application, so test every supported host.
How do I undo the setup?¶
Remove the g_midi line from /etc/modules, remove or rename its modprobe file, restore the backed-up config.txt, and reboot. Confirm the UDC is no longer bound before enabling another gadget.