With how things going nowadays, Zoom and Microsoft Teams have started to become a common fixture in my daily, Work From Home way. While I have a pretty decked desktop audio setup with a dedicated microphone and DAC/Amp combo on my work corner, sometime I want to work down stair at my dinner table, or my newly renovated back porch. Thus I got myself a nice pair of Bluetooth headphone and earbuds.

Unfortunately, Bluetooth has always been Linux Achilles’ heel. In fact, the only way for the Bluetooth module on my Envy X360 to work after waking up from hibernation is to upgrade the kernel to an unsupported version.

So the box can detect and connect to my Bluetooth headsets just fine, and listening to music and watching movies works out of the box. The problem starts when I need to join a Zoom call or a Teams meeting. I can’t use the headset’s mic because Ubuntu doesn’t want to switch to headset to HFP/HSP profile. The issue here, as every audio related issue on linux, is Pulseaudio. Apparently the current version of Pulseaudio does not support Bluetooth headset profile out of the box. You can, however add the support by through oFono, a free software project for mobile telephony on linux. But to do that, we need to fool our box to think that it’s a phone, because oFono only works with the device that has GSM modem on it.

Sound complicated? Yes, it is. Which is why I instead, opted to remove Pulseaudio and replace it with Pipewire. This guide is made with Ubuntu and Gnome Shell. We’ll start by adding the PPA for the current version of Pipewire

$sudo add-apt-repository ppa:pipewire-debian/pipewire-upstream

Update the box repository

$sudo apt update

..And then install Pipewire and other packages that we will need to run Pipewire

$sudo apt install pipewire gstreamer1.0-pipewire libspa-0.2-bluetooth pipewire-audio-client-libraries

Reload the list of SystemD daemons

$systemctl --user daemon-reload

Disable Pulseaudio

$systemctl --user --now disable pulseaudio.service pulseaudio.socket
$systemctl --user mask pulseaudio

…and enable Pipewire

$systemctl --user --now enable pipewire-media-session.service
$systemctl --user restart pipewire-pulse.service

To see if we are successful, do

└──╼ $pactl info
Server String: /run/user/1000/pulse/native
Library Protocol Version: 34
Server Protocol Version: 35
Is Local: yes
Client Index: 105
Tile Size: 65472
User Name: ikhsan
Host Name: M5-NXN
Server Name: PulseAudio (on PipeWire 0.3.30)
Server Version: 14.0.0
Default Sample Specification: float32le 2ch 48000Hz
Default Channel Map: front-left,front-right
Default Sink: bluez_output.64_23_15_68_7E_D1.a2dp-sink
Default Source: alsa_input.pci-0000_04_00.6.HiFi__hw_acp__source
Cookie: 0824:e8da

As you can see, Pipewire is now active. Connect your Bluetooth headset, and open the sound setting for your distro, here’s for Gnome Shell on Ubuntu.

Sound Setting – Output

We should now able to pick “Headset Head Unit (HSP/HFP)” to switch the headset to …headset mode. Another way is to switch your input device to the headset. It will automatically switch the active microphone of the system to the Bluetooth headset as well as switch it to HSP/HFP profile.

Select your mic

When you’re done with the meeting and would like to continue binging the 3rd season of “The Rookie”, open Sound setting again, ensure the Bluetooth headphone is selected as Output Device, and change the Configuration to “High Fidelity Playback (A2DP Sink)”

Back to A2DP

So, we’re done, right? Well, not quite. Unfortunately in my case, Pipewire’s A2DP performance is not as good as Pulseaudio as it introduces severe delay when playing movies. If you’re facing the same issue, the delay offset can be configured through ..ironically, Pulseaudio Volume Control module, which you can install with

$sudo apt install pavucontrol

Once installed, open Pulseaudio Volume Control and switch to Output Devices tab

Pulseaudio Volume Control

Find the Bluetooth headset, and expand the Advanced portion and adjust the latency offset until the video and the audio properly synced.


By ikhsan

4 thoughts on “Fixing Bluetooth HSP/HFP profile on Ubuntu 20.10/21.04”
    I had the same headache – nice Sony WI-C200 headset – wants to use HSP/HFP profile
    to be bidirectional, but dear old PulseAudio just couldn’t hack it. Only worked with the older
    profile / leaving MIC out of the picture / hence no use for TEAMS etc.

    Installed as this article recommends – but on Lubuntu 18.04 – works fine (after a reboot).
    Before the reboot the Pavucontrol bewildered, but shook itself out after and just offered up more detailed device options. Using HSP/HFP with CVSD codec as the Config choice for WI-C200, then
    works fine on Google Meet and on onlinemictest.com – hopefully also Teams.
    Thanks again / great bit of advice.
    Mike H / London

  2. I’m confused about this, what is this for? I followed all the steps and now I have more codecs for output but the behaviour is the same. It doesn’t change on the fly from A2DP to HSP to allow headseat micro and good sould quality at the same time. Is it possible to do like Android and iOS do?
    Thank you,

    1. My problem is that HSP/HFP totally does not work on my Ubuntu box. Gnome sound menu will let me select the profile, but nothing changes. If your problem is different, or if you have a working HS/HF profile under pulseaudio, then this article is not for you. From what I have gathered so far, the implementation of automatic profile switching on Pipewire is still incomplete. My use case however, does not really need that as I primarily use a USB microphone. I need the profile on my XM4 to stay on A2DP, up until I manually switch the input to HSP/HFP if I need to, ie: when I move away from my desk. At the end of the meeting, I will switch it back to A2DP

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.