bluetooth: Make use of getsockopt() to determine MTU configurable
authorGeorg Chini <georg@chini.tk>
Sat, 4 Feb 2017 19:32:15 +0000 (20:32 +0100)
committerTanu Kaskinen <tanuk@iki.fi>
Tue, 14 Feb 2017 09:48:10 +0000 (11:48 +0200)
A recent patch changed the MTU size from the default value of 48 to the value
returned by getsockopt(). This breaks HSP for some setups. To circumvent the
problem, this patch introduces a boolean parameter "autodetect_mtu" for
module-bluetooth-discover, module-bluez5-discover and module-bluez5-device to
make this use of getsockopt() configurable.

src/modules/bluetooth/backend-native.c
src/modules/bluetooth/bluez5-util.h
src/modules/bluetooth/module-bluetooth-discover.c
src/modules/bluetooth/module-bluez5-device.c
src/modules/bluetooth/module-bluez5-discover.c

index 4974c3f4b1dde1d1b34559ab1f545d8d09693563..2a5a13a195e05db5f687fb08484cf427928c35e1 100644 (file)
@@ -103,7 +103,6 @@ static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_backend *backend, D
 static int bluez5_sco_acquire_cb(pa_bluetooth_transport *t, bool optional, size_t *imtu, size_t *omtu) {
     pa_bluetooth_device *d = t->device;
     struct sockaddr_sco addr;
-    struct sco_options sco_opt;
     socklen_t len;
     int err, i;
     int sock;
@@ -147,18 +146,21 @@ static int bluez5_sco_acquire_cb(pa_bluetooth_transport *t, bool optional, size_
         goto fail_close;
     }
 
-    len = sizeof(sco_opt);
-    memset(&sco_opt, 0, len);
+    if (imtu) *imtu = 48;
+    if (omtu) *omtu = 48;
 
-    if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, &len) < 0) {
-        pa_log_warn("getsockopt(SCO_OPTIONS) failed, loading defaults");
+    if (t->device->autodetect_mtu) {
+        struct sco_options sco_opt;
 
-        /* Setting defaults in case of error */
-        if (imtu) *imtu = 48;
-        if (omtu) *omtu = 48;
-    } else {
-        if (imtu) *imtu = sco_opt.mtu;
-        if (omtu) *omtu = sco_opt.mtu;
+        len = sizeof(sco_opt);
+        memset(&sco_opt, 0, len);
+
+        if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, &len) < 0)
+            pa_log_warn("getsockopt(SCO_OPTIONS) failed, loading defaults");
+        else {
+            if (imtu) *imtu = sco_opt.mtu;
+            if (omtu) *omtu = sco_opt.mtu;
+        }
     }
 
     return sock;
index 7f124e28719d639a5fc6bca84c7fa0a2dc6009b3..ef0c73142f27d9bd635846e678652ec85d53e1c1 100644 (file)
@@ -95,6 +95,7 @@ struct pa_bluetooth_device {
     bool properties_received;
     bool tried_to_link_with_adapter;
     bool valid;
+    bool autodetect_mtu;
 
     /* Device information */
     char *path;
index fe8aec90596c66cb48047ca9fcd7b674a77602f3..d69a77f10f80c26356c6e3b50f3e31b71c9bc9ce 100644 (file)
@@ -33,6 +33,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(true);
 PA_MODULE_USAGE(
     "headset=ofono|native|auto (bluez 5 only)"
+    "autodetect_mtu=<boolean> (bluez 5 only)"
 );
 
 struct userdata {
index 065fcaa612e46d6472d16369fa466648c19616d3..47842f792fbae4935ede1c9f780e9ac8924c6a7e 100644 (file)
@@ -54,7 +54,8 @@ PA_MODULE_AUTHOR("João Paulo Rechi Vita");
 PA_MODULE_DESCRIPTION("BlueZ 5 Bluetooth audio sink and source");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(false);
-PA_MODULE_USAGE("path=<device object path>");
+PA_MODULE_USAGE("path=<device object path>"
+                "autodetect_mtu=<boolean>");
 
 #define MAX_PLAYBACK_CATCH_UP_USEC (100 * PA_USEC_PER_MSEC)
 #define FIXED_LATENCY_PLAYBACK_A2DP (25 * PA_USEC_PER_MSEC)
@@ -68,6 +69,7 @@ PA_MODULE_USAGE("path=<device object path>");
 
 static const char* const valid_modargs[] = {
     "path",
+    "autodetect_mtu",
     NULL
 };
 
@@ -2158,6 +2160,7 @@ int pa__init(pa_module* m) {
     struct userdata *u;
     const char *path;
     pa_modargs *ma;
+    bool autodetect_mtu;
 
     pa_assert(m);
 
@@ -2187,6 +2190,14 @@ int pa__init(pa_module* m) {
         goto fail_free_modargs;
     }
 
+    autodetect_mtu = true;
+    if (pa_modargs_get_value_boolean(ma, "autodetect_mtu", &autodetect_mtu) < 0) {
+        pa_log("Invalid boolean value for autodetect_mtu parameter");
+        goto fail_free_modargs;
+    }
+
+    u->device->autodetect_mtu = autodetect_mtu;
+
     pa_modargs_free(ma);
 
     u->device_connection_changed_slot =
index 080e5d0a6dd4fc24a4ef953002a272a51282efb5..bc5dbd49e543c8961fa01c311ba75ba1fb61b20c 100644 (file)
@@ -42,6 +42,7 @@ PA_MODULE_USAGE(
 
 static const char* const valid_modargs[] = {
     "headset",
+    "autodetect_mtu",
     NULL
 };
 
@@ -51,6 +52,7 @@ struct userdata {
     pa_hashmap *loaded_device_paths;
     pa_hook_slot *device_connection_changed_slot;
     pa_bluetooth_discovery *discovery;
+    bool autodetect_mtu;
 };
 
 static pa_hook_result_t device_connection_changed_cb(pa_bluetooth_discovery *y, const pa_bluetooth_device *d, struct userdata *u) {
@@ -71,7 +73,7 @@ static pa_hook_result_t device_connection_changed_cb(pa_bluetooth_discovery *y,
     if (!module_loaded && pa_bluetooth_device_any_transport_connected(d)) {
         /* a new device has been connected */
         pa_module *m;
-        char *args = pa_sprintf_malloc("path=%s", d->path);
+        char *args = pa_sprintf_malloc("path=%s autodetect_mtu=%i", d->path, (int)u->autodetect_mtu);
 
         pa_log_debug("Loading module-bluez5-device %s", args);
         m = pa_module_load(u->module->core, "module-bluez5-device", args);
@@ -101,6 +103,7 @@ int pa__init(pa_module *m) {
     pa_modargs *ma;
     const char *headset_str;
     int headset_backend;
+    bool autodetect_mtu;
 
     pa_assert(m);
 
@@ -121,9 +124,16 @@ int pa__init(pa_module *m) {
         goto fail;
     }
 
+    autodetect_mtu = true;
+    if (pa_modargs_get_value_boolean(ma, "autodetect_mtu", &autodetect_mtu) < 0) {
+        pa_log("Invalid boolean value for autodetect_mtu parameter");
+        goto fail;
+    }
+
     m->userdata = u = pa_xnew0(struct userdata, 1);
     u->module = m;
     u->core = m->core;
+    u->autodetect_mtu = autodetect_mtu;
     u->loaded_device_paths = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
 
     if (!(u->discovery = pa_bluetooth_discovery_get(u->core, headset_backend)))