Linux USB-Audio Gadget (RPi4 OTG)

"Standard" way to switch a RPi3A+ into device mode is to edit the /boot/config.txt, adding the line
dtoverlay=dwc2,dr_mode=peripheral
It works, but I don't especially like this approach, because it looks so very RPI-specific to me. Therefore my question: Is there a more elegant and general way to do so, a more linux-standard way?

I am sure there must be such a more generic approach, e.g. because of
... usb ports ... setting only one of them to "device", setting one or both to "peripheral" (what's the difference?) or "otg" ...

I e.g. unsuccessfully tried an approach with an /etc/modprobe.d/dwc2.conf file containing the line
options dwc2 dr_mode=peripheral
after which dmesg reported that dwc2: unknown parameter 'dr_mode' ignored

And another question: Is there a way to sense/check for the mode the gadget currently works? I guess there might be some info about this buried deep in either the /sys/... or the /proc/... tree?
 
I'm struggling with another issue now. Something is happening every 90-120 seconds that makes a glitch. The capture from the gadget takes so long that camilladsp goes in stalled state for a second or so. Super annoying! I tried playing around with priorities, digging through logs, and even disabling journals logging, nothing made any difference. Pinning the cpu frequency at max also didn't help. And looking in top (with a faster update rate) while it happens haven't given any useful ideas. Anyone??
 
"Standard" way to switch a RPi3A+ into device mode is to edit the /boot/config.txt, adding the line
dtoverlay=dwc2,dr_mode=peripheral
It works, but I don't especially like this approach, because it looks so very RPI-specific to me. Therefore my question: Is there a more elegant and general way to do so, a more linux-standard way?
Well the whole concept of device trees is pretty device-specific. I don't think there can be any really standardised way.
I e.g. unsuccessfully tried an approach with an /etc/modprobe.d/dwc2.conf file containing the line
options dwc2 dr_mode=peripheral
after which dmesg reported that dwc2: unknown parameter 'dr_mode' ignored
It's apparently possible to switch without rebooting thanks to the dtoverlay tool on rpi os: https://forums.raspberrypi.com/viewtopic.php?t=246348#p1622016

There is a lot of stuff in /sys, for example /sys/class/udc contains links to active gadget ports:
[henrik@quartz ~]$ ls /sys/class/udc/fcc00000.usb
a_alt_hnp_support b_hnp_enable device is_a_peripheral is_selfpowered power srp subsystem
a_hnp_support current_speed function is_otg maximum_speed soft_connect state uevent
 
  • Thank You
Reactions: 1 user
Please try just capturing (no pitch feedback control) a single tone (1khz) with sox with the spectrogram effect. If the spectrogram cuts off at 30 secs, use the -d param. Any data inconsistency is visible on the sox spectrogram, even in longer recordings. That would be a "measurement bench".

What kernel do you use? The dwc3 UDC keeps receiving lots of commits, basically it has been a standard for the last few years https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git/log/drivers/usb/dwc3?h=usb-next
 
"Standard" way to switch a RPi3A+ into device mode is to edit the /boot/config.txt, adding the line
dtoverlay=dwc2,dr_mode=peripheral
It works, but I don't especially like this approach, because it looks so very RPI-specific to me. Therefore my question: Is there a more elegant and general way to do so, a more linux-standard way?
The dr_mode config is part of device tree configuration which is a standard for ARM linux (and possibly more architectures). Legacy module params are not flexible enough for detailed description of hardware without autodetection, therefore the device tree layer was created in 2009 https://elinux.org/Device_tree_history

The RP customarily added the overlays feature which allows to simply modify individual nodes of the DT and is actually quite handy.
I e.g. unsuccessfully tried an approach with an /etc/modprobe.d/dwc2.conf file containing the line
options dwc2 dr_mode=peripheral
after which dmesg reported that dwc2: unknown parameter 'dr_mode' ignored
The dr_mode is read from the device tree, it's not a module parameter https://elixir.bootlin.com/linux/latest/source/drivers/usb/common/common.c#L190
 
  • Thank You
Reactions: 1 user
Please can you compare DSP/float64 performance of that RK3566 board with RPi4B?
Here you go. I just ran the camilladsp benches on both.

Quartz64
Conv/FftConv/1024 time: [117.53 µs 117.84 µs 118.23 µs]
Conv/FftConv/4096 time: [153.89 µs 154.36 µs 154.98 µs]
Conv/FftConv/16384 time: [320.97 µs 322.54 µs 324.31 µs]
Biquad time: [9.0872 µs 9.1085 µs 9.1371 µs]
DiffEq time: [62.437 µs 62.586 µs 62.793 µs]

Pi4
Conv/FftConv/1024 time: [80.919 us 84.411 us 89.103 us]
Conv/FftConv/4096 time: [95.151 us 95.181 us 95.213 us]
Conv/FftConv/16384 time: [177.18 us 177.61 us 178.10 us]
Biquad time: [6.8833 us 6.9015 us 6.9236 us]
DiffEq time: [31.779 us 31.862 us 31.959 us]

Both were running at stock clocks (1.5 GHz for Pi, 1.8 for quartz) and used rustc 1.68. A pretty comfortable win for the pi..
 
Please try just capturing (no pitch feedback control) a single tone (1khz) with sox with the spectrogram effect. If the spectrogram cuts off at 30 secs, use the -d param. Any data inconsistency is visible on the sox spectrogram, even in longer recordings. That would be a "measurement bench".

What kernel do you use? The dwc3 UDC keeps receiving lots of commits, basically it has been a standard for the last few years https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git/log/drivers/usb/dwc3?h=usb-next
I'm running kernel 6.2.5 on the quartz. I'm guessing the sine test will show it working fine for 1-2 minutes, then a short gap, and then fine again for another 1-2 minutes etc. I will test it but I have the pi4 hooked up at the moment, and it runs glitch-free (as usual).
 
Henrik, thanks a lot for the benchmarks. Float64, right?

6.2 is pretty new, that allows reporting to the mailinglist. Actually I have Radxa CM3 with their IO board (also RK3566) , not tested yet, just compiled newer kernel & distro image. I will check the performance after making it run (I do not expect such smooth ride as you had :) ).
 
  • Like
Reactions: 1 user
Everything to set up a linux USB audio DSP gadget using a RPi3A+ along with Raspberry Pi OS 64Bit Lite and CamillaDSP ...
There is an updated version of the HowTo. Main motivation for the rework was the transition from the (deprecated) g_audio kernel module approach to the up-to-date configfs interface method. Some more text and functional tests have been added, also some more polish to some bells and whistles. Sorry that the HowTo now got a bit bloated because of that.
 

Attachments

  • Rpi_USB_Audio_Gadet.pdf
    117.2 KB · Views: 306
  • Like
  • Thank You
Reactions: 2 users
There is an updated version of the HowTo. Main motivation for the rework was the transition from the (deprecated) g_audio kernel module approach to the up-to-date configfs interface method. Some more text and functional tests have been added, also some more polish to some bells and whistles. Sorry that the HowTo now got a bit bloated because of that.
thanks for the guide! i will try to implement it later on a minimal arch rpi4
 
nevermind i got it, it was a error on my side
dietpi is miles more userfriendly and actually lighter on cpu as arch as it seems

tho i still try to figure out how to copy the stream in the most lossless way and preferably allowing dynamic samplerate

currently i use alsaloop
sudo chrt -f 70 alsaloop -d -f S32_LE -S 0 -C plughw:0,0 -P plughw:1,0 -t 50000
but alsaloop seems to be a little quirky... i get sometimes quiet pops and cpu usage seems funky... it uses nearly no cpu but after a while one core goes up to 80-90%

should i maybe try to install pipewire or is there another easy solution like alsaloop?
 
What are you trying to accomplish? This needlessly complicated if you are just copying the stream so I guess you want to do something more.
no, i just wanna copy it for now, im still debating what i should do, a dedicated DDC would be probably a smoother expierence

i kinda just need good pc output, since using fedora/pipewire/easyeffects im really happy with sound quality software-wise but hardware still seems to matter, so i thought i might benefit from going trough the pi with using a rpi hat to get basicly a ddc which i could also use for mpd etc (tho i dont really need it i think if i get "perfect" pc output)

i just tried "desktop pc -> usb -> rpi4 -> usb -> dac" vs "desktop pc -> usb -> dac" today, there is a slight improvement but alsaloop seems to quirky, i also found a cpu load fix, but its a bad one... you have to raise latency quite high (100ms for 48khz and for higher sampling rates you need even more..) and above 100-150ms total latency lipsync starts getting noticeable

one solution might be to try pipewire(pw-loopback) instead of alsaloop?
 
i just tried "desktop pc -> usb -> rpi4 -> usb -> dac" vs "desktop pc -> usb -> dac" today, there is a slight improvement
Are you sure that improvement is not just in your ears? Did you do some blind tests, e.g. with a friend? IMO there is no reason to complicate the USB chain with another computer unless you want to run some DSP on that middle computer.
 
Are you sure that improvement is not just in your ears?
im pretty sure its a real difference its not a big difference tho imagine the difference being resampled vs non-resampled, its not huge but it seems to be there

Did you do some blind tests, e.g. with a friend?
i might do this at some point

IMO there is no reason to complicate the USB chain with another computer unless you want to run some DSP on that middle computer.
well the endgoal is to use something like spdif/rca so a rpi + hat (or a usb bridge, tho a usb bridge mostly uses the same usb implemenation as a dac so a rpi might even be better) so i can avoid usb altogether and get also better clock performance since my dac doesnt have "fancy" clocks and better isolation to the pc

im pretty much speculating since i havent tested for differences here but the endgoal is to improve the pc output where i can do everything i want, even heavy resampling which isnt possible on a pie

but specially before using the fedora/easyeffects/pipewire combo the desktop pc was basicly unusable for good audio compared to a dedicated rpi streamer