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