Fixing the hard lockup caused by bluetooth in linux during sleep

  • May 24, 2012
Table of Contents

I basically stopped using the bluetooth subsystem on my machine for a while, since it would lockup my system during sleep. Today I decided to investigate a little, here’s what I found out:

  1. Stopping the bluetooth daemon will bring down the bluetooth subsystem. You can check it’s state as follows:
    cat /sys/module/btusb/refcnt
    anything besides 0 means it’s doing something.
  2. The freeze occurs when bluetooth is paired with a device and someone trys to bring down bluetooth. Subsequently playing music through A2DP and then stopping the bluetooth daemon results in a hard freeze.
  3. To fix all these issues you need to disconnect all connected bluetooth devices before going to sleep.

Copy & paste the following script (or simply download ) in your /etc/pm/sleep.d folder to fix the freeze. Feel free to adapt it to your distribution.

#!/bin/sh
# generic bluetooth hack based on the IBM specific hack
# Reza Jelveh

. "${PM_FUNCTIONS}"

[ -f /sys/module/btusb/refcnt ] || exit $NA

disconnect_devices()
{
	# sorry not that good with bash scripting,
	# so i'll use a space as string terminator
	var="`hcitool con` "

	while test -n "$var";do
		res="${var%% *}"
		var="${var#* }"
		if [[ $res =~ ([[:alnum:]:]{17}) ]]; then sudo hcitool dc ${BASH_REMATCH[0]}; fi
	done
}

suspend_bluetooth()
{
	if grep -q 0 /sys/module/btusb/refcnt; then
		savestate bluetooth_generic disable
	else
		savestate bluetooth_generic enable
		# if we run stop while some bluetooth device is running
		# the system will freeze, disconnect all devices first
		disconnect_devices
		/usr/sbin/rc.d stop bluetooth

		# wait for up to 2 seconds for the module to actually get
		# unused
		TIMEOUT=20
		while [ $TIMEOUT -ge 0 ]; do
		    [ `cat /sys/module/btusb/refcnt` = 0 ] && break
		    TIMEOUT=$((TIMEOUT-1))
		    sleep 0.1
		done
		/sbin/modprobe -r btusb
	fi
}

resume_bluetooth()
{
	state_exists bluetooth_generic || return
	if [[ `restorestate bluetooth_generic` == "enable" ]]; then
		/sbin/modprobe btusb
		/usr/sbin/rc.d start bluetooth
	fi
}

case "$1" in
	hibernate|suspend)
		suspend_bluetooth
		;;
	thaw|resume)
		resume_bluetooth
		;;
	*) exit $NA
		;;
esac
comments powered by Disqus

Related Posts

Changing the cursor color within tmux based on vi mode

As outlined on SE and SU you can execute actions in zsh when you change between normal and insert mode in a vi mode zsh session.

Read More

Proper snippets for vim... wooohoooo!

For a very long time vim has had only snippets plugins, which were using nasty regex hacks to get TextMate like snippets going…

Read More

A minimalistic rfkill gtk gui for toggling your bluetooth and wireless

I just wrote a little rfkill frontend with gtk+. If you use an acer laptop you should load acer-wmi, make sure you have acpi_osi=Linux in your kernel boot.

Read More