raspberrypi / linux

Kernel source tree for Raspberry Pi-provided kernel builds. Issues unrelated to the linux kernel should be posted on the community forum at https://forums.raspberrypi.com/
Other
11.22k stars 5.02k forks source link

Bluetooth HSP/HFP not working in Raspberry PI 3 #2229

Open SoloVeniaASaludar opened 7 years ago

SoloVeniaASaludar commented 7 years ago

Trying to use a bluetooth mic/speaker in a raspberry pi 3 (headless).

Hardware is Raspberry pi 3, firmware updated today, running raspbian also dist-upgraded today. Using bluez and pulseaudio (system service start mode).

No error messages seen in any log file.

Moreover, if I "down" ("hciadmin hci0 down") the internal raspberry bluetooth controller and use instead an external bluetooth controller connected in an usb port, both modes works correctly. Thus, problem seems related with the bluetooth device in raspberry card.

These are result from some related commands.

pi@raspberrypi:~ $ uname -a Linux raspberrypi 4.9.56-v7+ #1044 SMP Fri Oct 13 15:23:13 BST 2017 armv7l GNU/Linux

pi@raspberrypi:~ $ hciconfig -a
hci0:   Type: Primary  Bus: UART
    BD Address: B8:27:EB:7E:DA:2A  ACL MTU: 1021:8  SCO MTU: 64:1
    UP RUNNING 
    RX bytes:14641 acl:101 sco:0 events:1341 errors:0
    TX bytes:2208546 acl:2358 sco:7 commands:97 errors:0
    Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
    Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 
    Link policy: RSWITCH SNIFF 
    Link mode: SLAVE ACCEPT 
    Name: 'raspberrypi'
    Class: 0x0c0000
    Service Classes: Rendering, Capturing
    Device Class: Miscellaneous, 
    HCI Version: 4.1 (0x7)  Revision: 0x145
    LMP Version: 4.1 (0x7)  Subversion: 0x2209
    Manufacturer: Broadcom Corporation (15)

pi@raspberrypi:~ $ pactl list
...
Card #3
    Name: bluez_card.E8_07_BF_11_10_A0
    Driver: module-bluez5-device.c
    Owner Module: 15
    Properties:
        device.description = "SPUBT710"
        device.string = "E8:07:BF:11:10:A0"
        device.api = "bluez"
        device.class = "sound"
        device.bus = "bluetooth"
        device.form_factor = "speaker"
        bluez.path = "/org/bluez/hci0/dev_E8_07_BF_11_10_A0"
        bluez.class = "0x240414"
        bluez.alias = "SPUBT710"
        device.icon_name = "audio-speakers-bluetooth"
    Profiles:
        headset_head_unit: Headset Head Unit (HSP/HFP) (sinks: 1, sources: 1, priority: 20, available: yes)
        a2dp_sink: High Fidelity Playback (A2DP Sink) (sinks: 1, sources: 0, priority: 10, available: yes)
        off: Off (sinks: 0, sources: 0, priority: 0, available: yes)
    Active Profile: headset_head_unit
    Ports:
        speaker-output: Speaker (priority: 0, latency offset: 0 usec)
            Part of profile(s): headset_head_unit, a2dp_sink
        speaker-input: Bluetooth Input (priority: 0, latency offset: 0 usec)
            Part of profile(s): headset_head_unit 

# systemctl status bluetooth
● bluetooth.service - Bluetooth service
   Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2017-10-14 15:49:16 UTC; 36min ago
     Docs: man:bluetoothd(8)
 Main PID: 461 (bluetoothd)
   Status: "Running"
   CGroup: /system.slice/bluetooth.service
           └─461 /usr/lib/bluetooth/bluetoothd

Oct 14 15:49:16 raspberrypi bluetoothd[461]: Bluetooth daemon 5.43
Oct 14 15:49:16 raspberrypi systemd[1]: Started Bluetooth service.
Oct 14 15:49:16 raspberrypi bluetoothd[461]: Starting SDP server
Oct 14 15:49:16 raspberrypi bluetoothd[461]: Bluetooth management interface 1.14 initialized
Oct 14 15:49:16 raspberrypi bluetoothd[461]: Failed to obtain handles for "Service Changed" characteristic
Oct 14 15:49:16 raspberrypi bluetoothd[461]: Sap driver initialization failed.
Oct 14 15:49:16 raspberrypi bluetoothd[461]: sap-server: Operation not permitted (1)
Oct 14 15:49:16 raspberrypi bluetoothd[461]: Endpoint registered: sender=:1.3 path=/MediaEndpoint/A2DPSource
Oct 14 15:49:16 raspberrypi bluetoothd[461]: Endpoint registered: sender=:1.3 path=/MediaEndpoint/A2DPSink
Oct 14 15:55:04 raspberrypi bluetoothd[461]: /org/bluez/hci0/dev_E8_07_BF_11_10_A0/fd0: fd(24) ready

systemctl status pulseaudio

● pulseaudio.service - Pulse Audio
   Loaded: loaded (/etc/systemd/system/pulseaudio.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2017-10-14 15:49:12 UTC; 36min ago
 Main PID: 343 (pulseaudio)
   CGroup: /system.slice/pulseaudio.service
           └─343 /usr/bin/pulseaudio --system --disallow-exit --disable-shm --exit-idle-time=-1

Oct 14 15:49:12 raspberrypi pulseaudio[343]: W: [pulseaudio] main.c: OK, so you are running PA in system mode. Please make sure that you actually do want to do that.
Oct 14 15:49:12 raspberrypi pulseaudio[343]: W: [pulseaudio] main.c: Please read http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/WhatIsWrongWithSystemWide/ for an explanation why system mode is usually a bad idea.
Oct 14 15:49:12 raspberrypi pulseaudio[343]: W: [pulseaudio] authkey.c: Failed to open cookie file '/var/run/pulse/.config/pulse/cookie': No such file or directory
Oct 14 15:49:12 raspberrypi pulseaudio[343]: W: [pulseaudio] authkey.c: Failed to load authentication key '/var/run/pulse/.config/pulse/cookie': No such file or directory
Oct 14 15:49:12 raspberrypi pulseaudio[343]: W: [pulseaudio] authkey.c: Failed to open cookie file '/var/run/pulse/.pulse-cookie': No such file or directory
Oct 14 15:49:12 raspberrypi pulseaudio[343]: W: [pulseaudio] authkey.c: Failed to load authentication key '/var/run/pulse/.pulse-cookie': No such file or directory
Oct 14 15:49:16 raspberrypi pulseaudio[343]: E: [pulseaudio] bluez5-util.c: Found duplicated D-Bus path for adapter /org/bluez/hci0
Oct 14 15:49:16 raspberrypi pulseaudio[343]: E: [pulseaudio] bluez5-util.c: Found duplicated D-Bus path for device /org/bluez/hci0/dev_E8_07_BF_11_10_A0
pelwell commented 6 years ago

No - there are no suitable test pins.

pelwell commented 5 years ago

@ricardosalveti A recent read of the 3A+ schematic revealed that, due to routing congestion around the WiFi combo chip, the BT_ON pin is slaved off the WL_ON pin, both being driven by GPIO1 on the expander. During the discussion with the hardware team it came to light that this same arrangement is used on the current production 3B+s, which explains the behaviour you have seen.

The 3B+ on my desk I use for testing, and the schematic I have for the 3B+, comes from the penultimate design that still had BT_ON on a dedicated pin (GPIO 0 on the expander), which unfortunately was not suitable for volume manufacturing.

ricardosalveti commented 5 years ago

@pelwell thanks for the update, good to have a confirmation from the hardware side, too bad there is no a good software workaround that can be done without also affecting wifi when getting bt hardware errors.

Do you know if there is a way identify, from the software side, the 3b+ boards that are using the latest design? That way we could at least have a software workaround that would not affect the boards based on the penultimate design.

pelwell commented 5 years ago

No, unfortunately - both versions are programmed with the same revision code:

$ grep Revision /proc/cpuinfo
Revision        : a020d3
ole1986 commented 5 years ago

Will the raspberry also work with HFP using ofono?

aurelihein commented 5 years ago

Seems like on the rpi4 with CYW43455 the problem with SCO audio routing is back ! I have the exact same symptom that we had before getting the magic hci command (sudo hcitool cmd 0x3F 0x01C 0x01 0x02 0x00 0x01 0x01). nothing want to play and record HSP / HFP uses SCO audio packets to transmit audio and in order to make PulseAudio work the packets must be routed to the HCI interface. But what command needs to be send ? Yes HSP / HFP works well with an external USB Bluetooth dongle

pelwell commented 5 years ago

Thanks for the report - I've opened a case with Cypress.

killerkalamari commented 5 years ago

Having problems with SCO on a non-Raspberry Pi CYW43455 used in the recently discontinued Samsung Artik 710 module. Dunno if that helps any, but mentioning it just in case. Thanks for looking into this!

Also, maybe some Pi 3 B+'s use the CYW43455 as well, at least if this press release is accurate: https://www.cypress.com/news/cypress-delivers-robust-wireless-connectivity-raspberry-pi-3-model-b-iot-single-board-computer

pelwell commented 5 years ago

We've never made a secret of the fact that all 3B+s use CYW43455.

killerkalamari commented 5 years ago

I just went ahead and tried that hcitool command on the CYW43455 and at least for me it got the audio to play. It clips on the end, but that's probably a separate issue (and I'm using bluealsa, so that could even be involved). However, this is not a Pi, so my results are not that relevant. I have a Pi 3 (older, non-B+) and Pi 4 and I plan on giving those a try when I can.

EDIT for offtopic info: I was able to recreate the audio truncation issue with the Pi 3 (non-plus) and bluealsa with hsp-ag. Ended up not being able to test on the Pi 4 for unrelated reasons. Also tried the Pi 3 with pulseaudio in headset mode. With pulse the beginning of the audio was gone and the sound seemed to play slower than it should, with extremely bad quality. So, the results weren't as conclusive as I was hoping. It appears that there are probably software issues with both bluealsa and pulse... or there could also be further hardware problems, hard to say. There is a third non-free bluetooth stack for Linux, I might give it a try and see what happens.

EDIT 2 offtopic: Opened a bluealsa bug, here, and the truncation was resolved with a bluealsa source modification: Arkq/bluez-alsa#260

ole1986 commented 5 years ago

Secret or not. I was expecting to have a proper working chip for WLAN and BLUETOOTH on my Pi 3 which is not the case and in addition to this people reporting several other issues, related to this ticket here.

pelwell commented 5 years ago

FWIW, Cypress have acknowledged my request and forwarded it to the right person, but nothing more so far.

pelwell commented 5 years ago

Cypress think that the required SCO audio routing is already enabled in the firmware. They would like a log of the HCI traffic to the modem, which you can capture by running "sudo btmon -w btmon.cap" somewhere, ideally before you pair the device. After pairing, connect to it and attempt to play something short - I use piano2.wav from https://www.kozco.com/tech/soundtests.html - then run the hcitool cmd line and try again. After successful playback you can Ctrl-C the btmon command and upload the resulting capture somewhere - it was about 500kB for me.

pelwell commented 5 years ago

Without HCI logs and/or a detailed description of the equipment and steps involved to reproduce the problem there is little we can do. Will close if no response in 30 days.

aurelihein commented 5 years ago

Hello, Here is the test ask done on Rpi4 using SCO mode : 20191029-sco_issue_rpi4.zip You will find the cmd line used for the test : 20191029-complete_log_cmdline Let me know Regards,

pelwell commented 5 years ago

Thank you - that's very helpful, and it's been forwarded to Cypress.

pelwell commented 5 years ago

@aurelihein I have audio playing over HSP/HFP now. In order for it to work properly I had to follow this guide: https://hackaday.io/project/165208-an-old-rotary-phone-as-bluetooth-set/log/162491-setting-up-the-bluetooth

I started from a clean Raspbian install. Pairing and audio device selection can be done using the standard Raspbian Bluetooth tool (but note that starting pulseaudio will require the audio device is reselected, and I found I usually had to do it twice for it to work (there is a beep on connection, and I only got that on the second attempt).

There are one or two steps missing from the guide:

  1. ofono must be enabled and started. Running sudo systemctl enable --now ofono will start it immediately and at every boot.
  2. pulseaudio must be started - pulseaudio --start should do it.

If you don't edit default.pa it will use a2dp. If you don't patch pulseaudio with the correct mtu size it will sound strangely slowed down. If you don't start pulseaudio then when you play a sound it will try, then switch back to another output (HDMI for me).

Note that this assumes you are running Raspbian, which has the magic hcitool command in /usr/bin/bthelper. Without that (and if the headset has been powered off since it was last run) you'll get no sound.

aurelihein commented 5 years ago

Nope it does not work ! They are talking about Rpi zero ! I am talking about Rpi4 !! bthelper doesn't handle Rpi4 yet !

pelwell commented 5 years ago

I was testing on a convenient 3B+ which runs the same firmware on the same hardware. The crucial difference is that the 3B+ doesn't have a MAC address from the new dc:a6:32 OUI. The bthelper command needs to be updated to also recognise the new OUI and apply the same patch. An offline task is then to figure out why the HCI cmd is necessary, given that according to Cypress this should be the default.

Try replacing the hciconfig ... grep ... line with:

/bin/hciconfig "$dev" | grep -qE "BD Address (B8:27:EB|DC:A6:32):" || exit 0
pelwell commented 5 years ago

See https://github.com/RPi-Distro/pi-bluetooth/pull/10.

pelwell commented 5 years ago

Forget my previous post and try this instead:

  1. Start with a clean Raspbian image. Edit /usr/bin/bthelper and comment out the hci cmd line to prove that it isn't required.
  2. Pair the headset using the Raspbian Bluetooth plugin, then use the volume control to select it for output.
  3. Before playing any audio, edit .asoundrc and change profile "a2dp" to profile "sco". This will be deleted when you disconnect the headset, but for now this is a proof of concept.
  4. Play some audio, and revel in the poor telephone-quality audio.
  5. Now use the volume control to connect to the headset for audio input. (If you take a look at .asoundrc you'll see that the pcm.input section is already configured for "sco".
  6. Use your favourite audio capture app, or run arecord test.wav and speak into the microphone, ending with Ctrl-C. Then aplay test.wav to replay your recording.

If this works for you then it shows there's nothing fundamentally wrong with the Bluetooth modem and its HSP handling.

pelwell commented 5 years ago

To summarise my findings so far:

  1. The bthelper script wasn't applying the "hci cmd" fix on Pi 4s - this has now been fixed.
  2. The LXPanel volume plugin and the BlueALSA audio interface will automatically use "a2dp" for audio output and "sco" for audio input.
  3. Editing .asoundrc after connecting to a headset allows "sco" mode (HSP) to be used.

It isn't clear to me why anyone would want to use HSP for output when A2DP is available, which leads me to ask: i. Do items 1-3 above cover all the issues? ii. If 3 is useful, would it help if the plugin was altered to allow such a connection without the need to manually edit .asoundrc, e.g. by provided two different connection modes? iii. If the above doesn't resolve your problems, describe your use case and where it fails.

StuartIanNaylor commented 4 years ago

Anyone know how to get this working as doesn't seem to be.

Also if you want HSP then if *imtu should be 48/60/64? https://hackaday.io/project/165208-an-old-rotary-phone-as-bluetooth-set/log/162491-setting-up-the-bluetooth

Confused.com but in the latest 2020-02-05 a bluetooth speaker/mic does not seem to work?

Im PA11.0 MTA is now set in the kernel for PA.

Improved bluetooth MTU configuration The packet size (a.k.a. MTU, "maximum transmission unit") that PulseAudio uses with the bluetooth HSP profile was previously always configured to be 48 bytes. That worked with most hardware, but some adapters require a different packet size. Now PulseAudio asks the kernel what packet size should be used, which fixes the problem.

However, a new problem appeared: some adapters that used to work with 48 byte packet size don't any more work with the size that the kernel tells PulseAudio to use. If you find that HSP audio stopped working when upgrading to PulseAudio 11.0, you can revert to the old behaviour by passing option "autodetect_mtu=no" to module-bluetooth-discover in /etc/pulse/default.pa. If that fixes the problem, then please report the problem to the BlueZ and/or PulseAudio developers, so that the kernel can be fixed.

Update: We decided to disable the MTU autodetection in 11.1 by default, because the feature caused too much problems and it looked like the kernel would not really get fixed even when people reported issues.

So the kernel should have a MTU config of 64?

There are a ton of devices that use HSP and since 1.6 HSP has been wideband audio it was just pulseaudio and settings that make HSP bad not HSP. The devices are not OS configurable and firmware and HSP is likely to continue and the same questions are being asked on the Ubuntu bugzilla as why on Ubuntu does HSP sound so bad when you plug into other OS it sounds great. Ubuntu is the same but other distros and win or android HSP is 16Khz great quality plug it into a Pi and not because of the MTU and not using ofono with pulseaudio

I am not even sure if PA12 works with HSF/HSP as even with a bluetoothdongle/headset I can not switch profile. In PA12 they swapped the priority with A2DP & HSF/HSP because it would 'stick' in HSF/HSP profile but now the opisite happens but rather than lower quality on headphones you now get headsets that are now only headphone only.

Seems Arch and Ubuntu are the same and maybe its just me but PA12/Bluetooth seems to be broken for HSF/HSP

Also if you go the bluealsa route for some reason bluealsa is compiled with

--enable-ofono enable HFP over oFono - requires no extra libraries at build time. Including this option will disable bluealsa's internal HSP/HFP and instead defer all telephone integration to oFono

So disabling internal bluealsa support which would seem contary in terms of bloat to the rational of opting for bluealsa

E500E commented 4 years ago

The problem was identified as a timing issue in PulseAudio.

In an nutshell, PulseAudio uses a hard-coded (e)SCO packet size of 48 bytes, instead of using the packet size negotiated at the eSCO connect (ex 60 bytes). The timing logic used for SCO connections, is to send (e)SCO packets (one at a time), at each SCO packet received. If the negotiated packet size is bigger (ex 60 bytes) than the hard-coded 48 bytes, the SCO packets are received at a lower rate, which causes PulseAudio to send the SCO packets way too slow.

More details on the following [pulseaudio-discuss] thread: [pulseaudio-discuss] Bluetooth - HSP / HFP - source based timing & hard-coded MTU causes SCO packets to be badly delayed

Thank you @bluetiger9 and @kp339 ---- With your clues I was able to solve the metallic garbled noises by recompiling pulseaudio --- thanks so much!

However I seem to be stuck on the next step - getting echo cancellation to work.
I am trying to use my pi0w as a bluetooth HFP set. Meaning my phone connects via bluetooth to the pi0w. The pi0w has a speaker and a microphone (via a USB audio adapter) and the goal is that I conduct my telephone call with the speaker/microphone.

The problem is that I can place calls and hear the other call participant clearly as well as speak, but I just cannot get the echo cancellation module to work I have tried these combos to no avail:

What happens is that I place the call, the conversation starts, and the other call participant has a devil of a time in the call because he/she can hear himself/herself. No doubt it is because of echo from the other participant speaking, getting played out of my pi's speaker, then picked up by my pi's microphone, and then fed back through the call.

First I tried putting this in /etc/pulse/default.pa load-module module-echo-cancel aec_method=webrtc

But that didn't work at all. Then, instead of putting that line inside the file, tried to manually load the echo cancel module on the shell:
pactl load-module module-echo-cancel

which just seems to crash pulseaudio every time. You can see the results of pulseaudio -v -v -v below --- the last two lines show the attempted load and "Illegal Instruction" and then pulseaudio quits.

D: [pulseaudio] srbchannel.c: SHM block is 65496 bytes, ringbuffer capacity is 2 * 32724 bytes
D: [pulseaudio] protocol-native.c: Enabling srbchannel...
D: [pulseaudio] module-augment-properties.c: Looking for .desktop file for pactl
D: [pulseaudio] protocol-native.c: Client enabled srbchannel.
I: [pulseaudio] module-echo-cancel.c: Using AEC engine: webrtc
Illegal instruction

This happens on both Buster and Stretch, and happens whether or not I use the sudo apt-get install pulseaudio pulseaudio-module-bluetooth -y command to get a "standard" version of pulse audio, or if I compile my own version of pulseaudio (to solve for metallic / robotic / garbled noises. Any advice would be appreciated. Thanks.

ciaranj commented 2 years ago

Just went through this process (loosely following this guide) on an RPi 3B+, no bluetooth dongle, all onboard kit with wifi enabled. Raspbian Bullseye which was shipping PulseAudio 14.2.

I needed to make the changes suggested above by @kp339 (MTU from 48->64) in order to significantly reduce the garbled sound, which works a treat. (Even with the auto_detect_mtu module parameter specified.)

As the codebase has moved on from 11.1 -> 14.2, I've included an updated diff in case it helps others.

diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
index 5ba743966..87b479e0c 100644
--- a/src/modules/bluetooth/backend-native.c
+++ b/src/modules/bluetooth/backend-native.c
@@ -194,8 +194,8 @@ static int sco_acquire_cb(pa_bluetooth_transport *t, bool optional, size_t *imtu
     if (sock < 0)
         goto fail;

-    if (imtu) *imtu = 48;
-    if (omtu) *omtu = 48;
+    if (imtu) *imtu = 64;
+    if (omtu) *omtu = 64;

     if (t->device->autodetect_mtu) {
         struct sco_options sco_opt;
diff --git a/src/modules/bluetooth/backend-ofono.c b/src/modules/bluetooth/backend-ofono.c
index d7a13efd0..2b4ba578c 100644
--- a/src/modules/bluetooth/backend-ofono.c
+++ b/src/modules/bluetooth/backend-ofono.c
@@ -269,9 +269,9 @@ static int hf_audio_agent_transport_acquire(pa_bluetooth_transport *t, bool opti
      * made available to userspace by the Bluetooth kernel subsystem.
      * Meanwhile the empiric value 48 will be used. */
     if (imtu)
-        *imtu = 48;
+        *imtu = 64;
     if (omtu)
-        *omtu = 48;
+        *omtu = 64;

     err = socket_accept(card->fd);
     if (err < 0) {