Enabling Hands-Free Profile on Raspberry Pi (Raspbian Stretch) by using PulseAudio


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

 

Prerequisites

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.


 

Reference

– 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/

 

 

Sponsor Link

43 Comments

    1. 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)?

    1. 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?

      1. 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!

    1. 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.

  1. 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!

      1. 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.

        1. 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.

  2. 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.

    1. 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…

      1. 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

        1. 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)

  3. 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 !

    1. 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?

      1. 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

        1. Hey !

          I got it working again !
          i just ran “sudo pulseaudio –start” and now there is a sound even when i run a call !

  4. 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.

  5. 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)

  6. 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?

  7. Has anyone had a problem with this working for phone calls but sounding glitchy with media?

  8. Has anyone had a problem with this working fine for phone calls but sounding glitchy as can be with media?

  9. 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

  10. 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

    1. 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!

  11. Can we accomplish Handsfree Calling using bluealsa alone without pulseaudio, as you did with the streaming audio tutorial?

  12. 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 🙂

    1. 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?

  13. 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!

    1. 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.

  14. 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

  15. 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?

    1. I know this is a tad bit old, but look up OpenAuto. It’s a full android distribution specifically for cars.

  16. 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!

  17. 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?

Comments are closed.