1 /****************************************************************************** 2 * 3 * Copyright (C) 2008-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 main ATT functions 22 * 23 ******************************************************************************/ 24 25 #include "bt_target.h" 26 27 #if BLE_INCLUDED == TRUE 28 29 #include "bt_common.h" 30 #include "gatt_int.h" 31 #include "l2c_api.h" 32 #include "btm_int.h" 33 #include "btm_ble_int.h" 34 #include "bt_utils.h" 35 36 /* Configuration flags. */ 37 #define GATT_L2C_CFG_IND_DONE (1<<0) 38 #define GATT_L2C_CFG_CFM_DONE (1<<1) 39 40 /* minimum GATT MTU size over BR/EDR link 41 */ 42 #define GATT_MIN_BR_MTU_SIZE 48 43 44 /********************************************************************************/ 45 /* L O C A L F U N C T I O N P R O T O T Y P E S */ 46 /********************************************************************************/ 47 static void gatt_le_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected, 48 UINT16 reason, tBT_TRANSPORT transport); 49 static void gatt_le_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf); 50 static void gatt_le_cong_cback(BD_ADDR remote_bda, BOOLEAN congest); 51 52 static void gatt_l2cif_connect_ind_cback (BD_ADDR bd_addr, UINT16 l2cap_cid, 53 UINT16 psm, UINT8 l2cap_id); 54 static void gatt_l2cif_connect_cfm_cback (UINT16 l2cap_cid, UINT16 result); 55 static void gatt_l2cif_config_ind_cback (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg); 56 static void gatt_l2cif_config_cfm_cback (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg); 57 static void gatt_l2cif_disconnect_ind_cback (UINT16 l2cap_cid, BOOLEAN ack_needed); 58 static void gatt_l2cif_disconnect_cfm_cback (UINT16 l2cap_cid, UINT16 result); 59 static void gatt_l2cif_data_ind_cback (UINT16 l2cap_cid, BT_HDR *p_msg); 60 static void gatt_send_conn_cback (tGATT_TCB *p_tcb); 61 static void gatt_l2cif_congest_cback (UINT16 cid, BOOLEAN congested); 62 63 static const tL2CAP_APPL_INFO dyn_info = 64 { 65 gatt_l2cif_connect_ind_cback, 66 gatt_l2cif_connect_cfm_cback, 67 NULL, 68 gatt_l2cif_config_ind_cback, 69 gatt_l2cif_config_cfm_cback, 70 gatt_l2cif_disconnect_ind_cback, 71 gatt_l2cif_disconnect_cfm_cback, 72 NULL, 73 gatt_l2cif_data_ind_cback, 74 gatt_l2cif_congest_cback, 75 NULL 76 } ; 77 78 #if GATT_DYNAMIC_MEMORY == FALSE 79 tGATT_CB gatt_cb; 80 #endif 81 82 /******************************************************************************* 83 ** 84 ** Function gatt_init 85 ** 86 ** Description This function is enable the GATT profile on the device. 87 ** It clears out the control blocks, and registers with L2CAP. 88 ** 89 ** Returns void 90 ** 91 *******************************************************************************/ 92 void gatt_init (void) 93 { 94 tL2CAP_FIXED_CHNL_REG fixed_reg; 95 96 GATT_TRACE_DEBUG("gatt_init()"); 97 98 memset (&gatt_cb, 0, sizeof(tGATT_CB)); 99 memset (&fixed_reg, 0, sizeof(tL2CAP_FIXED_CHNL_REG)); 100 101 #if defined(GATT_INITIAL_TRACE_LEVEL) 102 gatt_cb.trace_level = GATT_INITIAL_TRACE_LEVEL; 103 #else 104 gatt_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */ 105 #endif 106 gatt_cb.def_mtu_size = GATT_DEF_BLE_MTU_SIZE; 107 gatt_cb.sign_op_queue = fixed_queue_new(SIZE_MAX); 108 gatt_cb.srv_chg_clt_q = fixed_queue_new(SIZE_MAX); 109 gatt_cb.pending_new_srv_start_q = fixed_queue_new(SIZE_MAX); 110 /* First, register fixed L2CAP channel for ATT over BLE */ 111 fixed_reg.fixed_chnl_opts.mode = L2CAP_FCR_BASIC_MODE; 112 fixed_reg.fixed_chnl_opts.max_transmit = 0xFF; 113 fixed_reg.fixed_chnl_opts.rtrans_tout = 2000; 114 fixed_reg.fixed_chnl_opts.mon_tout = 12000; 115 fixed_reg.fixed_chnl_opts.mps = 670; 116 fixed_reg.fixed_chnl_opts.tx_win_sz = 1; 117 118 fixed_reg.pL2CA_FixedConn_Cb = gatt_le_connect_cback; 119 fixed_reg.pL2CA_FixedData_Cb = gatt_le_data_ind; 120 fixed_reg.pL2CA_FixedCong_Cb = gatt_le_cong_cback; /* congestion callback */ 121 fixed_reg.default_idle_tout = 0xffff; /* 0xffff default idle timeout */ 122 123 L2CA_RegisterFixedChannel (L2CAP_ATT_CID, &fixed_reg); 124 125 /* Now, register with L2CAP for ATT PSM over BR/EDR */ 126 if (!L2CA_Register (BT_PSM_ATT, (tL2CAP_APPL_INFO *) &dyn_info)) 127 { 128 GATT_TRACE_ERROR ("ATT Dynamic Registration failed"); 129 } 130 131 BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT, 0, 0); 132 BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT, 0, 0); 133 134 gatt_cb.hdl_cfg.gatt_start_hdl = GATT_GATT_START_HANDLE; 135 gatt_cb.hdl_cfg.gap_start_hdl = GATT_GAP_START_HANDLE; 136 gatt_cb.hdl_cfg.app_start_hdl = GATT_APP_START_HANDLE; 137 gatt_profile_db_init(); 138 139 } 140 141 142 /******************************************************************************* 143 ** 144 ** Function gatt_free 145 ** 146 ** Description This function frees resources used by the GATT profile. 147 ** 148 ** Returns void 149 ** 150 *******************************************************************************/ 151 void gatt_free(void) 152 { 153 int i; 154 GATT_TRACE_DEBUG("gatt_free()"); 155 156 fixed_queue_free(gatt_cb.sign_op_queue, NULL); 157 gatt_cb.sign_op_queue = NULL; 158 fixed_queue_free(gatt_cb.srv_chg_clt_q, NULL); 159 gatt_cb.srv_chg_clt_q = NULL; 160 fixed_queue_free(gatt_cb.pending_new_srv_start_q, NULL); 161 gatt_cb.pending_new_srv_start_q = NULL; 162 for (i = 0; i < GATT_MAX_PHY_CHANNEL; i++) 163 { 164 fixed_queue_free(gatt_cb.tcb[i].pending_enc_clcb, NULL); 165 gatt_cb.tcb[i].pending_enc_clcb = NULL; 166 167 fixed_queue_free(gatt_cb.tcb[i].pending_ind_q, NULL); 168 gatt_cb.tcb[i].pending_ind_q = NULL; 169 170 alarm_free(gatt_cb.tcb[i].conf_timer); 171 gatt_cb.tcb[i].conf_timer = NULL; 172 173 alarm_free(gatt_cb.tcb[i].ind_ack_timer); 174 gatt_cb.tcb[i].ind_ack_timer = NULL; 175 176 fixed_queue_free(gatt_cb.tcb[i].sr_cmd.multi_rsp_q, NULL); 177 gatt_cb.tcb[i].sr_cmd.multi_rsp_q = NULL; 178 } 179 for (i = 0; i < GATT_MAX_SR_PROFILES; i++) 180 { 181 gatt_free_hdl_buffer(&gatt_cb.hdl_list[i]); 182 } 183 } 184 185 /******************************************************************************* 186 ** 187 ** Function gatt_connect 188 ** 189 ** Description This function is called to initiate a connection to a peer device. 190 ** 191 ** Parameter rem_bda: remote device address to connect to. 192 ** 193 ** Returns TRUE if connection is started, otherwise return FALSE. 194 ** 195 *******************************************************************************/ 196 BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb, tBT_TRANSPORT transport) 197 { 198 BOOLEAN gatt_ret = FALSE; 199 200 if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN) 201 gatt_set_ch_state(p_tcb, GATT_CH_CONN); 202 203 if (transport == BT_TRANSPORT_LE) 204 { 205 p_tcb->att_lcid = L2CAP_ATT_CID; 206 gatt_ret = L2CA_ConnectFixedChnl (L2CAP_ATT_CID, rem_bda); 207 } 208 else 209 { 210 if ((p_tcb->att_lcid = L2CA_ConnectReq(BT_PSM_ATT, rem_bda)) != 0) 211 gatt_ret = TRUE; 212 } 213 214 return gatt_ret; 215 } 216 217 /******************************************************************************* 218 ** 219 ** Function gatt_disconnect 220 ** 221 ** Description This function is called to disconnect to an ATT device. 222 ** 223 ** Parameter p_tcb: pointer to the TCB to disconnect. 224 ** 225 ** Returns TRUE: if connection found and to be disconnected; otherwise 226 ** return FALSE. 227 ** 228 *******************************************************************************/ 229 BOOLEAN gatt_disconnect (tGATT_TCB *p_tcb) 230 { 231 BOOLEAN ret = FALSE; 232 tGATT_CH_STATE ch_state; 233 234 GATT_TRACE_EVENT ("%s", __func__); 235 236 if (p_tcb != NULL) 237 { 238 ret = TRUE; 239 if ( (ch_state = gatt_get_ch_state(p_tcb)) != GATT_CH_CLOSING ) 240 { 241 if (p_tcb->att_lcid == L2CAP_ATT_CID) 242 { 243 if (ch_state == GATT_CH_OPEN) 244 { 245 /* only LCB exist between remote device and local */ 246 ret = L2CA_RemoveFixedChnl (L2CAP_ATT_CID, p_tcb->peer_bda); 247 } 248 else 249 { 250 gatt_set_ch_state(p_tcb, GATT_CH_CLOSING); 251 ret = L2CA_CancelBleConnectReq (p_tcb->peer_bda); 252 } 253 } 254 else 255 { 256 if ((ch_state == GATT_CH_OPEN) || (ch_state == GATT_CH_CFG)) 257 ret = L2CA_DisconnectReq(p_tcb->att_lcid); 258 else 259 GATT_TRACE_DEBUG ("%s gatt_disconnect channel not opened", __func__); 260 } 261 } 262 else 263 { 264 GATT_TRACE_DEBUG ("%s already in closing state", __func__); 265 } 266 } 267 268 return ret; 269 } 270 271 /******************************************************************************* 272 ** 273 ** Function gatt_update_app_hold_link_status 274 ** 275 ** Description Update the application use link status 276 ** 277 ** Returns void. 278 ** 279 *******************************************************************************/ 280 void gatt_update_app_hold_link_status (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add) 281 { 282 UINT8 i; 283 BOOLEAN found=FALSE; 284 285 if (p_tcb == NULL) 286 { 287 GATT_TRACE_ERROR("gatt_update_app_hold_link_status p_tcb=NULL"); 288 return; 289 } 290 291 292 for (i=0; i<GATT_MAX_APPS; i++) 293 { 294 if (p_tcb->app_hold_link[i] == gatt_if) 295 { 296 found = TRUE; 297 if (!is_add) 298 { 299 p_tcb->app_hold_link[i] = 0; 300 break; 301 } 302 } 303 } 304 305 if (!found && is_add) 306 { 307 for (i=0; i<GATT_MAX_APPS; i++) 308 { 309 if (p_tcb->app_hold_link[i] == 0) 310 { 311 p_tcb->app_hold_link[i] = gatt_if; 312 found = TRUE; 313 break; 314 } 315 } 316 } 317 318 GATT_TRACE_DEBUG("gatt_update_app_hold_link_status found=%d[1-found] idx=%d gatt_if=%d is_add=%d", found, i, gatt_if, is_add); 319 320 } 321 322 /******************************************************************************* 323 ** 324 ** Function gatt_update_app_use_link_flag 325 ** 326 ** Description Update the application use link flag and optional to check the acl link 327 ** if the link is up then set the idle time out accordingly 328 ** 329 ** Returns void. 330 ** 331 *******************************************************************************/ 332 void gatt_update_app_use_link_flag (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link) 333 { 334 GATT_TRACE_DEBUG("gatt_update_app_use_link_flag is_add=%d chk_link=%d", 335 is_add, check_acl_link); 336 337 gatt_update_app_hold_link_status(gatt_if, p_tcb, is_add); 338 339 if (check_acl_link && 340 p_tcb && 341 p_tcb->att_lcid == L2CAP_ATT_CID && /* only update link idle timer for fixed channel */ 342 (BTM_GetHCIConnHandle(p_tcb->peer_bda, p_tcb->transport) != GATT_INVALID_ACL_HANDLE)) 343 { 344 if (is_add) 345 { 346 GATT_TRACE_DEBUG("GATT disables link idle timer"); 347 /* acl link is connected disable the idle timeout */ 348 GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport); 349 } 350 else 351 { 352 if (!gatt_num_apps_hold_link(p_tcb)) 353 { 354 /* acl link is connected but no application needs to use the link 355 so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */ 356 GATT_TRACE_DEBUG("GATT starts link idle timer =%d sec", GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP); 357 GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP, p_tcb->transport); 358 } 359 360 } 361 } 362 } 363 364 /******************************************************************************* 365 ** 366 ** Function gatt_act_connect 367 ** 368 ** Description GATT connection initiation. 369 ** 370 ** Returns void. 371 ** 372 *******************************************************************************/ 373 BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBT_TRANSPORT transport) 374 { 375 BOOLEAN ret = FALSE; 376 tGATT_TCB *p_tcb; 377 UINT8 st; 378 379 if ((p_tcb = gatt_find_tcb_by_addr(bd_addr, transport)) != NULL) 380 { 381 ret = TRUE; 382 st = gatt_get_ch_state(p_tcb); 383 384 /* before link down, another app try to open a GATT connection */ 385 if(st == GATT_CH_OPEN && gatt_num_apps_hold_link(p_tcb) == 0 && 386 transport == BT_TRANSPORT_LE ) 387 { 388 if (!gatt_connect(bd_addr, p_tcb, transport)) 389 ret = FALSE; 390 } 391 else if(st == GATT_CH_CLOSING) 392 { 393 /* need to complete the closing first */ 394 ret = FALSE; 395 } 396 } 397 else 398 { 399 if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, transport)) != NULL) 400 { 401 if (!gatt_connect(bd_addr, p_tcb, transport)) 402 { 403 GATT_TRACE_ERROR("gatt_connect failed"); 404 fixed_queue_free(p_tcb->pending_enc_clcb, NULL); 405 fixed_queue_free(p_tcb->pending_ind_q, NULL); 406 fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL); 407 memset(p_tcb, 0, sizeof(tGATT_TCB)); 408 } 409 else 410 ret = TRUE; 411 } 412 else 413 { 414 ret = 0; 415 GATT_TRACE_ERROR("Max TCB for gatt_if [%d] reached.", p_reg->gatt_if); 416 } 417 } 418 419 if (ret) 420 { 421 gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, FALSE); 422 } 423 424 return ret; 425 } 426 427 /******************************************************************************* 428 ** 429 ** Function gatt_le_connect_cback 430 ** 431 ** Description This callback function is called by L2CAP to indicate that 432 ** the ATT fixed channel for LE is 433 ** connected (conn = TRUE)/disconnected (conn = FALSE). 434 ** 435 *******************************************************************************/ 436 static void gatt_le_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected, 437 UINT16 reason, tBT_TRANSPORT transport) 438 { 439 440 tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr, transport); 441 BOOLEAN check_srv_chg = FALSE; 442 tGATTS_SRV_CHG *p_srv_chg_clt=NULL; 443 444 /* ignore all fixed channel connect/disconnect on BR/EDR link for GATT */ 445 if (transport == BT_TRANSPORT_BR_EDR) 446 return; 447 448 GATT_TRACE_DEBUG ("GATT ATT protocol channel with BDA: %08x%04x is %s", 449 (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3], 450 (bd_addr[4]<<8)+bd_addr[5], (connected) ? "connected" : "disconnected"); 451 452 if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(bd_addr)) != NULL) 453 { 454 check_srv_chg = TRUE; 455 } 456 else 457 { 458 if (btm_sec_is_a_bonded_dev(bd_addr)) 459 gatt_add_a_bonded_dev_for_srv_chg(bd_addr); 460 } 461 462 if (connected) 463 { 464 /* do we have a channel initiating a connection? */ 465 if (p_tcb) 466 { 467 /* we are initiating connection */ 468 if ( gatt_get_ch_state(p_tcb) == GATT_CH_CONN) 469 { 470 /* send callback */ 471 gatt_set_ch_state(p_tcb, GATT_CH_OPEN); 472 p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE; 473 474 gatt_send_conn_cback(p_tcb); 475 } 476 if (check_srv_chg) 477 gatt_chk_srv_chg (p_srv_chg_clt); 478 } 479 /* this is incoming connection or background connection callback */ 480 481 else 482 { 483 if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, BT_TRANSPORT_LE)) != NULL) 484 { 485 p_tcb->att_lcid = L2CAP_ATT_CID; 486 487 gatt_set_ch_state(p_tcb, GATT_CH_OPEN); 488 489 p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE; 490 491 gatt_send_conn_cback (p_tcb); 492 if (check_srv_chg) 493 { 494 gatt_chk_srv_chg (p_srv_chg_clt); 495 } 496 } 497 else 498 { 499 GATT_TRACE_ERROR("CCB max out, no rsources"); 500 } 501 } 502 } 503 else 504 { 505 gatt_cleanup_upon_disc(bd_addr, reason, transport); 506 GATT_TRACE_DEBUG ("ATT disconnected"); 507 } 508 } 509 510 /******************************************************************************* 511 ** 512 ** Function gatt_channel_congestion 513 ** 514 ** Description This function is called to process the congestion callback 515 ** from lcb 516 ** 517 ** Returns void 518 ** 519 *******************************************************************************/ 520 static void gatt_channel_congestion(tGATT_TCB *p_tcb, BOOLEAN congested) 521 { 522 UINT8 i = 0; 523 tGATT_REG *p_reg=NULL; 524 UINT16 conn_id; 525 526 /* if uncongested, check to see if there is any more pending data */ 527 if (p_tcb != NULL && congested == FALSE) 528 { 529 gatt_cl_send_next_cmd_inq(p_tcb); 530 } 531 /* notifying all applications for the connection up event */ 532 for (i = 0, p_reg = gatt_cb.cl_rcb ; i < GATT_MAX_APPS; i++, p_reg++) 533 { 534 if (p_reg->in_use) 535 { 536 if (p_reg->app_cb.p_congestion_cb) 537 { 538 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if); 539 (*p_reg->app_cb.p_congestion_cb)(conn_id, congested); 540 } 541 } 542 } 543 } 544 545 /******************************************************************************* 546 ** 547 ** Function gatt_le_cong_cback 548 ** 549 ** Description This function is called when GATT fixed channel is congested 550 ** or uncongested. 551 ** 552 ** Returns void 553 ** 554 *******************************************************************************/ 555 static void gatt_le_cong_cback(BD_ADDR remote_bda, BOOLEAN congested) 556 { 557 tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(remote_bda, BT_TRANSPORT_LE); 558 559 /* if uncongested, check to see if there is any more pending data */ 560 if (p_tcb != NULL) 561 { 562 gatt_channel_congestion(p_tcb, congested); 563 } 564 } 565 566 /******************************************************************************* 567 ** 568 ** Function gatt_le_data_ind 569 ** 570 ** Description This function is called when data is received from L2CAP. 571 ** if we are the originator of the connection, we are the ATT 572 ** client, and the received message is queued up for the client. 573 ** 574 ** If we are the destination of the connection, we are the ATT 575 ** server, so the message is passed to the server processing 576 ** function. 577 ** 578 ** Returns void 579 ** 580 *******************************************************************************/ 581 static void gatt_le_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf) 582 { 583 tGATT_TCB *p_tcb; 584 585 /* Find CCB based on bd addr */ 586 if ((p_tcb = gatt_find_tcb_by_addr (bd_addr, BT_TRANSPORT_LE)) != NULL && 587 gatt_get_ch_state(p_tcb) >= GATT_CH_OPEN) 588 { 589 gatt_data_process(p_tcb, p_buf); 590 } 591 else 592 { 593 osi_free(p_buf); 594 595 if (p_tcb != NULL) 596 { 597 GATT_TRACE_WARNING ("ATT - Ignored L2CAP data while in state: %d", 598 gatt_get_ch_state(p_tcb)); 599 } 600 } 601 } 602 603 /******************************************************************************* 604 ** 605 ** Function gatt_l2cif_connect_ind 606 ** 607 ** Description This function handles an inbound connection indication 608 ** from L2CAP. This is the case where we are acting as a 609 ** server. 610 ** 611 ** Returns void 612 ** 613 *******************************************************************************/ 614 static void gatt_l2cif_connect_ind_cback (BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id) 615 { 616 /* do we already have a control channel for this peer? */ 617 UINT8 result = L2CAP_CONN_OK; 618 tL2CAP_CFG_INFO cfg; 619 tGATT_TCB *p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_BR_EDR); 620 UNUSED(psm); 621 622 GATT_TRACE_ERROR("Connection indication cid = %d", lcid); 623 /* new connection ? */ 624 if (p_tcb == NULL) 625 { 626 /* allocate tcb */ 627 if ((p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, BT_TRANSPORT_BR_EDR)) == NULL) 628 { 629 /* no tcb available, reject L2CAP connection */ 630 result = L2CAP_CONN_NO_RESOURCES; 631 } 632 else 633 p_tcb->att_lcid = lcid; 634 635 } 636 else /* existing connection , reject it */ 637 { 638 result = L2CAP_CONN_NO_RESOURCES; 639 } 640 641 /* Send L2CAP connect rsp */ 642 L2CA_ConnectRsp(bd_addr, id, lcid, result, 0); 643 644 /* if result ok, proceed with connection */ 645 if (result == L2CAP_CONN_OK) 646 { 647 /* transition to configuration state */ 648 gatt_set_ch_state(p_tcb, GATT_CH_CFG); 649 650 /* Send L2CAP config req */ 651 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); 652 cfg.mtu_present = TRUE; 653 cfg.mtu = GATT_MAX_MTU_SIZE; 654 655 L2CA_ConfigReq(lcid, &cfg); 656 } 657 } 658 659 /******************************************************************************* 660 ** 661 ** Function gatt_l2c_connect_cfm_cback 662 ** 663 ** Description This is the L2CAP connect confirm callback function. 664 ** 665 ** 666 ** Returns void 667 ** 668 *******************************************************************************/ 669 static void gatt_l2cif_connect_cfm_cback(UINT16 lcid, UINT16 result) 670 { 671 tGATT_TCB *p_tcb; 672 tL2CAP_CFG_INFO cfg; 673 674 /* look up clcb for this channel */ 675 if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL) 676 { 677 GATT_TRACE_DEBUG("gatt_l2c_connect_cfm_cback result: %d ch_state: %d, lcid:0x%x", result, gatt_get_ch_state(p_tcb), p_tcb->att_lcid); 678 679 /* if in correct state */ 680 if (gatt_get_ch_state(p_tcb) == GATT_CH_CONN) 681 { 682 /* if result successful */ 683 if (result == L2CAP_CONN_OK) 684 { 685 /* set channel state */ 686 gatt_set_ch_state(p_tcb, GATT_CH_CFG); 687 688 /* Send L2CAP config req */ 689 memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); 690 cfg.mtu_present = TRUE; 691 cfg.mtu = GATT_MAX_MTU_SIZE; 692 L2CA_ConfigReq(lcid, &cfg); 693 } 694 /* else initiating connection failure */ 695 else 696 { 697 gatt_cleanup_upon_disc(p_tcb->peer_bda, result, GATT_TRANSPORT_BR_EDR); 698 } 699 } 700 else /* wrong state, disconnect it */ 701 { 702 if (result == L2CAP_CONN_OK) 703 { 704 /* just in case the peer also accepts our connection - Send L2CAP disconnect req */ 705 L2CA_DisconnectReq(lcid); 706 } 707 } 708 } 709 } 710 711 /******************************************************************************* 712 ** 713 ** Function gatt_l2cif_config_cfm_cback 714 ** 715 ** Description This is the L2CAP config confirm callback function. 716 ** 717 ** 718 ** Returns void 719 ** 720 *******************************************************************************/ 721 void gatt_l2cif_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) 722 { 723 tGATT_TCB *p_tcb; 724 tGATTS_SRV_CHG *p_srv_chg_clt=NULL; 725 726 /* look up clcb for this channel */ 727 if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL) 728 { 729 /* if in correct state */ 730 if ( gatt_get_ch_state(p_tcb) == GATT_CH_CFG) 731 { 732 /* if result successful */ 733 if (p_cfg->result == L2CAP_CFG_OK) 734 { 735 /* update flags */ 736 p_tcb->ch_flags |= GATT_L2C_CFG_CFM_DONE; 737 738 /* if configuration complete */ 739 if (p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE) 740 { 741 gatt_set_ch_state(p_tcb, GATT_CH_OPEN); 742 743 if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL) 744 { 745 gatt_chk_srv_chg(p_srv_chg_clt); 746 } 747 else 748 { 749 if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda)) 750 gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda); 751 } 752 753 /* send callback */ 754 gatt_send_conn_cback(p_tcb); 755 } 756 } 757 /* else failure */ 758 else 759 { 760 /* Send L2CAP disconnect req */ 761 L2CA_DisconnectReq(lcid); 762 } 763 } 764 } 765 } 766 767 /******************************************************************************* 768 ** 769 ** Function gatt_l2cif_config_ind_cback 770 ** 771 ** Description This is the L2CAP config indication callback function. 772 ** 773 ** 774 ** Returns void 775 ** 776 *******************************************************************************/ 777 void gatt_l2cif_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) 778 { 779 tGATT_TCB *p_tcb; 780 tGATTS_SRV_CHG *p_srv_chg_clt=NULL; 781 /* look up clcb for this channel */ 782 if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL) 783 { 784 /* GATT uses the smaller of our MTU and peer's MTU */ 785 if ( p_cfg->mtu_present && 786 (p_cfg->mtu >= GATT_MIN_BR_MTU_SIZE && p_cfg->mtu < L2CAP_DEFAULT_MTU)) 787 p_tcb->payload_size = p_cfg->mtu; 788 else 789 p_tcb->payload_size = L2CAP_DEFAULT_MTU; 790 791 /* send L2CAP configure response */ 792 memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO)); 793 p_cfg->result = L2CAP_CFG_OK; 794 L2CA_ConfigRsp(lcid, p_cfg); 795 796 /* if first config ind */ 797 if ((p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE) == 0) 798 { 799 /* update flags */ 800 p_tcb->ch_flags |= GATT_L2C_CFG_IND_DONE; 801 802 /* if configuration complete */ 803 if (p_tcb->ch_flags & GATT_L2C_CFG_CFM_DONE) 804 { 805 gatt_set_ch_state(p_tcb, GATT_CH_OPEN); 806 if ((p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL) 807 { 808 gatt_chk_srv_chg(p_srv_chg_clt); 809 } 810 else 811 { 812 if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda)) 813 gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda); 814 } 815 816 /* send callback */ 817 gatt_send_conn_cback(p_tcb); 818 } 819 } 820 } 821 } 822 823 /******************************************************************************* 824 ** 825 ** Function gatt_l2cif_disconnect_ind_cback 826 ** 827 ** Description This is the L2CAP disconnect indication callback function. 828 ** 829 ** 830 ** Returns void 831 ** 832 *******************************************************************************/ 833 void gatt_l2cif_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed) 834 { 835 tGATT_TCB *p_tcb; 836 UINT16 reason; 837 838 /* look up clcb for this channel */ 839 if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL) 840 { 841 if (ack_needed) 842 { 843 /* send L2CAP disconnect response */ 844 L2CA_DisconnectRsp(lcid); 845 } 846 if (gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda) == NULL) 847 { 848 if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda)) 849 gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda); 850 } 851 /* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */ 852 if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda, p_tcb->transport)) == 0) 853 reason = GATT_CONN_TERMINATE_PEER_USER; 854 855 /* send disconnect callback */ 856 gatt_cleanup_upon_disc(p_tcb->peer_bda, reason, GATT_TRANSPORT_BR_EDR); 857 } 858 } 859 860 /******************************************************************************* 861 ** 862 ** Function gatt_l2cif_disconnect_cfm_cback 863 ** 864 ** Description This is the L2CAP disconnect confirm callback function. 865 ** 866 ** 867 ** Returns void 868 ** 869 *******************************************************************************/ 870 static void gatt_l2cif_disconnect_cfm_cback(UINT16 lcid, UINT16 result) 871 { 872 tGATT_TCB *p_tcb; 873 UINT16 reason; 874 UNUSED(result); 875 876 /* look up clcb for this channel */ 877 if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL) 878 { 879 /* If the device is not in the service changed client list, add it... */ 880 if (gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda) == NULL) 881 { 882 if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda)) 883 gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda); 884 } 885 886 /* send disconnect callback */ 887 /* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */ 888 if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda, p_tcb->transport)) == 0) 889 reason = GATT_CONN_TERMINATE_LOCAL_HOST; 890 891 gatt_cleanup_upon_disc(p_tcb->peer_bda, reason, GATT_TRANSPORT_BR_EDR); 892 } 893 } 894 895 /******************************************************************************* 896 ** 897 ** Function gatt_l2cif_data_ind_cback 898 ** 899 ** Description This is the L2CAP data indication callback function. 900 ** 901 ** 902 ** Returns void 903 ** 904 *******************************************************************************/ 905 static void gatt_l2cif_data_ind_cback(UINT16 lcid, BT_HDR *p_buf) 906 { 907 tGATT_TCB *p_tcb; 908 909 /* look up clcb for this channel */ 910 if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL && 911 gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) 912 { 913 /* process the data */ 914 gatt_data_process(p_tcb, p_buf); 915 } 916 else /* prevent buffer leak */ 917 osi_free(p_buf); 918 } 919 920 /******************************************************************************* 921 ** 922 ** Function gatt_l2cif_congest_cback 923 ** 924 ** Description L2CAP congestion callback 925 ** 926 ** Returns void 927 ** 928 *******************************************************************************/ 929 static void gatt_l2cif_congest_cback (UINT16 lcid, BOOLEAN congested) 930 { 931 tGATT_TCB *p_tcb = gatt_find_tcb_by_cid(lcid); 932 933 if (p_tcb != NULL) 934 { 935 gatt_channel_congestion(p_tcb, congested); 936 } 937 } 938 939 /******************************************************************************* 940 ** 941 ** Function gatt_send_conn_cback 942 ** 943 ** Description Callback used to notify layer above about a connection. 944 ** 945 ** 946 ** Returns void 947 ** 948 *******************************************************************************/ 949 static void gatt_send_conn_cback(tGATT_TCB *p_tcb) 950 { 951 UINT8 i; 952 tGATT_REG *p_reg; 953 tGATT_BG_CONN_DEV *p_bg_dev=NULL; 954 UINT16 conn_id; 955 956 p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda); 957 958 /* notifying all applications for the connection up event */ 959 for (i = 0, p_reg = gatt_cb.cl_rcb ; i < GATT_MAX_APPS; i++, p_reg++) 960 { 961 if (p_reg->in_use) 962 { 963 if (p_bg_dev && gatt_is_bg_dev_for_app(p_bg_dev, p_reg->gatt_if)) 964 gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, TRUE); 965 966 if (p_reg->app_cb.p_conn_cb) 967 { 968 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if); 969 (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, 970 TRUE, 0, p_tcb->transport); 971 } 972 } 973 } 974 975 976 if (gatt_num_apps_hold_link(p_tcb) && p_tcb->att_lcid == L2CAP_ATT_CID ) 977 { 978 /* disable idle timeout if one or more clients are holding the link disable the idle timer */ 979 GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport); 980 } 981 } 982 983 /******************************************************************************* 984 ** 985 ** Function gatt_le_data_ind 986 ** 987 ** Description This function is called when data is received from L2CAP. 988 ** if we are the originator of the connection, we are the ATT 989 ** client, and the received message is queued up for the client. 990 ** 991 ** If we are the destination of the connection, we are the ATT 992 ** server, so the message is passed to the server processing 993 ** function. 994 ** 995 ** Returns void 996 ** 997 *******************************************************************************/ 998 void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf) 999 { 1000 UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; 1001 UINT8 op_code, pseudo_op_code; 1002 UINT16 msg_len; 1003 1004 1005 if (p_buf->len > 0) 1006 { 1007 msg_len = p_buf->len - 1; 1008 STREAM_TO_UINT8(op_code, p); 1009 1010 /* remove the two MSBs associated with sign write and write cmd */ 1011 pseudo_op_code = op_code & (~GATT_WRITE_CMD_MASK); 1012 1013 if (pseudo_op_code < GATT_OP_CODE_MAX) 1014 { 1015 if (op_code == GATT_SIGN_CMD_WRITE) 1016 { 1017 gatt_verify_signature(p_tcb, p_buf); 1018 } 1019 else 1020 { 1021 /* message from client */ 1022 if ((op_code % 2) == 0) 1023 gatt_server_handle_client_req (p_tcb, op_code, msg_len, p); 1024 else 1025 gatt_client_handle_server_rsp (p_tcb, op_code, msg_len, p); 1026 } 1027 } 1028 else 1029 { 1030 GATT_TRACE_ERROR ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x", op_code); 1031 } 1032 } 1033 else 1034 { 1035 GATT_TRACE_ERROR ("invalid data length, ignore"); 1036 } 1037 1038 osi_free(p_buf); 1039 } 1040 1041 /******************************************************************************* 1042 ** 1043 ** Function gatt_add_a_bonded_dev_for_srv_chg 1044 ** 1045 ** Description Add a bonded dev to the service changed client list 1046 ** 1047 ** Returns void 1048 ** 1049 *******************************************************************************/ 1050 void gatt_add_a_bonded_dev_for_srv_chg (BD_ADDR bda) 1051 { 1052 tGATTS_SRV_CHG_REQ req; 1053 tGATTS_SRV_CHG srv_chg_clt; 1054 1055 memcpy(srv_chg_clt.bda, bda, BD_ADDR_LEN); 1056 srv_chg_clt.srv_changed = FALSE; 1057 if (gatt_add_srv_chg_clt(&srv_chg_clt) != NULL) 1058 { 1059 memcpy(req.srv_chg.bda, bda, BD_ADDR_LEN); 1060 req.srv_chg.srv_changed = FALSE; 1061 if (gatt_cb.cb_info.p_srv_chg_callback) 1062 (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_ADD_CLIENT, &req, NULL); 1063 } 1064 } 1065 1066 /******************************************************************************* 1067 ** 1068 ** Function gatt_send_srv_chg_ind 1069 ** 1070 ** Description This function is called to send a service chnaged indication to 1071 ** the specified bd address 1072 ** 1073 ** Returns void 1074 ** 1075 *******************************************************************************/ 1076 void gatt_send_srv_chg_ind (BD_ADDR peer_bda) 1077 { 1078 UINT8 handle_range[GATT_SIZE_OF_SRV_CHG_HNDL_RANGE]; 1079 UINT8 *p = handle_range; 1080 UINT16 conn_id; 1081 1082 GATT_TRACE_DEBUG("gatt_send_srv_chg_ind"); 1083 1084 if (gatt_cb.handle_of_h_r) 1085 { 1086 if ((conn_id = gatt_profile_find_conn_id_by_bd_addr(peer_bda)) != GATT_INVALID_CONN_ID) 1087 { 1088 UINT16_TO_STREAM (p, 1); 1089 UINT16_TO_STREAM (p, 0xFFFF); 1090 GATTS_HandleValueIndication (conn_id, 1091 gatt_cb.handle_of_h_r, 1092 GATT_SIZE_OF_SRV_CHG_HNDL_RANGE, 1093 handle_range); 1094 } 1095 else 1096 { 1097 GATT_TRACE_ERROR("Unable to find conn_id for %08x%04x ", 1098 (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3], 1099 (peer_bda[4]<<8)+peer_bda[5] ); 1100 } 1101 } 1102 } 1103 1104 /******************************************************************************* 1105 ** 1106 ** Function gatt_chk_srv_chg 1107 ** 1108 ** Description Check sending service chnaged Indication is required or not 1109 ** if required then send the Indication 1110 ** 1111 ** Returns void 1112 ** 1113 *******************************************************************************/ 1114 void gatt_chk_srv_chg(tGATTS_SRV_CHG *p_srv_chg_clt) 1115 { 1116 GATT_TRACE_DEBUG("gatt_chk_srv_chg srv_changed=%d", p_srv_chg_clt->srv_changed ); 1117 1118 if (p_srv_chg_clt->srv_changed) 1119 { 1120 gatt_send_srv_chg_ind(p_srv_chg_clt->bda); 1121 } 1122 } 1123 1124 /******************************************************************************* 1125 ** 1126 ** Function gatt_init_srv_chg 1127 ** 1128 ** Description This function is used to initialize the service changed 1129 ** attribute value 1130 ** 1131 ** Returns void 1132 ** 1133 *******************************************************************************/ 1134 void gatt_init_srv_chg (void) 1135 { 1136 tGATTS_SRV_CHG_REQ req; 1137 tGATTS_SRV_CHG_RSP rsp; 1138 BOOLEAN status; 1139 UINT8 num_clients,i; 1140 tGATTS_SRV_CHG srv_chg_clt; 1141 1142 GATT_TRACE_DEBUG("gatt_init_srv_chg"); 1143 if (gatt_cb.cb_info.p_srv_chg_callback) 1144 { 1145 status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_NUM_CLENTS, NULL, &rsp); 1146 1147 if (status && rsp.num_clients) 1148 { 1149 GATT_TRACE_DEBUG("gatt_init_srv_chg num_srv_chg_clt_clients=%d", rsp.num_clients); 1150 num_clients = rsp.num_clients; 1151 i = 1; /* use one based index */ 1152 while ((i <= num_clients) && status) 1153 { 1154 req.client_read_index = i; 1155 if ((status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp)) == TRUE) 1156 { 1157 memcpy(&srv_chg_clt, &rsp.srv_chg ,sizeof(tGATTS_SRV_CHG)); 1158 if (gatt_add_srv_chg_clt(&srv_chg_clt) == NULL) 1159 { 1160 GATT_TRACE_ERROR("Unable to add a service change client"); 1161 status = FALSE; 1162 } 1163 } 1164 i++; 1165 } 1166 } 1167 } 1168 else 1169 { 1170 GATT_TRACE_DEBUG("gatt_init_srv_chg callback not registered yet"); 1171 } 1172 } 1173 1174 /******************************************************************************* 1175 ** 1176 ** Function gatt_proc_srv_chg 1177 ** 1178 ** Description This function is process the service changed request 1179 ** 1180 ** Returns void 1181 ** 1182 *******************************************************************************/ 1183 void gatt_proc_srv_chg (void) 1184 { 1185 UINT8 start_idx, found_idx; 1186 BD_ADDR bda; 1187 BOOLEAN srv_chg_ind_pending=FALSE; 1188 tGATT_TCB *p_tcb; 1189 tBT_TRANSPORT transport; 1190 1191 GATT_TRACE_DEBUG ("gatt_proc_srv_chg"); 1192 1193 if (gatt_cb.cb_info.p_srv_chg_callback && gatt_cb.handle_of_h_r) 1194 { 1195 gatt_set_srv_chg(); 1196 start_idx =0; 1197 while (gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) 1198 { 1199 p_tcb = &gatt_cb.tcb[found_idx];; 1200 srv_chg_ind_pending = gatt_is_srv_chg_ind_pending(p_tcb); 1201 1202 if (!srv_chg_ind_pending) 1203 { 1204 gatt_send_srv_chg_ind(bda); 1205 } 1206 else 1207 { 1208 GATT_TRACE_DEBUG ("discard srv chg - already has one in the queue"); 1209 } 1210 start_idx = ++found_idx; 1211 } 1212 } 1213 } 1214 1215 /******************************************************************************* 1216 ** 1217 ** Function gatt_set_ch_state 1218 ** 1219 ** Description This function set the ch_state in tcb 1220 ** 1221 ** Returns none 1222 ** 1223 *******************************************************************************/ 1224 void gatt_set_ch_state(tGATT_TCB *p_tcb, tGATT_CH_STATE ch_state) 1225 { 1226 if (p_tcb) 1227 { 1228 GATT_TRACE_DEBUG ("gatt_set_ch_state: old=%d new=%d", p_tcb->ch_state, ch_state); 1229 p_tcb->ch_state = ch_state; 1230 } 1231 } 1232 1233 /******************************************************************************* 1234 ** 1235 ** Function gatt_get_ch_state 1236 ** 1237 ** Description This function get the ch_state in tcb 1238 ** 1239 ** Returns none 1240 ** 1241 *******************************************************************************/ 1242 tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB *p_tcb) 1243 { 1244 tGATT_CH_STATE ch_state = GATT_CH_CLOSE; 1245 if (p_tcb) 1246 { 1247 GATT_TRACE_DEBUG ("gatt_get_ch_state: ch_state=%d", p_tcb->ch_state); 1248 ch_state = p_tcb->ch_state; 1249 } 1250 return ch_state; 1251 } 1252 1253 #endif /* BLE_INCLUDED */ 1254