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