service.c revision d6334b6272048696a26b3022a9dff6129c41f1ca
1/* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2006-2007 Nokia Corporation 6 * Copyright (C) 2004-2008 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/hci.h> 35#include <bluetooth/hci_lib.h> 36#include <bluetooth/sdp.h> 37#include <bluetooth/sdp_lib.h> 38 39#include <gdbus.h> 40 41#include "sdpd.h" 42#include "sdp-xml.h" 43#include "plugin.h" 44#include "adapter.h" 45#include "error.h" 46#include "logging.h" 47 48#define SERVICE_INTERFACE "org.bluez.Service" 49 50static DBusConnection *connection; 51 52struct record_data { 53 uint32_t handle; 54 char *sender; 55 guint listener_id; 56 struct service_adapter *serv_adapter; 57}; 58 59struct context_data { 60 sdp_record_t *record; 61 sdp_data_t attr_data; 62 struct sdp_xml_data *stack_head; 63 uint16_t attr_id; 64}; 65 66struct pending_auth { 67 DBusConnection *conn; 68 DBusMessage *msg; 69 char *sender; 70 bdaddr_t dst; 71 char uuid[MAX_LEN_UUID_STR]; 72}; 73 74struct service_adapter { 75 struct btd_adapter *adapter; 76 GSList *pending_list; 77 GSList *records; 78}; 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 debug("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 debug("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 debug("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 debug("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 *invalid_arguments(DBusMessage *msg) 341{ 342 return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArguments", 343 "Invalid arguments in method call"); 344} 345 346static inline DBusMessage *not_available(DBusMessage *msg) 347{ 348 return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAvailable", 349 "Not Available"); 350} 351 352static inline DBusMessage *failed(DBusMessage *msg) 353{ 354 return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "Failed"); 355} 356 357static inline DBusMessage *failed_strerror(DBusMessage *msg, int err) 358{ 359 return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", 360 strerror(err)); 361} 362 363static inline DBusMessage *not_authorized(DBusMessage *msg) 364{ 365 return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAuthorized", 366 "Not Authorized"); 367} 368 369static inline DBusMessage *does_not_exist(DBusMessage *msg) 370{ 371 return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist", 372 "Does Not Exist"); 373} 374 375static int add_xml_record(DBusConnection *conn, const char *sender, 376 struct service_adapter *serv_adapter, 377 const char *record, dbus_uint32_t *handle) 378{ 379 struct record_data *user_record; 380 sdp_record_t *sdp_record; 381 bdaddr_t src; 382 383 sdp_record = sdp_xml_parse_record(record, strlen(record)); 384 if (!sdp_record) { 385 error("Parsing of XML service record failed"); 386 return -EIO; 387 } 388 389 if (serv_adapter->adapter) 390 adapter_get_address(serv_adapter->adapter, &src); 391 else 392 bacpy(&src, BDADDR_ANY); 393 394 if (add_record_to_server(&src, sdp_record) < 0) { 395 error("Failed to register service record"); 396 sdp_record_free(sdp_record); 397 return -EIO; 398 } 399 400 user_record = g_new0(struct record_data, 1); 401 user_record->handle = sdp_record->handle; 402 user_record->sender = g_strdup(sender); 403 user_record->serv_adapter = serv_adapter; 404 user_record->listener_id = g_dbus_add_disconnect_watch(conn, sender, 405 exit_callback, user_record, NULL); 406 407 serv_adapter->records = g_slist_append(serv_adapter->records, 408 user_record); 409 410 debug("listener_id %d", user_record->listener_id); 411 412 *handle = user_record->handle; 413 414 return 0; 415} 416 417static DBusMessage *update_record(DBusConnection *conn, DBusMessage *msg, 418 struct service_adapter *serv_adapter, 419 dbus_uint32_t handle, sdp_record_t *sdp_record) 420{ 421 bdaddr_t src; 422 int err; 423 424 if (remove_record_from_server(handle) < 0) { 425 sdp_record_free(sdp_record); 426 return g_dbus_create_error(msg, 427 ERROR_INTERFACE ".NotAvailable", 428 "Not Available"); 429 } 430 431 if (serv_adapter->adapter) 432 adapter_get_address(serv_adapter->adapter, &src); 433 else 434 bacpy(&src, BDADDR_ANY); 435 436 sdp_record->handle = handle; 437 err = add_record_to_server(&src, sdp_record); 438 if (err < 0) { 439 sdp_record_free(sdp_record); 440 error("Failed to update the service record"); 441 return g_dbus_create_error(msg, 442 ERROR_INTERFACE ".Failed", 443 strerror(EIO)); 444 } 445 446 return dbus_message_new_method_return(msg); 447} 448 449static DBusMessage *update_xml_record(DBusConnection *conn, 450 DBusMessage *msg, 451 struct service_adapter *serv_adapter) 452{ 453 struct record_data *user_record; 454 sdp_record_t *sdp_record; 455 const char *record; 456 dbus_uint32_t handle; 457 int len; 458 459 if (dbus_message_get_args(msg, NULL, 460 DBUS_TYPE_UINT32, &handle, 461 DBUS_TYPE_STRING, &record, 462 DBUS_TYPE_INVALID) == FALSE) 463 return NULL; 464 465 len = (record ? strlen(record) : 0); 466 if (len == 0) 467 return invalid_arguments(msg); 468 469 user_record = find_record(serv_adapter, handle, 470 dbus_message_get_sender(msg)); 471 if (!user_record) 472 return g_dbus_create_error(msg, 473 ERROR_INTERFACE ".NotAvailable", 474 "Not Available"); 475 476 sdp_record = sdp_xml_parse_record(record, len); 477 if (!sdp_record) { 478 error("Parsing of XML service record failed"); 479 sdp_record_free(sdp_record); 480 return g_dbus_create_error(msg, 481 ERROR_INTERFACE ".Failed", 482 strerror(EIO)); 483 } 484 485 return update_record(conn, msg, serv_adapter, handle, sdp_record); 486} 487 488static int remove_record(DBusConnection *conn, const char *sender, 489 struct service_adapter *serv_adapter, 490 dbus_uint32_t handle) 491{ 492 struct record_data *user_record; 493 494 debug("remove record 0x%x", handle); 495 496 user_record = find_record(serv_adapter, handle, sender); 497 if (!user_record) 498 return -1; 499 500 debug("listner_id %d", user_record->listener_id); 501 502 g_dbus_remove_watch(conn, user_record->listener_id); 503 504 exit_callback(conn, user_record); 505 506 return 0; 507} 508 509static DBusMessage *add_service_record(DBusConnection *conn, 510 DBusMessage *msg, void *data) 511{ 512 struct service_adapter *serv_adapter = data; 513 DBusMessage *reply; 514 const char *sender, *record; 515 dbus_uint32_t handle; 516 int err; 517 518 if (dbus_message_get_args(msg, NULL, 519 DBUS_TYPE_STRING, &record, DBUS_TYPE_INVALID) == FALSE) 520 return NULL; 521 522 sender = dbus_message_get_sender(msg); 523 err = add_xml_record(conn, sender, serv_adapter, record, &handle); 524 if (err < 0) 525 return failed_strerror(msg, err); 526 527 reply = dbus_message_new_method_return(msg); 528 if (!reply) 529 return NULL; 530 531 dbus_message_append_args(reply, DBUS_TYPE_UINT32, &handle, 532 DBUS_TYPE_INVALID); 533 534 return reply; 535} 536 537static DBusMessage *update_service_record(DBusConnection *conn, 538 DBusMessage *msg, void *data) 539{ 540 struct service_adapter *serv_adapter = data; 541 542 return update_xml_record(conn, msg, serv_adapter); 543} 544 545static DBusMessage *remove_service_record(DBusConnection *conn, 546 DBusMessage *msg, void *data) 547{ 548 struct service_adapter *serv_adapter = data; 549 dbus_uint32_t handle; 550 const char *sender; 551 552 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, 553 DBUS_TYPE_INVALID) == FALSE) 554 return NULL; 555 556 sender = dbus_message_get_sender(msg); 557 558 if (remove_record(conn, sender, serv_adapter, handle) < 0) 559 return not_available(msg); 560 561 return dbus_message_new_method_return(msg); 562} 563 564static void auth_cb(DBusError *derr, void *user_data) 565{ 566 struct service_adapter *serv_adapter = user_data; 567 DBusMessage *reply; 568 struct pending_auth *auth; 569 bdaddr_t src; 570 571 auth = next_pending(serv_adapter); 572 if (auth == NULL) { 573 info("Authorization cancelled: Client exited"); 574 return; 575 } 576 577 if (derr) { 578 adapter_get_address(serv_adapter->adapter, &src); 579 error("Access denied: %s", derr->message); 580 581 reply = not_authorized(auth->msg); 582 dbus_message_unref(auth->msg); 583 g_dbus_send_message(auth->conn, reply); 584 goto done; 585 } 586 587 g_dbus_send_reply(auth->conn, auth->msg, 588 DBUS_TYPE_INVALID); 589 590done: 591 dbus_connection_unref(auth->conn); 592 593 serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, 594 auth); 595 g_free(auth); 596 597 auth = next_pending(serv_adapter); 598 if (auth == NULL) 599 return; 600 601 if (serv_adapter->adapter) 602 adapter_get_address(serv_adapter->adapter, &src); 603 else 604 bacpy(&src, BDADDR_ANY); 605 606 btd_request_authorization(&src, &auth->dst, 607 auth->uuid, auth_cb, serv_adapter); 608} 609 610static DBusMessage *request_authorization(DBusConnection *conn, 611 DBusMessage *msg, void *data) 612{ 613 struct record_data *user_record; 614 struct service_adapter *serv_adapter = data; 615 sdp_record_t *record; 616 sdp_list_t *services; 617 const char *sender; 618 dbus_uint32_t handle; 619 const char *address; 620 struct pending_auth *auth; 621 char uuid_str[MAX_LEN_UUID_STR]; 622 uuid_t *uuid, *uuid128; 623 bdaddr_t src; 624 625 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address, 626 DBUS_TYPE_UINT32, &handle, 627 DBUS_TYPE_INVALID) == FALSE) 628 return NULL; 629 630 sender = dbus_message_get_sender(msg); 631 if (find_pending_by_sender(serv_adapter, sender)) 632 return failed(msg); 633 634 user_record = find_record(serv_adapter, handle, sender); 635 if (!user_record) 636 return not_authorized(msg); 637 638 record = sdp_record_find(user_record->handle); 639 640 if (sdp_get_service_classes(record, &services) < 0) { 641 sdp_record_free(record); 642 return not_authorized(msg); 643 } 644 645 if (services == NULL) 646 return not_authorized(msg); 647 648 uuid = services->data; 649 uuid128 = sdp_uuid_to_uuid128(uuid); 650 651 sdp_list_free(services, bt_free); 652 653 if (sdp_uuid2strn(uuid128, uuid_str, MAX_LEN_UUID_STR) < 0) { 654 bt_free(uuid128); 655 return not_authorized(msg); 656 } 657 bt_free(uuid128); 658 659 auth = g_new0(struct pending_auth, 1); 660 auth->msg = dbus_message_ref(msg); 661 auth->conn = dbus_connection_ref(connection); 662 auth->sender = user_record->sender; 663 memcpy(auth->uuid, uuid_str, MAX_LEN_UUID_STR); 664 str2ba(address, &auth->dst); 665 666 serv_adapter->pending_list = g_slist_append(serv_adapter->pending_list, 667 auth); 668 669 auth = next_pending(serv_adapter); 670 if (auth == NULL) 671 return does_not_exist(msg); 672 673 if (serv_adapter->adapter) 674 adapter_get_address(serv_adapter->adapter, &src); 675 else 676 bacpy(&src, BDADDR_ANY); 677 678 if (btd_request_authorization(&src, &auth->dst, auth->uuid, auth_cb, 679 serv_adapter) < 0) { 680 serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, 681 auth); 682 g_free(auth); 683 return not_authorized(msg); 684 } 685 686 return NULL; 687} 688 689static DBusMessage *cancel_authorization(DBusConnection *conn, 690 DBusMessage *msg, void *data) 691{ 692 DBusMessage *reply; 693 struct service_adapter *serv_adapter = data; 694 struct pending_auth *auth; 695 const gchar *sender; 696 bdaddr_t src; 697 698 sender = dbus_message_get_sender(msg); 699 700 auth = find_pending_by_sender(serv_adapter, sender); 701 if (auth == NULL) 702 return does_not_exist(msg); 703 704 if (serv_adapter->adapter) 705 adapter_get_address(serv_adapter->adapter, &src); 706 else 707 bacpy(&src, BDADDR_ANY); 708 709 btd_cancel_authorization(&src, &auth->dst); 710 711 reply = not_authorized(auth->msg); 712 dbus_message_unref(auth->msg); 713 g_dbus_send_message(auth->conn, reply); 714 715 dbus_connection_unref(auth->conn); 716 717 serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, 718 auth); 719 g_free(auth); 720 721 auth = next_pending(serv_adapter); 722 if (auth == NULL) 723 goto done; 724 725 if (serv_adapter->adapter) 726 adapter_get_address(serv_adapter->adapter, &src); 727 else 728 bacpy(&src, BDADDR_ANY); 729 730 btd_request_authorization(&src, &auth->dst, 731 auth->uuid, auth_cb, serv_adapter); 732 733done: 734 return dbus_message_new_method_return(msg); 735} 736 737static GDBusMethodTable service_methods[] = { 738 { "AddRecord", "s", "u", add_service_record }, 739 { "UpdateRecord", "us", "", update_service_record }, 740 { "RemoveRecord", "u", "", remove_service_record }, 741 { "RequestAuthorization","su", "", request_authorization, 742 G_DBUS_METHOD_FLAG_ASYNC}, 743 { "CancelAuthorization", "", "", cancel_authorization }, 744 { } 745}; 746 747static void path_unregister(void *data) 748{ 749 struct service_adapter *serv_adapter = data; 750 GSList *l, *next = NULL; 751 752 for (l = serv_adapter->records; l != NULL; l = next) { 753 struct record_data *user_record = l->data; 754 755 next = l->next; 756 757 g_dbus_remove_watch(connection, user_record->listener_id); 758 exit_callback(connection, user_record); 759 } 760} 761 762static int register_interface(const char *path, struct btd_adapter *adapter) 763{ 764 struct service_adapter *serv_adapter; 765 766 DBG("path %s", path); 767 768 serv_adapter = g_try_new0(struct service_adapter, 1); 769 if (serv_adapter == NULL) 770 return -ENOMEM; 771 772 serv_adapter->adapter = adapter; 773 serv_adapter->pending_list = NULL; 774 775 if (g_dbus_register_interface(connection, path, SERVICE_INTERFACE, 776 service_methods, NULL, NULL, serv_adapter, 777 path_unregister) == FALSE) { 778 error("D-Bus failed to register %s interface", 779 SERVICE_INTERFACE); 780 g_free(serv_adapter); 781 return -EIO; 782 } 783 784 info("Registered interface %s on path %s", SERVICE_INTERFACE, path); 785 786 return 0; 787} 788 789static void unregister_interface(const char *path) 790{ 791 DBG("path %s", path); 792 793 g_dbus_unregister_interface(connection, path, SERVICE_INTERFACE); 794} 795 796static int service_probe(struct btd_adapter *adapter) 797{ 798 register_interface(adapter_get_path(adapter), adapter); 799 800 return 0; 801} 802 803static void service_remove(struct btd_adapter *adapter) 804{ 805 unregister_interface(adapter_get_path(adapter)); 806} 807 808static struct btd_adapter_driver service_driver = { 809 .name = "service", 810 .probe = service_probe, 811 .remove = service_remove, 812}; 813 814static const char *any_path; 815 816static int service_init(void) 817{ 818 int err; 819 820 connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); 821 if (connection == NULL) 822 return -EIO; 823 824 any_path = btd_adapter_any_request_path(); 825 if (any_path != NULL) { 826 if (register_interface(any_path, NULL) < 0) { 827 btd_adapter_any_release_path(); 828 any_path = NULL; 829 } 830 } 831 832 err = btd_register_adapter_driver(&service_driver); 833 if (err < 0) { 834 dbus_connection_unref(connection); 835 return err; 836 } 837 838 return 0; 839} 840 841static void service_exit(void) 842{ 843 btd_unregister_adapter_driver(&service_driver); 844 845 if (any_path != NULL) { 846 unregister_interface(any_path); 847 848 btd_adapter_any_release_path(); 849 any_path = NULL; 850 } 851 852 dbus_connection_unref(connection); 853} 854 855BLUETOOTH_PLUGIN_DEFINE("service", service_init, service_exit) 856