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 (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 <stdio.h> 30 #include <errno.h> 31 #include <unistd.h> 32 #include <sys/stat.h> 33 #include <sys/param.h> 34 #include <netinet/in.h> 35 36 #include <bluetooth/bluetooth.h> 37 #include <bluetooth/sdp.h> 38 #include <bluetooth/sdp_lib.h> 39 40 #include <glib.h> 41 #include <dbus/dbus.h> 42 #include <gdbus.h> 43 44 #include "log.h" 45 #include "textfile.h" 46 #include "../src/adapter.h" 47 #include "../src/device.h" 48 49 #include "error.h" 50 #include "ipc.h" 51 #include "dbus-common.h" 52 #include "device.h" 53 #include "unix.h" 54 #include "avdtp.h" 55 #include "control.h" 56 #include "headset.h" 57 #include "gateway.h" 58 #include "sink.h" 59 #include "source.h" 60 61 #define AUDIO_INTERFACE "org.bluez.Audio" 62 63 #define CONTROL_CONNECT_TIMEOUT 2 64 #define AVDTP_CONNECT_TIMEOUT 1 65 #define HEADSET_CONNECT_TIMEOUT 1 66 67 typedef enum { 68 AUDIO_STATE_DISCONNECTED, 69 AUDIO_STATE_CONNECTING, 70 AUDIO_STATE_CONNECTED, 71 } audio_state_t; 72 73 struct service_auth { 74 service_auth_cb cb; 75 void *user_data; 76 }; 77 78 struct dev_priv { 79 audio_state_t state; 80 81 headset_state_t hs_state; 82 sink_state_t sink_state; 83 avctp_state_t avctp_state; 84 GSList *auths; 85 86 DBusMessage *conn_req; 87 DBusMessage *dc_req; 88 89 guint control_timer; 90 guint avdtp_timer; 91 guint headset_timer; 92 guint dc_id; 93 94 gboolean disconnecting; 95 gboolean authorized; 96 guint auth_idle_id; 97 }; 98 99 static unsigned int sink_callback_id = 0; 100 static unsigned int avctp_callback_id = 0; 101 static unsigned int avdtp_callback_id = 0; 102 static unsigned int headset_callback_id = 0; 103 104 static void device_free(struct audio_device *dev) 105 { 106 struct dev_priv *priv = dev->priv; 107 108 if (dev->conn) 109 dbus_connection_unref(dev->conn); 110 111 btd_device_unref(dev->btd_dev); 112 113 if (priv) { 114 if (priv->auths) 115 audio_device_cancel_authorization(dev, NULL, NULL); 116 if (priv->control_timer) 117 g_source_remove(priv->control_timer); 118 if (priv->avdtp_timer) 119 g_source_remove(priv->avdtp_timer); 120 if (priv->headset_timer) 121 g_source_remove(priv->headset_timer); 122 if (priv->dc_req) 123 dbus_message_unref(priv->dc_req); 124 if (priv->conn_req) 125 dbus_message_unref(priv->conn_req); 126 if (priv->dc_id) 127 device_remove_disconnect_watch(dev->btd_dev, 128 priv->dc_id); 129 g_free(priv); 130 } 131 132 g_free(dev->path); 133 g_free(dev); 134 } 135 136 static const char *state2str(audio_state_t state) 137 { 138 switch (state) { 139 case AUDIO_STATE_DISCONNECTED: 140 return "disconnected"; 141 case AUDIO_STATE_CONNECTING: 142 return "connecting"; 143 case AUDIO_STATE_CONNECTED: 144 return "connected"; 145 default: 146 error("Invalid audio state %d", state); 147 return NULL; 148 } 149 } 150 151 static gboolean control_connect_timeout(gpointer user_data) 152 { 153 struct audio_device *dev = user_data; 154 155 dev->priv->control_timer = 0; 156 157 if (dev->control) 158 avrcp_connect(dev); 159 160 return FALSE; 161 } 162 163 static gboolean device_set_control_timer(struct audio_device *dev) 164 { 165 struct dev_priv *priv = dev->priv; 166 167 if (!dev->control) 168 return FALSE; 169 170 if (priv->control_timer) 171 return FALSE; 172 173 priv->control_timer = g_timeout_add_seconds(CONTROL_CONNECT_TIMEOUT, 174 control_connect_timeout, 175 dev); 176 177 return TRUE; 178 } 179 180 static void device_remove_control_timer(struct audio_device *dev) 181 { 182 if (dev->priv->control_timer) 183 g_source_remove(dev->priv->control_timer); 184 dev->priv->control_timer = 0; 185 } 186 187 static void device_remove_avdtp_timer(struct audio_device *dev) 188 { 189 if (dev->priv->avdtp_timer) 190 g_source_remove(dev->priv->avdtp_timer); 191 dev->priv->avdtp_timer = 0; 192 } 193 194 static void device_remove_headset_timer(struct audio_device *dev) 195 { 196 if (dev->priv->headset_timer) 197 g_source_remove(dev->priv->headset_timer); 198 dev->priv->headset_timer = 0; 199 } 200 201 static void disconnect_cb(struct btd_device *btd_dev, gboolean removal, 202 void *user_data) 203 { 204 struct audio_device *dev = user_data; 205 struct dev_priv *priv = dev->priv; 206 207 if (priv->state == AUDIO_STATE_DISCONNECTED) 208 return; 209 210 if (priv->disconnecting) 211 return; 212 213 priv->disconnecting = TRUE; 214 215 device_remove_control_timer(dev); 216 device_remove_avdtp_timer(dev); 217 device_remove_headset_timer(dev); 218 219 if (dev->control) 220 avrcp_disconnect(dev); 221 222 if (dev->sink && priv->sink_state != SINK_STATE_DISCONNECTED) 223 sink_shutdown(dev->sink); 224 else if (priv->hs_state != HEADSET_STATE_DISCONNECTED) 225 headset_shutdown(dev); 226 else 227 priv->disconnecting = FALSE; 228 } 229 230 static void device_set_state(struct audio_device *dev, audio_state_t new_state) 231 { 232 struct dev_priv *priv = dev->priv; 233 const char *state_str; 234 DBusMessage *reply = NULL; 235 236 state_str = state2str(new_state); 237 if (!state_str) 238 return; 239 240 if (new_state == AUDIO_STATE_DISCONNECTED) { 241 priv->authorized = FALSE; 242 243 if (priv->dc_id) { 244 device_remove_disconnect_watch(dev->btd_dev, 245 priv->dc_id); 246 priv->dc_id = 0; 247 } 248 } else if (new_state == AUDIO_STATE_CONNECTING) 249 priv->dc_id = device_add_disconnect_watch(dev->btd_dev, 250 disconnect_cb, dev, NULL); 251 252 if (dev->priv->state == new_state) { 253 DBG("state change attempted from %s to %s", 254 state_str, state_str); 255 return; 256 } 257 258 dev->priv->state = new_state; 259 260 if (new_state == AUDIO_STATE_DISCONNECTED) { 261 if (priv->dc_req) { 262 reply = dbus_message_new_method_return(priv->dc_req); 263 dbus_message_unref(priv->dc_req); 264 priv->dc_req = NULL; 265 g_dbus_send_message(dev->conn, reply); 266 } 267 priv->disconnecting = FALSE; 268 } 269 270 if (priv->conn_req && new_state != AUDIO_STATE_CONNECTING) { 271 if (new_state == AUDIO_STATE_CONNECTED) 272 reply = dbus_message_new_method_return(priv->conn_req); 273 else 274 reply = btd_error_failed(priv->conn_req, 275 "Connect Failed"); 276 277 dbus_message_unref(priv->conn_req); 278 priv->conn_req = NULL; 279 g_dbus_send_message(dev->conn, reply); 280 } 281 282 emit_property_changed(dev->conn, dev->path, 283 AUDIO_INTERFACE, "State", 284 DBUS_TYPE_STRING, &state_str); 285 } 286 287 static gboolean avdtp_connect_timeout(gpointer user_data) 288 { 289 struct audio_device *dev = user_data; 290 291 dev->priv->avdtp_timer = 0; 292 293 if (dev->sink) { 294 struct avdtp *session = avdtp_get(&dev->src, &dev->dst); 295 296 if (!session) 297 return FALSE; 298 299 sink_setup_stream(dev->sink, session); 300 avdtp_unref(session); 301 } 302 303 return FALSE; 304 } 305 306 static gboolean device_set_avdtp_timer(struct audio_device *dev) 307 { 308 struct dev_priv *priv = dev->priv; 309 310 if (!dev->sink) 311 return FALSE; 312 313 if (priv->avdtp_timer) 314 return FALSE; 315 316 priv->avdtp_timer = g_timeout_add_seconds(AVDTP_CONNECT_TIMEOUT, 317 avdtp_connect_timeout, 318 dev); 319 320 return TRUE; 321 } 322 323 static gboolean headset_connect_timeout(gpointer user_data) 324 { 325 struct audio_device *dev = user_data; 326 struct dev_priv *priv = dev->priv; 327 328 dev->priv->headset_timer = 0; 329 330 if (dev->headset == NULL) 331 return FALSE; 332 333 if (headset_config_stream(dev, FALSE, NULL, NULL) == 0) { 334 if (priv->state != AUDIO_STATE_CONNECTED && 335 (priv->sink_state == SINK_STATE_CONNECTED || 336 priv->sink_state == SINK_STATE_PLAYING)) 337 device_set_state(dev, AUDIO_STATE_CONNECTED); 338 } 339 340 return FALSE; 341 } 342 343 static gboolean device_set_headset_timer(struct audio_device *dev) 344 { 345 struct dev_priv *priv = dev->priv; 346 347 if (!dev->headset) 348 return FALSE; 349 350 if (priv->headset_timer) 351 return FALSE; 352 353 priv->headset_timer = g_timeout_add_seconds(HEADSET_CONNECT_TIMEOUT, 354 headset_connect_timeout, dev); 355 356 return TRUE; 357 } 358 359 static void device_avdtp_cb(struct audio_device *dev, struct avdtp *session, 360 avdtp_session_state_t old_state, 361 avdtp_session_state_t new_state, 362 void *user_data) 363 { 364 if (!dev->sink || !dev->control) 365 return; 366 367 if (new_state == AVDTP_SESSION_STATE_CONNECTED) { 368 if (avdtp_stream_setup_active(session)) 369 device_set_control_timer(dev); 370 else 371 avrcp_connect(dev); 372 } 373 } 374 375 static void device_sink_cb(struct audio_device *dev, 376 sink_state_t old_state, 377 sink_state_t new_state, 378 void *user_data) 379 { 380 struct dev_priv *priv = dev->priv; 381 382 if (!dev->sink) 383 return; 384 385 priv->sink_state = new_state; 386 387 switch (new_state) { 388 case SINK_STATE_DISCONNECTED: 389 if (dev->control) { 390 device_remove_control_timer(dev); 391 avrcp_disconnect(dev); 392 } 393 if (priv->hs_state != HEADSET_STATE_DISCONNECTED && 394 (priv->dc_req || priv->disconnecting)) { 395 headset_shutdown(dev); 396 break; 397 } 398 if (priv->hs_state == HEADSET_STATE_DISCONNECTED) 399 device_set_state(dev, AUDIO_STATE_DISCONNECTED); 400 else if (old_state == SINK_STATE_CONNECTING) { 401 switch (priv->hs_state) { 402 case HEADSET_STATE_CONNECTED: 403 case HEADSET_STATE_PLAY_IN_PROGRESS: 404 case HEADSET_STATE_PLAYING: 405 device_set_state(dev, AUDIO_STATE_CONNECTED); 406 default: 407 break; 408 } 409 } 410 break; 411 case SINK_STATE_CONNECTING: 412 device_remove_avdtp_timer(dev); 413 if (priv->hs_state == HEADSET_STATE_DISCONNECTED) 414 device_set_state(dev, AUDIO_STATE_CONNECTING); 415 break; 416 case SINK_STATE_CONNECTED: 417 if (old_state == SINK_STATE_PLAYING) 418 break; 419 #ifdef ANDROID 420 android_set_high_priority(&dev->dst); 421 #endif 422 if (dev->auto_connect) { 423 if (!dev->headset) 424 device_set_state(dev, AUDIO_STATE_CONNECTED); 425 else if (priv->hs_state == HEADSET_STATE_DISCONNECTED) 426 device_set_headset_timer(dev); 427 else if (priv->hs_state == HEADSET_STATE_CONNECTED || 428 priv->hs_state == HEADSET_STATE_PLAY_IN_PROGRESS || 429 priv->hs_state == HEADSET_STATE_PLAYING) 430 device_set_state(dev, AUDIO_STATE_CONNECTED); 431 } else if (priv->hs_state == HEADSET_STATE_DISCONNECTED || 432 priv->hs_state == HEADSET_STATE_CONNECTING) 433 device_set_state(dev, AUDIO_STATE_CONNECTED); 434 break; 435 case SINK_STATE_PLAYING: 436 break; 437 } 438 } 439 440 static void device_avctp_cb(struct audio_device *dev, 441 avctp_state_t old_state, 442 avctp_state_t new_state, 443 void *user_data) 444 { 445 if (!dev->control) 446 return; 447 448 dev->priv->avctp_state = new_state; 449 450 switch (new_state) { 451 case AVCTP_STATE_DISCONNECTED: 452 break; 453 case AVCTP_STATE_CONNECTING: 454 device_remove_control_timer(dev); 455 break; 456 case AVCTP_STATE_CONNECTED: 457 break; 458 } 459 } 460 461 static void device_headset_cb(struct audio_device *dev, 462 headset_state_t old_state, 463 headset_state_t new_state, 464 void *user_data) 465 { 466 struct dev_priv *priv = dev->priv; 467 468 if (!dev->headset) 469 return; 470 471 priv->hs_state = new_state; 472 473 switch (new_state) { 474 case HEADSET_STATE_DISCONNECTED: 475 device_remove_avdtp_timer(dev); 476 if (priv->sink_state != SINK_STATE_DISCONNECTED && dev->sink && 477 (priv->dc_req || priv->disconnecting)) { 478 sink_shutdown(dev->sink); 479 break; 480 } 481 if (priv->sink_state == SINK_STATE_DISCONNECTED) 482 device_set_state(dev, AUDIO_STATE_DISCONNECTED); 483 else if (old_state == HEADSET_STATE_CONNECTING && 484 (priv->sink_state == SINK_STATE_CONNECTED || 485 priv->sink_state == SINK_STATE_PLAYING)) 486 device_set_state(dev, AUDIO_STATE_CONNECTED); 487 break; 488 case HEADSET_STATE_CONNECTING: 489 device_remove_headset_timer(dev); 490 if (priv->sink_state == SINK_STATE_DISCONNECTED) 491 device_set_state(dev, AUDIO_STATE_CONNECTING); 492 break; 493 case HEADSET_STATE_CONNECTED: 494 if (old_state == HEADSET_STATE_CONNECTED || 495 old_state == HEADSET_STATE_PLAY_IN_PROGRESS || 496 old_state == HEADSET_STATE_PLAYING) 497 break; 498 if (dev->auto_connect) { 499 if (!dev->sink) 500 device_set_state(dev, AUDIO_STATE_CONNECTED); 501 else if (priv->sink_state == SINK_STATE_DISCONNECTED) 502 device_set_avdtp_timer(dev); 503 else if (priv->sink_state == SINK_STATE_CONNECTED || 504 priv->sink_state == SINK_STATE_PLAYING) 505 device_set_state(dev, AUDIO_STATE_CONNECTED); 506 } else if (priv->sink_state == SINK_STATE_DISCONNECTED || 507 priv->sink_state == SINK_STATE_CONNECTING) 508 device_set_state(dev, AUDIO_STATE_CONNECTED); 509 break; 510 case HEADSET_STATE_PLAY_IN_PROGRESS: 511 break; 512 case HEADSET_STATE_PLAYING: 513 break; 514 } 515 } 516 517 static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg, 518 void *data) 519 { 520 struct audio_device *dev = data; 521 struct dev_priv *priv = dev->priv; 522 523 if (priv->state == AUDIO_STATE_CONNECTING) 524 return btd_error_in_progress(msg); 525 else if (priv->state == AUDIO_STATE_CONNECTED) 526 return btd_error_already_connected(msg); 527 528 dev->auto_connect = TRUE; 529 530 if (dev->headset) 531 headset_config_stream(dev, FALSE, NULL, NULL); 532 533 if (priv->state != AUDIO_STATE_CONNECTING && dev->sink) { 534 struct avdtp *session = avdtp_get(&dev->src, &dev->dst); 535 536 if (!session) 537 return btd_error_failed(msg, 538 "Failed to get AVDTP session"); 539 540 sink_setup_stream(dev->sink, session); 541 avdtp_unref(session); 542 } 543 544 /* The previous calls should cause a call to the state callback to 545 * indicate AUDIO_STATE_CONNECTING */ 546 if (priv->state != AUDIO_STATE_CONNECTING) 547 return btd_error_failed(msg, "Connect Failed"); 548 549 priv->conn_req = dbus_message_ref(msg); 550 551 return NULL; 552 } 553 554 static DBusMessage *dev_disconnect(DBusConnection *conn, DBusMessage *msg, 555 void *data) 556 { 557 struct audio_device *dev = data; 558 struct dev_priv *priv = dev->priv; 559 560 if (priv->state == AUDIO_STATE_DISCONNECTED) 561 return btd_error_not_connected(msg); 562 563 if (priv->dc_req) 564 return dbus_message_new_method_return(msg); 565 566 priv->dc_req = dbus_message_ref(msg); 567 568 if (dev->control) { 569 device_remove_control_timer(dev); 570 avrcp_disconnect(dev); 571 } 572 573 if (dev->sink && priv->sink_state != SINK_STATE_DISCONNECTED) 574 sink_shutdown(dev->sink); 575 else if (priv->hs_state != HEADSET_STATE_DISCONNECTED) 576 headset_shutdown(dev); 577 else { 578 dbus_message_unref(priv->dc_req); 579 priv->dc_req = NULL; 580 return dbus_message_new_method_return(msg); 581 } 582 583 return NULL; 584 } 585 586 static DBusMessage *dev_get_properties(DBusConnection *conn, DBusMessage *msg, 587 void *data) 588 { 589 struct audio_device *device = data; 590 DBusMessage *reply; 591 DBusMessageIter iter; 592 DBusMessageIter dict; 593 const char *state; 594 595 reply = dbus_message_new_method_return(msg); 596 if (!reply) 597 return NULL; 598 599 dbus_message_iter_init_append(reply, &iter); 600 601 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 602 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 603 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING 604 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); 605 606 /* State */ 607 state = state2str(device->priv->state); 608 if (state) 609 dict_append_entry(&dict, "State", DBUS_TYPE_STRING, &state); 610 611 dbus_message_iter_close_container(&iter, &dict); 612 613 return reply; 614 } 615 616 static GDBusMethodTable dev_methods[] = { 617 { "Connect", "", "", dev_connect, 618 G_DBUS_METHOD_FLAG_ASYNC }, 619 { "Disconnect", "", "", dev_disconnect }, 620 { "GetProperties", "", "a{sv}",dev_get_properties }, 621 { NULL, NULL, NULL, NULL } 622 }; 623 624 static GDBusSignalTable dev_signals[] = { 625 { "PropertyChanged", "sv" }, 626 { NULL, NULL } 627 }; 628 629 struct audio_device *audio_device_register(DBusConnection *conn, 630 struct btd_device *device, 631 const char *path, const bdaddr_t *src, 632 const bdaddr_t *dst) 633 { 634 struct audio_device *dev; 635 636 if (!conn || !path) 637 return NULL; 638 639 dev = g_new0(struct audio_device, 1); 640 641 dev->btd_dev = btd_device_ref(device); 642 dev->path = g_strdup(path); 643 bacpy(&dev->dst, dst); 644 bacpy(&dev->src, src); 645 dev->conn = dbus_connection_ref(conn); 646 dev->priv = g_new0(struct dev_priv, 1); 647 dev->priv->state = AUDIO_STATE_DISCONNECTED; 648 649 if (!g_dbus_register_interface(dev->conn, dev->path, 650 AUDIO_INTERFACE, 651 dev_methods, dev_signals, NULL, 652 dev, NULL)) { 653 error("Unable to register %s on %s", AUDIO_INTERFACE, 654 dev->path); 655 device_free(dev); 656 return NULL; 657 } 658 659 DBG("Registered interface %s on path %s", AUDIO_INTERFACE, 660 dev->path); 661 662 if (sink_callback_id == 0) 663 sink_callback_id = sink_add_state_cb(device_sink_cb, NULL); 664 665 if (avdtp_callback_id == 0) 666 avdtp_callback_id = avdtp_add_state_cb(device_avdtp_cb, NULL); 667 if (avctp_callback_id == 0) 668 avctp_callback_id = avctp_add_state_cb(device_avctp_cb, NULL); 669 670 if (headset_callback_id == 0) 671 headset_callback_id = headset_add_state_cb(device_headset_cb, 672 NULL); 673 674 return dev; 675 } 676 677 gboolean audio_device_is_active(struct audio_device *dev, 678 const char *interface) 679 { 680 if (!interface) { 681 if ((dev->sink || dev->source) && 682 avdtp_is_connected(&dev->src, &dev->dst)) 683 return TRUE; 684 if (dev->headset && headset_is_active(dev)) 685 return TRUE; 686 } else if (!strcmp(interface, AUDIO_SINK_INTERFACE) && dev->sink && 687 avdtp_is_connected(&dev->src, &dev->dst)) 688 return TRUE; 689 else if (!strcmp(interface, AUDIO_SOURCE_INTERFACE) && dev->source && 690 avdtp_is_connected(&dev->src, &dev->dst)) 691 return TRUE; 692 else if (!strcmp(interface, AUDIO_HEADSET_INTERFACE) && dev->headset && 693 headset_is_active(dev)) 694 return TRUE; 695 else if (!strcmp(interface, AUDIO_CONTROL_INTERFACE) && dev->control && 696 control_is_active(dev)) 697 return TRUE; 698 else if (!strcmp(interface, AUDIO_GATEWAY_INTERFACE) && dev->gateway && 699 gateway_is_connected(dev)) 700 return TRUE; 701 702 return FALSE; 703 } 704 705 void audio_device_unregister(struct audio_device *device) 706 { 707 unix_device_removed(device); 708 709 if (device->hs_preauth_id) { 710 g_source_remove(device->hs_preauth_id); 711 device->hs_preauth_id = 0; 712 } 713 714 if (device->headset) 715 headset_unregister(device); 716 717 if (device->gateway) 718 gateway_unregister(device); 719 720 if (device->sink) 721 sink_unregister(device); 722 723 if (device->source) 724 source_unregister(device); 725 726 if (device->control) 727 control_unregister(device); 728 729 g_dbus_unregister_interface(device->conn, device->path, 730 AUDIO_INTERFACE); 731 732 device_free(device); 733 } 734 735 static void auth_cb(DBusError *derr, void *user_data) 736 { 737 struct audio_device *dev = user_data; 738 struct dev_priv *priv = dev->priv; 739 740 if (derr == NULL) 741 priv->authorized = TRUE; 742 743 while (priv->auths) { 744 struct service_auth *auth = priv->auths->data; 745 746 auth->cb(derr, auth->user_data); 747 priv->auths = g_slist_remove(priv->auths, auth); 748 g_free(auth); 749 } 750 } 751 752 static gboolean auth_idle_cb(gpointer user_data) 753 { 754 struct audio_device *dev = user_data; 755 struct dev_priv *priv = dev->priv; 756 757 priv->auth_idle_id = 0; 758 759 auth_cb(NULL, dev); 760 761 return FALSE; 762 } 763 764 static gboolean audio_device_is_connected(struct audio_device *dev) 765 { 766 if (dev->headset) { 767 headset_state_t state = headset_get_state(dev); 768 769 if (state == HEADSET_STATE_CONNECTED || 770 state == HEADSET_STATE_PLAY_IN_PROGRESS || 771 state == HEADSET_STATE_PLAYING) 772 return TRUE; 773 } 774 775 if (dev->sink) { 776 sink_state_t state = sink_get_state(dev); 777 778 if (state == SINK_STATE_CONNECTED || 779 state == SINK_STATE_PLAYING) 780 return TRUE; 781 } 782 783 if (dev->source) { 784 source_state_t state = source_get_state(dev); 785 786 if (state == SOURCE_STATE_CONNECTED || 787 state == SOURCE_STATE_PLAYING) 788 return TRUE; 789 } 790 791 return FALSE; 792 } 793 794 int audio_device_request_authorization(struct audio_device *dev, 795 const char *uuid, service_auth_cb cb, 796 void *user_data) 797 { 798 struct dev_priv *priv = dev->priv; 799 struct service_auth *auth; 800 int err; 801 802 auth = g_try_new0(struct service_auth, 1); 803 if (!auth) 804 return -ENOMEM; 805 806 auth->cb = cb; 807 auth->user_data = user_data; 808 809 priv->auths = g_slist_append(priv->auths, auth); 810 if (g_slist_length(priv->auths) > 1) 811 return 0; 812 813 if (priv->authorized || audio_device_is_connected(dev)) { 814 priv->auth_idle_id = g_idle_add(auth_idle_cb, dev); 815 return 0; 816 } 817 818 err = btd_request_authorization(&dev->src, &dev->dst, uuid, auth_cb, 819 dev); 820 if (err < 0) { 821 priv->auths = g_slist_remove(priv->auths, auth); 822 g_free(auth); 823 } 824 825 return err; 826 } 827 828 int audio_device_cancel_authorization(struct audio_device *dev, 829 authorization_cb cb, void *user_data) 830 { 831 struct dev_priv *priv = dev->priv; 832 GSList *l, *next; 833 834 for (l = priv->auths; l != NULL; l = next) { 835 struct service_auth *auth = l->data; 836 837 next = g_slist_next(l); 838 839 if (cb && auth->cb != cb) 840 continue; 841 842 if (user_data && auth->user_data != user_data) 843 continue; 844 845 priv->auths = g_slist_remove(priv->auths, auth); 846 g_free(auth); 847 } 848 849 if (g_slist_length(priv->auths) == 0) { 850 if (priv->auth_idle_id > 0) { 851 g_source_remove(priv->auth_idle_id); 852 priv->auth_idle_id = 0; 853 } else 854 btd_cancel_authorization(&dev->src, &dev->dst); 855 } 856 857 return 0; 858 } 859 860 void audio_device_set_authorized(struct audio_device *dev, gboolean auth) 861 { 862 struct dev_priv *priv = dev->priv; 863 864 priv->authorized = auth; 865 } 866