Thursday, October 23, 2014

linux - bluetoothctl “Waiting to connect to bluetoothd…” in udev rule script



I have the following udev rule:



ACTION=="add", SUBSYSTEM=="bluetooth", RUN+="/usr/local/bin/a2dp-fix-wrapper"


that fires off the following script:



PID=$(pgrep pulseaudio)

USER=$(grep -z USER= /proc/$PID/environ | sed 's/.*=//')
USER_ID=$(id -u $USER)
HOME=$(echo $(getent passwd $USER )| cut -d : -f 6)

export XDG_RUNTIME_DIR=/run/user/$USER_ID
export XAUTHORITY=$HOME/.Xauthority
export DISPLAY=:0
export PULSE_RUNTIME_PATH=$XDG_RUNTIME_DIR/pulse/

sleep 5


sudo -u $USER -E /usr/local/bin/a2dp-fix &> /udev_output.txt


and a2dp-fix is the following:



bt_device_addr=$(pacmd list-cards | grep -i 'name:.*bluez_card' | sed -E 's/.*?/\1/')
device_mac=$(echo $bt_device_addr | sed 's/_/:/g')

a2dp_available=$(pacmd list-cards | grep -A30 bluez | grep "A2DP Sink" | sed -E 's/.* available: ([a-z]+)\)/\1/g')


if [[ "$a2dp_available" == "no" ]]
then
echo -e "connect $device_mac\nquit" | bluetoothctl
sleep 5
pacmd set-card-profile bluez_card.$bt_device_addr off
pacmd set-card-profile bluez_card.$bt_device_addr a2dp_sink
pacmd set-default-sink bluez_sink.$bt_device_addr.a2dp_sink
fi



After lots of meddling with env variables, I got the pacmd stuff to work. However, now the bluetoothctl part hangs with “Waiting to connect to bluetoothd…”. This works just fine if I invoke it manually from shell with sudo /usr/local/bin/a2dp-fix-wrapper but not when udev kicks it off. I imagine it must be some sort of env variable that prevents bluetoothctl from finding the running bluetoothd instance.



Anyone have any thoughts?


Answer



After a long time, I decided to give this another try and finally got it to do what I want using dbus instead of bluetoothctl.



I tried a few things that didn't work. Instead of echo -e "connect $device_mac\nquit" | bluetoothctl I tried:



coproc bluetoothctl

echo -e "select E4:B3:18:48:43:D2\nconnect $device_mac\nquit" >&${COPROC[1]}
output=$(cat <&${COPROC[0]})
echo $output


I also tried:



hcitool cc $device_mac



And I also tried a couple of python scripts, but ultimately, using dbus-send solved my problem.



My scripts are as follows:



/etc/udev/rules.d/80-bt-headset.rules



ACTION=="add", SUBSYSTEM=="bluetooth", RUN+="/usr/local/bin/a2dp-fix-wrapper"


/usr/local/bin/a2dp-fix-wrapper




#!/bin/bash

for PID in $(pgrep pulseaudio); do
USER=$(grep -z USER= /proc/$PID/environ | sed 's/.*=//' | tr -d '\0')
USER_ID=$(id -u $USER)
HOME=$(echo $(getent passwd $USER )| cut -d : -f 6)

export XDG_RUNTIME_DIR=/run/user/$USER_ID
export XAUTHORITY=$HOME/.Xauthority

export DISPLAY=:0

sleep 5
if [[ ! -z $USER ]]; then
sudo -u $USER -E /usr/local/bin/a2dp-fix
fi
done


/usr/local/bin/a2dp-fix




#!/bin/bash

bt_device_addr=$(pacmd list-cards | grep -i 'name:.*bluez_card' | sed -E 's/.*?/\1/')
device_mac=$(echo $bt_device_addr | sed 's/_/:/g')

a2dp_available=$(pacmd list-cards | grep -A30 bluez | grep "A2DP Sink" | sed -E 's/.* available: ([a-z]+)\)/\1/g')

if [[ "$a2dp_available" == "no" ]]
then

dbus-send --system --dest=org.bluez --print-reply /org/bluez/hci0/dev_$bt_device_addr org.bluez.Device1.Connect

pacmd set-card-profile bluez_card.$bt_device_addr off
pacmd set-card-profile bluez_card.$bt_device_addr a2dp_sink
pacmd set-default-sink bluez_sink.$bt_device_addr.a2dp_sink
fi


Now my bluetooth headset always connects using the a2dp sink :-D




Big thanks to this post for the inspiration.


No comments:

Post a Comment

linux - How to SSH to ec2 instance in VPC private subnet via NAT server

I have created a VPC in aws with a public subnet and a private subnet. The private subnet does not have direct access to external network. S...