USB audio devices on FreeBSD
Update 2024-04-16: The issue with suspend described below should be fixed by this recent commit to FreeBSD (which should be available in a RELEASE version soon). Thank you to Christos Margiolis for the patch, and for bringing it to my attention!
I recently got a Behringer UMC22 sound card for video conferencing and DJing. This page documents what I've learned about using this sound card, and USB audio in general, on FreeBSD.
tl;dr: Everything works as long as the sound card follows the USB audio device class specification.
Hardware support
Which USB sound cards are supported in FreeBSD? The hardware notes don't list USB sound cards, and neither does the manual page for the corresponding driver, snd_uaudio (4)
. Inspecting the source code for the snd_uaudio
driver lists some cards that require custom tweaks, but a complete list isn't present.
Hardware support for USB sound cards appears to be based on compliance with the USB audio device class specification, rather than on specific chipsets or models.
How can you verify whether a USB audio device is compliant with the specification? In the case of the UMC22, the chip used is the TI PCM 2902. The specifications for the PCM2902 chipset say somewhat ambiguously that "the whole board design should be considered to meet the USB specification as a USB-compliant product" and indicate that the interface communicates through a "the standard USB request and USB audio class specific request". There doesn't appear to be an explicit statement, but it is implied that the chipset is compliant with the USB audio device class specification. The same chipset is apparently used in other Behringer sound cards such as the UM2, UA222, UCA222, and UCA202.
Using the sound card
When connected to a FreeBSD machine, dmesg
shows that the UMC22 is recognized by the uaudio
driver. Note the string identifying the PCM2902 chipset from the spec sheet ("Burr-Brown from TI"):
uaudio0 on uhub1
uaudio0: <Burr-Brown from TI USB Audio CODEC, class 0/0, rev 1.10/1.00, addr 2> on usbus0
uaudio0: Play: 48000 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 44100 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 32000 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Record: 48000 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Record: 44100 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Record: 32000 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Record: 22050 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Record: 16000 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Record: 11025 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
uaudio0: No MIDI sequencer.
pcm3: <USB audio> on uaudio0
uaudio0: HID volume keys found.
The available sound devices can be listed using cat /dev/sndstat
, which shows that the sound card is recognized for both playback and recording (here at pcm3):
Installed devices:
pcm0: <Realtek (0x0257) (Analog 2.0+HP/2.0)> (play/rec) default
pcm1: <Realtek (0x0257) (Right Analog Mic)> (rec)
pcm2: <Intel Kaby Lake (HDMI/DP 8ch)> (play)
pcm3: <USB audio> (play/rec)
No devices installed from userspace.
How can the sound card be set as the playback device? Some programs, such as mixxx or Audacity, allow setting the output device in their preferences. Other programs will only use the default output device, which can be set using: sysctl hw.snd.default_unit=3
with the appropriate number for the device (in this case, pcm3
= 3).
The device number shown in /dev/sndstat
corresponds to the device number under /dev/dsp
and /dev/mixer
. For example, to view the volume levels on the sound card with mixer (8)
, you would use: mixer -f /dev/mixer3
To set the volume, you would use a command such as: mixer -f /dev/mixer3 vol 75
(If the sound card has been set as the default device, there is no need to specify the device in the mixer
command).
Challenges
If an application is playing audio from the sound card when the system goes into a suspend state, the system will get stuck until all programs using the sound card close the corresponding device nodes, with a series of messages like this on the console:
pcm3: unregister: channel pcm3:virtual:dsp3.vp0 busy (pid 45989)
pcm3: Waiting for sound application to exit!
These messages will continue to repeat until the application releases the audio device, at which point the system will finally be able to enter suspend state.
To work around this, I currently set the default audio device back to ID 0 as part of my pre-suspend script. This will prevent an application using the default device (such as Firefox) from preventing suspend.
However, for applications that set the audio device explicitly, this doesn't work. In fact, they'll often keep the audio device open even when audio isn't playing, hanging the suspend process and eventually forcing a reboot.
To allow suspend to continue, I use my pre-suspend script to just quit any program that has the sound card open before suspend:
# Close up the USB sound card before suspend
sysctl hw.snd.default_unit=0
# Close any programs still using the sound card
while fstat | grep dsp3 2>&1; do
fstat | grep dsp3 | cut -w -f 3 | while read pid;
do kill -15 "$pid"
done
done
while [ "$(ls -l /dev | grep -c dsp3)" -gt 1 ]; do
sleep 1
done