[pulseaudio-discuss] [PATCH v0] bluetooth: Fix potential assertion failure during pairing
Mikel Astiz
mikel.astiz.oss at gmail.com
Mon Feb 11 02:42:53 PST 2013
From: Mikel Astiz <mikel.astiz at bmw-carit.de>
Commit 40329acc1a28145643e49207e9d65cd05bbda2c8 introduced a potential
issue during headset pairing. If a headset supporting both HSP/HFP and
A2DP is paired, and a late UUID (i.e. A2DP) is announced after HSP/HFP
is already connected, the code in uuid_added_cb() can result in
duplicated port creation and therefore an assertion failure:
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.Headset, path=/org/bluez/12840/hci0/dev_00_13_1E_1F_F1_53, member=PropertyChanged
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.MediaTransport, path=/org/bluez/12840/hci0/dev_00_13_1E_1F_F1_53/fd0, member=PropertyChanged
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.Device, path=/org/bluez/12840/hci0/dev_00_13_1E_1F_F1_53, member=PropertyChanged
D: [pulseaudio] protocol-dbus.c: Interface org.PulseAudio.Core1.CardProfile added for object /org/pulseaudio/core1/card3/profile2
E: [pulseaudio] card.c: Assertion 'pa_hashmap_put(c->ports, p->name, p) >= 0' failed at pulsecore/card.c:107, function pa_card_add_ports(). Aborting.
The issue is very unlikely to reproduce but gains interest if further
ports needs to be merged in the future as well.
---
src/modules/bluetooth/module-bluetooth-device.c | 42 +++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 33b2afa..9921892 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -2401,6 +2401,44 @@ static pa_bluetooth_device* find_device(struct userdata *u, const char *address,
}
/* Run from main thread */
+static void handle_duplicated_ports(struct userdata *u, pa_hashmap *new_ports) {
+ void *state;
+ pa_device_port *new_port;
+ pa_device_port *old_port;
+
+ pa_assert(u);
+ pa_assert(new_ports);
+
+ /* Late-announced UUIDs might create duplicated ports because the code in
+ * create_ports_for_profile() does not consider previously existing ports.
+ * The scenario is very unlikely but possible if a headset being paired
+ * connects HSP/HFP before the A2DP UUID is received. In this case the port
+ * "bluetooth-output" will already exist and therefore it has to be removed
+ * from the new_ports hashmap */
+ PA_HASHMAP_FOREACH(new_port, new_ports, state) {
+ if ((old_port = pa_hashmap_get(u->card->ports, new_port->name)) == NULL)
+ continue;
+
+ pa_assert(new_port->is_input == old_port->is_input);
+ pa_assert(new_port->is_output == old_port->is_output);
+
+ /* FIXME: we should not modify the port's priority without a proper hook
+ * to propagate this change. However, the scenario is very unlikely and
+ * other extensions to the core are recently being discussed which would
+ * also fix this minor issue */
+ old_port->priority = PA_MAX(old_port->priority, new_port->priority);
+
+ if (new_port->available == PA_PORT_AVAILABLE_YES)
+ pa_device_port_set_available(old_port, PA_PORT_AVAILABLE_YES);
+ else if (new_port->available == PA_PORT_AVAILABLE_UNKNOWN && old_port->available == PA_PORT_AVAILABLE_NO)
+ pa_device_port_set_available(old_port, PA_PORT_AVAILABLE_UNKNOWN);
+
+ pa_hashmap_remove(new_ports, new_port->name);
+ pa_device_port_unref(new_port);
+ }
+}
+
+/* Run from main thread */
static pa_hook_result_t uuid_added_cb(pa_bluetooth_discovery *y, const struct pa_bluetooth_hook_uuid_data *data,
struct userdata *u) {
pa_card_profile *p;
@@ -2414,6 +2452,8 @@ static pa_hook_result_t uuid_added_cb(pa_bluetooth_discovery *y, const struct pa
if (data->device != u->device)
return PA_HOOK_OK;
+ pa_log_info("Device %s: new UUID '%s'", data->device->path, data->uuid);
+
p = create_card_profile(u, data->uuid);
if (!p)
@@ -2430,6 +2470,8 @@ static pa_hook_result_t uuid_added_cb(pa_bluetooth_discovery *y, const struct pa
create_ports_for_profile(u, new_ports, p);
+ handle_duplicated_ports(u, new_ports);
+
pa_card_add_ports(u->card, new_ports);
pa_device_port_hashmap_free(new_ports);
--
1.8.1
More information about the pulseaudio-discuss
mailing list