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