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