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 <errno.h> 30 31 #include <glib.h> 32 #include <gdbus.h> 33 34 #include "../src/adapter.h" 35 #include "../src/dbus-common.h" 36 37 #include "log.h" 38 #include "error.h" 39 #include "device.h" 40 #include "avdtp.h" 41 #include "media.h" 42 #include "transport.h" 43 #include "a2dp.h" 44 #include "headset.h" 45 #include "manager.h" 46 47 #ifndef DBUS_TYPE_UNIX_FD 48 #define DBUS_TYPE_UNIX_FD -1 49 #endif 50 51 #define MEDIA_INTERFACE "org.bluez.Media" 52 #define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint" 53 54 #define REQUEST_TIMEOUT (3 * 1000) /* 3 seconds */ 55 56 struct media_adapter { 57 bdaddr_t src; /* Adapter address */ 58 char *path; /* Adapter path */ 59 DBusConnection *conn; /* Adapter connection */ 60 GSList *endpoints; /* Endpoints list */ 61 }; 62 63 struct endpoint_request { 64 DBusMessage *msg; 65 DBusPendingCall *call; 66 media_endpoint_cb_t cb; 67 void *user_data; 68 }; 69 70 struct media_endpoint { 71 struct a2dp_sep *sep; 72 char *sender; /* Endpoint DBus bus id */ 73 char *path; /* Endpoint object path */ 74 char *uuid; /* Endpoint property UUID */ 75 uint8_t codec; /* Endpoint codec */ 76 uint8_t *capabilities; /* Endpoint property capabilities */ 77 size_t size; /* Endpoint capabilities size */ 78 guint hs_watch; 79 guint watch; 80 struct endpoint_request *request; 81 struct media_transport *transport; 82 struct media_adapter *adapter; 83 }; 84 85 static GSList *adapters = NULL; 86 87 static void endpoint_request_free(struct endpoint_request *request) 88 { 89 if (request->call) 90 dbus_pending_call_unref(request->call); 91 92 dbus_message_unref(request->msg); 93 g_free(request); 94 } 95 96 static void media_endpoint_cancel(struct media_endpoint *endpoint) 97 { 98 struct endpoint_request *request = endpoint->request; 99 100 if (request->call) 101 dbus_pending_call_cancel(request->call); 102 103 endpoint_request_free(request); 104 endpoint->request = NULL; 105 } 106 107 static void media_endpoint_remove(struct media_endpoint *endpoint) 108 { 109 struct media_adapter *adapter = endpoint->adapter; 110 111 if (g_slist_find(adapter->endpoints, endpoint) == NULL) 112 return; 113 114 info("Endpoint unregistered: sender=%s path=%s", endpoint->sender, 115 endpoint->path); 116 117 adapter->endpoints = g_slist_remove(adapter->endpoints, endpoint); 118 119 if (endpoint->sep) 120 a2dp_remove_sep(endpoint->sep); 121 122 if (endpoint->hs_watch) 123 headset_remove_state_cb(endpoint->hs_watch); 124 125 if (endpoint->request) 126 media_endpoint_cancel(endpoint); 127 128 if (endpoint->transport) 129 media_transport_destroy(endpoint->transport); 130 131 g_dbus_remove_watch(adapter->conn, endpoint->watch); 132 g_free(endpoint->capabilities); 133 g_free(endpoint->sender); 134 g_free(endpoint->path); 135 g_free(endpoint->uuid); 136 g_free(endpoint); 137 } 138 139 static void media_endpoint_exit(DBusConnection *connection, void *user_data) 140 { 141 struct media_endpoint *endpoint = user_data; 142 143 endpoint->watch = 0; 144 media_endpoint_remove(endpoint); 145 } 146 147 static void headset_setconf_cb(struct media_endpoint *endpoint, void *ret, 148 int size, void *user_data) 149 { 150 struct audio_device *dev = user_data; 151 152 if (ret != NULL) 153 return; 154 155 headset_set_state(dev, HEADSET_STATE_DISCONNECTED); 156 } 157 158 static void headset_state_changed(struct audio_device *dev, 159 headset_state_t old_state, 160 headset_state_t new_state, 161 void *user_data) 162 { 163 struct media_endpoint *endpoint = user_data; 164 165 DBG(""); 166 167 switch (new_state) { 168 case HEADSET_STATE_DISCONNECTED: 169 media_endpoint_clear_configuration(endpoint); 170 break; 171 case HEADSET_STATE_CONNECTING: 172 media_endpoint_set_configuration(endpoint, dev, NULL, 0, 173 headset_setconf_cb, dev); 174 break; 175 case HEADSET_STATE_CONNECTED: 176 break; 177 case HEADSET_STATE_PLAY_IN_PROGRESS: 178 break; 179 case HEADSET_STATE_PLAYING: 180 break; 181 } 182 } 183 184 static struct media_endpoint *media_endpoint_create(struct media_adapter *adapter, 185 const char *sender, 186 const char *path, 187 const char *uuid, 188 gboolean delay_reporting, 189 uint8_t codec, 190 uint8_t *capabilities, 191 int size, 192 int *err) 193 { 194 struct media_endpoint *endpoint; 195 196 endpoint = g_new0(struct media_endpoint, 1); 197 endpoint->sender = g_strdup(sender); 198 endpoint->path = g_strdup(path); 199 endpoint->uuid = g_strdup(uuid); 200 endpoint->codec = codec; 201 202 if (size > 0) { 203 endpoint->capabilities = g_new(uint8_t, size); 204 memcpy(endpoint->capabilities, capabilities, size); 205 endpoint->size = size; 206 } 207 208 endpoint->adapter = adapter; 209 210 if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0) { 211 endpoint->sep = a2dp_add_sep(&adapter->src, 212 AVDTP_SEP_TYPE_SOURCE, codec, 213 delay_reporting, endpoint, err); 214 if (endpoint->sep == NULL) 215 goto failed; 216 } else if (strcasecmp(uuid, A2DP_SINK_UUID) == 0) { 217 endpoint->sep = a2dp_add_sep(&adapter->src, 218 AVDTP_SEP_TYPE_SINK, codec, 219 delay_reporting, endpoint, err); 220 if (endpoint->sep == NULL) 221 goto failed; 222 } else if (strcasecmp(uuid, HFP_AG_UUID) == 0 || 223 g_strcmp0(uuid, HSP_AG_UUID) == 0) { 224 struct audio_device *dev; 225 226 endpoint->hs_watch = headset_add_state_cb(headset_state_changed, 227 endpoint); 228 dev = manager_find_device(NULL, &adapter->src, BDADDR_ANY, 229 AUDIO_HEADSET_INTERFACE, TRUE); 230 if (dev) 231 media_endpoint_set_configuration(endpoint, dev, NULL, 232 0, headset_setconf_cb, 233 dev); 234 } else { 235 if (err) 236 *err = -EINVAL; 237 goto failed; 238 } 239 240 endpoint->watch = g_dbus_add_disconnect_watch(adapter->conn, sender, 241 media_endpoint_exit, endpoint, 242 NULL); 243 244 adapter->endpoints = g_slist_append(adapter->endpoints, endpoint); 245 info("Endpoint registered: sender=%s path=%s", sender, path); 246 247 if (err) 248 *err = 0; 249 return endpoint; 250 251 failed: 252 g_free(endpoint); 253 return NULL; 254 } 255 256 static struct media_endpoint *media_adapter_find_endpoint( 257 struct media_adapter *adapter, 258 const char *sender, 259 const char *path, 260 const char *uuid) 261 { 262 GSList *l; 263 264 for (l = adapter->endpoints; l; l = l->next) { 265 struct media_endpoint *endpoint = l->data; 266 267 if (sender && g_strcmp0(endpoint->sender, sender) != 0) 268 continue; 269 270 if (path && g_strcmp0(endpoint->path, path) != 0) 271 continue; 272 273 if (uuid && g_strcmp0(endpoint->uuid, uuid) != 0) 274 continue; 275 276 return endpoint; 277 } 278 279 return NULL; 280 } 281 282 const char *media_endpoint_get_sender(struct media_endpoint *endpoint) 283 { 284 return endpoint->sender; 285 } 286 287 static int parse_properties(DBusMessageIter *props, const char **uuid, 288 gboolean *delay_reporting, uint8_t *codec, 289 uint8_t **capabilities, int *size) 290 { 291 gboolean has_uuid = FALSE; 292 gboolean has_codec = FALSE; 293 294 while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) { 295 const char *key; 296 DBusMessageIter value, entry; 297 int var; 298 299 dbus_message_iter_recurse(props, &entry); 300 dbus_message_iter_get_basic(&entry, &key); 301 302 dbus_message_iter_next(&entry); 303 dbus_message_iter_recurse(&entry, &value); 304 305 var = dbus_message_iter_get_arg_type(&value); 306 if (strcasecmp(key, "UUID") == 0) { 307 if (var != DBUS_TYPE_STRING) 308 return -EINVAL; 309 dbus_message_iter_get_basic(&value, uuid); 310 has_uuid = TRUE; 311 } else if (strcasecmp(key, "Codec") == 0) { 312 if (var != DBUS_TYPE_BYTE) 313 return -EINVAL; 314 dbus_message_iter_get_basic(&value, codec); 315 has_codec = TRUE; 316 } else if (strcasecmp(key, "DelayReporting") == 0) { 317 if (var != DBUS_TYPE_BOOLEAN) 318 return -EINVAL; 319 dbus_message_iter_get_basic(&value, delay_reporting); 320 } else if (strcasecmp(key, "Capabilities") == 0) { 321 DBusMessageIter array; 322 323 if (var != DBUS_TYPE_ARRAY) 324 return -EINVAL; 325 326 dbus_message_iter_recurse(&value, &array); 327 dbus_message_iter_get_fixed_array(&array, capabilities, 328 size); 329 } 330 331 dbus_message_iter_next(props); 332 } 333 334 return (has_uuid && has_codec) ? 0 : -EINVAL; 335 } 336 337 static DBusMessage *register_endpoint(DBusConnection *conn, DBusMessage *msg, 338 void *data) 339 { 340 struct media_adapter *adapter = data; 341 DBusMessageIter args, props; 342 const char *sender, *path, *uuid; 343 gboolean delay_reporting = FALSE; 344 uint8_t codec; 345 uint8_t *capabilities; 346 int size = 0; 347 int err; 348 349 sender = dbus_message_get_sender(msg); 350 351 dbus_message_iter_init(msg, &args); 352 353 dbus_message_iter_get_basic(&args, &path); 354 dbus_message_iter_next(&args); 355 356 if (media_adapter_find_endpoint(adapter, sender, path, NULL) != NULL) 357 return btd_error_already_exists(msg); 358 359 dbus_message_iter_recurse(&args, &props); 360 if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY) 361 return btd_error_invalid_args(msg); 362 363 if (parse_properties(&props, &uuid, &delay_reporting, &codec, 364 &capabilities, &size) < 0) 365 return btd_error_invalid_args(msg); 366 367 if (media_endpoint_create(adapter, sender, path, uuid, delay_reporting, 368 codec, capabilities, size, &err) == FALSE) { 369 if (err == -EPROTONOSUPPORT) 370 return btd_error_not_supported(msg); 371 else 372 return btd_error_invalid_args(msg); 373 } 374 375 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); 376 } 377 378 static DBusMessage *unregister_endpoint(DBusConnection *conn, DBusMessage *msg, 379 void *data) 380 { 381 struct media_adapter *adapter = data; 382 struct media_endpoint *endpoint; 383 const char *sender, *path; 384 385 if (!dbus_message_get_args(msg, NULL, 386 DBUS_TYPE_OBJECT_PATH, &path, 387 DBUS_TYPE_INVALID)) 388 return NULL; 389 390 sender = dbus_message_get_sender(msg); 391 392 endpoint = media_adapter_find_endpoint(adapter, sender, path, NULL); 393 if (endpoint == NULL) 394 return btd_error_does_not_exist(msg); 395 396 media_endpoint_remove(endpoint); 397 398 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); 399 } 400 401 static GDBusMethodTable media_methods[] = { 402 { "RegisterEndpoint", "oa{sv}", "", register_endpoint }, 403 { "UnregisterEndpoint", "o", "", unregister_endpoint }, 404 { }, 405 }; 406 407 static void path_free(void *data) 408 { 409 struct media_adapter *adapter = data; 410 411 g_slist_foreach(adapter->endpoints, (GFunc) media_endpoint_release, 412 NULL); 413 g_slist_free(adapter->endpoints); 414 415 dbus_connection_unref(adapter->conn); 416 417 adapters = g_slist_remove(adapters, adapter); 418 419 g_free(adapter->path); 420 g_free(adapter); 421 } 422 423 int media_register(DBusConnection *conn, const char *path, const bdaddr_t *src) 424 { 425 struct media_adapter *adapter; 426 427 if (DBUS_TYPE_UNIX_FD < 0) 428 return -EPERM; 429 430 adapter = g_new0(struct media_adapter, 1); 431 adapter->conn = dbus_connection_ref(conn); 432 bacpy(&adapter->src, src); 433 adapter->path = g_strdup(path); 434 435 if (!g_dbus_register_interface(conn, path, MEDIA_INTERFACE, 436 media_methods, NULL, NULL, 437 adapter, path_free)) { 438 error("D-Bus failed to register %s path", path); 439 path_free(adapter); 440 return -1; 441 } 442 443 adapters = g_slist_append(adapters, adapter); 444 445 return 0; 446 } 447 448 void media_unregister(const char *path) 449 { 450 GSList *l; 451 452 for (l = adapters; l; l = l->next) { 453 struct media_adapter *adapter = l->data; 454 455 if (g_strcmp0(path, adapter->path) == 0) { 456 g_dbus_unregister_interface(adapter->conn, path, 457 MEDIA_INTERFACE); 458 return; 459 } 460 } 461 } 462 463 size_t media_endpoint_get_capabilities(struct media_endpoint *endpoint, 464 uint8_t **capabilities) 465 { 466 *capabilities = endpoint->capabilities; 467 return endpoint->size; 468 } 469 470 static void endpoint_reply(DBusPendingCall *call, void *user_data) 471 { 472 struct media_endpoint *endpoint = user_data; 473 struct endpoint_request *request = endpoint->request; 474 DBusMessage *reply; 475 DBusError err; 476 gboolean value; 477 void *ret = NULL; 478 int size = -1; 479 480 /* steal_reply will always return non-NULL since the callback 481 * is only called after a reply has been received */ 482 reply = dbus_pending_call_steal_reply(call); 483 484 dbus_error_init(&err); 485 if (dbus_set_error_from_message(&err, reply)) { 486 error("Endpoint replied with an error: %s", 487 err.name); 488 489 /* Clear endpoint configuration in case of NO_REPLY error */ 490 if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) { 491 if (request->cb) 492 request->cb(endpoint, NULL, size, 493 request->user_data); 494 media_endpoint_clear_configuration(endpoint); 495 dbus_message_unref(reply); 496 dbus_error_free(&err); 497 return; 498 } 499 500 dbus_error_free(&err); 501 goto done; 502 } 503 504 dbus_error_init(&err); 505 if (dbus_message_is_method_call(request->msg, MEDIA_ENDPOINT_INTERFACE, 506 "SelectConfiguration")) { 507 DBusMessageIter args, array; 508 uint8_t *configuration; 509 510 dbus_message_iter_init(reply, &args); 511 512 dbus_message_iter_recurse(&args, &array); 513 514 dbus_message_iter_get_fixed_array(&array, &configuration, &size); 515 516 ret = configuration; 517 goto done; 518 } else if (!dbus_message_get_args(reply, &err, DBUS_TYPE_INVALID)) { 519 error("Wrong reply signature: %s", err.message); 520 dbus_error_free(&err); 521 goto done; 522 } 523 524 size = 1; 525 value = TRUE; 526 ret = &value; 527 528 done: 529 dbus_message_unref(reply); 530 531 if (request->cb) 532 request->cb(endpoint, ret, size, request->user_data); 533 534 endpoint_request_free(request); 535 endpoint->request = NULL; 536 } 537 538 static gboolean media_endpoint_async_call(DBusConnection *conn, 539 DBusMessage *msg, 540 struct media_endpoint *endpoint, 541 media_endpoint_cb_t cb, 542 void *user_data) 543 { 544 struct endpoint_request *request; 545 546 if (endpoint->request) 547 return FALSE; 548 549 request = g_new0(struct endpoint_request, 1); 550 551 /* Timeout should be less than avdtp request timeout (4 seconds) */ 552 if (dbus_connection_send_with_reply(conn, msg, &request->call, 553 REQUEST_TIMEOUT) == FALSE) { 554 error("D-Bus send failed"); 555 g_free(request); 556 return FALSE; 557 } 558 559 dbus_pending_call_set_notify(request->call, endpoint_reply, endpoint, NULL); 560 561 request->msg = msg; 562 request->cb = cb; 563 request->user_data = user_data; 564 endpoint->request = request; 565 566 DBG("Calling %s: name = %s path = %s", dbus_message_get_member(msg), 567 dbus_message_get_destination(msg), 568 dbus_message_get_path(msg)); 569 570 return TRUE; 571 } 572 573 gboolean media_endpoint_set_configuration(struct media_endpoint *endpoint, 574 struct audio_device *device, 575 uint8_t *configuration, size_t size, 576 media_endpoint_cb_t cb, 577 void *user_data) 578 { 579 DBusConnection *conn; 580 DBusMessage *msg; 581 const char *path; 582 DBusMessageIter iter; 583 584 if (endpoint->transport != NULL || endpoint->request != NULL) 585 return FALSE; 586 587 conn = endpoint->adapter->conn; 588 589 endpoint->transport = media_transport_create(conn, endpoint, device, 590 configuration, size); 591 if (endpoint->transport == NULL) 592 return FALSE; 593 594 msg = dbus_message_new_method_call(endpoint->sender, endpoint->path, 595 MEDIA_ENDPOINT_INTERFACE, 596 "SetConfiguration"); 597 if (msg == NULL) { 598 error("Couldn't allocate D-Bus message"); 599 return FALSE; 600 } 601 602 dbus_message_iter_init_append(msg, &iter); 603 604 path = media_transport_get_path(endpoint->transport); 605 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path); 606 607 transport_get_properties(endpoint->transport, &iter); 608 609 return media_endpoint_async_call(conn, msg, endpoint, cb, user_data); 610 } 611 612 gboolean media_endpoint_select_configuration(struct media_endpoint *endpoint, 613 uint8_t *capabilities, 614 size_t length, 615 media_endpoint_cb_t cb, 616 void *user_data) 617 { 618 DBusConnection *conn; 619 DBusMessage *msg; 620 621 if (endpoint->request != NULL) 622 return FALSE; 623 624 conn = endpoint->adapter->conn; 625 626 msg = dbus_message_new_method_call(endpoint->sender, endpoint->path, 627 MEDIA_ENDPOINT_INTERFACE, 628 "SelectConfiguration"); 629 if (msg == NULL) { 630 error("Couldn't allocate D-Bus message"); 631 return FALSE; 632 } 633 634 dbus_message_append_args(msg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 635 &capabilities, length, 636 DBUS_TYPE_INVALID); 637 638 return media_endpoint_async_call(conn, msg, endpoint, cb, user_data); 639 } 640 641 void media_endpoint_clear_configuration(struct media_endpoint *endpoint) 642 { 643 DBusConnection *conn; 644 DBusMessage *msg; 645 const char *path; 646 647 if (endpoint->transport == NULL) 648 return; 649 650 if (endpoint->request) 651 media_endpoint_cancel(endpoint); 652 653 conn = endpoint->adapter->conn; 654 655 msg = dbus_message_new_method_call(endpoint->sender, endpoint->path, 656 MEDIA_ENDPOINT_INTERFACE, 657 "ClearConfiguration"); 658 if (msg == NULL) { 659 error("Couldn't allocate D-Bus message"); 660 goto done; 661 } 662 663 path = media_transport_get_path(endpoint->transport); 664 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path, 665 DBUS_TYPE_INVALID); 666 g_dbus_send_message(conn, msg); 667 done: 668 media_transport_destroy(endpoint->transport); 669 endpoint->transport = NULL; 670 } 671 672 void media_endpoint_release(struct media_endpoint *endpoint) 673 { 674 DBusMessage *msg; 675 676 DBG("sender=%s path=%s", endpoint->sender, endpoint->path); 677 678 /* already exit */ 679 if (endpoint->watch == 0) 680 return; 681 682 msg = dbus_message_new_method_call(endpoint->sender, endpoint->path, 683 MEDIA_ENDPOINT_INTERFACE, 684 "Release"); 685 if (msg == NULL) { 686 error("Couldn't allocate D-Bus message"); 687 return; 688 } 689 690 g_dbus_send_message(endpoint->adapter->conn, msg); 691 692 media_endpoint_remove(endpoint); 693 } 694 695 struct a2dp_sep *media_endpoint_get_sep(struct media_endpoint *endpoint) 696 { 697 return endpoint->sep; 698 } 699 700 const char *media_endpoint_get_uuid(struct media_endpoint *endpoint) 701 { 702 return endpoint->uuid; 703 } 704 705 uint8_t media_endpoint_get_codec(struct media_endpoint *endpoint) 706 { 707 return endpoint->codec; 708 } 709 710 struct media_transport *media_endpoint_get_transport( 711 struct media_endpoint *endpoint) 712 { 713 return endpoint->transport; 714 } 715