]> code.delx.au - pulseaudio/blob - src/modules/bluetooth/module-bluez5-device.c
bluetooth: Create sink for BlueZ 5 cards
[pulseaudio] / src / modules / bluetooth / module-bluez5-device.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2008-2013 João Paulo Rechi Vita
5 Copyright 2011-2013 BMW Car IT GmbH.
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of the
10 License, or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <sbc/sbc.h>
28
29 #include <pulsecore/core-util.h>
30 #include <pulsecore/i18n.h>
31 #include <pulsecore/module.h>
32 #include <pulsecore/modargs.h>
33
34 #include "a2dp-codecs.h"
35 #include "bluez5-util.h"
36
37 #include "module-bluez5-device-symdef.h"
38
39 PA_MODULE_AUTHOR("João Paulo Rechi Vita");
40 PA_MODULE_DESCRIPTION("BlueZ 5 Bluetooth audio sink and source");
41 PA_MODULE_VERSION(PACKAGE_VERSION);
42 PA_MODULE_LOAD_ONCE(false);
43 PA_MODULE_USAGE("path=<device object path>");
44
45 static const char* const valid_modargs[] = {
46 "path",
47 NULL
48 };
49
50 typedef struct sbc_info {
51 sbc_t sbc; /* Codec data */
52 bool sbc_initialized; /* Keep track if the encoder is initialized */
53 size_t codesize, frame_length; /* SBC Codesize, frame_length. We simply cache those values here */
54 uint16_t seq_num; /* Cumulative packet sequence */
55 uint8_t min_bitpool;
56 uint8_t max_bitpool;
57
58 void* buffer; /* Codec transfer buffer */
59 size_t buffer_size; /* Size of the buffer */
60 } sbc_info_t;
61
62 struct userdata {
63 pa_module *module;
64 pa_core *core;
65
66 pa_hook_slot *device_connection_changed_slot;
67
68 pa_bluetooth_discovery *discovery;
69 pa_bluetooth_device *device;
70 pa_bluetooth_transport *transport;
71 bool transport_acquired;
72
73 pa_card *card;
74 pa_sink *sink;
75 pa_bluetooth_profile_t profile;
76 char *output_port_name;
77 char *input_port_name;
78
79 int stream_fd;
80 size_t read_link_mtu;
81 size_t write_link_mtu;
82 size_t read_block_size;
83 size_t write_block_size;
84 pa_sample_spec sample_spec;
85 struct sbc_info sbc_info;
86 };
87
88 typedef enum pa_bluetooth_form_factor {
89 PA_BLUETOOTH_FORM_FACTOR_UNKNOWN,
90 PA_BLUETOOTH_FORM_FACTOR_HEADSET,
91 PA_BLUETOOTH_FORM_FACTOR_HANDSFREE,
92 PA_BLUETOOTH_FORM_FACTOR_MICROPHONE,
93 PA_BLUETOOTH_FORM_FACTOR_SPEAKER,
94 PA_BLUETOOTH_FORM_FACTOR_HEADPHONE,
95 PA_BLUETOOTH_FORM_FACTOR_PORTABLE,
96 PA_BLUETOOTH_FORM_FACTOR_CAR,
97 PA_BLUETOOTH_FORM_FACTOR_HIFI,
98 PA_BLUETOOTH_FORM_FACTOR_PHONE,
99 } pa_bluetooth_form_factor_t;
100
101 /* Run from main thread */
102 static pa_bluetooth_form_factor_t form_factor_from_class(uint32_t class_of_device) {
103 unsigned major, minor;
104 pa_bluetooth_form_factor_t r;
105
106 static const pa_bluetooth_form_factor_t table[] = {
107 [1] = PA_BLUETOOTH_FORM_FACTOR_HEADSET,
108 [2] = PA_BLUETOOTH_FORM_FACTOR_HANDSFREE,
109 [4] = PA_BLUETOOTH_FORM_FACTOR_MICROPHONE,
110 [5] = PA_BLUETOOTH_FORM_FACTOR_SPEAKER,
111 [6] = PA_BLUETOOTH_FORM_FACTOR_HEADPHONE,
112 [7] = PA_BLUETOOTH_FORM_FACTOR_PORTABLE,
113 [8] = PA_BLUETOOTH_FORM_FACTOR_CAR,
114 [10] = PA_BLUETOOTH_FORM_FACTOR_HIFI
115 };
116
117 /*
118 * See Bluetooth Assigned Numbers:
119 * https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm
120 */
121 major = (class_of_device >> 8) & 0x1F;
122 minor = (class_of_device >> 2) & 0x3F;
123
124 switch (major) {
125 case 2:
126 return PA_BLUETOOTH_FORM_FACTOR_PHONE;
127 case 4:
128 break;
129 default:
130 pa_log_debug("Unknown Bluetooth major device class %u", major);
131 return PA_BLUETOOTH_FORM_FACTOR_UNKNOWN;
132 }
133
134 r = minor < PA_ELEMENTSOF(table) ? table[minor] : PA_BLUETOOTH_FORM_FACTOR_UNKNOWN;
135
136 if (!r)
137 pa_log_debug("Unknown Bluetooth minor device class %u", minor);
138
139 return r;
140 }
141
142 /* Run from main thread */
143 static const char *form_factor_to_string(pa_bluetooth_form_factor_t ff) {
144 switch (ff) {
145 case PA_BLUETOOTH_FORM_FACTOR_UNKNOWN:
146 return "unknown";
147 case PA_BLUETOOTH_FORM_FACTOR_HEADSET:
148 return "headset";
149 case PA_BLUETOOTH_FORM_FACTOR_HANDSFREE:
150 return "hands-free";
151 case PA_BLUETOOTH_FORM_FACTOR_MICROPHONE:
152 return "microphone";
153 case PA_BLUETOOTH_FORM_FACTOR_SPEAKER:
154 return "speaker";
155 case PA_BLUETOOTH_FORM_FACTOR_HEADPHONE:
156 return "headphone";
157 case PA_BLUETOOTH_FORM_FACTOR_PORTABLE:
158 return "portable";
159 case PA_BLUETOOTH_FORM_FACTOR_CAR:
160 return "car";
161 case PA_BLUETOOTH_FORM_FACTOR_HIFI:
162 return "hifi";
163 case PA_BLUETOOTH_FORM_FACTOR_PHONE:
164 return "phone";
165 }
166
167 pa_assert_not_reached();
168 }
169
170 /* Run from main thread */
171 static void connect_ports(struct userdata *u, void *new_data, pa_direction_t direction) {
172 pa_device_port *port;
173
174 if (direction == PA_DIRECTION_OUTPUT) {
175 pa_sink_new_data *sink_new_data = new_data;
176
177 pa_assert_se(port = pa_hashmap_get(u->card->ports, u->output_port_name));
178 pa_assert_se(pa_hashmap_put(sink_new_data->ports, port->name, port) >= 0);
179 pa_device_port_ref(port);
180 } else {
181 pa_source_new_data *source_new_data = new_data;
182
183 pa_assert_se(port = pa_hashmap_get(u->card->ports, u->input_port_name));
184 pa_assert_se(pa_hashmap_put(source_new_data->ports, port->name, port) >= 0);
185 pa_device_port_ref(port);
186 }
187 }
188
189 static int transport_acquire(struct userdata *u, bool optional) {
190 pa_assert(u->transport);
191
192 if (u->transport_acquired)
193 return 0;
194
195 pa_log_debug("Acquiring transport %s", u->transport->path);
196
197 u->stream_fd = u->transport->acquire(u->transport, optional, &u->read_link_mtu, &u->write_link_mtu);
198 if (u->stream_fd < 0)
199 return -1;
200
201 u->transport_acquired = true;
202 pa_log_info("Transport %s acquired: fd %d", u->transport->path, u->stream_fd);
203
204 return 0;
205 }
206
207 /* Run from main thread */
208 static int add_sink(struct userdata *u) {
209 pa_sink_new_data data;
210
211 pa_assert(u->transport);
212
213 pa_sink_new_data_init(&data);
214 data.module = u->module;
215 data.card = u->card;
216 data.driver = __FILE__;
217 data.name = pa_sprintf_malloc("bluez_sink.%s", u->device->address);
218 data.namereg_fail = false;
219 pa_proplist_sets(data.proplist, "bluetooth.protocol", pa_bluetooth_profile_to_string(u->profile));
220 pa_sink_new_data_set_sample_spec(&data, &u->sample_spec);
221
222 connect_ports(u, &data, PA_DIRECTION_OUTPUT);
223
224 if (!u->transport_acquired)
225 switch (u->profile) {
226 case PA_BLUETOOTH_PROFILE_A2DP_SINK:
227 /* Profile switch should have failed */
228 case PA_BLUETOOTH_PROFILE_A2DP_SOURCE:
229 case PA_BLUETOOTH_PROFILE_OFF:
230 pa_assert_not_reached();
231 break;
232 }
233
234 u->sink = pa_sink_new(u->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
235 pa_sink_new_data_done(&data);
236 if (!u->sink) {
237 pa_log_error("Failed to create sink");
238 return -1;
239 }
240
241 u->sink->userdata = u;
242
243 return 0;
244 }
245
246 /* Run from main thread */
247 static void transport_config(struct userdata *u) {
248 sbc_info_t *sbc_info = &u->sbc_info;
249 a2dp_sbc_t *config;
250
251 pa_assert(u->transport);
252
253 u->sample_spec.format = PA_SAMPLE_S16LE;
254 config = (a2dp_sbc_t *) u->transport->config;
255
256 if (sbc_info->sbc_initialized)
257 sbc_reinit(&sbc_info->sbc, 0);
258 else
259 sbc_init(&sbc_info->sbc, 0);
260 sbc_info->sbc_initialized = true;
261
262 switch (config->frequency) {
263 case SBC_SAMPLING_FREQ_16000:
264 sbc_info->sbc.frequency = SBC_FREQ_16000;
265 u->sample_spec.rate = 16000U;
266 break;
267 case SBC_SAMPLING_FREQ_32000:
268 sbc_info->sbc.frequency = SBC_FREQ_32000;
269 u->sample_spec.rate = 32000U;
270 break;
271 case SBC_SAMPLING_FREQ_44100:
272 sbc_info->sbc.frequency = SBC_FREQ_44100;
273 u->sample_spec.rate = 44100U;
274 break;
275 case SBC_SAMPLING_FREQ_48000:
276 sbc_info->sbc.frequency = SBC_FREQ_48000;
277 u->sample_spec.rate = 48000U;
278 break;
279 default:
280 pa_assert_not_reached();
281 }
282
283 switch (config->channel_mode) {
284 case SBC_CHANNEL_MODE_MONO:
285 sbc_info->sbc.mode = SBC_MODE_MONO;
286 u->sample_spec.channels = 1;
287 break;
288 case SBC_CHANNEL_MODE_DUAL_CHANNEL:
289 sbc_info->sbc.mode = SBC_MODE_DUAL_CHANNEL;
290 u->sample_spec.channels = 2;
291 break;
292 case SBC_CHANNEL_MODE_STEREO:
293 sbc_info->sbc.mode = SBC_MODE_STEREO;
294 u->sample_spec.channels = 2;
295 break;
296 case SBC_CHANNEL_MODE_JOINT_STEREO:
297 sbc_info->sbc.mode = SBC_MODE_JOINT_STEREO;
298 u->sample_spec.channels = 2;
299 break;
300 default:
301 pa_assert_not_reached();
302 }
303
304 switch (config->allocation_method) {
305 case SBC_ALLOCATION_SNR:
306 sbc_info->sbc.allocation = SBC_AM_SNR;
307 break;
308 case SBC_ALLOCATION_LOUDNESS:
309 sbc_info->sbc.allocation = SBC_AM_LOUDNESS;
310 break;
311 default:
312 pa_assert_not_reached();
313 }
314
315 switch (config->subbands) {
316 case SBC_SUBBANDS_4:
317 sbc_info->sbc.subbands = SBC_SB_4;
318 break;
319 case SBC_SUBBANDS_8:
320 sbc_info->sbc.subbands = SBC_SB_8;
321 break;
322 default:
323 pa_assert_not_reached();
324 }
325
326 switch (config->block_length) {
327 case SBC_BLOCK_LENGTH_4:
328 sbc_info->sbc.blocks = SBC_BLK_4;
329 break;
330 case SBC_BLOCK_LENGTH_8:
331 sbc_info->sbc.blocks = SBC_BLK_8;
332 break;
333 case SBC_BLOCK_LENGTH_12:
334 sbc_info->sbc.blocks = SBC_BLK_12;
335 break;
336 case SBC_BLOCK_LENGTH_16:
337 sbc_info->sbc.blocks = SBC_BLK_16;
338 break;
339 default:
340 pa_assert_not_reached();
341 }
342
343 sbc_info->min_bitpool = config->min_bitpool;
344 sbc_info->max_bitpool = config->max_bitpool;
345
346 /* Set minimum bitpool for source to get the maximum possible block_size */
347 sbc_info->sbc.bitpool = u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK ? sbc_info->max_bitpool : sbc_info->min_bitpool;
348 sbc_info->codesize = sbc_get_codesize(&sbc_info->sbc);
349 sbc_info->frame_length = sbc_get_frame_length(&sbc_info->sbc);
350
351 pa_log_info("SBC parameters: allocation=%u, subbands=%u, blocks=%u, bitpool=%u",
352 sbc_info->sbc.allocation, sbc_info->sbc.subbands, sbc_info->sbc.blocks, sbc_info->sbc.bitpool);
353 }
354
355 /* Run from main thread */
356 static int setup_transport(struct userdata *u) {
357 pa_bluetooth_transport *t;
358
359 pa_assert(u);
360 pa_assert(!u->transport);
361 pa_assert(u->profile != PA_BLUETOOTH_PROFILE_OFF);
362
363 /* check if profile has a transport */
364 t = u->device->transports[u->profile];
365 if (!t || t->state <= PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED) {
366 pa_log_warn("Profile has no transport");
367 return -1;
368 }
369
370 u->transport = t;
371
372 if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SOURCE)
373 transport_acquire(u, true); /* In case of error, the sink/sources will be created suspended */
374 else if (transport_acquire(u, false) < 0)
375 return -1; /* We need to fail here until the interactions with module-suspend-on-idle and alike get improved */
376
377 transport_config(u);
378
379 return 0;
380 }
381
382 /* Run from main thread */
383 static int init_profile(struct userdata *u) {
384 int r = 0;
385 pa_assert(u);
386 pa_assert(u->profile != PA_BLUETOOTH_PROFILE_OFF);
387
388 if (setup_transport(u) < 0)
389 return -1;
390
391 pa_assert(u->transport);
392
393 if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK)
394 if (add_sink(u) < 0)
395 r = -1;
396
397 /* TODO: add source */
398
399 return r;
400 }
401
402 /* Run from main thread */
403 static char *cleanup_name(const char *name) {
404 char *t, *s, *d;
405 bool space = false;
406
407 pa_assert(name);
408
409 while ((*name >= 1 && *name <= 32) || *name >= 127)
410 name++;
411
412 t = pa_xstrdup(name);
413
414 for (s = d = t; *s; s++) {
415
416 if (*s <= 32 || *s >= 127 || *s == '_') {
417 space = true;
418 continue;
419 }
420
421 if (space) {
422 *(d++) = ' ';
423 space = false;
424 }
425
426 *(d++) = *s;
427 }
428
429 *d = 0;
430
431 return t;
432 }
433
434 /* Run from main thread */
435 static pa_direction_t get_profile_direction(pa_bluetooth_profile_t p) {
436 static const pa_direction_t profile_direction[] = {
437 [PA_BLUETOOTH_PROFILE_A2DP_SINK] = PA_DIRECTION_OUTPUT,
438 [PA_BLUETOOTH_PROFILE_A2DP_SOURCE] = PA_DIRECTION_INPUT,
439 [PA_BLUETOOTH_PROFILE_OFF] = 0
440 };
441
442 return profile_direction[p];
443 }
444
445 /* Run from main thread */
446 static pa_available_t get_port_availability(struct userdata *u, pa_direction_t direction) {
447 pa_available_t result = PA_AVAILABLE_NO;
448 unsigned i;
449
450 pa_assert(u);
451 pa_assert(u->device);
452
453 for (i = 0; i < PA_BLUETOOTH_PROFILE_COUNT; i++) {
454 pa_bluetooth_transport *transport;
455
456 if (!(get_profile_direction(i) & direction))
457 continue;
458
459 if (!(transport = u->device->transports[i]))
460 continue;
461
462 switch(transport->state) {
463 case PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED:
464 continue;
465
466 case PA_BLUETOOTH_TRANSPORT_STATE_IDLE:
467 if (result == PA_AVAILABLE_NO)
468 result = PA_AVAILABLE_UNKNOWN;
469
470 break;
471
472 case PA_BLUETOOTH_TRANSPORT_STATE_PLAYING:
473 return PA_AVAILABLE_YES;
474 }
475 }
476
477 return result;
478 }
479
480 /* Run from main thread */
481 static pa_available_t transport_state_to_availability(pa_bluetooth_transport_state_t state) {
482 switch (state) {
483 case PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED:
484 return PA_AVAILABLE_NO;
485 case PA_BLUETOOTH_TRANSPORT_STATE_PLAYING:
486 return PA_AVAILABLE_YES;
487 default:
488 return PA_AVAILABLE_UNKNOWN;
489 }
490 }
491
492 /* Run from main thread */
493 static void create_card_ports(struct userdata *u, pa_hashmap *ports) {
494 pa_device_port *port;
495 pa_device_port_new_data port_data;
496 const char *name_prefix, *input_description, *output_description;
497
498 pa_assert(u);
499 pa_assert(ports);
500 pa_assert(u->device);
501
502 name_prefix = "unknown";
503 input_description = _("Bluetooth Input");
504 output_description = _("Bluetooth Output");
505
506 switch (form_factor_from_class(u->device->class_of_device)) {
507 case PA_BLUETOOTH_FORM_FACTOR_HEADSET:
508 name_prefix = "headset";
509 input_description = output_description = _("Headset");
510 break;
511
512 case PA_BLUETOOTH_FORM_FACTOR_HANDSFREE:
513 name_prefix = "handsfree";
514 input_description = output_description = _("Handsfree");
515 break;
516
517 case PA_BLUETOOTH_FORM_FACTOR_MICROPHONE:
518 name_prefix = "microphone";
519 input_description = _("Microphone");
520 output_description = _("Bluetooth Output");
521 break;
522
523 case PA_BLUETOOTH_FORM_FACTOR_SPEAKER:
524 name_prefix = "speaker";
525 input_description = _("Bluetooth Input");
526 output_description = _("Speaker");
527 break;
528
529 case PA_BLUETOOTH_FORM_FACTOR_HEADPHONE:
530 name_prefix = "headphone";
531 input_description = _("Bluetooth Input");
532 output_description = _("Headphone");
533 break;
534
535 case PA_BLUETOOTH_FORM_FACTOR_PORTABLE:
536 name_prefix = "portable";
537 input_description = output_description = _("Portable");
538 break;
539
540 case PA_BLUETOOTH_FORM_FACTOR_CAR:
541 name_prefix = "car";
542 input_description = output_description = _("Car");
543 break;
544
545 case PA_BLUETOOTH_FORM_FACTOR_HIFI:
546 name_prefix = "hifi";
547 input_description = output_description = _("HiFi");
548 break;
549
550 case PA_BLUETOOTH_FORM_FACTOR_PHONE:
551 name_prefix = "phone";
552 input_description = output_description = _("Phone");
553 break;
554
555 case PA_BLUETOOTH_FORM_FACTOR_UNKNOWN:
556 name_prefix = "unknown";
557 input_description = _("Bluetooth Input");
558 output_description = _("Bluetooth Output");
559 break;
560 }
561
562 u->output_port_name = pa_sprintf_malloc("%s-output", name_prefix);
563 pa_device_port_new_data_init(&port_data);
564 pa_device_port_new_data_set_name(&port_data, u->output_port_name);
565 pa_device_port_new_data_set_description(&port_data, output_description);
566 pa_device_port_new_data_set_direction(&port_data, PA_DIRECTION_OUTPUT);
567 pa_device_port_new_data_set_available(&port_data, get_port_availability(u, PA_DIRECTION_OUTPUT));
568 pa_assert_se(port = pa_device_port_new(u->core, &port_data, 0));
569 pa_assert_se(pa_hashmap_put(ports, port->name, port) >= 0);
570 pa_device_port_new_data_done(&port_data);
571
572 u->input_port_name = pa_sprintf_malloc("%s-input", name_prefix);
573 pa_device_port_new_data_init(&port_data);
574 pa_device_port_new_data_set_name(&port_data, u->input_port_name);
575 pa_device_port_new_data_set_description(&port_data, input_description);
576 pa_device_port_new_data_set_direction(&port_data, PA_DIRECTION_INPUT);
577 pa_device_port_new_data_set_available(&port_data, get_port_availability(u, PA_DIRECTION_INPUT));
578 pa_assert_se(port = pa_device_port_new(u->core, &port_data, 0));
579 pa_assert_se(pa_hashmap_put(ports, port->name, port) >= 0);
580 pa_device_port_new_data_done(&port_data);
581 }
582
583 /* Run from main thread */
584 static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid, pa_hashmap *ports) {
585 pa_device_port *input_port, *output_port;
586 pa_card_profile *cp = NULL;
587 pa_bluetooth_profile_t *p;
588
589 pa_assert(u->input_port_name);
590 pa_assert(u->output_port_name);
591 pa_assert_se(input_port = pa_hashmap_get(ports, u->input_port_name));
592 pa_assert_se(output_port = pa_hashmap_get(ports, u->output_port_name));
593
594 if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK)) {
595 /* TODO: Change this profile's name to a2dp_sink, to reflect the remote
596 * device's role and be consistent with the a2dp source profile */
597 cp = pa_card_profile_new("a2dp", _("High Fidelity Playback (A2DP Sink)"), sizeof(pa_bluetooth_profile_t));
598 cp->priority = 10;
599 cp->n_sinks = 1;
600 cp->n_sources = 0;
601 cp->max_sink_channels = 2;
602 cp->max_source_channels = 0;
603 pa_hashmap_put(output_port->profiles, cp->name, cp);
604
605 p = PA_CARD_PROFILE_DATA(cp);
606 *p = PA_BLUETOOTH_PROFILE_A2DP_SINK;
607 } else if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SOURCE)) {
608 cp = pa_card_profile_new("a2dp_source", _("High Fidelity Capture (A2DP Source)"), sizeof(pa_bluetooth_profile_t));
609 cp->priority = 10;
610 cp->n_sinks = 0;
611 cp->n_sources = 1;
612 cp->max_sink_channels = 0;
613 cp->max_source_channels = 2;
614 pa_hashmap_put(input_port->profiles, cp->name, cp);
615
616 p = PA_CARD_PROFILE_DATA(cp);
617 *p = PA_BLUETOOTH_PROFILE_A2DP_SOURCE;
618 }
619
620 if (cp && u->device->transports[*p])
621 cp->available = transport_state_to_availability(u->device->transports[*p]->state);
622
623 return cp;
624 }
625
626 /* Run from main thread */
627 static int add_card(struct userdata *u) {
628 const pa_bluetooth_device *d;
629 pa_card_new_data data;
630 char *alias;
631 pa_bluetooth_form_factor_t ff;
632 pa_card_profile *cp;
633 pa_bluetooth_profile_t *p;
634 const char *uuid;
635 void *state;
636
637 pa_assert(u);
638 pa_assert(u->device);
639
640 d = u->device;
641
642 pa_card_new_data_init(&data);
643 data.driver = __FILE__;
644 data.module = u->module;
645
646 alias = cleanup_name(d->alias);
647 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, alias);
648 pa_xfree(alias);
649
650 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, d->address);
651 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "bluez");
652 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "sound");
653 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_BUS, "bluetooth");
654
655 if ((ff = form_factor_from_class(d->class_of_device)) != PA_BLUETOOTH_FORM_FACTOR_UNKNOWN)
656 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_FORM_FACTOR, form_factor_to_string(ff));
657
658 pa_proplist_sets(data.proplist, "bluez.path", d->path);
659 pa_proplist_setf(data.proplist, "bluez.class", "0x%06x", d->class_of_device);
660 pa_proplist_sets(data.proplist, "bluez.alias", d->alias);
661 data.name = pa_sprintf_malloc("bluez_card.%s", d->address);
662 data.namereg_fail = false;
663
664 create_card_ports(u, data.ports);
665
666 PA_HASHMAP_FOREACH(uuid, d->uuids, state) {
667 cp = create_card_profile(u, uuid, data.ports);
668
669 if (!cp)
670 continue;
671
672 if (pa_hashmap_get(data.profiles, cp->name)) {
673 pa_card_profile_free(cp);
674 continue;
675 }
676
677 pa_hashmap_put(data.profiles, cp->name, cp);
678 }
679
680 pa_assert(!pa_hashmap_isempty(data.profiles));
681
682 cp = pa_card_profile_new("off", _("Off"), sizeof(pa_bluetooth_profile_t));
683 cp->available = PA_AVAILABLE_YES;
684 p = PA_CARD_PROFILE_DATA(cp);
685 *p = PA_BLUETOOTH_PROFILE_OFF;
686 pa_hashmap_put(data.profiles, cp->name, cp);
687
688 u->card = pa_card_new(u->core, &data);
689 pa_card_new_data_done(&data);
690 if (!u->card) {
691 pa_log("Failed to allocate card.");
692 return -1;
693 }
694
695 u->card->userdata = u;
696
697 p = PA_CARD_PROFILE_DATA(u->card->active_profile);
698 u->profile = *p;
699
700 return 0;
701 }
702
703 /* Run from main thread */
704 static pa_hook_result_t device_connection_changed_cb(pa_bluetooth_discovery *y, const pa_bluetooth_device *d, struct userdata *u) {
705 pa_assert(d);
706 pa_assert(u);
707
708 if (d != u->device || pa_bluetooth_device_any_transport_connected(d))
709 return PA_HOOK_OK;
710
711 pa_log_debug("Unloading module for device %s", d->path);
712 pa_module_unload(u->core, u->module, true);
713
714 return PA_HOOK_OK;
715 }
716
717 int pa__init(pa_module* m) {
718 struct userdata *u;
719 const char *path;
720 pa_modargs *ma;
721
722 pa_assert(m);
723
724 m->userdata = u = pa_xnew0(struct userdata, 1);
725 u->module = m;
726 u->core = m->core;
727
728 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
729 pa_log_error("Failed to parse module arguments");
730 goto fail;
731 }
732
733 if (!(path = pa_modargs_get_value(ma, "path", NULL))) {
734 pa_log_error("Failed to get device path from module arguments");
735 goto fail;
736 }
737
738 if (!(u->discovery = pa_bluetooth_discovery_get(m->core)))
739 goto fail;
740
741 if (!(u->device = pa_bluetooth_discovery_get_device_by_path(u->discovery, path))) {
742 pa_log_error("%s is unknown", path);
743 goto fail;
744 }
745
746 pa_modargs_free(ma);
747
748 u->device_connection_changed_slot =
749 pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED),
750 PA_HOOK_NORMAL, (pa_hook_cb_t) device_connection_changed_cb, u);
751
752 if (add_card(u) < 0)
753 goto fail;
754
755 if (u->profile != PA_BLUETOOTH_PROFILE_OFF)
756 if (init_profile(u) < 0)
757 goto off;
758
759 return 0;
760
761 off:
762
763 pa_assert_se(pa_card_set_profile(u->card, "off", false) >= 0);
764
765 return 0;
766
767 fail:
768
769 if (ma)
770 pa_modargs_free(ma);
771
772 pa__done(m);
773
774 return -1;
775 }
776
777 void pa__done(pa_module *m) {
778 struct userdata *u;
779
780 pa_assert(m);
781
782 if (!(u = m->userdata))
783 return;
784
785 if (u->device_connection_changed_slot)
786 pa_hook_slot_free(u->device_connection_changed_slot);
787
788 if (u->sbc_info.sbc_initialized)
789 sbc_finish(&u->sbc_info.sbc);
790
791 if (u->card)
792 pa_card_free(u->card);
793
794 if (u->discovery)
795 pa_bluetooth_discovery_unref(u->discovery);
796
797 pa_xfree(u->output_port_name);
798 pa_xfree(u->input_port_name);
799
800 pa_xfree(u);
801 }