• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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