[pulseaudio-discuss] [PATCH v1] bluetooth: Dynamically change outgoing MTU

Mikel Astiz mikel.astiz.oss at gmail.com
Tue Mar 12 02:32:44 PDT 2013

From: Mikel Astiz <mikel.astiz at bmw-carit.de>

Dynamically change the size of the SCO packets according to the size of
the received ones.
This patch has been hanging around for some time since our last discussion [1].

I haven't been able to clarify why exactly this MTU change is needed, but it can be experimentally observed that several Bluetooth chips from different manufacturers behave similarly: when two SCO streams are set up, the size of the packets doubles.

My best guess is that it's influenced by the constraints in the USB transport layer, but I wasn't able to confirm this yet nor was I able to find such behavior in the Bluetooth spec.

In any case, I believe the patch should do no harm.

This v1 proposal rewrites the patch in a more conservative way. The MTU changes are accepted only if they match the known pattern of changing between 48 and 96 back and forth.

You can test this patch by connecting two headsets (or two phones or whatever else doing HFP/HSP). You probably also need to change the adapter's SCO MTU by doing:

sudo ./hciconfig hci0 scomtu 96:8

[1] http://thread.gmane.org/gmane.comp.audio.pulseaudio.general/12982/focus=15363

 src/modules/bluetooth/module-bluetooth-device.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index c877df2..552db4b 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -625,7 +625,8 @@ static int hsp_process_push(struct userdata *u) {
-    memchunk.memblock = pa_memblock_new(u->core->mempool, u->read_block_size);
+    /* Read minimum 96 bytes to be able to detect multi-SCO setup */
+    memchunk.memblock = pa_memblock_new(u->core->mempool, PA_MAX(96U, u->read_block_size));
     memchunk.index = memchunk.length = 0;
     for (;;) {
@@ -681,6 +682,23 @@ static int hsp_process_push(struct userdata *u) {
+        /* In order to support multi-SCO scenarios, adapt size of I/O blocks
+         * according to the size we just got, only considering the typical MTU
+         * changes observed in these cases */
+        if ((size_t) l != u->read_link_mtu && (l == 48U || l == 96U)) {
+            pa_log_info("SCO MTU change detected: %zu->%zd", u->write_block_size, l);
+            u->read_link_mtu = (size_t) l;
+            u->write_link_mtu = (size_t) l;
+            bt_transport_config_mtu(u);
+            if (u->write_memchunk.memblock) {
+                pa_memblock_unref(u->write_memchunk.memblock);
+                pa_memchunk_reset(&u->write_memchunk);
+            }
+        }
         memchunk.length = (size_t) l;
         u->read_index += (uint64_t) l;

More information about the pulseaudio-discuss mailing list