Open barolo opened 2 weeks ago
If you would like to try an experiment, it may be worth updating the connection interval:
/etc/bluetooth/main.conf
and reduce the MinConnectionInterval
and MaxConnectionInterval
from 16 to 8btmgmt read-sysconfig
(root not needed). The values you are looking for are Type: 0x0017
and Type: 0x0018
, which should now both be 0800
instead of 1600
Note that on my system, I had to restart the bluetooth service several times, and eventually remove and reinsert the btusb kernel module before the config would take. It may be easier to just restart your system.
Having the connection interval cut in half gives the adapter twice as many opportunities to transmit/receive information, which I'm hoping will make your connection more stable. It may also have an adverse effect on your battery life on both your hearing devices and your peripherals, so watch out for that and let me know how bad it gets.
The android code attempts to set this value if a config value tells it to, but it will fall back to a 16 (20ms) interval if it doesn't work, which I think means that not all hearing devices will support this. I have no way to check if the connection settings negotiation succeeded or not, so if this fails, your audio probably just won't work, and I won't have any feedback in the program indicating why.
A strict reading of the ASHA protocol would seem to indicate that by cutting the connection interval in half, I should be cutting the frames in half and sending them twice as frequently. It seems to work fine on my devices without this change though.
Use your bluetooth UI to "forget" your devices
Edit
/etc/bluetooth/main.conf
and reduce theMinConnectionInterval
andMaxConnectionInterval
from 16 to 8Restart your bluetooth service
Verify that the configuration has been updated by running
btmgmt sysconfig
(root not needed). The values you are looking for areType: 0x0017
andType: 0x0018
, which should now both be0800
instead of1600
It was btmgmt read-sysconfig
for me, and indeed it was changed to 0800. That being said the connection became significantly worse. I could tell from the start, I had a hard time pairing them, and after I could barely keep both connected, one would always disconnected. After them both connected, starting asha_pipewire_sink would disconnect them immediately.
So I reduced my connection interval to 8 and my frame size to 80, and all I get out of my hearing aids is a loud buzzing. I tried several different variants on the connection parameter update and the ACP status, and it still doesn't work.
I think the fact that my hearing aids can continue to use 160 byte frames even with a connection interval of 8 is a bug in the hearing aids.
I'm starting to wonder if going through pipewire is the right approach, and is there any other possibility? Not in the context of multiple devices, just in general.
I'm starting to wonder if going through pipewire is the right approach, and is there any other possibility?
Not really? On a modern linux system, even pulseaudio clients use pipewire.
I'm not sure where you are going with this. I don't think your instability is due to pipewire, its due to an incomplete linux bluetooth implementation.
Not really? On a modern linux system, even pulseaudio clients use pipewire.
Yeah, I'm aware, also alsa clients via alsa plugin. But I have some Raspberry PIs which don't have any sound-server and just use bluetooth-alsa directly. That Pi Zero embedded project made me think of this.
Is there an exclusive audio mode
in Pipewire? And could it make any things better?. Because some of the instability is coming from pipewire too.
Possibly more related to #13
If I connect my Stadia Bluetooth controller, asha_pipewire_sink will start dropping frames like crazy and disconnect the hearing aids. It's not possible to have both my Stadia controller and hearing aids connected at the same time. Is this a limitation with ASHA protocol or something with Bluez? Because I think you can have more than 3 devices connected at the same time? Most adapters says up to eight devices but that's maybe not true on Linux?
but that's maybe not true on Linux?
Linux can handle 8 devices fine. I believe that the problem is that ASHA requires the host to explicitly set the connection interval, where normally the peripheral negotiates the interval that it needs. Linux does not provide an api for the host to set the connection interval, so we work around that by setting the interval globally for all devices, which is not ideal.
You may have some luck decreasing the interval from 16 to 8. It works for me, but it breaks others.
Linux does not provide an api for the host to set the connection interval, so we work around that by setting the interval globally for all devices, which is not ideal.
Linux in this case is the Bluez Bluetooth stack? I know Google is replacing the Bluez stack with Fluoride in ChromeOS: https://chromeos.dev/en/posts/androids-bluetooth-stack-fluoride-comes-to-chromeos
Just thinking if Fluoride might fix this issue or if the same problem exists in the Fluoride Bluetooth stack?
Linux does not provide an api for the host to set the connection interval, so we work around that by setting the interval globally for all devices, which is not ideal.
Linux in this case is the Bluez Bluetooth stack? I know Google is replacing the Bluez stack with Fluoride in ChromeOS: https://chromeos.dev/en/posts/androids-bluetooth-stack-fluoride-comes-to-chromeos
Just thinking if Fluoride might fix this issue or if the same problem exists in the Fluoride Bluetooth stack?
They seem to be skipping most of the kernel, so it's fair to assume that they don't share the same issues.
Linux does not provide an api for the host to set the connection interval, so we work around that by setting the interval globally for all devices, which is not ideal.
Linux in this case is the Bluez Bluetooth stack? I know Google is replacing the Bluez stack with Fluoride in ChromeOS: https://chromeos.dev/en/posts/androids-bluetooth-stack-fluoride-comes-to-chromeos Just thinking if Fluoride might fix this issue or if the same problem exists in the Fluoride Bluetooth stack?
They seem to be skipping most of the kernel, so it's fair to assume that they don't share the same issues.
According to this website it should be possible to run Flouride on Debian based distros: https://android.googlesource.com/platform/packages/modules/Bluetooth/
@barolo Can you reproduce this using asha_stream_test using the fixed algorithm?
@barolo Can you reproduce this using asha_stream_test using the fixed algorithm?
Yes I can, algorithm doesn't matter.
4. Verify that the configuration has been updated by running
btmgmt read-sysconfig
(root not needed). The values you are looking for areType: 0x0017
andType: 0x0018
, which should now both be0800
instead of1600
Hm, I'm getting the value 1000 with MinConnectionInterval
and MaxConnectionInterval
set to 16...
$ btmgmt read-sysconfig
Type: 0x0017 Length: 02 Value: 1000
Type: 0x0018 Length: 02 Value: 1000
Have not tried to set the values down to 8 yet, but the values are set to 16 and was a bit suprised when the btmgmt
command shows 1000 and not the expected 1600 value...
Are on bluez ver. 5.71 while the last one is ver. 5.76. Maybe this could be the reason?
Have not tried to set the values down to 8 yet, but the values are set to 16 and was a bit suprised when the
btmgmt
command shows 1000 and not the expected 1600 value...
This is expected. the "Value" printed there is little-endian hexidecimal. The values in the config file are decimal, so decimal 16 = hexidecimal 10
@barolo Can you reproduce this using asha_stream_test using the fixed algorithm?
Yes I can, algorithm doesn't matter.
I pushed a new version of asha_stream_test
which has some options for explicitly setting the phy and the ce length. Both of these options require CAP_NET_RAW to work, so you will either need to use setcap to set it, or you need to run it as root.
Of particular interest is the --celength
option, which is used to "suggest" to the peripheral how long it should listen for traffic when it wakes up for network activity. The usual, ASHA spec requires the central (the computer) to set it, but bluetooth normally expects the peripheral to set it. ASHA says that this value should be set to 8, and the android implementation sets it to 12.
I would like you to try --celength 12
and maybe higher values like --celength 16
. If your hearing device's bluetooth stack is religiously following this value instead of adjusting it to fit the connection parameters, then this may help.
Note that asha_stream_test is pretty bad at getting your hearing devices both up and running (I need to fix this), so please get them up and the audio streaming reliably first, and then test what happens when you activate other peripherals.
Also... I would like you to explicitly disable 2M PHY and see if that works better. My original streaming test apps still don't work with 1M PHY, but for some reason, the latest asha_pipewire_sink works great with it. Go figure.
I did some test with asha_stream_test and the only workable setup when it comes to multiple devices [tested with Logitech's BT mouse] is having only one side connected and to use -algo poll with --phy1m [this one probably doesn't matter], it's still unstable and will disconnect eventually. . Fixed will keep breaking with any mouse movement and will disconnect quite fast. If both sides are connected they will just drop frames then disconnect. I can use celength from 4 to 16, It doesn't seem to make any difference though.
I would like you to explicitly disable 2M PHY and see if that works better
I'm not sure how to do this
I would like you to explicitly disable 2M PHY and see if that works better
I'm not sure how to do this
Use btmgmt phy to remove the LE2MTX and LE2MRX entries. On my system that looks like this:
btmgmt phy BR1M1SLOT BR1M3SLOT BR1M5SLOT EDR2M1SLOT EDR2M3SLOT EDR2M5SLOT EDR3M1SLOT EDR3M3SLOT EDR3M5SLOT LE1MTX LE1MRX
I'm not entirely sure its possible for you to disable it though... with your kernel version it may just enable it if both sides support it, regardless of what the global defaults are set to.
I would like you to explicitly disable 2M PHY and see if that works better
I'm not sure how to do this
Use btmgmt phy to remove the LE2MTX and LE2MRX entries. On my system that looks like this:
btmgmt phy BR1M1SLOT BR1M3SLOT BR1M5SLOT EDR2M1SLOT EDR2M3SLOT EDR2M5SLOT EDR3M1SLOT EDR3M3SLOT EDR3M5SLOT LE1MTX LE1MRX
I'm not entirely sure its possible for you to disable it though... with your kernel version it may just enable it if both sides support it, regardless of what the global defaults are set to.
I cannot make it work [asha_pipewire_sink], with both sides and 2M PHY disabled; will start dropping packets, then one side will disconnect.
Also, the weird thing about using sudo ./asha_stream_test --left ../sounds/left.g722 --algorithm poll --volume -64 --celength 16 --phy1m
with mouse connected is, that it will be perfectly stable initially until it's not, and how long it will last seems totally random.
Can you get a btmon capture of the bluetooth traffic when you get a disconnect? use asha_pipewire_sink
this time, and use whatever bluetooth devices you can to get it to drop.
Can you get a btmon capture of the bluetooth traffic when you get a disconnect? use
asha_pipewire_sink
this time, and use whatever bluetooth devices you can to get it to drop.
Here you go btmon.zip My uneducated guess is the issue might be in the stack, at least part of it, since even before launching asha_pipewire_sink it might be hard to connect them all at once, asha_pipewire_sink just exacerbates it, causing everything to disconnect. Would the asha stuff that landed in blueZ master be of any help?
Here you go btmon.zip
Your devices are stingy with the flow control credits. I think they are trying to keep the latency down, but mostly just makes the kernel hesitate a lot before sending.
We are dropping audio before your other bluetooth devices even start sending a lot. I can see your hearing devices just not acknowledging the traffic I'm sending.
Would the asha stuff that landed in blueZ master be of any help?
Probably not. I don't think they will even work together.
Your devices are stingy with the flow control credits. I think they are trying to keep the latency down, but mostly just makes the kernel hesitate a lot before sending.
Actually, now that I think about it, that is probably why the poll algorithm works for you when it doesn't work for anybody else. That polling algorithm waits until your hearing aids dish out another flow control credit before sending the the next packet.
Poll has one downside though, I've noticed that left and right sides are not properly synced [it's slight] and don't create coherent stereo field.
That makes sense. I can see one side going out of sync first, then the other.
That makes sense. I can see one side going out of sync first, then the other.
I don't think that's unique to poll though, it happens in a similar way with all of them.
Use btmgmt phy to remove the LE2MTX and LE2MRX entries. On my system that looks like this:
btmgmt phy BR1M1SLOT BR1M3SLOT BR1M5SLOT EDR2M1SLOT EDR2M3SLOT EDR2M5SLOT EDR3M1SLOT EDR3M3SLOT EDR3M5SLOT LE1MTX LE1MRX
Hi! Tried this but with this setting nothing worked. Just a short "beep" and then disconnect. With LE2MTX LE2MRX it works.
Played around a bit with asha_stream_test
, but then only with the --left
option as I only have one aid. Tried the three different parameters to the --algorithm option. All three played sound, but it is, with the amount of testing that I've done so far, hard to say which one that worked the best. All three started out with stable sound (only latency
messages), but then with "Dropped frame
" message after some time.
I'm not sure whether it is of interest but I collected a btmon
dump file where I was running asha_pipewire_sink
and where the was one disconnect. Attached here: btmon-oticon.zip
Hm, forgot to remove and reestablish the pairing when doing the configuration changes. Could have something to say? Will to some more testing.
(Btw., the testing was done with BT LE keyboard and mouse connected and in use.)
Sorry for the long delay, as I've been distracted adding other features... I've pushed an update with 5 different configurable queuing algorithms in an attempt to work around the lack of flow control information. The only algorithm that doesn't work for me is "none", which doesn't do any queuing at all. I've also added dbus property logging for asha devices. One of those properties is RSSI, which unfortunately only gets logged if the userspace bluez daemon is processing advertisement packets (such as when adding a new bluetooth device).
I would like you to retry your test with either asha_stream_test or asha_pipewire_sink (they both take the same arguments now), while you leave your bluetooth gui's add new device window open. Please note in the program output when the audio starts to get unstable, and note any logged RSSI levels.
Additional BT peripherals, like mouse, keyboard etc. [besides hearing devices] will led to a very unstable stream.