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