summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTanu Kaskinen <tanuk@iki.fi>2016-08-03 23:41:31 +0300
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-09-23 15:27:03 +0100
commit0271b3ab00cec06e510c04d651f77c2210bda1a3 (patch)
treeeb32413fb4fc223bc3aeecd83d63e97baa85f2dd
parent4cbb398d852ee689ce9fc7e42a5429118a6179a5 (diff)
downloadpoky-0271b3ab00cec06e510c04d651f77c2210bda1a3.tar.gz
pulseaudio: fix crash when disconnecting bluetooth devices
[YOCTO #10018] Add a patch that makes the bluetooth code create the HSP/HFP card profile only once. The old behaviour of creating the profile twice was not compatible with 0001-card-add-pa_card_profile.ports.patch. This fix is not needed for master, because master doesn't any more have 0001-card-add-pa_card_profile.ports.patch. (From OE-Core rev: e416c32f6059a5d4cb47809186c2feaaef7ff4ba) Signed-off-by: Tanu Kaskinen <tanuk@iki.fi> Signed-off-by: Armin Kuster <akuster808@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/recipes-multimedia/pulseaudio/pulseaudio/0001-bluetooth-don-t-create-the-HSP-HFP-profile-twice.patch343
-rw-r--r--meta/recipes-multimedia/pulseaudio/pulseaudio_8.0.bb1
2 files changed, 344 insertions, 0 deletions
diff --git a/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-bluetooth-don-t-create-the-HSP-HFP-profile-twice.patch b/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-bluetooth-don-t-create-the-HSP-HFP-profile-twice.patch
new file mode 100644
index 0000000000..a5ca325ba8
--- /dev/null
+++ b/meta/recipes-multimedia/pulseaudio/pulseaudio/0001-bluetooth-don-t-create-the-HSP-HFP-profile-twice.patch
@@ -0,0 +1,343 @@
1From 14ff15bf5acac7b7edd64e2240fc6fe5d227b8c4 Mon Sep 17 00:00:00 2001
2From: Tanu Kaskinen <tanuk@iki.fi>
3Date: Sun, 31 Jul 2016 01:03:02 +0300
4Subject: [PATCH] bluetooth: don't create the HSP/HFP profile twice
5
6create_card_profile() used to get called separately for HSP and HFP,
7so if a headset supports both profiles, a profile named
8"headset_head_unit" would get created twice. The second instance would
9get immediately freed, so that wasn't a particularly serious problem.
10However, I think it makes more sense to create the profile only once.
11This patch makes things so that before a profile is created, we check
12what name that profile would have, and if a profile with that name
13already exists, we don't create the profile.
14
15A couple of Yocto releases (jethro and krogoth) have non-upstream
16patches that suffer from this double creation. The patches add
17associations between profiles and ports, and those associations use
18the profile name as the key. When the second profile gets freed, the
19associations between the profile and its ports get removed, and since
20the profile name is used as the key, this erroneously affects the
21first profile too. Crashing ensues.
22
23I have tested this only with BlueZ 5.
24
25BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
26
27Upstream-Status: Submitted [https://patchwork.freedesktop.org/patch/101926/]
28
29Signed-off-by: Tanu Kaskinen <tanuk@iki.fi>
30---
31 src/modules/bluetooth/module-bluez4-device.c | 81 +++++++++++++++++-----------
32 src/modules/bluetooth/module-bluez5-device.c | 72 ++++++++++++++++---------
33 2 files changed, 99 insertions(+), 54 deletions(-)
34
35diff --git a/src/modules/bluetooth/module-bluez4-device.c b/src/modules/bluetooth/module-bluez4-device.c
36index 5d0d3db..df51168 100644
37--- a/src/modules/bluetooth/module-bluez4-device.c
38+++ b/src/modules/bluetooth/module-bluez4-device.c
39@@ -2162,18 +2162,23 @@ static void create_card_ports(struct userdata *u, pa_hashmap *ports) {
40 }
41
42 /* Run from main thread */
43-static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid, pa_hashmap *ports) {
44+static pa_card_profile *create_card_profile(struct userdata *u, pa_bluez4_profile_t profile, pa_hashmap *ports) {
45 pa_device_port *input_port, *output_port;
46+ const char *name;
47 pa_card_profile *p = NULL;
48- pa_bluez4_profile_t *d;
49+ pa_bluez4_profile_t *d = NULL;
50+ pa_bluez4_transport *t;
51
52 pa_assert(u->input_port_name);
53 pa_assert(u->output_port_name);
54 pa_assert_se(input_port = pa_hashmap_get(ports, u->input_port_name));
55 pa_assert_se(output_port = pa_hashmap_get(ports, u->output_port_name));
56
57- if (pa_streq(uuid, A2DP_SINK_UUID)) {
58- p = pa_card_profile_new("a2dp", _("High Fidelity Playback (A2DP)"), sizeof(pa_bluez4_profile_t));
59+ name = pa_bluez4_profile_to_string(profile);
60+
61+ switch (profile) {
62+ case PA_BLUEZ4_PROFILE_A2DP:
63+ p = pa_card_profile_new(name, _("High Fidelity Playback (A2DP)"), sizeof(pa_bluez4_profile_t));
64 p->priority = 10;
65 p->n_sinks = 1;
66 p->n_sources = 0;
67@@ -2183,9 +2188,10 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
68 pa_card_profile_add_port(p, output_port);
69
70 d = PA_CARD_PROFILE_DATA(p);
71- *d = PA_BLUEZ4_PROFILE_A2DP;
72- } else if (pa_streq(uuid, A2DP_SOURCE_UUID)) {
73- p = pa_card_profile_new("a2dp_source", _("High Fidelity Capture (A2DP)"), sizeof(pa_bluez4_profile_t));
74+ break;
75+
76+ case PA_BLUEZ4_PROFILE_A2DP_SOURCE:
77+ p = pa_card_profile_new(name, _("High Fidelity Capture (A2DP)"), sizeof(pa_bluez4_profile_t));
78 p->priority = 10;
79 p->n_sinks = 0;
80 p->n_sources = 1;
81@@ -2195,9 +2201,10 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
82 pa_card_profile_add_port(p, input_port);
83
84 d = PA_CARD_PROFILE_DATA(p);
85- *d = PA_BLUEZ4_PROFILE_A2DP_SOURCE;
86- } else if (pa_streq(uuid, HSP_HS_UUID) || pa_streq(uuid, HFP_HS_UUID)) {
87- p = pa_card_profile_new("hsp", _("Telephony Duplex (HSP/HFP)"), sizeof(pa_bluez4_profile_t));
88+ break;
89+
90+ case PA_BLUEZ4_PROFILE_HSP:
91+ p = pa_card_profile_new(name, _("Telephony Duplex (HSP/HFP)"), sizeof(pa_bluez4_profile_t));
92 p->priority = 20;
93 p->n_sinks = 1;
94 p->n_sources = 1;
95@@ -2209,9 +2216,10 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
96 pa_card_profile_add_port(p, output_port);
97
98 d = PA_CARD_PROFILE_DATA(p);
99- *d = PA_BLUEZ4_PROFILE_HSP;
100- } else if (pa_streq(uuid, HFP_AG_UUID)) {
101- p = pa_card_profile_new("hfgw", _("Handsfree Gateway"), sizeof(pa_bluez4_profile_t));
102+ break;
103+
104+ case PA_BLUEZ4_PROFILE_HFGW:
105+ p = pa_card_profile_new(name, _("Handsfree Gateway"), sizeof(pa_bluez4_profile_t));
106 p->priority = 20;
107 p->n_sinks = 1;
108 p->n_sources = 1;
109@@ -2223,19 +2231,35 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
110 pa_card_profile_add_port(p, output_port);
111
112 d = PA_CARD_PROFILE_DATA(p);
113- *d = PA_BLUEZ4_PROFILE_HFGW;
114+ break;
115+
116+ case PA_BLUEZ4_PROFILE_OFF:
117+ pa_assert_not_reached();
118 }
119
120- if (p) {
121- pa_bluez4_transport *t;
122+ *d = profile;
123
124- if ((t = u->device->transports[*d]))
125- p->available = transport_state_to_availability(t->state);
126- }
127+ if ((t = u->device->transports[*d]))
128+ p->available = transport_state_to_availability(t->state);
129
130 return p;
131 }
132
133+static int uuid_to_profile(const char *uuid, pa_bluez4_profile_t *_r) {
134+ if (pa_streq(uuid, A2DP_SINK_UUID))
135+ *_r = PA_BLUEZ4_PROFILE_A2DP;
136+ else if (pa_streq(uuid, A2DP_SOURCE_UUID))
137+ *_r = PA_BLUEZ4_PROFILE_A2DP_SOURCE;
138+ else if (pa_streq(uuid, HSP_HS_UUID) || pa_streq(uuid, HFP_HS_UUID))
139+ *_r = PA_BLUEZ4_PROFILE_HSP;
140+ else if (pa_streq(uuid, HSP_AG_UUID) || pa_streq(uuid, HFP_AG_UUID))
141+ *_r = PA_BLUEZ4_PROFILE_HFGW;
142+ else
143+ return -PA_ERR_INVALID;
144+
145+ return 0;
146+}
147+
148 /* Run from main thread */
149 static int add_card(struct userdata *u) {
150 pa_card_new_data data;
151@@ -2283,16 +2307,15 @@ static int add_card(struct userdata *u) {
152 create_card_ports(u, data.ports);
153
154 PA_LLIST_FOREACH(uuid, device->uuids) {
155- p = create_card_profile(u, uuid->uuid, data.ports);
156+ pa_bluez4_profile_t profile;
157
158- if (!p)
159+ if (uuid_to_profile(uuid->uuid, &profile) < 0)
160 continue;
161
162- if (pa_hashmap_get(data.profiles, p->name)) {
163- pa_card_profile_free(p);
164+ if (pa_hashmap_get(data.profiles, pa_bluez4_profile_to_string(profile)))
165 continue;
166- }
167
168+ p = create_card_profile(u, profile, data.ports);
169 pa_hashmap_put(data.profiles, p->name, p);
170 }
171
172@@ -2382,6 +2405,7 @@ static pa_bluez4_device* find_device(struct userdata *u, const char *address, co
173 /* Run from main thread */
174 static pa_hook_result_t uuid_added_cb(pa_bluez4_discovery *y, const struct pa_bluez4_hook_uuid_data *data,
175 struct userdata *u) {
176+ pa_bluez4_profile_t profile;
177 pa_card_profile *p;
178
179 pa_assert(data);
180@@ -2392,16 +2416,13 @@ static pa_hook_result_t uuid_added_cb(pa_bluez4_discovery *y, const struct pa_bl
181 if (data->device != u->device)
182 return PA_HOOK_OK;
183
184- p = create_card_profile(u, data->uuid, u->card->ports);
185-
186- if (!p)
187+ if (uuid_to_profile(data->uuid, &profile) < 0)
188 return PA_HOOK_OK;
189
190- if (pa_hashmap_get(u->card->profiles, p->name)) {
191- pa_card_profile_free(p);
192+ if (pa_hashmap_get(u->card->profiles, pa_bluez4_profile_to_string(profile)))
193 return PA_HOOK_OK;
194- }
195
196+ p = create_card_profile(u, profile, u->card->ports);
197 pa_card_add_profile(u->card, p);
198
199 return PA_HOOK_OK;
200diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
201index 7b90a31..db06ac1 100644
202--- a/src/modules/bluetooth/module-bluez5-device.c
203+++ b/src/modules/bluetooth/module-bluez5-device.c
204@@ -1772,8 +1772,9 @@ static void create_card_ports(struct userdata *u, pa_hashmap *ports) {
205 }
206
207 /* Run from main thread */
208-static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid, pa_hashmap *ports) {
209+static pa_card_profile *create_card_profile(struct userdata *u, pa_bluetooth_profile_t profile, pa_hashmap *ports) {
210 pa_device_port *input_port, *output_port;
211+ const char *name;
212 pa_card_profile *cp = NULL;
213 pa_bluetooth_profile_t *p;
214
215@@ -1782,8 +1783,11 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
216 pa_assert_se(input_port = pa_hashmap_get(ports, u->input_port_name));
217 pa_assert_se(output_port = pa_hashmap_get(ports, u->output_port_name));
218
219- if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK)) {
220- cp = pa_card_profile_new("a2dp_sink", _("High Fidelity Playback (A2DP Sink)"), sizeof(pa_bluetooth_profile_t));
221+ name = pa_bluetooth_profile_to_string(profile);
222+
223+ switch (profile) {
224+ case PA_BLUETOOTH_PROFILE_A2DP_SINK:
225+ cp = pa_card_profile_new(name, _("High Fidelity Playback (A2DP Sink)"), sizeof(pa_bluetooth_profile_t));
226 cp->priority = 10;
227 cp->n_sinks = 1;
228 cp->n_sources = 0;
229@@ -1793,9 +1797,10 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
230 pa_card_profile_add_port(cp, output_port);
231
232 p = PA_CARD_PROFILE_DATA(cp);
233- *p = PA_BLUETOOTH_PROFILE_A2DP_SINK;
234- } else if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SOURCE)) {
235- cp = pa_card_profile_new("a2dp_source", _("High Fidelity Capture (A2DP Source)"), sizeof(pa_bluetooth_profile_t));
236+ break;
237+
238+ case PA_BLUETOOTH_PROFILE_A2DP_SOURCE:
239+ cp = pa_card_profile_new(name, _("High Fidelity Capture (A2DP Source)"), sizeof(pa_bluetooth_profile_t));
240 cp->priority = 10;
241 cp->n_sinks = 0;
242 cp->n_sources = 1;
243@@ -1805,9 +1810,10 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
244 pa_card_profile_add_port(cp, input_port);
245
246 p = PA_CARD_PROFILE_DATA(cp);
247- *p = PA_BLUETOOTH_PROFILE_A2DP_SOURCE;
248- } else if (pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_HS) || pa_streq(uuid, PA_BLUETOOTH_UUID_HFP_HF)) {
249- cp = pa_card_profile_new("headset_head_unit", _("Headset Head Unit (HSP/HFP)"), sizeof(pa_bluetooth_profile_t));
250+ break;
251+
252+ case PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT:
253+ cp = pa_card_profile_new(name, _("Headset Head Unit (HSP/HFP)"), sizeof(pa_bluetooth_profile_t));
254 cp->priority = 20;
255 cp->n_sinks = 1;
256 cp->n_sources = 1;
257@@ -1819,9 +1825,10 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
258 pa_card_profile_add_port(cp, output_port);
259
260 p = PA_CARD_PROFILE_DATA(cp);
261- *p = PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT;
262- } else if (pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_AG) || pa_streq(uuid, PA_BLUETOOTH_UUID_HFP_AG)) {
263- cp = pa_card_profile_new("headset_audio_gateway", _("Headset Audio Gateway (HSP/HFP)"), sizeof(pa_bluetooth_profile_t));
264+ break;
265+
266+ case PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY:
267+ cp = pa_card_profile_new(name, _("Headset Audio Gateway (HSP/HFP)"), sizeof(pa_bluetooth_profile_t));
268 cp->priority = 20;
269 cp->n_sinks = 1;
270 cp->n_sources = 1;
271@@ -1833,16 +1840,19 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid
272 pa_card_profile_add_port(cp, output_port);
273
274 p = PA_CARD_PROFILE_DATA(cp);
275- *p = PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY;
276- }
277+ break;
278
279- if (cp) {
280- if (u->device->transports[*p])
281- cp->available = transport_state_to_availability(u->device->transports[*p]->state);
282- else
283- cp->available = PA_AVAILABLE_NO;
284+ case PA_BLUETOOTH_PROFILE_OFF:
285+ pa_assert_not_reached();
286 }
287
288+ *p = profile;
289+
290+ if (u->device->transports[*p])
291+ cp->available = transport_state_to_availability(u->device->transports[*p]->state);
292+ else
293+ cp->available = PA_AVAILABLE_NO;
294+
295 return cp;
296 }
297
298@@ -1888,6 +1898,21 @@ off:
299 return -PA_ERR_IO;
300 }
301
302+static int uuid_to_profile(const char *uuid, pa_bluetooth_profile_t *_r) {
303+ if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK))
304+ *_r = PA_BLUETOOTH_PROFILE_A2DP_SINK;
305+ else if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SOURCE))
306+ *_r = PA_BLUETOOTH_PROFILE_A2DP_SOURCE;
307+ else if (pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_HS) || pa_streq(uuid, PA_BLUETOOTH_UUID_HFP_HF))
308+ *_r = PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT;
309+ else if (pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_AG) || pa_streq(uuid, PA_BLUETOOTH_UUID_HFP_AG))
310+ *_r = PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY;
311+ else
312+ return -PA_ERR_INVALID;
313+
314+ return 0;
315+}
316+
317 /* Run from main thread */
318 static int add_card(struct userdata *u) {
319 const pa_bluetooth_device *d;
320@@ -1929,16 +1954,15 @@ static int add_card(struct userdata *u) {
321 create_card_ports(u, data.ports);
322
323 PA_HASHMAP_FOREACH(uuid, d->uuids, state) {
324- cp = create_card_profile(u, uuid, data.ports);
325+ pa_bluetooth_profile_t profile;
326
327- if (!cp)
328+ if (uuid_to_profile(uuid, &profile) < 0)
329 continue;
330
331- if (pa_hashmap_get(data.profiles, cp->name)) {
332- pa_card_profile_free(cp);
333+ if (pa_hashmap_get(data.profiles, pa_bluetooth_profile_to_string(profile)))
334 continue;
335- }
336
337+ cp = create_card_profile(u, profile, data.ports);
338 pa_hashmap_put(data.profiles, cp->name, cp);
339 }
340
341--
3422.8.1
343
diff --git a/meta/recipes-multimedia/pulseaudio/pulseaudio_8.0.bb b/meta/recipes-multimedia/pulseaudio/pulseaudio_8.0.bb
index b01ba8f689..b947c62812 100644
--- a/meta/recipes-multimedia/pulseaudio/pulseaudio_8.0.bb
+++ b/meta/recipes-multimedia/pulseaudio/pulseaudio_8.0.bb
@@ -9,6 +9,7 @@ SRC_URI = "http://freedesktop.org/software/pulseaudio/releases/${BP}.tar.xz \
9 file://0003-card-move-profile-selection-after-pa_card_new.patch \ 9 file://0003-card-move-profile-selection-after-pa_card_new.patch \
10 file://0004-alsa-set-availability-for-some-unavailable-profiles.patch \ 10 file://0004-alsa-set-availability-for-some-unavailable-profiles.patch \
11 file://0001-Revert-module-switch-on-port-available-Route-to-pref.patch \ 11 file://0001-Revert-module-switch-on-port-available-Route-to-pref.patch \
12 file://0001-bluetooth-don-t-create-the-HSP-HFP-profile-twice.patch \
12" 13"
13SRC_URI[md5sum] = "8678442ba0bb4b4c33ac6f62542962df" 14SRC_URI[md5sum] = "8678442ba0bb4b4c33ac6f62542962df"
14SRC_URI[sha256sum] = "690eefe28633466cfd1ab9d85ebfa9376f6b622deec6bfee5091ac9737cd1989" 15SRC_URI[sha256sum] = "690eefe28633466cfd1ab9d85ebfa9376f6b622deec6bfee5091ac9737cd1989"