The purpose of this post is to enable Bluetooth Handsfree Profile (HFP) with PulseAudio on Raspbian Stretch so that Raspberry Pi can act like as a handsfree speaker phone or a handsfree car kit. This is an updated version of this post. When I wrote the previous post, I was using Raspbian Jessie and some steps needed to be updated to apply Raspbian Stretch.
There is one thing needs to be mentioned before start. The original plan was to use Raspberry Pi3’s on-board Bluetooth chip for this project. Unfortunately, it didn’t work. It seems that the problem is related with the chip. So, we have to use a Bluetooth dongle instead.
Here is the list of contents of this post.
Contents
– Prerequisites
– Steps
1. Preparations
2. oFono Installation
3. PulseAudio Installation & Settings
4. Connecting Your Phone
5. Making a Call
– Summary
– Reference
- Raspberry Pi board (e.g. Raspberry Pi 3 B+)
Assuming your Raspberry Pi is running Raspbian Stretch. If it’s not, please install it first. I used Raspberry Pi 3 B+ but other models should work. - Bluetooth USB dongle (e.g. Panda Bluetooth 4.0 USB Adapter)
As mentioned above, we’ll use a Bluetooth dongle since the on-board Bluetooth chip doesn’t work for HFP. - USB Sound Card with microphone input (e.g. SYBA USB sound adapter / FG-UAUDV1-C119)
Required since Raspberry Pi board doesn’t have microphone input. - Microphone with 3.5 mm audio jack (e.g. HDE Mini 3.5mm Aux Auxiliary Voice Microphone)
- Speakers with 3.5 mm audio jack
Below are the required application versions to enable Bluetooth HFP according to PulseAudio release note.
- Bluez 5.0 or later (v5.43 is pre-installed in Stretch)
- PulseAudio 6.0 or later (not pre-installed in Stretch, but it supports v10.0)
- oFono 1.13 or later (not pre-installed in Stretch, but it supports v1.18)
Steps
1. Preparations
1-1. Connect Bluetooth dongle and USB sound card with Raspberry Pi.
1-2. Connect the microphone and speakers to 3.5 mm audio jacks on the USB sound card.
1-3. Boot up Raspberry Pi Board.
1-4. As described, we don’t use on-board Bluetooth chip. So we’ll disable it. To do that, open “/etc/modprobe.d/raspi-blacklist.conf”.
sudo nano /etc/modprobe.d/raspi-blacklist.conf
1-5. Add lines below and save.
blacklist btbcm blacklist hci_uart
1-6. According to a Raspberry Pi Foundation blog post, Bluetooth audio is handled by ALSA through bluez-alsa in Stretch. However, since in this post we are using PulseAudio, let’s uninstall bluez-alsa.
sudo apt-get purge bluealsa -y
1-7. Then reboot the board.
sudo reboot
1-8. After reboot, check dmesg and make sure there is no Bluetooth-related errors.
dmesg | grep -i bluetooth
1-9. Also, make sure hci0 is UP.
hciconfig
The result should be like this:
hci0: Type: BR/EDR Bus: USB BD Address: XX:XX:XX:XX:XX:XX ACL MTU: 310:10 SCO MTU: 64:8 UP RUNNING RX bytes:622 acl:0 sco:0 events:38 errors:0 TX bytes:1437 acl:0 sco:0 commands:38 errors:0
If it’s DOWN for some reason, then turn it up.
sudo hciconfig hci0 up
2. oFono Installation
2-1. oFono is not installed by default, so let’s install it.
sudo apt-get install ofono -y
2-2. Make sure if it’s successfully installed.
$ ofonod --version 1.18
2-2. Then, start the service.
sudo systemctl start ofono
You can check the service running like below.
$ systemctl -a |grep ofono ofono.service loaded active running Telephony service
3. PulseAudio Installation & Settings
3-1. In Raspbian Stretch, PulseAudio is not pre-installed. Install PulseAudio and its Bluetooth module:
sudo apt-get install pulseaudio pulseaudio-module-bluetooth -y
3-2. Check the version. It should be v10.0 (or higher).
$ pulseaudio --version pulseaudio 10.0
3-3. Open “/etc/pulse/default.pa”.
sudo nano /etc/pulse/default.pa
3-4. Add “headset=ofono” on the line of ‘module-bluetooth-discover’.
load-module module-bluetooth-discover headset=ofono
3-5. Restart Raspberry Pi.
sudo reboot
4. Connecting Your Phone
4-1. Launch bluetoothctl.
bluetoothctl
4-2. Then, input below commands.
power on agent on default-agent
4-3. Start searching your phone. Make sure your phone is discoverable.
scan on
4-4. After detecting your phone, turn scan off.
scan off
devices command shows a list of found devices.
[bluetooth]# devices Device XX:XX:XX:XX:XX:XX Galaxy S7
4-5. Then, pair, trust and connect to your phone by specifying the Bluetooth device address (in this case it’s “XX:XX:XX:XX:XX:XX”, please replace it wity your device’s address).
pair XX:XX:XX:XX:XX:XX trust XX:XX:XX:XX:XX:XX connect XX:XX:XX:XX:XX:XX
If everything is ok, you should see “successful” at the end of the result for each command like below.
[bluetooth]# pair XX:XX:XX:XX:XX:XX ... Pairing successful
[bluetooth]# trust XX:XX:XX:XX:XX:XX ... trust succeeded
[bluetooth]# connect XX:XX:XX:XX:XX:XX ... Connection successful
5. Making a Call
To make a call, you can use oFono test scripts which is included in the source code.
5-1. First, download the source and extruct.
wget https://www.kernel.org/pub/linux/network/ofono/ofono-1.18.tar.gz tar -xzvf ofono-1.18.tar.gz
5-2. Then, you can make a call by:
python ./ofono-1.18/test/dial-number 8586515050
If you want to end the call, then type:
python ./ofono-1.18/test/hangup-active
Summary
Since Raspbian Stretch supports PulseAudio v10.0, the steps are now a little simpler than previous one. I confirmed both sending and receiving audio are fine during a hands free call. I confirmed Bluetooth audio streaming (A2DP) is working too.
Update (May 2, 2018):
The steps to enable equalizer on HFP sending audio is newly posted.
– Raspbian Stretch has arrived for Raspberry Pi
https://www.raspberrypi.org/blog/raspbian-stretch/
– Connect Bluetooth Headset To Raspberry Pi 3 (A2DP & HSP)
http://youness.net/raspberry-pi/bluetooth-headset-raspberry-pi-3-ad2p-hsp
– PulseAudio 6.0 Release Notes –freedesktop.org
https://www.freedesktop.org/wiki/Software/PulseAudio/Notes/6.0/
– PulseAudio Documentation –freedesktop.org
https://freedesktop.org/wiki/Software/PulseAudio/Documentation/
Nice write up, how did you manage to set the default sound card to 1 for the USB sound card on Raspbian Stretch?
Hi Tony. It’s always assigned to index 1 and default without any additional configuration in my case. Maybe because it’s the only connected card (except the on-board sound card)?
Could you provide some details on how you setup and tested A2DP audio streaming?
Hi Jack,
What I did was after the BT connection is up (step 4-5), I just opened a music app on my phone (e.g. Pandora). Are you having a problem with A2DP streaming?
Hello!
thanks a lot for the tutorial,
dialing number is working just fine but there is no sound coming from the raspberry pi so i’m guessing it is a pulseaudio problem since a2DP on Alsa works just fine!
any suggestions ?
Thank you!
Is it possible to use a hfp to use a buetooth earpiece as a microphone?
I think it should be technically possible, but not sure. I believe Bluetooth earpieces support only HF role, so, Raspberry Pi needs to be configured as AG role. According to freedesktop.org, PulseAudio 11 supports HFP AG role. So, you need to figure out how to install Pulseaudio 11 and how to configure as AG. Also, I’m not sure how to control SCO connection (HFP Audio connection) using Bluez/Pulseaudio/Ofono.
Hello,
This setup worked for me. Now I’m trying to configure an equalizer, I’ve tried PulseAudio first, no luck, and now I’m trying Alsa Equal, based on LADSPA, its not working on raspberry either: the .asoundrc is being overwritten every reboot, I guess my configuration is not ok.
Which one is the right (or better) one to setup? Alsa Equal or PulseAudio equalizer? (based on this tutorial).
I need to know in which one of these I must spend more time to make it work.
Thanks!
Hi Fernando, I just uploaded a post “Enabling Equalizer on Handsfree Sending Audio with ALSA equal plugin” which I drafted a while ago and hadn’t posted. It’s working for me on Raspberry Pi 3 running the latest Raspbian Stretch (2018 April).
As I remember correctly, module-equalizer-sink module on pulseaudio was also working. I’ll check.
Hello Max!
You are amazing! Thanks for sharing this! Your HSP / HFP tutorial worked very well.
Unfortunately the equalizer post (which I’ve followed) didn’t worked for me. I’ll check later if its something related to my setup, or if just works with HFP, and not with A2DP. I’m trying to find a system-wide equalizer, which works for every sound. If it is not possible, then at least A2DP would be nice.
I was basically focusing on HFP and the steps in yesterday’s post applies the equalizer only on HFP sending signal. For a system-wide equalizer, you need to modify the sound routing. But if you don’t need HFP, bluealsa (instead of pulseaudio) + alsa equal-plugin might be straightforward.
Hi, I was able to enable a system wide equalizer (including A2DP) with bluealsa & alsa equal plugin. If you interested, please check this post to enable Bluetooth audio sink with bluealsa, and this post to setup a equalizer.
Hi Max,
Thank you for taking the time to figure all of this out. I wonder if you have some ideas about the following project I’m trying to suss out:
I’m part of a motorcycle touring group and we are struggling with the limitations of the current batch of Bluetooth intercom headsets available on the market. To complicate matters, many of my group use HAM radios with HFP -> GMRS/HAM PTT adapters. The problem with most of our setups is that it relies on the bluetooth headset mounted on our helmets to prioritize the audio of the connected devices. Since our headsets can only connect to TWO devices in total, if one of them is a HFP/HSP (which is what the adapter that connects to the GMRS/HAM radio uses) this connection will never let go of the connection which in turn prevents the other device that is normally used to stream A2DP music from ever being heard.
What we would like to happen: multiple HFP/HSP and A2DP connected audio sources being “mixed” at the same level (and maybe with adjustable volume levels so if nothing is coming in on say the GMRS/HAM adapter it could be set as a higher volume to “override” the music.
We would obviously need to connect to the helmet’s Bluetooth headset for the Mic and audio to be heard.
My thought (and why I landed here) was that we could leverage a RPI3 as some sort of “Bluetooth Mixer”. The nice thing about the RPI3 is that it has a stack of 4 USB ports…to connect multiple bluetooth dongles to.
So…this is what this monstrosity might look like:
Helmet Sena 20s RPI3 BT dongle 1
Sena SR10 (can only connect using HFP/HSP) RPI3 BT dongle 2
Garmin Zumo 595LM RPI3 BT dongle 3
Is it even possible to take multiple BT connected A2DP / HFP / HSP streams and mix them all together and then hear them through a BT headset using the RPi3?
Thoughts?
Thanks again for taking the time.
Hi Dan, sounds an interesting project!
It’s possible to mix multiple BT sources on RPi (using ALSA/PulseAudio/etc). I think also possible to send it to another BT device through A2DP. (RPi –> Sena S20)
However, if you want to use mic on Sena S20, the connection between Sena S20 and RPi must be HFP. So, the mixed signal (Sena SR10 + Garmin Zumo 595LM) should be sent over HFP, not A2DP. It can be tricky. Maybe I can do some experiment this weekend…
Awesome! So it’s interesting, I have been playing with this over the last week and it seems that in PA 10 that hfp/hsp isn’t fully working yet. I’m basically running into the issue listed on this thread:
https://github.com/raspberrypi/linux/issues/2229
I think it’s the reason why the SR10 can’t be found by the rpi3, even with a dongle, since it only pairs in HFP. (I can connect it to my car’s HFP, but it’s not even found during a scan in bluetoothctl, etc on the rpi3). It looks like we need PA 11.1 for full HFP/HSP functionality at this point.
Once I get past this connectivity issue, the mixing is the last bit to make this all work! =)
Thanks again for the time you’ve invested in all of this!
Dan
Hi Dan, thank you for the update. Unfortunately I was not able to find time to experiment last weekend. As far as I understand from the link, the issue is about SCO audio issue (no sound or distortion), not connectivity issue. If SR10 supports HFP/HSP and it’s discoverable, RPi3 should be able to find it… (even with PA 10)
Hello !
Thanks a lot for this tutorial !
Dialing number works fine, but the sound is not coming out of the raspi,
Maybe the a2dp not working with pulseaudio, because when using bluealsa i can stream music just fine!
Any suggestions to fix this ?
Thank you !
Hi Chadi,
Did you disable bluealsa? (e.g. in above post, “sudo apt-get purge bluealsa -y”) If both bluealsa and pulseaudio are enabled, those conflict and the audio routing may not work as intended. Also, what are you trying to do? Phone calling using HFP/HSP, or music streaming using A2DP?
Hey Max,
I want to use both HFP and A2DP,
yes alsa is disabled, the problem was that pulseaudio didn’t start automatically so i had to do “pulseaudio –start” so now A2DP is working with pulseaudio but when i run a call the sound does not come out of raspberry pi !
Both worked for a while but when i tried to run it again there was no sound when running a call.I’m trying to figure out the problem but no luck so far .
any suggestions would be great !
Thanks
Hey !
I got it working again !
i just ran “sudo pulseaudio –start” and now there is a sound even when i run a call !
Hey Chadi, grad to hear it works!
I can connect to my raspberry pi but it wont let me stream music from my IOS device it worked for the first couple of days but it now doesn’t work.
After installing Pulseaudio I am getting an error:
xcb_connection_has_error() returned true
In seemingly random situations such as:
1. Launching alsmixer and exiting it
2. after command ffplay -nodisp speech.wav
(Also getting flagged as a bot when trying to reply with mac)
Is there a way to send command to phone to change/pause/play/skip the song when audio streaming?
I plan to install this setup in my car – also using CAN bus (display and keypresses on media control of my car) to display caller name, confirm call. Is there a way to get info about song that is playing over audio streaming?
Hi Tomislav,
That sounds interesting! Yes, you can control playback status with media-api from Bluez. Also, they have a sample code, simple-player. Let me know how it goes!
I created a post about playback control for Bluetooth audio. Please check it if you interested!
Has anyone had a problem with this working for phone calls but sounding glitchy with media?
Has anyone had a problem with this working fine for phone calls but sounding glitchy as can be with media?
Hey Max,
thanks a lot for this excellent HowTo!
I have one small question:
Right now the audio use 8kHz mono, but there should be as well 16kHz mono possible.
Do You have an idea, how to negotiate this?
Thanks a lot
Jack
Hello Max.
First let me thank you for this excellent guide, it helped a lot.
I had been trying to get that working for years with another SBC (Odroid C2).
Now to the point :
* I followed your guide completely, except I tried to make it work with the built-in bluetooth chip on Raspberry Pi 3B.
* It “works” out of the box, with Raspbian Buster, PulseAudio 12.2 and ofono 1.21 !
* My problem is that the sound during call is heavily distorted : just as if the bandwidth was insufficient for the stream
* When streaming music from the phone, it’s a bit better, but not reaaly satisfactory.
Do you have a clue about what could go wrong ? Is that the problem you encountered trying to make it work with the internal bluetooth chip, or was it a completely different problem ?
Thanks in advance for your help.
Myster-D
Hi Myster D,
I have the same issue with my raspberry pi 4 : very poor audio quality during a phone call.
I’m curious as to whether you’ve found a solution?
To Max:
Would it be possible to perhaps ‘force’ A2DP profile for audio input while in HSP/HFP mode?
I think if that’s possible then the sound quality can be improved.
For my purposes, I don’t need to use my microphone input during the calls.
Please let us know!
Thanks a lot!
Can we accomplish Handsfree Calling using bluealsa alone without pulseaudio, as you did with the streaming audio tutorial?
Hi Max,
Thanks for beautifully explaining this tutorial. Really appreciate it. I need your small help.
I have my setup with me, in which I have connected a USB mic on Raspberry Pi 4 and using the on-board bluetooth. I’m able to make the calls but I am facing the following 2 problems in the call.
1. The call is lagging from 5-6 seconds. For example: When I’m speaking into my pi mic, it reaches the other mobile phone after 4-5 seconds. But as soon as the mobile phone user says anything, it comes back instantly to the raspberry pi. Meaning audio input is lagging not audio output from pi.
2. Audio is having a lot of noise.
I am working on a personal project and your tutorial came in like an angle and literally saved me. Thank you so much, looking forward to hear from you soon 🙂
Parvinder, I now have the same issue as you — the noise level is extremely high (as if the audio outputs and inputs are being over driven …. even if I crank down the levels with alsamixer) and the call lags. Did you find a solution to this?
Thank you so much for figuring all this out! I am trying to make a small interface via Raspberry pi0w to connect the super-obsolete car-phone buttons on my early 1990s classic Mercedes auto to work with modern bluetooth phones!
I’m a relative newcomer to all this and so may I ask what may be an elementary question? I got all the way to step 5:
python ./ofono-1.18/test/dial-number 8586515050
But the script didn’t work because it says:
File “./ofono-1.18/test/dial-number”, line 4, in
import dbus
ImportError: No module named dbus
So I figured I have to run ./configure inside ~/ofono-1.18 first. That was a little challenging. First I had to install GLIB, then D-Bus, and now the ./configure script gives this:
checking for GLIB… yes
checking for DBUS… yes
checking for UDEV… yes
checking for mobile-broadband-provider-info… configure: error: Mobile broadband provider database is required
Googling shows various packages for “mobile-broadband-provider-info” but I don’t know how to install it, where to put it, or what to do with it….? Could you please tell me if I am going down the right path? Many many thanks!
Ah, Max, I figured it out (duh). I executed:
sudo apt-get install python-dbus
and now I got the dialing script to work … but I have to Sudo the dialing script — i.e.
sudo python ./ofono-1.18/test/dial-number 8586515050
Any idea why I cannot just execute this script as regular “pi” user? Thanks.
Perhaps there is a group you need to ad pi user to?
Thank you very much for your help on this. You wont believe how many tutorials I have followed.
This one is very clear and works great. I just had some issues in the beginning due to my versions being old.
I have now one doubt. If I’m playing a song (via spotify for example) is there any way to get the album info etc.? I think I saw somewhere someone doing something similar with dbus.
Thanks a lot
Thanks for the easy guide.
Do you know of any graphical phone dialer so as to use your project as a part of a car headunit replacement?
I know this is a tad bit old, but look up OpenAuto. It’s a full android distribution specifically for cars.
Hi Max,
Thank you so much for this tutorial, it’s very clear and useful.
I followed the whole tutorial and it works well, making calls and receiving, but I still have a question.
When there is an incoming call, the phone turn on the screen but the raspberry does anything (in my case).
Is there any event to capture an incoming call? In order to activate a ringtone for instance.
Thanks a lot!
I know this is an old topic, but I was still able to follow it and got everything working correctly on my RPi 3B+ (this is ultimately for an embedded system, so I don’t mind running on Stretch), so thank you for such thorough coverage of the topic. That said, I took the SD card out of my RPi 3 and put it and my ASUS USB BT5, TP-Link Wi-Fi, and no-name USB->TRRS headset adaptor into an RPi Zero 1.3 (no wireless). I can initiate a phone call from the Pi Zero, ensuring that the sending phone is set to the Pi, but I get no sound over the headset. On the receiving phone, every sound I make into the microphone echoes to that phone’s speaker after a momentary delay. I have and can email the “pacmd info” logs for both boards, as well as the script I call to ensure that the pulse audio default sink and default source are set correctly. Any ideas?