Linux USB-Audio Gadget (RPi4 OTG)

Where ist the best place to get the most concise and most up-to-date informations about all these changes?
E.g. https://github.com/torvalds/linux/blob/master/Documentation/usb/gadget-testing.rst or configfs--usb-gadget-xxx files in https://github.com/torvalds/linux/tree/master/Documentation/ABI/testing

The 3rd line of this link is somewhat irritating however, and maybe misleading also. Because the link refers to 6.2, but the text reads ...
... "Date: 20. August 2004" ... ???
That file is a gadget coding hint, I do not think anyone cares much about that file and nobody bothered to update it (apart of a few formatting changes https://github.com/torvalds/linux/commits/master/Documentation/driver-api/usb/gadget.rst ). New composite functions are created with code/inspiration from the existing ones.
 
  • Thank You
Reactions: 1 user
I'm playing a bit with gadget mode on a Pine Quartz64 A board (link: https://www.pine64.org/quartz64a/)
This uses the dwc3 usb controller (instead of dwc2 on the pi4). I'm running Manjaro with kernel 6.2.5.

First it was a bit of a pain to get the gadget to work at all. I needed to modify the device tree, specifically these two commands:
sudo fdtput -t s -v /boot/dtbs/rockchip/rk3566-quartz64-a-otg.dtb /usb@fcc00000 dr_mode device
sudo fdtput -t s -v /boot/dtbs/rockchip/rk3566-quartz64-a-otg.dtb /usb@fd000000 dr_mode device
where /boot/dtbs/rockchip/rk3566-quartz64-a-otg.dtb is a copy of the standard /boot/dtbs/rockchip/rk3566-quartz64-a.dtb

IIUC this should enable th gadget on two separate usb ports, but only one of them works. I have tried countless other combinations like setting only one of them to "device", setting one or both to "peripheral" (what's the difference?) or "otg", but nothing else works.

Right now it works, but with a bunch of problems.
It only works at 16 bits. Trying 32 bits (S32_LE) gives stuttering garbage. I haven't tried 24 bits but I'm not really optimistic about that.
I can only get it to work on Windows. A linux box finds it but playback fails. A mac doesn't find it at all.

Another problem is that I'm missing the capture pitch adjust:
$ amixer controls
numid=2,iface=MIXER,name='PCM Playback Switch'
numid=3,iface=MIXER,name='PCM Playback Volume'
numid=5,iface=MIXER,name='PCM Capture Switch'
numid=6,iface=MIXER,name='PCM Capture Volume'
numid=7,iface=PCM,name='Capture Rate'
numid=1,iface=PCM,name='Playback Pitch 1000000'
numid=4,iface=PCM,name='Playback Rate'
Where is my "Capture Pitch 1000000"?

So I kindof have it working a little bit, but it's not good enough to use for anything. Anyone have any ideas for things to try?
 
Update on that, it seems I was somehow using the uac1 gadget, not uac2.
New try via configfs, using this script (adapted from here: https://forums.raspberrypi.com/viewtopic.php?t=333504):
#!/bin/sh

# USB Audio configuration:
AUDIO_CHANNEL_MASK=3
AUDIO_SAMPLE_RATES=44100
AUDIO_SAMPLE_SIZE=4

# Load libcomposite
modprobe libcomposite

# Create a gadget called usb-gadgets
cd /sys/kernel/config/usb_gadget/
mkdir -p usb-gadgets
cd usb-gadgets

# Configure our gadget details
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
mkdir -p strings/0x409
echo "0123456789abcdef" > strings/0x409/serialnumber
echo "Z Engineering" > strings/0x409/manufacturer
echo "Z Audio" > strings/0x409/product

mkdir -p configs/c.1/strings/0x409

# UAC2 (audio) gadget
# attributes from: https://www.kernel.org/doc/Documentation/ABI/testing/configfs-usb-gadget-uac2
mkdir -p functions/uac2.usb0
echo $AUDIO_CHANNEL_MASK > functions/uac2.usb0/c_chmask
echo $AUDIO_SAMPLE_RATES > functions/uac2.usb0/c_srate
echo $AUDIO_SAMPLE_SIZE > functions/uac2.usb0/c_ssize
echo $AUDIO_CHANNEL_MASK > functions/uac2.usb0/p_chmask
echo $AUDIO_SAMPLE_RATES > functions/uac2.usb0/p_srate
echo $AUDIO_SAMPLE_SIZE > functions/uac2.usb0/p_ssize
ln -s functions/uac2.usb0 configs/c.1/

# End functions
ls /sys/class/udc > UDC

This works much better. 16&32 bit both work, and the capture pitch is back. Works on windows and linux, only the mac doesn't like it.
 
Update on that, it seems I was somehow using the uac1 gadget, not uac2.
The gaudio module is basically a hard-coded composite configuration, which picks the audio function based on kernel configs
https://github.com/torvalds/linux/b...5/drivers/usb/gadget/legacy/audio.c#L268-L277 . The module offers only some of the composite config options via its module params. The gaudio module is deprecated (configfs is the preferred way) and kernel admins do not welcome new features to that module (typically adding new parameters).

Most likely your kernel config has the option CONFIG_GADGET_UAC1 enabled. Typically distributions include the kernel configs in /boot/config-CURRENT_KERNEL_VERSION, that's often handy to check.
 
  • Like
Reactions: 1 user
I probably did something wrong before, there is no need to touch usb@fd000000. This is enough:
sudo fdtput -t s -v /boot/dtbs/rockchip/rk3566-quartz64-a-otg.dtb /usb@fcc00000 dr_mode otg
And the mode should be "otg" and nothing else, "device" is not a valid option and makes it revert to the default which happens to be "otg".

This quartz board is somehow configured so that it can't auto-switch between host and device (read something about some pin that should have been connected for that to work). Selecting "otg" makes the port device only.

Now let's see if I can get this to start on boot..
 
All set up! I'm listening to spotify on windows -> usb to quartz64 (with camilladsp capturing from the gadget) ->usb to Motu M4. It has been nice and stable for an hour or so.
The gadget configfs is set up by a systemd service at boot. Camilladsp also runs as a systemd service that is started by a udev rule when the dac connects.
 
...
# Configure our gadget details
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
...


And collabora.com says ...
...
0x1d6b is for Linux Foundation and 0x0104 is for Ethernet Gagdet. If your USB host sees such ids it assumes it needs the cdc_ether host-side driver.
...

So declaring ...

echo 0x0104 > idProduct # Multifunction Composite Gadget

... as advocated in the raspberry forum and applyed by Henrik then would make the host providing the cdc_ether driver. But we have an audio gadget here. Is this really the perfect match ??? I think there might be another, specific idProduct code for an audio gadget? Or not?
 
IMO the product ID in this case does not mark any driver, if the device complies with standard USB functions and does not require a custom driver (which could be tied to the specific PID).

Yes, it's true Linux Foundation has put a few PIDs into the USB database https://the-sz.com/products/usbid/index.php?v=0x1D6B but IMO these are not critical. Linux Foundation has no custom drivers for windows, OSX etc.
 
Thank you for the link and your comments. So, peeping into your link

0x0104 stands for a Multifunction Composite Gadget (which might include ethernet as well as audio)
and instead
0x0101 would stand for the specific Audio Gadget

Well then, let's go along with the RaspiPibians and with Henrik for ID 0x0104 which seems perfect for our maybe multifunctional audio needs.
 
0x0104 stands for a Multifunction Composite Gadget (which might include ethernet as well as audio)
and instead
0x0101 would stand for the specific Audio Gadget

Well then, let's go along with the RaspiPibians and with Henrik for ID 0x0104 which seems perfect for our maybe multifunctional audio needs.
IMO the PID really does not matter, if the USB descriptor contains valid standard USB functions for which built-in drivers of the OS exist.

IIUC the issue is with windows which caches the combination VID+PID+firmware_version (bcdDevice) for a particular USB driver. If the functionality changes, some of it needs to be changed to restart driver installation.

See the notes in https://github.com/RoganDawes/P4wnP1/search?q=pid https://github.com/RoganDawes/P4wnP...c07caab8b7/payloads/stickykey/trigger.txt#L30
 
  • Thank You
Reactions: 1 user