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