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 39 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb); 40 static 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) 49 static 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 *******************************************************************************/ 66 static 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 *******************************************************************************/ 109 static 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 *******************************************************************************/ 136 BT_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 *******************************************************************************/ 169 tBTA_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 *******************************************************************************/ 211 static 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 *******************************************************************************/ 236 static 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 *******************************************************************************/ 265 static 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 *******************************************************************************/ 317 static 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 *******************************************************************************/ 398 void 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 *******************************************************************************/ 428 tBTA_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 *******************************************************************************/ 452 tBTA_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 return GATT_ERROR; 474 } 475 } 476 return GATTC_Discover (conn_id, disc_type, ¶m); 477 478 } 479 /******************************************************************************* 480 ** 481 ** Function bta_gattc_start_disc_include_srvc 482 ** 483 ** Description Start discovery for included service 484 ** 485 ** Returns status of the operation. 486 ** 487 *******************************************************************************/ 488 tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 489 { 490 return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC); 491 } 492 /******************************************************************************* 493 ** 494 ** Function bta_gattc_start_disc_char 495 ** 496 ** Description Start discovery for characteristic 497 ** 498 ** Returns status of the operation. 499 ** 500 *******************************************************************************/ 501 tBTA_GATT_STATUS bta_gattc_start_disc_char(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 502 { 503 p_srvc_cb->total_char = 0; 504 505 return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR); 506 } 507 /******************************************************************************* 508 ** 509 ** Function bta_gattc_start_disc_char_dscp 510 ** 511 ** Description Start discovery for characteristic descriptor 512 ** 513 ** Returns none. 514 ** 515 *******************************************************************************/ 516 void bta_gattc_start_disc_char_dscp(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 517 { 518 APPL_TRACE_DEBUG0("starting discover characteristics descriptor"); 519 520 if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) != 0) 521 bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb); 522 523 } 524 /******************************************************************************* 525 ** 526 ** Function bta_gattc_explore_srvc 527 ** 528 ** Description process the service discovery complete event 529 ** 530 ** Returns status 531 ** 532 *******************************************************************************/ 533 static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 534 { 535 tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx; 536 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 537 538 APPL_TRACE_DEBUG1("Start service discovery: srvc_idx = %d", p_srvc_cb->cur_srvc_idx); 539 540 p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc; 541 542 if (p_clcb == NULL) 543 { 544 APPL_TRACE_ERROR0("unknown connection ID"); 545 return; 546 } 547 /* start expore a service if there is service not been explored */ 548 if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc) 549 { 550 /* add the first service into cache */ 551 if (bta_gattc_add_srvc_to_cache (p_srvc_cb, 552 p_rec->s_handle, 553 p_rec->e_handle, 554 &p_rec->uuid, 555 p_rec->is_primary, 556 p_rec->srvc_inst_id) == 0) 557 { 558 /* start discovering included services */ 559 bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb); 560 return; 561 } 562 } 563 /* no service found at all, the end of server discovery*/ 564 APPL_TRACE_ERROR0("No More Service found"); 565 566 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 567 bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache); 568 #endif 569 /* save cache to NV */ 570 p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE; 571 bta_gattc_co_cache_open(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT, 572 conn_id, TRUE); 573 } 574 /******************************************************************************* 575 ** 576 ** Function bta_gattc_incl_srvc_disc_cmpl 577 ** 578 ** Description process the relationship discovery complete event 579 ** 580 ** Returns status 581 ** 582 *******************************************************************************/ 583 static void bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 584 { 585 p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc; 586 587 /* start discoverying characteristic */ 588 bta_gattc_start_disc_char(conn_id, p_srvc_cb); 589 } 590 /******************************************************************************* 591 ** 592 ** Function bta_gattc_char_disc_cmpl 593 ** 594 ** Description process the characteristic discovery complete event 595 ** 596 ** Returns status 597 ** 598 *******************************************************************************/ 599 static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 600 { 601 tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx; 602 603 /* if there are characteristic needs to be explored */ 604 if (p_srvc_cb->total_char > 0) 605 { 606 /* add the first characteristic into cache */ 607 bta_gattc_add_attr_to_cache (p_srvc_cb, 608 p_rec->s_handle, 609 &p_rec->uuid, 610 p_rec->property, 611 BTA_GATTC_ATTR_TYPE_CHAR); 612 613 /* start discoverying characteristic descriptor , if failed, disc for next char*/ 614 bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb); 615 } 616 else /* otherwise start with next service */ 617 { 618 p_srvc_cb->cur_srvc_idx ++; 619 620 bta_gattc_explore_srvc (conn_id, p_srvc_cb); 621 } 622 } 623 /******************************************************************************* 624 ** 625 ** Function bta_gattc_char_dscpt_disc_cmpl 626 ** 627 ** Description process the char descriptor discovery complete event 628 ** 629 ** Returns status 630 ** 631 *******************************************************************************/ 632 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) 633 { 634 tBTA_GATTC_ATTR_REC *p_rec = NULL; 635 636 if (-- p_srvc_cb->total_char > 0) 637 { 638 p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx); 639 /* add the next characteristic into cache */ 640 bta_gattc_add_attr_to_cache (p_srvc_cb, 641 p_rec->s_handle, 642 &p_rec->uuid, 643 p_rec->property, 644 BTA_GATTC_ATTR_TYPE_CHAR); 645 646 /* start discoverying next characteristic for char descriptor */ 647 bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb); 648 } 649 else 650 /* all characteristic has been explored, start with next service if any */ 651 { 652 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 653 APPL_TRACE_ERROR0("all char has been explored"); 654 #endif 655 p_srvc_cb->cur_srvc_idx ++; 656 bta_gattc_explore_srvc (conn_id, p_srvc_cb); 657 } 658 659 } 660 static BOOLEAN bta_gattc_srvc_in_list(tBTA_GATTC_SERV *p_srvc_cb, UINT16 s_handle, 661 UINT16 e_handle, tBT_UUID uuid) 662 { 663 tBTA_GATTC_ATTR_REC *p_rec = NULL; 664 UINT8 i; 665 BOOLEAN exist_srvc = FALSE; 666 667 if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle)) 668 { 669 APPL_TRACE_ERROR2("invalid included service handle: [0x%04x ~ 0x%04x]", s_handle, e_handle); 670 exist_srvc = TRUE; 671 } 672 else 673 { 674 for (i = 0; i < p_srvc_cb->next_avail_idx; i ++) 675 { 676 p_rec = p_srvc_cb->p_srvc_list + i; 677 678 /* a new service should not have any overlap with other service handle range */ 679 if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle) 680 { 681 exist_srvc = TRUE; 682 break; 683 } 684 } 685 } 686 return exist_srvc; 687 } 688 /******************************************************************************* 689 ** 690 ** Function bta_gattc_add_srvc_to_list 691 ** 692 ** Description Add a service into explore pending list 693 ** 694 ** Returns status 695 ** 696 *******************************************************************************/ 697 static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb, 698 UINT16 s_handle, UINT16 e_handle, 699 tBT_UUID uuid, BOOLEAN is_primary) 700 { 701 tBTA_GATTC_ATTR_REC *p_rec = NULL; 702 tBTA_GATT_STATUS status = BTA_GATT_OK; 703 704 if (p_srvc_cb->p_srvc_list && p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR) 705 { 706 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx; 707 708 p_srvc_cb->total_srvc ++; 709 710 APPL_TRACE_DEBUG2("bta_gattc_add_srvc_to_list handle = %d, service type = 0x%04x", 711 s_handle, uuid.uu.uuid16); 712 713 p_rec->s_handle = s_handle; 714 p_rec->e_handle = e_handle; 715 p_rec->is_primary = is_primary; 716 p_rec->srvc_inst_id = bta_gattc_get_srvc_inst_id(p_srvc_cb, uuid); 717 memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID)); 718 719 p_srvc_cb->next_avail_idx ++; 720 721 } 722 else 723 { /* allocate bigger buffer ?? */ 724 status = GATT_DB_FULL; 725 726 APPL_TRACE_ERROR0("service not added, no resources or wrong state"); 727 } 728 return status; 729 } 730 /******************************************************************************* 731 ** 732 ** Function bta_gattc_add_char_to_list 733 ** 734 ** Description Add a characteristic into explore pending list 735 ** 736 ** Returns status 737 ** 738 *******************************************************************************/ 739 static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb, 740 UINT16 decl_handle, UINT16 value_handle, 741 tBT_UUID uuid, UINT8 property) 742 { 743 tBTA_GATTC_ATTR_REC *p_rec = NULL; 744 tBTA_GATT_STATUS status = BTA_GATT_OK; 745 746 if (p_srvc_cb->p_srvc_list == NULL) 747 { 748 APPL_TRACE_ERROR0("No service available, unexpected char discovery result"); 749 status = BTA_GATT_INTERNAL_ERROR; 750 } 751 else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR) 752 { 753 754 p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx; 755 756 p_srvc_cb->total_char ++; 757 758 p_rec->s_handle = value_handle; 759 p_rec->property = property; 760 p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle; 761 memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID)); 762 763 /* update the endind handle of pervious characteristic if available */ 764 if (p_srvc_cb->total_char > 1) 765 { 766 p_rec -= 1; 767 p_rec->e_handle = decl_handle - 1; 768 } 769 p_srvc_cb->next_avail_idx ++; 770 } 771 else 772 { 773 APPL_TRACE_ERROR0("char not added, no resources"); 774 /* allocate bigger buffer ?? */ 775 status = BTA_GATT_DB_FULL; 776 } 777 return status; 778 779 } 780 /******************************************************************************* 781 ** 782 ** Function bta_gattc_sdp_callback 783 ** 784 ** Description Process the discovery result from sdp 785 ** 786 ** Returns void 787 ** 788 *******************************************************************************/ 789 void bta_gattc_sdp_callback (UINT16 sdp_status) 790 { 791 tSDP_DISC_REC *p_sdp_rec = NULL; 792 tBT_UUID service_uuid; 793 tSDP_PROTOCOL_ELEM pe; 794 UINT16 start_handle = 0, end_handle = 0; 795 tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_scb_by_cid(bta_gattc_cb.sdp_conn_id); 796 797 if(((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) && p_srvc_cb != NULL) 798 { 799 do 800 { 801 /* find a service record, report it */ 802 p_sdp_rec = SDP_FindServiceInDb(bta_gattc_cb.p_sdp_db, 803 0, p_sdp_rec); 804 if (p_sdp_rec) 805 { 806 if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) 807 { 808 809 if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT, &pe)) 810 { 811 start_handle = (UINT16) pe.params[0]; 812 end_handle = (UINT16) pe.params[1]; 813 814 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 815 APPL_TRACE_EVENT3("Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]", 816 service_uuid.uu.uuid16, start_handle, end_handle); 817 #endif 818 819 if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle) && 820 p_srvc_cb != NULL) 821 { 822 /* discover services result, add services into a service list */ 823 bta_gattc_add_srvc_to_list(p_srvc_cb, 824 start_handle, 825 end_handle, 826 service_uuid, 827 TRUE); 828 } 829 else 830 { 831 APPL_TRACE_ERROR2("invalid start_handle = %d end_handle = %d", start_handle, end_handle); 832 } 833 } 834 835 836 } 837 } 838 } while (p_sdp_rec); 839 } 840 841 if ( p_srvc_cb != NULL) 842 /* start discover primary service */ 843 bta_gattc_explore_srvc(bta_gattc_cb.sdp_conn_id, p_srvc_cb); 844 else 845 { 846 APPL_TRACE_ERROR0("GATT service discovery is done on unknown connection"); 847 } 848 849 GKI_freebuf(bta_gattc_cb.p_sdp_db); 850 bta_gattc_cb.p_sdp_db = NULL; 851 bta_gattc_cb.sdp_conn_id = 0; 852 } 853 /******************************************************************************* 854 ** 855 ** Function bta_gattc_sdp_service_disc 856 ** 857 ** Description Start DSP Service Discovert 858 ** 859 ** Returns void 860 ** 861 *******************************************************************************/ 862 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb) 863 { 864 tSDP_UUID uuid; 865 UINT16 num_attrs = 2; 866 UINT16 attr_list[2]; 867 tBTA_GATT_STATUS status = BTA_GATT_ERROR; 868 869 memset (&uuid, 0, sizeof(tSDP_UUID)); 870 871 uuid.len = LEN_UUID_16; 872 uuid.uu.uuid16 = UUID_PROTOCOL_ATT; 873 874 if((bta_gattc_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_GATT_SDP_DB_SIZE)) != NULL) 875 { 876 attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; 877 attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST; 878 879 SDP_InitDiscoveryDb (bta_gattc_cb.p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1, &uuid, num_attrs, attr_list); 880 881 if(!SDP_ServiceSearchAttributeRequest (p_server_cb->server_bda, bta_gattc_cb.p_sdp_db, &bta_gattc_sdp_callback)) 882 { 883 GKI_freebuf(bta_gattc_cb.p_sdp_db); 884 bta_gattc_cb.p_sdp_db = NULL; 885 } 886 else 887 { 888 bta_gattc_cb.sdp_conn_id = conn_id; 889 status = BTA_GATT_OK; 890 } 891 } 892 return status; 893 } 894 /******************************************************************************* 895 ** 896 ** Function bta_gattc_disc_res_cback 897 ** bta_gattc_disc_cmpl_cback 898 ** 899 ** Description callback functions to GATT client stack. 900 ** 901 ** Returns void 902 ** 903 *******************************************************************************/ 904 void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data) 905 { 906 tBTA_GATTC_SERV * p_srvc_cb = NULL; 907 BOOLEAN pri_srvc; 908 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 909 910 p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id); 911 912 if (p_srvc_cb != NULL && p_clcb != NULL && p_clcb->state == BTA_GATTC_DISCOVER_ST) 913 { 914 switch (disc_type) 915 { 916 case GATT_DISC_SRVC_ALL: 917 /* discover services result, add services into a service list */ 918 bta_gattc_add_srvc_to_list(p_srvc_cb, 919 p_data->handle, 920 p_data->value.group_value.e_handle, 921 p_data->value.group_value.service_type, 922 TRUE); 923 924 break; 925 case GATT_DISC_SRVC_BY_UUID: 926 bta_gattc_add_srvc_to_list(p_srvc_cb, 927 p_data->handle, 928 p_data->value.group_value.e_handle, 929 p_data->value.group_value.service_type, 930 TRUE); 931 break; 932 933 case GATT_DISC_INC_SRVC: 934 /* add included service into service list if it's secondary or it never showed up 935 in the primary service search */ 936 pri_srvc = bta_gattc_srvc_in_list(p_srvc_cb, 937 p_data->value.incl_service.s_handle, 938 p_data->value.incl_service.e_handle, 939 p_data->value.incl_service.service_type); 940 941 if (!pri_srvc) 942 bta_gattc_add_srvc_to_list(p_srvc_cb, 943 p_data->value.incl_service.s_handle, 944 p_data->value.incl_service.e_handle, 945 p_data->value.incl_service.service_type, 946 FALSE); 947 /* add into database */ 948 bta_gattc_add_attr_to_cache(p_srvc_cb, 949 p_data->handle, 950 &p_data->value.incl_service.service_type, 951 pri_srvc, 952 BTA_GATTC_ATTR_TYPE_INCL_SRVC); 953 break; 954 955 case GATT_DISC_CHAR: 956 /* add char value into database */ 957 bta_gattc_add_char_to_list(p_srvc_cb, 958 p_data->handle, 959 p_data->value.dclr_value.val_handle, 960 p_data->value.dclr_value.char_uuid, 961 p_data->value.dclr_value.char_prop); 962 break; 963 964 case GATT_DISC_CHAR_DSCPT: 965 bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0, BTA_GATTC_ATTR_TYPE_CHAR_DESCR); 966 break; 967 } 968 } 969 } 970 void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status) 971 { 972 tBTA_GATTC_SERV * p_srvc_cb; 973 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 974 975 if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) ) 976 { 977 if (p_clcb->status == GATT_SUCCESS) 978 p_clcb->status = status; 979 bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL); 980 return; 981 } 982 p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id); 983 984 if (p_srvc_cb != NULL) 985 { 986 switch (disc_type) 987 { 988 case GATT_DISC_SRVC_ALL: 989 case GATT_DISC_SRVC_BY_UUID: 990 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 991 bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx); 992 #endif 993 bta_gattc_explore_srvc(conn_id, p_srvc_cb); 994 break; 995 996 case GATT_DISC_INC_SRVC: 997 bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb); 998 999 break; 1000 1001 case GATT_DISC_CHAR: 1002 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1003 bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx); 1004 #endif 1005 bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb); 1006 break; 1007 1008 case GATT_DISC_CHAR_DSCPT: 1009 bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb); 1010 break; 1011 } 1012 } 1013 } 1014 /******************************************************************************* 1015 ** 1016 ** Function bta_gattc_id2handle 1017 ** 1018 ** Description map GATT ID to handle in a given cache. 1019 ** 1020 ** Returns the handle mapped. 0 if not found. 1021 ** 1022 *******************************************************************************/ 1023 UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id, 1024 tBTA_GATT_ID *p_char_id, tBT_UUID descr_uuid) 1025 { 1026 tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache; 1027 tBTA_GATTC_CACHE_ATTR *p_attr; 1028 UINT8 j; 1029 UINT16 handle = 0; 1030 tBT_UUID attr_uuid; 1031 BOOLEAN char_map = FALSE, done = FALSE; 1032 1033 while (p_service_id && p_cache && !done) 1034 { 1035 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1036 APPL_TRACE_DEBUG3("Service: handle[%d] uuid[0x%04x] inst[%d]", 1037 p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16, 1038 p_cache->service_uuid.id.inst_id); 1039 #endif 1040 p_attr = p_cache->p_attr; 1041 1042 if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid)) 1043 { 1044 for (j = 0; p_attr; j ++) 1045 { 1046 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1047 APPL_TRACE_DEBUG5("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]", 1048 j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id, p_attr->attr_type); 1049 #endif 1050 bta_gattc_pack_attr_uuid(p_attr, &attr_uuid); 1051 1052 if (bta_gattc_uuid_compare(p_char_id->uuid, attr_uuid, TRUE) && 1053 p_char_id->inst_id == p_attr->inst_id) 1054 { 1055 if (descr_uuid.len == 0) 1056 { 1057 handle = p_attr->attr_handle; 1058 done = TRUE; 1059 break; 1060 } 1061 else 1062 { 1063 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1064 APPL_TRACE_DEBUG0("found matching characteristic for the descriptor"); 1065 #endif 1066 char_map = TRUE; 1067 } 1068 } 1069 else if (char_map == TRUE) 1070 { 1071 if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) 1072 { 1073 1074 if (bta_gattc_uuid_compare(descr_uuid, attr_uuid, TRUE)) 1075 { 1076 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1077 APPL_TRACE_DEBUG0("found descriptor!!"); 1078 #endif 1079 handle = p_attr->attr_handle; 1080 done = TRUE; 1081 break; 1082 } 1083 else 1084 { 1085 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1086 APPL_TRACE_DEBUG0("descriptor UUID not matching"); 1087 #endif 1088 } 1089 } 1090 else /* another char */ 1091 { 1092 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1093 APPL_TRACE_DEBUG0("no matching descriptor found!! start of next characteristic"); 1094 #endif 1095 char_map = FALSE; 1096 done = TRUE; 1097 break; 1098 } 1099 } 1100 p_attr = p_attr->p_next; 1101 } 1102 } 1103 p_cache = p_cache->p_next; 1104 } 1105 1106 return handle; 1107 } 1108 /******************************************************************************* 1109 ** 1110 ** Function bta_gattc_handle2id 1111 ** 1112 ** Description map a handle to GATT ID in a given cache. 1113 ** 1114 ** Returns FALSE if map can not be found. 1115 ** 1116 *******************************************************************************/ 1117 1118 BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *p_service_id, 1119 tBTA_GATT_ID *p_char_id, tBT_UUID *p_descr_type) 1120 { 1121 tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache; 1122 tBTA_GATTC_CACHE_ATTR *p_attr, *p_char = NULL; 1123 UINT8 j; 1124 1125 memset(p_service_id, 0, sizeof(tBTA_GATT_SRVC_ID)); 1126 memset(p_char_id, 0, sizeof(tBTA_GATT_ID)); 1127 memset(p_descr_type, 0, sizeof(tBT_UUID)); 1128 1129 while (p_cache) 1130 { 1131 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1132 APPL_TRACE_DEBUG3("Service: handle[%d] uuid[0x%04x] inst[%d]", 1133 p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16, 1134 p_cache->service_uuid.id.inst_id); 1135 #endif 1136 /* a service found */ 1137 if (p_cache->s_handle == handle) 1138 { 1139 memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID)); 1140 1141 return TRUE; 1142 } 1143 else /* start looking for attributes within the service */ 1144 { 1145 p_attr = p_cache->p_attr; 1146 1147 for (j = 0; p_attr; j ++) 1148 { 1149 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1150 APPL_TRACE_DEBUG5("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]", 1151 j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id, p_attr->attr_type); 1152 #endif 1153 if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR) 1154 p_char = p_attr; 1155 1156 if (handle == p_attr->attr_handle) 1157 { 1158 memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID)); 1159 1160 if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) 1161 { 1162 bta_gattc_pack_attr_uuid(p_attr, p_descr_type); 1163 1164 if (p_char != NULL) 1165 { 1166 bta_gattc_pack_attr_uuid(p_char, &p_char_id->uuid); 1167 p_char_id->inst_id = p_char->inst_id; 1168 } 1169 else 1170 { 1171 APPL_TRACE_ERROR0("descriptor does not belong to any chracteristic, error"); 1172 } 1173 } 1174 else 1175 /* is a characterisitc value or included service */ 1176 { 1177 bta_gattc_pack_attr_uuid(p_attr, &p_char_id->uuid); 1178 p_char_id->inst_id =p_attr->inst_id; 1179 } 1180 return TRUE; 1181 } 1182 p_attr = p_attr->p_next; 1183 } 1184 } 1185 p_cache = p_cache->p_next; 1186 } 1187 1188 return FALSE; 1189 } 1190 1191 /******************************************************************************* 1192 ** 1193 ** Function bta_gattc_search_service 1194 ** 1195 ** Description search local cache for matching service record. 1196 ** 1197 ** Returns FALSE if map can not be found. 1198 ** 1199 *******************************************************************************/ 1200 void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID uuid) 1201 { 1202 tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb; 1203 tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache; 1204 tBTA_GATTC cb_data; 1205 1206 while (p_cache) 1207 { 1208 if (bta_gattc_uuid_compare(uuid, p_cache->service_uuid.id.uuid, FALSE)) 1209 { 1210 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1211 APPL_TRACE_DEBUG3("found service [0x%04x], inst[%d] handle [%d]", 1212 p_cache->service_uuid.id.uuid.uu.uuid16, 1213 p_cache->service_uuid.id.inst_id, 1214 p_cache->s_handle); 1215 #endif 1216 if (p_clcb->p_rcb->p_cback) 1217 { 1218 memset(&cb_data, 0, sizeof(tBTA_GATTC)); 1219 1220 cb_data.srvc_res.conn_id = p_clcb->bta_conn_id; 1221 memcpy(&cb_data.srvc_res.service_uuid, &p_cache->service_uuid ,sizeof(tBTA_GATT_SRVC_ID)); 1222 1223 (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data); 1224 } 1225 } 1226 p_cache = p_cache->p_next; 1227 } 1228 } 1229 /******************************************************************************* 1230 ** 1231 ** Function bta_gattc_find_record 1232 ** 1233 ** Description search local cache for matching attribute record. 1234 ** 1235 ** Parameter p_result: output parameter to store the characteristic/ 1236 ** included service GATT ID. 1237 ** 1238 ** Returns GATT_ERROR is no recording found. BTA_GATT_OK if record found. 1239 ** 1240 *******************************************************************************/ 1241 static tBTA_GATT_STATUS bta_gattc_find_record(tBTA_GATTC_SERV *p_srcb, 1242 tBTA_GATTC_ATTR_TYPE attr_type, 1243 tBTA_GATT_SRVC_ID *p_service_id, 1244 tBTA_GATT_ID *p_start_rec, 1245 tBT_UUID * p_uuid_cond, 1246 tBTA_GATT_ID *p_result, 1247 void *p_param) 1248 { 1249 tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache; 1250 tBTA_GATT_STATUS status = BTA_GATT_ERROR; 1251 tBT_UUID uuid_cond = {0}, start_descr = {0}; 1252 UINT8 i, j; 1253 tBTA_GATTC_CACHE_ATTR *p_attr; 1254 BOOLEAN char_found = FALSE, descr_found = FALSE; 1255 1256 if (p_uuid_cond) 1257 memcpy(&uuid_cond, p_uuid_cond, sizeof(tBT_UUID)); 1258 1259 for (i = 0; p_cache && status != BTA_GATT_OK; i ++) 1260 { 1261 if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid)) 1262 { 1263 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1264 APPL_TRACE_DEBUG2("found matching service [0x%04x], inst[%d]", 1265 p_cache->service_uuid.id.uuid.uu.uuid16, 1266 p_cache->service_uuid.id.inst_id); 1267 #endif 1268 p_attr = p_cache->p_attr; 1269 1270 for (j = 0; p_attr; j ++) 1271 { 1272 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1273 APPL_TRACE_DEBUG5("\t Attr[%d] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]", 1274 j + 1, p_attr->attr_handle, 1275 p_attr->p_uuid->uuid16, 1276 p_attr->inst_id, 1277 p_attr->attr_type); 1278 #endif 1279 bta_gattc_pack_attr_uuid(p_attr, &p_result->uuid); 1280 1281 if (p_start_rec != NULL && char_found == FALSE) 1282 { 1283 /* find the starting record first */ 1284 if (bta_gattc_uuid_compare(p_start_rec->uuid, p_result->uuid, FALSE) && 1285 p_start_rec->inst_id == p_attr->inst_id && 1286 (attr_type == p_attr->attr_type || 1287 /* find descriptor would look for characteristic first */ 1288 (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR && p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR))) 1289 { 1290 char_found = TRUE; 1291 } 1292 } 1293 else 1294 { 1295 /* if looking for descriptor, here is the where the descrptor to be found */ 1296 if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) 1297 { 1298 /* starting descriptor UUID */ 1299 if (p_param != NULL) 1300 memcpy(&start_descr, p_param, sizeof(tBT_UUID)); 1301 /* next characeteristic already, return error */ 1302 if (p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR_DESCR) 1303 { 1304 break; 1305 } 1306 else 1307 { 1308 if (start_descr.len != 0 && !descr_found) 1309 { 1310 if (bta_gattc_uuid_compare(start_descr, p_result->uuid, FALSE)) 1311 { 1312 descr_found = TRUE; 1313 } 1314 } 1315 else 1316 { 1317 /* with matching descriptor */ 1318 if (bta_gattc_uuid_compare(uuid_cond, p_result->uuid, FALSE)) 1319 { 1320 status = BTA_GATT_OK; 1321 break; 1322 } 1323 } 1324 } 1325 } 1326 else 1327 { 1328 if (bta_gattc_uuid_compare(uuid_cond, p_result->uuid, FALSE) && 1329 attr_type == p_attr->attr_type) 1330 { 1331 1332 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1333 APPL_TRACE_DEBUG0("found char handle mapping characteristic"); 1334 #endif 1335 p_result->inst_id = p_attr->inst_id; 1336 1337 if (p_param != NULL) 1338 { 1339 if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR || 1340 attr_type == BTA_GATTC_ATTR_TYPE_INCL_SRVC) 1341 { 1342 *(tBTA_GATT_CHAR_PROP *)p_param = p_attr->property; 1343 } 1344 } 1345 1346 status = BTA_GATT_OK; 1347 break; 1348 } 1349 } 1350 } 1351 p_attr = p_attr->p_next; 1352 } 1353 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) 1354 if (status) 1355 { 1356 APPL_TRACE_ERROR0("In the given service, can not find matching record"); 1357 } 1358 #endif 1359 break; 1360 } 1361 1362 p_cache = p_cache->p_next; 1363 } 1364 return status; 1365 1366 } 1367 1368 /******************************************************************************* 1369 ** 1370 ** Function bta_gattc_query_cache 1371 ** 1372 ** Description search local cache for matching attribute record. 1373 ** 1374 ** Parameters conn_id: connection ID which identify the server. 1375 ** p_srvc_id: the service ID of which the characteristic is belonged to. 1376 ** *p_start_rec: start the search from the next record 1377 ** after the one identified by *p_start_rec. 1378 ** p_uuid_cond: UUID, if NULL find the first available 1379 ** characteristic/included service. 1380 ** p_output: output parameter which will store the GATT ID 1381 ** of the characteristic /included service found. 1382 ** 1383 ** Returns BTA_GATT_ERROR is no recording found. BTA_GATT_OK if record found. 1384 ** 1385 *******************************************************************************/ 1386 tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id, 1387 tBTA_GATTC_ATTR_TYPE query_type, 1388 tBTA_GATT_SRVC_ID *p_srvc_id, 1389 tBTA_GATT_ID *p_start_rec, 1390 tBT_UUID *p_uuid_cond, 1391 tBTA_GATT_ID *p_output, 1392 void *p_param) 1393 { 1394 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 1395 tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER; 1396 1397 /* lock other GKI task */ 1398 GKI_sched_lock(); 1399 1400 if (p_clcb != NULL ) 1401 { 1402 if (p_clcb->state == BTA_GATTC_CONN_ST) 1403 { 1404 if (p_clcb->p_srcb && 1405 !p_clcb->p_srcb->p_srvc_list && /* no active discovery */ 1406 p_clcb->p_srcb->p_srvc_cache) 1407 { 1408 status = bta_gattc_find_record(p_clcb->p_srcb, 1409 query_type, 1410 p_srvc_id, 1411 p_start_rec, 1412 p_uuid_cond, 1413 p_output, 1414 p_param); 1415 } 1416 else 1417 { 1418 status = BTA_GATT_ERROR; 1419 APPL_TRACE_ERROR0("No server cache available"); 1420 } 1421 } 1422 else 1423 { 1424 APPL_TRACE_ERROR1("server cache not available, CLCB state = %d", p_clcb->state); 1425 1426 status = (p_clcb->state == BTA_GATTC_DISCOVER_ST) ? BTA_GATT_BUSY : BTA_GATT_ERROR; 1427 } 1428 } 1429 else 1430 { 1431 APPL_TRACE_ERROR1("Unknown conn ID: %d", conn_id); 1432 } 1433 GKI_sched_unlock(); 1434 1435 return status; 1436 } 1437 1438 /******************************************************************************* 1439 ** 1440 ** Function bta_gattc_rebuild_cache 1441 ** 1442 ** Description rebuild server cache from NV cache. 1443 ** 1444 ** Parameters 1445 ** 1446 ** Returns None. 1447 ** 1448 *******************************************************************************/ 1449 void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr, 1450 tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index) 1451 { 1452 /* first attribute loading, initialize buffer */ 1453 APPL_TRACE_ERROR0("bta_gattc_rebuild_cache"); 1454 if (attr_index == 0) 1455 { 1456 while (p_srvc_cb->cache_buffer.p_first) 1457 GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer)); 1458 1459 if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL) 1460 { 1461 APPL_TRACE_ERROR0("allocate cache buffer failed, no resources"); 1462 } 1463 else 1464 { 1465 p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL; 1466 } 1467 } 1468 1469 while (num_attr > 0 && p_attr != NULL) 1470 { 1471 switch (p_attr->attr_type) 1472 { 1473 case BTA_GATTC_ATTR_TYPE_SRVC: 1474 bta_gattc_add_srvc_to_cache(p_srvc_cb, 1475 p_attr->s_handle, 1476 p_attr->e_handle, 1477 &p_attr->uuid, 1478 p_attr->is_primary, 1479 p_attr->id); 1480 break; 1481 1482 case BTA_GATTC_ATTR_TYPE_CHAR: 1483 case BTA_GATTC_ATTR_TYPE_CHAR_DESCR: 1484 case BTA_GATTC_ATTR_TYPE_INCL_SRVC: 1485 bta_gattc_add_attr_to_cache(p_srvc_cb, 1486 p_attr->s_handle, 1487 &p_attr->uuid, 1488 p_attr->prop, 1489 p_attr->attr_type); 1490 break; 1491 } 1492 p_attr ++; 1493 num_attr --; 1494 } 1495 } 1496 1497 /******************************************************************************* 1498 ** 1499 ** Function bta_gattc_fill_nv_attr 1500 ** 1501 ** Description fill a NV attribute entry value 1502 ** 1503 ** Returns None. 1504 ** 1505 *******************************************************************************/ 1506 void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle, 1507 UINT16 e_handle, UINT8 id, tBT_UUID uuid, UINT8 prop, BOOLEAN is_primary) 1508 { 1509 p_attr->s_handle = s_handle; 1510 p_attr->e_handle = e_handle; 1511 p_attr->attr_type = type; 1512 p_attr->is_primary = is_primary; 1513 p_attr->id = id; 1514 p_attr->prop = prop; 1515 1516 memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID)); 1517 } 1518 /******************************************************************************* 1519 ** 1520 ** Function bta_gattc_cache_save 1521 ** 1522 ** Description save the server cache into NV 1523 ** 1524 ** Returns None. 1525 ** 1526 *******************************************************************************/ 1527 BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id) 1528 { 1529 tBTA_GATTC_CACHE *p_cur_srvc = p_srvc_cb->p_srvc_cache; 1530 UINT8 i = 0; 1531 UINT16 offset = 0; 1532 tBTA_GATTC_NV_ATTR nv_attr[BTA_GATTC_NV_LOAD_MAX]; 1533 tBTA_GATTC_CACHE_ATTR *p_attr; 1534 tBT_UUID uuid; 1535 1536 while (p_cur_srvc && i < BTA_GATTC_NV_LOAD_MAX) 1537 { 1538 if (offset ++ >= p_srvc_cb->attr_index) 1539 { 1540 bta_gattc_fill_nv_attr(&nv_attr[i++], 1541 BTA_GATTC_ATTR_TYPE_SRVC, 1542 p_cur_srvc->s_handle, 1543 p_cur_srvc->e_handle, 1544 p_cur_srvc->service_uuid.id.inst_id, 1545 p_cur_srvc->service_uuid.id.uuid, 1546 0, 1547 p_cur_srvc->service_uuid.is_primary); 1548 } 1549 1550 p_attr = p_cur_srvc->p_attr; 1551 1552 for (; p_attr && i < BTA_GATTC_NV_LOAD_MAX ; offset ++, p_attr = p_attr->p_next) 1553 { 1554 if (offset >= p_srvc_cb->attr_index) 1555 { 1556 if ((uuid.len = p_attr->uuid_len) == LEN_UUID_16) 1557 { 1558 uuid.uu.uuid16 = p_attr->p_uuid->uuid16; 1559 } 1560 else 1561 { 1562 memcpy(uuid.uu.uuid128, p_attr->p_uuid->uuid128, LEN_UUID_128); 1563 } 1564 1565 bta_gattc_fill_nv_attr(&nv_attr[i++], 1566 p_attr->attr_type, 1567 p_attr->attr_handle, 1568 0, 1569 p_attr->inst_id, 1570 uuid, 1571 p_attr->property, 1572 FALSE); 1573 } 1574 } 1575 p_cur_srvc = p_cur_srvc->p_next; 1576 } 1577 1578 if (i > 0) 1579 { 1580 bta_gattc_co_cache_save(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_SAVE_EVT, i, 1581 nv_attr, p_srvc_cb->attr_index, conn_id); 1582 1583 p_srvc_cb->attr_index += i; 1584 1585 return TRUE; 1586 } 1587 else 1588 { 1589 return FALSE; 1590 } 1591 } 1592 #endif /* BTA_GATT_INCLUDED */ 1593 1594