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