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 41static 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*******************************************************************************/ 53void 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*******************************************************************************/ 70BOOLEAN 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*******************************************************************************/ 121tBTA_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*******************************************************************************/ 143UINT8 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*******************************************************************************/ 163tBTA_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*******************************************************************************/ 187tBTA_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*******************************************************************************/ 210tBTA_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*******************************************************************************/ 256tBTA_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*******************************************************************************/ 276void 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*******************************************************************************/ 307tBTA_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*******************************************************************************/ 328tBTA_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*******************************************************************************/ 346tBTA_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*******************************************************************************/ 394BOOLEAN 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*******************************************************************************/ 423void 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*******************************************************************************/ 451BOOLEAN 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*******************************************************************************/ 483void 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*******************************************************************************/ 517tBTA_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*******************************************************************************/ 565BOOLEAN 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*******************************************************************************/ 615BOOLEAN 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*******************************************************************************/ 642void 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