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