1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2010 Nokia Corporation 6 * Copyright (C) 2010 Marcel Holtmann <marcel (at) holtmann.org> 7 * 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 * 23 */ 24 25 26 #ifdef HAVE_CONFIG_H 27 #include <config.h> 28 #endif 29 30 #include <errno.h> 31 #include <stdlib.h> 32 #include <glib.h> 33 34 #include <bluetooth/bluetooth.h> 35 #include <bluetooth/uuid.h> 36 37 #include "adapter.h" 38 #include "device.h" 39 #include "log.h" 40 #include "gdbus.h" 41 #include "error.h" 42 #include "dbus-common.h" 43 #include "btio.h" 44 #include "storage.h" 45 46 #include "att.h" 47 #include "gattrib.h" 48 #include "gatt.h" 49 #include "client.h" 50 51 #define CHAR_INTERFACE "org.bluez.Characteristic" 52 53 struct gatt_service { 54 struct btd_device *dev; 55 DBusConnection *conn; 56 bdaddr_t sba; 57 bdaddr_t dba; 58 char *path; 59 GSList *primary; 60 GAttrib *attrib; 61 DBusMessage *msg; 62 int psm; 63 gboolean listen; 64 }; 65 66 struct format { 67 guint8 format; 68 guint8 exponent; 69 guint16 unit; 70 guint8 namespace; 71 guint16 desc; 72 } __attribute__ ((packed)); 73 74 struct primary { 75 struct gatt_service *gatt; 76 struct att_primary *att; 77 char *path; 78 GSList *chars; 79 GSList *watchers; 80 }; 81 82 struct characteristic { 83 struct primary *prim; 84 char *path; 85 uint16_t handle; 86 uint16_t end; 87 uint8_t perm; 88 char type[MAX_LEN_UUID_STR + 1]; 89 char *name; 90 char *desc; 91 struct format *format; 92 uint8_t *value; 93 size_t vlen; 94 }; 95 96 struct query_data { 97 struct primary *prim; 98 struct characteristic *chr; 99 DBusMessage *msg; 100 uint16_t handle; 101 }; 102 103 struct watcher { 104 guint id; 105 char *name; 106 char *path; 107 struct primary *prim; 108 }; 109 110 static GSList *gatt_services = NULL; 111 112 static void characteristic_free(void *user_data) 113 { 114 struct characteristic *chr = user_data; 115 116 g_free(chr->path); 117 g_free(chr->desc); 118 g_free(chr->format); 119 g_free(chr->value); 120 g_free(chr->name); 121 g_free(chr); 122 } 123 124 static void watcher_free(void *user_data) 125 { 126 struct watcher *watcher = user_data; 127 128 g_free(watcher->path); 129 g_free(watcher->name); 130 g_free(watcher); 131 } 132 133 static void primary_free(void *user_data) 134 { 135 struct primary *prim = user_data; 136 GSList *l; 137 138 for (l = prim->watchers; l; l = l->next) { 139 struct watcher *watcher = l->data; 140 g_dbus_remove_watch(prim->gatt->conn, watcher->id); 141 } 142 143 g_slist_foreach(prim->chars, (GFunc) characteristic_free, NULL); 144 g_slist_free(prim->chars); 145 g_free(prim->path); 146 g_free(prim); 147 } 148 149 static void gatt_service_free(void *user_data) 150 { 151 struct gatt_service *gatt = user_data; 152 153 g_slist_foreach(gatt->primary, (GFunc) primary_free, NULL); 154 g_slist_free(gatt->primary); 155 g_attrib_unref(gatt->attrib); 156 g_free(gatt->path); 157 btd_device_unref(gatt->dev); 158 dbus_connection_unref(gatt->conn); 159 g_free(gatt); 160 } 161 162 static int gatt_dev_cmp(gconstpointer a, gconstpointer b) 163 { 164 const struct gatt_service *gatt = a; 165 const struct btd_device *dev = b; 166 167 return gatt->dev != dev; 168 } 169 170 static int characteristic_handle_cmp(gconstpointer a, gconstpointer b) 171 { 172 const struct characteristic *chr = a; 173 uint16_t handle = GPOINTER_TO_UINT(b); 174 175 return chr->handle - handle; 176 } 177 178 static int watcher_cmp(gconstpointer a, gconstpointer b) 179 { 180 const struct watcher *watcher = a; 181 const struct watcher *match = b; 182 int ret; 183 184 ret = g_strcmp0(watcher->name, match->name); 185 if (ret != 0) 186 return ret; 187 188 return g_strcmp0(watcher->path, match->path); 189 } 190 191 static void append_char_dict(DBusMessageIter *iter, struct characteristic *chr) 192 { 193 DBusMessageIter dict; 194 const char *name = ""; 195 char *uuid; 196 197 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, 198 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 199 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING 200 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); 201 202 uuid = g_strdup(chr->type); 203 dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &uuid); 204 g_free(uuid); 205 206 /* FIXME: Translate UUID to name. */ 207 dict_append_entry(&dict, "Name", DBUS_TYPE_STRING, &name); 208 209 if (chr->desc) 210 dict_append_entry(&dict, "Description", DBUS_TYPE_STRING, 211 &chr->desc); 212 213 if (chr->value) 214 dict_append_array(&dict, "Value", DBUS_TYPE_BYTE, &chr->value, 215 chr->vlen); 216 217 /* FIXME: Missing Format, Value and Representation */ 218 219 dbus_message_iter_close_container(iter, &dict); 220 } 221 222 static void watcher_exit(DBusConnection *conn, void *user_data) 223 { 224 struct watcher *watcher = user_data; 225 struct primary *prim = watcher->prim; 226 struct gatt_service *gatt = prim->gatt; 227 228 DBG("%s watcher %s exited", prim->path, watcher->name); 229 230 prim->watchers = g_slist_remove(prim->watchers, watcher); 231 232 g_attrib_unref(gatt->attrib); 233 } 234 235 static int characteristic_set_value(struct characteristic *chr, 236 const uint8_t *value, size_t vlen) 237 { 238 chr->value = g_try_realloc(chr->value, vlen); 239 if (chr->value == NULL) 240 return -ENOMEM; 241 242 memcpy(chr->value, value, vlen); 243 chr->vlen = vlen; 244 245 return 0; 246 } 247 248 static void update_watchers(gpointer data, gpointer user_data) 249 { 250 struct watcher *w = data; 251 struct characteristic *chr = user_data; 252 DBusConnection *conn = w->prim->gatt->conn; 253 DBusMessage *msg; 254 255 msg = dbus_message_new_method_call(w->name, w->path, 256 "org.bluez.Watcher", "ValueChanged"); 257 if (msg == NULL) 258 return; 259 260 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &chr->path, 261 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 262 &chr->value, chr->vlen, DBUS_TYPE_INVALID); 263 264 dbus_message_set_no_reply(msg, TRUE); 265 g_dbus_send_message(conn, msg); 266 } 267 268 static void events_handler(const uint8_t *pdu, uint16_t len, 269 gpointer user_data) 270 { 271 struct gatt_service *gatt = user_data; 272 struct characteristic *chr; 273 struct primary *prim; 274 GSList *lprim, *lchr; 275 uint8_t opdu[ATT_MAX_MTU]; 276 guint handle; 277 uint16_t olen; 278 279 if (len < 3) { 280 DBG("Malformed notification/indication packet (opcode 0x%02x)", 281 pdu[0]); 282 return; 283 } 284 285 handle = att_get_u16(&pdu[1]); 286 287 for (lprim = gatt->primary, prim = NULL, chr = NULL; lprim; 288 lprim = lprim->next) { 289 prim = lprim->data; 290 291 lchr = g_slist_find_custom(prim->chars, 292 GUINT_TO_POINTER(handle), characteristic_handle_cmp); 293 if (lchr) { 294 chr = lchr->data; 295 break; 296 } 297 } 298 299 if (chr == NULL) { 300 DBG("Attribute handle 0x%02x not found", handle); 301 return; 302 } 303 304 switch (pdu[0]) { 305 case ATT_OP_HANDLE_IND: 306 olen = enc_confirmation(opdu, sizeof(opdu)); 307 g_attrib_send(gatt->attrib, 0, opdu[0], opdu, olen, 308 NULL, NULL, NULL); 309 case ATT_OP_HANDLE_NOTIFY: 310 if (characteristic_set_value(chr, &pdu[3], len - 3) < 0) 311 DBG("Can't change Characteristic 0x%02x", handle); 312 313 g_slist_foreach(prim->watchers, update_watchers, chr); 314 break; 315 } 316 } 317 318 static void attrib_destroy(gpointer user_data) 319 { 320 struct gatt_service *gatt = user_data; 321 322 gatt->attrib = NULL; 323 } 324 325 static void attrib_disconnect(gpointer user_data) 326 { 327 struct gatt_service *gatt = user_data; 328 329 /* Remote initiated disconnection only */ 330 g_attrib_unref(gatt->attrib); 331 } 332 333 static void connect_cb(GIOChannel *chan, GError *gerr, gpointer user_data) 334 { 335 struct gatt_service *gatt = user_data; 336 337 if (gerr) { 338 if (gatt->msg) { 339 DBusMessage *reply = btd_error_failed(gatt->msg, 340 gerr->message); 341 g_dbus_send_message(gatt->conn, reply); 342 } 343 344 error("%s", gerr->message); 345 goto fail; 346 } 347 348 if (gatt->attrib == NULL) 349 return; 350 351 /* Listen mode: used for notification and indication */ 352 if (gatt->listen == TRUE) { 353 g_attrib_register(gatt->attrib, 354 ATT_OP_HANDLE_NOTIFY, 355 events_handler, gatt, NULL); 356 g_attrib_register(gatt->attrib, 357 ATT_OP_HANDLE_IND, 358 events_handler, gatt, NULL); 359 return; 360 } 361 362 return; 363 fail: 364 g_attrib_unref(gatt->attrib); 365 } 366 367 static int l2cap_connect(struct gatt_service *gatt, GError **gerr, 368 gboolean listen) 369 { 370 GIOChannel *io; 371 372 if (gatt->attrib != NULL) { 373 gatt->attrib = g_attrib_ref(gatt->attrib); 374 gatt->listen = listen; 375 return 0; 376 } 377 378 /* 379 * FIXME: If the service doesn't support Client Characteristic 380 * Configuration it is necessary to poll the server from time 381 * to time checking for modifications. 382 */ 383 if (gatt->psm < 0) 384 io = bt_io_connect(BT_IO_L2CAP, connect_cb, gatt, NULL, gerr, 385 BT_IO_OPT_SOURCE_BDADDR, &gatt->sba, 386 BT_IO_OPT_DEST_BDADDR, &gatt->dba, 387 BT_IO_OPT_CID, ATT_CID, 388 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, 389 BT_IO_OPT_INVALID); 390 else 391 io = bt_io_connect(BT_IO_L2CAP, connect_cb, gatt, NULL, gerr, 392 BT_IO_OPT_SOURCE_BDADDR, &gatt->sba, 393 BT_IO_OPT_DEST_BDADDR, &gatt->dba, 394 BT_IO_OPT_PSM, gatt->psm, 395 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, 396 BT_IO_OPT_INVALID); 397 if (!io) 398 return -1; 399 400 gatt->attrib = g_attrib_new(io); 401 g_io_channel_unref(io); 402 gatt->listen = listen; 403 404 g_attrib_set_destroy_function(gatt->attrib, attrib_destroy, gatt); 405 g_attrib_set_disconnect_function(gatt->attrib, attrib_disconnect, 406 gatt); 407 408 return 0; 409 } 410 411 static DBusMessage *register_watcher(DBusConnection *conn, 412 DBusMessage *msg, void *data) 413 { 414 const char *sender = dbus_message_get_sender(msg); 415 struct primary *prim = data; 416 struct watcher *watcher; 417 GError *gerr = NULL; 418 char *path; 419 420 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path, 421 DBUS_TYPE_INVALID)) 422 return btd_error_invalid_args(msg); 423 424 if (l2cap_connect(prim->gatt, &gerr, TRUE) < 0) { 425 DBusMessage *reply = btd_error_failed(msg, gerr->message); 426 g_error_free(gerr); 427 return reply; 428 } 429 430 watcher = g_new0(struct watcher, 1); 431 watcher->name = g_strdup(sender); 432 watcher->prim = prim; 433 watcher->path = g_strdup(path); 434 watcher->id = g_dbus_add_disconnect_watch(conn, sender, watcher_exit, 435 watcher, watcher_free); 436 437 prim->watchers = g_slist_append(prim->watchers, watcher); 438 439 return dbus_message_new_method_return(msg); 440 } 441 442 static DBusMessage *unregister_watcher(DBusConnection *conn, 443 DBusMessage *msg, void *data) 444 { 445 const char *sender = dbus_message_get_sender(msg); 446 struct primary *prim = data; 447 struct watcher *watcher, *match; 448 GSList *l; 449 char *path; 450 451 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path, 452 DBUS_TYPE_INVALID)) 453 return btd_error_invalid_args(msg); 454 455 match = g_new0(struct watcher, 1); 456 match->name = g_strdup(sender); 457 match->path = g_strdup(path); 458 l = g_slist_find_custom(prim->watchers, match, watcher_cmp); 459 watcher_free(match); 460 if (!l) 461 return btd_error_not_authorized(msg); 462 463 watcher = l->data; 464 g_dbus_remove_watch(conn, watcher->id); 465 prim->watchers = g_slist_remove(prim->watchers, watcher); 466 watcher_free(watcher); 467 468 return dbus_message_new_method_return(msg); 469 } 470 471 static DBusMessage *set_value(DBusConnection *conn, DBusMessage *msg, 472 DBusMessageIter *iter, struct characteristic *chr) 473 { 474 struct gatt_service *gatt = chr->prim->gatt; 475 DBusMessageIter sub; 476 GError *gerr = NULL; 477 uint8_t *value; 478 int len; 479 480 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY || 481 dbus_message_iter_get_element_type(iter) != DBUS_TYPE_BYTE) 482 return btd_error_invalid_args(msg); 483 484 dbus_message_iter_recurse(iter, &sub); 485 486 dbus_message_iter_get_fixed_array(&sub, &value, &len); 487 488 if (l2cap_connect(gatt, &gerr, FALSE) < 0) { 489 DBusMessage *reply = btd_error_failed(msg, gerr->message); 490 g_error_free(gerr); 491 return reply; 492 } 493 494 gatt_write_cmd(gatt->attrib, chr->handle, value, len, NULL, NULL); 495 496 characteristic_set_value(chr, value, len); 497 498 return dbus_message_new_method_return(msg); 499 } 500 501 static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg, 502 void *data) 503 { 504 struct characteristic *chr = data; 505 DBusMessage *reply; 506 DBusMessageIter iter; 507 508 reply = dbus_message_new_method_return(msg); 509 if (!reply) 510 return NULL; 511 512 dbus_message_iter_init_append(reply, &iter); 513 514 append_char_dict(&iter, chr); 515 516 return reply; 517 } 518 519 static DBusMessage *set_property(DBusConnection *conn, 520 DBusMessage *msg, void *data) 521 { 522 struct characteristic *chr = data; 523 DBusMessageIter iter; 524 DBusMessageIter sub; 525 const char *property; 526 527 if (!dbus_message_iter_init(msg, &iter)) 528 return btd_error_invalid_args(msg); 529 530 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) 531 return btd_error_invalid_args(msg); 532 533 dbus_message_iter_get_basic(&iter, &property); 534 dbus_message_iter_next(&iter); 535 536 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) 537 return btd_error_invalid_args(msg); 538 539 dbus_message_iter_recurse(&iter, &sub); 540 541 if (g_str_equal("Value", property)) 542 return set_value(conn, msg, &sub, chr); 543 544 return btd_error_invalid_args(msg); 545 } 546 547 static GDBusMethodTable char_methods[] = { 548 { "GetProperties", "", "a{sv}", get_properties }, 549 { "SetProperty", "sv", "", set_property, 550 G_DBUS_METHOD_FLAG_ASYNC}, 551 { } 552 }; 553 554 static char *characteristic_list_to_string(GSList *chars) 555 { 556 GString *characteristics; 557 GSList *l; 558 559 characteristics = g_string_new(NULL); 560 561 for (l = chars; l; l = l->next) { 562 struct characteristic *chr = l->data; 563 char chr_str[64]; 564 565 memset(chr_str, 0, sizeof(chr_str)); 566 567 snprintf(chr_str, sizeof(chr_str), "%04X#%02X#%04X#%s ", 568 chr->handle, chr->perm, chr->end, chr->type); 569 570 characteristics = g_string_append(characteristics, chr_str); 571 } 572 573 return g_string_free(characteristics, FALSE); 574 } 575 576 static void store_characteristics(struct gatt_service *gatt, 577 struct primary *prim) 578 { 579 char *characteristics; 580 struct att_primary *att = prim->att; 581 582 characteristics = characteristic_list_to_string(prim->chars); 583 584 write_device_characteristics(&gatt->sba, &gatt->dba, att->start, 585 characteristics); 586 587 g_free(characteristics); 588 } 589 590 static void register_characteristics(struct primary *prim) 591 { 592 GSList *lc; 593 594 for (lc = prim->chars; lc; lc = lc->next) { 595 struct characteristic *chr = lc->data; 596 g_dbus_register_interface(prim->gatt->conn, chr->path, 597 CHAR_INTERFACE, char_methods, 598 NULL, NULL, chr, NULL); 599 DBG("Registered: %s", chr->path); 600 } 601 } 602 603 static GSList *string_to_characteristic_list(struct primary *prim, 604 const char *str) 605 { 606 GSList *l = NULL; 607 char **chars; 608 int i; 609 610 if (str == NULL) 611 return NULL; 612 613 chars = g_strsplit(str, " ", 0); 614 if (chars == NULL) 615 return NULL; 616 617 for (i = 0; chars[i]; i++) { 618 struct characteristic *chr; 619 int ret; 620 621 chr = g_new0(struct characteristic, 1); 622 623 ret = sscanf(chars[i], "%04hX#%02hhX#%04hX#%s", &chr->handle, 624 &chr->perm, &chr->end, chr->type); 625 if (ret < 4) { 626 g_free(chr); 627 continue; 628 } 629 630 chr->prim = prim; 631 chr->path = g_strdup_printf("%s/characteristic%04x", 632 prim->path, chr->handle); 633 634 l = g_slist_append(l, chr); 635 } 636 637 g_strfreev(chars); 638 639 return l; 640 } 641 642 static void load_characteristics(gpointer data, gpointer user_data) 643 { 644 struct primary *prim = data; 645 struct att_primary *att = prim->att; 646 struct gatt_service *gatt = user_data; 647 GSList *chrs_list; 648 char *str; 649 650 if (prim->chars) { 651 DBG("Characteristics already loaded"); 652 return; 653 } 654 655 str = read_device_characteristics(&gatt->sba, &gatt->dba, att->start); 656 if (str == NULL) 657 return; 658 659 chrs_list = string_to_characteristic_list(prim, str); 660 661 free(str); 662 663 if (chrs_list == NULL) 664 return; 665 666 prim->chars = chrs_list; 667 register_characteristics(prim); 668 669 return; 670 } 671 672 static void store_attribute(struct gatt_service *gatt, uint16_t handle, 673 uint16_t type, uint8_t *value, gsize len) 674 { 675 bt_uuid_t uuid; 676 char *str, *tmp; 677 guint i; 678 679 str = g_malloc0(MAX_LEN_UUID_STR + len * 2 + 1); 680 681 bt_uuid16_create(&uuid, type); 682 bt_uuid_to_string(&uuid, str, MAX_LEN_UUID_STR); 683 684 str[MAX_LEN_UUID_STR - 1] = '#'; 685 686 for (i = 0, tmp = str + MAX_LEN_UUID_STR; i < len; i++, tmp += 2) 687 sprintf(tmp, "%02X", value[i]); 688 689 write_device_attribute(&gatt->sba, &gatt->dba, handle, str); 690 g_free(str); 691 } 692 693 static void update_char_desc(guint8 status, const guint8 *pdu, guint16 len, 694 gpointer user_data) 695 { 696 struct query_data *current = user_data; 697 struct gatt_service *gatt = current->prim->gatt; 698 struct characteristic *chr = current->chr; 699 700 if (status == 0) { 701 702 g_free(chr->desc); 703 704 chr->desc = g_malloc(len); 705 memcpy(chr->desc, pdu + 1, len - 1); 706 chr->desc[len - 1] = '\0'; 707 708 store_attribute(gatt, current->handle, 709 GATT_CHARAC_USER_DESC_UUID, 710 (void *) chr->desc, len); 711 } else if (status == ATT_ECODE_INSUFF_ENC) { 712 GIOChannel *io = g_attrib_get_channel(gatt->attrib); 713 714 if (bt_io_set(io, BT_IO_L2CAP, NULL, 715 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_HIGH, 716 BT_IO_OPT_INVALID)) { 717 gatt_read_char(gatt->attrib, current->handle, 0, 718 update_char_desc, current); 719 return; 720 } 721 } 722 723 g_attrib_unref(gatt->attrib); 724 g_free(current); 725 } 726 727 static void update_char_format(guint8 status, const guint8 *pdu, guint16 len, 728 gpointer user_data) 729 { 730 struct query_data *current = user_data; 731 struct gatt_service *gatt = current->prim->gatt; 732 struct characteristic *chr = current->chr; 733 734 if (status != 0) 735 goto done; 736 737 if (len < 8) 738 goto done; 739 740 g_free(chr->format); 741 742 chr->format = g_new0(struct format, 1); 743 memcpy(chr->format, pdu + 1, 7); 744 745 store_attribute(gatt, current->handle, GATT_CHARAC_FMT_UUID, 746 (void *) chr->format, sizeof(*chr->format)); 747 748 done: 749 g_attrib_unref(gatt->attrib); 750 g_free(current); 751 } 752 753 static void update_char_value(guint8 status, const guint8 *pdu, 754 guint16 len, gpointer user_data) 755 { 756 struct query_data *current = user_data; 757 struct gatt_service *gatt = current->prim->gatt; 758 struct characteristic *chr = current->chr; 759 760 if (status == 0) 761 characteristic_set_value(chr, pdu + 1, len - 1); 762 else if (status == ATT_ECODE_INSUFF_ENC) { 763 GIOChannel *io = g_attrib_get_channel(gatt->attrib); 764 765 if (bt_io_set(io, BT_IO_L2CAP, NULL, 766 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_HIGH, 767 BT_IO_OPT_INVALID)) { 768 gatt_read_char(gatt->attrib, chr->handle, 0, 769 update_char_value, current); 770 return; 771 } 772 } 773 774 g_attrib_unref(gatt->attrib); 775 g_free(current); 776 } 777 778 static int uuid_desc16_cmp(bt_uuid_t *uuid, guint16 desc) 779 { 780 bt_uuid_t u16; 781 782 bt_uuid16_create(&u16, desc); 783 784 return bt_uuid_cmp(uuid, &u16); 785 } 786 787 static void descriptor_cb(guint8 status, const guint8 *pdu, guint16 plen, 788 gpointer user_data) 789 { 790 struct query_data *current = user_data; 791 struct gatt_service *gatt = current->prim->gatt; 792 struct att_data_list *list; 793 guint8 format; 794 int i; 795 796 if (status != 0) 797 goto done; 798 799 DBG("Find Information Response received"); 800 801 list = dec_find_info_resp(pdu, plen, &format); 802 if (list == NULL) 803 goto done; 804 805 for (i = 0; i < list->num; i++) { 806 guint16 handle; 807 bt_uuid_t uuid; 808 uint8_t *info = list->data[i]; 809 struct query_data *qfmt; 810 811 handle = att_get_u16(info); 812 813 if (format == 0x01) { 814 uuid = att_get_uuid16(&info[2]); 815 } else { 816 /* Currently, only "user description" and "presentation 817 * format" descriptors are used, and both have 16-bit 818 * UUIDs. Therefore there is no need to support format 819 * 0x02 yet. */ 820 continue; 821 } 822 qfmt = g_new0(struct query_data, 1); 823 qfmt->prim = current->prim; 824 qfmt->chr = current->chr; 825 qfmt->handle = handle; 826 827 if (uuid_desc16_cmp(&uuid, GATT_CHARAC_USER_DESC_UUID) == 0) { 828 gatt->attrib = g_attrib_ref(gatt->attrib); 829 gatt_read_char(gatt->attrib, handle, 0, update_char_desc, 830 qfmt); 831 } else if (uuid_desc16_cmp(&uuid, GATT_CHARAC_FMT_UUID) == 0) { 832 gatt->attrib = g_attrib_ref(gatt->attrib); 833 gatt_read_char(gatt->attrib, handle, 0, 834 update_char_format, qfmt); 835 } else 836 g_free(qfmt); 837 } 838 839 att_data_list_free(list); 840 done: 841 g_attrib_unref(gatt->attrib); 842 g_free(current); 843 } 844 845 static void update_all_chars(gpointer data, gpointer user_data) 846 { 847 struct query_data *qdesc, *qvalue; 848 struct characteristic *chr = data; 849 struct primary *prim = user_data; 850 struct gatt_service *gatt = prim->gatt; 851 852 qdesc = g_new0(struct query_data, 1); 853 qdesc->prim = prim; 854 qdesc->chr = chr; 855 856 gatt->attrib = g_attrib_ref(gatt->attrib); 857 gatt_find_info(gatt->attrib, chr->handle + 1, chr->end, descriptor_cb, 858 qdesc); 859 860 qvalue = g_new0(struct query_data, 1); 861 qvalue->prim = prim; 862 qvalue->chr = chr; 863 864 gatt->attrib = g_attrib_ref(gatt->attrib); 865 gatt_read_char(gatt->attrib, chr->handle, 0, update_char_value, qvalue); 866 } 867 868 static void char_discovered_cb(GSList *characteristics, guint8 status, 869 gpointer user_data) 870 { 871 DBusMessage *reply; 872 DBusMessageIter iter, array_iter; 873 struct query_data *current = user_data; 874 struct primary *prim = current->prim; 875 struct att_primary *att = prim->att; 876 struct gatt_service *gatt = prim->gatt; 877 uint16_t *previous_end = NULL; 878 GSList *l; 879 880 if (status != 0) { 881 const char *str = att_ecode2str(status); 882 883 DBG("Discover all characteristics failed: %s", str); 884 reply = btd_error_failed(current->msg, str); 885 goto fail; 886 } 887 888 for (l = characteristics; l; l = l->next) { 889 struct att_char *current_chr = l->data; 890 struct characteristic *chr; 891 guint handle = current_chr->value_handle; 892 GSList *lchr; 893 894 lchr = g_slist_find_custom(prim->chars, 895 GUINT_TO_POINTER(handle), characteristic_handle_cmp); 896 if (lchr) 897 continue; 898 899 chr = g_new0(struct characteristic, 1); 900 chr->prim = prim; 901 chr->perm = current_chr->properties; 902 chr->handle = current_chr->value_handle; 903 chr->path = g_strdup_printf("%s/characteristic%04x", 904 prim->path, chr->handle); 905 strncpy(chr->type, current_chr->uuid, sizeof(chr->type)); 906 907 if (previous_end) 908 *previous_end = current_chr->handle; 909 910 previous_end = &chr->end; 911 912 prim->chars = g_slist_append(prim->chars, chr); 913 } 914 915 if (previous_end) 916 *previous_end = att->end; 917 918 store_characteristics(gatt, prim); 919 register_characteristics(prim); 920 921 reply = dbus_message_new_method_return(current->msg); 922 923 dbus_message_iter_init_append(reply, &iter); 924 925 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 926 DBUS_TYPE_OBJECT_PATH_AS_STRING, &array_iter); 927 928 for (l = prim->chars; l; l = l->next) { 929 struct characteristic *chr = l->data; 930 931 dbus_message_iter_append_basic(&array_iter, 932 DBUS_TYPE_OBJECT_PATH, &chr->path); 933 } 934 935 dbus_message_iter_close_container(&iter, &array_iter); 936 937 g_slist_foreach(prim->chars, update_all_chars, prim); 938 939 fail: 940 g_dbus_send_message(gatt->conn, reply); 941 g_attrib_unref(gatt->attrib); 942 g_free(current); 943 } 944 945 static DBusMessage *discover_char(DBusConnection *conn, DBusMessage *msg, 946 void *data) 947 { 948 struct primary *prim = data; 949 struct att_primary *att = prim->att; 950 struct gatt_service *gatt = prim->gatt; 951 struct query_data *qchr; 952 GError *gerr = NULL; 953 954 if (l2cap_connect(prim->gatt, &gerr, FALSE) < 0) { 955 DBusMessage *reply = btd_error_failed(msg, gerr->message); 956 g_error_free(gerr); 957 return reply; 958 } 959 960 qchr = g_new0(struct query_data, 1); 961 qchr->prim = prim; 962 qchr->msg = dbus_message_ref(msg); 963 964 gatt_discover_char(gatt->attrib, att->start, att->end, NULL, 965 char_discovered_cb, qchr); 966 967 return NULL; 968 } 969 970 static DBusMessage *prim_get_properties(DBusConnection *conn, DBusMessage *msg, 971 void *data) 972 { 973 struct primary *prim = data; 974 DBusMessage *reply; 975 DBusMessageIter iter; 976 DBusMessageIter dict; 977 GSList *l; 978 char **chars; 979 const char *uuid; 980 int i; 981 982 reply = dbus_message_new_method_return(msg); 983 if (!reply) 984 return NULL; 985 986 dbus_message_iter_init_append(reply, &iter); 987 988 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 989 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 990 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING 991 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); 992 993 chars = g_new0(char *, g_slist_length(prim->chars) + 1); 994 995 for (i = 0, l = prim->chars; l; l = l->next, i++) { 996 struct characteristic *chr = l->data; 997 chars[i] = chr->path; 998 } 999 1000 dict_append_array(&dict, "Characteristics", DBUS_TYPE_OBJECT_PATH, 1001 &chars, i); 1002 uuid = prim->att->uuid; 1003 dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &uuid); 1004 1005 g_free(chars); 1006 1007 dbus_message_iter_close_container(&iter, &dict); 1008 1009 return reply; 1010 } 1011 1012 static GDBusMethodTable prim_methods[] = { 1013 { "DiscoverCharacteristics", "", "ao", discover_char, 1014 G_DBUS_METHOD_FLAG_ASYNC }, 1015 { "RegisterCharacteristicsWatcher", "o", "", 1016 register_watcher }, 1017 { "UnregisterCharacteristicsWatcher", "o", "", 1018 unregister_watcher }, 1019 { "GetProperties", "", "a{sv}",prim_get_properties }, 1020 { } 1021 }; 1022 1023 static GSList *register_primaries(struct gatt_service *gatt, GSList *primaries) 1024 { 1025 GSList *l, *paths; 1026 1027 for (paths = NULL, l = primaries; l; l = l->next) { 1028 struct att_primary *att = l->data; 1029 struct primary *prim; 1030 1031 prim = g_new0(struct primary, 1); 1032 prim->att = att; 1033 prim->gatt = gatt; 1034 prim->path = g_strdup_printf("%s/service%04x", gatt->path, 1035 att->start); 1036 1037 g_dbus_register_interface(gatt->conn, prim->path, 1038 CHAR_INTERFACE, prim_methods, 1039 NULL, NULL, prim, NULL); 1040 DBG("Registered: %s", prim->path); 1041 1042 gatt->primary = g_slist_append(gatt->primary, prim); 1043 paths = g_slist_append(paths, g_strdup(prim->path)); 1044 load_characteristics(prim, gatt); 1045 } 1046 1047 return paths; 1048 } 1049 1050 GSList *attrib_client_register(DBusConnection *connection, 1051 struct btd_device *device, int psm, 1052 GAttrib *attrib, GSList *primaries) 1053 { 1054 struct btd_adapter *adapter = device_get_adapter(device); 1055 const char *path = device_get_path(device); 1056 struct gatt_service *gatt; 1057 bdaddr_t sba, dba; 1058 1059 adapter_get_address(adapter, &sba); 1060 device_get_address(device, &dba); 1061 1062 gatt = g_new0(struct gatt_service, 1); 1063 gatt->dev = btd_device_ref(device); 1064 gatt->conn = dbus_connection_ref(connection); 1065 gatt->listen = FALSE; 1066 gatt->path = g_strdup(path); 1067 bacpy(&gatt->sba, &sba); 1068 bacpy(&gatt->dba, &dba); 1069 gatt->psm = psm; 1070 1071 if (attrib) 1072 gatt->attrib = g_attrib_ref(attrib); 1073 1074 gatt_services = g_slist_append(gatt_services, gatt); 1075 1076 return register_primaries(gatt, primaries); 1077 } 1078 1079 void attrib_client_unregister(struct btd_device *device) 1080 { 1081 struct gatt_service *gatt; 1082 GSList *l, *lp, *lc; 1083 1084 l = g_slist_find_custom(gatt_services, device, gatt_dev_cmp); 1085 if (!l) 1086 return; 1087 1088 gatt = l->data; 1089 gatt_services = g_slist_remove(gatt_services, gatt); 1090 1091 for (lp = gatt->primary; lp; lp = lp->next) { 1092 struct primary *prim = lp->data; 1093 for (lc = prim->chars; lc; lc = lc->next) { 1094 struct characteristic *chr = lc->data; 1095 g_dbus_unregister_interface(gatt->conn, chr->path, 1096 CHAR_INTERFACE); 1097 } 1098 g_dbus_unregister_interface(gatt->conn, prim->path, 1099 CHAR_INTERFACE); 1100 } 1101 1102 gatt_service_free(gatt); 1103 } 1104