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