#!/bin/sh SCAN_PERIOD=5 AUTOTRUST=false #trust every newly paired device AUTOSCAN=true #immediately start scanning when started to speed up pairing process #locations of blacklist and hard coded list of paired devices (watch out, need to modify Makefile as well if you want to change these values and still use make install) BLACKLIST=${XDG_DATA_HOME:-$HOME/.local/share}/bt/blacklist PAIRLIST=${XDG_DATA_HOME:-$HOME/.local/share}/bt/paired actions="pair unpair" [ "$AUTOTRUST" = false ] && actions="${actions} trust" #Checks for necessary programs to be present. Very unlikely not to be present but let's just err on the safer side. for prog in dmenu bluetoothctl awk cat date nl; do if ! hash "$prog" 2>/dev/null; then printf 'bthandler: %s: command not found\n' "$prog" >&2 exit 127 fi done power(){ powerstatus="$( bluetoothctl show | grep Powered | awk '{print $2}' )" [ "$powerstatus" = "no" ] && [ "$1" = on ] && bluetoothctl power on [ "$powerstatus" = "yes" ] && [ "$1" = off ] && bluetoothctl power off } scan(){ scanstatus="$( bluetoothctl show | grep Discovering | awk '{print $2}' )" if [ "$1" = on ]; then #sets variable in case scanning was no already on before the start of bt [ "$start_scan" = "" ] && start_scan="$( date +'%s' )" if [ "$scanstatus" = "no" ]; then bluetoothctl scan on & start_scan="$( date +'%s' )" fi elif [ "$1" = off ]; then if [ "$scanstatus" = "yes" ]; then bluetoothctl scan off fi fi } #Check bluetoothctl paired-devices for new devices to be hardcoded into pair list update_pair_list(){ btctl_paired_devices="$(bluetoothctl paired-devices)" if [ -n "$btctl_paired_devices" ] then btctl_not_in_list="$( echo "$btctl_paired_devices" | grep -vf "$PAIRLIST")" [ -n "$btctl_not_in_list" ] && echo "$btctl_not_in_list" >> "$PAIRLIST" fi } #start scanning as early as possible to speed up pairing process #In function to more quickly display the menu startup(){ if $AUTOSCAN then power on scan on fi } #Sadly needs to be run without '&' for now, since it otherwise breaks start_scan variable startup update_pair_list & # shellcheck disable=SC1091 if bluetoothctl devices | awk '{print "bluetoothctl info "$2}' | . /dev/stdin | grep -q "Connected: yes" then actions="$(printf "disconnect\n%s" "$actions")" fi #Compile list of all Bluetooth IDS of paired devices (from bluetoothctl and from hardcoded list) bt_IDS="$( ( bluetoothctl paired-devices && cat "$PAIRLIST" ) | sort -u | awk '{print $2}' )" #Compile list of all device Names of paired devices (from bluetoothctl and from hardcoded list) paired_devices="$( ( bluetoothctl paired-devices && cat "$PAIRLIST" ) | sort -u | awk '{for (i=3; i /tmp/paired_devices$$ filtered_devices="$( echo "$all_devices" | grep -v "$paired_devices")" bt_IDS="$( echo "$filtered_devices" | awk '{print $2}' )" new_devices="$( echo "$filtered_devices" | awk '{for (i=3; i> "$PAIRLIST" fi fi fi } case $choice in "power on") bluetoothctl power on;; "power off") bluetoothctl power off;; "scan on") bluetoothctl power on && echo power on && sleep 2 ([ -n "$TERMINAL" ] && $TERMINAL -e bluetoothctl scan on ) || st bluetoothctl scan on;; "pair") pair;; "unpair") choice=$( echo "$paired_devices" | dmenu -l 10 -i -p 'remove which paired device?') if [ -n "$choice" ]; then dev_no=$( echo "$paired_devices" | nl | grep -P "[0-9]+\t$choice$" | awk '{print $1}') dev_id=$( echo "$bt_IDS" | nl | grep -P "^.*$dev_no\t" | awk '{print $2}' ) bluetoothctl remove "$dev_id" #remove device to unpair from hard coded paired devices list new_paired_list="$( grep -v "$dev_id" "$PAIRLIST" )" if [ "$new_paired_list" != "" ] then echo "$new_paired_list" > "$PAIRLIST" else rm -rf "$PAIRLIST" touch "$PAIRLIST" fi fi;; "trust") #search through all devices which are connected and only list those as options # shellcheck disable=SC1091 untrusted_devices="$( awk '{print "bluetoothctl info "$2}' "$PAIRLIST" | . /dev/stdin | grep -E '(Alias:|Trusted:)' | sed -e 'N;s/\n/;/;s/^.?*Alias: //' | grep "Trusted: no" | awk -F ';' '{print $1}' )" if [ "$( echo "$untrusted_devices" | wc -l )" -gt 0 ] then choice=$( echo "$untrusted_devices" | dmenu -l 10 -i -p 'remove which paired device?') else notify-send "Bluetooth" "No paired devices that are not trusted" fi if [ -n "$choice" ]; then dev_no=$( echo "$paired_devices" | nl | grep -P "[0-9]+\t$choice$" | awk '{print $1}') dev_id=$( echo "$bt_IDS" | nl | grep -P "^.*$dev_no\t" | awk '{print $2}' ) bluetoothctl trust "$dev_id" fi;; "disconnect") #search through all devices which are connected and only list those as options # shellcheck disable=SC1091 connected_devices="$( bluetoothctl devices | awk '{print "bluetoothctl info "$2}' | . /dev/stdin | grep -E '(Alias:|Connected:)' | sed -e 'N;s/\n/;/;s/^.?*Alias: //' | grep "Connected: yes" | awk -F ';' '{print $1}' )" #only open dmenu prompt if there is more than one connected device if [ "$( echo "$connected_devices" | wc -l )" -gt 1 ] then choice=$( echo "$connected_devices" | dmenu -l 10 -i -p 'remove which paired device?') else choice="$connected_devices" fi #only there was a choice (instead of canceling the dmenu) if [ -n "$choice" ]; then dev_no=$( echo "$paired_devices" | nl | grep -P "[0-9]+\t$choice$" | awk '{print $1}') dev_id=$( echo "$bt_IDS" | nl | grep -P "^.*$dev_no\t" | awk '{print $2}' ) bluetoothctl disconnect "$dev_id" fi;; "blacklist") choice=$( echo "$paired_devices" | dmenu -l 10 -i -p 'blacklist which paired device from selection?') if [ -n "$choice" ]; then echo "$choice" >> "$BLACKLIST" fi;; *) dev_no=$( echo "$paired_devices" | nl | grep -P "[0-9]+\t$choice$" | awk '{print $1}') [ "$dev_no" != "" ] && dev_id=$( echo "$bt_IDS" | nl | grep -P "^.*$dev_no\t" | awk '{print $2}') if [ -n "$dev_id" ]; then power on bluetoothctl pair "$dev_id" bluetoothctl connect "$dev_id" fi;; esac