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