service.c revision 3df548164d179e08032c82b90cc56edbf83ef9bf
1/* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2006-2010 Nokia Corporation 6 * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org> 7 * 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#include <stdlib.h> 31#include <string.h> 32 33#include <bluetooth/bluetooth.h> 34#include <bluetooth/sdp.h> 35#include <bluetooth/sdp_lib.h> 36 37#include <gdbus.h> 38 39#include "sdpd.h" 40#include "sdp-xml.h" 41#include "plugin.h" 42#include "adapter.h" 43#include "error.h" 44#include "log.h" 45 46#define SERVICE_INTERFACE "org.bluez.Service" 47 48static DBusConnection *connection; 49 50struct record_data { 51 uint32_t handle; 52 char *sender; 53 guint listener_id; 54 struct service_adapter *serv_adapter; 55}; 56 57struct context_data { 58 sdp_record_t *record; 59 sdp_data_t attr_data; 60 struct sdp_xml_data *stack_head; 61 uint16_t attr_id; 62}; 63 64struct pending_auth { 65 DBusConnection *conn; 66 DBusMessage *msg; 67 char *sender; 68 bdaddr_t dst; 69 char uuid[MAX_LEN_UUID_STR]; 70}; 71 72struct service_adapter { 73 struct btd_adapter *adapter; 74 GSList *pending_list; 75 GSList *records; 76}; 77 78static struct service_adapter *serv_adapter_any = NULL; 79 80static int compute_seq_size(sdp_data_t *data) 81{ 82 int unit_size = data->unitSize; 83 sdp_data_t *seq = data->val.dataseq; 84 85 for (; seq; seq = seq->next) 86 unit_size += seq->unitSize; 87 88 return unit_size; 89} 90 91static void element_start(GMarkupParseContext *context, 92 const gchar *element_name, const gchar **attribute_names, 93 const gchar **attribute_values, gpointer user_data, GError **err) 94{ 95 struct context_data *ctx_data = user_data; 96 97 if (!strcmp(element_name, "record")) 98 return; 99 100 if (!strcmp(element_name, "attribute")) { 101 int i; 102 for (i = 0; attribute_names[i]; i++) { 103 if (!strcmp(attribute_names[i], "id")) { 104 ctx_data->attr_id = strtol(attribute_values[i], 0, 0); 105 break; 106 } 107 } 108 DBG("New attribute 0x%04x", ctx_data->attr_id); 109 return; 110 } 111 112 if (ctx_data->stack_head) { 113 struct sdp_xml_data *newelem = sdp_xml_data_alloc(); 114 newelem->next = ctx_data->stack_head; 115 ctx_data->stack_head = newelem; 116 } else { 117 ctx_data->stack_head = sdp_xml_data_alloc(); 118 ctx_data->stack_head->next = NULL; 119 } 120 121 if (!strcmp(element_name, "sequence")) 122 ctx_data->stack_head->data = sdp_data_alloc(SDP_SEQ8, NULL); 123 else if (!strcmp(element_name, "alternate")) 124 ctx_data->stack_head->data = sdp_data_alloc(SDP_ALT8, NULL); 125 else { 126 int i; 127 /* Parse value, name, encoding */ 128 for (i = 0; attribute_names[i]; i++) { 129 if (!strcmp(attribute_names[i], "value")) { 130 int curlen = strlen(ctx_data->stack_head->text); 131 int attrlen = strlen(attribute_values[i]); 132 133 /* Ensure we're big enough */ 134 while ((curlen + 1 + attrlen) > ctx_data->stack_head->size) { 135 sdp_xml_data_expand(ctx_data->stack_head); 136 } 137 138 memcpy(ctx_data->stack_head->text + curlen, 139 attribute_values[i], attrlen); 140 ctx_data->stack_head->text[curlen + attrlen] = '\0'; 141 } 142 143 if (!strcmp(attribute_names[i], "encoding")) { 144 if (!strcmp(attribute_values[i], "hex")) 145 ctx_data->stack_head->type = 1; 146 } 147 148 if (!strcmp(attribute_names[i], "name")) { 149 ctx_data->stack_head->name = strdup(attribute_values[i]); 150 } 151 } 152 153 ctx_data->stack_head->data = sdp_xml_parse_datatype(element_name, 154 ctx_data->stack_head, ctx_data->record); 155 156 if (ctx_data->stack_head->data == NULL) 157 error("Can't parse element %s", element_name); 158 } 159} 160 161static void element_end(GMarkupParseContext *context, 162 const gchar *element_name, gpointer user_data, GError **err) 163{ 164 struct context_data *ctx_data = user_data; 165 struct sdp_xml_data *elem; 166 167 if (!strcmp(element_name, "record")) 168 return; 169 170 if (!strcmp(element_name, "attribute")) { 171 if (ctx_data->stack_head && ctx_data->stack_head->data) { 172 int ret = sdp_attr_add(ctx_data->record, ctx_data->attr_id, 173 ctx_data->stack_head->data); 174 if (ret == -1) 175 DBG("Trouble adding attribute\n"); 176 177 ctx_data->stack_head->data = NULL; 178 sdp_xml_data_free(ctx_data->stack_head); 179 ctx_data->stack_head = NULL; 180 } else { 181 DBG("No data for attribute 0x%04x\n", ctx_data->attr_id); 182 } 183 return; 184 } 185 186 if (!strcmp(element_name, "sequence")) { 187 ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data); 188 189 if (ctx_data->stack_head->data->unitSize > USHRT_MAX) { 190 ctx_data->stack_head->data->unitSize += sizeof(uint32_t); 191 ctx_data->stack_head->data->dtd = SDP_SEQ32; 192 } else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) { 193 ctx_data->stack_head->data->unitSize += sizeof(uint16_t); 194 ctx_data->stack_head->data->dtd = SDP_SEQ16; 195 } else { 196 ctx_data->stack_head->data->unitSize += sizeof(uint8_t); 197 } 198 } else if (!strcmp(element_name, "alternate")) { 199 ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data); 200 201 if (ctx_data->stack_head->data->unitSize > USHRT_MAX) { 202 ctx_data->stack_head->data->unitSize += sizeof(uint32_t); 203 ctx_data->stack_head->data->dtd = SDP_ALT32; 204 } else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) { 205 ctx_data->stack_head->data->unitSize += sizeof(uint16_t); 206 ctx_data->stack_head->data->dtd = SDP_ALT16; 207 } else { 208 ctx_data->stack_head->data->unitSize += sizeof(uint8_t); 209 } 210 } 211 212 if (ctx_data->stack_head->next && ctx_data->stack_head->data && 213 ctx_data->stack_head->next->data) { 214 switch (ctx_data->stack_head->next->data->dtd) { 215 case SDP_SEQ8: 216 case SDP_SEQ16: 217 case SDP_SEQ32: 218 case SDP_ALT8: 219 case SDP_ALT16: 220 case SDP_ALT32: 221 ctx_data->stack_head->next->data->val.dataseq = 222 sdp_seq_append(ctx_data->stack_head->next->data->val.dataseq, 223 ctx_data->stack_head->data); 224 ctx_data->stack_head->data = NULL; 225 break; 226 } 227 228 elem = ctx_data->stack_head; 229 ctx_data->stack_head = ctx_data->stack_head->next; 230 231 sdp_xml_data_free(elem); 232 } 233} 234 235static GMarkupParser parser = { 236 element_start, element_end, NULL, NULL, NULL 237}; 238 239static sdp_record_t *sdp_xml_parse_record(const char *data, int size) 240{ 241 GMarkupParseContext *ctx; 242 struct context_data *ctx_data; 243 sdp_record_t *record; 244 245 ctx_data = malloc(sizeof(*ctx_data)); 246 if (!ctx_data) 247 return NULL; 248 249 record = sdp_record_alloc(); 250 if (!record) { 251 free(ctx_data); 252 return NULL; 253 } 254 255 memset(ctx_data, 0, sizeof(*ctx_data)); 256 ctx_data->record = record; 257 258 ctx = g_markup_parse_context_new(&parser, 0, ctx_data, NULL); 259 260 if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) { 261 error("XML parsing error"); 262 g_markup_parse_context_free(ctx); 263 sdp_record_free(record); 264 free(ctx_data); 265 return NULL; 266 } 267 268 g_markup_parse_context_free(ctx); 269 270 free(ctx_data); 271 272 return record; 273} 274 275static struct record_data *find_record(struct service_adapter *serv_adapter, 276 uint32_t handle, const char *sender) 277{ 278 GSList *list; 279 280 for (list = serv_adapter->records; list; list = list->next) { 281 struct record_data *data = list->data; 282 if (handle == data->handle && !strcmp(sender, data->sender)) 283 return data; 284 } 285 286 return NULL; 287} 288 289static struct pending_auth *next_pending(struct service_adapter *serv_adapter) 290{ 291 GSList *l = serv_adapter->pending_list; 292 293 if (l) { 294 struct pending_auth *auth = l->data; 295 return auth; 296 } 297 298 return NULL; 299} 300 301static struct pending_auth *find_pending_by_sender( 302 struct service_adapter *serv_adapter, 303 const char *sender) 304{ 305 GSList *l = serv_adapter->pending_list; 306 307 for (; l; l = l->next) { 308 struct pending_auth *auth = l->data; 309 if (g_str_equal(auth->sender, sender)) 310 return auth; 311 } 312 313 return NULL; 314} 315 316static void exit_callback(DBusConnection *conn, void *user_data) 317{ 318 struct record_data *user_record = user_data; 319 struct service_adapter *serv_adapter = user_record->serv_adapter; 320 struct pending_auth *auth; 321 322 DBG("remove record"); 323 324 serv_adapter->records = g_slist_remove(serv_adapter->records, 325 user_record); 326 327 auth = find_pending_by_sender(serv_adapter, user_record->sender); 328 if (auth) { 329 serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, 330 auth); 331 g_free(auth); 332 } 333 334 remove_record_from_server(user_record->handle); 335 336 g_free(user_record->sender); 337 g_free(user_record); 338} 339 340static inline DBusMessage *failed(DBusMessage *msg) 341{ 342 return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "Failed"); 343} 344 345static inline DBusMessage *failed_strerror(DBusMessage *msg, int err) 346{ 347 return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", 348 "%s", strerror(err)); 349} 350 351static int add_xml_record(DBusConnection *conn, const char *sender, 352 struct service_adapter *serv_adapter, 353 const char *record, dbus_uint32_t *handle) 354{ 355 struct record_data *user_record; 356 sdp_record_t *sdp_record; 357 bdaddr_t src; 358 359 sdp_record = sdp_xml_parse_record(record, strlen(record)); 360 if (!sdp_record) { 361 error("Parsing of XML service record failed"); 362 return -EIO; 363 } 364 365 if (serv_adapter->adapter) 366 adapter_get_address(serv_adapter->adapter, &src); 367 else 368 bacpy(&src, BDADDR_ANY); 369 370 if (add_record_to_server(&src, sdp_record) < 0) { 371 error("Failed to register service record"); 372 sdp_record_free(sdp_record); 373 return -EIO; 374 } 375 376 user_record = g_new0(struct record_data, 1); 377 user_record->handle = sdp_record->handle; 378 user_record->sender = g_strdup(sender); 379 user_record->serv_adapter = serv_adapter; 380 user_record->listener_id = g_dbus_add_disconnect_watch(conn, sender, 381 exit_callback, user_record, NULL); 382 383 serv_adapter->records = g_slist_append(serv_adapter->records, 384 user_record); 385 386 DBG("listener_id %d", user_record->listener_id); 387 388 *handle = user_record->handle; 389 390 return 0; 391} 392 393static DBusMessage *update_record(DBusConnection *conn, DBusMessage *msg, 394 struct service_adapter *serv_adapter, 395 dbus_uint32_t handle, sdp_record_t *sdp_record) 396{ 397 bdaddr_t src; 398 int err; 399 400 if (remove_record_from_server(handle) < 0) { 401 sdp_record_free(sdp_record); 402 return btd_error_not_available(msg); 403 } 404 405 if (serv_adapter->adapter) 406 adapter_get_address(serv_adapter->adapter, &src); 407 else 408 bacpy(&src, BDADDR_ANY); 409 410 sdp_record->handle = handle; 411 err = add_record_to_server(&src, sdp_record); 412 if (err < 0) { 413 sdp_record_free(sdp_record); 414 error("Failed to update the service record"); 415 return g_dbus_create_error(msg, 416 ERROR_INTERFACE ".Failed", 417 "%s", strerror(EIO)); 418 } 419 420 return dbus_message_new_method_return(msg); 421} 422 423static DBusMessage *update_xml_record(DBusConnection *conn, 424 DBusMessage *msg, 425 struct service_adapter *serv_adapter) 426{ 427 struct record_data *user_record; 428 sdp_record_t *sdp_record; 429 const char *record; 430 dbus_uint32_t handle; 431 int len; 432 433 if (dbus_message_get_args(msg, NULL, 434 DBUS_TYPE_UINT32, &handle, 435 DBUS_TYPE_STRING, &record, 436 DBUS_TYPE_INVALID) == FALSE) 437 return NULL; 438 439 len = (record ? strlen(record) : 0); 440 if (len == 0) 441 return btd_error_invalid_args(msg); 442 443 user_record = find_record(serv_adapter, handle, 444 dbus_message_get_sender(msg)); 445 if (!user_record) 446 return btd_error_not_available(msg); 447 448 sdp_record = sdp_xml_parse_record(record, len); 449 if (!sdp_record) { 450 error("Parsing of XML service record failed"); 451 sdp_record_free(sdp_record); 452 return g_dbus_create_error(msg, 453 ERROR_INTERFACE ".Failed", 454 "%s", strerror(EIO)); 455 } 456 457 return update_record(conn, msg, serv_adapter, handle, sdp_record); 458} 459 460static int remove_record(DBusConnection *conn, const char *sender, 461 struct service_adapter *serv_adapter, 462 dbus_uint32_t handle) 463{ 464 struct record_data *user_record; 465 466 DBG("remove record 0x%x", handle); 467 468 user_record = find_record(serv_adapter, handle, sender); 469 if (!user_record) 470 return -1; 471 472 DBG("listner_id %d", user_record->listener_id); 473 474 g_dbus_remove_watch(conn, user_record->listener_id); 475 476 exit_callback(conn, user_record); 477 478 return 0; 479} 480 481static DBusMessage *add_service_record(DBusConnection *conn, 482 DBusMessage *msg, void *data) 483{ 484 struct service_adapter *serv_adapter = data; 485 DBusMessage *reply; 486 const char *sender, *record; 487 dbus_uint32_t handle; 488 int err; 489 490 if (dbus_message_get_args(msg, NULL, 491 DBUS_TYPE_STRING, &record, DBUS_TYPE_INVALID) == FALSE) 492 return NULL; 493 494 sender = dbus_message_get_sender(msg); 495 err = add_xml_record(conn, sender, serv_adapter, record, &handle); 496 if (err < 0) 497 return failed_strerror(msg, err); 498 499 reply = dbus_message_new_method_return(msg); 500 if (!reply) 501 return NULL; 502 503 dbus_message_append_args(reply, DBUS_TYPE_UINT32, &handle, 504 DBUS_TYPE_INVALID); 505 506 return reply; 507} 508 509static DBusMessage *update_service_record(DBusConnection *conn, 510 DBusMessage *msg, void *data) 511{ 512 struct service_adapter *serv_adapter = data; 513 514 return update_xml_record(conn, msg, serv_adapter); 515} 516 517static DBusMessage *remove_service_record(DBusConnection *conn, 518 DBusMessage *msg, void *data) 519{ 520 struct service_adapter *serv_adapter = data; 521 dbus_uint32_t handle; 522 const char *sender; 523 524 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, 525 DBUS_TYPE_INVALID) == FALSE) 526 return NULL; 527 528 sender = dbus_message_get_sender(msg); 529 530 if (remove_record(conn, sender, serv_adapter, handle) < 0) 531 return btd_error_not_available(msg); 532 533 return dbus_message_new_method_return(msg); 534} 535 536static void auth_cb(DBusError *derr, void *user_data) 537{ 538 struct service_adapter *serv_adapter = user_data; 539 DBusMessage *reply; 540 struct pending_auth *auth; 541 bdaddr_t src; 542 543 auth = next_pending(serv_adapter); 544 if (auth == NULL) { 545 info("Authorization cancelled: Client exited"); 546 return; 547 } 548 549 if (derr) { 550 error("Access denied: %s", derr->message); 551 552 reply = btd_error_not_authorized(auth->msg); 553 dbus_message_unref(auth->msg); 554 g_dbus_send_message(auth->conn, reply); 555 goto done; 556 } 557 558 g_dbus_send_reply(auth->conn, auth->msg, 559 DBUS_TYPE_INVALID); 560 561done: 562 dbus_connection_unref(auth->conn); 563 564 serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, 565 auth); 566 g_free(auth); 567 568 auth = next_pending(serv_adapter); 569 if (auth == NULL) 570 return; 571 572 if (serv_adapter->adapter) 573 adapter_get_address(serv_adapter->adapter, &src); 574 else 575 bacpy(&src, BDADDR_ANY); 576 577 btd_request_authorization(&src, &auth->dst, 578 auth->uuid, auth_cb, serv_adapter); 579} 580 581static DBusMessage *request_authorization(DBusConnection *conn, 582 DBusMessage *msg, void *data) 583{ 584 struct record_data *user_record; 585 struct service_adapter *serv_adapter = data; 586 sdp_record_t *record; 587 sdp_list_t *services; 588 const char *sender; 589 dbus_uint32_t handle; 590 const char *address; 591 struct pending_auth *auth; 592 char uuid_str[MAX_LEN_UUID_STR]; 593 uuid_t *uuid, *uuid128; 594 bdaddr_t src; 595 596 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address, 597 DBUS_TYPE_UINT32, &handle, 598 DBUS_TYPE_INVALID) == FALSE) 599 return NULL; 600 601 sender = dbus_message_get_sender(msg); 602 if (find_pending_by_sender(serv_adapter, sender)) 603 return btd_error_does_not_exist(msg); 604 605 user_record = find_record(serv_adapter, handle, sender); 606 if (!user_record) { 607 user_record = find_record(serv_adapter_any, handle, sender); 608 if (!user_record) 609 return btd_error_not_authorized(msg); 610 } 611 612 record = sdp_record_find(user_record->handle); 613 if (record == NULL) 614 return btd_error_not_authorized(msg); 615 616 if (sdp_get_service_classes(record, &services) < 0) { 617 sdp_record_free(record); 618 return btd_error_not_authorized(msg); 619 } 620 621 if (services == NULL) 622 return btd_error_not_authorized(msg); 623 624 uuid = services->data; 625 uuid128 = sdp_uuid_to_uuid128(uuid); 626 627 sdp_list_free(services, bt_free); 628 629 if (sdp_uuid2strn(uuid128, uuid_str, MAX_LEN_UUID_STR) < 0) { 630 bt_free(uuid128); 631 return btd_error_not_authorized(msg); 632 } 633 bt_free(uuid128); 634 635 auth = g_new0(struct pending_auth, 1); 636 auth->msg = dbus_message_ref(msg); 637 auth->conn = dbus_connection_ref(connection); 638 auth->sender = user_record->sender; 639 memcpy(auth->uuid, uuid_str, MAX_LEN_UUID_STR); 640 str2ba(address, &auth->dst); 641 642 serv_adapter->pending_list = g_slist_append(serv_adapter->pending_list, 643 auth); 644 645 auth = next_pending(serv_adapter); 646 if (auth == NULL) 647 return btd_error_does_not_exist(msg); 648 649 if (serv_adapter->adapter) 650 adapter_get_address(serv_adapter->adapter, &src); 651 else 652 bacpy(&src, BDADDR_ANY); 653 654 if (btd_request_authorization(&src, &auth->dst, auth->uuid, auth_cb, 655 serv_adapter) < 0) { 656 serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, 657 auth); 658 g_free(auth); 659 return btd_error_not_authorized(msg); 660 } 661 662 return NULL; 663} 664 665static DBusMessage *cancel_authorization(DBusConnection *conn, 666 DBusMessage *msg, void *data) 667{ 668 DBusMessage *reply; 669 struct service_adapter *serv_adapter = data; 670 struct pending_auth *auth; 671 const gchar *sender; 672 bdaddr_t src; 673 674 sender = dbus_message_get_sender(msg); 675 676 auth = find_pending_by_sender(serv_adapter, sender); 677 if (auth == NULL) 678 return btd_error_does_not_exist(msg); 679 680 if (serv_adapter->adapter) 681 adapter_get_address(serv_adapter->adapter, &src); 682 else 683 bacpy(&src, BDADDR_ANY); 684 685 btd_cancel_authorization(&src, &auth->dst); 686 687 reply = btd_error_not_authorized(auth->msg); 688 dbus_message_unref(auth->msg); 689 g_dbus_send_message(auth->conn, reply); 690 691 dbus_connection_unref(auth->conn); 692 693 serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, 694 auth); 695 g_free(auth); 696 697 auth = next_pending(serv_adapter); 698 if (auth == NULL) 699 goto done; 700 701 if (serv_adapter->adapter) 702 adapter_get_address(serv_adapter->adapter, &src); 703 else 704 bacpy(&src, BDADDR_ANY); 705 706 btd_request_authorization(&src, &auth->dst, 707 auth->uuid, auth_cb, serv_adapter); 708 709done: 710 return dbus_message_new_method_return(msg); 711} 712 713static GDBusMethodTable service_methods[] = { 714 { "AddRecord", "s", "u", add_service_record }, 715 { "UpdateRecord", "us", "", update_service_record }, 716 { "RemoveRecord", "u", "", remove_service_record }, 717 { "RequestAuthorization","su", "", request_authorization, 718 G_DBUS_METHOD_FLAG_ASYNC}, 719 { "CancelAuthorization", "", "", cancel_authorization }, 720 { } 721}; 722 723static void path_unregister(void *data) 724{ 725 struct service_adapter *serv_adapter = data; 726 GSList *l, *next = NULL; 727 728 for (l = serv_adapter->records; l != NULL; l = next) { 729 struct record_data *user_record = l->data; 730 731 next = l->next; 732 733 g_dbus_remove_watch(connection, user_record->listener_id); 734 exit_callback(connection, user_record); 735 } 736 737 g_free(serv_adapter); 738} 739 740static int register_interface(const char *path, struct btd_adapter *adapter) 741{ 742 struct service_adapter *serv_adapter; 743 744 DBG("path %s", path); 745 746 serv_adapter = g_try_new0(struct service_adapter, 1); 747 if (serv_adapter == NULL) 748 return -ENOMEM; 749 750 serv_adapter->adapter = adapter; 751 serv_adapter->pending_list = NULL; 752 753 if (g_dbus_register_interface(connection, path, SERVICE_INTERFACE, 754 service_methods, NULL, NULL, serv_adapter, 755 path_unregister) == FALSE) { 756 error("D-Bus failed to register %s interface", 757 SERVICE_INTERFACE); 758 g_free(serv_adapter); 759 return -EIO; 760 } 761 762 DBG("Registered interface %s on path %s", SERVICE_INTERFACE, path); 763 764 if (serv_adapter->adapter == NULL) 765 serv_adapter_any = serv_adapter; 766 767 return 0; 768} 769 770static void unregister_interface(const char *path) 771{ 772 DBG("path %s", path); 773 774 g_dbus_unregister_interface(connection, path, SERVICE_INTERFACE); 775} 776 777static int service_probe(struct btd_adapter *adapter) 778{ 779 register_interface(adapter_get_path(adapter), adapter); 780 781 return 0; 782} 783 784static void service_remove(struct btd_adapter *adapter) 785{ 786 unregister_interface(adapter_get_path(adapter)); 787} 788 789static struct btd_adapter_driver service_driver = { 790 .name = "service", 791 .probe = service_probe, 792 .remove = service_remove, 793}; 794 795static const char *any_path; 796 797static int service_init(void) 798{ 799 int err; 800 801 connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); 802 if (connection == NULL) 803 return -EIO; 804 805 any_path = btd_adapter_any_request_path(); 806 if (any_path != NULL) { 807 if (register_interface(any_path, NULL) < 0) { 808 btd_adapter_any_release_path(); 809 any_path = NULL; 810 } 811 } 812 813 err = btd_register_adapter_driver(&service_driver); 814 if (err < 0) { 815 dbus_connection_unref(connection); 816 return err; 817 } 818 819 return 0; 820} 821 822static void service_exit(void) 823{ 824 btd_unregister_adapter_driver(&service_driver); 825 826 if (any_path != NULL) { 827 unregister_interface(any_path); 828 829 btd_adapter_any_release_path(); 830 any_path = NULL; 831 } 832 833 dbus_connection_unref(connection); 834} 835 836BLUETOOTH_PLUGIN_DEFINE(service, VERSION, 837 BLUETOOTH_PLUGIN_PRIORITY_HIGH, service_init, service_exit) 838