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