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