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