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