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