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