93d0460b62efd73056dd319f20dbba767adbd1ae
[platform/upstream/bluez.git] / profiles / audio / a2dp.c
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  *  Copyright (C) 2011  BMW Car IT GmbH. All rights reserved.
8  *
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <errno.h>
33
34 #include <dbus/dbus.h>
35 #include <glib.h>
36
37 #include "lib/bluetooth.h"
38 #include "lib/sdp.h"
39 #include "lib/sdp_lib.h"
40 #include "lib/uuid.h"
41
42 #include "gdbus/gdbus.h"
43
44 #include "src/hcid.h"
45 #include "src/plugin.h"
46 #include "src/adapter.h"
47 #include "src/device.h"
48 #include "src/dbus-common.h"
49 #include "src/error.h"
50 #include "src/profile.h"
51 #include "src/service.h"
52 #include "src/log.h"
53 #include "src/sdpd.h"
54 #include "src/shared/queue.h"
55 #include "src/shared/util.h"
56
57 #include "btio/btio.h"
58
59 #include "avdtp.h"
60 #include "sink.h"
61 #include "source.h"
62 #include "a2dp.h"
63 #include "a2dp-codecs.h"
64 #include "media.h"
65
66 /* The duration that streams without users are allowed to stay in
67  * STREAMING state. */
68 #define SUSPEND_TIMEOUT 5
69 #define RECONFIGURE_TIMEOUT 500
70
71 #define AVDTP_PSM 25
72 #define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint1"
73
74 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
75 #ifdef TIZEN_FEATURE_SSC_ENCODER
76 /* Vendor and Codec ID for Samsung Scalable codec */
77 #define PREFRED_VENDOR_ID       0x00000075
78 #define PREFRED_CODEC_ID        0x0103
79 #endif
80 #endif
81
82 struct a2dp_sep {
83         struct a2dp_server *server;
84         struct a2dp_endpoint *endpoint;
85         uint8_t type;
86         uint8_t codec;
87         struct avdtp_local_sep *lsep;
88         struct avdtp *session;
89         struct avdtp_stream *stream;
90         guint suspend_timer;
91 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
92         gboolean remote_suspended;
93 #endif
94         gboolean delay_reporting;
95         gboolean locked;
96         gboolean suspending;
97         gboolean starting;
98         void *user_data;
99         GDestroyNotify destroy;
100 };
101
102 struct a2dp_setup_cb {
103         struct a2dp_setup *setup;
104         a2dp_discover_cb_t discover_cb;
105         a2dp_select_cb_t select_cb;
106         a2dp_config_cb_t config_cb;
107         a2dp_stream_cb_t resume_cb;
108         a2dp_stream_cb_t suspend_cb;
109         guint source_id;
110         void *user_data;
111         unsigned int id;
112 };
113
114 struct a2dp_setup {
115         struct a2dp_channel *chan;
116         struct avdtp *session;
117         struct queue *eps;
118         struct a2dp_sep *sep;
119         struct a2dp_remote_sep *rsep;
120         struct avdtp_stream *stream;
121         struct avdtp_error *err;
122         avdtp_set_configuration_cb setconf_cb;
123         GSList *seps;
124         GSList *caps;
125         gboolean reconfigure;
126         gboolean start;
127         GSList *cb;
128         GIOChannel *io;
129         int ref;
130 };
131
132 struct a2dp_server {
133         struct btd_adapter *adapter;
134         GSList *sinks;
135         GSList *sources;
136         uint32_t source_record_id;
137         uint32_t sink_record_id;
138         gboolean sink_enabled;
139         gboolean source_enabled;
140         GIOChannel *io;
141         struct queue *seps;
142         struct queue *channels;
143 };
144
145 struct a2dp_remote_sep {
146         struct a2dp_channel *chan;
147         char *path;
148         struct avdtp_remote_sep *sep;
149 };
150
151 struct a2dp_last_used {
152         struct a2dp_sep *lsep;
153         struct a2dp_remote_sep *rsep;
154 };
155
156 struct a2dp_channel {
157         struct a2dp_server *server;
158         struct btd_device *device;
159         GIOChannel *io;
160         guint io_id;
161         unsigned int state_id;
162         unsigned int auth_id;
163         struct avdtp *session;
164         struct queue *seps;
165         struct a2dp_last_used *last_used;
166 };
167
168 static GSList *servers = NULL;
169 static GSList *setups = NULL;
170 static unsigned int cb_id = 0;
171
172 static struct a2dp_setup *setup_ref(struct a2dp_setup *setup)
173 {
174         setup->ref++;
175
176         DBG("%p: ref=%d", setup, setup->ref);
177
178         return setup;
179 }
180
181 static bool match_by_session(const void *data, const void *user_data)
182 {
183         const struct a2dp_channel *chan = data;
184         const struct avdtp *session = user_data;
185
186         return chan->session == session;
187 }
188
189 static struct a2dp_channel *find_channel(struct avdtp *session)
190 {
191         GSList *l;
192
193         for (l = servers; l; l = g_slist_next(l)) {
194                 struct a2dp_server *server = l->data;
195                 struct a2dp_channel *chan;
196
197                 chan = queue_find(server->channels, match_by_session, session);
198                 if (chan)
199                         return chan;
200         }
201
202         return NULL;
203 }
204
205 static struct a2dp_setup *setup_new(struct avdtp *session)
206 {
207         struct a2dp_setup *setup;
208         struct a2dp_channel *chan;
209
210         chan = find_channel(session);
211         if (!chan)
212                 return NULL;
213
214         setup = g_new0(struct a2dp_setup, 1);
215         setup->session = avdtp_ref(session);
216         setup->chan = find_channel(session);
217         setups = g_slist_append(setups, setup);
218
219         return setup;
220 }
221
222 static void setup_free(struct a2dp_setup *s)
223 {
224         DBG("%p", s);
225
226         if (s->io) {
227                 g_io_channel_shutdown(s->io, TRUE, NULL);
228                 g_io_channel_unref(s->io);
229         }
230
231         queue_destroy(s->eps, NULL);
232
233         setups = g_slist_remove(setups, s);
234         if (s->session)
235                 avdtp_unref(s->session);
236         g_slist_free_full(s->cb, g_free);
237         g_slist_free_full(s->caps, g_free);
238         g_free(s);
239 }
240
241 static void setup_unref(struct a2dp_setup *setup)
242 {
243         setup->ref--;
244
245         DBG("%p: ref=%d", setup, setup->ref);
246
247         if (setup->ref > 0)
248                 return;
249
250         setup_free(setup);
251 }
252
253 static struct a2dp_setup_cb *setup_cb_new(struct a2dp_setup *setup)
254 {
255         struct a2dp_setup_cb *cb;
256
257         cb = g_new0(struct a2dp_setup_cb, 1);
258         cb->setup = setup;
259         cb->id = ++cb_id;
260
261         setup->cb = g_slist_append(setup->cb, cb);
262         return cb;
263 }
264
265 static void setup_cb_free(struct a2dp_setup_cb *cb)
266 {
267         struct a2dp_setup *setup = cb->setup;
268
269         if (cb->source_id)
270                 g_source_remove(cb->source_id);
271
272         setup->cb = g_slist_remove(setup->cb, cb);
273         setup_unref(cb->setup);
274         g_free(cb);
275 }
276
277 static void finalize_setup_errno(struct a2dp_setup *s, int err,
278                                         GSourceFunc cb1, ...)
279 {
280         GSourceFunc finalize;
281         va_list args;
282 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
283         struct avdtp_error *avdtp_err;
284 #else
285         struct avdtp_error avdtp_err;
286 #endif
287
288         if (err < 0) {
289 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
290                 avdtp_err = g_new(struct avdtp_error, 1);
291                 avdtp_error_init(avdtp_err, AVDTP_ERRNO, -err);
292                 s->err = avdtp_err;
293 #else
294                 avdtp_error_init(&avdtp_err, AVDTP_ERRNO, -err);
295                 s->err = &avdtp_err;
296 #endif
297         }
298
299         va_start(args, cb1);
300         finalize = cb1;
301         setup_ref(s);
302         while (finalize != NULL) {
303                 finalize(s);
304                 finalize = va_arg(args, GSourceFunc);
305         }
306         setup_unref(s);
307         va_end(args);
308 }
309
310 static int error_to_errno(struct avdtp_error *err)
311 {
312         int perr;
313
314         if (!err)
315                 return 0;
316
317         if (avdtp_error_category(err) != AVDTP_ERRNO)
318                 return -EIO;
319
320         perr = avdtp_error_posix_errno(err);
321         switch (perr) {
322         case EHOSTDOWN:
323         case ECONNABORTED:
324                 return -perr;
325         default:
326                 /*
327                  * An unexpect error has occurred setup may be attempted again.
328                  */
329                 return -EAGAIN;
330         }
331 }
332
333 static gboolean finalize_config(gpointer data)
334 {
335         struct a2dp_setup *s = data;
336         GSList *l;
337         struct avdtp_stream *stream = s->err ? NULL : s->stream;
338
339         for (l = s->cb; l != NULL; ) {
340                 struct a2dp_setup_cb *cb = l->data;
341
342                 l = l->next;
343
344                 if (!cb->config_cb)
345                         continue;
346
347                 cb->config_cb(s->session, s->sep, stream,
348                                 error_to_errno(s->err), cb->user_data);
349                 setup_cb_free(cb);
350         }
351
352         return FALSE;
353 }
354
355 static gboolean finalize_resume(gpointer data)
356 {
357         struct a2dp_setup *s = data;
358         GSList *l;
359
360         for (l = s->cb; l != NULL; ) {
361                 struct a2dp_setup_cb *cb = l->data;
362
363                 l = l->next;
364
365                 if (!cb->resume_cb)
366                         continue;
367
368                 cb->resume_cb(s->session, error_to_errno(s->err),
369                                                         cb->user_data);
370                 setup_cb_free(cb);
371         }
372
373         return FALSE;
374 }
375
376 static gboolean finalize_suspend(gpointer data)
377 {
378         struct a2dp_setup *s = data;
379         GSList *l;
380
381         for (l = s->cb; l != NULL; ) {
382                 struct a2dp_setup_cb *cb = l->data;
383
384                 l = l->next;
385
386                 if (!cb->suspend_cb)
387                         continue;
388
389                 cb->suspend_cb(s->session, error_to_errno(s->err),
390                                                         cb->user_data);
391                 setup_cb_free(cb);
392         }
393
394         return FALSE;
395 }
396
397 static void finalize_select(struct a2dp_setup *s)
398 {
399         GSList *l;
400
401         for (l = s->cb; l != NULL; ) {
402                 struct a2dp_setup_cb *cb = l->data;
403
404                 l = l->next;
405
406                 if (!cb->select_cb)
407                         continue;
408
409                 cb->select_cb(s->session, s->sep, s->caps, cb->user_data);
410                 setup_cb_free(cb);
411         }
412 }
413
414 static void finalize_discover(struct a2dp_setup *s)
415 {
416         GSList *l;
417
418         for (l = s->cb; l != NULL; ) {
419                 struct a2dp_setup_cb *cb = l->data;
420
421                 l = l->next;
422
423                 if (!cb->discover_cb)
424                         continue;
425
426                 cb->discover_cb(s->session, s->seps, error_to_errno(s->err),
427                                                                 cb->user_data);
428                 setup_cb_free(cb);
429         }
430 }
431
432 static struct a2dp_setup *find_setup_by_session(struct avdtp *session)
433 {
434         GSList *l;
435
436         for (l = setups; l != NULL; l = l->next) {
437                 struct a2dp_setup *setup = l->data;
438
439                 if (setup->session == session)
440                         return setup;
441         }
442
443         return NULL;
444 }
445
446 static struct a2dp_setup *a2dp_setup_get(struct avdtp *session)
447 {
448         struct a2dp_setup *setup;
449
450         setup = find_setup_by_session(session);
451         if (!setup) {
452                 setup = setup_new(session);
453                 if (!setup)
454                         return NULL;
455         }
456
457         return setup_ref(setup);
458 }
459
460 static struct a2dp_setup *find_setup_by_stream(struct avdtp_stream *stream)
461 {
462         GSList *l;
463
464         for (l = setups; l != NULL; l = l->next) {
465                 struct a2dp_setup *setup = l->data;
466
467                 if (setup->stream == stream)
468                         return setup;
469         }
470
471         return NULL;
472 }
473
474 static void stream_state_changed(struct avdtp_stream *stream,
475                                         avdtp_state_t old_state,
476                                         avdtp_state_t new_state,
477                                         struct avdtp_error *err,
478                                         void *user_data)
479 {
480         struct a2dp_sep *sep = user_data;
481
482         if (new_state == AVDTP_STATE_OPEN) {
483                 struct a2dp_setup *setup;
484                 int err;
485
486                 setup = find_setup_by_stream(stream);
487                 if (!setup || !setup->start)
488                         return;
489
490                 setup->start = FALSE;
491
492                 err = avdtp_start(setup->session, stream);
493                 if (err < 0 && err != -EINPROGRESS) {
494                         error("avdtp_start: %s (%d)", strerror(-err), -err);
495                         finalize_setup_errno(setup, err, finalize_resume,
496                                                                         NULL);
497                         return;
498                 }
499
500                 sep->starting = TRUE;
501
502                 return;
503         }
504
505 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
506         if (new_state == AVDTP_STATE_STREAMING && sep->suspend_timer) {
507                 g_source_remove(sep->suspend_timer);
508                 sep->suspend_timer = 0;
509         }
510 #endif
511
512         if (new_state != AVDTP_STATE_IDLE)
513                 return;
514
515         if (sep->suspend_timer) {
516                 g_source_remove(sep->suspend_timer);
517                 sep->suspend_timer = 0;
518         }
519
520         if (sep->session) {
521                 avdtp_unref(sep->session);
522                 sep->session = NULL;
523         }
524
525         sep->stream = NULL;
526
527         if (sep->endpoint && sep->endpoint->clear_configuration)
528                 sep->endpoint->clear_configuration(sep, sep->user_data);
529 }
530
531 static gboolean auto_config(gpointer data)
532 {
533         struct a2dp_setup *setup = data;
534         struct btd_device *dev = NULL;
535         struct btd_service *service;
536
537         /* Check if configuration was aborted */
538         if (setup->sep->stream == NULL)
539                 return FALSE;
540
541         if (setup->err != NULL)
542                 goto done;
543
544         dev = avdtp_get_device(setup->session);
545
546         avdtp_stream_add_cb(setup->session, setup->stream,
547                                 stream_state_changed, setup->sep);
548
549         if (setup->sep->type == AVDTP_SEP_TYPE_SOURCE) {
550                 service = btd_device_get_service(dev, A2DP_SINK_UUID);
551                 sink_new_stream(service, setup->session, setup->stream);
552         } else {
553                 service = btd_device_get_service(dev, A2DP_SOURCE_UUID);
554                 source_new_stream(service, setup->session, setup->stream);
555         }
556
557 done:
558         if (setup->setconf_cb)
559                 setup->setconf_cb(setup->session, setup->stream, setup->err);
560
561         finalize_config(setup);
562
563         if (setup->err) {
564                 g_free(setup->err);
565                 setup->err = NULL;
566         }
567
568         setup_unref(setup);
569
570         return FALSE;
571 }
572
573 static void endpoint_setconf_cb(struct a2dp_setup *setup, gboolean ret)
574 {
575         if (ret == FALSE) {
576                 setup->err = g_new(struct avdtp_error, 1);
577                 avdtp_error_init(setup->err, AVDTP_MEDIA_CODEC,
578                                         AVDTP_UNSUPPORTED_CONFIGURATION);
579         }
580
581         auto_config(setup);
582         setup_unref(setup);
583 }
584
585 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
586 #ifdef TIZEN_FEATURE_SSC_ENCODER
587 static gboolean endpoint_match_codec_preference(struct avdtp *session,
588                 struct avdtp_media_codec_capability *codec,
589                 void *user_data)
590 {
591         struct a2dp_sep *sep = user_data;
592         uint8_t *capabilities;
593         a2dp_vendor_codec_t *local_codec;
594         size_t length;
595
596         length = sep->endpoint->get_capabilities(sep, &capabilities,
597                         sep->user_data);
598         if (length < sizeof(a2dp_vendor_codec_t))
599                 return FALSE;
600
601         local_codec = (a2dp_vendor_codec_t *) capabilities;
602         DBG("vendor 0x%08x codec 0x%04x", btohl(local_codec->vendor_id),
603                         btohs(local_codec->codec_id));
604         if (btohl(local_codec->vendor_id) == PREFRED_VENDOR_ID &&
605                         btohs(local_codec->codec_id) == PREFRED_CODEC_ID) {
606                 DBG("Samsung Scalable Codec Selected");
607                 return TRUE;
608         }
609         return FALSE;
610 }
611 #endif
612 #endif
613
614 static gboolean endpoint_match_codec_ind(struct avdtp *session,
615                                 struct avdtp_media_codec_capability *codec,
616                                 void *user_data)
617 {
618         struct a2dp_sep *sep = user_data;
619         a2dp_vendor_codec_t *remote_codec;
620         a2dp_vendor_codec_t *local_codec;
621         uint8_t *capabilities;
622         size_t length;
623
624         if (codec->media_codec_type != A2DP_CODEC_VENDOR)
625                 return TRUE;
626
627         if (sep->endpoint == NULL)
628                 return FALSE;
629
630         length = sep->endpoint->get_capabilities(sep, &capabilities,
631                                                         sep->user_data);
632         if (length < sizeof(a2dp_vendor_codec_t))
633                 return FALSE;
634
635         local_codec = (a2dp_vendor_codec_t *) capabilities;
636         remote_codec = (a2dp_vendor_codec_t *) codec->data;
637
638         if (A2DP_GET_VENDOR_ID(*remote_codec) !=
639                         A2DP_GET_VENDOR_ID(*local_codec))
640                 return FALSE;
641
642         if (A2DP_GET_CODEC_ID(*remote_codec) != A2DP_GET_CODEC_ID(*local_codec))
643                 return FALSE;
644
645         DBG("vendor 0x%08x codec 0x%04x", A2DP_GET_VENDOR_ID(*remote_codec),
646                                         A2DP_GET_CODEC_ID(*remote_codec));
647         return TRUE;
648 }
649
650 static void reverse_discover(struct avdtp *session, GSList *seps, int err,
651                                                         void *user_data)
652 {
653         DBG("err %d", err);
654 }
655
656 static gboolean endpoint_setconf_ind(struct avdtp *session,
657                                                 struct avdtp_local_sep *sep,
658                                                 struct avdtp_stream *stream,
659                                                 GSList *caps,
660                                                 avdtp_set_configuration_cb cb,
661                                                 void *user_data)
662 {
663         struct a2dp_sep *a2dp_sep = user_data;
664         struct a2dp_setup *setup;
665
666         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
667                 DBG("Sink %p: Set_Configuration_Ind", sep);
668         else
669                 DBG("Source %p: Set_Configuration_Ind", sep);
670
671         setup = a2dp_setup_get(session);
672         if (!session)
673                 return FALSE;
674
675         a2dp_sep->stream = stream;
676         setup->sep = a2dp_sep;
677         setup->stream = stream;
678         setup->setconf_cb = cb;
679
680         for (; caps != NULL; caps = g_slist_next(caps)) {
681                 struct avdtp_service_capability *cap = caps->data;
682                 struct avdtp_media_codec_capability *codec;
683                 gboolean ret;
684
685                 if (cap->category == AVDTP_DELAY_REPORTING &&
686                                         !a2dp_sep->delay_reporting) {
687                         setup->err = g_new(struct avdtp_error, 1);
688                         avdtp_error_init(setup->err, AVDTP_DELAY_REPORTING,
689                                         AVDTP_UNSUPPORTED_CONFIGURATION);
690                         goto done;
691                 }
692
693                 if (cap->category != AVDTP_MEDIA_CODEC)
694                         continue;
695
696                 codec = (struct avdtp_media_codec_capability *) cap->data;
697
698                 if (codec->media_codec_type != a2dp_sep->codec) {
699                         setup->err = g_new(struct avdtp_error, 1);
700                         avdtp_error_init(setup->err, AVDTP_MEDIA_CODEC,
701                                         AVDTP_UNSUPPORTED_CONFIGURATION);
702                         goto done;
703                 }
704
705                 ret = a2dp_sep->endpoint->set_configuration(a2dp_sep,
706                                                 codec->data,
707                                                 cap->length - sizeof(*codec),
708                                                 setup_ref(setup),
709                                                 endpoint_setconf_cb,
710                                                 a2dp_sep->user_data);
711                 if (ret == 0) {
712                         /* Attempt to reverse discover if there are no remote
713                          * SEPs.
714                          */
715                         if (queue_isempty(setup->chan->seps))
716                                 a2dp_discover(session, reverse_discover, NULL);
717                         return TRUE;
718                 }
719
720                 setup_unref(setup);
721                 setup->err = g_new(struct avdtp_error, 1);
722                 avdtp_error_init(setup->err, AVDTP_MEDIA_CODEC,
723                                         AVDTP_UNSUPPORTED_CONFIGURATION);
724                 break;
725         }
726
727 done:
728         g_idle_add(auto_config, setup);
729         return TRUE;
730 }
731
732 static gboolean endpoint_getcap_ind(struct avdtp *session,
733                                         struct avdtp_local_sep *sep,
734                                         gboolean get_all, GSList **caps,
735                                         uint8_t *err, void *user_data)
736 {
737         struct a2dp_sep *a2dp_sep = user_data;
738         struct avdtp_service_capability *media_transport, *media_codec;
739         struct avdtp_media_codec_capability *codec_caps;
740         uint8_t *capabilities;
741         size_t length;
742
743         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
744                 DBG("Sink %p: Get_Capability_Ind", sep);
745         else
746                 DBG("Source %p: Get_Capability_Ind", sep);
747
748         *caps = NULL;
749
750         media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
751                                                 NULL, 0);
752
753         *caps = g_slist_append(*caps, media_transport);
754
755         length = a2dp_sep->endpoint->get_capabilities(a2dp_sep, &capabilities,
756                                                         a2dp_sep->user_data);
757
758         codec_caps = g_malloc0(sizeof(*codec_caps) + length);
759         codec_caps->media_type = AVDTP_MEDIA_TYPE_AUDIO;
760         codec_caps->media_codec_type = a2dp_sep->codec;
761         memcpy(codec_caps->data, capabilities, length);
762
763         media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, codec_caps,
764                                                 sizeof(*codec_caps) + length);
765
766         *caps = g_slist_append(*caps, media_codec);
767         g_free(codec_caps);
768
769         if (get_all) {
770                 struct avdtp_service_capability *delay_reporting;
771                 delay_reporting = avdtp_service_cap_new(AVDTP_DELAY_REPORTING,
772                                                                 NULL, 0);
773                 *caps = g_slist_append(*caps, delay_reporting);
774         }
775
776         return TRUE;
777 }
778
779 static void endpoint_open_cb(struct a2dp_setup *setup, gboolean ret)
780 {
781         int err;
782
783         if (ret == FALSE) {
784                 setup->stream = NULL;
785                 finalize_setup_errno(setup, -EPERM, finalize_config, NULL);
786                 goto done;
787         }
788
789         err = avdtp_open(setup->session, setup->stream);
790         if (err == 0)
791                 goto done;
792
793         error("avdtp_open %s (%d)", strerror(-err), -err);
794         setup->stream = NULL;
795         finalize_setup_errno(setup, err, finalize_config, NULL);
796 done:
797         setup_unref(setup);
798 }
799
800 static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
801                                 struct avdtp_stream *stream,
802                                 struct avdtp_error *err, void *user_data)
803 {
804         struct a2dp_sep *a2dp_sep = user_data;
805         struct a2dp_setup *setup;
806         struct btd_device *dev;
807         struct btd_service *service;
808         int ret;
809
810         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
811                 DBG("Sink %p: Set_Configuration_Cfm", sep);
812         else
813                 DBG("Source %p: Set_Configuration_Cfm", sep);
814
815         setup = find_setup_by_session(session);
816
817         if (err) {
818                 if (setup) {
819                         setup_ref(setup);
820                         setup->err = err;
821                         finalize_config(setup);
822                         setup->err = NULL;
823                         setup_unref(setup);
824                 }
825                 return;
826         }
827
828         avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep);
829         a2dp_sep->stream = stream;
830
831         if (!setup)
832                 return;
833
834         dev = avdtp_get_device(session);
835
836         /* Notify D-Bus interface of the new stream */
837         if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE) {
838                 service = btd_device_get_service(dev, A2DP_SINK_UUID);
839                 sink_new_stream(service, session, setup->stream);
840         } else {
841                 service = btd_device_get_service(dev, A2DP_SOURCE_UUID);
842                 source_new_stream(service, session, setup->stream);
843         }
844
845         /* Notify Endpoint */
846         if (a2dp_sep->endpoint) {
847                 struct avdtp_service_capability *service;
848                 struct avdtp_media_codec_capability *codec;
849                 int err;
850
851                 service = avdtp_stream_get_codec(stream);
852                 codec = (struct avdtp_media_codec_capability *) service->data;
853
854                 err = a2dp_sep->endpoint->set_configuration(a2dp_sep,
855                                                 codec->data, service->length -
856                                                 sizeof(*codec),
857                                                 setup_ref(setup),
858                                                 endpoint_open_cb,
859                                                 a2dp_sep->user_data);
860                 if (err == 0)
861                         return;
862
863                 setup->stream = NULL;
864                 finalize_setup_errno(setup, -EPERM, finalize_config, NULL);
865                 setup_unref(setup);
866                 return;
867         }
868
869         ret = avdtp_open(session, stream);
870         if (ret < 0) {
871                 error("avdtp_open %s (%d)", strerror(-ret), -ret);
872                 setup->stream = NULL;
873                 finalize_setup_errno(setup, ret, finalize_config, NULL);
874         }
875 }
876
877 static gboolean getconf_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: Get_Configuration_Ind", sep);
884         else
885                 DBG("Source %p: Get_Configuration_Ind", sep);
886         return TRUE;
887 }
888
889 static void getconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
890                         struct avdtp_stream *stream, struct avdtp_error *err,
891                         void *user_data)
892 {
893         struct a2dp_sep *a2dp_sep = user_data;
894
895         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
896                 DBG("Sink %p: Set_Configuration_Cfm", sep);
897         else
898                 DBG("Source %p: Set_Configuration_Cfm", sep);
899 }
900
901 static bool match_remote_sep(const void *data, const void *user_data)
902 {
903         const struct a2dp_remote_sep *sep = data;
904         const struct avdtp_remote_sep *rsep = user_data;
905
906         return sep->sep == rsep;
907 }
908
909 static void store_last_used(struct a2dp_channel *chan, uint8_t lseid,
910                                                         uint8_t rseid)
911 {
912         GKeyFile *key_file;
913         char filename[PATH_MAX];
914         char dst_addr[18];
915         char value[6];
916         char *data;
917         size_t len = 0;
918
919         ba2str(device_get_address(chan->device), dst_addr);
920
921         snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
922                 btd_adapter_get_storage_dir(device_get_adapter(chan->device)),
923                 dst_addr);
924         key_file = g_key_file_new();
925         g_key_file_load_from_file(key_file, filename, 0, NULL);
926
927         sprintf(value, "%02hhx:%02hhx", lseid, rseid);
928
929         g_key_file_set_string(key_file, "Endpoints", "LastUsed", value);
930
931         data = g_key_file_to_data(key_file, &len, NULL);
932         g_file_set_contents(filename, data, len, NULL);
933
934         g_free(data);
935         g_key_file_free(key_file);
936 }
937
938 static void add_last_used(struct a2dp_channel *chan, struct a2dp_sep *lsep,
939                                 struct a2dp_remote_sep *rsep)
940 {
941         if (!chan->last_used)
942                 chan->last_used = new0(struct a2dp_last_used, 1);
943
944         chan->last_used->lsep = lsep;
945         chan->last_used->rsep = rsep;
946 }
947
948 static void update_last_used(struct a2dp_channel *chan, struct a2dp_sep *lsep,
949                                         struct avdtp_stream *stream)
950 {
951         struct avdtp_remote_sep *rsep;
952         struct a2dp_remote_sep *sep;
953
954         rsep = avdtp_stream_get_remote_sep(stream);
955         sep = queue_find(chan->seps, match_remote_sep, rsep);
956         if (!sep) {
957                 error("Unable to find remote SEP");
958                 return;
959         }
960
961         /* Check if already stored then skip */
962         if (chan->last_used && (chan->last_used->lsep == lsep &&
963                                 chan->last_used->rsep == sep))
964                 return;
965
966         add_last_used(chan, lsep, sep);
967
968         store_last_used(chan, avdtp_sep_get_seid(lsep->lsep),
969                                         avdtp_get_seid(rsep));
970 }
971
972 static gboolean open_ind(struct avdtp *session, struct avdtp_local_sep *sep,
973                                 struct avdtp_stream *stream, uint8_t *err,
974                                 void *user_data)
975 {
976         struct a2dp_sep *a2dp_sep = user_data;
977         struct a2dp_setup *setup;
978
979         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
980                 DBG("Sink %p: Open_Ind", sep);
981         else
982                 DBG("Source %p: Open_Ind", sep);
983
984         setup = a2dp_setup_get(session);
985         if (!setup)
986                 return FALSE;
987
988         setup->stream = stream;
989
990         if (!err && setup->chan)
991                 update_last_used(setup->chan, a2dp_sep, stream);
992
993         if (setup->reconfigure)
994                 setup->reconfigure = FALSE;
995
996         finalize_config(setup);
997
998         return TRUE;
999 }
1000
1001 static void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
1002                         struct avdtp_stream *stream, struct avdtp_error *err,
1003                         void *user_data)
1004 {
1005         struct a2dp_sep *a2dp_sep = user_data;
1006         struct a2dp_setup *setup;
1007
1008         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1009                 DBG("Sink %p: Open_Cfm", sep);
1010         else
1011                 DBG("Source %p: Open_Cfm", sep);
1012
1013         setup = find_setup_by_session(session);
1014         if (!setup)
1015                 return;
1016
1017         if (setup->reconfigure)
1018                 setup->reconfigure = FALSE;
1019
1020         if (err) {
1021                 setup->stream = NULL;
1022                 setup->err = err;
1023                 if (setup->start)
1024                         finalize_resume(setup);
1025         } else if (setup->chan)
1026                 update_last_used(setup->chan, a2dp_sep, stream);
1027
1028         finalize_config(setup);
1029
1030         return;
1031 }
1032
1033 static gboolean suspend_timeout(struct a2dp_sep *sep)
1034 {
1035         if (avdtp_suspend(sep->session, sep->stream) == 0)
1036                 sep->suspending = TRUE;
1037
1038         sep->suspend_timer = 0;
1039
1040         avdtp_unref(sep->session);
1041         sep->session = NULL;
1042
1043         return FALSE;
1044 }
1045
1046 static gboolean start_ind(struct avdtp *session, struct avdtp_local_sep *sep,
1047                                 struct avdtp_stream *stream, uint8_t *err,
1048                                 void *user_data)
1049 {
1050         struct a2dp_sep *a2dp_sep = user_data;
1051         struct a2dp_setup *setup;
1052
1053         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1054                 DBG("Sink %p: Start_Ind", sep);
1055         else
1056                 DBG("Source %p: Start_Ind", sep);
1057
1058 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1059         if (!a2dp_sep->locked) {
1060                 if (a2dp_sep->remote_suspended == FALSE) {
1061                         a2dp_sep->session = avdtp_ref(session);
1062                         a2dp_sep->suspend_timer = g_timeout_add_seconds(SUSPEND_TIMEOUT,
1063                                                         (GSourceFunc) suspend_timeout,
1064                                                         a2dp_sep);
1065                 } else
1066                         a2dp_sep->remote_suspended = FALSE;
1067         }
1068 #else
1069
1070         if (!a2dp_sep->locked) {
1071                 a2dp_sep->session = avdtp_ref(session);
1072                 a2dp_sep->suspend_timer = g_timeout_add_seconds(SUSPEND_TIMEOUT,
1073                                                 (GSourceFunc) suspend_timeout,
1074                                                 a2dp_sep);
1075         }
1076 #endif
1077
1078         if (!a2dp_sep->starting)
1079                 return TRUE;
1080
1081         a2dp_sep->starting = FALSE;
1082
1083         setup = find_setup_by_session(session);
1084         if (setup)
1085                 finalize_resume(setup);
1086
1087         return TRUE;
1088 }
1089
1090 static void start_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
1091                         struct avdtp_stream *stream, struct avdtp_error *err,
1092                         void *user_data)
1093 {
1094         struct a2dp_sep *a2dp_sep = user_data;
1095         struct a2dp_setup *setup;
1096
1097         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1098                 DBG("Sink %p: Start_Cfm", sep);
1099         else
1100                 DBG("Source %p: Start_Cfm", sep);
1101
1102         a2dp_sep->starting = FALSE;
1103
1104         setup = find_setup_by_session(session);
1105         if (!setup)
1106                 return;
1107
1108         if (err) {
1109                 setup->stream = NULL;
1110                 setup->err = err;
1111         }
1112
1113         finalize_resume(setup);
1114 }
1115
1116 static gboolean suspend_ind(struct avdtp *session, struct avdtp_local_sep *sep,
1117                                 struct avdtp_stream *stream, uint8_t *err,
1118                                 void *user_data)
1119 {
1120         struct a2dp_sep *a2dp_sep = user_data;
1121         struct a2dp_setup *setup;
1122         gboolean start;
1123         int start_err;
1124
1125         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1126                 DBG("Sink %p: Suspend_Ind", sep);
1127         else
1128                 DBG("Source %p: Suspend_Ind", sep);
1129
1130 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1131         a2dp_sep->remote_suspended = TRUE;
1132 #endif
1133
1134         if (a2dp_sep->suspend_timer) {
1135                 g_source_remove(a2dp_sep->suspend_timer);
1136                 a2dp_sep->suspend_timer = 0;
1137                 avdtp_unref(a2dp_sep->session);
1138                 a2dp_sep->session = NULL;
1139         }
1140
1141         if (!a2dp_sep->suspending)
1142                 return TRUE;
1143
1144         a2dp_sep->suspending = FALSE;
1145
1146         setup = find_setup_by_session(session);
1147         if (!setup)
1148                 return TRUE;
1149
1150         start = setup->start;
1151         setup->start = FALSE;
1152
1153         finalize_suspend(setup);
1154
1155         if (!start)
1156                 return TRUE;
1157
1158         start_err = avdtp_start(session, a2dp_sep->stream);
1159         if (start_err < 0 && start_err != -EINPROGRESS) {
1160                 error("avdtp_start: %s (%d)", strerror(-start_err),
1161                                                                 -start_err);
1162                 finalize_setup_errno(setup, start_err, finalize_resume, NULL);
1163         }
1164
1165         return TRUE;
1166 }
1167
1168 static void suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
1169                         struct avdtp_stream *stream, struct avdtp_error *err,
1170                         void *user_data)
1171 {
1172         struct a2dp_sep *a2dp_sep = user_data;
1173         struct a2dp_setup *setup;
1174         gboolean start;
1175         int start_err;
1176
1177         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1178                 DBG("Sink %p: Suspend_Cfm", sep);
1179         else
1180                 DBG("Source %p: Suspend_Cfm", sep);
1181
1182         a2dp_sep->suspending = FALSE;
1183
1184         setup = find_setup_by_session(session);
1185         if (!setup)
1186                 return;
1187
1188         start = setup->start;
1189         setup->start = FALSE;
1190
1191         if (err) {
1192                 setup->stream = NULL;
1193                 setup->err = err;
1194         }
1195
1196         finalize_suspend(setup);
1197
1198         if (!start)
1199                 return;
1200
1201         if (err) {
1202                 finalize_resume(setup);
1203                 return;
1204         }
1205
1206         start_err = avdtp_start(session, a2dp_sep->stream);
1207         if (start_err < 0 && start_err != -EINPROGRESS) {
1208                 error("avdtp_start: %s (%d)", strerror(-start_err), -start_err);
1209                 finalize_setup_errno(setup, start_err, finalize_suspend, NULL);
1210         }
1211 }
1212
1213 static gboolean close_ind(struct avdtp *session, struct avdtp_local_sep *sep,
1214                                 struct avdtp_stream *stream, uint8_t *err,
1215                                 void *user_data)
1216 {
1217         struct a2dp_sep *a2dp_sep = user_data;
1218         struct a2dp_setup *setup;
1219
1220         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1221                 DBG("Sink %p: Close_Ind", sep);
1222         else
1223                 DBG("Source %p: Close_Ind", sep);
1224
1225         setup = find_setup_by_session(session);
1226         if (!setup)
1227                 return TRUE;
1228
1229         finalize_setup_errno(setup, -ECONNRESET, finalize_suspend,
1230                                                         finalize_resume, NULL);
1231
1232         return TRUE;
1233 }
1234
1235 static struct a2dp_remote_sep *find_remote_sep(struct a2dp_channel *chan,
1236                                                 struct a2dp_sep *sep)
1237 {
1238         struct avdtp_remote_sep *rsep;
1239
1240         rsep = avdtp_find_remote_sep(chan->session, sep->lsep);
1241
1242         return queue_find(chan->seps, match_remote_sep, rsep);
1243 }
1244
1245 static gboolean a2dp_reconfigure(gpointer data)
1246 {
1247         struct a2dp_setup *setup = data;
1248         struct a2dp_sep *sep = setup->sep;
1249         int posix_err;
1250         struct avdtp_media_codec_capability *rsep_codec;
1251         struct avdtp_service_capability *cap;
1252
1253         if (!sep->lsep) {
1254                 error("no valid local SEP");
1255                 posix_err = -EINVAL;
1256                 goto failed;
1257         }
1258
1259         if (setup->rsep) {
1260                 cap = avdtp_get_codec(setup->rsep->sep);
1261                 rsep_codec = (struct avdtp_media_codec_capability *) cap->data;
1262         }
1263
1264         if (!setup->rsep || sep->codec != rsep_codec->media_codec_type)
1265                 setup->rsep = find_remote_sep(setup->chan, sep);
1266
1267         if (!setup->rsep) {
1268                 error("unable to find remote SEP");
1269                 posix_err = -EINVAL;
1270                 goto failed;
1271         }
1272
1273         posix_err = avdtp_set_configuration(setup->session, setup->rsep->sep,
1274                                                 sep->lsep,
1275                                                 setup->caps,
1276                                                 &setup->stream);
1277         if (posix_err < 0) {
1278                 error("avdtp_set_configuration: %s", strerror(-posix_err));
1279                 goto failed;
1280         }
1281
1282         return FALSE;
1283
1284 failed:
1285         finalize_setup_errno(setup, posix_err, finalize_config, NULL);
1286         return FALSE;
1287 }
1288
1289 static struct a2dp_remote_sep *get_remote_sep(struct a2dp_channel *chan,
1290                                                 struct avdtp_stream *stream)
1291 {
1292         struct avdtp_remote_sep *rsep;
1293
1294         rsep = avdtp_stream_get_remote_sep(stream);
1295
1296         return queue_find(chan->seps, match_remote_sep, rsep);
1297 }
1298
1299 static void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
1300                         struct avdtp_stream *stream, struct avdtp_error *err,
1301                         void *user_data)
1302 {
1303         struct a2dp_sep *a2dp_sep = user_data;
1304         struct a2dp_setup *setup;
1305
1306         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1307                 DBG("Sink %p: Close_Cfm", sep);
1308         else
1309                 DBG("Source %p: Close_Cfm", sep);
1310
1311         setup = find_setup_by_session(session);
1312         if (!setup)
1313                 return;
1314
1315         if (err) {
1316                 setup->stream = NULL;
1317                 setup->err = err;
1318                 finalize_config(setup);
1319                 return;
1320         }
1321
1322         if (!setup->rsep)
1323                 setup->rsep = get_remote_sep(setup->chan, stream);
1324
1325         if (setup->reconfigure)
1326                 g_timeout_add(RECONFIGURE_TIMEOUT, a2dp_reconfigure, setup);
1327 }
1328
1329 static void abort_ind(struct avdtp *session, struct avdtp_local_sep *sep,
1330                                 struct avdtp_stream *stream, uint8_t *err,
1331                                 void *user_data)
1332 {
1333         struct a2dp_sep *a2dp_sep = user_data;
1334         struct a2dp_setup *setup;
1335
1336         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1337                 DBG("Sink %p: Abort_Ind", sep);
1338         else
1339                 DBG("Source %p: Abort_Ind", sep);
1340
1341         a2dp_sep->stream = NULL;
1342
1343         setup = find_setup_by_session(session);
1344         if (!setup)
1345                 return;
1346
1347         finalize_setup_errno(setup, -ECONNRESET, finalize_suspend,
1348                                                         finalize_resume,
1349                                                         finalize_config, NULL);
1350
1351         return;
1352 }
1353
1354 static void abort_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
1355                         struct avdtp_stream *stream, struct avdtp_error *err,
1356                         void *user_data)
1357 {
1358         struct a2dp_sep *a2dp_sep = user_data;
1359         struct a2dp_setup *setup;
1360
1361         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1362                 DBG("Sink %p: Abort_Cfm", sep);
1363         else
1364                 DBG("Source %p: Abort_Cfm", sep);
1365
1366         setup = find_setup_by_session(session);
1367         if (!setup)
1368                 return;
1369
1370         if (setup->reconfigure) {
1371                 g_timeout_add(RECONFIGURE_TIMEOUT, a2dp_reconfigure, setup);
1372                 return;
1373         }
1374
1375         setup_unref(setup);
1376 }
1377
1378 static gboolean reconf_ind(struct avdtp *session, struct avdtp_local_sep *sep,
1379                                 uint8_t *err, void *user_data)
1380 {
1381         struct a2dp_sep *a2dp_sep = user_data;
1382
1383         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1384                 DBG("Sink %p: ReConfigure_Ind", sep);
1385         else
1386                 DBG("Source %p: ReConfigure_Ind", sep);
1387
1388         return TRUE;
1389 }
1390
1391 static gboolean endpoint_delayreport_ind(struct avdtp *session,
1392                                                 struct avdtp_local_sep *sep,
1393                                                 uint8_t rseid, uint16_t delay,
1394                                                 uint8_t *err, void *user_data)
1395 {
1396         struct a2dp_sep *a2dp_sep = user_data;
1397
1398         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1399                 DBG("Sink %p: DelayReport_Ind", sep);
1400         else
1401                 DBG("Source %p: DelayReport_Ind", sep);
1402
1403         if (a2dp_sep->endpoint == NULL ||
1404                                 a2dp_sep->endpoint->set_delay == NULL)
1405                 return FALSE;
1406
1407         a2dp_sep->endpoint->set_delay(a2dp_sep, delay, a2dp_sep->user_data);
1408
1409         return TRUE;
1410 }
1411
1412 static void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
1413                         struct avdtp_stream *stream, struct avdtp_error *err,
1414                         void *user_data)
1415 {
1416         struct a2dp_sep *a2dp_sep = user_data;
1417         struct a2dp_setup *setup;
1418
1419         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1420                 DBG("Sink %p: ReConfigure_Cfm", sep);
1421         else
1422                 DBG("Source %p: ReConfigure_Cfm", sep);
1423
1424         setup = find_setup_by_session(session);
1425         if (!setup)
1426                 return;
1427
1428         if (err) {
1429                 setup->stream = NULL;
1430                 setup->err = err;
1431         }
1432
1433         finalize_config(setup);
1434 }
1435
1436 static void delay_report_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
1437                                 struct avdtp_stream *stream,
1438                                 struct avdtp_error *err, void *user_data)
1439 {
1440         struct a2dp_sep *a2dp_sep = user_data;
1441
1442         if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK)
1443                 DBG("Sink %p: DelayReport_Cfm", sep);
1444         else
1445                 DBG("Source %p: DelayReport_Cfm", sep);
1446 }
1447
1448 static struct avdtp_sep_cfm cfm = {
1449         .set_configuration      = setconf_cfm,
1450         .get_configuration      = getconf_cfm,
1451         .open                   = open_cfm,
1452         .start                  = start_cfm,
1453         .suspend                = suspend_cfm,
1454         .close                  = close_cfm,
1455         .abort                  = abort_cfm,
1456         .reconfigure            = reconf_cfm,
1457         .delay_report           = delay_report_cfm,
1458 };
1459
1460 static struct avdtp_sep_ind endpoint_ind = {
1461         .match_codec            = endpoint_match_codec_ind,
1462         .get_capability         = endpoint_getcap_ind,
1463         .set_configuration      = endpoint_setconf_ind,
1464         .get_configuration      = getconf_ind,
1465         .open                   = open_ind,
1466         .start                  = start_ind,
1467         .suspend                = suspend_ind,
1468         .close                  = close_ind,
1469         .abort                  = abort_ind,
1470         .reconfigure            = reconf_ind,
1471         .delayreport            = endpoint_delayreport_ind,
1472 };
1473
1474 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1475 static sdp_record_t *a2dp_record(uint8_t type, gboolean sink_enabled)
1476 #else
1477 static sdp_record_t *a2dp_record(uint8_t type)
1478 #endif
1479 {
1480         sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1481         uuid_t root_uuid, l2cap_uuid, avdtp_uuid, a2dp_uuid;
1482         sdp_profile_desc_t profile[1];
1483         sdp_list_t *aproto, *proto[2];
1484         sdp_record_t *record;
1485         sdp_data_t *psm, *version, *features;
1486         uint16_t lp = AVDTP_UUID;
1487 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1488         uint16_t a2dp_ver, avdtp_ver, feat;
1489         if (sink_enabled) {
1490                 DBG("A2DP record for Sink role");
1491                 a2dp_ver = 0x0102;
1492                 avdtp_ver = 0x0103;
1493                 feat = 0x0002;
1494         } else {
1495                 DBG("A2DP record for Source role");
1496                 a2dp_ver = 0x0102;
1497                 avdtp_ver = 0x0103;
1498                 feat = 0x0001;
1499         }
1500 #else
1501         uint16_t a2dp_ver = 0x0103, avdtp_ver = 0x0103, feat = 0x000f;
1502 #endif
1503
1504         record = sdp_record_alloc();
1505         if (!record)
1506                 return NULL;
1507
1508         sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1509         root = sdp_list_append(0, &root_uuid);
1510         sdp_set_browse_groups(record, root);
1511
1512         if (type == AVDTP_SEP_TYPE_SOURCE)
1513                 sdp_uuid16_create(&a2dp_uuid, AUDIO_SOURCE_SVCLASS_ID);
1514         else
1515                 sdp_uuid16_create(&a2dp_uuid, AUDIO_SINK_SVCLASS_ID);
1516         svclass_id = sdp_list_append(0, &a2dp_uuid);
1517         sdp_set_service_classes(record, svclass_id);
1518
1519         sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
1520         profile[0].version = a2dp_ver;
1521         pfseq = sdp_list_append(0, &profile[0]);
1522         sdp_set_profile_descs(record, pfseq);
1523
1524         sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1525         proto[0] = sdp_list_append(0, &l2cap_uuid);
1526         psm = sdp_data_alloc(SDP_UINT16, &lp);
1527         proto[0] = sdp_list_append(proto[0], psm);
1528         apseq = sdp_list_append(0, proto[0]);
1529
1530         sdp_uuid16_create(&avdtp_uuid, AVDTP_UUID);
1531         proto[1] = sdp_list_append(0, &avdtp_uuid);
1532         version = sdp_data_alloc(SDP_UINT16, &avdtp_ver);
1533         proto[1] = sdp_list_append(proto[1], version);
1534         apseq = sdp_list_append(apseq, proto[1]);
1535
1536         aproto = sdp_list_append(0, apseq);
1537         sdp_set_access_protos(record, aproto);
1538
1539         features = sdp_data_alloc(SDP_UINT16, &feat);
1540         sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
1541
1542         if (type == AVDTP_SEP_TYPE_SOURCE)
1543                 sdp_set_info_attr(record, "Audio Source", 0, 0);
1544         else
1545                 sdp_set_info_attr(record, "Audio Sink", 0, 0);
1546
1547         free(psm);
1548         free(version);
1549         sdp_list_free(proto[0], 0);
1550         sdp_list_free(proto[1], 0);
1551         sdp_list_free(apseq, 0);
1552         sdp_list_free(pfseq, 0);
1553         sdp_list_free(aproto, 0);
1554         sdp_list_free(root, 0);
1555         sdp_list_free(svclass_id, 0);
1556
1557         return record;
1558 }
1559
1560 static struct a2dp_server *find_server(GSList *list, struct btd_adapter *a)
1561 {
1562
1563         for (; list; list = list->next) {
1564                 struct a2dp_server *server = list->data;
1565
1566                 if (server->adapter == a)
1567                         return server;
1568         }
1569
1570         return NULL;
1571 }
1572
1573 static void remote_sep_free(void *data)
1574 {
1575         struct a2dp_remote_sep *sep = data;
1576
1577         free(sep->path);
1578         free(sep);
1579 }
1580
1581 static void remove_remote_sep(void *data)
1582 {
1583         struct a2dp_remote_sep *sep = data;
1584
1585         if (!sep->path) {
1586                 remote_sep_free(sep);
1587                 return;
1588         }
1589
1590         g_dbus_unregister_interface(btd_get_dbus_connection(), sep->path,
1591                                                 MEDIA_ENDPOINT_INTERFACE);
1592 }
1593
1594 static void channel_free(void *data)
1595 {
1596         struct a2dp_channel *chan = data;
1597
1598         if (chan->auth_id > 0)
1599                 btd_cancel_authorization(chan->auth_id);
1600
1601         if (chan->io_id > 0)
1602                 g_source_remove(chan->io_id);
1603
1604         if (chan->io) {
1605                 g_io_channel_shutdown(chan->io, TRUE, NULL);
1606                 g_io_channel_unref(chan->io);
1607         }
1608
1609         avdtp_remove_state_cb(chan->state_id);
1610
1611         queue_destroy(chan->seps, remove_remote_sep);
1612         free(chan->last_used);
1613         g_free(chan);
1614 }
1615
1616 static void channel_remove(struct a2dp_channel *chan)
1617 {
1618         struct a2dp_server *server = chan->server;
1619
1620         DBG("chan %p", chan);
1621
1622         queue_remove(server->channels, chan);
1623
1624         channel_free(chan);
1625 }
1626
1627 static gboolean disconnect_cb(GIOChannel *io, GIOCondition cond, gpointer data)
1628 {
1629         struct a2dp_channel *chan = data;
1630
1631         DBG("chan %p", chan);
1632
1633         chan->io_id = 0;
1634
1635         channel_remove(chan);
1636
1637         return FALSE;
1638 }
1639
1640 static void caps_add_codec(GSList **l, uint8_t codec, uint8_t *caps,
1641                                                         size_t size)
1642 {
1643         struct avdtp_service_capability *media_transport, *media_codec;
1644         struct avdtp_media_codec_capability *cap;
1645
1646         media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
1647                                                 NULL, 0);
1648
1649         *l = g_slist_append(*l, media_transport);
1650
1651         cap = g_malloc0(sizeof(*cap) + size);
1652         cap->media_type = AVDTP_MEDIA_TYPE_AUDIO;
1653         cap->media_codec_type = codec;
1654         memcpy(cap->data, caps, size);
1655
1656         media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, cap,
1657                                                 sizeof(*cap) + size);
1658
1659         *l = g_slist_append(*l, media_codec);
1660         g_free(cap);
1661 }
1662
1663 struct client {
1664         const char *sender;
1665         const char *path;
1666 };
1667
1668 static int match_client(const void *data, const void *user_data)
1669 {
1670         struct a2dp_sep *sep = (void *) data;
1671         const struct a2dp_endpoint *endpoint = sep->endpoint;
1672         const struct client *client = user_data;
1673
1674         if (strcmp(client->sender, endpoint->get_name(sep, sep->user_data)))
1675                 return -1;
1676
1677         return strcmp(client->path, endpoint->get_path(sep, sep->user_data));
1678 }
1679
1680 static struct a2dp_sep *find_sep(struct a2dp_server *server, uint8_t type,
1681                                         const char *sender, const char *path)
1682 {
1683         GSList *l;
1684         struct client client = { sender, path };
1685
1686         l = type == AVDTP_SEP_TYPE_SINK ? server->sources : server->sinks;
1687
1688         l = g_slist_find_custom(l, &client, match_client);
1689         if (l)
1690                 return l->data;
1691
1692         return NULL;
1693 }
1694
1695 static int parse_properties(DBusMessageIter *props, uint8_t **caps, int *size)
1696 {
1697         while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
1698                 const char *key;
1699                 DBusMessageIter value, entry;
1700                 int var;
1701
1702                 dbus_message_iter_recurse(props, &entry);
1703                 dbus_message_iter_get_basic(&entry, &key);
1704
1705                 dbus_message_iter_next(&entry);
1706                 dbus_message_iter_recurse(&entry, &value);
1707
1708                 var = dbus_message_iter_get_arg_type(&value);
1709                 if (strcasecmp(key, "Capabilities") == 0) {
1710                         DBusMessageIter array;
1711
1712                         if (var != DBUS_TYPE_ARRAY)
1713                                 return -EINVAL;
1714
1715                         dbus_message_iter_recurse(&value, &array);
1716                         dbus_message_iter_get_fixed_array(&array, caps, size);
1717                         return 0;
1718                 }
1719
1720                 dbus_message_iter_next(props);
1721         }
1722
1723         return -EINVAL;
1724 }
1725
1726 static void reconfig_cb(struct avdtp *session, struct a2dp_sep *sep,
1727                         struct avdtp_stream *stream, int err, void *user_data)
1728 {
1729         DBusMessage *msg = user_data;
1730
1731         if (err)
1732                 g_dbus_send_message(btd_get_dbus_connection(),
1733                                         btd_error_failed(msg, strerror(-err)));
1734         else
1735                 g_dbus_send_reply(btd_get_dbus_connection(), msg,
1736                                         DBUS_TYPE_INVALID);
1737
1738         dbus_message_unref(msg);
1739 }
1740
1741 static int a2dp_reconfig(struct a2dp_channel *chan, const char *sender,
1742                         struct a2dp_sep *lsep, struct a2dp_remote_sep *rsep,
1743                         uint8_t *caps, int size, void *user_data)
1744 {
1745         struct a2dp_setup *setup;
1746         struct a2dp_setup_cb *cb_data;
1747         GSList *l;
1748         int err;
1749
1750         setup = a2dp_setup_get(chan->session);
1751         if (!setup)
1752                 return -ENOMEM;
1753
1754         cb_data = setup_cb_new(setup);
1755         cb_data->config_cb = reconfig_cb;
1756         cb_data->user_data = user_data;
1757
1758         setup->sep = lsep;
1759         setup->rsep = rsep;
1760
1761         g_slist_free_full(setup->caps, g_free);
1762         setup->caps = NULL;
1763
1764         caps_add_codec(&setup->caps, setup->sep->codec, caps, size);
1765
1766         l = avdtp_get_type(rsep->sep) == AVDTP_SEP_TYPE_SINK ?
1767                                         chan->server->sources :
1768                                         chan->server->sinks;
1769
1770         /* Check for existing stream and close it */
1771         for (; l; l = g_slist_next(l)) {
1772                 struct a2dp_sep *tmp = l->data;
1773
1774                 /* Attempt to reconfigure if a stream already exists */
1775                 if (tmp->stream) {
1776                         /* Only allow switching sep from the same sender */
1777                         if (strcmp(sender, tmp->endpoint->get_name(tmp,
1778                                                         tmp->user_data)))
1779                                 return -EPERM;
1780
1781                         /* Check if stream is for the channel */
1782                         if (!avdtp_has_stream(chan->session, tmp->stream))
1783                                 continue;
1784
1785                         err = avdtp_close(chan->session, tmp->stream, FALSE);
1786                         if (err < 0) {
1787                                 err = avdtp_abort(chan->session, tmp->stream);
1788                                 if (err < 0) {
1789                                         error("avdtp_abort: %s",
1790                                                         strerror(-err));
1791                                         goto fail;
1792                                 }
1793                         }
1794
1795                         setup->reconfigure = TRUE;
1796
1797                         return 0;
1798                 }
1799         }
1800
1801         err = avdtp_set_configuration(setup->session, setup->rsep->sep,
1802                                                 lsep->lsep,
1803                                                 setup->caps,
1804                                                 &setup->stream);
1805         if (err < 0) {
1806                 error("avdtp_set_configuration: %s", strerror(-err));
1807                 goto fail;
1808         }
1809
1810         return 0;
1811
1812 fail:
1813         setup_cb_free(cb_data);
1814         return err;
1815 }
1816
1817 static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
1818                                                                 void *data)
1819 {
1820         struct a2dp_remote_sep *rsep = data;
1821         struct a2dp_channel *chan = rsep->chan;
1822         struct a2dp_sep *lsep = NULL;
1823         struct avdtp_service_capability *service;
1824         struct avdtp_media_codec_capability *codec;
1825         DBusMessageIter args, props;
1826         const char *sender, *path;
1827         uint8_t *caps;
1828         int err, size = 0;
1829
1830         sender = dbus_message_get_sender(msg);
1831
1832         dbus_message_iter_init(msg, &args);
1833
1834         dbus_message_iter_get_basic(&args, &path);
1835         dbus_message_iter_next(&args);
1836
1837         lsep = find_sep(chan->server, avdtp_get_type(rsep->sep), sender, path);
1838         if (!lsep)
1839                 return btd_error_invalid_args(msg);
1840
1841         service = avdtp_get_codec(rsep->sep);
1842         codec = (struct avdtp_media_codec_capability *) service->data;
1843
1844         /* Check if codec really matches */
1845         if (!endpoint_match_codec_ind(chan->session, codec, lsep))
1846                 return btd_error_invalid_args(msg);
1847
1848         dbus_message_iter_recurse(&args, &props);
1849         if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY)
1850                 return btd_error_invalid_args(msg);
1851
1852         if (parse_properties(&props, &caps, &size) < 0)
1853                 return btd_error_invalid_args(msg);
1854
1855         err = a2dp_reconfig(chan, sender, lsep, rsep, caps, size,
1856                                         dbus_message_ref(msg));
1857         if (err < 0) {
1858                 dbus_message_unref(msg);
1859                 return btd_error_failed(msg, strerror(-err));
1860         }
1861
1862         return NULL;
1863 }
1864
1865 static const GDBusMethodTable sep_methods[] = {
1866         { GDBUS_ASYNC_METHOD("SetConfiguration",
1867                                         GDBUS_ARGS({ "endpoint", "o" },
1868                                                 { "properties", "a{sv}" } ),
1869                                         NULL, set_configuration) },
1870         { },
1871 };
1872
1873 static gboolean get_uuid(const GDBusPropertyTable *property,
1874                                         DBusMessageIter *iter, void *data)
1875 {
1876         struct a2dp_remote_sep *sep = data;
1877         const char *uuid;
1878
1879         switch (avdtp_get_type(sep->sep)) {
1880         case AVDTP_SEP_TYPE_SOURCE:
1881                 uuid = A2DP_SOURCE_UUID;
1882                 break;
1883         case AVDTP_SEP_TYPE_SINK:
1884                 uuid = A2DP_SINK_UUID;
1885                 break;
1886         default:
1887                 uuid = "";
1888         }
1889
1890         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
1891
1892         return TRUE;
1893 }
1894
1895 static gboolean get_codec(const GDBusPropertyTable *property,
1896                                         DBusMessageIter *iter, void *data)
1897 {
1898         struct a2dp_remote_sep *sep = data;
1899         struct avdtp_service_capability *cap = avdtp_get_codec(sep->sep);
1900         struct avdtp_media_codec_capability *codec = (void *) cap->data;
1901
1902         dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
1903                                                 &codec->media_codec_type);
1904
1905         return TRUE;
1906 }
1907
1908 static gboolean get_capabilities(const GDBusPropertyTable *property,
1909                                         DBusMessageIter *iter, void *data)
1910 {
1911         struct a2dp_remote_sep *sep = data;
1912         struct avdtp_service_capability *service = avdtp_get_codec(sep->sep);
1913         struct avdtp_media_codec_capability *codec = (void *) service->data;
1914         uint8_t *caps = codec->data;
1915         DBusMessageIter array;
1916
1917         dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
1918                                         DBUS_TYPE_BYTE_AS_STRING, &array);
1919
1920         dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE, &caps,
1921                                         service->length - sizeof(*codec));
1922
1923         dbus_message_iter_close_container(iter, &array);
1924
1925         return TRUE;
1926 }
1927
1928 static gboolean get_device(const GDBusPropertyTable *property,
1929                                         DBusMessageIter *iter, void *data)
1930 {
1931         struct a2dp_remote_sep *sep = data;
1932         const char *path;
1933
1934         path = device_get_path(sep->chan->device);
1935
1936         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
1937
1938         return TRUE;
1939 }
1940
1941 static gboolean get_delay_reporting(const GDBusPropertyTable *property,
1942                                         DBusMessageIter *iter, void *data)
1943 {
1944         struct a2dp_remote_sep *sep = data;
1945         dbus_bool_t delay_report;
1946
1947         delay_report = avdtp_get_delay_reporting(sep->sep);
1948
1949         dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &delay_report);
1950
1951         return TRUE;
1952 }
1953
1954 static const GDBusPropertyTable sep_properties[] = {
1955         { "UUID", "s", get_uuid, NULL, NULL },
1956         { "Codec", "y", get_codec, NULL, NULL },
1957         { "Capabilities", "ay", get_capabilities, NULL, NULL },
1958         { "Device", "o", get_device, NULL, NULL },
1959         { "DelayReporting", "b", get_delay_reporting, NULL, NULL },
1960         { }
1961 };
1962
1963 static void register_remote_sep(void *data, void *user_data)
1964 {
1965         struct avdtp_remote_sep *rsep = data;
1966         struct a2dp_channel *chan = user_data;
1967         struct a2dp_remote_sep *sep;
1968
1969         sep = queue_find(chan->seps, match_remote_sep, rsep);
1970         if (sep)
1971                 return;
1972
1973         sep = new0(struct a2dp_remote_sep, 1);
1974         sep->chan = chan;
1975         sep->sep = rsep;
1976
1977         if (asprintf(&sep->path, "%s/sep%d",
1978                                 device_get_path(chan->device),
1979                                 avdtp_get_seid(rsep)) < 0) {
1980                 error("Could not allocate path for remote sep %s/sep%d",
1981                                 device_get_path(chan->device),
1982                                 avdtp_get_seid(rsep));
1983                 sep->path = NULL;
1984                 goto done;
1985         }
1986
1987         if (g_dbus_register_interface(btd_get_dbus_connection(),
1988                                 sep->path, MEDIA_ENDPOINT_INTERFACE,
1989                                 sep_methods, NULL, sep_properties,
1990                                 sep, remote_sep_free) == FALSE) {
1991                 error("Could not register remote sep %s", sep->path);
1992                 free(sep->path);
1993                 sep->path = NULL;
1994                 goto done;
1995         }
1996
1997         DBG("Found remote SEP: %s", sep->path);
1998
1999 done:
2000         queue_push_tail(chan->seps, sep);
2001 }
2002
2003 static bool match_seid(const void *data, const void *user_data)
2004 {
2005         const struct a2dp_remote_sep *sep = data;
2006         const uint8_t *seid = user_data;
2007
2008         return avdtp_get_seid(sep->sep) == *seid;
2009 }
2010
2011 static int match_sep(const void *data, const void *user_data)
2012 {
2013         struct a2dp_sep *sep = (void *) data;
2014         const uint8_t *seid = user_data;
2015
2016         return *seid - avdtp_sep_get_seid(sep->lsep);
2017 }
2018
2019 static struct a2dp_sep *find_sep_by_seid(struct a2dp_server *server,
2020                                                         uint8_t seid)
2021 {
2022         GSList *l;
2023
2024         l = g_slist_find_custom(server->sources, &seid, match_sep);
2025         if (l)
2026                 return l->data;
2027
2028         l = g_slist_find_custom(server->sinks, &seid, match_sep);
2029         if (l)
2030                 return l->data;
2031
2032         return NULL;
2033 }
2034
2035 static void load_remote_sep(struct a2dp_channel *chan, GKeyFile *key_file,
2036                                                                 char **seids)
2037 {
2038         struct a2dp_sep *lsep;
2039         struct a2dp_remote_sep *sep;
2040         struct avdtp_remote_sep *rsep;
2041         uint8_t lseid, rseid;
2042         char *value;
2043
2044         if (!seids)
2045                 return;
2046
2047         for (; *seids; seids++) {
2048                 uint8_t type;
2049                 uint8_t codec;
2050                 uint8_t delay_reporting;
2051                 GSList *l = NULL;
2052                 char caps[256];
2053                 uint8_t data[128];
2054                 int i, size;
2055
2056                 if (sscanf(*seids, "%02hhx", &rseid) != 1)
2057                         continue;
2058
2059                 value = g_key_file_get_string(key_file, "Endpoints", *seids,
2060                                                                 NULL);
2061                 if (!value)
2062                         continue;
2063
2064                 /* Try loading with delay_reporting first */
2065                 if (sscanf(value, "%02hhx:%02hhx:%02hhx:%s", &type, &codec,
2066                                         &delay_reporting, caps) != 4) {
2067                         /* Try old format */
2068                         if (sscanf(value, "%02hhx:%02hhx:%s", &type, &codec,
2069                                                                 caps) != 3) {
2070                                 warn("Unable to load Endpoint: seid %u", rseid);
2071                                 g_free(value);
2072                                 continue;
2073                         }
2074                         delay_reporting = false;
2075                 }
2076
2077                 for (i = 0, size = strlen(caps); i < size; i += 2) {
2078                         uint8_t *tmp = data + i / 2;
2079
2080                         if (sscanf(caps + i, "%02hhx", tmp) != 1) {
2081                                 warn("Unable to load Endpoint: seid %u", rseid);
2082                                 break;
2083                         }
2084                 }
2085
2086                 g_free(value);
2087
2088                 if (i != size)
2089                         continue;
2090
2091                 caps_add_codec(&l, codec, data, size / 2);
2092
2093                 rsep = avdtp_register_remote_sep(chan->session, rseid, type, l,
2094                                                         delay_reporting);
2095                 if (!rsep) {
2096                         warn("Unable to register Endpoint: seid %u", rseid);
2097                         continue;
2098                 }
2099
2100                 register_remote_sep(rsep, chan);
2101         }
2102
2103         value = g_key_file_get_string(key_file, "Endpoints", "LastUsed", NULL);
2104         if (!value)
2105                 return;
2106
2107         if (sscanf(value, "%02hhx:%02hhx", &lseid, &rseid) != 2) {
2108                 warn("Unable to load LastUsed");
2109                 g_free(value);
2110                 return;
2111         }
2112
2113         g_free(value);
2114
2115         lsep = find_sep_by_seid(chan->server, lseid);
2116         if (!lsep) {
2117                 warn("Unable to load LastUsed: lseid %u not found", lseid);
2118                 return;
2119         }
2120
2121         sep = queue_find(chan->seps, match_seid, &rseid);
2122         if (!sep) {
2123                 warn("Unable to load LastUsed: rseid %u not found", rseid);
2124                 return;
2125         }
2126
2127         add_last_used(chan, lsep, sep);
2128 }
2129
2130 static void load_remote_seps(struct a2dp_channel *chan)
2131 {
2132         struct btd_device *device = chan->device;
2133         char filename[PATH_MAX];
2134         char dst_addr[18];
2135         char **keys;
2136         GKeyFile *key_file;
2137
2138         ba2str(device_get_address(device), dst_addr);
2139
2140         snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
2141                         btd_adapter_get_storage_dir(device_get_adapter(device)),
2142                         dst_addr);
2143         key_file = g_key_file_new();
2144         g_key_file_load_from_file(key_file, filename, 0, NULL);
2145         keys = g_key_file_get_keys(key_file, "Endpoints", NULL, NULL);
2146
2147         load_remote_sep(chan, key_file, keys);
2148
2149         g_strfreev(keys);
2150         g_key_file_free(key_file);
2151 }
2152
2153 static void avdtp_state_cb(struct btd_device *dev, struct avdtp *session,
2154                                         avdtp_session_state_t old_state,
2155                                         avdtp_session_state_t new_state,
2156                                         void *user_data)
2157 {
2158         struct a2dp_channel *chan = user_data;
2159
2160         switch (new_state) {
2161         case AVDTP_SESSION_STATE_DISCONNECTED:
2162                 if (chan->session == session)
2163                         channel_remove(chan);
2164                 break;
2165         case AVDTP_SESSION_STATE_CONNECTING:
2166                 break;
2167         case AVDTP_SESSION_STATE_CONNECTED:
2168                 if (!chan->session)
2169                         chan->session = session;
2170                 load_remote_seps(chan);
2171                 break;
2172         }
2173 }
2174
2175 static struct a2dp_channel *channel_new(struct a2dp_server *server,
2176                                         struct btd_device *device,
2177                                         GIOChannel *io)
2178 {
2179         struct a2dp_channel *chan;
2180
2181         chan = g_new0(struct a2dp_channel, 1);
2182         chan->server = server;
2183         chan->device = device;
2184         chan->seps = queue_new();
2185         chan->state_id = avdtp_add_state_cb(device, avdtp_state_cb, chan);
2186
2187         if (!queue_push_tail(server->channels, chan)) {
2188                 g_free(chan);
2189                 return NULL;
2190         }
2191
2192         if (!io)
2193                 return chan;
2194
2195         chan->io = g_io_channel_ref(io);
2196         chan->io_id = g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
2197                                         (GIOFunc) disconnect_cb, chan);
2198
2199         return chan;
2200 }
2201
2202 static bool match_by_device(const void *data, const void *user_data)
2203 {
2204         const struct a2dp_channel *chan = data;
2205         const struct btd_device *device = user_data;
2206
2207         return chan->device == device;
2208 }
2209
2210 struct avdtp *a2dp_avdtp_get(struct btd_device *device)
2211 {
2212         struct a2dp_server *server;
2213         struct a2dp_channel *chan;
2214         const struct queue_entry *entry;
2215
2216         server = find_server(servers, device_get_adapter(device));
2217         if (server == NULL)
2218                 return NULL;
2219
2220         chan = queue_find(server->channels, match_by_device, device);
2221         if (!chan) {
2222                 chan = channel_new(server, device, NULL);
2223                 if (!chan)
2224                         return NULL;
2225         }
2226
2227 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2228         if (chan->auth_id) {
2229                 DBG("auth is already going...");
2230                 return NULL;
2231         }
2232 #endif
2233
2234         if (chan->session)
2235                 return avdtp_ref(chan->session);
2236
2237         /* Check if there is any SEP available */
2238         for (entry = queue_get_entries(server->seps); entry;
2239                                         entry = entry->next) {
2240                 struct avdtp_local_sep *sep = entry->data;
2241
2242                 if (avdtp_sep_get_state(sep) == AVDTP_STATE_IDLE)
2243                         goto found;
2244         }
2245
2246         DBG("Unable to find any available SEP");
2247
2248         return NULL;
2249
2250 found:
2251         chan->session = avdtp_new(chan->io, device, server->seps);
2252         if (!chan->session) {
2253                 channel_remove(chan);
2254                 return NULL;
2255         }
2256
2257         return avdtp_ref(chan->session);
2258 }
2259
2260 static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
2261 {
2262         struct a2dp_channel *chan = user_data;
2263
2264         if (err) {
2265                 error("%s", err->message);
2266                 goto fail;
2267         }
2268
2269         if (!chan->session) {
2270                 chan->session = avdtp_new(chan->io, chan->device,
2271                                                         chan->server->seps);
2272                 if (!chan->session) {
2273                         error("Unable to create AVDTP session");
2274                         goto fail;
2275                 }
2276         }
2277
2278         g_io_channel_unref(chan->io);
2279         chan->io = NULL;
2280
2281         g_source_remove(chan->io_id);
2282         chan->io_id = 0;
2283
2284         return;
2285
2286 fail:
2287         channel_remove(chan);
2288 }
2289
2290 static void auth_cb(DBusError *derr, void *user_data)
2291 {
2292         struct a2dp_channel *chan = user_data;
2293         GError *err = NULL;
2294
2295         chan->auth_id = 0;
2296
2297         if (derr && dbus_error_is_set(derr)) {
2298                 error("Access denied: %s", derr->message);
2299                 goto fail;
2300         }
2301
2302         if (!bt_io_accept(chan->io, connect_cb, chan, NULL, &err)) {
2303                 error("bt_io_accept: %s", err->message);
2304                 g_error_free(err);
2305                 goto fail;
2306         }
2307
2308         return;
2309
2310 fail:
2311         channel_remove(chan);
2312 }
2313
2314 static void transport_cb(GIOChannel *io, GError *err, gpointer user_data)
2315 {
2316         struct a2dp_setup *setup = user_data;
2317         uint16_t omtu, imtu;
2318
2319         if (!g_slist_find(setups, setup)) {
2320                 warn("bt_io_accept: setup %p no longer valid", setup);
2321                 g_io_channel_shutdown(io, TRUE, NULL);
2322                 return;
2323         }
2324
2325         if (err) {
2326                 error("%s", err->message);
2327                 goto drop;
2328         }
2329
2330         bt_io_get(io, &err, BT_IO_OPT_OMTU, &omtu, BT_IO_OPT_IMTU, &imtu,
2331                                                         BT_IO_OPT_INVALID);
2332         if (err) {
2333                 error("%s", err->message);
2334                 g_error_free(err);
2335                 goto drop;
2336         }
2337
2338         if (!avdtp_stream_set_transport(setup->stream,
2339                                         g_io_channel_unix_get_fd(io),
2340                                         imtu, omtu))
2341                 goto drop;
2342
2343         g_io_channel_set_close_on_unref(io, FALSE);
2344
2345         g_io_channel_unref(setup->io);
2346         setup->io = NULL;
2347
2348         setup_unref(setup);
2349
2350         return;
2351
2352 drop:
2353         setup_unref(setup);
2354         g_io_channel_shutdown(io, TRUE, NULL);
2355
2356 }
2357 static void confirm_cb(GIOChannel *io, gpointer data)
2358 {
2359         struct a2dp_server *server = data;
2360         struct a2dp_channel *chan;
2361         char address[18];
2362         bdaddr_t src, dst;
2363         GError *err = NULL;
2364         struct btd_device *device;
2365
2366         bt_io_get(io, &err,
2367                         BT_IO_OPT_SOURCE_BDADDR, &src,
2368                         BT_IO_OPT_DEST_BDADDR, &dst,
2369                         BT_IO_OPT_DEST, address,
2370                         BT_IO_OPT_INVALID);
2371         if (err) {
2372                 error("%s", err->message);
2373                 g_error_free(err);
2374                 goto drop;
2375         }
2376
2377         DBG("AVDTP: incoming connect from %s", address);
2378
2379         device = btd_adapter_find_device(adapter_find(&src), &dst,
2380                                                                 BDADDR_BREDR);
2381         if (!device)
2382                 goto drop;
2383
2384 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2385         if (device_is_profile_blocked(device, A2DP_SINK_UUID)) {
2386                 DBG("A2DP is restricted");
2387                 goto drop;
2388         }
2389 #endif
2390
2391         chan = queue_find(server->channels, match_by_device, device);
2392         if (chan) {
2393                 struct a2dp_setup *setup;
2394
2395                 setup = find_setup_by_session(chan->session);
2396                 if (!setup || !setup->stream)
2397                         goto drop;
2398
2399                 if (setup->io) {
2400                         error("transport channel already exists");
2401                         goto drop;
2402                 }
2403
2404                 if (!bt_io_accept(io, transport_cb, setup, NULL, &err)) {
2405                         error("bt_io_accept: %s", err->message);
2406                         g_error_free(err);
2407                         goto drop;
2408                 }
2409
2410                 /*
2411                  * Reference the channel so it can be shutdown properly
2412                  * stopping bt_io_accept from calling the callback with invalid
2413                  * setup pointer.
2414                  */
2415                 setup->io = g_io_channel_ref(io);
2416
2417                 return;
2418         }
2419
2420         chan = channel_new(server, device, io);
2421         if (!chan)
2422                 goto drop;
2423
2424         chan->auth_id = btd_request_authorization(&src, &dst,
2425                                                         ADVANCED_AUDIO_UUID,
2426                                                         auth_cb, chan);
2427         if (chan->auth_id == 0 && !chan->session)
2428                 channel_remove(chan);
2429
2430         return;
2431
2432 drop:
2433         g_io_channel_shutdown(io, TRUE, NULL);
2434 }
2435
2436 static bool a2dp_server_listen(struct a2dp_server *server)
2437 {
2438         GError *err = NULL;
2439         BtIOMode mode;
2440
2441         if (server->io)
2442                 return true;
2443
2444         if (main_opts.mps == MPS_OFF)
2445                 mode = BT_IO_MODE_BASIC;
2446         else
2447                 mode = BT_IO_MODE_STREAMING;
2448
2449 #if defined(TIZEN_FEATURE_BLUEZ_MODIFY)
2450         if (btd_adapter_get_a2dp_role(server->adapter) == BLUETOOTH_A2DP_SINK_ROLE) {
2451                 server->io = bt_io_listen(NULL, confirm_cb, server, NULL, &err,
2452                                 BT_IO_OPT_SOURCE_BDADDR,
2453                                 btd_adapter_get_address(server->adapter),
2454                                 BT_IO_OPT_PSM, AVDTP_PSM,
2455                                 BT_IO_OPT_MODE, mode,
2456                                 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
2457                                 BT_IO_OPT_IMTU, 895,
2458                                 BT_IO_OPT_MASTER, true,
2459                                 BT_IO_OPT_INVALID);
2460         } else {
2461                 server->io = bt_io_listen(NULL, confirm_cb, server, NULL, &err,
2462                                 BT_IO_OPT_SOURCE_BDADDR,
2463                                 btd_adapter_get_address(server->adapter),
2464                                 BT_IO_OPT_PSM, AVDTP_PSM,
2465                                 BT_IO_OPT_MODE, mode,
2466                                 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
2467                                 BT_IO_OPT_MASTER, true,
2468                                 BT_IO_OPT_INVALID);
2469         }
2470 #else
2471         server->io = bt_io_listen(NULL, confirm_cb, server, NULL, &err,
2472                                 BT_IO_OPT_SOURCE_BDADDR,
2473                                 btd_adapter_get_address(server->adapter),
2474                                 BT_IO_OPT_PSM, AVDTP_PSM,
2475                                 BT_IO_OPT_MODE, mode,
2476                                 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
2477                                 BT_IO_OPT_MASTER, true,
2478                                 BT_IO_OPT_INVALID);
2479 #endif
2480         if (server->io)
2481                 return true;
2482
2483         error("%s", err->message);
2484         g_error_free(err);
2485
2486         return false;
2487 }
2488
2489 static struct a2dp_server *a2dp_server_register(struct btd_adapter *adapter)
2490 {
2491         struct a2dp_server *server;
2492
2493         server = g_new0(struct a2dp_server, 1);
2494
2495         server->adapter = btd_adapter_ref(adapter);
2496         server->seps = queue_new();
2497         server->channels = queue_new();
2498
2499         servers = g_slist_append(servers, server);
2500
2501         return server;
2502 }
2503
2504 static void a2dp_unregister_sep(struct a2dp_sep *sep)
2505 {
2506         struct a2dp_server *server = sep->server;
2507
2508         if (sep->destroy) {
2509                 sep->destroy(sep->user_data);
2510                 sep->endpoint = NULL;
2511         }
2512
2513         avdtp_unregister_sep(server->seps, sep->lsep);
2514
2515         g_free(sep);
2516
2517         if (!queue_isempty(server->seps))
2518                 return;
2519
2520         if (server->io) {
2521                 g_io_channel_shutdown(server->io, TRUE, NULL);
2522                 g_io_channel_unref(server->io);
2523                 server->io = NULL;
2524         }
2525 }
2526
2527 static void a2dp_server_unregister(struct a2dp_server *server)
2528 {
2529         servers = g_slist_remove(servers, server);
2530         queue_destroy(server->channels, channel_free);
2531         queue_destroy(server->seps, NULL);
2532
2533         if (server->io) {
2534                 g_io_channel_shutdown(server->io, TRUE, NULL);
2535                 g_io_channel_unref(server->io);
2536         }
2537
2538         btd_adapter_unref(server->adapter);
2539         g_free(server);
2540 }
2541
2542 struct a2dp_sep *a2dp_add_sep(struct btd_adapter *adapter, uint8_t type,
2543                                 uint8_t codec, gboolean delay_reporting,
2544                                 struct a2dp_endpoint *endpoint,
2545                                 void *user_data, GDestroyNotify destroy,
2546                                 int *err)
2547 {
2548         struct a2dp_server *server;
2549         struct a2dp_sep *sep;
2550         GSList **l;
2551         uint32_t *record_id;
2552         sdp_record_t *record;
2553
2554         server = find_server(servers, adapter);
2555         if (server == NULL) {
2556                 if (err)
2557                         *err = -EPROTONOSUPPORT;
2558                 return NULL;
2559         }
2560
2561         if (type == AVDTP_SEP_TYPE_SINK && !server->sink_enabled) {
2562                 if (err)
2563                         *err = -EPROTONOSUPPORT;
2564                 return NULL;
2565         }
2566
2567         if (type == AVDTP_SEP_TYPE_SOURCE && !server->source_enabled) {
2568                 if (err)
2569                         *err = -EPROTONOSUPPORT;
2570                 return NULL;
2571         }
2572
2573         sep = g_new0(struct a2dp_sep, 1);
2574
2575         sep->lsep = avdtp_register_sep(server->seps, type,
2576                                         AVDTP_MEDIA_TYPE_AUDIO, codec,
2577                                         delay_reporting, &endpoint_ind,
2578                                         &cfm, sep);
2579
2580         if (sep->lsep == NULL) {
2581                 g_free(sep);
2582                 if (err)
2583                         *err = -EINVAL;
2584                 return NULL;
2585         }
2586
2587         sep->server = server;
2588         sep->endpoint = endpoint;
2589         sep->codec = codec;
2590         sep->type = type;
2591         sep->delay_reporting = delay_reporting;
2592         sep->user_data = user_data;
2593         sep->destroy = destroy;
2594
2595         if (type == AVDTP_SEP_TYPE_SOURCE) {
2596                 l = &server->sources;
2597                 record_id = &server->source_record_id;
2598         } else {
2599                 l = &server->sinks;
2600                 record_id = &server->sink_record_id;
2601         }
2602
2603         if (*record_id != 0)
2604                 goto add;
2605
2606 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2607         if (btd_adapter_get_a2dp_role(adapter) == BLUETOOTH_A2DP_SINK_ROLE)
2608                 record = a2dp_record(type, true);
2609         else
2610                 record = a2dp_record(type, false);
2611 #else
2612         record = a2dp_record(type);
2613 #endif
2614         if (!record) {
2615                 error("Unable to allocate new service record");
2616                 a2dp_unregister_sep(sep);
2617                 if (err)
2618                         *err = -EINVAL;
2619                 return NULL;
2620         }
2621
2622         if (adapter_service_add(server->adapter, record) < 0) {
2623                 error("Unable to register A2DP service record");
2624                 sdp_record_free(record);
2625                 a2dp_unregister_sep(sep);
2626                 if (err)
2627                         *err = -EINVAL;
2628                 return NULL;
2629         }
2630
2631         if (!a2dp_server_listen(server)) {
2632                 sdp_record_free(record);
2633                 a2dp_unregister_sep(sep);
2634                 if (err)
2635                         *err = -EINVAL;
2636                 return NULL;
2637         }
2638
2639         *record_id = record->handle;
2640
2641 add:
2642         *l = g_slist_append(*l, sep);
2643
2644         if (err)
2645                 *err = 0;
2646         return sep;
2647 }
2648
2649 void a2dp_remove_sep(struct a2dp_sep *sep)
2650 {
2651         struct a2dp_server *server = sep->server;
2652
2653         if (sep->type == AVDTP_SEP_TYPE_SOURCE) {
2654                 if (g_slist_find(server->sources, sep) == NULL)
2655                         return;
2656                 server->sources = g_slist_remove(server->sources, sep);
2657                 if (server->sources == NULL && server->source_record_id) {
2658                         adapter_service_remove(server->adapter,
2659                                                 server->source_record_id);
2660                         server->source_record_id = 0;
2661                 }
2662         } else {
2663                 if (g_slist_find(server->sinks, sep) == NULL)
2664                         return;
2665                 server->sinks = g_slist_remove(server->sinks, sep);
2666                 if (server->sinks == NULL && server->sink_record_id) {
2667                         adapter_service_remove(server->adapter,
2668                                                 server->sink_record_id);
2669                         server->sink_record_id = 0;
2670                 }
2671         }
2672
2673         if (sep->locked)
2674                 return;
2675
2676         a2dp_unregister_sep(sep);
2677 }
2678
2679 static void select_cb(struct a2dp_setup *setup, void *ret, int size)
2680 {
2681         struct avdtp_service_capability *service;
2682         struct avdtp_media_codec_capability *codec;
2683         int err;
2684
2685         if (size >= 0) {
2686                 caps_add_codec(&setup->caps, setup->sep->codec, ret, size);
2687                 goto done;
2688         }
2689
2690         setup->sep = queue_pop_head(setup->eps);
2691         if (!setup->sep) {
2692                 error("Unable to select a valid configuration");
2693                 goto done;
2694         }
2695
2696         setup->rsep = find_remote_sep(setup->chan, setup->sep);
2697         service = avdtp_get_codec(setup->rsep->sep);
2698         codec = (struct avdtp_media_codec_capability *) service->data;
2699
2700         err = setup->sep->endpoint->select_configuration(setup->sep,
2701                                         codec->data,
2702                                         service->length - sizeof(*codec),
2703                                         setup,
2704                                         select_cb, setup->sep->user_data);
2705         if (err == 0)
2706                 return;
2707
2708 done:
2709         finalize_select(setup);
2710         setup_unref(setup);
2711 }
2712
2713 static struct queue *a2dp_find_eps(struct avdtp *session, GSList *list,
2714                                         const char *sender)
2715 {
2716 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2717         struct queue *selected_sep = NULL;
2718 #endif
2719
2720         struct a2dp_channel *chan = find_channel(session);
2721         struct queue *seps = NULL;
2722
2723         for (; list; list = list->next) {
2724                 struct a2dp_sep *sep = list->data;
2725                 struct avdtp_remote_sep *rsep;
2726 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2727                 struct avdtp_media_codec_capability *cap;
2728                 struct avdtp_service_capability *service;
2729 #endif
2730
2731                 /* Use sender's endpoint if available */
2732                 if (sender) {
2733                         const char *name;
2734
2735                         if (sep->endpoint == NULL)
2736                                 continue;
2737
2738                         name = sep->endpoint->get_name(sep, sep->user_data);
2739                         if (g_strcmp0(sender, name) != 0)
2740                                 continue;
2741                 }
2742
2743 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2744                 rsep = avdtp_find_remote_sep(session, sep->lsep);
2745                 if (rsep == NULL)
2746                         continue;
2747
2748                 service = avdtp_get_codec(rsep);
2749                 cap = (struct avdtp_media_codec_capability *) service->data;
2750
2751                 if (cap->media_codec_type != A2DP_CODEC_VENDOR) {
2752                         if (!selected_sep)
2753                                 selected_sep = queue_new();
2754                         queue_push_head(selected_sep, sep);
2755                         continue;
2756 #ifdef TIZEN_FEATURE_SSC_ENCODER
2757                 } else {
2758                         /* This is vendor codec */
2759                         queue_push_head(selected_sep, sep);
2760                         if (endpoint_match_codec_preference(session, cap, sep))
2761                                 return selected_sep;
2762                         continue;
2763 #endif
2764                 }
2765 #else
2766                 rsep = avdtp_find_remote_sep(session, sep->lsep);
2767                 if (!rsep)
2768                         continue;
2769
2770                 if (!seps)
2771                         seps = queue_new();
2772 #endif
2773                 /* Prepend last used so it is preferred over others */
2774                 if (chan->last_used && (chan->last_used->lsep == sep &&
2775                                         chan->last_used->rsep->sep == rsep))
2776                         queue_push_head(seps, sep);
2777                 else
2778                         queue_push_tail(seps, sep);     
2779         }
2780
2781 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2782         if (selected_sep)
2783                 return selected_sep;
2784         else
2785                 return NULL;
2786 #else
2787         return seps;
2788 #endif
2789 }
2790
2791 static struct queue *a2dp_select_eps(struct avdtp *session, uint8_t type,
2792                                         const char *sender)
2793 {
2794         struct a2dp_server *server;
2795         struct queue *seps;
2796         GSList *l;
2797
2798         server = find_server(servers, avdtp_get_adapter(session));
2799         if (!server)
2800                 return NULL;
2801
2802         l = type == AVDTP_SEP_TYPE_SINK ? server->sources : server->sinks;
2803
2804         /* Check sender's seps first */
2805         seps = a2dp_find_eps(session, l, sender);
2806         if (seps != NULL)
2807                 return seps;
2808
2809         return a2dp_find_eps(session, l, NULL);
2810 }
2811
2812 static void store_remote_sep(void *data, void *user_data)
2813 {
2814         struct a2dp_remote_sep *sep = data;
2815         GKeyFile *key_file = user_data;
2816         char seid[4], value[256];
2817         struct avdtp_service_capability *service = avdtp_get_codec(sep->sep);
2818         struct avdtp_media_codec_capability *codec = (void *) service->data;
2819         unsigned int i;
2820         ssize_t offset;
2821
2822         sprintf(seid, "%02hhx", avdtp_get_seid(sep->sep));
2823
2824         offset = sprintf(value, "%02hhx:%02hhx:%02hhx:",
2825                         avdtp_get_type(sep->sep), codec->media_codec_type,
2826                         avdtp_get_delay_reporting(sep->sep));
2827
2828         for (i = 0; i < service->length - sizeof(*codec); i++)
2829                 offset += sprintf(value + offset, "%02hhx", codec->data[i]);
2830
2831         g_key_file_set_string(key_file, "Endpoints", seid, value);
2832 }
2833
2834 static void store_remote_seps(struct a2dp_channel *chan)
2835 {
2836         struct btd_device *device = chan->device;
2837         char filename[PATH_MAX];
2838         char dst_addr[18];
2839         GKeyFile *key_file;
2840         char *data;
2841         gsize length = 0;
2842
2843         if (queue_isempty(chan->seps))
2844                 return;
2845
2846         ba2str(device_get_address(device), dst_addr);
2847
2848         snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
2849                         btd_adapter_get_storage_dir(device_get_adapter(device)),
2850                         dst_addr);
2851         key_file = g_key_file_new();
2852         g_key_file_load_from_file(key_file, filename, 0, NULL);
2853
2854         data = g_key_file_get_string(key_file, "Endpoints", "LastUsed",
2855                                                                 NULL);
2856
2857         /* Remove current endpoints since it might have changed */
2858         g_key_file_remove_group(key_file, "Endpoints", NULL);
2859
2860         queue_foreach(chan->seps, store_remote_sep, key_file);
2861
2862         if (data) {
2863                 g_key_file_set_string(key_file, "Endpoints", "LastUsed",
2864                                                 data);
2865                 g_free(data);
2866         }
2867
2868         data = g_key_file_to_data(key_file, &length, NULL);
2869         g_file_set_contents(filename, data, length, NULL);
2870
2871         g_free(data);
2872         g_key_file_free(key_file);
2873 }
2874
2875 static void discover_cb(struct avdtp *session, GSList *seps,
2876                                 struct avdtp_error *err, void *user_data)
2877 {
2878         struct a2dp_setup *setup = user_data;
2879         uint16_t version = avdtp_get_version(session);
2880
2881         DBG("version 0x%04x err %p", version, err);
2882
2883 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
2884         if (!g_slist_find(setups, setup)) {
2885                 warn("setup %p no longer valid", setup);
2886                 return;
2887         }
2888 #endif
2889
2890         setup->seps = seps;
2891         setup->err = err;
2892
2893         if (!err) {
2894                 g_slist_foreach(seps, register_remote_sep, setup->chan);
2895
2896                 /* Only store version has been initialized as features like
2897                  * Delay Reporting may not be queried if the version in
2898                  * unknown.
2899                  */
2900                 if (version)
2901                         store_remote_seps(setup->chan);
2902         }
2903
2904         finalize_discover(setup);
2905 }
2906
2907 unsigned int a2dp_discover(struct avdtp *session, a2dp_discover_cb_t cb,
2908                                                         void *user_data)
2909 {
2910         struct a2dp_setup *setup;
2911         struct a2dp_setup_cb *cb_data;
2912
2913         setup = a2dp_setup_get(session);
2914         if (!setup)
2915                 return 0;
2916
2917         cb_data = setup_cb_new(setup);
2918         cb_data->discover_cb = cb;
2919         cb_data->user_data = user_data;
2920
2921         if (avdtp_discover(session, discover_cb, setup) == 0)
2922                 return cb_data->id;
2923
2924         setup_cb_free(cb_data);
2925         return 0;
2926 }
2927
2928 unsigned int a2dp_select_capabilities(struct avdtp *session,
2929                                         uint8_t type, const char *sender,
2930                                         a2dp_select_cb_t cb,
2931                                         void *user_data)
2932 {
2933         struct a2dp_setup *setup;
2934         struct a2dp_setup_cb *cb_data;
2935         struct queue *eps;
2936         struct avdtp_service_capability *service;
2937         struct avdtp_media_codec_capability *codec;
2938         int err;
2939
2940         eps = a2dp_select_eps(session, type, sender);
2941         if (!eps) {
2942                 error("Unable to select SEP");
2943                 return 0;
2944         }
2945
2946         setup = a2dp_setup_get(session);
2947         if (!setup)
2948                 return 0;
2949
2950         cb_data = setup_cb_new(setup);
2951         cb_data->select_cb = cb;
2952         cb_data->user_data = user_data;
2953
2954         setup->eps = eps;
2955         setup->sep = queue_pop_head(eps);
2956         setup->rsep = find_remote_sep(setup->chan, setup->sep);
2957
2958         if (setup->rsep == NULL) {
2959                 error("Could not find remote sep");
2960                 goto fail;
2961         }
2962
2963         service = avdtp_get_codec(setup->rsep->sep);
2964         codec = (struct avdtp_media_codec_capability *) service->data;
2965
2966         err = setup->sep->endpoint->select_configuration(setup->sep,
2967                                                         codec->data,
2968                                                         service->length -
2969                                                         sizeof(*codec),
2970                                                         setup_ref(setup),
2971                                                         select_cb,
2972                                                         setup->sep->user_data);
2973         if (err == 0)
2974                 return cb_data->id;
2975
2976         setup_unref(setup);
2977
2978 fail:
2979         setup_cb_free(cb_data);
2980         return 0;
2981
2982 }
2983
2984 unsigned int a2dp_config(struct avdtp *session, struct a2dp_sep *sep,
2985                                 a2dp_config_cb_t cb, GSList *caps,
2986                                 void *user_data)
2987 {
2988         struct a2dp_setup_cb *cb_data;
2989         GSList *l;
2990         struct a2dp_server *server;
2991         struct a2dp_setup *setup;
2992         struct a2dp_sep *tmp;
2993         struct avdtp_service_capability *cap;
2994         struct avdtp_media_codec_capability *codec_cap = NULL;
2995         int posix_err;
2996
2997         server = find_server(servers, avdtp_get_adapter(session));
2998         if (!server)
2999                 return 0;
3000
3001         for (l = caps; l != NULL; l = l->next) {
3002                 cap = l->data;
3003
3004                 if (cap->category != AVDTP_MEDIA_CODEC)
3005                         continue;
3006
3007                 codec_cap = (void *) cap->data;
3008                 break;
3009         }
3010
3011         if (!codec_cap)
3012                 return 0;
3013
3014         if (sep->codec != codec_cap->media_codec_type)
3015                 return 0;
3016
3017         DBG("a2dp_config: selected SEP %p", sep->lsep);
3018
3019         setup = a2dp_setup_get(session);
3020         if (!setup)
3021                 return 0;
3022
3023         cb_data = setup_cb_new(setup);
3024         cb_data->config_cb = cb;
3025         cb_data->user_data = user_data;
3026
3027         setup->sep = sep;
3028         setup->stream = sep->stream;
3029
3030         /* Copy given caps if they are different than current caps */
3031         if (setup->caps != caps) {
3032                 g_slist_free_full(setup->caps, g_free);
3033                 setup->caps = g_slist_copy(caps);
3034         }
3035
3036         switch (avdtp_sep_get_state(sep->lsep)) {
3037         case AVDTP_STATE_IDLE:
3038                 if (sep->type == AVDTP_SEP_TYPE_SOURCE)
3039                         l = server->sources;
3040                 else
3041                         l = server->sinks;
3042
3043                 for (; l != NULL; l = l->next) {
3044                         tmp = l->data;
3045                         if (avdtp_has_stream(session, tmp->stream))
3046                                 break;
3047                 }
3048
3049                 if (l != NULL) {
3050                         if (tmp->locked)
3051                                 goto failed;
3052                         setup->reconfigure = TRUE;
3053                         if (avdtp_close(session, tmp->stream, FALSE) < 0) {
3054                                 error("avdtp_close failed");
3055                                 goto failed;
3056                         }
3057                         break;
3058                 }
3059
3060                 setup->rsep = find_remote_sep(setup->chan, sep);
3061                 if (setup->rsep == NULL) {
3062                         error("No matching ACP and INT SEPs found");
3063                         goto failed;
3064                 }
3065
3066                 posix_err = avdtp_set_configuration(session, setup->rsep->sep,
3067                                                         sep->lsep, caps,
3068                                                         &setup->stream);
3069                 if (posix_err < 0) {
3070                         error("avdtp_set_configuration: %s",
3071                                 strerror(-posix_err));
3072                         goto failed;
3073                 }
3074                 break;
3075         case AVDTP_STATE_OPEN:
3076         case AVDTP_STATE_STREAMING:
3077                 if (avdtp_stream_has_capabilities(setup->stream, caps)) {
3078                         DBG("Configuration match: resuming");
3079                         cb_data->source_id = g_idle_add(finalize_config,
3080                                                                 setup);
3081                 } else if (!setup->reconfigure) {
3082                         setup->reconfigure = TRUE;
3083                         if (avdtp_close(session, sep->stream, FALSE) < 0) {
3084                                 error("avdtp_close failed");
3085                                 goto failed;
3086                         }
3087                 }
3088                 break;
3089         case AVDTP_STATE_CONFIGURED:
3090         case AVDTP_STATE_CLOSING:
3091         case AVDTP_STATE_ABORTING:
3092         default:
3093                 error("SEP in bad state for requesting a new stream");
3094                 goto failed;
3095         }
3096
3097         return cb_data->id;
3098
3099 failed:
3100         setup_cb_free(cb_data);
3101         return 0;
3102 }
3103
3104 unsigned int a2dp_resume(struct avdtp *session, struct a2dp_sep *sep,
3105                                 a2dp_stream_cb_t cb, void *user_data)
3106 {
3107         struct a2dp_setup_cb *cb_data;
3108         struct a2dp_setup *setup;
3109
3110         setup = a2dp_setup_get(session);
3111         if (!setup)
3112                 return 0;
3113
3114         cb_data = setup_cb_new(setup);
3115         cb_data->resume_cb = cb;
3116         cb_data->user_data = user_data;
3117
3118         setup->sep = sep;
3119         setup->stream = sep->stream;
3120
3121         switch (avdtp_sep_get_state(sep->lsep)) {
3122         case AVDTP_STATE_IDLE:
3123                 goto failed;
3124                 break;
3125         case AVDTP_STATE_CONFIGURED:
3126                 setup->start = TRUE;
3127                 break;
3128         case AVDTP_STATE_OPEN:
3129                 if (avdtp_start(session, sep->stream) < 0) {
3130                         error("avdtp_start failed");
3131                         goto failed;
3132                 }
3133                 sep->starting = TRUE;
3134                 break;
3135         case AVDTP_STATE_STREAMING:
3136                 if (!sep->suspending && sep->suspend_timer) {
3137                         g_source_remove(sep->suspend_timer);
3138                         sep->suspend_timer = 0;
3139                         avdtp_unref(sep->session);
3140                         sep->session = NULL;
3141                 }
3142                 if (sep->suspending)
3143                         setup->start = TRUE;
3144                 else
3145                         cb_data->source_id = g_idle_add(finalize_resume,
3146                                                                 setup);
3147                 break;
3148         case AVDTP_STATE_CLOSING:
3149         case AVDTP_STATE_ABORTING:
3150         default:
3151                 error("SEP in bad state for resume");
3152                 goto failed;
3153         }
3154
3155         return cb_data->id;
3156
3157 failed:
3158         setup_cb_free(cb_data);
3159         return 0;
3160 }
3161
3162 unsigned int a2dp_suspend(struct avdtp *session, struct a2dp_sep *sep,
3163                                 a2dp_stream_cb_t cb, void *user_data)
3164 {
3165         struct a2dp_setup_cb *cb_data;
3166         struct a2dp_setup *setup;
3167
3168         setup = a2dp_setup_get(session);
3169         if (!setup)
3170                 return 0;
3171
3172         cb_data = setup_cb_new(setup);
3173         cb_data->suspend_cb = cb;
3174         cb_data->user_data = user_data;
3175
3176         setup->sep = sep;
3177         setup->stream = sep->stream;
3178
3179         switch (avdtp_sep_get_state(sep->lsep)) {
3180         case AVDTP_STATE_IDLE:
3181                 error("a2dp_suspend: no stream to suspend");
3182                 goto failed;
3183                 break;
3184         case AVDTP_STATE_OPEN:
3185                 cb_data->source_id = g_idle_add(finalize_suspend, setup);
3186                 break;
3187         case AVDTP_STATE_STREAMING:
3188                 if (avdtp_suspend(session, sep->stream) < 0) {
3189                         error("avdtp_suspend failed");
3190                         goto failed;
3191                 }
3192                 sep->suspending = TRUE;
3193                 break;
3194         case AVDTP_STATE_CONFIGURED:
3195         case AVDTP_STATE_CLOSING:
3196         case AVDTP_STATE_ABORTING:
3197         default:
3198                 error("SEP in bad state for suspend");
3199                 goto failed;
3200         }
3201
3202         return cb_data->id;
3203
3204 failed:
3205         setup_cb_free(cb_data);
3206         return 0;
3207 }
3208
3209 gboolean a2dp_cancel(unsigned int id)
3210 {
3211         GSList *ls;
3212
3213         for (ls = setups; ls != NULL; ls = g_slist_next(ls)) {
3214                 struct a2dp_setup *setup = ls->data;
3215                 GSList *l;
3216                 for (l = setup->cb; l != NULL; l = g_slist_next(l)) {
3217                         struct a2dp_setup_cb *cb = l->data;
3218
3219                         if (cb->id != id)
3220                                 continue;
3221
3222                         setup_ref(setup);
3223                         setup_cb_free(cb);
3224
3225                         if (!setup->cb) {
3226                                 DBG("aborting setup %p", setup);
3227                                 if (!avdtp_abort(setup->session, setup->stream))
3228                                         return TRUE;
3229                         }
3230
3231                         setup_unref(setup);
3232                         return TRUE;
3233                 }
3234         }
3235
3236         return FALSE;
3237 }
3238
3239 gboolean a2dp_sep_lock(struct a2dp_sep *sep, struct avdtp *session)
3240 {
3241         if (sep->locked)
3242                 return FALSE;
3243
3244         DBG("SEP %p locked", sep->lsep);
3245         sep->locked = TRUE;
3246
3247         return TRUE;
3248 }
3249
3250 gboolean a2dp_sep_unlock(struct a2dp_sep *sep, struct avdtp *session)
3251 {
3252         struct a2dp_server *server = sep->server;
3253         avdtp_state_t state;
3254         GSList *l;
3255
3256         state = avdtp_sep_get_state(sep->lsep);
3257
3258         sep->locked = FALSE;
3259
3260         DBG("SEP %p unlocked", sep->lsep);
3261
3262         if (sep->type == AVDTP_SEP_TYPE_SOURCE)
3263                 l = server->sources;
3264         else
3265                 l = server->sinks;
3266
3267         /* Unregister sep if it was removed */
3268         if (g_slist_find(l, sep) == NULL) {
3269                 a2dp_unregister_sep(sep);
3270                 return TRUE;
3271         }
3272
3273         if (!sep->stream || state == AVDTP_STATE_IDLE)
3274                 return TRUE;
3275
3276         switch (state) {
3277         case AVDTP_STATE_OPEN:
3278                 /* Set timer here */
3279                 break;
3280         case AVDTP_STATE_STREAMING:
3281                 if (avdtp_suspend(session, sep->stream) == 0)
3282                         sep->suspending = TRUE;
3283                 break;
3284         case AVDTP_STATE_IDLE:
3285         case AVDTP_STATE_CONFIGURED:
3286         case AVDTP_STATE_CLOSING:
3287         case AVDTP_STATE_ABORTING:
3288         default:
3289                 break;
3290         }
3291
3292         return TRUE;
3293 }
3294
3295 struct avdtp_stream *a2dp_sep_get_stream(struct a2dp_sep *sep)
3296 {
3297         return sep->stream;
3298 }
3299
3300 struct btd_device *a2dp_setup_get_device(struct a2dp_setup *setup)
3301 {
3302         if (setup->session == NULL)
3303                 return NULL;
3304
3305         return avdtp_get_device(setup->session);
3306 }
3307
3308 const char *a2dp_setup_remote_path(struct a2dp_setup *setup)
3309 {
3310         if (setup->rsep) {
3311                 return setup->rsep->path;
3312         }
3313
3314         return NULL;
3315 }
3316
3317 static int a2dp_source_probe(struct btd_service *service)
3318 {
3319         struct btd_device *dev = btd_service_get_device(service);
3320
3321         DBG("path %s", device_get_path(dev));
3322
3323         source_init(service);
3324
3325         return 0;
3326 }
3327
3328 static void a2dp_source_remove(struct btd_service *service)
3329 {
3330         source_unregister(service);
3331 }
3332
3333 static int a2dp_sink_probe(struct btd_service *service)
3334 {
3335         struct btd_device *dev = btd_service_get_device(service);
3336
3337         DBG("path %s", device_get_path(dev));
3338
3339         return sink_init(service);
3340 }
3341
3342 static void a2dp_sink_remove(struct btd_service *service)
3343 {
3344         sink_unregister(service);
3345 }
3346
3347 static int a2dp_source_connect(struct btd_service *service)
3348 {
3349         struct btd_device *dev = btd_service_get_device(service);
3350         struct btd_adapter *adapter = device_get_adapter(dev);
3351         struct a2dp_server *server;
3352         const char *path = device_get_path(dev);
3353
3354         DBG("path %s", path);
3355
3356         server = find_server(servers, adapter);
3357         if (!server || !server->sink_enabled) {
3358                 DBG("Unexpected error: cannot find server");
3359                 return -EPROTONOSUPPORT;
3360         }
3361
3362         /* Return protocol not available if no record/endpoint exists */
3363         if (server->sink_record_id == 0)
3364                 return -ENOPROTOOPT;
3365
3366         return source_connect(service);
3367 }
3368
3369 static int a2dp_source_disconnect(struct btd_service *service)
3370 {
3371         struct btd_device *dev = btd_service_get_device(service);
3372         const char *path = device_get_path(dev);
3373
3374         DBG("path %s", path);
3375
3376         return source_disconnect(service);
3377 }
3378
3379 static int a2dp_sink_connect(struct btd_service *service)
3380 {
3381         struct btd_device *dev = btd_service_get_device(service);
3382         struct btd_adapter *adapter = device_get_adapter(dev);
3383         struct a2dp_server *server;
3384         const char *path = device_get_path(dev);
3385
3386         DBG("path %s", path);
3387
3388         server = find_server(servers, adapter);
3389         if (!server || !server->source_enabled) {
3390                 DBG("Unexpected error: cannot find server");
3391                 return -EPROTONOSUPPORT;
3392         }
3393
3394         /* Return protocol not available if no record/endpoint exists */
3395         if (server->source_record_id == 0)
3396                 return -ENOPROTOOPT;
3397
3398         return sink_connect(service);
3399 }
3400
3401 static int a2dp_sink_disconnect(struct btd_service *service)
3402 {
3403         struct btd_device *dev = btd_service_get_device(service);
3404         const char *path = device_get_path(dev);
3405
3406         DBG("path %s", path);
3407
3408         return sink_disconnect(service);
3409 }
3410
3411 static int a2dp_source_server_probe(struct btd_profile *p,
3412                                                 struct btd_adapter *adapter)
3413 {
3414         struct a2dp_server *server;
3415
3416         DBG("path %s", adapter_get_path(adapter));
3417
3418         server = find_server(servers, adapter);
3419         if (server != NULL)
3420                 goto done;
3421
3422         server = a2dp_server_register(adapter);
3423         if (server == NULL)
3424                 return -EPROTONOSUPPORT;
3425
3426 done:
3427         server->source_enabled = TRUE;
3428
3429         return 0;
3430 }
3431
3432 static void a2dp_source_server_remove(struct btd_profile *p,
3433                                                 struct btd_adapter *adapter)
3434 {
3435         struct a2dp_server *server;
3436
3437         DBG("path %s", adapter_get_path(adapter));
3438
3439         server = find_server(servers, adapter);
3440         if (!server)
3441                 return;
3442
3443         g_slist_free_full(server->sources,
3444                                         (GDestroyNotify) a2dp_unregister_sep);
3445
3446         if (server->source_record_id) {
3447                 adapter_service_remove(server->adapter,
3448                                         server->source_record_id);
3449                 server->source_record_id = 0;
3450         }
3451
3452         if (server->sink_record_id)
3453                 return;
3454
3455         a2dp_server_unregister(server);
3456 }
3457
3458 static int a2dp_sink_server_probe(struct btd_profile *p,
3459                                                 struct btd_adapter *adapter)
3460 {
3461         struct a2dp_server *server;
3462
3463         DBG("path %s", adapter_get_path(adapter));
3464
3465         server = find_server(servers, adapter);
3466         if (server != NULL)
3467                 goto done;
3468
3469         server = a2dp_server_register(adapter);
3470         if (server == NULL)
3471                 return -EPROTONOSUPPORT;
3472
3473 done:
3474         server->sink_enabled = TRUE;
3475
3476         return 0;
3477 }
3478
3479 static void a2dp_sink_server_remove(struct btd_profile *p,
3480                                                 struct btd_adapter *adapter)
3481 {
3482         struct a2dp_server *server;
3483
3484         DBG("path %s", adapter_get_path(adapter));
3485
3486         server = find_server(servers, adapter);
3487         if (!server)
3488                 return;
3489
3490         g_slist_free_full(server->sinks, (GDestroyNotify) a2dp_unregister_sep);
3491
3492         if (server->sink_record_id) {
3493                 adapter_service_remove(server->adapter, server->sink_record_id);
3494                 server->sink_record_id = 0;
3495         }
3496
3497         if (server->source_record_id)
3498                 return;
3499
3500         a2dp_server_unregister(server);
3501 }
3502
3503 static int media_server_probe(struct btd_adapter *adapter)
3504 {
3505         DBG("path %s", adapter_get_path(adapter));
3506
3507         return media_register(adapter);
3508 }
3509
3510 static void media_server_remove(struct btd_adapter *adapter)
3511 {
3512         DBG("path %s", adapter_get_path(adapter));
3513
3514         media_unregister(adapter);
3515 }
3516
3517 static struct btd_profile a2dp_source_profile = {
3518         .name           = "a2dp-source",
3519         .priority       = BTD_PROFILE_PRIORITY_MEDIUM,
3520
3521         .remote_uuid    = A2DP_SOURCE_UUID,
3522         .device_probe   = a2dp_source_probe,
3523         .device_remove  = a2dp_source_remove,
3524
3525         .auto_connect   = true,
3526         .connect        = a2dp_source_connect,
3527         .disconnect     = a2dp_source_disconnect,
3528
3529         .adapter_probe  = a2dp_sink_server_probe,
3530         .adapter_remove = a2dp_sink_server_remove,
3531 };
3532
3533 static struct btd_profile a2dp_sink_profile = {
3534         .name           = "a2dp-sink",
3535         .priority       = BTD_PROFILE_PRIORITY_MEDIUM,
3536
3537         .remote_uuid    = A2DP_SINK_UUID,
3538         .device_probe   = a2dp_sink_probe,
3539         .device_remove  = a2dp_sink_remove,
3540
3541         .auto_connect   = true,
3542         .connect        = a2dp_sink_connect,
3543         .disconnect     = a2dp_sink_disconnect,
3544
3545         .adapter_probe  = a2dp_source_server_probe,
3546         .adapter_remove = a2dp_source_server_remove,
3547 };
3548
3549 static struct btd_adapter_driver media_driver = {
3550         .name           = "media",
3551         .probe          = media_server_probe,
3552         .remove         = media_server_remove,
3553 };
3554
3555 static int a2dp_init(void)
3556 {
3557         btd_register_adapter_driver(&media_driver);
3558         btd_profile_register(&a2dp_source_profile);
3559         btd_profile_register(&a2dp_sink_profile);
3560
3561         return 0;
3562 }
3563
3564 static void a2dp_exit(void)
3565 {
3566         btd_unregister_adapter_driver(&media_driver);
3567         btd_profile_unregister(&a2dp_source_profile);
3568         btd_profile_unregister(&a2dp_sink_profile);
3569 }
3570
3571 BLUETOOTH_PLUGIN_DEFINE(a2dp, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
3572                 a2dp_init, a2dp_exit)