1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos. 6 * Authors: 7 * Santiago Carot Nemesio <sancane at gmail.com> 8 * Jose Antonio Santos-Cadenas <santoscadenas at gmail.com> 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 #include <gdbus.h> 27 28 #include <adapter.h> 29 #include <device.h> 30 #include <stdint.h> 31 #include <hdp_types.h> 32 #include <hdp_util.h> 33 #include <mcap.h> 34 #include <hdp.h> 35 36 #include <sdpd.h> 37 #include <bluetooth/sdp_lib.h> 38 #include <glib-helper.h> 39 40 #include <btio.h> 41 #include <mcap_lib.h> 42 43 #include <log.h> 44 45 typedef gboolean (*parse_item_f)(DBusMessageIter *iter, gpointer user_data, 46 GError **err); 47 48 struct dict_entry_func { 49 char *key; 50 parse_item_f func; 51 }; 52 53 struct get_mdep_data { 54 struct hdp_application *app; 55 gpointer data; 56 hdp_continue_mdep_f func; 57 GDestroyNotify destroy; 58 }; 59 60 struct conn_mcl_data { 61 int refs; 62 gpointer data; 63 hdp_continue_proc_f func; 64 GDestroyNotify destroy; 65 struct hdp_device *dev; 66 }; 67 68 struct get_dcpsm_data { 69 gpointer data; 70 hdp_continue_dcpsm_f func; 71 GDestroyNotify destroy; 72 }; 73 74 static gboolean parse_dict_entry(struct dict_entry_func dict_context[], 75 DBusMessageIter *iter, 76 GError **err, 77 gpointer user_data) 78 { 79 DBusMessageIter entry; 80 char *key; 81 int ctype, i; 82 struct dict_entry_func df; 83 84 dbus_message_iter_recurse(iter, &entry); 85 ctype = dbus_message_iter_get_arg_type(&entry); 86 if (ctype != DBUS_TYPE_STRING) { 87 g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR, 88 "Dictionary entries should have a string as key"); 89 return FALSE; 90 } 91 92 dbus_message_iter_get_basic(&entry, &key); 93 dbus_message_iter_next(&entry); 94 /* Find function and call it */ 95 for (i = 0, df = dict_context[0]; df.key; i++, df = dict_context[i]) { 96 if (g_ascii_strcasecmp(df.key, key) == 0) 97 return df.func(&entry, user_data, err); 98 } 99 100 g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR, 101 "No function found for parsing value for key %s", key); 102 return FALSE; 103 } 104 105 static gboolean parse_dict(struct dict_entry_func dict_context[], 106 DBusMessageIter *iter, 107 GError **err, 108 gpointer user_data) 109 { 110 int ctype; 111 DBusMessageIter dict; 112 113 ctype = dbus_message_iter_get_arg_type(iter); 114 if (ctype != DBUS_TYPE_ARRAY) { 115 g_set_error(err, HDP_ERROR, HDP_DIC_PARSE_ERROR, 116 "Dictionary should be an array"); 117 return FALSE; 118 } 119 120 dbus_message_iter_recurse(iter, &dict); 121 while ((ctype = dbus_message_iter_get_arg_type(&dict)) != 122 DBUS_TYPE_INVALID) { 123 if (ctype != DBUS_TYPE_DICT_ENTRY) { 124 g_set_error(err, HDP_ERROR, HDP_DIC_PARSE_ERROR, 125 "Dictionary array should " 126 "contain dict entries"); 127 return FALSE; 128 } 129 130 /* Start parsing entry */ 131 if (!parse_dict_entry(dict_context, &dict, err, 132 user_data)) 133 return FALSE; 134 /* Finish entry parsing */ 135 136 dbus_message_iter_next(&dict); 137 } 138 139 return TRUE; 140 } 141 142 static gboolean parse_data_type(DBusMessageIter *iter, gpointer data, 143 GError **err) 144 { 145 struct hdp_application *app = data; 146 DBusMessageIter *value; 147 int ctype; 148 149 ctype = dbus_message_iter_get_arg_type(iter); 150 value = iter; 151 if (ctype == DBUS_TYPE_VARIANT) { 152 DBusMessageIter variant; 153 154 /* Get value inside the variable */ 155 dbus_message_iter_recurse(iter, &variant); 156 ctype = dbus_message_iter_get_arg_type(&variant); 157 value = &variant; 158 } 159 160 if (ctype != DBUS_TYPE_UINT16) { 161 g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR, 162 "Final value for data type should be uint16"); 163 return FALSE; 164 } 165 166 dbus_message_iter_get_basic(value, &app->data_type); 167 app->data_type_set = TRUE; 168 return TRUE; 169 } 170 171 static gboolean parse_role(DBusMessageIter *iter, gpointer data, GError **err) 172 { 173 struct hdp_application *app = data; 174 DBusMessageIter *string; 175 int ctype; 176 const char *role; 177 178 ctype = dbus_message_iter_get_arg_type(iter); 179 if (ctype == DBUS_TYPE_VARIANT) { 180 DBusMessageIter value; 181 182 /* Get value inside the variable */ 183 dbus_message_iter_recurse(iter, &value); 184 ctype = dbus_message_iter_get_arg_type(&value); 185 string = &value; 186 } else { 187 string = iter; 188 } 189 190 if (ctype != DBUS_TYPE_STRING) { 191 g_set_error(err, HDP_ERROR, HDP_UNSPECIFIED_ERROR, 192 "Value data spec should be variable or string"); 193 return FALSE; 194 } 195 196 dbus_message_iter_get_basic(string, &role); 197 if (g_ascii_strcasecmp(role, HDP_SINK_ROLE_AS_STRING) == 0) { 198 app->role = HDP_SINK; 199 } else if (g_ascii_strcasecmp(role, HDP_SOURCE_ROLE_AS_STRING) == 0) { 200 app->role = HDP_SOURCE; 201 } else { 202 g_set_error(err, HDP_ERROR, HDP_UNSPECIFIED_ERROR, 203 "Role value should be \"source\" or \"sink\""); 204 return FALSE; 205 } 206 207 app->role_set = TRUE; 208 209 return TRUE; 210 } 211 212 static gboolean parse_desc(DBusMessageIter *iter, gpointer data, GError **err) 213 { 214 struct hdp_application *app = data; 215 DBusMessageIter *string; 216 int ctype; 217 const char *desc; 218 219 ctype = dbus_message_iter_get_arg_type(iter); 220 if (ctype == DBUS_TYPE_VARIANT) { 221 DBusMessageIter variant; 222 223 /* Get value inside the variable */ 224 dbus_message_iter_recurse(iter, &variant); 225 ctype = dbus_message_iter_get_arg_type(&variant); 226 string = &variant; 227 } else { 228 string = iter; 229 } 230 231 if (ctype != DBUS_TYPE_STRING) { 232 g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR, 233 "Value data spec should be variable or string"); 234 return FALSE; 235 } 236 237 dbus_message_iter_get_basic(string, &desc); 238 app->description = g_strdup(desc); 239 return TRUE; 240 } 241 242 static gboolean parse_chan_type(DBusMessageIter *iter, gpointer data, 243 GError **err) 244 { 245 struct hdp_application *app = data; 246 DBusMessageIter *value; 247 char *chan_type; 248 int ctype; 249 250 ctype = dbus_message_iter_get_arg_type(iter); 251 value = iter; 252 if (ctype == DBUS_TYPE_VARIANT) { 253 DBusMessageIter variant; 254 255 /* Get value inside the variable */ 256 dbus_message_iter_recurse(iter, &variant); 257 ctype = dbus_message_iter_get_arg_type(&variant); 258 value = &variant; 259 } 260 261 if (ctype != DBUS_TYPE_STRING) { 262 g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR, 263 "Final value for channel type should be an string"); 264 return FALSE; 265 } 266 267 dbus_message_iter_get_basic(value, &chan_type); 268 269 if (g_ascii_strcasecmp("Reliable", chan_type) == 0) 270 app->chan_type = HDP_RELIABLE_DC; 271 else if (g_ascii_strcasecmp("Streaming", chan_type) == 0) 272 app->chan_type = HDP_STREAMING_DC; 273 else { 274 g_set_error(err, HDP_ERROR, HDP_DIC_ENTRY_PARSE_ERROR, 275 "Invalid value for data type"); 276 return FALSE; 277 } 278 279 app->chan_type_set = TRUE; 280 281 return TRUE; 282 } 283 284 static struct dict_entry_func dict_parser[] = { 285 {"DataType", parse_data_type}, 286 {"Role", parse_role}, 287 {"Description", parse_desc}, 288 {"ChannelType", parse_chan_type}, 289 {NULL, NULL} 290 }; 291 292 struct hdp_application *hdp_get_app_config(DBusMessageIter *iter, GError **err) 293 { 294 struct hdp_application *app; 295 296 app = g_new0(struct hdp_application, 1); 297 app->ref = 1; 298 if (!parse_dict(dict_parser, iter, err, app)) 299 goto fail; 300 if (!app->data_type_set || !app->role_set) { 301 g_set_error(err, HDP_ERROR, HDP_DIC_PARSE_ERROR, 302 "Mandatory fields aren't set"); 303 goto fail; 304 } 305 return app; 306 307 fail: 308 hdp_application_unref(app); 309 return NULL; 310 } 311 312 static gboolean is_app_role(GSList *app_list, HdpRole role) 313 { 314 GSList *l; 315 316 for (l = app_list; l; l = l->next) { 317 struct hdp_application *app = l->data; 318 319 if (app->role == role) 320 return TRUE; 321 } 322 323 return FALSE; 324 } 325 326 static gboolean set_sdp_services_uuid(sdp_record_t *record, HdpRole role) 327 { 328 uuid_t svc_uuid_source, svc_uuid_sink; 329 sdp_list_t *svc_list = NULL; 330 331 sdp_uuid16_create(&svc_uuid_sink, HDP_SINK_SVCLASS_ID); 332 sdp_uuid16_create(&svc_uuid_source, HDP_SOURCE_SVCLASS_ID); 333 334 sdp_get_service_classes(record, &svc_list); 335 336 if (role == HDP_SOURCE) { 337 if (!sdp_list_find(svc_list, &svc_uuid_source, sdp_uuid_cmp)) 338 svc_list = sdp_list_append(svc_list, &svc_uuid_source); 339 } else if (role == HDP_SINK) { 340 if (!sdp_list_find(svc_list, &svc_uuid_sink, sdp_uuid_cmp)) 341 svc_list = sdp_list_append(svc_list, &svc_uuid_sink); 342 } 343 344 if (sdp_set_service_classes(record, svc_list) < 0) { 345 sdp_list_free(svc_list, NULL); 346 return FALSE; 347 } 348 349 sdp_list_free(svc_list, NULL); 350 351 return TRUE; 352 } 353 354 static gboolean register_service_protocols(struct hdp_adapter *adapter, 355 sdp_record_t *sdp_record) 356 { 357 gboolean ret; 358 uuid_t l2cap_uuid, mcap_c_uuid; 359 sdp_list_t *l2cap_list, *proto_list = NULL, *mcap_list = NULL; 360 sdp_list_t *access_proto_list = NULL; 361 sdp_data_t *psm = NULL, *mcap_ver = NULL; 362 uint16_t version = MCAP_VERSION; 363 364 /* set l2cap information */ 365 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 366 l2cap_list = sdp_list_append(NULL, &l2cap_uuid); 367 if (!l2cap_list) { 368 ret = FALSE; 369 goto end; 370 } 371 372 psm = sdp_data_alloc(SDP_UINT16, &adapter->ccpsm); 373 if (!psm) { 374 ret = FALSE; 375 goto end; 376 } 377 378 if (!sdp_list_append(l2cap_list, psm)) { 379 ret = FALSE; 380 goto end; 381 } 382 383 proto_list = sdp_list_append(NULL, l2cap_list); 384 if (!proto_list) { 385 ret = FALSE; 386 goto end; 387 } 388 389 /* set mcap information */ 390 sdp_uuid16_create(&mcap_c_uuid, MCAP_CTRL_UUID); 391 mcap_list = sdp_list_append(NULL, &mcap_c_uuid); 392 if (!mcap_list) { 393 ret = FALSE; 394 goto end; 395 } 396 397 mcap_ver = sdp_data_alloc(SDP_UINT16, &version); 398 if (!mcap_ver) { 399 ret = FALSE; 400 goto end; 401 } 402 403 if (!sdp_list_append(mcap_list, mcap_ver)) { 404 ret = FALSE; 405 goto end; 406 } 407 408 if (!sdp_list_append(proto_list, mcap_list)) { 409 ret = FALSE; 410 goto end; 411 } 412 413 /* attach protocol information to service record */ 414 access_proto_list = sdp_list_append(NULL, proto_list); 415 if (!access_proto_list) { 416 ret = FALSE; 417 goto end; 418 } 419 420 if (sdp_set_access_protos(sdp_record, access_proto_list) < 0) { 421 ret = FALSE; 422 goto end; 423 } 424 ret = TRUE; 425 426 end: 427 if (l2cap_list) 428 sdp_list_free(l2cap_list, NULL); 429 if (mcap_list) 430 sdp_list_free(mcap_list, NULL); 431 if (proto_list) 432 sdp_list_free(proto_list, NULL); 433 if (access_proto_list) 434 sdp_list_free(access_proto_list, NULL); 435 if (psm) 436 sdp_data_free(psm); 437 if (mcap_ver) 438 sdp_data_free(mcap_ver); 439 440 return ret; 441 } 442 443 static gboolean register_service_profiles(sdp_record_t *sdp_record) 444 { 445 gboolean ret; 446 sdp_list_t *profile_list; 447 sdp_profile_desc_t hdp_profile; 448 449 /* set hdp information */ 450 sdp_uuid16_create(&hdp_profile.uuid, HDP_SVCLASS_ID); 451 hdp_profile.version = HDP_VERSION; 452 profile_list = sdp_list_append(NULL, &hdp_profile); 453 if (!profile_list) 454 return FALSE; 455 456 /* set profile descriptor list */ 457 if (sdp_set_profile_descs(sdp_record, profile_list) < 0) 458 ret = FALSE; 459 else 460 ret = TRUE; 461 462 sdp_list_free(profile_list, NULL); 463 464 return ret; 465 } 466 467 static gboolean register_service_additional_protocols( 468 struct hdp_adapter *adapter, 469 sdp_record_t *sdp_record) 470 { 471 gboolean ret; 472 uuid_t l2cap_uuid, mcap_d_uuid; 473 sdp_list_t *l2cap_list, *proto_list = NULL, *mcap_list = NULL; 474 sdp_list_t *access_proto_list = NULL; 475 sdp_data_t *psm = NULL; 476 477 /* set l2cap information */ 478 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 479 l2cap_list = sdp_list_append(NULL, &l2cap_uuid); 480 if (!l2cap_list) { 481 ret = FALSE; 482 goto end; 483 } 484 485 psm = sdp_data_alloc(SDP_UINT16, &adapter->dcpsm); 486 if (!psm) { 487 ret = FALSE; 488 goto end; 489 } 490 491 if (!sdp_list_append(l2cap_list, psm)) { 492 ret = FALSE; 493 goto end; 494 } 495 496 proto_list = sdp_list_append(NULL, l2cap_list); 497 if (!proto_list) { 498 ret = FALSE; 499 goto end; 500 } 501 502 /* set mcap information */ 503 sdp_uuid16_create(&mcap_d_uuid, MCAP_DATA_UUID); 504 mcap_list = sdp_list_append(NULL, &mcap_d_uuid); 505 if (!mcap_list) { 506 ret = FALSE; 507 goto end; 508 } 509 510 if (!sdp_list_append(proto_list, mcap_list)) { 511 ret = FALSE; 512 goto end; 513 } 514 515 /* attach protocol information to service record */ 516 access_proto_list = sdp_list_append(NULL, proto_list); 517 if (!access_proto_list) { 518 ret = FALSE; 519 goto end; 520 } 521 522 if (sdp_set_add_access_protos(sdp_record, access_proto_list) < 0) 523 ret = FALSE; 524 else 525 ret = TRUE; 526 527 end: 528 if (l2cap_list) 529 sdp_list_free(l2cap_list, NULL); 530 if (mcap_list) 531 sdp_list_free(mcap_list, NULL); 532 if (proto_list) 533 sdp_list_free(proto_list, NULL); 534 if (access_proto_list) 535 sdp_list_free(access_proto_list, NULL); 536 if (psm) 537 sdp_data_free(psm); 538 539 return ret; 540 } 541 542 static sdp_list_t *app_to_sdplist(struct hdp_application *app) 543 { 544 sdp_data_t *mdepid, 545 *dtype = NULL, 546 *role = NULL, 547 *desc = NULL; 548 sdp_list_t *f_list = NULL; 549 550 mdepid = sdp_data_alloc(SDP_UINT8, &app->id); 551 if (!mdepid) 552 return NULL; 553 554 dtype = sdp_data_alloc(SDP_UINT16, &app->data_type); 555 if (!dtype) 556 goto fail; 557 558 role = sdp_data_alloc(SDP_UINT8, &app->role); 559 if (!role) 560 goto fail; 561 562 if (app->description) { 563 desc = sdp_data_alloc(SDP_TEXT_STR8, app->description); 564 if (!desc) 565 goto fail; 566 } 567 568 f_list = sdp_list_append(NULL, mdepid); 569 if (!f_list) 570 goto fail; 571 572 if (!sdp_list_append(f_list, dtype)) 573 goto fail; 574 575 if (!sdp_list_append(f_list, role)) 576 goto fail; 577 578 if (desc) 579 if (!sdp_list_append(f_list, desc)) 580 goto fail; 581 582 return f_list; 583 584 fail: 585 if (f_list) 586 sdp_list_free(f_list, NULL); 587 if (mdepid) 588 sdp_data_free(mdepid); 589 if (dtype) 590 sdp_data_free(dtype); 591 if (role) 592 sdp_data_free(role); 593 if (desc) 594 sdp_data_free(desc); 595 596 return NULL; 597 } 598 599 static gboolean register_features(struct hdp_application *app, 600 sdp_list_t **sup_features) 601 { 602 sdp_list_t *hdp_feature; 603 604 hdp_feature = app_to_sdplist(app); 605 if (!hdp_feature) 606 goto fail; 607 608 if (!*sup_features) { 609 *sup_features = sdp_list_append(NULL, hdp_feature); 610 if (!*sup_features) 611 goto fail; 612 } else if (!sdp_list_append(*sup_features, hdp_feature)) { 613 goto fail; 614 } 615 616 return TRUE; 617 618 fail: 619 if (hdp_feature) 620 sdp_list_free(hdp_feature, (sdp_free_func_t)sdp_data_free); 621 return FALSE; 622 } 623 624 static void free_hdp_list(void *list) 625 { 626 sdp_list_t *hdp_list = list; 627 628 sdp_list_free(hdp_list, (sdp_free_func_t)sdp_data_free); 629 } 630 631 static gboolean register_service_sup_features(GSList *app_list, 632 sdp_record_t *sdp_record) 633 { 634 GSList *l; 635 sdp_list_t *sup_features = NULL; 636 637 for (l = app_list; l; l = l->next) { 638 if (!register_features(l->data, &sup_features)) 639 return FALSE; 640 } 641 642 if (sdp_set_supp_feat(sdp_record, sup_features) < 0) { 643 sdp_list_free(sup_features, free_hdp_list); 644 return FALSE; 645 } 646 647 return TRUE; 648 } 649 650 static gboolean register_data_exchange_spec(sdp_record_t *record) 651 { 652 sdp_data_t *spec; 653 uint8_t data_spec = DATA_EXCHANGE_SPEC_11073; 654 /* As by now 11073 is the only supported we set it by default */ 655 656 spec = sdp_data_alloc(SDP_UINT8, &data_spec); 657 if (!spec) 658 return FALSE; 659 660 if (sdp_attr_add(record, SDP_ATTR_DATA_EXCHANGE_SPEC, spec) < 0) { 661 sdp_data_free(spec); 662 return FALSE; 663 } 664 665 return TRUE; 666 } 667 668 static gboolean register_mcap_features(sdp_record_t *sdp_record) 669 { 670 sdp_data_t *mcap_proc; 671 uint8_t mcap_sup_proc = MCAP_SUP_PROC; 672 673 mcap_proc = sdp_data_alloc(SDP_UINT8, &mcap_sup_proc); 674 if (!mcap_proc) 675 return FALSE; 676 677 if (sdp_attr_add(sdp_record, SDP_ATTR_MCAP_SUPPORTED_PROCEDURES, 678 mcap_proc) < 0) { 679 sdp_data_free(mcap_proc); 680 return FALSE; 681 } 682 683 return TRUE; 684 } 685 686 gboolean hdp_update_sdp_record(struct hdp_adapter *adapter, GSList *app_list) 687 { 688 sdp_record_t *sdp_record; 689 bdaddr_t addr; 690 691 if (adapter->sdp_handler) 692 remove_record_from_server(adapter->sdp_handler); 693 694 if (!app_list) { 695 adapter->sdp_handler = 0; 696 return TRUE; 697 } 698 699 sdp_record = sdp_record_alloc(); 700 if (!sdp_record) 701 return FALSE; 702 703 if (adapter->sdp_handler) 704 sdp_record->handle = adapter->sdp_handler; 705 else 706 sdp_record->handle = 0xffffffff; /* Set automatically */ 707 708 if (is_app_role(app_list, HDP_SINK)) 709 set_sdp_services_uuid(sdp_record, HDP_SINK); 710 if (is_app_role(app_list, HDP_SOURCE)) 711 set_sdp_services_uuid(sdp_record, HDP_SOURCE); 712 713 if (!register_service_protocols(adapter, sdp_record)) 714 goto fail; 715 if (!register_service_profiles(sdp_record)) 716 goto fail; 717 if (!register_service_additional_protocols(adapter, sdp_record)) 718 goto fail; 719 720 sdp_set_info_attr(sdp_record, HDP_SERVICE_NAME, HDP_SERVICE_PROVIDER, 721 HDP_SERVICE_DSC); 722 if (!register_service_sup_features(app_list, sdp_record)) 723 goto fail; 724 if (!register_data_exchange_spec(sdp_record)) 725 goto fail; 726 727 register_mcap_features(sdp_record); 728 729 if (sdp_set_record_state(sdp_record, adapter->record_state++)) 730 goto fail; 731 732 adapter_get_address(adapter->btd_adapter, &addr); 733 734 if (add_record_to_server(&addr, sdp_record) < 0) 735 goto fail; 736 adapter->sdp_handler = sdp_record->handle; 737 return TRUE; 738 739 fail: 740 if (sdp_record) 741 sdp_record_free(sdp_record); 742 return FALSE; 743 } 744 745 static gboolean check_role(uint8_t rec_role, uint8_t app_role) 746 { 747 if ((rec_role == HDP_SINK && app_role == HDP_SOURCE) || 748 (rec_role == HDP_SOURCE && app_role == HDP_SINK)) 749 return TRUE; 750 751 return FALSE; 752 } 753 754 static gboolean get_mdep_from_rec(const sdp_record_t *rec, uint8_t role, 755 uint16_t d_type, uint8_t *mdep, char **desc) 756 { 757 sdp_data_t *list, *feat; 758 759 if (!desc && !mdep) 760 return TRUE; 761 762 list = sdp_data_get(rec, SDP_ATTR_SUPPORTED_FEATURES_LIST); 763 764 if (list->dtd != SDP_SEQ8 && list->dtd != SDP_SEQ16 && 765 list->dtd != SDP_SEQ32) 766 return FALSE; 767 768 for (feat = list->val.dataseq; feat; feat = feat->next) { 769 sdp_data_t *data_type, *mdepid, *role_t, *desc_t; 770 771 if (feat->dtd != SDP_SEQ8 && feat->dtd != SDP_SEQ16 && 772 feat->dtd != SDP_SEQ32) 773 continue; 774 775 mdepid = feat->val.dataseq; 776 if (!mdepid) 777 continue; 778 779 data_type = mdepid->next; 780 if (!data_type) 781 continue; 782 783 role_t = data_type->next; 784 if (!role_t) 785 continue; 786 787 desc_t = role_t->next; 788 789 if (data_type->dtd != SDP_UINT16 || mdepid->dtd != SDP_UINT8 || 790 role_t->dtd != SDP_UINT8) 791 continue; 792 793 if (data_type->val.uint16 != d_type || 794 !check_role(role_t->val.uint8, role)) 795 continue; 796 797 if (mdep) 798 *mdep = mdepid->val.uint8; 799 800 if (desc && desc_t && (desc_t->dtd == SDP_TEXT_STR8 || 801 desc_t->dtd == SDP_TEXT_STR16 || 802 desc_t->dtd == SDP_TEXT_STR32)) 803 *desc = g_strdup(desc_t->val.str); 804 805 return TRUE; 806 } 807 808 return FALSE; 809 } 810 811 static void get_mdep_cb(sdp_list_t *recs, int err, gpointer user_data) 812 { 813 struct get_mdep_data *mdep_data = user_data; 814 GError *gerr = NULL; 815 uint8_t mdep; 816 817 if (err || !recs) { 818 g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR, 819 "Error getting remote SDP records"); 820 mdep_data->func(0, mdep_data->data, gerr); 821 g_error_free(gerr); 822 return; 823 } 824 825 if (!get_mdep_from_rec(recs->data, mdep_data->app->role, 826 mdep_data->app->data_type, &mdep, NULL)) { 827 g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR, 828 "No matching MDEP found"); 829 mdep_data->func(0, mdep_data->data, gerr); 830 g_error_free(gerr); 831 return; 832 } 833 834 mdep_data->func(mdep, mdep_data->data, NULL); 835 } 836 837 static void free_mdep_data(gpointer data) 838 { 839 struct get_mdep_data *mdep_data = data; 840 841 if (mdep_data->destroy) 842 mdep_data->destroy(mdep_data->data); 843 hdp_application_unref(mdep_data->app); 844 845 g_free(mdep_data); 846 } 847 848 gboolean hdp_get_mdep(struct hdp_device *device, struct hdp_application *app, 849 hdp_continue_mdep_f func, gpointer data, 850 GDestroyNotify destroy, GError **err) 851 { 852 struct get_mdep_data *mdep_data; 853 bdaddr_t dst, src; 854 uuid_t uuid; 855 856 device_get_address(device->dev, &dst); 857 adapter_get_address(device_get_adapter(device->dev), &src); 858 859 mdep_data = g_new0(struct get_mdep_data, 1); 860 mdep_data->app = hdp_application_ref(app); 861 mdep_data->func = func; 862 mdep_data->data = data; 863 mdep_data->destroy = destroy; 864 865 bt_string2uuid(&uuid, HDP_UUID); 866 if (bt_search_service(&src, &dst, &uuid, get_mdep_cb, mdep_data, 867 free_mdep_data)) { 868 g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR, 869 "Can't get remote SDP record"); 870 g_free(mdep_data); 871 return FALSE; 872 } 873 874 return TRUE; 875 } 876 877 static gboolean get_prot_desc_entry(sdp_data_t *entry, int type, guint16 *val) 878 { 879 sdp_data_t *iter; 880 int proto; 881 882 if (!entry || (entry->dtd != SDP_SEQ8 && entry->dtd != SDP_SEQ16 && 883 entry->dtd != SDP_SEQ32)) 884 return FALSE; 885 886 iter = entry->val.dataseq; 887 if (!(iter->dtd & SDP_UUID_UNSPEC)) 888 return FALSE; 889 890 proto = sdp_uuid_to_proto(&iter->val.uuid); 891 if (proto != type) 892 return FALSE; 893 894 if (!val) 895 return TRUE; 896 897 iter = iter->next; 898 if (iter->dtd != SDP_UINT16) 899 return FALSE; 900 901 *val = iter->val.uint16; 902 903 return TRUE; 904 } 905 906 static gboolean hdp_get_prot_desc_list(const sdp_record_t *rec, guint16 *psm, 907 guint16 *version) 908 { 909 sdp_data_t *pdl, *p0, *p1; 910 911 if (!psm && !version) 912 return TRUE; 913 914 pdl = sdp_data_get(rec, SDP_ATTR_PROTO_DESC_LIST); 915 if (pdl->dtd != SDP_SEQ8 && pdl->dtd != SDP_SEQ16 && 916 pdl->dtd != SDP_SEQ32) 917 return FALSE; 918 919 p0 = pdl->val.dataseq; 920 if (!get_prot_desc_entry(p0, L2CAP_UUID, psm)) 921 return FALSE; 922 923 p1 = p0->next; 924 if (!get_prot_desc_entry(p1, MCAP_CTRL_UUID, version)) 925 return FALSE; 926 927 return TRUE; 928 } 929 930 static gboolean hdp_get_add_prot_desc_list(const sdp_record_t *rec, 931 guint16 *psm) 932 { 933 sdp_data_t *pdl, *p0, *p1; 934 935 if (!psm) 936 return TRUE; 937 938 pdl = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST); 939 if (pdl->dtd != SDP_SEQ8) 940 return FALSE; 941 pdl = pdl->val.dataseq; 942 if (pdl->dtd != SDP_SEQ8) 943 return FALSE; 944 945 p0 = pdl->val.dataseq; 946 947 if (!get_prot_desc_entry(p0, L2CAP_UUID, psm)) 948 return FALSE; 949 p1 = p0->next; 950 if (!get_prot_desc_entry(p1, MCAP_DATA_UUID, NULL)) 951 return FALSE; 952 953 return TRUE; 954 } 955 956 static gboolean get_ccpsm(sdp_list_t *recs, uint16_t *ccpsm) 957 { 958 sdp_list_t *l; 959 960 for (l = recs; l; l = l->next) { 961 sdp_record_t *rec = l->data; 962 963 if (hdp_get_prot_desc_list(rec, ccpsm, NULL)) 964 return TRUE; 965 } 966 967 return FALSE; 968 } 969 970 static gboolean get_dcpsm(sdp_list_t *recs, uint16_t *dcpsm) 971 { 972 sdp_list_t *l; 973 974 for (l = recs; l; l = l->next) { 975 sdp_record_t *rec = l->data; 976 977 if (hdp_get_add_prot_desc_list(rec, dcpsm)) 978 return TRUE; 979 } 980 981 return FALSE; 982 } 983 984 static void con_mcl_data_unref(struct conn_mcl_data *conn_data) 985 { 986 if (!conn_data) 987 return; 988 989 if (--conn_data->refs > 0) 990 return; 991 992 if (conn_data->destroy) 993 conn_data->destroy(conn_data->data); 994 995 health_device_unref(conn_data->dev); 996 g_free(conn_data); 997 } 998 999 static void destroy_con_mcl_data(gpointer data) 1000 { 1001 con_mcl_data_unref(data); 1002 } 1003 1004 static struct conn_mcl_data *con_mcl_data_ref(struct conn_mcl_data *conn_data) 1005 { 1006 if (!conn_data) 1007 return NULL; 1008 1009 conn_data->refs++; 1010 return conn_data; 1011 } 1012 1013 static void create_mcl_cb(struct mcap_mcl *mcl, GError *err, gpointer data) 1014 { 1015 struct conn_mcl_data *conn_data = data; 1016 struct hdp_device *device = conn_data->dev; 1017 GError *gerr = NULL; 1018 1019 if (err) { 1020 conn_data->func(conn_data->data, err); 1021 return; 1022 } 1023 1024 if (!device->mcl) 1025 device->mcl = mcap_mcl_ref(mcl); 1026 device->mcl_conn = TRUE; 1027 1028 hdp_set_mcl_cb(device, &gerr); 1029 1030 conn_data->func(conn_data->data, gerr); 1031 if (gerr) 1032 g_error_free(gerr); 1033 } 1034 1035 static void search_cb(sdp_list_t *recs, int err, gpointer user_data) 1036 { 1037 struct conn_mcl_data *conn_data = user_data; 1038 GError *gerr = NULL; 1039 bdaddr_t dst; 1040 uint16_t ccpsm; 1041 1042 if (!conn_data->dev->hdp_adapter->mi) { 1043 g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR, 1044 "Mcap instance released"); 1045 goto fail; 1046 } 1047 1048 if (err || !recs) { 1049 g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR, 1050 "Error getting remote SDP records"); 1051 goto fail; 1052 } 1053 1054 if (!get_ccpsm(recs, &ccpsm)) { 1055 g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR, 1056 "Can't get remote PSM for control channel"); 1057 goto fail; 1058 } 1059 1060 conn_data = con_mcl_data_ref(conn_data); 1061 1062 device_get_address(conn_data->dev->dev, &dst); 1063 if (!mcap_create_mcl(conn_data->dev->hdp_adapter->mi, &dst, ccpsm, 1064 create_mcl_cb, conn_data, 1065 destroy_con_mcl_data, &gerr)) { 1066 con_mcl_data_unref(conn_data); 1067 goto fail; 1068 } 1069 return; 1070 fail: 1071 conn_data->func(conn_data->data, gerr); 1072 g_error_free(gerr); 1073 } 1074 1075 gboolean hdp_establish_mcl(struct hdp_device *device, 1076 hdp_continue_proc_f func, 1077 gpointer data, 1078 GDestroyNotify destroy, 1079 GError **err) 1080 { 1081 struct conn_mcl_data *conn_data; 1082 bdaddr_t dst, src; 1083 uuid_t uuid; 1084 1085 device_get_address(device->dev, &dst); 1086 adapter_get_address(device_get_adapter(device->dev), &src); 1087 1088 conn_data = g_new0(struct conn_mcl_data, 1); 1089 conn_data->refs = 1; 1090 conn_data->func = func; 1091 conn_data->data = data; 1092 conn_data->destroy = destroy; 1093 conn_data->dev = health_device_ref(device); 1094 1095 bt_string2uuid(&uuid, HDP_UUID); 1096 if (bt_search_service(&src, &dst, &uuid, search_cb, conn_data, 1097 destroy_con_mcl_data)) { 1098 g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR, 1099 "Can't get remote SDP record"); 1100 g_free(conn_data); 1101 return FALSE; 1102 } 1103 1104 return TRUE; 1105 } 1106 1107 static void get_dcpsm_cb(sdp_list_t *recs, int err, gpointer data) 1108 { 1109 struct get_dcpsm_data *dcpsm_data = data; 1110 GError *gerr = NULL; 1111 uint16_t dcpsm; 1112 1113 if (err || !recs) { 1114 g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR, 1115 "Error getting remote SDP records"); 1116 goto fail; 1117 } 1118 1119 if (!get_dcpsm(recs, &dcpsm)) { 1120 g_set_error(&gerr, HDP_ERROR, HDP_CONNECTION_ERROR, 1121 "Can't get remote PSM for data channel"); 1122 goto fail; 1123 } 1124 1125 dcpsm_data->func(dcpsm, dcpsm_data->data, NULL); 1126 return; 1127 1128 fail: 1129 dcpsm_data->func(0, dcpsm_data->data, gerr); 1130 g_error_free(gerr); 1131 } 1132 1133 static void free_dcpsm_data(gpointer data) 1134 { 1135 struct get_dcpsm_data *dcpsm_data = data; 1136 1137 if (!dcpsm_data) 1138 return; 1139 1140 if (dcpsm_data->destroy) 1141 dcpsm_data->destroy(dcpsm_data->data); 1142 1143 g_free(dcpsm_data); 1144 } 1145 1146 gboolean hdp_get_dcpsm(struct hdp_device *device, hdp_continue_dcpsm_f func, 1147 gpointer data, 1148 GDestroyNotify destroy, 1149 GError **err) 1150 { 1151 struct get_dcpsm_data *dcpsm_data; 1152 bdaddr_t dst, src; 1153 uuid_t uuid; 1154 1155 device_get_address(device->dev, &dst); 1156 adapter_get_address(device_get_adapter(device->dev), &src); 1157 1158 dcpsm_data = g_new0(struct get_dcpsm_data, 1); 1159 dcpsm_data->func = func; 1160 dcpsm_data->data = data; 1161 dcpsm_data->destroy = destroy; 1162 1163 bt_string2uuid(&uuid, HDP_UUID); 1164 if (bt_search_service(&src, &dst, &uuid, get_dcpsm_cb, dcpsm_data, 1165 free_dcpsm_data)) { 1166 g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR, 1167 "Can't get remote SDP record"); 1168 g_free(dcpsm_data); 1169 return FALSE; 1170 } 1171 1172 return TRUE; 1173 } 1174 1175 static void hdp_free_application(struct hdp_application *app) 1176 { 1177 if (app->dbus_watcher) 1178 g_dbus_remove_watch(app->conn, app->dbus_watcher); 1179 1180 if (app->conn) 1181 dbus_connection_unref(app->conn); 1182 g_free(app->oname); 1183 g_free(app->description); 1184 g_free(app->path); 1185 g_free(app); 1186 } 1187 1188 struct hdp_application *hdp_application_ref(struct hdp_application *app) 1189 { 1190 if (!app) 1191 return NULL; 1192 1193 app->ref++; 1194 1195 DBG("health_application_ref(%p): ref=%d", app, app->ref); 1196 return app; 1197 } 1198 1199 void hdp_application_unref(struct hdp_application *app) 1200 { 1201 if (!app) 1202 return; 1203 1204 app->ref --; 1205 1206 DBG("health_application_unref(%p): ref=%d", app, app->ref); 1207 if (app->ref > 0) 1208 return; 1209 1210 hdp_free_application(app); 1211 } 1212