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