Currently I am running Kubuntu x64 14.04 LTS on Asus G750JX laptop and
just until recently had been plagued by exactly the same bug with my
Sound Blaster HD USB. Upgrading to a newer kernel and/or installing the
latest unstable pulseaudio proved to decrease the probability of
triggering the bug, but it just lingered on and didn't want to go.
Luckily I was able to find and test a workaround involving four simple
components: a custom udev rule; a script to be launched upon triggering
this rule; another script to properly load pulseaudio's equalizer
modules; finally a session cleanup script to prevent device lockup on
warm reboot.

After much error and trial I found that the USB Sound Blaster HD would
hang when:

1. ...its corresponding ALSA sink is discovered by pulseaudio while
pulseaudio simultaneously loads various modules. This causes the device
randomly hang on system start.

2. ...its corresponding kernel module snd_usb_audio remains in use at
the moment when the device receives an unbind command. This is even
worse because once triggered, the device preserves its zombie state
across warm reboots (unfortunately few PCs and laptops cycle USB power
during a warm reboot)

3. Physical replugging recovers the device, but at least on a few
occasions I observed the USB hub itself entering an abnormal state after
triggering this bug. Because of this, even physical replugging does not
always help. I had to power down the laptop completely.

I found that the best way to keep the device from hanging is to ensure
that: 1. it remains unmounted until pulseaudio is up and running 2. its
module is unloaded (immediately followed by an unbind command) early
during system shutdown

THE FIX:

1. Create and make executable the following script in your user script
folder:

#######################################

#!/bin/bash

# The following line makes udev behave differently
# depending on whether the rule is triggered before
# or after pulseaudio has started:

if ! $(ps ax | grep [p]ulseaudio > /dev/null )

# So if it's the first time the rule is triggered, let's unload
# the device's kernel module to ensure safe device removal

then

modprobe -r snd_usb_audio

# Now the module is no longer running, so
# we can safely issue an unbind command

echo $1 | tee /sys/bus/usb/drivers/usb/unbind

# Let's wait for pulseaudio to start...

while ! $(ps ax | grep [p]ulseaudio > /dev/null)

do
sleep 1
done

# ...then one extra second to let finish loading modules:

sleep 1

# Now we can safely bind the device:

echo $1 | tee /sys/bus/usb/drivers/usb/bind
fi

# At this point the rule is triggered again and the script
# has a second run, but does nothing so udev just proceeds
# to automatically load the snd_usb_audio module

#######################################

2. Create a udev rule that launches the script upon device discovery,
passing its USB address as an argument:

#######################################

ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="041e",
ATTRS{idProduct}=="30d7", ATTRS{manufacturer}=="Creative Technology",
ATTRS{product}=="USB Sound Blaster HD", RUN+="/home/user/.scripts/load-
usb-audio.sh $attr{busnum}-$attr{devpath}"

#######################################

3. If you are using pulseaudio equalizer, remove these two lines from
/etc/pulse/default.pa:

#######################################

pacmd load-module module-dbus-protocol
pacmd load-module module-equalizer-sink sink_name=equalized

#######################################

Then create and make executable the following script in your user script
folder:

#######################################

#!/bin/bash

# Let's wait until we can say for sure that pulseaudio is running
# and the USB device has been given time to initialize gracefully

while ! $(lsmod | grep [s]nd_usb_audio > /dev/null); do sleep 1; done

# Then another second, otherwise there's
# a slim chance of triggering the bug

sleep 1

# Now we can safely load equalizer modules:

pacmd load-module module-dbus-protocol
pacmd load-module module-equalizer-sink sink_name=equalized

#######################################

Make the above script execute as user upon login. The script must be
aware of the user's pulseaudio session, otherwise it will fail (e.g.
plainly starting it from ~/.profile won't work) In KDE, the best way to
achieve this is to add the script as a 'desktop file' to the Autorun
section in System Settings. Anything added as a 'desktop file' acts the
same as if it were started by the user from their desktop environment,
while 'script file' entries are not aware of user's dbus / pulseaudio
sessions, etc. Other distros may employ different methods so please make
sure pacmd has access to the user's pulseaudio session during script
execution.

4. Lastly, create and make executable the following script in your user
script folder:

#######################################

# let's find the device's USB port:

for f in $(ls -1L /sys/bus/usb/drivers/usb/*/product)

do
if [ "$(cat $f)" == "USB Sound Blaster HD" ]

then
SB_USB="$(echo $f | sed 's/\// /g' | awk '{print $6}')"
fi
done

# Otherwise no graceful ALSA shudown:
killall pulseaudio 

# Otherwise no permission to unload driver module:
alsa force-unload 

# Doing this before unbinding device saves the day:
modprobe -r snd_usb_audio 

# For a safer world better do this:
echo $SB_USB | tee /sys/bus/usb/drivers/usb/unbind 

#######################################

Make this run with root privileges as early during shutdown as possible.
With Kubuntu's default session manager, LightDM, the best way to achieve
this is to call the script from a session cleanup script defined in
/etc/lightdm/lightdm.conf (google 'lightdm.conf session-cleanup-script'
if unfamiliar)

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1191898

Title:
  [USB-Audio - USB Sound Blaster HD, playback] fails after reboot

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/1191898/+subscriptions

-- 
ubuntu-bugs mailing list
ubuntu-bugs@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to