balena sound DAC disconnects and doesn't reconnect

I’m using a Raspberry Pi 3 with two USB DAC/amps from Aune, the T1 and the X1 Pro. Both units power down their DAC when switched off, causing a USB disconnect from the Raspberry Pi. (By contrast, a unit like the O2+ODAC keeps the DAC powered via USB).

These are the messages I get in the audio service when the device is disconnected:

 audio  E: [alsa-sink-USB Audio] alsa-sink.c: snd_pcm_avail: No such device, trying to restart PCM
 audio  E: [alsa-sink-USB Audio] alsa-sink.c: Error opening PCM device front:0: No such file or directory

This is what is detected on startup of the audio service:

 audio  - pulseaudio 13.0
 audio  - Pulse log level: NOTICE
 audio  - Default output: AUTO
 audio  
 audio  Detected audio cards:
 audio  0 usb-soundcard-0 USB-Audio-DigiHugUSBAudio

I’m able to reconnect to the USB DAC with a restart of the audio service. I’m wondering if there’s a way to configure the audio service to re-detect devices when a new device is connected, or to restart the service automatically when this happens. Otherwise if I power down the DAC/amp, I lose the connection to balena-sound until I restart the audio service.

Thanks!

I’ve been doing a bit of research here, and I have a temporary solution, but I’d like to understand more why pulseaudio doesn’t recover correctly with the audio service.

It appears when a USB DAC is disconnected and reconnected, pulseaudio should be using module-udev-detect to find the USB audio device again, but pactl list sinks or pactl list cards doesn’t show the device. Unloading and reloading the module-udev-detect manually does at least restore the card in pulseaudio, but it’s no longer the default sink.

I wonder if some of Pottering’s concerns about udev rules might lead to a “correct” solution long-term. He complains here about how changes to udev rules can cause module-udev-detect to not function correctly, and I wonder if the udev rules in the audio service are inadvertently causing this.

I’ve added a file called 96-udev-redetect.rules to /etc/udev/rules.d/ in the audio service that looks like this:

SUBSYSTEM!="sound", GOTO="udev_redetect_end"
ACTION!="change", GOTO="udev_redetect_end" 

DRIVERS=="snd-usb-audio", RUN+="/bin/sh -c 'pactl unload-module module-udev-detect && pactl load-module module-udev-detect && pactl set-default-sink `cat /run/pulse/pulseaudio.sink`'"

LABEL="udev_redetect_end"

It’s a hack, but when a device that uses the snb-usb-audio driver is connected, it kicks pulseaudio to redetect the device, then sets whatever is in /run/pulse/pulseaudio.sink to be the default sink. Alternately, it could be forced back to be sink 0. The script start.sh seems to think this file should always exist.

All this said, I don’t think this will work if the DAC isn’t connected and powered at boot (otherwise the name in pulseaudio.sink may be blank or the file nonexistant). A better thought would be to take all the sinks and identify the USB one and use its name/index as the default sink. It’s at best a hack fix for now that will have to be reapplied any time the device is reset or updated.

If you do decide to use it, you’ll likely have to get the rules into udev by restarting it. I used this: udevadm control --reload-rules && udevadm trigger. Alternately, you can restart the audio service.

Hi @jedcred, sorry for the delayed response. I’ve been giving this a good look and investigating a bit, this problem is really unique!

For starters, I think your initial assessment is spot on, it seems PulseAudio is not handling well the udev reconnection events. Why is that is still a mystery to me. I wouldn’t take Pottering’s concerns at face value in this case as they are 12 years old at this point, and even then the changes made by our udev rules are not substantial, almost aesthetic.

Here are some things you could try that maybe would shed some light on this problem:

  • Remove the udev rule and see what happens. Some functionality of the audio block won’t work but basic PulseAudio commands should be fine, you can inspect using pactl list sinks, etc.
  • Capture udev events that get fired when you flip the DAC on and off (udevadm monitor to capture)
  • What happens if you start the audio service with the DAC not connected but turned on and connect it with the service running? Does that work? Would be useful if you can capture those udev events too.
  • Try a more recent PulseAudio version. Currently we are on v13 but I have a branch that is on v15 you could try (GitHub - balenablocks/audio at 84-bump-pa-version). I’ve skimmed through the changelog and didn’t notice anything related to udev module, but perhaps this is a bug that is not present in recent versions.

The solution you propose could work but as you say it’s a bit hacky, which I wouldn’t mind except for the problems you mention. We would need to patch many things to accommodate this hack so I’m a bit uncertain of it. I’ll keep thinking about this and see if something clicks. Let me know if you end up trying any of the suggestions above. Cheers!

Another thing you could try is increasing the log level: GitHub - balenablocks/audio: Audio building block, based on pulseaudio.

Okay, so something weird I found out.

It seems that hot-plugging USB devices doesn’t work in PulseAudio if there were no USB devices connected when it was started. ALSA and udev have no problem detecting the devices and loading up the sound cards, but PulseAudio won’t unless there was a USB device connected when it started. I’m not sure why this is the case however it seems there is some funky business going on with udev events and audio (see pulseaudio/module-udev-detect.c at 5b000acb1a3677c71dcccf7ecd6d76c89bb3a7a0 · pulseaudio/pulseaudio · GitHub and 78-sound-card.rules\rules - systemd/systemd - System and Session Manager).

I don’t have the bandwidth at the moment to keep investigating but I just created a GitHub issue to dump this information and will go back to it in the future (PulseAudio doesn't detect USB hot-plugging if no USB device was connected at startup · Issue #85 · balenablocks/audio · GitHub)