1 /****************************************************************************** 2 * 3 * Copyright 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 #define LOG_TAG "bt_bta_gattc" 26 27 #include "bt_target.h" 28 29 #include <base/logging.h> 30 #include <string.h> 31 32 #include "bt_common.h" 33 #include "bta_gattc_int.h" 34 #include "bta_sys.h" 35 #include "l2c_api.h" 36 #include "utl.h" 37 38 /******************************************************************************* 39 * 40 * Function bta_gattc_cl_get_regcb 41 * 42 * Description get registration control block by client interface. 43 * 44 * Returns pointer to the regcb 45 * 46 ******************************************************************************/ 47 tBTA_GATTC_RCB* bta_gattc_cl_get_regcb(uint8_t client_if) { 48 uint8_t i = 0; 49 tBTA_GATTC_RCB* p_clrcb = &bta_gattc_cb.cl_rcb[0]; 50 51 for (i = 0; i < BTA_GATTC_CL_MAX; i++, p_clrcb++) { 52 if (p_clrcb->in_use && p_clrcb->client_if == client_if) return p_clrcb; 53 } 54 return NULL; 55 } 56 /******************************************************************************* 57 * 58 * Function bta_gattc_num_reg_app 59 * 60 * Description find the number of registered application. 61 * 62 * Returns pointer to the regcb 63 * 64 ******************************************************************************/ 65 uint8_t bta_gattc_num_reg_app(void) { 66 uint8_t i = 0, j = 0; 67 68 for (i = 0; i < BTA_GATTC_CL_MAX; i++) { 69 if (bta_gattc_cb.cl_rcb[i].in_use) j++; 70 } 71 return j; 72 } 73 /******************************************************************************* 74 * 75 * Function bta_gattc_find_clcb_by_cif 76 * 77 * Description get clcb by client interface and remote bd adddress 78 * 79 * Returns pointer to the clcb 80 * 81 ******************************************************************************/ 82 tBTA_GATTC_CLCB* bta_gattc_find_clcb_by_cif(uint8_t client_if, 83 const RawAddress& remote_bda, 84 tBTA_TRANSPORT transport) { 85 tBTA_GATTC_CLCB* p_clcb = &bta_gattc_cb.clcb[0]; 86 uint8_t i; 87 88 for (i = 0; i < BTA_GATTC_CLCB_MAX; i++, p_clcb++) { 89 if (p_clcb->in_use && p_clcb->p_rcb->client_if == client_if && 90 p_clcb->transport == transport && p_clcb->bda == remote_bda) 91 return p_clcb; 92 } 93 return NULL; 94 } 95 /******************************************************************************* 96 * 97 * Function bta_gattc_find_clcb_by_conn_id 98 * 99 * Description get clcb by connection ID 100 * 101 * Returns pointer to the clcb 102 * 103 ******************************************************************************/ 104 tBTA_GATTC_CLCB* bta_gattc_find_clcb_by_conn_id(uint16_t conn_id) { 105 tBTA_GATTC_CLCB* p_clcb = &bta_gattc_cb.clcb[0]; 106 uint8_t i; 107 108 for (i = 0; i < BTA_GATTC_CLCB_MAX; i++, p_clcb++) { 109 if (p_clcb->in_use && p_clcb->bta_conn_id == conn_id) return p_clcb; 110 } 111 return NULL; 112 } 113 114 /******************************************************************************* 115 * 116 * Function bta_gattc_clcb_alloc 117 * 118 * Description allocate CLCB 119 * 120 * Returns pointer to the clcb 121 * 122 ******************************************************************************/ 123 tBTA_GATTC_CLCB* bta_gattc_clcb_alloc(tGATT_IF client_if, 124 const RawAddress& remote_bda, 125 tBTA_TRANSPORT transport) { 126 uint8_t i_clcb = 0; 127 tBTA_GATTC_CLCB* p_clcb = NULL; 128 129 for (i_clcb = 0; i_clcb < BTA_GATTC_CLCB_MAX; i_clcb++) { 130 if (!bta_gattc_cb.clcb[i_clcb].in_use) { 131 #if (BTA_GATT_DEBUG == TRUE) 132 VLOG(1) << __func__ << ": found clcb:" << +i_clcb << " available"; 133 #endif 134 p_clcb = &bta_gattc_cb.clcb[i_clcb]; 135 p_clcb->in_use = true; 136 p_clcb->status = GATT_SUCCESS; 137 p_clcb->transport = transport; 138 p_clcb->bda = remote_bda; 139 140 p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if); 141 142 p_clcb->p_srcb = bta_gattc_find_srcb(remote_bda); 143 if (p_clcb->p_srcb == NULL) 144 p_clcb->p_srcb = bta_gattc_srcb_alloc(remote_bda); 145 146 if (p_clcb->p_rcb != NULL && p_clcb->p_srcb != NULL) { 147 p_clcb->p_srcb->num_clcb++; 148 p_clcb->p_rcb->num_clcb++; 149 } else { 150 /* release this clcb if clcb or srcb allocation failed */ 151 p_clcb->in_use = false; 152 p_clcb = NULL; 153 } 154 break; 155 } 156 } 157 return p_clcb; 158 } 159 /******************************************************************************* 160 * 161 * Function bta_gattc_find_alloc_clcb 162 * 163 * Description find or allocate CLCB if not found. 164 * 165 * Returns pointer to the clcb 166 * 167 ******************************************************************************/ 168 tBTA_GATTC_CLCB* bta_gattc_find_alloc_clcb(tGATT_IF client_if, 169 const RawAddress& remote_bda, 170 tBTA_TRANSPORT transport) { 171 tBTA_GATTC_CLCB* p_clcb; 172 173 p_clcb = bta_gattc_find_clcb_by_cif(client_if, remote_bda, transport); 174 if (p_clcb == NULL) { 175 p_clcb = bta_gattc_clcb_alloc(client_if, remote_bda, transport); 176 } 177 return p_clcb; 178 } 179 180 /******************************************************************************* 181 * 182 * Function bta_gattc_clcb_dealloc 183 * 184 * Description Deallocte a clcb 185 * 186 * Returns pointer to the clcb 187 * 188 ******************************************************************************/ 189 void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB* p_clcb) { 190 if (!p_clcb) { 191 LOG(ERROR) << __func__ << " p_clcb=NULL"; 192 return; 193 } 194 195 tBTA_GATTC_SERV* p_srcb = p_clcb->p_srcb; 196 if (p_srcb->num_clcb) p_srcb->num_clcb--; 197 198 if (p_clcb->p_rcb->num_clcb) p_clcb->p_rcb->num_clcb--; 199 200 /* if the srcb is no longer needed, reset the state */ 201 if (p_srcb->num_clcb == 0) { 202 p_srcb->connected = false; 203 p_srcb->state = BTA_GATTC_SERV_IDLE; 204 p_srcb->mtu = 0; 205 206 // clear reallocating 207 std::vector<tBTA_GATTC_SERVICE>().swap(p_srcb->srvc_cache); 208 } 209 210 osi_free_and_reset((void**)&p_clcb->p_q_cmd); 211 memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB)); 212 } 213 214 /******************************************************************************* 215 * 216 * Function bta_gattc_find_srcb 217 * 218 * Description find server cache by remote bd address currently in use 219 * 220 * Returns pointer to the server cache. 221 * 222 ******************************************************************************/ 223 tBTA_GATTC_SERV* bta_gattc_find_srcb(const RawAddress& bda) { 224 tBTA_GATTC_SERV* p_srcb = &bta_gattc_cb.known_server[0]; 225 uint8_t i; 226 227 for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i++, p_srcb++) { 228 if (p_srcb->in_use && p_srcb->server_bda == bda) return p_srcb; 229 } 230 return NULL; 231 } 232 233 /******************************************************************************* 234 * 235 * Function bta_gattc_find_srvr_cache 236 * 237 * Description find server cache by remote bd address 238 * 239 * Returns pointer to the server cache. 240 * 241 ******************************************************************************/ 242 tBTA_GATTC_SERV* bta_gattc_find_srvr_cache(const RawAddress& bda) { 243 tBTA_GATTC_SERV* p_srcb = &bta_gattc_cb.known_server[0]; 244 uint8_t i; 245 246 for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i++, p_srcb++) { 247 if (p_srcb->server_bda == bda) return p_srcb; 248 } 249 return NULL; 250 } 251 /******************************************************************************* 252 * 253 * Function bta_gattc_find_scb_by_cid 254 * 255 * Description find server control block by connection ID 256 * 257 * Returns pointer to the server cache. 258 * 259 ******************************************************************************/ 260 tBTA_GATTC_SERV* bta_gattc_find_scb_by_cid(uint16_t conn_id) { 261 tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); 262 263 if (p_clcb) 264 return p_clcb->p_srcb; 265 else 266 return NULL; 267 } 268 /******************************************************************************* 269 * 270 * Function bta_gattc_srcb_alloc 271 * 272 * Description allocate server cache control block 273 * 274 * Returns pointer to the server cache. 275 * 276 ******************************************************************************/ 277 tBTA_GATTC_SERV* bta_gattc_srcb_alloc(const RawAddress& bda) { 278 tBTA_GATTC_SERV *p_tcb = &bta_gattc_cb.known_server[0], *p_recycle = NULL; 279 bool found = false; 280 uint8_t i; 281 282 for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i++, p_tcb++) { 283 if (!p_tcb->in_use) { 284 found = true; 285 break; 286 } else if (!p_tcb->connected) { 287 p_recycle = p_tcb; 288 } 289 } 290 291 /* if not found, try to recycle one known device */ 292 if (!found && !p_recycle) 293 p_tcb = NULL; 294 else if (!found && p_recycle) 295 p_tcb = p_recycle; 296 297 if (p_tcb != NULL) { 298 // clear reallocating 299 std::vector<tBTA_GATTC_SERVICE>().swap(p_tcb->srvc_cache); 300 std::vector<tBTA_GATTC_SERVICE>().swap(p_tcb->pending_discovery); 301 *p_tcb = tBTA_GATTC_SERV(); 302 303 p_tcb->in_use = true; 304 p_tcb->server_bda = bda; 305 } 306 return p_tcb; 307 } 308 /******************************************************************************* 309 * 310 * Function bta_gattc_enqueue 311 * 312 * Description enqueue a client request in clcb. 313 * 314 * Returns success or failure. 315 * 316 ******************************************************************************/ 317 bool bta_gattc_enqueue(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) { 318 if (p_clcb->p_q_cmd == NULL) { 319 p_clcb->p_q_cmd = p_data; 320 return true; 321 } 322 323 LOG(ERROR) << __func__ << ": already has a pending command"; 324 /* skip the callback now. ----- need to send callback ? */ 325 return false; 326 } 327 328 /******************************************************************************* 329 * 330 * Function bta_gattc_check_notif_registry 331 * 332 * Description check if the service notificaition has been registered. 333 * 334 * Returns 335 * 336 ******************************************************************************/ 337 bool bta_gattc_check_notif_registry(tBTA_GATTC_RCB* p_clreg, 338 tBTA_GATTC_SERV* p_srcb, 339 tBTA_GATTC_NOTIFY* p_notify) { 340 uint8_t i; 341 342 for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i++) { 343 if (p_clreg->notif_reg[i].in_use && 344 p_clreg->notif_reg[i].remote_bda == p_srcb->server_bda && 345 p_clreg->notif_reg[i].handle == p_notify->handle) { 346 VLOG(1) << "Notification registered!"; 347 return true; 348 } 349 } 350 return false; 351 } 352 /******************************************************************************* 353 * 354 * Function bta_gattc_clear_notif_registration 355 * 356 * Description Clear up the notification registration information by 357 * RawAddress. 358 * Where handle is between start_handle and end_handle, and 359 * start_handle and end_handle are boundaries of service 360 * containing characteristic. 361 * 362 * Returns None. 363 * 364 ******************************************************************************/ 365 void bta_gattc_clear_notif_registration(tBTA_GATTC_SERV* p_srcb, 366 uint16_t conn_id, uint16_t start_handle, 367 uint16_t end_handle) { 368 RawAddress remote_bda; 369 tGATT_IF gatt_if; 370 tBTA_GATTC_RCB* p_clrcb; 371 uint8_t i; 372 tGATT_TRANSPORT transport; 373 uint16_t handle; 374 375 if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport)) { 376 p_clrcb = bta_gattc_cl_get_regcb(gatt_if); 377 if (p_clrcb != NULL) { 378 for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i++) { 379 if (p_clrcb->notif_reg[i].in_use && 380 p_clrcb->notif_reg[i].remote_bda == remote_bda) { 381 /* It's enough to get service or characteristic handle, as 382 * clear boundaries are always around service. 383 */ 384 handle = p_clrcb->notif_reg[i].handle; 385 if (handle >= start_handle && handle <= end_handle) 386 memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG)); 387 } 388 } 389 } 390 } else { 391 LOG(ERROR) << "can not clear indication/notif registration for unknown app"; 392 } 393 return; 394 } 395 396 /******************************************************************************* 397 * 398 * Function bta_gattc_mark_bg_conn 399 * 400 * Description mark background connection status when a bg connection is 401 * initiated or terminated. 402 * 403 * Returns true if success; false otherwise. 404 * 405 ******************************************************************************/ 406 bool bta_gattc_mark_bg_conn(tGATT_IF client_if, 407 const RawAddress& remote_bda_ptr, bool add) { 408 tBTA_GATTC_BG_TCK* p_bg_tck = &bta_gattc_cb.bg_track[0]; 409 uint8_t i = 0; 410 tBTA_GATTC_CIF_MASK* p_cif_mask; 411 412 for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i++, p_bg_tck++) { 413 if (p_bg_tck->in_use && ((p_bg_tck->remote_bda == remote_bda_ptr) || 414 (p_bg_tck->remote_bda.IsEmpty()))) { 415 p_cif_mask = &p_bg_tck->cif_mask; 416 417 if (add) /* mask on the cif bit */ 418 *p_cif_mask |= (1 << (client_if - 1)); 419 else { 420 if (client_if != 0) 421 *p_cif_mask &= (~(1 << (client_if - 1))); 422 else 423 *p_cif_mask = 0; 424 } 425 /* no BG connection for this device, make it available */ 426 if (p_bg_tck->cif_mask == 0) { 427 memset(p_bg_tck, 0, sizeof(tBTA_GATTC_BG_TCK)); 428 } 429 return true; 430 } 431 } 432 if (!add) { 433 LOG(ERROR) << __func__ 434 << " unable to find the bg connection mask for bd_addr=" 435 << remote_bda_ptr; 436 return false; 437 } else /* adding a new device mask */ 438 { 439 for (i = 0, p_bg_tck = &bta_gattc_cb.bg_track[0]; 440 i < BTA_GATTC_KNOWN_SR_MAX; i++, p_bg_tck++) { 441 if (!p_bg_tck->in_use) { 442 p_bg_tck->in_use = true; 443 p_bg_tck->remote_bda = remote_bda_ptr; 444 445 p_cif_mask = &p_bg_tck->cif_mask; 446 447 *p_cif_mask = (1 << (client_if - 1)); 448 return true; 449 } 450 } 451 LOG(ERROR) << "no available space to mark the bg connection status"; 452 return false; 453 } 454 } 455 /******************************************************************************* 456 * 457 * Function bta_gattc_check_bg_conn 458 * 459 * Description check if this is a background connection background 460 * connection. 461 * 462 * Returns true if success; false otherwise. 463 * 464 ******************************************************************************/ 465 bool bta_gattc_check_bg_conn(tGATT_IF client_if, const RawAddress& remote_bda, 466 uint8_t role) { 467 tBTA_GATTC_BG_TCK* p_bg_tck = &bta_gattc_cb.bg_track[0]; 468 uint8_t i = 0; 469 bool is_bg_conn = false; 470 471 for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX && !is_bg_conn; i++, p_bg_tck++) { 472 if (p_bg_tck->in_use && (p_bg_tck->remote_bda == remote_bda || 473 p_bg_tck->remote_bda.IsEmpty())) { 474 if (((p_bg_tck->cif_mask & (1 << (client_if - 1))) != 0) && 475 role == HCI_ROLE_MASTER) 476 is_bg_conn = true; 477 } 478 } 479 return is_bg_conn; 480 } 481 /******************************************************************************* 482 * 483 * Function bta_gattc_send_open_cback 484 * 485 * Description send open callback 486 * 487 * Returns 488 * 489 ******************************************************************************/ 490 void bta_gattc_send_open_cback(tBTA_GATTC_RCB* p_clreg, tGATT_STATUS status, 491 const RawAddress& remote_bda, uint16_t conn_id, 492 tBTA_TRANSPORT transport, uint16_t mtu) { 493 tBTA_GATTC cb_data; 494 495 if (p_clreg->p_cback) { 496 memset(&cb_data, 0, sizeof(tBTA_GATTC)); 497 498 cb_data.open.status = status; 499 cb_data.open.client_if = p_clreg->client_if; 500 cb_data.open.conn_id = conn_id; 501 cb_data.open.mtu = mtu; 502 cb_data.open.transport = transport; 503 cb_data.open.remote_bda = remote_bda; 504 505 (*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data); 506 } 507 } 508 /******************************************************************************* 509 * 510 * Function bta_gattc_conn_alloc 511 * 512 * Description allocate connection tracking spot 513 * 514 * Returns pointer to the clcb 515 * 516 ******************************************************************************/ 517 tBTA_GATTC_CONN* bta_gattc_conn_alloc(const RawAddress& remote_bda) { 518 uint8_t i_conn = 0; 519 tBTA_GATTC_CONN* p_conn = &bta_gattc_cb.conn_track[0]; 520 521 for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn++) { 522 if (!p_conn->in_use) { 523 #if (BTA_GATT_DEBUG == TRUE) 524 VLOG(1) << __func__ << ": found conn_track:" << +i_conn << " available"; 525 #endif 526 p_conn->in_use = true; 527 p_conn->remote_bda = remote_bda; 528 return p_conn; 529 } 530 } 531 return NULL; 532 } 533 534 /******************************************************************************* 535 * 536 * Function bta_gattc_conn_find 537 * 538 * Description allocate connection tracking spot 539 * 540 * Returns pointer to the clcb 541 * 542 ******************************************************************************/ 543 tBTA_GATTC_CONN* bta_gattc_conn_find(const RawAddress& remote_bda) { 544 uint8_t i_conn = 0; 545 tBTA_GATTC_CONN* p_conn = &bta_gattc_cb.conn_track[0]; 546 547 for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn++) { 548 if (p_conn->in_use && remote_bda == p_conn->remote_bda) { 549 #if (BTA_GATT_DEBUG == TRUE) 550 VLOG(1) << __func__ << ": found conn_track:" << +i_conn << " matched"; 551 #endif 552 return p_conn; 553 } 554 } 555 return NULL; 556 } 557 558 /******************************************************************************* 559 * 560 * Function bta_gattc_conn_find_alloc 561 * 562 * Description find or allocate connection tracking spot 563 * 564 * Returns pointer to the clcb 565 * 566 ******************************************************************************/ 567 tBTA_GATTC_CONN* bta_gattc_conn_find_alloc(const RawAddress& remote_bda) { 568 tBTA_GATTC_CONN* p_conn = bta_gattc_conn_find(remote_bda); 569 570 if (p_conn == NULL) { 571 p_conn = bta_gattc_conn_alloc(remote_bda); 572 } 573 return p_conn; 574 } 575 576 /******************************************************************************* 577 * 578 * Function bta_gattc_conn_dealloc 579 * 580 * Description de-allocate connection tracking spot 581 * 582 * Returns pointer to the clcb 583 * 584 ******************************************************************************/ 585 bool bta_gattc_conn_dealloc(const RawAddress& remote_bda) { 586 tBTA_GATTC_CONN* p_conn = bta_gattc_conn_find(remote_bda); 587 588 if (p_conn != NULL) { 589 p_conn->in_use = false; 590 p_conn->remote_bda = RawAddress::kEmpty; 591 return true; 592 } 593 return false; 594 } 595 596 /******************************************************************************* 597 * 598 * Function bta_gattc_find_int_conn_clcb 599 * 600 * Description try to locate a clcb when an internal connecion event 601 * arrives. 602 * 603 * Returns pointer to the clcb 604 * 605 ******************************************************************************/ 606 tBTA_GATTC_CLCB* bta_gattc_find_int_conn_clcb(tBTA_GATTC_DATA* p_msg) { 607 tBTA_GATTC_CLCB* p_clcb = NULL; 608 609 if (p_msg->int_conn.role == HCI_ROLE_SLAVE) 610 bta_gattc_conn_find_alloc(p_msg->int_conn.remote_bda); 611 612 /* try to locate a logic channel */ 613 p_clcb = bta_gattc_find_clcb_by_cif(p_msg->int_conn.client_if, 614 p_msg->int_conn.remote_bda, 615 p_msg->int_conn.transport); 616 if (p_clcb == NULL) { 617 /* for a background connection or listening connection */ 618 if (/*p_msg->int_conn.role == HCI_ROLE_SLAVE || */ 619 bta_gattc_check_bg_conn(p_msg->int_conn.client_if, 620 p_msg->int_conn.remote_bda, 621 p_msg->int_conn.role)) { 622 /* allocate a new channel */ 623 p_clcb = bta_gattc_clcb_alloc(p_msg->int_conn.client_if, 624 p_msg->int_conn.remote_bda, 625 p_msg->int_conn.transport); 626 } 627 } 628 return p_clcb; 629 } 630 631 /******************************************************************************* 632 * 633 * Function bta_gattc_find_int_disconn_clcb 634 * 635 * Description try to locate a clcb when an internal disconnect callback 636 * arrives. 637 * 638 * Returns pointer to the clcb 639 * 640 ******************************************************************************/ 641 tBTA_GATTC_CLCB* bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA* p_msg) { 642 tBTA_GATTC_CLCB* p_clcb = NULL; 643 644 bta_gattc_conn_dealloc(p_msg->int_conn.remote_bda); 645 p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->int_conn.hdr.layer_specific); 646 if (p_clcb == NULL) { 647 /* connection attempt failed, send connection callback event */ 648 p_clcb = bta_gattc_find_clcb_by_cif(p_msg->int_conn.client_if, 649 p_msg->int_conn.remote_bda, 650 p_msg->int_conn.transport); 651 } 652 if (p_clcb == NULL) { 653 VLOG(1) << " disconnection ID:" << +p_msg->int_conn.hdr.layer_specific 654 << " not used by BTA"; 655 } 656 return p_clcb; 657 } 658