1 /****************************************************************************** 2 * 3 * Copyright (C) 2003-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 /****************************************************************************** 20 * 21 * This file contains the GATT client discovery procedures and cache 22 * related functions. 23 * 24 ******************************************************************************/ 25 26 #define LOG_TAG "bt_bta_gattc" 27 28 #include "bt_target.h" 29 30 #if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE) 31 32 #include <errno.h> 33 #include <stdio.h> 34 #include <string.h> 35 36 #include "bta_gattc_int.h" 37 #include "bta_sys.h" 38 #include "btm_api.h" 39 #include "btm_ble_api.h" 40 #include "btm_int.h" 41 #include "bt_common.h" 42 #include "osi/include/log.h" 43 #include "sdp_api.h" 44 #include "sdpdefs.h" 45 #include "utl.h" 46 47 static void bta_gattc_cache_write(BD_ADDR server_bda, UINT16 num_attr, tBTA_GATTC_NV_ATTR *attr); 48 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb); 49 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb); 50 extern void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src); 51 tBTA_GATTC_SERVICE* bta_gattc_find_matching_service(const list_t *services, UINT16 handle); 52 tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle); 53 tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle); 54 55 #define BTA_GATT_SDP_DB_SIZE 4096 56 57 #define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_" 58 #define GATT_CACHE_VERSION 2 59 60 static void bta_gattc_generate_cache_file_name(char *buffer, BD_ADDR bda) 61 { 62 sprintf(buffer, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX, 63 bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); 64 } 65 66 /***************************************************************************** 67 ** Constants and data types 68 *****************************************************************************/ 69 70 typedef struct 71 { 72 tSDP_DISCOVERY_DB *p_sdp_db; 73 UINT16 sdp_conn_id; 74 } tBTA_GATTC_CB_DATA; 75 76 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 77 static char *bta_gattc_attr_type[] = 78 { 79 "I", /* Included Service */ 80 "C", /* Characteristic */ 81 "D" /* Characteristic Descriptor */ 82 }; 83 /* utility functions */ 84 85 bool display_cache_attribute(void *data, void *context) { 86 tBTA_GATTC_CACHE_ATTR *p_attr = data; 87 APPL_TRACE_ERROR("\t Attr handle[%d] uuid[0x%04x] type[%s] prop[0x%1x]", 88 p_attr->handle, p_attr->uuid.uu.uuid16, 89 bta_gattc_attr_type[p_attr->attr_type], p_attr->property); 90 return true; 91 } 92 93 bool display_cache_service(void *data, void *context) { 94 tBTA_GATTC_SERVICE *p_cur_srvc = data; 95 APPL_TRACE_ERROR("Service: handle[%d ~ %d] %s[0x%04x] inst[%d]", 96 p_cur_srvc->s_handle, p_cur_srvc->e_handle, 97 ((p_cur_srvc->uuid.len == 2) ? "uuid16" : "uuid128"), 98 p_cur_srvc->uuid.uu.uuid16, 99 p_cur_srvc->handle); 100 101 if (p_cur_srvc->characteristics != NULL) { 102 list_foreach(p_cur_srvc->characteristics, display_cache_attribute, NULL); 103 } 104 105 return true; 106 } 107 108 /******************************************************************************* 109 ** 110 ** Function bta_gattc_display_cache_server 111 ** 112 ** Description debug function to display the server cache. 113 ** 114 ** Returns none. 115 ** 116 *******************************************************************************/ 117 static void bta_gattc_display_cache_server(list_t *p_cache) 118 { 119 APPL_TRACE_ERROR("<================Start Server Cache =============>"); 120 list_foreach(p_cache, display_cache_service, NULL); 121 APPL_TRACE_ERROR("<================End Server Cache =============>"); 122 APPL_TRACE_ERROR(" "); 123 } 124 125 /******************************************************************************* 126 ** 127 ** Function bta_gattc_display_explore_record 128 ** 129 ** Description debug function to display the exploration list 130 ** 131 ** Returns none. 132 ** 133 *******************************************************************************/ 134 static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC *p_rec, UINT8 num_rec) 135 { 136 UINT8 i; 137 tBTA_GATTC_ATTR_REC *pp = p_rec; 138 139 APPL_TRACE_ERROR("<================Start Explore Queue =============>"); 140 for (i = 0; i < num_rec; i ++, pp ++) 141 { 142 APPL_TRACE_ERROR("\t rec[%d] uuid[0x%04x] s_handle[%d] e_handle[%d] is_primary[%d]", 143 i + 1, pp->uuid.uu.uuid16, pp->s_handle, pp->e_handle, pp->is_primary); 144 } 145 APPL_TRACE_ERROR("<================ End Explore Queue =============>"); 146 APPL_TRACE_ERROR(" "); 147 148 } 149 #endif /* BTA_GATT_DEBUG == TRUE */ 150 151 /******************************************************************************* 152 ** 153 ** Function bta_gattc_init_cache 154 ** 155 ** Description Initialize the database cache and discovery related resources. 156 ** 157 ** Returns status 158 ** 159 *******************************************************************************/ 160 tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb) 161 { 162 if (p_srvc_cb->p_srvc_cache != NULL) { 163 list_free(p_srvc_cb->p_srvc_cache); 164 p_srvc_cb->p_srvc_cache = NULL; 165 } 166 167 osi_free(p_srvc_cb->p_srvc_list); 168 p_srvc_cb->p_srvc_list = 169 (tBTA_GATTC_ATTR_REC *)osi_malloc(BTA_GATTC_ATTR_LIST_SIZE); 170 p_srvc_cb->total_srvc = 0; 171 p_srvc_cb->cur_srvc_idx = 0; 172 p_srvc_cb->cur_char_idx = 0; 173 p_srvc_cb->next_avail_idx = 0; 174 175 return BTA_GATT_OK; 176 } 177 178 static void characteristic_free(void *ptr) { 179 tBTA_GATTC_CHARACTERISTIC *p_char = ptr; 180 list_free(p_char->descriptors); 181 osi_free(p_char); 182 } 183 184 static void service_free(void *ptr) { 185 tBTA_GATTC_SERVICE *srvc = ptr; 186 list_free(srvc->characteristics); 187 list_free(srvc->included_svc); 188 osi_free(srvc); 189 } 190 191 /******************************************************************************* 192 ** 193 ** Function bta_gattc_add_srvc_to_cache 194 ** 195 ** Description Add a service into database cache. 196 ** 197 ** Returns status 198 ** 199 *******************************************************************************/ 200 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb, 201 UINT16 s_handle, UINT16 e_handle, 202 tBT_UUID *p_uuid, 203 BOOLEAN is_primary) 204 { 205 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 206 APPL_TRACE_DEBUG("Add a service into Service"); 207 #endif 208 209 tBTA_GATTC_SERVICE *p_new_srvc = osi_malloc(sizeof(tBTA_GATTC_SERVICE)); 210 211 /* update service information */ 212 p_new_srvc->s_handle = s_handle; 213 p_new_srvc->e_handle = e_handle; 214 p_new_srvc->is_primary = is_primary; 215 memcpy(&p_new_srvc->uuid, p_uuid, sizeof(tBT_UUID)); 216 p_new_srvc->handle = s_handle; 217 p_new_srvc->characteristics = list_new(characteristic_free); 218 p_new_srvc->included_svc = list_new(osi_free); 219 220 if (p_srvc_cb->p_srvc_cache == NULL) { 221 p_srvc_cb->p_srvc_cache = list_new(service_free); 222 } 223 224 list_append(p_srvc_cb->p_srvc_cache, p_new_srvc); 225 return BTA_GATT_OK; 226 } 227 228 static tBTA_GATT_STATUS bta_gattc_add_char_to_cache(tBTA_GATTC_SERV *p_srvc_cb, 229 UINT16 attr_handle, 230 UINT16 value_handle, 231 tBT_UUID *p_uuid, 232 UINT8 property) 233 { 234 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 235 APPL_TRACE_DEBUG("%s: Add a characteristic into Service", __func__); 236 APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x", 237 value_handle, p_uuid->uu.uuid16, property); 238 #endif 239 240 tBTA_GATTC_SERVICE *service = bta_gattc_find_matching_service(p_srvc_cb->p_srvc_cache, attr_handle); 241 if (!service) { 242 APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc for non-existing service!"); 243 return GATT_WRONG_STATE; 244 } 245 246 /* TODO(jpawlowski): We should use attribute handle, not value handle to refer to characteristic. 247 This is just a temporary workaround. 248 */ 249 if (service->e_handle < value_handle) 250 service->e_handle = value_handle; 251 252 tBTA_GATTC_CHARACTERISTIC *characteristic = osi_malloc(sizeof(tBTA_GATTC_CHARACTERISTIC)); 253 254 characteristic->handle = value_handle; 255 characteristic->properties = property; 256 characteristic->descriptors = list_new(osi_free); 257 memcpy(&characteristic->uuid, p_uuid, sizeof(tBT_UUID)); 258 259 characteristic->service = service; 260 list_append(service->characteristics, characteristic); 261 262 return BTA_GATT_OK; 263 } 264 265 /******************************************************************************* 266 ** 267 ** Function bta_gattc_add_attr_to_cache 268 ** 269 ** Description Add an attribute into database cache buffer. 270 ** 271 ** Returns status 272 ** 273 *******************************************************************************/ 274 static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb, 275 UINT16 handle, 276 tBT_UUID *p_uuid, 277 UINT8 property, 278 UINT16 incl_srvc_s_handle, 279 tBTA_GATTC_ATTR_TYPE type) 280 { 281 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 282 APPL_TRACE_DEBUG("%s: Add a [%s] into Service", __func__, bta_gattc_attr_type[type]); 283 APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d", 284 handle, p_uuid->uu.uuid16, property, type); 285 #endif 286 287 tBTA_GATTC_SERVICE *service = bta_gattc_find_matching_service(p_srvc_cb->p_srvc_cache, handle); 288 if (!service) { 289 APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc for non-existing service!"); 290 return GATT_WRONG_STATE; 291 } 292 293 if (type == BTA_GATTC_ATTR_TYPE_INCL_SRVC) { 294 tBTA_GATTC_INCLUDED_SVC *isvc = 295 osi_malloc(sizeof(tBTA_GATTC_INCLUDED_SVC)); 296 297 isvc->handle = handle; 298 memcpy(&isvc->uuid, p_uuid, sizeof(tBT_UUID)); 299 300 isvc->owning_service = service; 301 isvc->included_service = bta_gattc_find_matching_service( 302 p_srvc_cb->p_srvc_cache, incl_srvc_s_handle); 303 if (!isvc->included_service) { 304 APPL_TRACE_ERROR("%s: Illegal action to add non-existing included service!", __func__); 305 osi_free(isvc); 306 return GATT_WRONG_STATE; 307 } 308 309 list_append(service->included_svc, isvc); 310 } else if (type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) { 311 tBTA_GATTC_DESCRIPTOR *descriptor = 312 osi_malloc(sizeof(tBTA_GATTC_DESCRIPTOR)); 313 314 descriptor->handle = handle; 315 memcpy(&descriptor->uuid, p_uuid, sizeof(tBT_UUID)); 316 317 if (service->characteristics == NULL) { 318 APPL_TRACE_ERROR("%s: Illegal action to add descriptor before adding a characteristic!", 319 __func__); 320 osi_free(descriptor); 321 return GATT_WRONG_STATE; 322 } 323 324 tBTA_GATTC_CHARACTERISTIC *char_node = list_back(service->characteristics); 325 326 descriptor->characteristic = char_node; 327 list_append(char_node->descriptors, descriptor); 328 } 329 return BTA_GATT_OK; 330 } 331 332 /******************************************************************************* 333 ** 334 ** Function bta_gattc_get_disc_range 335 ** 336 ** Description get discovery stating and ending handle range. 337 ** 338 ** Returns None. 339 ** 340 *******************************************************************************/ 341 void bta_gattc_get_disc_range(tBTA_GATTC_SERV *p_srvc_cb, UINT16 *p_s_hdl, UINT16 *p_e_hdl, BOOLEAN is_srvc) 342 { 343 tBTA_GATTC_ATTR_REC *p_rec = NULL; 344 345 if (is_srvc) 346 { 347 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx; 348 *p_s_hdl = p_rec->s_handle; 349 } 350 else 351 { 352 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx; 353 *p_s_hdl = p_rec->s_handle + 1; 354 } 355 356 *p_e_hdl = p_rec->e_handle; 357 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 358 APPL_TRACE_DEBUG("discover range [%d ~ %d]",p_rec->s_handle, p_rec->e_handle); 359 #endif 360 return; 361 } 362 /******************************************************************************* 363 ** 364 ** Function bta_gattc_discover_pri_service 365 ** 366 ** Description Start primary service discovery 367 ** 368 ** Returns status of the operation. 369 ** 370 *******************************************************************************/ 371 tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, 372 UINT8 disc_type) 373 { 374 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 375 tBTA_GATT_STATUS status = BTA_GATT_ERROR; 376 377 if (p_clcb) 378 { 379 if (p_clcb->transport == BTA_TRANSPORT_LE) 380 status = bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type); 381 else 382 status = bta_gattc_sdp_service_disc(conn_id, p_server_cb); 383 } 384 385 return status; 386 } 387 /******************************************************************************* 388 ** 389 ** Function bta_gattc_discover_procedure 390 ** 391 ** Description Start a particular type of discovery procedure on server. 392 ** 393 ** Returns status of the operation. 394 ** 395 *******************************************************************************/ 396 tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, 397 UINT8 disc_type) 398 { 399 tGATT_DISC_PARAM param; 400 BOOLEAN is_service = TRUE; 401 402 memset(¶m, 0, sizeof(tGATT_DISC_PARAM)); 403 404 if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID) 405 { 406 param.s_handle = 1; 407 param.e_handle = 0xFFFF; 408 } 409 else 410 { 411 if (disc_type == GATT_DISC_CHAR_DSCPT) 412 is_service = FALSE; 413 414 bta_gattc_get_disc_range(p_server_cb, ¶m.s_handle, ¶m.e_handle, is_service); 415 416 if (param.s_handle > param.e_handle) 417 { 418 return GATT_ERROR; 419 } 420 } 421 return GATTC_Discover (conn_id, disc_type, ¶m); 422 423 } 424 /******************************************************************************* 425 ** 426 ** Function bta_gattc_start_disc_include_srvc 427 ** 428 ** Description Start discovery for included service 429 ** 430 ** Returns status of the operation. 431 ** 432 *******************************************************************************/ 433 tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 434 { 435 return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC); 436 } 437 /******************************************************************************* 438 ** 439 ** Function bta_gattc_start_disc_char 440 ** 441 ** Description Start discovery for characteristic 442 ** 443 ** Returns status of the operation. 444 ** 445 *******************************************************************************/ 446 tBTA_GATT_STATUS bta_gattc_start_disc_char(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 447 { 448 p_srvc_cb->total_char = 0; 449 450 return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR); 451 } 452 /******************************************************************************* 453 ** 454 ** Function bta_gattc_start_disc_char_dscp 455 ** 456 ** Description Start discovery for characteristic descriptor 457 ** 458 ** Returns none. 459 ** 460 *******************************************************************************/ 461 void bta_gattc_start_disc_char_dscp(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 462 { 463 APPL_TRACE_DEBUG("starting discover characteristics descriptor"); 464 465 if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) != 0) 466 bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb); 467 468 } 469 /******************************************************************************* 470 ** 471 ** Function bta_gattc_explore_srvc 472 ** 473 ** Description process the service discovery complete event 474 ** 475 ** Returns status 476 ** 477 *******************************************************************************/ 478 static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 479 { 480 tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx; 481 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 482 483 APPL_TRACE_DEBUG("Start service discovery: srvc_idx = %d", p_srvc_cb->cur_srvc_idx); 484 485 p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc; 486 487 if (p_clcb == NULL) 488 { 489 APPL_TRACE_ERROR("unknown connection ID"); 490 return; 491 } 492 /* start expore a service if there is service not been explored */ 493 if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc) 494 { 495 /* add the first service into cache */ 496 if (bta_gattc_add_srvc_to_cache (p_srvc_cb, 497 p_rec->s_handle, 498 p_rec->e_handle, 499 &p_rec->uuid, 500 p_rec->is_primary) == 0) 501 { 502 /* start discovering included services */ 503 bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb); 504 return; 505 } 506 } 507 /* no service found at all, the end of server discovery*/ 508 LOG_WARN(LOG_TAG, "%s no more services found", __func__); 509 510 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 511 bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache); 512 #endif 513 /* save cache to NV */ 514 p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE; 515 516 if (btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) { 517 bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id); 518 } 519 520 bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK); 521 } 522 /******************************************************************************* 523 ** 524 ** Function bta_gattc_incl_srvc_disc_cmpl 525 ** 526 ** Description process the relationship discovery complete event 527 ** 528 ** Returns status 529 ** 530 *******************************************************************************/ 531 static void bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 532 { 533 p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc; 534 535 /* start discoverying characteristic */ 536 bta_gattc_start_disc_char(conn_id, p_srvc_cb); 537 } 538 /******************************************************************************* 539 ** 540 ** Function bta_gattc_char_disc_cmpl 541 ** 542 ** Description process the characteristic discovery complete event 543 ** 544 ** Returns status 545 ** 546 *******************************************************************************/ 547 static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 548 { 549 tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx; 550 551 /* if there are characteristic needs to be explored */ 552 if (p_srvc_cb->total_char > 0) 553 { 554 /* add the first characteristic into cache */ 555 bta_gattc_add_char_to_cache (p_srvc_cb, 556 p_rec->char_decl_handle, 557 p_rec->s_handle, 558 &p_rec->uuid, 559 p_rec->property); 560 561 /* start discoverying characteristic descriptor , if failed, disc for next char*/ 562 bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb); 563 } 564 else /* otherwise start with next service */ 565 { 566 p_srvc_cb->cur_srvc_idx ++; 567 568 bta_gattc_explore_srvc (conn_id, p_srvc_cb); 569 } 570 } 571 /******************************************************************************* 572 ** 573 ** Function bta_gattc_char_dscpt_disc_cmpl 574 ** 575 ** Description process the char descriptor discovery complete event 576 ** 577 ** Returns status 578 ** 579 *******************************************************************************/ 580 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 581 { 582 tBTA_GATTC_ATTR_REC *p_rec = NULL; 583 584 if (-- p_srvc_cb->total_char > 0) 585 { 586 p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx); 587 /* add the next characteristic into cache */ 588 bta_gattc_add_char_to_cache (p_srvc_cb, 589 p_rec->char_decl_handle, 590 p_rec->s_handle, 591 &p_rec->uuid, 592 p_rec->property); 593 594 /* start discoverying next characteristic for char descriptor */ 595 bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb); 596 } 597 else 598 /* all characteristic has been explored, start with next service if any */ 599 { 600 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 601 APPL_TRACE_ERROR("all char has been explored"); 602 #endif 603 p_srvc_cb->cur_srvc_idx ++; 604 bta_gattc_explore_srvc (conn_id, p_srvc_cb); 605 } 606 607 } 608 static BOOLEAN bta_gattc_srvc_in_list(tBTA_GATTC_SERV *p_srvc_cb, UINT16 s_handle, 609 UINT16 e_handle, tBT_UUID uuid) 610 { 611 tBTA_GATTC_ATTR_REC *p_rec = NULL; 612 UINT8 i; 613 BOOLEAN exist_srvc = FALSE; 614 UNUSED(uuid); 615 616 if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle)) 617 { 618 APPL_TRACE_ERROR("invalid included service handle: [0x%04x ~ 0x%04x]", s_handle, e_handle); 619 exist_srvc = TRUE; 620 } 621 else 622 { 623 for (i = 0; i < p_srvc_cb->next_avail_idx; i ++) 624 { 625 p_rec = p_srvc_cb->p_srvc_list + i; 626 627 /* a new service should not have any overlap with other service handle range */ 628 if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle) 629 { 630 exist_srvc = TRUE; 631 break; 632 } 633 } 634 } 635 return exist_srvc; 636 } 637 /******************************************************************************* 638 ** 639 ** Function bta_gattc_add_srvc_to_list 640 ** 641 ** Description Add a service into explore pending list 642 ** 643 ** Returns status 644 ** 645 *******************************************************************************/ 646 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb, 647 UINT16 s_handle, UINT16 e_handle, 648 tBT_UUID uuid, BOOLEAN is_primary) 649 { 650 tBTA_GATTC_ATTR_REC *p_rec = NULL; 651 tBTA_GATT_STATUS status = BTA_GATT_OK; 652 653 if (p_srvc_cb->p_srvc_list && p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR) 654 { 655 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx; 656 657 APPL_TRACE_DEBUG("%s handle=%d, service type=0x%04x", 658 __func__, s_handle, uuid.uu.uuid16); 659 660 p_rec->s_handle = s_handle; 661 p_rec->e_handle = e_handle; 662 p_rec->is_primary = is_primary; 663 memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID)); 664 665 p_srvc_cb->total_srvc ++; 666 p_srvc_cb->next_avail_idx ++; 667 } 668 else 669 { /* allocate bigger buffer ?? */ 670 status = GATT_DB_FULL; 671 672 APPL_TRACE_ERROR("service not added, no resources or wrong state"); 673 } 674 return status; 675 } 676 /******************************************************************************* 677 ** 678 ** Function bta_gattc_add_char_to_list 679 ** 680 ** Description Add a characteristic into explore pending list 681 ** 682 ** Returns status 683 ** 684 *******************************************************************************/ 685 static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb, 686 UINT16 decl_handle, UINT16 value_handle, 687 tBT_UUID uuid, UINT8 property) 688 { 689 tBTA_GATTC_ATTR_REC *p_rec = NULL; 690 tBTA_GATT_STATUS status = BTA_GATT_OK; 691 692 if (p_srvc_cb->p_srvc_list == NULL) 693 { 694 APPL_TRACE_ERROR("No service available, unexpected char discovery result"); 695 status = BTA_GATT_INTERNAL_ERROR; 696 } 697 else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR) 698 { 699 700 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx; 701 702 p_srvc_cb->total_char ++; 703 704 p_rec->s_handle = value_handle; 705 p_rec->char_decl_handle = decl_handle; 706 p_rec->property = property; 707 p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle; 708 memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID)); 709 710 /* update the endind handle of pervious characteristic if available */ 711 if (p_srvc_cb->total_char > 1) 712 { 713 p_rec -= 1; 714 p_rec->e_handle = decl_handle - 1; 715 } 716 p_srvc_cb->next_avail_idx ++; 717 } 718 else 719 { 720 APPL_TRACE_ERROR("char not added, no resources"); 721 /* allocate bigger buffer ?? */ 722 status = BTA_GATT_DB_FULL; 723 } 724 return status; 725 726 } 727 728 /******************************************************************************* 729 ** 730 ** Function bta_gattc_sdp_callback 731 ** 732 ** Description Process the discovery result from sdp 733 ** 734 ** Returns void 735 ** 736 *******************************************************************************/ 737 void bta_gattc_sdp_callback(UINT16 sdp_status, void* user_data) 738 { 739 tSDP_DISC_REC *p_sdp_rec = NULL; 740 tBT_UUID service_uuid; 741 tSDP_PROTOCOL_ELEM pe; 742 UINT16 start_handle = 0, end_handle = 0; 743 tBTA_GATTC_CB_DATA *cb_data = user_data; 744 tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_scb_by_cid(cb_data->sdp_conn_id); 745 746 if (((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) && p_srvc_cb != NULL) 747 { 748 do 749 { 750 /* find a service record, report it */ 751 p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, p_sdp_rec); 752 if (p_sdp_rec) 753 { 754 if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) 755 { 756 757 if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT, &pe)) 758 { 759 start_handle = (UINT16) pe.params[0]; 760 end_handle = (UINT16) pe.params[1]; 761 762 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 763 APPL_TRACE_EVENT("Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]", 764 service_uuid.uu.uuid16, start_handle, end_handle); 765 #endif 766 767 if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle)&& 768 p_srvc_cb != NULL) 769 { 770 /* discover services result, add services into a service list */ 771 bta_gattc_add_srvc_to_list(p_srvc_cb, 772 start_handle, 773 end_handle, 774 service_uuid, 775 TRUE); 776 } 777 else 778 { 779 APPL_TRACE_ERROR("invalid start_handle = %d end_handle = %d", 780 start_handle, end_handle); 781 } 782 } 783 784 785 } 786 } 787 } while (p_sdp_rec); 788 } 789 790 if ( p_srvc_cb != NULL) 791 { 792 /* start discover primary service */ 793 bta_gattc_explore_srvc(cb_data->sdp_conn_id, p_srvc_cb); 794 } 795 else 796 { 797 APPL_TRACE_ERROR("GATT service discovery is done on unknown connection"); 798 } 799 800 /* both were allocated in bta_gattc_sdp_service_disc */ 801 osi_free(cb_data->p_sdp_db); 802 osi_free(cb_data); 803 } 804 /******************************************************************************* 805 ** 806 ** Function bta_gattc_sdp_service_disc 807 ** 808 ** Description Start DSP Service Discovert 809 ** 810 ** Returns void 811 ** 812 *******************************************************************************/ 813 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb) 814 { 815 tSDP_UUID uuid; 816 UINT16 num_attrs = 2; 817 UINT16 attr_list[2]; 818 819 memset (&uuid, 0, sizeof(tSDP_UUID)); 820 821 uuid.len = LEN_UUID_16; 822 uuid.uu.uuid16 = UUID_PROTOCOL_ATT; 823 824 /* 825 * On success, cb_data will be freed inside bta_gattc_sdp_callback, 826 * otherwise it will be freed within this function. 827 */ 828 tBTA_GATTC_CB_DATA *cb_data = 829 (tBTA_GATTC_CB_DATA *)osi_malloc(sizeof(tBTA_GATTC_CB_DATA)); 830 831 cb_data->p_sdp_db = (tSDP_DISCOVERY_DB *)osi_malloc(BTA_GATT_SDP_DB_SIZE); 832 attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; 833 attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST; 834 835 SDP_InitDiscoveryDb(cb_data->p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1, 836 &uuid, num_attrs, attr_list); 837 838 if (!SDP_ServiceSearchAttributeRequest2(p_server_cb->server_bda, 839 cb_data->p_sdp_db, &bta_gattc_sdp_callback, cb_data)) 840 { 841 osi_free(cb_data->p_sdp_db); 842 osi_free(cb_data); 843 return BTA_GATT_ERROR; 844 } 845 846 cb_data->sdp_conn_id = conn_id; 847 return BTA_GATT_OK; 848 } 849 /******************************************************************************* 850 ** 851 ** Function bta_gattc_disc_res_cback 852 ** bta_gattc_disc_cmpl_cback 853 ** 854 ** Description callback functions to GATT client stack. 855 ** 856 ** Returns void 857 ** 858 *******************************************************************************/ 859 void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data) 860 { 861 tBTA_GATTC_SERV * p_srvc_cb = NULL; 862 BOOLEAN pri_srvc; 863 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 864 865 p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id); 866 867 if (p_srvc_cb != NULL && p_clcb != NULL && p_clcb->state == BTA_GATTC_DISCOVER_ST) 868 { 869 switch (disc_type) 870 { 871 case GATT_DISC_SRVC_ALL: 872 /* discover services result, add services into a service list */ 873 bta_gattc_add_srvc_to_list(p_srvc_cb, 874 p_data->handle, 875 p_data->value.group_value.e_handle, 876 p_data->value.group_value.service_type, 877 TRUE); 878 879 break; 880 case GATT_DISC_SRVC_BY_UUID: 881 bta_gattc_add_srvc_to_list(p_srvc_cb, 882 p_data->handle, 883 p_data->value.group_value.e_handle, 884 p_data->value.group_value.service_type, 885 TRUE); 886 break; 887 888 case GATT_DISC_INC_SRVC: 889 /* add included service into service list if it's secondary or it never showed up 890 in the primary service search */ 891 pri_srvc = bta_gattc_srvc_in_list(p_srvc_cb, 892 p_data->value.incl_service.s_handle, 893 p_data->value.incl_service.e_handle, 894 p_data->value.incl_service.service_type); 895 896 if (!pri_srvc) 897 bta_gattc_add_srvc_to_list(p_srvc_cb, 898 p_data->value.incl_service.s_handle, 899 p_data->value.incl_service.e_handle, 900 p_data->value.incl_service.service_type, 901 FALSE); 902 /* add into database */ 903 bta_gattc_add_attr_to_cache(p_srvc_cb, 904 p_data->handle, 905 &p_data->value.incl_service.service_type, 906 pri_srvc, 907 p_data->value.incl_service.s_handle, 908 BTA_GATTC_ATTR_TYPE_INCL_SRVC); 909 break; 910 911 case GATT_DISC_CHAR: 912 /* add char value into database */ 913 bta_gattc_add_char_to_list(p_srvc_cb, 914 p_data->handle, 915 p_data->value.dclr_value.val_handle, 916 p_data->value.dclr_value.char_uuid, 917 p_data->value.dclr_value.char_prop); 918 break; 919 920 case GATT_DISC_CHAR_DSCPT: 921 bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0, 922 0 /* incl_srvc_handle */, 923 BTA_GATTC_ATTR_TYPE_CHAR_DESCR); 924 break; 925 } 926 } 927 } 928 void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status) 929 { 930 tBTA_GATTC_SERV * p_srvc_cb; 931 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 932 933 if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) ) 934 { 935 if (status == GATT_SUCCESS) 936 p_clcb->status = status; 937 bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL); 938 return; 939 } 940 p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id); 941 942 if (p_srvc_cb != NULL) 943 { 944 switch (disc_type) 945 { 946 case GATT_DISC_SRVC_ALL: 947 case GATT_DISC_SRVC_BY_UUID: 948 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 949 bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx); 950 #endif 951 bta_gattc_explore_srvc(conn_id, p_srvc_cb); 952 break; 953 954 case GATT_DISC_INC_SRVC: 955 bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb); 956 957 break; 958 959 case GATT_DISC_CHAR: 960 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 961 bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx); 962 #endif 963 bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb); 964 break; 965 966 case GATT_DISC_CHAR_DSCPT: 967 bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb); 968 break; 969 } 970 } 971 } 972 973 /******************************************************************************* 974 ** 975 ** Function bta_gattc_search_service 976 ** 977 ** Description search local cache for matching service record. 978 ** 979 ** Returns FALSE if map can not be found. 980 ** 981 *******************************************************************************/ 982 void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid) 983 { 984 tBTA_GATTC cb_data; 985 986 if (!p_clcb->p_srcb->p_srvc_cache || list_is_empty(p_clcb->p_srcb->p_srvc_cache)) 987 return; 988 989 for (list_node_t *sn = list_begin(p_clcb->p_srcb->p_srvc_cache); 990 sn != list_end(p_clcb->p_srcb->p_srvc_cache); sn = list_next(sn)) { 991 tBTA_GATTC_SERVICE *p_cache = list_node(sn); 992 993 if (!bta_gattc_uuid_compare(p_uuid, &p_cache->uuid, FALSE)) 994 continue; 995 996 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 997 APPL_TRACE_DEBUG("found service [0x%04x], inst[%d] handle [%d]", 998 p_cache->uuid.uu.uuid16, 999 p_cache->handle, 1000 p_cache->s_handle); 1001 #endif 1002 if (!p_clcb->p_rcb->p_cback) 1003 continue; 1004 1005 memset(&cb_data, 0, sizeof(tBTA_GATTC)); 1006 1007 cb_data.srvc_res.conn_id = p_clcb->bta_conn_id; 1008 cb_data.srvc_res.service_uuid.inst_id = p_cache->handle; 1009 memcpy(&cb_data.srvc_res.service_uuid.uuid, &p_cache->uuid, sizeof(tBTA_GATT_ID)); 1010 1011 (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data); 1012 } 1013 } 1014 1015 list_t* bta_gattc_get_services_srcb(tBTA_GATTC_SERV *p_srcb) { 1016 if (!p_srcb || !p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache)) 1017 return NULL; 1018 1019 return p_srcb->p_srvc_cache; 1020 } 1021 1022 const list_t* bta_gattc_get_services(UINT16 conn_id) { 1023 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 1024 1025 if (p_clcb == NULL ) 1026 return NULL; 1027 1028 tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb; 1029 1030 return bta_gattc_get_services_srcb(p_srcb); 1031 } 1032 1033 tBTA_GATTC_SERVICE* bta_gattc_find_matching_service(const list_t *services, UINT16 handle) { 1034 if (!services || list_is_empty(services)) 1035 return NULL; 1036 1037 for (list_node_t *sn = list_begin(services); 1038 sn != list_end(services); sn = list_next(sn)) { 1039 tBTA_GATTC_SERVICE *service = list_node(sn); 1040 1041 if (handle >= service->s_handle && handle <= service->e_handle) 1042 return service; 1043 } 1044 1045 return NULL; 1046 } 1047 1048 const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle) { 1049 const list_t *services = bta_gattc_get_services_srcb(p_srcb); 1050 1051 return bta_gattc_find_matching_service(services, handle); 1052 } 1053 1054 const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle(UINT16 conn_id, UINT16 handle) { 1055 const list_t *services = bta_gattc_get_services(conn_id); 1056 1057 return bta_gattc_find_matching_service(services, handle); 1058 } 1059 1060 tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle) { 1061 const tBTA_GATTC_SERVICE* service = bta_gattc_get_service_for_handle_srcb(p_srcb, handle); 1062 1063 if (!service) 1064 return NULL; 1065 1066 for (list_node_t *cn = list_begin(service->characteristics); 1067 cn != list_end(service->characteristics); cn = list_next(cn)) { 1068 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn); 1069 if (handle == p_char->handle) 1070 return p_char; 1071 } 1072 1073 return NULL; 1074 } 1075 1076 tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic(UINT16 conn_id, UINT16 handle) { 1077 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 1078 1079 if (p_clcb == NULL ) 1080 return NULL; 1081 1082 tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb; 1083 return bta_gattc_get_characteristic_srcb(p_srcb, handle); 1084 } 1085 1086 tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle) { 1087 const tBTA_GATTC_SERVICE* service = bta_gattc_get_service_for_handle_srcb(p_srcb, handle); 1088 1089 if (!service) { 1090 return NULL; 1091 } 1092 1093 for (list_node_t *cn = list_begin(service->characteristics); 1094 cn != list_end(service->characteristics); cn = list_next(cn)) { 1095 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn); 1096 for (list_node_t *dn = list_begin(p_char->descriptors); 1097 dn != list_end(p_char->descriptors); dn = list_next(dn)) { 1098 tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn); 1099 if (handle == p_desc->handle) 1100 return p_desc; 1101 } 1102 } 1103 1104 return NULL; 1105 } 1106 1107 tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor(UINT16 conn_id, UINT16 handle) { 1108 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 1109 1110 if (p_clcb == NULL ) 1111 return NULL; 1112 1113 tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb; 1114 return bta_gattc_get_descriptor_srcb(p_srcb, handle); 1115 } 1116 1117 /******************************************************************************* 1118 ** 1119 ** Function bta_gattc_fill_gatt_db_el 1120 ** 1121 ** Description fill a btgatt_db_element_t value 1122 ** 1123 ** Returns None. 1124 ** 1125 *******************************************************************************/ 1126 void bta_gattc_fill_gatt_db_el(btgatt_db_element_t *p_attr, 1127 bt_gatt_db_attribute_type_t type, 1128 UINT16 att_handle, 1129 UINT16 s_handle, UINT16 e_handle, 1130 UINT16 id, tBT_UUID uuid, UINT8 prop) 1131 { 1132 p_attr->type = type; 1133 p_attr->attribute_handle = att_handle; 1134 p_attr->start_handle = s_handle; 1135 p_attr->end_handle = e_handle; 1136 p_attr->id = id; 1137 p_attr->properties = prop; 1138 bta_to_btif_uuid(&p_attr->uuid, &uuid); 1139 } 1140 1141 /******************************************************************************* 1142 ** Returns number of elements inside db from start_handle to end_handle 1143 *******************************************************************************/ 1144 static size_t bta_gattc_get_db_size(list_t *services, 1145 UINT16 start_handle, UINT16 end_handle) { 1146 if (!services || list_is_empty(services)) 1147 return 0; 1148 1149 size_t db_size = 0; 1150 1151 for (list_node_t *sn = list_begin(services); 1152 sn != list_end(services); sn = list_next(sn)) { 1153 tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn); 1154 1155 if (p_cur_srvc->s_handle < start_handle) 1156 continue; 1157 1158 if (p_cur_srvc->e_handle > end_handle) 1159 break; 1160 1161 db_size++; 1162 if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics)) 1163 continue; 1164 1165 for (list_node_t *cn = list_begin(p_cur_srvc->characteristics); 1166 cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) { 1167 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn); 1168 db_size++; 1169 1170 if (p_char->descriptors) 1171 db_size += list_length(p_char->descriptors); 1172 } 1173 1174 if (p_cur_srvc->included_svc) { 1175 db_size += list_length(p_cur_srvc->included_svc); 1176 } 1177 } 1178 1179 return db_size; 1180 } 1181 1182 /******************************************************************************* 1183 ** 1184 ** Function bta_gattc_get_gatt_db_impl 1185 ** 1186 ** Description copy the server GATT database into db parameter. 1187 ** 1188 ** Parameters p_srvc_cb: server. 1189 ** db: output parameter which will contain GATT database copy. 1190 ** Caller is responsible for freeing it. 1191 ** count: output parameter which will contain number of 1192 ** elements in database. 1193 ** 1194 ** Returns None. 1195 ** 1196 *******************************************************************************/ 1197 static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV *p_srvc_cb, 1198 UINT16 start_handle, UINT16 end_handle, 1199 btgatt_db_element_t **db, 1200 int *count) 1201 { 1202 APPL_TRACE_DEBUG("%s: start_handle 0x%04x, end_handle 0x%04x", 1203 __func__, start_handle, end_handle); 1204 1205 if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache)) { 1206 *count = 0; 1207 *db = NULL; 1208 return; 1209 } 1210 1211 size_t db_size = bta_gattc_get_db_size(p_srvc_cb->p_srvc_cache, start_handle, end_handle); 1212 1213 void* buffer = osi_malloc(db_size * sizeof(btgatt_db_element_t)); 1214 btgatt_db_element_t *curr_db_attr = buffer; 1215 1216 for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache); 1217 sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) { 1218 tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn); 1219 1220 if (p_cur_srvc->s_handle < start_handle) 1221 continue; 1222 1223 if (p_cur_srvc->e_handle > end_handle) 1224 break; 1225 1226 bta_gattc_fill_gatt_db_el(curr_db_attr, 1227 p_cur_srvc->is_primary ? 1228 BTGATT_DB_PRIMARY_SERVICE : 1229 BTGATT_DB_SECONDARY_SERVICE, 1230 0 /* att_handle */, 1231 p_cur_srvc->s_handle, 1232 p_cur_srvc->e_handle, 1233 p_cur_srvc->s_handle, 1234 p_cur_srvc->uuid, 1235 0 /* prop */); 1236 curr_db_attr++; 1237 1238 if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics)) 1239 continue; 1240 1241 for (list_node_t *cn = list_begin(p_cur_srvc->characteristics); 1242 cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) { 1243 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn); 1244 1245 bta_gattc_fill_gatt_db_el(curr_db_attr, 1246 BTGATT_DB_CHARACTERISTIC, 1247 p_char->handle, 1248 0 /* s_handle */, 1249 0 /* e_handle */, 1250 p_char->handle, 1251 p_char->uuid, 1252 p_char->properties); 1253 curr_db_attr++; 1254 1255 if (!p_char->descriptors || list_is_empty(p_char->descriptors)) 1256 continue; 1257 1258 for (list_node_t *dn = list_begin(p_char->descriptors); 1259 dn != list_end(p_char->descriptors); dn = list_next(dn)) { 1260 tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn); 1261 1262 bta_gattc_fill_gatt_db_el(curr_db_attr, 1263 BTGATT_DB_DESCRIPTOR, 1264 p_desc->handle, 1265 0 /* s_handle */, 1266 0 /* e_handle */, 1267 p_desc->handle, 1268 p_desc->uuid, 1269 0 /* property */); 1270 curr_db_attr++; 1271 } 1272 } 1273 1274 if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc)) 1275 continue; 1276 1277 for (list_node_t *isn = list_begin(p_cur_srvc->included_svc); 1278 isn != list_end(p_cur_srvc->included_svc); isn = list_next(isn)) { 1279 tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(isn); 1280 1281 bta_gattc_fill_gatt_db_el(curr_db_attr, 1282 BTGATT_DB_INCLUDED_SERVICE, 1283 p_isvc->handle, 1284 0 /* s_handle */, 1285 0 /* e_handle */, 1286 p_isvc->handle, 1287 p_isvc->uuid, 1288 0 /* property */); 1289 curr_db_attr++; 1290 } 1291 } 1292 1293 *db = buffer; 1294 *count = db_size; 1295 } 1296 1297 /******************************************************************************* 1298 ** 1299 ** Function bta_gattc_get_gatt_db 1300 ** 1301 ** Description copy the server GATT database into db parameter. 1302 ** 1303 ** Parameters conn_id: connection ID which identify the server. 1304 ** db: output parameter which will contain GATT database copy. 1305 ** Caller is responsible for freeing it. 1306 ** count: number of elements in database. 1307 ** 1308 ** Returns None. 1309 ** 1310 *******************************************************************************/ 1311 void bta_gattc_get_gatt_db(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, btgatt_db_element_t **db, int *count) 1312 { 1313 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 1314 1315 LOG_DEBUG(LOG_TAG, "%s", __func__); 1316 if (p_clcb == NULL) { 1317 APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id); 1318 return; 1319 } 1320 1321 if (p_clcb->state != BTA_GATTC_CONN_ST) { 1322 APPL_TRACE_ERROR("server cache not available, CLCB state = %d", 1323 p_clcb->state); 1324 return; 1325 } 1326 1327 if (!p_clcb->p_srcb || p_clcb->p_srcb->p_srvc_list || /* no active discovery */ 1328 !p_clcb->p_srcb->p_srvc_cache) { 1329 APPL_TRACE_ERROR("No server cache available"); 1330 } 1331 1332 bta_gattc_get_gatt_db_impl(p_clcb->p_srcb, start_handle, end_handle, db, count); 1333 } 1334 1335 /******************************************************************************* 1336 ** 1337 ** Function bta_gattc_rebuild_cache 1338 ** 1339 ** Description rebuild server cache from NV cache. 1340 ** 1341 ** Parameters 1342 ** 1343 ** Returns None. 1344 ** 1345 *******************************************************************************/ 1346 void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr, 1347 tBTA_GATTC_NV_ATTR *p_attr) 1348 { 1349 /* first attribute loading, initialize buffer */ 1350 APPL_TRACE_ERROR("%s: bta_gattc_rebuild_cache", __func__); 1351 1352 list_free(p_srvc_cb->p_srvc_cache); 1353 p_srvc_cb->p_srvc_cache = NULL; 1354 1355 while (num_attr > 0 && p_attr != NULL) 1356 { 1357 switch (p_attr->attr_type) 1358 { 1359 case BTA_GATTC_ATTR_TYPE_SRVC: 1360 bta_gattc_add_srvc_to_cache(p_srvc_cb, 1361 p_attr->s_handle, 1362 p_attr->e_handle, 1363 &p_attr->uuid, 1364 p_attr->is_primary); 1365 break; 1366 1367 case BTA_GATTC_ATTR_TYPE_CHAR: 1368 //TODO(jpawlowski): store decl_handle properly. 1369 bta_gattc_add_char_to_cache(p_srvc_cb, 1370 p_attr->s_handle, 1371 p_attr->s_handle, 1372 &p_attr->uuid, 1373 p_attr->prop); 1374 break; 1375 1376 case BTA_GATTC_ATTR_TYPE_CHAR_DESCR: 1377 case BTA_GATTC_ATTR_TYPE_INCL_SRVC: 1378 bta_gattc_add_attr_to_cache(p_srvc_cb, 1379 p_attr->s_handle, 1380 &p_attr->uuid, 1381 p_attr->prop, 1382 p_attr->incl_srvc_handle, 1383 p_attr->attr_type); 1384 break; 1385 } 1386 p_attr ++; 1387 num_attr --; 1388 } 1389 } 1390 1391 /******************************************************************************* 1392 ** 1393 ** Function bta_gattc_fill_nv_attr 1394 ** 1395 ** Description fill a NV attribute entry value 1396 ** 1397 ** Returns None. 1398 ** 1399 *******************************************************************************/ 1400 void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle, 1401 UINT16 e_handle, tBT_UUID uuid, UINT8 prop, UINT16 incl_srvc_handle, 1402 BOOLEAN is_primary) 1403 { 1404 p_attr->s_handle = s_handle; 1405 p_attr->e_handle = e_handle; 1406 p_attr->attr_type = type; 1407 p_attr->is_primary = is_primary; 1408 p_attr->id = 0; 1409 p_attr->prop = prop; 1410 p_attr->incl_srvc_handle = incl_srvc_handle; 1411 1412 memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID)); 1413 } 1414 1415 /******************************************************************************* 1416 ** 1417 ** Function bta_gattc_cache_save 1418 ** 1419 ** Description save the server cache into NV 1420 ** 1421 ** Returns None. 1422 ** 1423 *******************************************************************************/ 1424 void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id) 1425 { 1426 if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache)) 1427 return; 1428 1429 int i = 0; 1430 size_t db_size = bta_gattc_get_db_size(p_srvc_cb->p_srvc_cache, 0x0000, 0xFFFF); 1431 tBTA_GATTC_NV_ATTR *nv_attr = osi_malloc(db_size * sizeof(tBTA_GATTC_NV_ATTR)); 1432 1433 for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache); 1434 sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) { 1435 tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn); 1436 1437 bta_gattc_fill_nv_attr(&nv_attr[i++], 1438 BTA_GATTC_ATTR_TYPE_SRVC, 1439 p_cur_srvc->s_handle, 1440 p_cur_srvc->e_handle, 1441 p_cur_srvc->uuid, 1442 0 /* properties */, 1443 0 /* incl_srvc_handle */, 1444 p_cur_srvc->is_primary); 1445 } 1446 1447 for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache); 1448 sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) { 1449 tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn); 1450 1451 if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics)) 1452 continue; 1453 1454 for (list_node_t *cn = list_begin(p_cur_srvc->characteristics); 1455 cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) { 1456 tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn); 1457 1458 bta_gattc_fill_nv_attr(&nv_attr[i++], 1459 BTA_GATTC_ATTR_TYPE_CHAR, 1460 p_char->handle, 1461 0, 1462 p_char->uuid, 1463 p_char->properties, 1464 0 /* incl_srvc_handle */, 1465 FALSE); 1466 1467 if (!p_char->descriptors || list_is_empty(p_char->descriptors)) 1468 continue; 1469 1470 for (list_node_t *dn = list_begin(p_char->descriptors); 1471 dn != list_end(p_char->descriptors); dn = list_next(dn)) { 1472 tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn); 1473 1474 bta_gattc_fill_nv_attr(&nv_attr[i++], 1475 BTA_GATTC_ATTR_TYPE_CHAR_DESCR, 1476 p_desc->handle, 1477 0, 1478 p_desc->uuid, 1479 0 /* properties */, 1480 0 /* incl_srvc_handle */, 1481 FALSE); 1482 } 1483 } 1484 1485 if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc)) 1486 continue; 1487 1488 for (list_node_t *an = list_begin(p_cur_srvc->included_svc); 1489 an != list_end(p_cur_srvc->included_svc); an = list_next(an)) { 1490 tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(an); 1491 1492 bta_gattc_fill_nv_attr(&nv_attr[i++], 1493 BTA_GATTC_ATTR_TYPE_INCL_SRVC, 1494 p_isvc->handle, 1495 0, 1496 p_isvc->uuid, 1497 0 /* properties */, 1498 p_isvc->included_service->s_handle, 1499 FALSE); 1500 } 1501 } 1502 1503 bta_gattc_cache_write(p_srvc_cb->server_bda, db_size, nv_attr); 1504 osi_free(nv_attr); 1505 } 1506 1507 /******************************************************************************* 1508 ** 1509 ** Function bta_gattc_cache_load 1510 ** 1511 ** Description Load GATT cache from storage for server. 1512 ** 1513 ** Parameter p_clcb: pointer to server clcb, that will 1514 ** be filled from storage 1515 ** Returns true on success, false otherwise 1516 ** 1517 *******************************************************************************/ 1518 bool bta_gattc_cache_load(tBTA_GATTC_CLCB *p_clcb) 1519 { 1520 char fname[255] = {0}; 1521 bta_gattc_generate_cache_file_name(fname, p_clcb->p_srcb->server_bda); 1522 1523 FILE *fd = fopen(fname, "rb"); 1524 if (!fd) { 1525 APPL_TRACE_ERROR("%s: can't open GATT cache file %s for reading, error: %s", 1526 __func__, fname, strerror(errno)); 1527 return false; 1528 } 1529 1530 UINT16 cache_ver = 0; 1531 tBTA_GATTC_NV_ATTR *attr = NULL; 1532 bool success = false; 1533 1534 if (fread(&cache_ver, sizeof(UINT16), 1, fd) != 1) { 1535 APPL_TRACE_ERROR("%s: can't read GATT cache version from: %s", __func__, fname); 1536 goto done; 1537 } 1538 1539 if (cache_ver != GATT_CACHE_VERSION) { 1540 APPL_TRACE_ERROR("%s: wrong GATT cache version: %s", __func__, fname); 1541 goto done; 1542 } 1543 1544 UINT16 num_attr = 0; 1545 1546 if (fread(&num_attr, sizeof(UINT16), 1, fd) != 1) { 1547 APPL_TRACE_ERROR("%s: can't read number of GATT attributes: %s", __func__, fname); 1548 goto done; 1549 } 1550 1551 attr = osi_malloc(sizeof(tBTA_GATTC_NV_ATTR) * num_attr); 1552 1553 if (fread(attr, sizeof(tBTA_GATTC_NV_ATTR), 0xFF, fd) != num_attr) { 1554 APPL_TRACE_ERROR("%s: can't read GATT attributes: %s", __func__, fname); 1555 goto done; 1556 } 1557 1558 bta_gattc_rebuild_cache(p_clcb->p_srcb, num_attr, attr); 1559 1560 success = true; 1561 1562 done: 1563 osi_free(attr); 1564 fclose(fd); 1565 return success; 1566 } 1567 1568 /******************************************************************************* 1569 ** 1570 ** Function bta_gattc_cache_write 1571 ** 1572 ** Description This callout function is executed by GATT when a server cache 1573 ** is available to save. 1574 ** 1575 ** Parameter server_bda: server bd address of this cache belongs to 1576 ** num_attr: number of attribute to be save. 1577 ** attr: pointer to the list of attributes to save. 1578 ** Returns 1579 ** 1580 *******************************************************************************/ 1581 static void bta_gattc_cache_write(BD_ADDR server_bda, UINT16 num_attr, 1582 tBTA_GATTC_NV_ATTR *attr) 1583 { 1584 char fname[255] = {0}; 1585 bta_gattc_generate_cache_file_name(fname, server_bda); 1586 1587 FILE *fd = fopen(fname, "wb"); 1588 if (!fd) { 1589 APPL_TRACE_ERROR("%s: can't open GATT cache file for writing: %s", __func__, fname); 1590 return; 1591 } 1592 1593 UINT16 cache_ver = GATT_CACHE_VERSION; 1594 if (fwrite(&cache_ver, sizeof(UINT16), 1, fd) != 1) { 1595 APPL_TRACE_ERROR("%s: can't write GATT cache version: %s", __func__, fname); 1596 fclose(fd); 1597 return; 1598 } 1599 1600 if (fwrite(&num_attr, sizeof(UINT16), 1, fd) != 1) { 1601 APPL_TRACE_ERROR("%s: can't write GATT cache attribute count: %s", __func__, fname); 1602 fclose(fd); 1603 return; 1604 } 1605 1606 if (fwrite(attr, sizeof(tBTA_GATTC_NV_ATTR), num_attr, fd) != num_attr) { 1607 APPL_TRACE_ERROR("%s: can't write GATT cache attributes: %s", __func__, fname); 1608 fclose(fd); 1609 return; 1610 } 1611 1612 fclose(fd); 1613 } 1614 1615 /******************************************************************************* 1616 ** 1617 ** Function bta_gattc_cache_reset 1618 ** 1619 ** Description This callout function is executed by GATTC to reset cache in 1620 ** application 1621 ** 1622 ** Parameter server_bda: server bd address of this cache belongs to 1623 ** 1624 ** Returns void. 1625 ** 1626 *******************************************************************************/ 1627 void bta_gattc_cache_reset(BD_ADDR server_bda) 1628 { 1629 BTIF_TRACE_DEBUG("%s", __func__); 1630 char fname[255] = {0}; 1631 bta_gattc_generate_cache_file_name(fname, server_bda); 1632 unlink(fname); 1633 } 1634 #endif /* BTA_GATT_INCLUDED */ 1635 1636