1 /*
2 *
3 * BlueZ - Bluetooth protocol stack for Linux
4 *
5 * Copyright (C) 2006-2007 Nokia Corporation
6 * Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <stdlib.h>
30 #include <errno.h>
31
32 #include <dbus/dbus.h>
33 #include <glib.h>
34
35 #include <bluetooth/bluetooth.h>
36 #include <bluetooth/sdp.h>
37 #include <bluetooth/sdp_lib.h>
38
39 #include "logging.h"
40 #include "device.h"
41 #include "manager.h"
42 #include "avdtp.h"
43 #include "sink.h"
44 #include "source.h"
45 #include "a2dp.h"
46 #include "sdpd.h"
47
48 /* The duration that streams without users are allowed to stay in
49 * STREAMING state. */
50 #define SUSPEND_TIMEOUT 5
51 #define RECONFIGURE_TIMEOUT 500
52
53 #ifndef MIN
54 # define MIN(x, y) ((x) < (y) ? (x) : (y))
55 #endif
56
57 #ifndef MAX
58 # define MAX(x, y) ((x) > (y) ? (x) : (y))
59 #endif
60
61 struct a2dp_sep {
62 uint8_t type;
63 uint8_t codec;
64 struct avdtp_local_sep *sep;
65 struct avdtp *session;
66 struct avdtp_stream *stream;
67 guint suspend_timer;
68 gboolean locked;
69 gboolean suspending;
70 gboolean starting;
71 };
72
73 struct a2dp_setup_cb {
74 a2dp_config_cb_t config_cb;
75 a2dp_stream_cb_t resume_cb;
76 a2dp_stream_cb_t suspend_cb;
77 void *user_data;
78 unsigned int id;
79 };
80
81 struct a2dp_setup {
82 struct audio_device *dev;
83 struct avdtp *session;
84 struct a2dp_sep *sep;
85 struct avdtp_stream *stream;
86 struct avdtp_error *err;
87 GSList *client_caps;
88 gboolean reconfigure;
89 gboolean canceled;
90 gboolean start;
91 GSList *cb;
92 int ref;
93 };
94
95 static DBusConnection *connection = NULL;
96
97 struct a2dp_server {
98 bdaddr_t src;
99 GSList *sinks;
100 GSList *sources;
101 uint32_t source_record_id;
102 uint32_t sink_record_id;
103 };
104
105 static GSList *servers = NULL;
106 static GSList *setups = NULL;
107 static unsigned int cb_id = 0;
108
setup_ref(struct a2dp_setup * setup)109 static struct a2dp_setup *setup_ref(struct a2dp_setup *setup)
110 {
111 setup->ref++;
112
113 debug("setup_ref(%p): ref=%d", setup, setup->ref);
114
115 return setup;
116 }
117
setup_free(struct a2dp_setup * s)118 static void setup_free(struct a2dp_setup *s)
119 {
120 debug("setup_free(%p)", s);
121 setups = g_slist_remove(setups, s);
122 if (s->session)
123 avdtp_unref(s->session);
124 g_slist_foreach(s->cb, (GFunc) g_free, NULL);
125 g_slist_free(s->cb);
126 g_free(s);
127 }
128
setup_unref(struct a2dp_setup * setup)129 static void setup_unref(struct a2dp_setup *setup)
130 {
131 setup->ref--;
132
133 debug("setup_unref(%p): ref=%d", setup, setup->ref);
134
135 if (setup->ref <= 0)
136 setup_free(setup);
137 }
138
a2dp_get_dev(struct avdtp * session)139 static struct audio_device *a2dp_get_dev(struct avdtp *session)
140 {
141 bdaddr_t src, dst;
142
143 avdtp_get_peers(session, &src, &dst);
144
145 return manager_find_device(NULL, &src, &dst, NULL, FALSE);
146 }
147
finalize_config(struct a2dp_setup * s)148 static gboolean finalize_config(struct a2dp_setup *s)
149 {
150 GSList *l;
151
152 setup_ref(s);
153 for (l = s->cb; l != NULL; l = l->next) {
154 struct a2dp_setup_cb *cb = l->data;
155 struct avdtp_stream *stream = s->err ? NULL : s->stream;
156
157 if (!cb->config_cb)
158 continue;
159
160 cb->config_cb(s->session, s->sep, stream, s->err,
161 cb->user_data);
162 cb->config_cb = NULL;
163 setup_unref(s);
164 }
165
166 setup_unref(s);
167 return FALSE;
168 }
169
finalize_config_errno(struct a2dp_setup * s,int err)170 static gboolean finalize_config_errno(struct a2dp_setup *s, int err)
171 {
172 struct avdtp_error avdtp_err;
173
174 avdtp_error_init(&avdtp_err, AVDTP_ERROR_ERRNO, -err);
175 s->err = err ? &avdtp_err : NULL;
176
177 return finalize_config(s);
178 }
179
finalize_resume(struct a2dp_setup * s)180 static gboolean finalize_resume(struct a2dp_setup *s)
181 {
182 GSList *l;
183
184 setup_ref(s);
185 for (l = s->cb; l != NULL; l = l->next) {
186 struct a2dp_setup_cb *cb = l->data;
187
188 if (cb && cb->resume_cb) {
189 cb->resume_cb(s->session, s->err, cb->user_data);
190 cb->resume_cb = NULL;
191 setup_unref(s);
192 }
193 }
194
195 setup_unref(s);
196 return FALSE;
197 }
198
finalize_suspend(struct a2dp_setup * s)199 static gboolean finalize_suspend(struct a2dp_setup *s)
200 {
201 GSList *l;
202
203 setup_ref(s);
204 for (l = s->cb; l != NULL; l = l->next) {
205 struct a2dp_setup_cb *cb = l->data;
206
207 if (cb->suspend_cb) {
208 cb->suspend_cb(s->session, s->err, cb->user_data);
209 cb->suspend_cb = NULL;
210 setup_unref(s);
211 }
212 }
213
214 setup_unref(s);
215 return FALSE;
216 }
217
finalize_suspend_errno(struct a2dp_setup * s,int err)218 static gboolean finalize_suspend_errno(struct a2dp_setup *s, int err)
219 {
220 struct avdtp_error avdtp_err;
221
222 avdtp_error_init(&avdtp_err, AVDTP_ERROR_ERRNO, -err);
223 s->err = err ? &avdtp_err : NULL;
224
225 return finalize_suspend(s);
226 }
227
find_setup_by_session(struct avdtp * session)228 static struct a2dp_setup *find_setup_by_session(struct avdtp *session)
229 {
230 GSList *l;
231
232 for (l = setups; l != NULL; l = l->next) {
233 struct a2dp_setup *setup = l->data;
234
235 if (setup->session == session)
236 return setup;
237 }
238
239 return NULL;
240 }
241
find_setup_by_dev(struct audio_device * dev)242 static struct a2dp_setup *find_setup_by_dev(struct audio_device *dev)
243 {
244 GSList *l;
245
246 for (l = setups; l != NULL; l = l->next) {
247 struct a2dp_setup *setup = l->data;
248
249 if (setup->dev == dev)
250 return setup;
251 }
252
253 return NULL;
254 }
255
stream_state_changed(struct avdtp_stream * stream,avdtp_state_t old_state,avdtp_state_t new_state,struct avdtp_error * err,void * user_data)256 static void stream_state_changed(struct avdtp_stream *stream,
257 avdtp_state_t old_state,
258 avdtp_state_t new_state,
259 struct avdtp_error *err,
260 void *user_data)
261 {
262 struct a2dp_sep *sep = user_data;
263
264 if (new_state != AVDTP_STATE_IDLE)
265 return;
266
267 if (sep->suspend_timer) {
268 g_source_remove(sep->suspend_timer);
269 sep->suspend_timer = 0;
270 }
271
272 if (sep->session) {
273 avdtp_unref(sep->session);
274 sep->session = NULL;
275 }
276
277 sep->stream = NULL;
278
279 }
280
sbc_setconf_ind(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,GSList * caps,uint8_t * err,uint8_t * category,void * user_data)281 static gboolean sbc_setconf_ind(struct avdtp *session,
282 struct avdtp_local_sep *sep,
283 struct avdtp_stream *stream,
284 GSList *caps, uint8_t *err,
285 uint8_t *category, void *user_data)
286 {
287 struct a2dp_sep *a2dp_sep = user_data;
288 struct audio_device *dev;
289 struct avdtp_service_capability *cap;
290 struct avdtp_media_codec_capability *codec_cap;
291 struct sbc_codec_cap *sbc_cap;
292
293 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
294 debug("Sink %p: Set_Configuration_Ind", sep);
295 else
296 debug("Source %p: Set_Configuration_Ind", sep);
297
298 dev = a2dp_get_dev(session);
299 if (!dev) {
300 *err = AVDTP_UNSUPPORTED_CONFIGURATION;
301 *category = 0x00;
302 return FALSE;
303 }
304
305 /* Check bipool range */
306 for (codec_cap = NULL; caps; caps = g_slist_next(caps)) {
307 cap = caps->data;
308 if (cap->category != AVDTP_MEDIA_CODEC)
309 continue;
310
311 if (cap->length < sizeof(struct sbc_codec_cap))
312 continue;
313
314 codec_cap = (void *) cap->data;
315
316 if (codec_cap->media_codec_type != A2DP_CODEC_SBC)
317 continue;
318
319 sbc_cap = (void *) codec_cap;
320
321 if (sbc_cap->min_bitpool < MIN_BITPOOL ||
322 sbc_cap->max_bitpool > MAX_BITPOOL) {
323 *err = AVDTP_UNSUPPORTED_CONFIGURATION;
324 *category = AVDTP_MEDIA_CODEC;
325 return FALSE;
326 }
327
328 break;
329 }
330
331 avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
332 a2dp_sep->stream = stream;
333
334 if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE)
335 sink_new_stream(dev, session, stream);
336
337 return TRUE;
338 }
339
sbc_getcap_ind(struct avdtp * session,struct avdtp_local_sep * sep,GSList ** caps,uint8_t * err,void * user_data)340 static gboolean sbc_getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep,
341 GSList **caps, uint8_t *err, void *user_data)
342 {
343 struct a2dp_sep *a2dp_sep = user_data;
344 struct avdtp_service_capability *media_transport, *media_codec;
345 struct sbc_codec_cap sbc_cap;
346
347 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
348 debug("Sink %p: Get_Capability_Ind", sep);
349 else
350 debug("Source %p: Get_Capability_Ind", sep);
351
352 *caps = NULL;
353
354 media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
355 NULL, 0);
356
357 *caps = g_slist_append(*caps, media_transport);
358
359 memset(&sbc_cap, 0, sizeof(struct sbc_codec_cap));
360
361 sbc_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
362 sbc_cap.cap.media_codec_type = A2DP_CODEC_SBC;
363
364 #ifdef ANDROID
365 sbc_cap.frequency = SBC_SAMPLING_FREQ_44100;
366 #else
367 sbc_cap.frequency = ( SBC_SAMPLING_FREQ_48000 |
368 SBC_SAMPLING_FREQ_44100 |
369 SBC_SAMPLING_FREQ_32000 |
370 SBC_SAMPLING_FREQ_16000 );
371 #endif
372
373 sbc_cap.channel_mode = ( SBC_CHANNEL_MODE_JOINT_STEREO |
374 SBC_CHANNEL_MODE_STEREO |
375 SBC_CHANNEL_MODE_DUAL_CHANNEL |
376 SBC_CHANNEL_MODE_MONO );
377
378 sbc_cap.block_length = ( SBC_BLOCK_LENGTH_16 |
379 SBC_BLOCK_LENGTH_12 |
380 SBC_BLOCK_LENGTH_8 |
381 SBC_BLOCK_LENGTH_4 );
382
383 sbc_cap.subbands = ( SBC_SUBBANDS_8 | SBC_SUBBANDS_4 );
384
385 sbc_cap.allocation_method = ( SBC_ALLOCATION_LOUDNESS |
386 SBC_ALLOCATION_SNR );
387
388 sbc_cap.min_bitpool = MIN_BITPOOL;
389 sbc_cap.max_bitpool = MAX_BITPOOL;
390
391 media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap,
392 sizeof(sbc_cap));
393
394 *caps = g_slist_append(*caps, media_codec);
395
396 return TRUE;
397 }
398
mpeg_setconf_ind(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,GSList * caps,uint8_t * err,uint8_t * category,void * user_data)399 static gboolean mpeg_setconf_ind(struct avdtp *session,
400 struct avdtp_local_sep *sep,
401 struct avdtp_stream *stream,
402 GSList *caps, uint8_t *err,
403 uint8_t *category, void *user_data)
404 {
405 struct a2dp_sep *a2dp_sep = user_data;
406 struct audio_device *dev;
407
408 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
409 debug("Sink %p: Set_Configuration_Ind", sep);
410 else
411 debug("Source %p: Set_Configuration_Ind", sep);
412
413 dev = a2dp_get_dev(session);
414 if (!dev) {
415 *err = AVDTP_UNSUPPORTED_CONFIGURATION;
416 *category = 0x00;
417 return FALSE;
418 }
419
420 avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
421 a2dp_sep->stream = stream;
422
423 if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE)
424 sink_new_stream(dev, session, stream);
425
426 return TRUE;
427 }
428
mpeg_getcap_ind(struct avdtp * session,struct avdtp_local_sep * sep,GSList ** caps,uint8_t * err,void * user_data)429 static gboolean mpeg_getcap_ind(struct avdtp *session,
430 struct avdtp_local_sep *sep,
431 GSList **caps, uint8_t *err, void *user_data)
432 {
433 struct a2dp_sep *a2dp_sep = user_data;
434 struct avdtp_service_capability *media_transport, *media_codec;
435 struct mpeg_codec_cap mpeg_cap;
436
437 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
438 debug("Sink %p: Get_Capability_Ind", sep);
439 else
440 debug("Source %p: Get_Capability_Ind", sep);
441
442 *caps = NULL;
443
444 media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
445 NULL, 0);
446
447 *caps = g_slist_append(*caps, media_transport);
448
449 memset(&mpeg_cap, 0, sizeof(struct mpeg_codec_cap));
450
451 mpeg_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
452 mpeg_cap.cap.media_codec_type = A2DP_CODEC_MPEG12;
453
454 mpeg_cap.frequency = ( MPEG_SAMPLING_FREQ_48000 |
455 MPEG_SAMPLING_FREQ_44100 |
456 MPEG_SAMPLING_FREQ_32000 |
457 MPEG_SAMPLING_FREQ_24000 |
458 MPEG_SAMPLING_FREQ_22050 |
459 MPEG_SAMPLING_FREQ_16000 );
460
461 mpeg_cap.channel_mode = ( MPEG_CHANNEL_MODE_JOINT_STEREO |
462 MPEG_CHANNEL_MODE_STEREO |
463 MPEG_CHANNEL_MODE_DUAL_CHANNEL |
464 MPEG_CHANNEL_MODE_MONO );
465
466 mpeg_cap.layer = ( MPEG_LAYER_MP3 | MPEG_LAYER_MP2 | MPEG_LAYER_MP1 );
467
468 mpeg_cap.bitrate = 0xFFFF;
469
470 media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &mpeg_cap,
471 sizeof(mpeg_cap));
472
473 *caps = g_slist_append(*caps, media_codec);
474
475 return TRUE;
476 }
477
setconf_cfm(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,struct avdtp_error * err,void * user_data)478 static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
479 struct avdtp_stream *stream,
480 struct avdtp_error *err, void *user_data)
481 {
482 struct a2dp_sep *a2dp_sep = user_data;
483 struct a2dp_setup *setup;
484 struct audio_device *dev;
485 int ret;
486
487 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
488 debug("Sink %p: Set_Configuration_Cfm", sep);
489 else
490 debug("Source %p: Set_Configuration_Cfm", sep);
491
492 setup = find_setup_by_session(session);
493
494 if (err) {
495 if (setup) {
496 setup->err = err;
497 finalize_config(setup);
498 }
499 return;
500 }
501
502 avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
503 a2dp_sep->stream = stream;
504
505 if (!setup)
506 return;
507
508 dev = a2dp_get_dev(session);
509
510 /* Notify D-Bus interface of the new stream */
511 if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE)
512 sink_new_stream(dev, session, setup->stream);
513 else
514 source_new_stream(dev, session, setup->stream);
515
516 ret = avdtp_open(session, stream);
517 if (ret < 0) {
518 error("Error on avdtp_open %s (%d)", strerror(-ret), -ret);
519 setup->stream = NULL;
520 finalize_config_errno(setup, ret);
521 }
522 }
523
getconf_ind(struct avdtp * session,struct avdtp_local_sep * sep,uint8_t * err,void * user_data)524 static gboolean getconf_ind(struct avdtp *session, struct avdtp_local_sep *sep,
525 uint8_t *err, void *user_data)
526 {
527 struct a2dp_sep *a2dp_sep = user_data;
528
529 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
530 debug("Sink %p: Get_Configuration_Ind", sep);
531 else
532 debug("Source %p: Get_Configuration_Ind", sep);
533 return TRUE;
534 }
535
getconf_cfm(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,struct avdtp_error * err,void * user_data)536 static void getconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
537 struct avdtp_stream *stream, struct avdtp_error *err,
538 void *user_data)
539 {
540 struct a2dp_sep *a2dp_sep = user_data;
541
542 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
543 debug("Sink %p: Set_Configuration_Cfm", sep);
544 else
545 debug("Source %p: Set_Configuration_Cfm", sep);
546 }
547
open_ind(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,uint8_t * err,void * user_data)548 static gboolean open_ind(struct avdtp *session, struct avdtp_local_sep *sep,
549 struct avdtp_stream *stream, uint8_t *err,
550 void *user_data)
551 {
552 struct a2dp_sep *a2dp_sep = user_data;
553
554 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
555 debug("Sink %p: Open_Ind", sep);
556 else
557 debug("Source %p: Open_Ind", sep);
558 return TRUE;
559 }
560
open_cfm(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,struct avdtp_error * err,void * user_data)561 static void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
562 struct avdtp_stream *stream, struct avdtp_error *err,
563 void *user_data)
564 {
565 struct a2dp_sep *a2dp_sep = user_data;
566 struct a2dp_setup *setup;
567
568 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
569 debug("Sink %p: Open_Cfm", sep);
570 else
571 debug("Source %p: Open_Cfm", sep);
572
573 setup = find_setup_by_session(session);
574 if (!setup)
575 return;
576
577 if (setup->canceled) {
578 if (!err)
579 avdtp_close(session, stream);
580 setup_unref(setup);
581 return;
582 }
583
584 if (setup->reconfigure)
585 setup->reconfigure = FALSE;
586
587 if (err) {
588 setup->stream = NULL;
589 setup->err = err;
590 }
591
592 finalize_config(setup);
593 }
594
suspend_timeout(struct a2dp_sep * sep)595 static gboolean suspend_timeout(struct a2dp_sep *sep)
596 {
597 if (avdtp_suspend(sep->session, sep->stream) == 0)
598 sep->suspending = TRUE;
599
600 sep->suspend_timer = 0;
601
602 avdtp_unref(sep->session);
603 sep->session = NULL;
604
605 return FALSE;
606 }
607
start_ind(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,uint8_t * err,void * user_data)608 static gboolean start_ind(struct avdtp *session, struct avdtp_local_sep *sep,
609 struct avdtp_stream *stream, uint8_t *err,
610 void *user_data)
611 {
612 struct a2dp_sep *a2dp_sep = user_data;
613 struct a2dp_setup *setup;
614
615 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
616 debug("Sink %p: Start_Ind", sep);
617 else
618 debug("Source %p: Start_Ind", sep);
619
620 setup = find_setup_by_session(session);
621 if (setup) {
622 if (setup->canceled)
623 setup_unref(setup);
624 else
625 finalize_resume(setup);
626 }
627
628 if (!a2dp_sep->locked) {
629 a2dp_sep->session = avdtp_ref(session);
630 a2dp_sep->suspend_timer = g_timeout_add_seconds(SUSPEND_TIMEOUT,
631 (GSourceFunc) suspend_timeout,
632 a2dp_sep);
633 }
634
635 return TRUE;
636 }
637
start_cfm(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,struct avdtp_error * err,void * user_data)638 static void start_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
639 struct avdtp_stream *stream, struct avdtp_error *err,
640 void *user_data)
641 {
642 struct a2dp_sep *a2dp_sep = user_data;
643 struct a2dp_setup *setup;
644
645 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
646 debug("Sink %p: Start_Cfm", sep);
647 else
648 debug("Source %p: Start_Cfm", sep);
649
650 setup = find_setup_by_session(session);
651 if (!setup)
652 return;
653
654 if (setup->canceled) {
655 if (!err)
656 avdtp_close(session, stream);
657 setup_unref(setup);
658 return;
659 }
660
661 if (err) {
662 setup->stream = NULL;
663 setup->err = err;
664 }
665
666 finalize_resume(setup);
667 }
668
suspend_ind(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,uint8_t * err,void * user_data)669 static gboolean suspend_ind(struct avdtp *session, struct avdtp_local_sep *sep,
670 struct avdtp_stream *stream, uint8_t *err,
671 void *user_data)
672 {
673 struct a2dp_sep *a2dp_sep = user_data;
674
675 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
676 debug("Sink %p: Suspend_Ind", sep);
677 else
678 debug("Source %p: Suspend_Ind", sep);
679
680 if (a2dp_sep->suspend_timer) {
681 g_source_remove(a2dp_sep->suspend_timer);
682 a2dp_sep->suspend_timer = 0;
683 avdtp_unref(a2dp_sep->session);
684 a2dp_sep->session = NULL;
685 }
686
687 return TRUE;
688 }
689
suspend_cfm(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,struct avdtp_error * err,void * user_data)690 static void suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
691 struct avdtp_stream *stream, struct avdtp_error *err,
692 void *user_data)
693 {
694 struct a2dp_sep *a2dp_sep = user_data;
695 struct a2dp_setup *setup;
696 gboolean start;
697
698 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
699 debug("Sink %p: Suspend_Cfm", sep);
700 else
701 debug("Source %p: Suspend_Cfm", sep);
702
703 a2dp_sep->suspending = FALSE;
704
705 setup = find_setup_by_session(session);
706 if (!setup)
707 return;
708
709 start = setup->start;
710 setup->start = FALSE;
711
712 if (err) {
713 setup->stream = NULL;
714 setup->err = err;
715 finalize_suspend(setup);
716 }
717 else
718 finalize_suspend_errno(setup, 0);
719
720 if (!start)
721 return;
722
723 if (err) {
724 setup->err = err;
725 finalize_suspend(setup);
726 } else if (avdtp_start(session, a2dp_sep->stream) < 0) {
727 struct avdtp_error start_err;
728 error("avdtp_start failed");
729 avdtp_error_init(&start_err, AVDTP_ERROR_ERRNO, EIO);
730 setup->err = err;
731 finalize_suspend(setup);
732 }
733 }
734
close_ind(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,uint8_t * err,void * user_data)735 static gboolean close_ind(struct avdtp *session, struct avdtp_local_sep *sep,
736 struct avdtp_stream *stream, uint8_t *err,
737 void *user_data)
738 {
739 struct a2dp_sep *a2dp_sep = user_data;
740
741 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
742 debug("Sink %p: Close_Ind", sep);
743 else
744 debug("Source %p: Close_Ind", sep);
745
746 return TRUE;
747 }
748
a2dp_reconfigure(gpointer data)749 static gboolean a2dp_reconfigure(gpointer data)
750 {
751 struct a2dp_setup *setup = data;
752 struct avdtp_local_sep *lsep;
753 struct avdtp_remote_sep *rsep;
754 struct avdtp_service_capability *cap;
755 struct avdtp_media_codec_capability *codec_cap = NULL;
756 GSList *l;
757 int posix_err;
758
759 for (l = setup->client_caps; l != NULL; l = l->next) {
760 cap = l->data;
761
762 if (cap->category != AVDTP_MEDIA_CODEC)
763 continue;
764
765 codec_cap = (void *) cap->data;
766 break;
767 }
768
769 if (!codec_cap) {
770 error("Cannot find capabilities to reconfigure");
771 posix_err = -EINVAL;
772 goto failed;
773 }
774
775 posix_err = avdtp_get_seps(setup->session, AVDTP_SEP_TYPE_SINK,
776 codec_cap->media_type,
777 codec_cap->media_codec_type,
778 &lsep, &rsep);
779 if (posix_err < 0) {
780 error("No matching ACP and INT SEPs found");
781 goto failed;
782 }
783
784 posix_err = avdtp_set_configuration(setup->session, rsep, lsep,
785 setup->client_caps,
786 &setup->stream);
787 if (posix_err < 0) {
788 error("avdtp_set_configuration: %s", strerror(-posix_err));
789 goto failed;
790 }
791
792 return FALSE;
793
794 failed:
795 finalize_config_errno(setup, posix_err);
796 return FALSE;
797 }
798
close_cfm(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,struct avdtp_error * err,void * user_data)799 static void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
800 struct avdtp_stream *stream, struct avdtp_error *err,
801 void *user_data)
802 {
803 struct a2dp_sep *a2dp_sep = user_data;
804 struct a2dp_setup *setup;
805
806 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
807 debug("Sink %p: Close_Cfm", sep);
808 else
809 debug("Source %p: Close_Cfm", sep);
810
811 setup = find_setup_by_session(session);
812 if (!setup)
813 return;
814
815 if (setup->canceled) {
816 setup_unref(setup);
817 return;
818 }
819
820 if (err) {
821 setup->stream = NULL;
822 setup->err = err;
823 finalize_config(setup);
824 return;
825 }
826
827 if (setup->reconfigure)
828 g_timeout_add(RECONFIGURE_TIMEOUT, a2dp_reconfigure, setup);
829 }
830
abort_ind(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,uint8_t * err,void * user_data)831 static gboolean abort_ind(struct avdtp *session, struct avdtp_local_sep *sep,
832 struct avdtp_stream *stream, uint8_t *err,
833 void *user_data)
834 {
835 struct a2dp_sep *a2dp_sep = user_data;
836
837 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
838 debug("Sink %p: Abort_Ind", sep);
839 else
840 debug("Source %p: Abort_Ind", sep);
841
842 a2dp_sep->stream = NULL;
843
844 return TRUE;
845 }
846
abort_cfm(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,struct avdtp_error * err,void * user_data)847 static void abort_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
848 struct avdtp_stream *stream, struct avdtp_error *err,
849 void *user_data)
850 {
851 struct a2dp_sep *a2dp_sep = user_data;
852 struct a2dp_setup *setup;
853
854 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
855 debug("Sink %p: Abort_Cfm", sep);
856 else
857 debug("Source %p: Abort_Cfm", sep);
858
859 setup = find_setup_by_session(session);
860 if (!setup)
861 return;
862
863 setup_unref(setup);
864 }
865
reconf_ind(struct avdtp * session,struct avdtp_local_sep * sep,uint8_t * err,void * user_data)866 static gboolean reconf_ind(struct avdtp *session, struct avdtp_local_sep *sep,
867 uint8_t *err, void *user_data)
868 {
869 struct a2dp_sep *a2dp_sep = user_data;
870
871 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
872 debug("Sink %p: ReConfigure_Ind", sep);
873 else
874 debug("Source %p: ReConfigure_Ind", sep);
875 return TRUE;
876 }
877
reconf_cfm(struct avdtp * session,struct avdtp_local_sep * sep,struct avdtp_stream * stream,struct avdtp_error * err,void * user_data)878 static void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
879 struct avdtp_stream *stream, struct avdtp_error *err,
880 void *user_data)
881 {
882 struct a2dp_sep *a2dp_sep = user_data;
883 struct a2dp_setup *setup;
884
885 if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
886 debug("Sink %p: ReConfigure_Cfm", sep);
887 else
888 debug("Source %p: ReConfigure_Cfm", sep);
889
890 setup = find_setup_by_session(session);
891 if (!setup)
892 return;
893
894 if (setup->canceled) {
895 if (!err)
896 avdtp_close(session, stream);
897 setup_unref(setup);
898 return;
899 }
900
901 if (err) {
902 setup->stream = NULL;
903 setup->err = err;
904 }
905
906 finalize_config(setup);
907 }
908
909 static struct avdtp_sep_cfm cfm = {
910 .set_configuration = setconf_cfm,
911 .get_configuration = getconf_cfm,
912 .open = open_cfm,
913 .start = start_cfm,
914 .suspend = suspend_cfm,
915 .close = close_cfm,
916 .abort = abort_cfm,
917 .reconfigure = reconf_cfm
918 };
919
920 static struct avdtp_sep_ind sbc_ind = {
921 .get_capability = sbc_getcap_ind,
922 .set_configuration = sbc_setconf_ind,
923 .get_configuration = getconf_ind,
924 .open = open_ind,
925 .start = start_ind,
926 .suspend = suspend_ind,
927 .close = close_ind,
928 .abort = abort_ind,
929 .reconfigure = reconf_ind
930 };
931
932 static struct avdtp_sep_ind mpeg_ind = {
933 .get_capability = mpeg_getcap_ind,
934 .set_configuration = mpeg_setconf_ind,
935 .get_configuration = getconf_ind,
936 .open = open_ind,
937 .start = start_ind,
938 .suspend = suspend_ind,
939 .close = close_ind,
940 .abort = abort_ind,
941 .reconfigure = reconf_ind
942 };
943
a2dp_record(uint8_t type)944 static sdp_record_t *a2dp_record(uint8_t type)
945 {
946 sdp_list_t *svclass_id, *pfseq, *apseq, *root;
947 uuid_t root_uuid, l2cap_uuid, avdtp_uuid, a2dp_uuid;
948 sdp_profile_desc_t profile[1];
949 sdp_list_t *aproto, *proto[2];
950 sdp_record_t *record;
951 sdp_data_t *psm, *version, *features;
952 uint16_t lp = AVDTP_UUID, ver = 0x0100, feat = 0x000F;
953
954 record = sdp_record_alloc();
955 if (!record)
956 return NULL;
957
958 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
959 root = sdp_list_append(0, &root_uuid);
960 sdp_set_browse_groups(record, root);
961
962 if (type == AVDTP_SEP_TYPE_SOURCE)
963 sdp_uuid16_create(&a2dp_uuid, AUDIO_SOURCE_SVCLASS_ID);
964 else
965 sdp_uuid16_create(&a2dp_uuid, AUDIO_SINK_SVCLASS_ID);
966 svclass_id = sdp_list_append(0, &a2dp_uuid);
967 sdp_set_service_classes(record, svclass_id);
968
969 sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
970 profile[0].version = 0x0100;
971 pfseq = sdp_list_append(0, &profile[0]);
972 sdp_set_profile_descs(record, pfseq);
973
974 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
975 proto[0] = sdp_list_append(0, &l2cap_uuid);
976 psm = sdp_data_alloc(SDP_UINT16, &lp);
977 proto[0] = sdp_list_append(proto[0], psm);
978 apseq = sdp_list_append(0, proto[0]);
979
980 sdp_uuid16_create(&avdtp_uuid, AVDTP_UUID);
981 proto[1] = sdp_list_append(0, &avdtp_uuid);
982 version = sdp_data_alloc(SDP_UINT16, &ver);
983 proto[1] = sdp_list_append(proto[1], version);
984 apseq = sdp_list_append(apseq, proto[1]);
985
986 aproto = sdp_list_append(0, apseq);
987 sdp_set_access_protos(record, aproto);
988
989 features = sdp_data_alloc(SDP_UINT16, &feat);
990 sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
991
992 if (type == AVDTP_SEP_TYPE_SOURCE)
993 sdp_set_info_attr(record, "Audio Source", 0, 0);
994 else
995 sdp_set_info_attr(record, "Audio Sink", 0, 0);
996
997 free(psm);
998 free(version);
999 sdp_list_free(proto[0], 0);
1000 sdp_list_free(proto[1], 0);
1001 sdp_list_free(apseq, 0);
1002 sdp_list_free(pfseq, 0);
1003 sdp_list_free(aproto, 0);
1004 sdp_list_free(root, 0);
1005 sdp_list_free(svclass_id, 0);
1006
1007 return record;
1008 }
1009
a2dp_add_sep(struct a2dp_server * server,uint8_t type,uint8_t codec)1010 static struct a2dp_sep *a2dp_add_sep(struct a2dp_server *server, uint8_t type,
1011 uint8_t codec)
1012 {
1013 struct a2dp_sep *sep;
1014 GSList **l;
1015 uint32_t *record_id;
1016 sdp_record_t *record;
1017 struct avdtp_sep_ind *ind;
1018
1019 sep = g_new0(struct a2dp_sep, 1);
1020
1021 ind = (codec == A2DP_CODEC_MPEG12) ? &mpeg_ind : &sbc_ind;
1022 sep->sep = avdtp_register_sep(&server->src, type,
1023 AVDTP_MEDIA_TYPE_AUDIO, codec, ind,
1024 &cfm, sep);
1025 if (sep->sep == NULL) {
1026 g_free(sep);
1027 return NULL;
1028 }
1029
1030 sep->codec = codec;
1031 sep->type = type;
1032
1033 if (type == AVDTP_SEP_TYPE_SOURCE) {
1034 l = &server->sources;
1035 record_id = &server->source_record_id;
1036 } else {
1037 l = &server->sinks;
1038 record_id = &server->sink_record_id;
1039 }
1040
1041 if (*record_id != 0)
1042 goto add;
1043
1044 record = a2dp_record(type);
1045 if (!record) {
1046 error("Unable to allocate new service record");
1047 avdtp_unregister_sep(sep->sep);
1048 g_free(sep);
1049 return NULL;
1050 }
1051
1052 if (add_record_to_server(&server->src, record) < 0) {
1053 error("Unable to register A2DP service record");\
1054 sdp_record_free(record);
1055 avdtp_unregister_sep(sep->sep);
1056 g_free(sep);
1057 return NULL;
1058 }
1059 *record_id = record->handle;
1060
1061 add:
1062 *l = g_slist_append(*l, sep);
1063
1064 return sep;
1065 }
1066
find_server(GSList * list,const bdaddr_t * src)1067 static struct a2dp_server *find_server(GSList *list, const bdaddr_t *src)
1068 {
1069 GSList *l;
1070
1071 for (l = list; l; l = l->next) {
1072 struct a2dp_server *server = l->data;
1073
1074 if (bacmp(&server->src, src) == 0)
1075 return server;
1076 }
1077
1078 return NULL;
1079 }
1080
a2dp_register(DBusConnection * conn,const bdaddr_t * src,GKeyFile * config)1081 int a2dp_register(DBusConnection *conn, const bdaddr_t *src, GKeyFile *config)
1082 {
1083 int sbc_srcs = 1, sbc_sinks = 1;
1084 int mpeg12_srcs = 0, mpeg12_sinks = 0;
1085 gboolean source = TRUE, sink = FALSE;
1086 char *str;
1087 GError *err = NULL;
1088 int i;
1089 struct a2dp_server *server;
1090
1091 if (!config)
1092 goto proceed;
1093
1094 str = g_key_file_get_string(config, "General", "Enable", &err);
1095
1096 if (err) {
1097 debug("audio.conf: %s", err->message);
1098 g_clear_error(&err);
1099 } else {
1100 if (strstr(str, "Sink"))
1101 source = TRUE;
1102 if (strstr(str, "Source"))
1103 sink = TRUE;
1104 g_free(str);
1105 }
1106
1107 str = g_key_file_get_string(config, "General", "Disable", &err);
1108
1109 if (err) {
1110 debug("audio.conf: %s", err->message);
1111 g_clear_error(&err);
1112 } else {
1113 if (strstr(str, "Sink"))
1114 source = FALSE;
1115 if (strstr(str, "Source"))
1116 sink = FALSE;
1117 g_free(str);
1118 }
1119
1120 str = g_key_file_get_string(config, "A2DP", "SBCSources", &err);
1121 if (err) {
1122 debug("audio.conf: %s", err->message);
1123 g_clear_error(&err);
1124 } else {
1125 sbc_srcs = atoi(str);
1126 g_free(str);
1127 }
1128
1129 str = g_key_file_get_string(config, "A2DP", "MPEG12Sources", &err);
1130 if (err) {
1131 debug("audio.conf: %s", err->message);
1132 g_clear_error(&err);
1133 } else {
1134 mpeg12_srcs = atoi(str);
1135 g_free(str);
1136 }
1137
1138 str = g_key_file_get_string(config, "A2DP", "SBCSinks", &err);
1139 if (err) {
1140 debug("audio.conf: %s", err->message);
1141 g_clear_error(&err);
1142 } else {
1143 sbc_sinks = atoi(str);
1144 g_free(str);
1145 }
1146
1147 str = g_key_file_get_string(config, "A2DP", "MPEG12Sinks", &err);
1148 if (err) {
1149 debug("audio.conf: %s", err->message);
1150 g_clear_error(&err);
1151 } else {
1152 mpeg12_sinks = atoi(str);
1153 g_free(str);
1154 }
1155
1156 proceed:
1157 if (!connection)
1158 connection = dbus_connection_ref(conn);
1159
1160 server = find_server(servers, src);
1161 if (!server) {
1162 int av_err;
1163
1164 server = g_new0(struct a2dp_server, 1);
1165 if (!server)
1166 return -ENOMEM;
1167
1168 av_err = avdtp_init(src, config);
1169 if (av_err < 0)
1170 return av_err;
1171
1172 bacpy(&server->src, src);
1173 servers = g_slist_append(servers, server);
1174 }
1175
1176 if (source) {
1177 for (i = 0; i < sbc_srcs; i++)
1178 a2dp_add_sep(server, AVDTP_SEP_TYPE_SOURCE,
1179 A2DP_CODEC_SBC);
1180
1181 for (i = 0; i < mpeg12_srcs; i++)
1182 a2dp_add_sep(server, AVDTP_SEP_TYPE_SOURCE,
1183 A2DP_CODEC_MPEG12);
1184 }
1185
1186 if (sink) {
1187 for (i = 0; i < sbc_sinks; i++)
1188 a2dp_add_sep(server, AVDTP_SEP_TYPE_SINK,
1189 A2DP_CODEC_SBC);
1190
1191 for (i = 0; i < mpeg12_sinks; i++)
1192 a2dp_add_sep(server, AVDTP_SEP_TYPE_SINK,
1193 A2DP_CODEC_MPEG12);
1194 }
1195
1196 return 0;
1197 }
1198
a2dp_unregister_sep(struct a2dp_sep * sep)1199 static void a2dp_unregister_sep(struct a2dp_sep *sep)
1200 {
1201 avdtp_unregister_sep(sep->sep);
1202 g_free(sep);
1203 }
1204
a2dp_unregister(const bdaddr_t * src)1205 void a2dp_unregister(const bdaddr_t *src)
1206 {
1207 struct a2dp_server *server;
1208
1209 server = find_server(servers, src);
1210 if (!server)
1211 return;
1212
1213 g_slist_foreach(server->sinks, (GFunc) a2dp_unregister_sep, NULL);
1214 g_slist_free(server->sinks);
1215
1216 g_slist_foreach(server->sources, (GFunc) a2dp_unregister_sep, NULL);
1217 g_slist_free(server->sources);
1218
1219 avdtp_exit(src);
1220
1221 if (server->source_record_id)
1222 remove_record_from_server(server->source_record_id);
1223
1224 if (server->sink_record_id)
1225 remove_record_from_server(server->sink_record_id);
1226
1227 servers = g_slist_remove(servers, server);
1228 g_free(server);
1229
1230 if (servers)
1231 return;
1232
1233 dbus_connection_unref(connection);
1234 connection = NULL;
1235 }
1236
a2dp_get(struct avdtp * session,struct avdtp_remote_sep * rsep)1237 struct a2dp_sep *a2dp_get(struct avdtp *session,
1238 struct avdtp_remote_sep *rsep)
1239 {
1240 GSList *l;
1241 struct a2dp_server *server;
1242 struct avdtp_service_capability *cap;
1243 struct avdtp_media_codec_capability *codec_cap = NULL;
1244 bdaddr_t src;
1245
1246 avdtp_get_peers(session, &src, NULL);
1247 server = find_server(servers, &src);
1248 if (!server)
1249 return NULL;
1250
1251 cap = avdtp_get_codec(rsep);
1252 codec_cap = (void *) cap->data;
1253
1254 if (avdtp_get_type(rsep) == AVDTP_SEP_TYPE_SINK)
1255 l = server->sources;
1256 else
1257 l = server->sinks;
1258
1259 for (; l != NULL; l = l->next) {
1260 struct a2dp_sep *sep = l->data;
1261
1262 if (sep->locked)
1263 continue;
1264
1265 if (sep->codec != codec_cap->media_codec_type)
1266 continue;
1267
1268 if (!sep->stream || avdtp_has_stream(session, sep->stream))
1269 return sep;
1270 }
1271
1272 return NULL;
1273 }
1274
a2dp_config(struct avdtp * session,struct a2dp_sep * sep,a2dp_config_cb_t cb,GSList * caps,void * user_data)1275 unsigned int a2dp_config(struct avdtp *session, struct a2dp_sep *sep,
1276 a2dp_config_cb_t cb, GSList *caps,
1277 void *user_data)
1278 {
1279 struct a2dp_setup_cb *cb_data;
1280 GSList *l;
1281 struct a2dp_server *server;
1282 struct a2dp_setup *setup;
1283 struct a2dp_sep *tmp;
1284 struct avdtp_local_sep *lsep;
1285 struct avdtp_remote_sep *rsep;
1286 struct avdtp_service_capability *cap;
1287 struct avdtp_media_codec_capability *codec_cap = NULL;
1288 int posix_err;
1289 bdaddr_t src;
1290 uint8_t remote_type;
1291
1292 avdtp_get_peers(session, &src, NULL);
1293 server = find_server(servers, &src);
1294 if (!server)
1295 return 0;
1296
1297 for (l = caps; l != NULL; l = l->next) {
1298 cap = l->data;
1299
1300 if (cap->category != AVDTP_MEDIA_CODEC)
1301 continue;
1302
1303 codec_cap = (void *) cap->data;
1304 break;
1305 }
1306
1307 if (!codec_cap)
1308 return 0;
1309
1310 if (sep->codec != codec_cap->media_codec_type)
1311 return 0;
1312
1313 debug("a2dp_config: selected SEP %p", sep->sep);
1314
1315 cb_data = g_new0(struct a2dp_setup_cb, 1);
1316 cb_data->config_cb = cb;
1317 cb_data->user_data = user_data;
1318 cb_data->id = ++cb_id;
1319
1320 setup = find_setup_by_session(session);
1321 if (!setup) {
1322 setup = g_new0(struct a2dp_setup, 1);
1323 setup->session = avdtp_ref(session);
1324 setup->dev = a2dp_get_dev(session);
1325 setups = g_slist_append(setups, setup);
1326 }
1327
1328 setup_ref(setup);
1329 setup->cb = g_slist_append(setup->cb, cb_data);
1330 setup->sep = sep;
1331 setup->stream = sep->stream;
1332 setup->client_caps = caps;
1333
1334 switch (avdtp_sep_get_state(sep->sep)) {
1335 case AVDTP_STATE_IDLE:
1336 if (sep->type == AVDTP_SEP_TYPE_SOURCE) {
1337 l = server->sources;
1338 remote_type = AVDTP_SEP_TYPE_SINK;
1339 } else {
1340 remote_type = AVDTP_SEP_TYPE_SOURCE;
1341 l = server->sinks;
1342 }
1343
1344 for (; l != NULL; l = l->next) {
1345 tmp = l->data;
1346 if (avdtp_has_stream(session, tmp->stream))
1347 break;
1348 }
1349
1350 if (l != NULL) {
1351 setup->reconfigure = TRUE;
1352 if (avdtp_close(session, tmp->stream) < 0) {
1353 error("avdtp_close failed");
1354 goto failed;
1355 }
1356 break;
1357 }
1358
1359 if (avdtp_get_seps(session, remote_type,
1360 codec_cap->media_type,
1361 codec_cap->media_codec_type,
1362 &lsep, &rsep) < 0) {
1363 error("No matching ACP and INT SEPs found");
1364 goto failed;
1365 }
1366
1367 posix_err = avdtp_set_configuration(session, rsep, lsep,
1368 caps, &setup->stream);
1369 if (posix_err < 0) {
1370 error("avdtp_set_configuration: %s",
1371 strerror(-posix_err));
1372 goto failed;
1373 }
1374 break;
1375 case AVDTP_STATE_OPEN:
1376 case AVDTP_STATE_STREAMING:
1377 if (avdtp_stream_has_capabilities(setup->stream, caps)) {
1378 debug("Configuration match: resuming");
1379 g_idle_add((GSourceFunc) finalize_config, setup);
1380 } else if (!setup->reconfigure) {
1381 setup->reconfigure = TRUE;
1382 if (avdtp_close(session, sep->stream) < 0) {
1383 error("avdtp_close failed");
1384 goto failed;
1385 }
1386 }
1387 break;
1388 default:
1389 error("SEP in bad state for requesting a new stream");
1390 goto failed;
1391 }
1392
1393 return cb_data->id;
1394
1395 failed:
1396 setup_unref(setup);
1397 cb_id--;
1398 return 0;
1399 }
1400
a2dp_resume(struct avdtp * session,struct a2dp_sep * sep,a2dp_stream_cb_t cb,void * user_data)1401 unsigned int a2dp_resume(struct avdtp *session, struct a2dp_sep *sep,
1402 a2dp_stream_cb_t cb, void *user_data)
1403 {
1404 struct a2dp_setup_cb *cb_data;
1405 struct a2dp_setup *setup;
1406
1407 cb_data = g_new0(struct a2dp_setup_cb, 1);
1408 cb_data->resume_cb = cb;
1409 cb_data->user_data = user_data;
1410 cb_data->id = ++cb_id;
1411
1412 setup = find_setup_by_session(session);
1413 if (!setup) {
1414 setup = g_new0(struct a2dp_setup, 1);
1415 setup->session = avdtp_ref(session);
1416 setup->dev = a2dp_get_dev(session);
1417 setups = g_slist_append(setups, setup);
1418 }
1419
1420 setup_ref(setup);
1421 setup->cb = g_slist_append(setup->cb, cb_data);
1422 setup->sep = sep;
1423 setup->stream = sep->stream;
1424
1425 switch (avdtp_sep_get_state(sep->sep)) {
1426 case AVDTP_STATE_IDLE:
1427 goto failed;
1428 break;
1429 case AVDTP_STATE_OPEN:
1430 if (avdtp_start(session, sep->stream) < 0) {
1431 error("avdtp_start failed");
1432 goto failed;
1433 }
1434 break;
1435 case AVDTP_STATE_STREAMING:
1436 if (!sep->suspending && sep->suspend_timer) {
1437 g_source_remove(sep->suspend_timer);
1438 sep->suspend_timer = 0;
1439 avdtp_unref(sep->session);
1440 sep->session = NULL;
1441 }
1442 if (sep->suspending)
1443 setup->start = TRUE;
1444 else
1445 g_idle_add((GSourceFunc) finalize_resume, setup);
1446 break;
1447 default:
1448 error("SEP in bad state for resume");
1449 goto failed;
1450 }
1451
1452 return cb_data->id;
1453
1454 failed:
1455 setup_unref(setup);
1456 cb_id--;
1457 return 0;
1458 }
1459
a2dp_suspend(struct avdtp * session,struct a2dp_sep * sep,a2dp_stream_cb_t cb,void * user_data)1460 unsigned int a2dp_suspend(struct avdtp *session, struct a2dp_sep *sep,
1461 a2dp_stream_cb_t cb, void *user_data)
1462 {
1463 struct a2dp_setup_cb *cb_data;
1464 struct a2dp_setup *setup;
1465
1466 cb_data = g_new0(struct a2dp_setup_cb, 1);
1467 cb_data->suspend_cb = cb;
1468 cb_data->user_data = user_data;
1469 cb_data->id = ++cb_id;
1470
1471 setup = find_setup_by_session(session);
1472 if (!setup) {
1473 setup = g_new0(struct a2dp_setup, 1);
1474 setup->session = avdtp_ref(session);
1475 setup->dev = a2dp_get_dev(session);
1476 setups = g_slist_append(setups, setup);
1477 }
1478
1479 setup_ref(setup);
1480 setup->cb = g_slist_append(setup->cb, cb_data);
1481 setup->sep = sep;
1482 setup->stream = sep->stream;
1483
1484 switch (avdtp_sep_get_state(sep->sep)) {
1485 case AVDTP_STATE_IDLE:
1486 error("a2dp_suspend: no stream to suspend");
1487 goto failed;
1488 break;
1489 case AVDTP_STATE_OPEN:
1490 g_idle_add((GSourceFunc) finalize_suspend, setup);
1491 break;
1492 case AVDTP_STATE_STREAMING:
1493 if (avdtp_suspend(session, sep->stream) < 0) {
1494 error("avdtp_suspend failed");
1495 goto failed;
1496 }
1497 break;
1498 default:
1499 error("SEP in bad state for suspend");
1500 goto failed;
1501 }
1502
1503 return cb_data->id;
1504
1505 failed:
1506 setup_unref(setup);
1507 cb_id--;
1508 return 0;
1509 }
1510
a2dp_cancel(struct audio_device * dev,unsigned int id)1511 gboolean a2dp_cancel(struct audio_device *dev, unsigned int id)
1512 {
1513 struct a2dp_setup_cb *cb_data;
1514 struct a2dp_setup *setup;
1515 GSList *l;
1516
1517 debug("a2dp_cancel()");
1518
1519 setup = find_setup_by_dev(dev);
1520 if (!setup)
1521 return FALSE;
1522
1523 for (cb_data = NULL, l = setup->cb; l != NULL; l = g_slist_next(l)) {
1524 struct a2dp_setup_cb *cb = l->data;
1525
1526 if (cb->id == id) {
1527 cb_data = cb;
1528 break;
1529 }
1530 }
1531
1532 if (!cb_data)
1533 error("a2dp_cancel: no matching callback with id %u", id);
1534
1535 setup->cb = g_slist_remove(setup->cb, cb_data);
1536 g_free(cb_data);
1537
1538 if (!setup->cb) {
1539 setup->canceled = TRUE;
1540 setup->sep = NULL;
1541 }
1542
1543 return TRUE;
1544 }
1545
a2dp_sep_lock(struct a2dp_sep * sep,struct avdtp * session)1546 gboolean a2dp_sep_lock(struct a2dp_sep *sep, struct avdtp *session)
1547 {
1548 if (sep->locked)
1549 return FALSE;
1550
1551 debug("SEP %p locked", sep->sep);
1552 sep->locked = TRUE;
1553
1554 return TRUE;
1555 }
1556
a2dp_sep_unlock(struct a2dp_sep * sep,struct avdtp * session)1557 gboolean a2dp_sep_unlock(struct a2dp_sep *sep, struct avdtp *session)
1558 {
1559 avdtp_state_t state;
1560
1561 state = avdtp_sep_get_state(sep->sep);
1562
1563 sep->locked = FALSE;
1564
1565 debug("SEP %p unlocked", sep->sep);
1566
1567 if (!sep->stream || state == AVDTP_STATE_IDLE)
1568 return TRUE;
1569
1570 switch (state) {
1571 case AVDTP_STATE_OPEN:
1572 /* Set timer here */
1573 break;
1574 case AVDTP_STATE_STREAMING:
1575 if (avdtp_suspend(session, sep->stream) == 0)
1576 sep->suspending = TRUE;
1577 break;
1578 default:
1579 break;
1580 }
1581
1582 return TRUE;
1583 }
1584
a2dp_sep_get_lock(struct a2dp_sep * sep)1585 gboolean a2dp_sep_get_lock(struct a2dp_sep *sep)
1586 {
1587 return sep->locked;
1588 }
1589
stream_cmp(gconstpointer data,gconstpointer user_data)1590 static int stream_cmp(gconstpointer data, gconstpointer user_data)
1591 {
1592 const struct a2dp_sep *sep = data;
1593 const struct avdtp_stream *stream = user_data;
1594
1595 return (sep->stream != stream);
1596 }
1597
a2dp_get_sep(struct avdtp * session,struct avdtp_stream * stream)1598 struct a2dp_sep *a2dp_get_sep(struct avdtp *session,
1599 struct avdtp_stream *stream)
1600 {
1601 struct a2dp_server *server;
1602 bdaddr_t src, dst;
1603 GSList *l;
1604
1605 avdtp_get_peers(session, &src, &dst);
1606
1607 for (l = servers; l; l = l->next) {
1608 server = l->data;
1609
1610 if (bacmp(&src, &server->src) == 0)
1611 break;
1612 }
1613
1614 if (!l)
1615 return NULL;
1616
1617 l = g_slist_find_custom(server->sources, stream, stream_cmp);
1618 if (l)
1619 return l->data;
1620
1621 l = g_slist_find_custom(server->sinks, stream, stream_cmp);
1622 if (l)
1623 return l->data;
1624
1625 return NULL;
1626 }
1627