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 utility function. 22 * 23 ******************************************************************************/ 24 25 #include "bt_target.h" 26 27 #if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE) 28 29 #include <string.h> 30 #include "utl.h" 31 #include "gki.h" 32 #include "bta_sys.h" 33 #include "bta_gattc_int.h" 34 #include "bd.h" 35 36 /***************************************************************************** 37 ** Constants 38 *****************************************************************************/ 39 40 41 static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, 42 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 43 44 /******************************************************************************* 45 ** 46 ** Function bta_gatt_convert_uuid16_to_uuid128 47 ** 48 ** Description Convert a 16 bits UUID to be an standard 128 bits one. 49 ** 50 ** Returns TRUE if two uuid match; FALSE otherwise. 51 ** 52 *******************************************************************************/ 53 void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16) 54 { 55 UINT8 *p = &uuid_128[LEN_UUID_128 - 4]; 56 57 memcpy (uuid_128, base_uuid, LEN_UUID_128); 58 59 UINT16_TO_STREAM(p, uuid_16); 60 } 61 /******************************************************************************* 62 ** 63 ** Function bta_gattc_uuid_compare 64 ** 65 ** Description Compare two UUID to see if they are the same. 66 ** 67 ** Returns TRUE if two uuid match; FALSE otherwise. 68 ** 69 *******************************************************************************/ 70 BOOLEAN bta_gattc_uuid_compare (tBT_UUID src, tBT_UUID tar, BOOLEAN is_precise) 71 { 72 UINT8 su[LEN_UUID_128], tu[LEN_UUID_128]; 73 UINT8 *ps, *pt; 74 75 /* any of the UUID is unspecified */ 76 if (src.len == 0 || tar.len == 0) 77 { 78 if (is_precise) 79 return FALSE; 80 else 81 return TRUE; 82 } 83 84 /* If both are 16-bit, we can do a simple compare */ 85 if (src.len == 2 && tar.len == 2) 86 { 87 return src.uu.uuid16 == tar.uu.uuid16; 88 } 89 90 /* One or both of the UUIDs is 128-bit */ 91 if (src.len == LEN_UUID_16) 92 { 93 /* convert a 16 bits UUID to 128 bits value */ 94 bta_gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16); 95 ps = su; 96 } 97 else 98 ps = src.uu.uuid128; 99 100 if (tar.len == LEN_UUID_16) 101 { 102 /* convert a 16 bits UUID to 128 bits value */ 103 bta_gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16); 104 pt = tu; 105 } 106 else 107 pt = tar.uu.uuid128; 108 109 return(memcmp(ps, pt, LEN_UUID_128) == 0); 110 } 111 112 /******************************************************************************* 113 ** 114 ** Function bta_gattc_cl_get_regcb 115 ** 116 ** Description get registration control block by client interface. 117 ** 118 ** Returns pointer to the regcb 119 ** 120 *******************************************************************************/ 121 tBTA_GATTC_RCB * bta_gattc_cl_get_regcb(UINT8 client_if) 122 { 123 UINT8 i = 0; 124 tBTA_GATTC_RCB *p_clrcb = &bta_gattc_cb.cl_rcb[0]; 125 126 for (i = 0; i < BTA_GATTC_CL_MAX; i ++, p_clrcb ++) 127 { 128 if (p_clrcb->in_use && 129 p_clrcb->client_if == client_if) 130 return p_clrcb; 131 } 132 return NULL; 133 } 134 /******************************************************************************* 135 ** 136 ** Function bta_gattc_num_reg_app 137 ** 138 ** Description find the number of registered application. 139 ** 140 ** Returns pointer to the regcb 141 ** 142 *******************************************************************************/ 143 UINT8 bta_gattc_num_reg_app(void) 144 { 145 UINT8 i = 0, j = 0; 146 147 for (i = 0; i < BTA_GATTC_CL_MAX; i ++) 148 { 149 if (bta_gattc_cb.cl_rcb[i].in_use) 150 j ++; 151 } 152 return j; 153 } 154 /******************************************************************************* 155 ** 156 ** Function bta_gattc_find_clcb_by_cif 157 ** 158 ** Description get clcb by client interface and remote bd adddress 159 ** 160 ** Returns pointer to the clcb 161 ** 162 *******************************************************************************/ 163 tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda) 164 { 165 tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0]; 166 UINT8 i; 167 168 for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++) 169 { 170 if (p_clcb->in_use && 171 p_clcb->p_rcb->client_if == client_if && 172 p_clcb->p_srcb && 173 bdcmp(p_clcb->p_srcb->server_bda, remote_bda) == 0) 174 return p_clcb; 175 } 176 return NULL; 177 } 178 /******************************************************************************* 179 ** 180 ** Function bta_gattc_find_clcb_by_conn_id 181 ** 182 ** Description get clcb by connection ID 183 ** 184 ** Returns pointer to the clcb 185 ** 186 *******************************************************************************/ 187 tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_conn_id (UINT16 conn_id) 188 { 189 tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0]; 190 UINT8 i; 191 192 for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++) 193 { 194 if (p_clcb->in_use && 195 p_clcb->bta_conn_id == conn_id) 196 return p_clcb; 197 } 198 return NULL; 199 } 200 201 /******************************************************************************* 202 ** 203 ** Function bta_gattc_clcb_alloc 204 ** 205 ** Description allocate CLCB 206 ** 207 ** Returns pointer to the clcb 208 ** 209 *******************************************************************************/ 210 tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda) 211 { 212 UINT8 i_clcb = 0; 213 tBTA_GATTC_CLCB *p_clcb = NULL; 214 215 for (i_clcb = 0; i_clcb < BTA_GATTC_CLCB_MAX; i_clcb++) 216 { 217 if (!bta_gattc_cb.clcb[i_clcb].in_use) 218 { 219 #if BTA_GATT_DEBUG == TRUE 220 APPL_TRACE_DEBUG1("bta_gattc_clcb_alloc: found clcb[%d] available",i_clcb); 221 #endif 222 p_clcb = &bta_gattc_cb.clcb[i_clcb]; 223 p_clcb->in_use = TRUE; 224 bdcpy(p_clcb->bda, remote_bda); 225 226 p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if); 227 228 if ((p_clcb->p_srcb = bta_gattc_find_srcb(remote_bda)) == NULL) 229 p_clcb->p_srcb = bta_gattc_srcb_alloc(remote_bda); 230 231 if (p_clcb->p_rcb != NULL && p_clcb->p_srcb != NULL) 232 { 233 p_clcb->p_srcb->num_clcb ++; 234 p_clcb->p_rcb->num_clcb ++; 235 } 236 else 237 { 238 /* release this clcb if clcb or srcb allocation failed */ 239 p_clcb->in_use = FALSE; 240 p_clcb = NULL; 241 } 242 break; 243 } 244 } 245 return p_clcb; 246 } 247 /******************************************************************************* 248 ** 249 ** Function bta_gattc_find_alloc_clcb 250 ** 251 ** Description find or allocate CLCB if not found. 252 ** 253 ** Returns pointer to the clcb 254 ** 255 *******************************************************************************/ 256 tBTA_GATTC_CLCB *bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda) 257 { 258 tBTA_GATTC_CLCB *p_clcb ; 259 260 if ((p_clcb = bta_gattc_find_clcb_by_cif(client_if, remote_bda)) == NULL) 261 { 262 p_clcb = bta_gattc_clcb_alloc(client_if, remote_bda); 263 } 264 return p_clcb; 265 } 266 267 /******************************************************************************* 268 ** 269 ** Function bta_gattc_clcb_dealloc 270 ** 271 ** Description Deallocte a clcb 272 ** 273 ** Returns pointer to the clcb 274 ** 275 *******************************************************************************/ 276 void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb) 277 { 278 279 if (p_clcb) 280 { 281 if (p_clcb->p_srcb->num_clcb) 282 p_clcb->p_srcb->num_clcb --; 283 284 if (p_clcb->p_rcb->num_clcb) 285 p_clcb->p_rcb->num_clcb --; 286 287 utl_freebuf((void **)&p_clcb->p_q_cmd); 288 289 APPL_TRACE_ERROR2("bta_gattc_clcb_dealloc in_use=%d conn_id=%d",p_clcb->in_use, p_clcb->bta_conn_id); 290 memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB)); 291 } 292 else 293 { 294 APPL_TRACE_ERROR0("bta_gattc_clcb_dealloc p_clcb=NULL"); 295 } 296 } 297 298 /******************************************************************************* 299 ** 300 ** Function bta_gattc_find_srcb 301 ** 302 ** Description find server cache by remote bd address 303 ** 304 ** Returns pointer to the server cache. 305 ** 306 *******************************************************************************/ 307 tBTA_GATTC_SERV * bta_gattc_find_srcb(BD_ADDR bda) 308 { 309 tBTA_GATTC_SERV *p_srcb = &bta_gattc_cb.known_server[0]; 310 UINT8 i; 311 312 for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_srcb ++) 313 { 314 if (p_srcb->in_use && bdcmp(p_srcb->server_bda, bda) == 0) 315 return p_srcb; 316 } 317 return NULL; 318 } 319 /******************************************************************************* 320 ** 321 ** Function bta_gattc_find_scb_by_cid 322 ** 323 ** Description find server control block by connection ID 324 ** 325 ** Returns pointer to the server cache. 326 ** 327 *******************************************************************************/ 328 tBTA_GATTC_SERV * bta_gattc_find_scb_by_cid (UINT16 conn_id) 329 { 330 tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 331 332 if (p_clcb) 333 return p_clcb->p_srcb; 334 else 335 return NULL; 336 } 337 /******************************************************************************* 338 ** 339 ** Function bta_gattc_srcb_alloc 340 ** 341 ** Description allocate server cache control block 342 ** 343 ** Returns pointer to the server cache. 344 ** 345 *******************************************************************************/ 346 tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda) 347 { 348 tBTA_GATTC_SERV *p_tcb = &bta_gattc_cb.known_server[0], 349 *p_recycle = NULL; 350 BOOLEAN found = FALSE; 351 UINT8 i; 352 353 for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_tcb ++) 354 { 355 if (!p_tcb->in_use) 356 { 357 found = TRUE; 358 break; 359 } 360 else if (!p_tcb->connected) 361 { 362 p_recycle = p_tcb; 363 } 364 } 365 366 /* if not found, try to recycle one known device */ 367 if (!found && !p_recycle) 368 p_tcb = NULL; 369 else if (p_recycle) 370 p_tcb = p_recycle; 371 372 if (p_tcb != NULL) 373 { 374 while (p_tcb->cache_buffer.p_first) 375 GKI_freebuf (GKI_dequeue (&p_tcb->cache_buffer)); 376 377 utl_freebuf((void **)&p_tcb->p_srvc_list); 378 memset(p_tcb, 0 , sizeof(tBTA_GATTC_SERV)); 379 380 p_tcb->in_use = TRUE; 381 bdcpy(p_tcb->server_bda, bda); 382 } 383 return p_tcb; 384 } 385 /******************************************************************************* 386 ** 387 ** Function bta_gattc_enqueue 388 ** 389 ** Description enqueue a client request in clcb. 390 ** 391 ** Returns success or failure. 392 ** 393 *******************************************************************************/ 394 BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) 395 { 396 BOOLEAN in_q = FALSE; 397 398 if (p_clcb->p_q_cmd == NULL) 399 { 400 p_clcb->p_q_cmd = (tBTA_GATTC_DATA *)GKI_getbuf(sizeof(tBTA_GATTC_DATA)); 401 402 if (p_data) 403 memcpy(p_clcb->p_q_cmd, p_data, sizeof(tBTA_GATTC_DATA)); 404 405 in_q = TRUE; 406 } 407 else 408 { 409 APPL_TRACE_ERROR0("already has a pending command!!"); 410 /* skip the callback now. ----- need to send callback ? */ 411 } 412 return in_q; 413 } 414 /******************************************************************************* 415 ** 416 ** Function bta_gattc_pack_attr_uuid 417 ** 418 ** Description pack UUID into a stream. 419 ** 420 ** Returns 421 ** 422 *******************************************************************************/ 423 void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR *p_attr, tBT_UUID *p_uuid) 424 { 425 UINT8 *pp = (UINT8 *)p_attr->p_uuid; 426 427 memset(p_uuid, 0, sizeof(tBT_UUID)); 428 429 p_uuid->len = p_attr->uuid_len; 430 431 if (p_attr->uuid_len == LEN_UUID_16) 432 { 433 STREAM_TO_UINT16(p_uuid->uu.uuid16, pp); 434 } 435 else 436 { 437 memcpy(p_uuid->uu.uuid128, pp, LEN_UUID_128); 438 } 439 440 return; 441 } 442 /******************************************************************************* 443 ** 444 ** Function bta_gattc_check_notif_registry 445 ** 446 ** Description check if the service notificaition has been registered. 447 ** 448 ** Returns 449 ** 450 *******************************************************************************/ 451 BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_SERV *p_srcb, 452 tBTA_GATTC_NOTIFY *p_notify) 453 { 454 UINT8 i; 455 456 for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++) 457 { 458 if (p_clreg->notif_reg[i].in_use && 459 bdcmp(p_clreg->notif_reg[i].remote_bda, p_srcb->server_bda) == 0 && 460 (bta_gattc_uuid_compare(p_clreg->notif_reg[i].char_id.srvc_id.id.uuid, p_notify->char_id.srvc_id.id.uuid, FALSE) && 461 p_clreg->notif_reg[i].char_id.srvc_id.id.inst_id == p_notify->char_id.srvc_id.id.inst_id && 462 p_clreg->notif_reg[i].char_id.srvc_id.is_primary == p_notify->char_id.srvc_id.is_primary && 463 bta_gattc_uuid_compare(p_clreg->notif_reg[i].char_id.char_id.uuid, p_notify->char_id.char_id.uuid, FALSE) && 464 p_clreg->notif_reg[i].char_id.char_id.inst_id == p_notify->char_id.char_id.inst_id) 465 ) 466 { 467 APPL_TRACE_DEBUG0("Notification registered!"); 468 return TRUE; 469 } 470 } 471 return FALSE; 472 473 } 474 /******************************************************************************* 475 ** 476 ** Function bta_gattc_clear_notif_registration 477 ** 478 ** Description clear up the notification registration information by BD_ADDR. 479 ** 480 ** Returns None. 481 ** 482 *******************************************************************************/ 483 void bta_gattc_clear_notif_registration(UINT16 conn_id) 484 { 485 BD_ADDR remote_bda; 486 tBTA_GATTC_IF gatt_if; 487 tBTA_GATTC_RCB *p_clrcb ; 488 UINT8 i; 489 490 if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda)) 491 { 492 if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) != NULL) 493 { 494 for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++) 495 { 496 if (p_clrcb->notif_reg[i].in_use && !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda)) 497 memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG)); 498 } 499 } 500 } 501 else 502 { 503 APPL_TRACE_ERROR0("can not clear indication/notif registration for unknown app"); 504 } 505 return; 506 } 507 508 /******************************************************************************* 509 ** 510 ** Function bta_gattc_pack_cb_data 511 ** 512 ** Description pack the data from read response into callback data structure. 513 ** 514 ** Returns 515 ** 516 *******************************************************************************/ 517 tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID descr_uuid, 518 tGATT_VALUE *p_attr, tBTA_GATT_READ_VAL *p_value) 519 { 520 UINT8 i = 0, *pp = p_attr->value; 521 tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_AGG_FORMAT}}; 522 UINT16 handle; 523 tBTA_GATT_STATUS status = BTA_GATT_OK; 524 525 /* GATT_UUID_CHAR_AGG_FORMAT */ 526 if (bta_gattc_uuid_compare (uuid, descr_uuid, TRUE)) 527 { 528 while (p_attr->len >= 2 && i < BTA_GATTC_MULTI_MAX) 529 { 530 STREAM_TO_UINT16(handle, pp); 531 532 if (bta_gattc_handle2id(p_srcb, 533 handle, 534 &p_value->aggre_value.pre_format[i].char_id.srvc_id, 535 &p_value->aggre_value.pre_format[i].char_id.char_id, 536 &p_value->aggre_value.pre_format[i].descr_type) == FALSE) 537 { 538 status = BTA_GATT_INTERNAL_ERROR; 539 APPL_TRACE_ERROR1("can not map to GATT ID. handle = 0x%04x", handle); 540 break; 541 } 542 i ++; 543 p_attr->len -= 2; 544 } 545 p_value->aggre_value.num_pres_fmt = i; 546 } 547 else 548 { 549 /* all others, take as raw format */ 550 p_value->unformat.len = p_attr->len; 551 p_value->unformat.p_value = p_attr->value; 552 } 553 return status; 554 } 555 /******************************************************************************* 556 ** 557 ** Function bta_gattc_mark_bg_conn 558 ** 559 ** Description mark background connection status when a bg connection is initiated 560 ** or terminated. 561 ** 562 ** Returns TRUE if success; FALSE otherwise. 563 ** 564 *******************************************************************************/ 565 BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN add) 566 { 567 tBTA_GATTC_BG_TCK *p_bg_tck = &bta_gattc_cb.bg_track[0]; 568 UINT8 i = 0; 569 570 for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++) 571 { 572 if (p_bg_tck->in_use && 573 bdcmp(p_bg_tck->remote_bda, remote_bda) == 0) 574 { 575 if (add) 576 /* mask on the cif bit */ 577 p_bg_tck->cif_mask |= (1 <<(client_if - 1)); 578 else 579 p_bg_tck->cif_mask &= (~(1 <<(client_if - 1))); 580 581 return TRUE; 582 } 583 } 584 if (!add) 585 { 586 APPL_TRACE_ERROR0("Do not find the bg connection mask for the remote device"); 587 return FALSE; 588 } 589 else /* adding a new device mask */ 590 { 591 for (i = 0, p_bg_tck = &bta_gattc_cb.bg_track[0]; 592 i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++) 593 { 594 if (!p_bg_tck->in_use) 595 { 596 p_bg_tck->in_use = TRUE; 597 bdcpy(p_bg_tck->remote_bda, remote_bda); 598 p_bg_tck->cif_mask = (1 <<(client_if - 1)); 599 return TRUE; 600 } 601 } 602 APPL_TRACE_ERROR0("no available space to mark the bg connection status"); 603 return FALSE; 604 } 605 } 606 /******************************************************************************* 607 ** 608 ** Function bta_gattc_check_bg_conn 609 ** 610 ** Description check if this is a background connection background connection. 611 ** 612 ** Returns TRUE if success; FALSE otherwise. 613 ** 614 *******************************************************************************/ 615 BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda) 616 { 617 tBTA_GATTC_BG_TCK *p_bg_tck = &bta_gattc_cb.bg_track[0]; 618 UINT8 i = 0; 619 BOOLEAN is_bg_conn = FALSE; 620 621 for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++) 622 { 623 if (p_bg_tck->in_use && 624 bdcmp(p_bg_tck->remote_bda, remote_bda) == 0) 625 { 626 if ((p_bg_tck->cif_mask &(1 <<(client_if - 1))) != 0) 627 is_bg_conn = TRUE; 628 break; 629 } 630 } 631 return is_bg_conn; 632 } 633 /******************************************************************************* 634 ** 635 ** Function bta_gattc_send_open_cback 636 ** 637 ** Description send open callback 638 ** 639 ** Returns 640 ** 641 *******************************************************************************/ 642 void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status, 643 BD_ADDR remote_bda, UINT16 conn_id) 644 { 645 tBTA_GATTC cb_data; 646 647 if (p_clreg->p_cback) 648 { 649 memset(&cb_data, 0, sizeof(tBTA_GATTC)); 650 651 cb_data.open.status = status; 652 cb_data.open.client_if = p_clreg->client_if; 653 cb_data.open.conn_id = conn_id; 654 bdcpy(cb_data.open.remote_bda, remote_bda); 655 656 (*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data); 657 } 658 } 659 660 661 662 663 664 #endif /* BTA_GATT_INCLUDED */ 665