Integrating Bose's QuietComfort 35 II into Linux
This article demonstrates how to connect the QuietComfort 35 II wireless headphones within Arch Linux, persisting the connection and integrating them within the i3 window manager. Although the instructions revolve around Arch, I’m sure they can be easily adapted to work with any other distribution or OS that is similar enough.
Logo of Arch Linux and photograph of the Bose QuietComfort 35 II
Connection setup
Installing prerequisites
First of all it is required to connect the device through Bluetooth. To secure this connection in a comfortable way, pairing is needed to be performed first. The following sections require you to install the required libraries:
root@host # pacman -S bluez-tools bluez-utils
Deactivate Bluetooth LE
As stated in this helpful note, the Bose QuietComfort 35 II may have problems pairing, when using Bluetooth LE on Linux.
To temporarily disable it, the following line needs to be added to /etc/bluetooth/main.conf
:
ControllerMode = bredr
Afterwards the Bluetooth service has to be restarted:
root@host # systemctl restart bluetooth
Pairing device
To now pair your device you need to slide the Power/Bluetooth button to the right and hold for two seconds as instructed by the manual. The headphone is now in pairing mode.
Illustration of the headphones’ buttons: It displays the usage of the power & Bluetooth button for pairing and how the LED behaves. It was extracted from the official manual.
Following the very helpful Arch wiki page you can pair by using the command line by using the program bluetoothctl
:
[bluetooth]# power on
[bluetooth]# agent on
[bluetooth]# default-agent
[bluetooth]# scan on
You should now see your headphones pop up with either the default name or the one you have given them earlier using the Bose Connect application on Android or iPhone, along with their Bluetooth device address (BD_ADDR
):
[NEW] Device XX:XX:XX:XX:XX:XX Bose QuietComfort 35 II
The BD_ADDR
of XX:XX:XX:XX:XX:XX
should be adapted to your specific address.
You then need to pair the device and connect to it, also trusting it allows for easier reconnects later:
[bluetooth]# pair XX:XX:XX:XX:XX:XX
[bluetooth]# connect XX:XX:XX:XX:XX:XX
[bluetooth]# trust XX:XX:XX:XX:XX:XX
When connected the headphones should spell your hostname
.
It is now possible to revert the changes to the /etc/bluetooth/main.conf
configuration file and restart the Bluetooth service, to use Bluetooth LE again.
Auto-connect
For not having to reconnect manually each time using connect
within bluetoothctl
adding the following line to your /etc/pulse/default.pa
will remedy this problem:
load-module module-switch-on-connect
Afterwards, it is needed to restart PulseAudio:
user@host $ pulseaudio -k
After killing PulseAudio, the automatically reconnected headphones had bad sound. I assume this is because of an error of their Bluetooth LE usage. If this happens, simply turning them off and on again helps. You need to either manually enable Bluetooth after a reboot, automatically enable it, or follow this article to enable Bluetooth only on demand. The latter option is recommended, because of its lower energy consumption.
Using multimedia buttons
As can be seen on the photograph below, the headphones have multiple buttons used for controlling noise cancellation modes and volume. There is also a dedicated button for playback in the center of the three buttons on the right earpiece.
Illustration of the headphones’ buttons: the multimedia button is highlighted in dark grey. It was extracted from the official manual and modified slightly.
For multimedia buttons on the headphones to be recognized as input, it is needed to enable them first by creating the file /etc/modules-load.d/uinput.conf
containing:
uinput
Integration in i3
Setting up hotkeys
With a connected pair of heaphones, the information from the manual and a running instance of xev
, the following table can be constructed:
Button | Action | Keycode |
---|---|---|
Single press | Play/Pause | XF86AudioPlay |
Double press | Next Track | XF86AudioNext |
Triple press | Previous Track | XF86AudioPrev |
Double press, hold last | Seek forward | XF86AudioForward |
Triple press, hold last | Seek backward | XF86AudioRewind |
With this information we can now add the following bindings to our i3 configuration in ~/.config/i3/config
to control mpd with the hotkeys:
bindsym XF86AudioPlay exec "mpc toggle"
bindsym XF86AudioPrev exec "mpc prev"
bindsym XF86AudioNext exec "mpc next"
bindsym XF86AudioForward exec "mpc seek +1"
bindsym XF86AudioRewind exec "mpc seek -1"
Context-sensitive controls
Taking into account which window currently has focus and decide which command to run based on that, a more sophisticated approach is required.
The following shell script does exactly this and decides its action based on whether the video player mpv
has focus, or some other program.
For future reference it is saved in ~/.util/xf86audio
:
#!/bin/bash
actions="toggle|prev|next|forw|back"
# Check for correct usage
if [[ $# -ne 1 || ! "$1" =~ ^($actions)$ ]]; then
echo "Usage: "
echo "${0##*/} [${actions[*]}]"
exit 1
fi
# Get focused process' name
pid=$(xdotool getactivewindow getwindowpid)
process=$(ps -p $pid -o comm=)
case $process in
# Control mpv if focused
mpv)
case $1 in
toggle)
xdotool key space
;;
prev)
xdotool key less
;;
next)
xdotool key greater
;;
forw)
xdotool click 4
;;
back)
xdotool click 5
;;
esac
notify-send "; $1"
;;
# Control mpd per default
*)
case $1 in
toggle)
mpc toggle
;;
prev)
mpc prev
;;
next)
mpc next
;;
forw)
mpc seek +1
;;
back)
mpc seek -1
;;
esac
;;
esac
Afterwards it is verified that the script is executable:
user@host $ chmod +x ~/.util/xf86audio
With the custom script now available we adapt the i3 config at ~/.config/i3/config
:
bindsym XF86AudioPlay exec "~/.util/xf86audio toggle"
bindsym XF86AudioPrev exec "~/.util/xf86audio prev"
bindsym XF86AudioNext exec "~/.util/xf86audio next"
bindsym XF86AudioForward exec "~/.util/xf86audio forw"
bindsym XF86AudioRewind exec "~/.util/xf86audio back"
Reloading the i3 config now enables the bindings and the multimedia button does what it was intended to.
The only thing that still does not work completely is seeking in mpv
, either with simulating a mouse wheel scroll or arrow presses, although this surely could be remedied by using mpv
’s IPC socket.
Toggle Bluetooth
A small utility script that toggles Bluetooth on and off was added to ~/.bin/toggle-bt
#!/bin/bash
# Checks if bluetooth is already on and if so switches it off, or on otherwise.
# State file
sf=/tmp/bluetooth
if [[ -f "$sf" ]]; then
bluetoothctl power off && (notify-send "Bluetooth turned off"; rm -f "$sf") || notify-send "Bluetooth could NOT be turned off"
else
bluetoothctl power on && (notify-send "Bluetooth turned on"; touch "$sf") || notify-send "Bluetooth could NOT be turned on"
fi
To access this script with a shortcut, the following lines were added to ~/.config/i3/config
:
# Toggle Bluetooth
bindsym $mod+B exec "~/.bin/toggle-bt"
Display in i3blocks
I’m using i3blocks as a replacement for i3bar.
Adding the following snippet to the config in ~/.config/i3blocks/config
integrates a display of the headphones symbol followed by either OK
, signaling that the headphones can be connected, or N/A
in grey which shows that they’re unavailable.
[headphones-bluetooth]
command=echo -n ' '; [[ -f /tmp/bluetooth ]] && echo 'OK' || echo -e 'N/A\n\n#504945'
interval=10
The symbol above is replaced by using Font Awesome within i3 status bar.
This is achieved by the following parts of my ~/.config/i3/config
, which also needs the package otf-font-awesome
to be installed:
bar {
status_command i3blocks
# ...
font pango:Droid Sans Mono, FontAwesome 13.5
# ...
}
Make sure to have installed the otf-font-awesome
package.
Checking battery level
Unfortunately, there is nothing available to be used easily. This Stackoverflow answer gives a starting point for developing your own software. If you are going down this route and have created something usable, I’d be happy to hear. I will be updating this post if something turns up.
Debugging
A2DP unavailable
If you are within pavucontrol
and set the headphones’ profile to Headset Head Unit (HSP/HFP)
and disconnect the device, after a reconnect the profile High Fidelity Playback (A2DP Sink)
might become unavailable.
This can be fixed in the following way:
- Connect headphones
- Open
pavucontrol
- Select
Configuration
›Headphones
›Profile
›Off
- Run
bluetoothctl disconnect XX:XX:XX:XX:XX:XX
- Reconnect from the headphones
- Profile is now available again
Low volume
You may be afflicted by low volume via Bluetooth on Arch compared to other devices. I found two methods to remedy this, of which the second one worked for me.
Editing service file
Following this post on the Arch forums this might help you.
First, edit /lib/systemd/system/bluetooth.service
as follows:
# Before change
ExecStart=/usr/lib/bluetooth/bluetoothd
# After change
ExecStart=/usr/lib/bluetooth/bluetoothd --plugin=a2dp
Afterwards you have to restart your Bluetooth connections:
root@host # systemctl daemon-reload
root@host # systemctl restart bluetooth.service
user@host $ bluetoothctl power on
Repairing with high volume
Another method mentioned in the same thread is the following:
-
Unpair your device with your Arch host
bluetoothctl remove XX:XX:XX:XX:XX:XX
- Connect to the device via another OS, preferably Android
- Set the maximum volume there
- Disconnect the device from the other OS
-
Pair and connect the device with your Arch host
bluetoothctl pair XX:XX:XX:XX:XX:XX bluetoothctl connect XX:XX:XX:XX:XX:XX
Final thoughts
Although the setup is not yet perfect, it does a well enough job. I wish for somebody to make improvements on the communication of battery levels, so they work analogous to Android’s implementation. Also I hope that this post did help you setting up either the Bose QuietComfort 35 II headphones or a similar pair on either Arch or a similar OS. Let me know if you made improvements to this setup or something is unclear.