1 /****************************************************************************** 2 * 3 * Copyright 1999-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 L2CAP channel state machine 22 * 23 ******************************************************************************/ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 29 #include "bt_common.h" 30 #include "bt_target.h" 31 #include "btm_int.h" 32 #include "btu.h" 33 #include "hcidefs.h" 34 #include "hcimsgs.h" 35 #include "l2c_int.h" 36 #include "l2cdefs.h" 37 38 /******************************************************************************/ 39 /* L O C A L F U N C T I O N P R O T O T Y P E S */ 40 /******************************************************************************/ 41 static void l2c_csm_closed(tL2C_CCB* p_ccb, uint16_t event, void* p_data); 42 static void l2c_csm_orig_w4_sec_comp(tL2C_CCB* p_ccb, uint16_t event, 43 void* p_data); 44 static void l2c_csm_term_w4_sec_comp(tL2C_CCB* p_ccb, uint16_t event, 45 void* p_data); 46 static void l2c_csm_w4_l2cap_connect_rsp(tL2C_CCB* p_ccb, uint16_t event, 47 void* p_data); 48 static void l2c_csm_w4_l2ca_connect_rsp(tL2C_CCB* p_ccb, uint16_t event, 49 void* p_data); 50 static void l2c_csm_config(tL2C_CCB* p_ccb, uint16_t event, void* p_data); 51 static void l2c_csm_open(tL2C_CCB* p_ccb, uint16_t event, void* p_data); 52 static void l2c_csm_w4_l2cap_disconnect_rsp(tL2C_CCB* p_ccb, uint16_t event, 53 void* p_data); 54 static void l2c_csm_w4_l2ca_disconnect_rsp(tL2C_CCB* p_ccb, uint16_t event, 55 void* p_data); 56 57 static const char* l2c_csm_get_event_name(uint16_t event); 58 59 /******************************************************************************* 60 * 61 * Function l2c_csm_execute 62 * 63 * Description This function executes the state machine. 64 * 65 * Returns void 66 * 67 ******************************************************************************/ 68 void l2c_csm_execute(tL2C_CCB* p_ccb, uint16_t event, void* p_data) { 69 if (!l2cu_is_ccb_active(p_ccb)) { 70 L2CAP_TRACE_WARNING("%s CCB not in use, event (%d) cannot be processed", 71 __func__, event); 72 return; 73 } 74 75 switch (p_ccb->chnl_state) { 76 case CST_CLOSED: 77 l2c_csm_closed(p_ccb, event, p_data); 78 break; 79 80 case CST_ORIG_W4_SEC_COMP: 81 l2c_csm_orig_w4_sec_comp(p_ccb, event, p_data); 82 break; 83 84 case CST_TERM_W4_SEC_COMP: 85 l2c_csm_term_w4_sec_comp(p_ccb, event, p_data); 86 break; 87 88 case CST_W4_L2CAP_CONNECT_RSP: 89 l2c_csm_w4_l2cap_connect_rsp(p_ccb, event, p_data); 90 break; 91 92 case CST_W4_L2CA_CONNECT_RSP: 93 l2c_csm_w4_l2ca_connect_rsp(p_ccb, event, p_data); 94 break; 95 96 case CST_CONFIG: 97 l2c_csm_config(p_ccb, event, p_data); 98 break; 99 100 case CST_OPEN: 101 l2c_csm_open(p_ccb, event, p_data); 102 break; 103 104 case CST_W4_L2CAP_DISCONNECT_RSP: 105 l2c_csm_w4_l2cap_disconnect_rsp(p_ccb, event, p_data); 106 break; 107 108 case CST_W4_L2CA_DISCONNECT_RSP: 109 l2c_csm_w4_l2ca_disconnect_rsp(p_ccb, event, p_data); 110 break; 111 112 default: 113 L2CAP_TRACE_DEBUG("Unhandled event! event = %d", event); 114 break; 115 } 116 } 117 118 /******************************************************************************* 119 * 120 * Function l2c_csm_closed 121 * 122 * Description This function handles events when the channel is in 123 * CLOSED state. This state exists only when the link is 124 * being initially established. 125 * 126 * Returns void 127 * 128 ******************************************************************************/ 129 static void l2c_csm_closed(tL2C_CCB* p_ccb, uint16_t event, void* p_data) { 130 tL2C_CONN_INFO* p_ci = (tL2C_CONN_INFO*)p_data; 131 uint16_t local_cid = p_ccb->local_cid; 132 tL2CA_DISCONNECT_IND_CB* disconnect_ind; 133 tL2CA_CONNECT_CFM_CB* connect_cfm; 134 135 if (p_ccb->p_rcb == NULL) { 136 L2CAP_TRACE_ERROR("L2CAP - LCID: 0x%04x st: CLOSED evt: %s p_rcb == NULL", 137 p_ccb->local_cid, l2c_csm_get_event_name(event)); 138 return; 139 } 140 141 disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb; 142 connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb; 143 144 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: CLOSED evt: %s", 145 p_ccb->local_cid, l2c_csm_get_event_name(event)); 146 147 switch (event) { 148 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */ 149 L2CAP_TRACE_API( 150 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", 151 p_ccb->local_cid); 152 l2cu_release_ccb(p_ccb); 153 (*disconnect_ind)(local_cid, false); 154 break; 155 156 case L2CEVT_LP_CONNECT_CFM: /* Link came up */ 157 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) { 158 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP; 159 l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, 160 true, &l2c_link_sec_comp2, p_ccb); 161 } else { 162 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP; 163 btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, 164 p_ccb->p_rcb->psm, p_ccb->p_lcb->handle, true, 165 &l2c_link_sec_comp, p_ccb); 166 } 167 break; 168 169 case L2CEVT_LP_CONNECT_CFM_NEG: /* Link failed */ 170 /* Disconnect unless ACL collision and upper layer wants to handle it */ 171 if (p_ci->status != HCI_ERR_CONNECTION_EXISTS || 172 !btm_acl_notif_conn_collision(p_ccb->p_lcb->remote_bd_addr)) { 173 L2CAP_TRACE_API( 174 "L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d", 175 p_ccb->local_cid, p_ci->status); 176 l2cu_release_ccb(p_ccb); 177 (*connect_cfm)(local_cid, p_ci->status); 178 } 179 break; 180 181 case L2CEVT_L2CA_CONNECT_REQ: /* API connect request */ 182 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) { 183 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP; 184 l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, 185 true, &l2c_link_sec_comp2, p_ccb); 186 } else { 187 /* Cancel sniff mode if needed */ 188 tBTM_PM_PWR_MD settings; 189 memset((void*)&settings, 0, sizeof(settings)); 190 settings.mode = BTM_PM_MD_ACTIVE; 191 192 BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, 193 &settings); 194 195 /* If sec access does not result in started SEC_COM or COMP_NEG are 196 * already processed */ 197 if (btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, 198 p_ccb->p_rcb->psm, p_ccb->p_lcb->handle, 199 true, &l2c_link_sec_comp, 200 p_ccb) == BTM_CMD_STARTED) { 201 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP; 202 } 203 } 204 break; 205 206 case L2CEVT_SEC_COMP: 207 p_ccb->chnl_state = CST_W4_L2CAP_CONNECT_RSP; 208 209 /* Wait for the info resp in this state before sending connect req (if 210 * needed) */ 211 if (!p_ccb->p_lcb->w4_info_rsp) { 212 /* Need to have at least one compatible channel to continue */ 213 if (!l2c_fcr_chk_chan_modes(p_ccb)) { 214 l2cu_release_ccb(p_ccb); 215 (*p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb)(local_cid, 216 L2CAP_CONN_NO_LINK); 217 } else { 218 l2cu_send_peer_connect_req(p_ccb); 219 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, 220 L2CAP_CHNL_CONNECT_TIMEOUT_MS, 221 l2c_ccb_timer_timeout, p_ccb); 222 } 223 } 224 break; 225 226 case L2CEVT_SEC_COMP_NEG: /* something is really bad with security */ 227 L2CAP_TRACE_API( 228 "L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d", 229 p_ccb->local_cid, L2CAP_CONN_TIMEOUT); 230 l2cu_release_ccb(p_ccb); 231 (*connect_cfm)(local_cid, L2CAP_CONN_SECURITY_BLOCK); 232 break; 233 234 case L2CEVT_L2CAP_CONNECT_REQ: /* Peer connect request */ 235 /* stop link timer to avoid race condition between A2MP, Security, and 236 * L2CAP */ 237 alarm_cancel(p_ccb->p_lcb->l2c_lcb_timer); 238 239 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) { 240 p_ccb->chnl_state = CST_TERM_W4_SEC_COMP; 241 l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, 242 false, &l2c_link_sec_comp2, p_ccb); 243 } else { 244 /* Cancel sniff mode if needed */ 245 { 246 tBTM_PM_PWR_MD settings; 247 memset((void*)&settings, 0, sizeof(settings)); 248 settings.mode = BTM_PM_MD_ACTIVE; 249 250 BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, 251 &settings); 252 } 253 254 p_ccb->chnl_state = CST_TERM_W4_SEC_COMP; 255 if (btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, 256 p_ccb->p_rcb->psm, p_ccb->p_lcb->handle, 257 false, &l2c_link_sec_comp, 258 p_ccb) == BTM_CMD_STARTED) { 259 /* started the security process, tell the peer to set a longer timer 260 */ 261 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_PENDING, 0); 262 } 263 } 264 break; 265 266 case L2CEVT_TIMEOUT: 267 L2CAP_TRACE_API( 268 "L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d", 269 p_ccb->local_cid, L2CAP_CONN_TIMEOUT); 270 l2cu_release_ccb(p_ccb); 271 (*connect_cfm)(local_cid, L2CAP_CONN_TIMEOUT); 272 break; 273 274 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 275 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 276 osi_free(p_data); 277 break; 278 279 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */ 280 l2cu_release_ccb(p_ccb); 281 break; 282 } 283 } 284 285 /******************************************************************************* 286 * 287 * Function l2c_csm_orig_w4_sec_comp 288 * 289 * Description This function handles events when the channel is in 290 * CST_ORIG_W4_SEC_COMP state. 291 * 292 * Returns void 293 * 294 ******************************************************************************/ 295 static void l2c_csm_orig_w4_sec_comp(tL2C_CCB* p_ccb, uint16_t event, 296 void* p_data) { 297 tL2CA_DISCONNECT_IND_CB* disconnect_ind = 298 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb; 299 tL2CA_CONNECT_CFM_CB* connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb; 300 uint16_t local_cid = p_ccb->local_cid; 301 302 L2CAP_TRACE_EVENT( 303 "%s: %sL2CAP - LCID: 0x%04x st: ORIG_W4_SEC_COMP evt: %s", __func__, 304 ((p_ccb->p_lcb) && (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)) ? "LE " 305 : "", 306 p_ccb->local_cid, l2c_csm_get_event_name(event)); 307 308 switch (event) { 309 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */ 310 L2CAP_TRACE_API( 311 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", 312 p_ccb->local_cid); 313 l2cu_release_ccb(p_ccb); 314 (*disconnect_ind)(local_cid, false); 315 break; 316 317 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */ 318 case L2CEVT_LP_CONNECT_CFM: /* Link came up */ 319 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) { 320 l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, 321 false, &l2c_link_sec_comp2, p_ccb); 322 } else { 323 btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, 324 p_ccb->p_rcb->psm, p_ccb->p_lcb->handle, true, 325 &l2c_link_sec_comp, p_ccb); 326 } 327 break; 328 329 case L2CEVT_SEC_COMP: /* Security completed success */ 330 /* Wait for the info resp in this state before sending connect req (if 331 * needed) */ 332 p_ccb->chnl_state = CST_W4_L2CAP_CONNECT_RSP; 333 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) { 334 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CONNECT_TIMEOUT_MS, 335 l2c_ccb_timer_timeout, p_ccb); 336 l2cble_credit_based_conn_req(p_ccb); /* Start Connection */ 337 } else { 338 if (!p_ccb->p_lcb->w4_info_rsp) { 339 /* Need to have at least one compatible channel to continue */ 340 if (!l2c_fcr_chk_chan_modes(p_ccb)) { 341 l2cu_release_ccb(p_ccb); 342 (*connect_cfm)(local_cid, L2CAP_CONN_NO_LINK); 343 } else { 344 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, 345 L2CAP_CHNL_CONNECT_TIMEOUT_MS, 346 l2c_ccb_timer_timeout, p_ccb); 347 l2cu_send_peer_connect_req(p_ccb); /* Start Connection */ 348 } 349 } 350 } 351 break; 352 353 case L2CEVT_SEC_COMP_NEG: 354 L2CAP_TRACE_API( 355 "L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d", 356 p_ccb->local_cid, HCI_ERR_AUTH_FAILURE); 357 358 /* If last channel immediately disconnect the ACL for better security. 359 Also prevents a race condition between BTM and L2CAP */ 360 if ((p_ccb == p_ccb->p_lcb->ccb_queue.p_first_ccb) && 361 (p_ccb == p_ccb->p_lcb->ccb_queue.p_last_ccb)) { 362 p_ccb->p_lcb->idle_timeout = 0; 363 } 364 365 l2cu_release_ccb(p_ccb); 366 (*connect_cfm)(local_cid, HCI_ERR_AUTH_FAILURE); 367 break; 368 369 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 370 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 371 osi_free(p_data); 372 break; 373 374 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */ 375 /* Tell security manager to abort */ 376 btm_sec_abort_access_req(p_ccb->p_lcb->remote_bd_addr); 377 378 l2cu_release_ccb(p_ccb); 379 break; 380 } 381 } 382 383 /******************************************************************************* 384 * 385 * Function l2c_csm_term_w4_sec_comp 386 * 387 * Description This function handles events when the channel is in 388 * CST_TERM_W4_SEC_COMP state. 389 * 390 * Returns void 391 * 392 ******************************************************************************/ 393 static void l2c_csm_term_w4_sec_comp(tL2C_CCB* p_ccb, uint16_t event, 394 void* p_data) { 395 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: TERM_W4_SEC_COMP evt: %s", 396 p_ccb->local_cid, l2c_csm_get_event_name(event)); 397 398 switch (event) { 399 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */ 400 /* Tell security manager to abort */ 401 btm_sec_abort_access_req(p_ccb->p_lcb->remote_bd_addr); 402 403 l2cu_release_ccb(p_ccb); 404 break; 405 406 case L2CEVT_SEC_COMP: 407 p_ccb->chnl_state = CST_W4_L2CA_CONNECT_RSP; 408 409 /* Wait for the info resp in next state before sending connect ind (if 410 * needed) */ 411 if (!p_ccb->p_lcb->w4_info_rsp) { 412 /* Don't need to get info from peer or already retrieved so continue */ 413 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CONNECT_TIMEOUT_MS, 414 l2c_ccb_timer_timeout, p_ccb); 415 L2CAP_TRACE_API("L2CAP - Calling Connect_Ind_Cb(), CID: 0x%04x", 416 p_ccb->local_cid); 417 418 (*p_ccb->p_rcb->api.pL2CA_ConnectInd_Cb)( 419 p_ccb->p_lcb->remote_bd_addr, p_ccb->local_cid, p_ccb->p_rcb->psm, 420 p_ccb->remote_id); 421 } else { 422 /* 423 ** L2CAP Connect Response will be sent out by 3 sec timer expiration 424 ** because Bluesoleil doesn't respond to L2CAP Information Request. 425 ** Bluesoleil seems to disconnect ACL link as failure case, because 426 ** it takes too long (4~7secs) to get response. 427 ** product version : Bluesoleil 2.1.1.0 EDR Release 060123 428 ** stack version : 05.04.11.20060119 429 */ 430 431 /* Waiting for the info resp, tell the peer to set a longer timer */ 432 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_PENDING, 0); 433 } 434 break; 435 436 case L2CEVT_SEC_COMP_NEG: 437 if (((tL2C_CONN_INFO*)p_data)->status == BTM_DELAY_CHECK) { 438 /* start a timer - encryption change not received before L2CAP connect 439 * req */ 440 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, 441 L2CAP_DELAY_CHECK_SM4_TIMEOUT_MS, 442 l2c_ccb_timer_timeout, p_ccb); 443 } else { 444 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) 445 l2cu_reject_ble_connection(p_ccb->p_lcb, p_ccb->remote_id, 446 L2CAP_LE_INSUFFICIENT_AUTHENTICATION); 447 else 448 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_SECURITY_BLOCK, 0); 449 l2cu_release_ccb(p_ccb); 450 } 451 break; 452 453 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 454 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 455 osi_free(p_data); 456 break; 457 458 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */ 459 l2cu_release_ccb(p_ccb); 460 break; 461 462 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */ 463 l2cu_send_peer_disc_rsp(p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, 464 p_ccb->remote_cid); 465 466 /* Tell security manager to abort */ 467 btm_sec_abort_access_req(p_ccb->p_lcb->remote_bd_addr); 468 469 l2cu_release_ccb(p_ccb); 470 break; 471 472 case L2CEVT_TIMEOUT: 473 /* SM4 related. */ 474 btsnd_hcic_disconnect(p_ccb->p_lcb->handle, HCI_ERR_AUTH_FAILURE); 475 break; 476 477 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */ 478 btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, 479 p_ccb->p_lcb->handle, false, &l2c_link_sec_comp, 480 p_ccb); 481 break; 482 } 483 } 484 485 /******************************************************************************* 486 * 487 * Function l2c_csm_w4_l2cap_connect_rsp 488 * 489 * Description This function handles events when the channel is in 490 * CST_W4_L2CAP_CONNECT_RSP state. 491 * 492 * Returns void 493 * 494 ******************************************************************************/ 495 static void l2c_csm_w4_l2cap_connect_rsp(tL2C_CCB* p_ccb, uint16_t event, 496 void* p_data) { 497 tL2C_CONN_INFO* p_ci = (tL2C_CONN_INFO*)p_data; 498 tL2CA_DISCONNECT_IND_CB* disconnect_ind = 499 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb; 500 tL2CA_CONNECT_CFM_CB* connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb; 501 uint16_t local_cid = p_ccb->local_cid; 502 503 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: W4_L2CAP_CON_RSP evt: %s", 504 p_ccb->local_cid, l2c_csm_get_event_name(event)); 505 506 switch (event) { 507 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */ 508 /* Send disc indication unless peer to peer race condition AND normal 509 * disconnect */ 510 /* *((uint8_t *)p_data) != HCI_ERR_PEER_USER happens when peer device try 511 * to disconnect for normal reason */ 512 p_ccb->chnl_state = CST_CLOSED; 513 if ((p_ccb->flags & CCB_FLAG_NO_RETRY) || !p_data || 514 (*((uint8_t*)p_data) != HCI_ERR_PEER_USER)) { 515 L2CAP_TRACE_API( 516 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", 517 p_ccb->local_cid); 518 l2cu_release_ccb(p_ccb); 519 (*disconnect_ind)(local_cid, false); 520 } 521 p_ccb->flags |= CCB_FLAG_NO_RETRY; 522 break; 523 524 case L2CEVT_L2CAP_CONNECT_RSP: /* Got peer connect confirm */ 525 p_ccb->remote_cid = p_ci->remote_cid; 526 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) { 527 /* Connection is completed */ 528 alarm_cancel(p_ccb->l2c_ccb_timer); 529 p_ccb->chnl_state = CST_OPEN; 530 } else { 531 p_ccb->chnl_state = CST_CONFIG; 532 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS, 533 l2c_ccb_timer_timeout, p_ccb); 534 } 535 L2CAP_TRACE_API("L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Success", 536 p_ccb->local_cid); 537 538 (*p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb)(local_cid, L2CAP_CONN_OK); 539 break; 540 541 case L2CEVT_L2CAP_CONNECT_RSP_PND: /* Got peer connect pending */ 542 p_ccb->remote_cid = p_ci->remote_cid; 543 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, 544 L2CAP_CHNL_CONNECT_EXT_TIMEOUT_MS, 545 l2c_ccb_timer_timeout, p_ccb); 546 if (p_ccb->p_rcb->api.pL2CA_ConnectPnd_Cb) { 547 L2CAP_TRACE_API("L2CAP - Calling Connect_Pnd_Cb(), CID: 0x%04x", 548 p_ccb->local_cid); 549 (*p_ccb->p_rcb->api.pL2CA_ConnectPnd_Cb)(p_ccb->local_cid); 550 } 551 break; 552 553 case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer rejected connection */ 554 LOG(WARNING) << __func__ << ": L2CAP connection rejected, lcid=" 555 << loghex(p_ccb->local_cid) 556 << ", reason=" << loghex(p_ci->l2cap_result); 557 l2cu_release_ccb(p_ccb); 558 (*connect_cfm)(local_cid, p_ci->l2cap_result); 559 break; 560 561 case L2CEVT_TIMEOUT: 562 LOG(WARNING) << __func__ << ": L2CAP connection timeout, lcid=" 563 << loghex(p_ccb->local_cid); 564 l2cu_release_ccb(p_ccb); 565 (*connect_cfm)(local_cid, L2CAP_CONN_TIMEOUT); 566 break; 567 568 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */ 569 /* If we know peer CID from connect pending, we can send disconnect */ 570 if (p_ccb->remote_cid != 0) { 571 l2cu_send_peer_disc_req(p_ccb); 572 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP; 573 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, 574 L2CAP_CHNL_DISCONNECT_TIMEOUT_MS, 575 l2c_ccb_timer_timeout, p_ccb); 576 } else { 577 tL2CA_DISCONNECT_CFM_CB* disconnect_cfm = 578 p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb; 579 l2cu_release_ccb(p_ccb); 580 if (disconnect_cfm) { 581 L2CAP_TRACE_API("%s: L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", 582 __func__, local_cid); 583 (*disconnect_cfm)(local_cid, L2CAP_CONN_NO_LINK); 584 } 585 } 586 break; 587 588 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 589 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 590 osi_free(p_data); 591 break; 592 593 case L2CEVT_L2CAP_INFO_RSP: 594 /* Need to have at least one compatible channel to continue */ 595 if (!l2c_fcr_chk_chan_modes(p_ccb)) { 596 l2cu_release_ccb(p_ccb); 597 (*connect_cfm)(local_cid, L2CAP_CONN_NO_LINK); 598 } else { 599 /* We have feature info, so now send peer connect request */ 600 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CONNECT_TIMEOUT_MS, 601 l2c_ccb_timer_timeout, p_ccb); 602 l2cu_send_peer_connect_req(p_ccb); /* Start Connection */ 603 } 604 break; 605 } 606 } 607 608 /******************************************************************************* 609 * 610 * Function l2c_csm_w4_l2ca_connect_rsp 611 * 612 * Description This function handles events when the channel is in 613 * CST_W4_L2CA_CONNECT_RSP state. 614 * 615 * Returns void 616 * 617 ******************************************************************************/ 618 static void l2c_csm_w4_l2ca_connect_rsp(tL2C_CCB* p_ccb, uint16_t event, 619 void* p_data) { 620 tL2C_CONN_INFO* p_ci; 621 tL2CA_DISCONNECT_IND_CB* disconnect_ind = 622 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb; 623 uint16_t local_cid = p_ccb->local_cid; 624 625 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: W4_L2CA_CON_RSP evt: %s", 626 p_ccb->local_cid, l2c_csm_get_event_name(event)); 627 628 switch (event) { 629 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */ 630 L2CAP_TRACE_API( 631 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", 632 p_ccb->local_cid); 633 l2cu_release_ccb(p_ccb); 634 (*disconnect_ind)(local_cid, false); 635 break; 636 637 case L2CEVT_L2CA_CONNECT_RSP: 638 p_ci = (tL2C_CONN_INFO*)p_data; 639 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) { 640 /* Result should be OK or Reject */ 641 if ((!p_ci) || (p_ci->l2cap_result == L2CAP_CONN_OK)) { 642 l2cble_credit_based_conn_res(p_ccb, L2CAP_CONN_OK); 643 p_ccb->chnl_state = CST_OPEN; 644 alarm_cancel(p_ccb->l2c_ccb_timer); 645 } else { 646 l2cble_credit_based_conn_res(p_ccb, p_ci->l2cap_result); 647 l2cu_release_ccb(p_ccb); 648 } 649 } else { 650 /* Result should be OK or PENDING */ 651 if ((!p_ci) || (p_ci->l2cap_result == L2CAP_CONN_OK)) { 652 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_OK, 0); 653 p_ccb->chnl_state = CST_CONFIG; 654 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS, 655 l2c_ccb_timer_timeout, p_ccb); 656 } else { 657 /* If pending, stay in same state and start extended timer */ 658 l2cu_send_peer_connect_rsp(p_ccb, p_ci->l2cap_result, 659 p_ci->l2cap_status); 660 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, 661 L2CAP_CHNL_CONNECT_EXT_TIMEOUT_MS, 662 l2c_ccb_timer_timeout, p_ccb); 663 } 664 } 665 break; 666 667 case L2CEVT_L2CA_CONNECT_RSP_NEG: 668 p_ci = (tL2C_CONN_INFO*)p_data; 669 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) 670 l2cble_credit_based_conn_res(p_ccb, p_ci->l2cap_result); 671 else 672 l2cu_send_peer_connect_rsp(p_ccb, p_ci->l2cap_result, 673 p_ci->l2cap_status); 674 l2cu_release_ccb(p_ccb); 675 break; 676 677 case L2CEVT_TIMEOUT: 678 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_NO_PSM, 0); 679 L2CAP_TRACE_API( 680 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", 681 p_ccb->local_cid); 682 l2cu_release_ccb(p_ccb); 683 (*disconnect_ind)(local_cid, false); 684 break; 685 686 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 687 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 688 osi_free(p_data); 689 break; 690 691 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */ 692 l2cu_send_peer_disc_req(p_ccb); 693 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP; 694 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS, 695 l2c_ccb_timer_timeout, p_ccb); 696 break; 697 698 case L2CEVT_L2CAP_INFO_RSP: 699 /* We have feature info, so now give the upper layer connect IND */ 700 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CONNECT_TIMEOUT_MS, 701 l2c_ccb_timer_timeout, p_ccb); 702 L2CAP_TRACE_API("L2CAP - Calling Connect_Ind_Cb(), CID: 0x%04x", 703 p_ccb->local_cid); 704 705 (*p_ccb->p_rcb->api.pL2CA_ConnectInd_Cb)( 706 p_ccb->p_lcb->remote_bd_addr, p_ccb->local_cid, p_ccb->p_rcb->psm, 707 p_ccb->remote_id); 708 break; 709 } 710 } 711 712 /******************************************************************************* 713 * 714 * Function l2c_csm_config 715 * 716 * Description This function handles events when the channel is in 717 * CONFIG state. 718 * 719 * Returns void 720 * 721 ******************************************************************************/ 722 static void l2c_csm_config(tL2C_CCB* p_ccb, uint16_t event, void* p_data) { 723 tL2CAP_CFG_INFO* p_cfg = (tL2CAP_CFG_INFO*)p_data; 724 tL2CA_DISCONNECT_IND_CB* disconnect_ind = 725 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb; 726 uint16_t local_cid = p_ccb->local_cid; 727 uint8_t cfg_result; 728 729 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: CONFIG evt: %s", 730 p_ccb->local_cid, l2c_csm_get_event_name(event)); 731 732 switch (event) { 733 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */ 734 L2CAP_TRACE_API( 735 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", 736 p_ccb->local_cid); 737 l2cu_release_ccb(p_ccb); 738 (*disconnect_ind)(local_cid, false); 739 break; 740 741 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request */ 742 743 cfg_result = l2cu_process_peer_cfg_req(p_ccb, p_cfg); 744 if (cfg_result == L2CAP_PEER_CFG_OK) { 745 L2CAP_TRACE_EVENT( 746 "L2CAP - Calling Config_Req_Cb(), CID: 0x%04x, C-bit %d", 747 p_ccb->local_cid, (p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT)); 748 (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg); 749 } else if (cfg_result == L2CAP_PEER_CFG_DISCONNECT) { 750 /* Disconnect if channels are incompatible */ 751 L2CAP_TRACE_EVENT("L2CAP - incompatible configurations disconnect"); 752 l2cu_disconnect_chnl(p_ccb); 753 } else /* Return error to peer so he can renegotiate if possible */ 754 { 755 L2CAP_TRACE_EVENT( 756 "L2CAP - incompatible configurations trying reconfig"); 757 l2cu_send_peer_config_rsp(p_ccb, p_cfg); 758 } 759 break; 760 761 case L2CEVT_L2CAP_CONFIG_RSP: /* Peer config response */ 762 l2cu_process_peer_cfg_rsp(p_ccb, p_cfg); 763 764 if (p_cfg->result != L2CAP_CFG_PENDING) { 765 /* TBD: When config options grow beyong minimum MTU (48 bytes) 766 * logic needs to be added to handle responses with 767 * continuation bit set in flags field. 768 * 1. Send additional config request out until C-bit is cleared in 769 * response 770 */ 771 p_ccb->config_done |= OB_CFG_DONE; 772 773 if (p_ccb->config_done & IB_CFG_DONE) { 774 /* Verify two sides are in compatible modes before continuing */ 775 if (p_ccb->our_cfg.fcr.mode != p_ccb->peer_cfg.fcr.mode) { 776 l2cu_send_peer_disc_req(p_ccb); 777 L2CAP_TRACE_WARNING( 778 "L2CAP - Calling Disconnect_Ind_Cb(Incompatible CFG), CID: " 779 "0x%04x No Conf Needed", 780 p_ccb->local_cid); 781 l2cu_release_ccb(p_ccb); 782 (*disconnect_ind)(local_cid, false); 783 break; 784 } 785 786 p_ccb->config_done |= RECONFIG_FLAG; 787 p_ccb->chnl_state = CST_OPEN; 788 l2c_link_adjust_chnl_allocation(); 789 alarm_cancel(p_ccb->l2c_ccb_timer); 790 791 /* If using eRTM and waiting for an ACK, restart the ACK timer */ 792 if (p_ccb->fcrb.wait_ack) l2c_fcr_start_timer(p_ccb); 793 794 /* 795 ** check p_ccb->our_cfg.fcr.mon_tout and 796 *p_ccb->our_cfg.fcr.rtrans_tout 797 ** we may set them to zero when sending config request during 798 *renegotiation 799 */ 800 if ((p_ccb->our_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && 801 ((p_ccb->our_cfg.fcr.mon_tout == 0) || 802 (p_ccb->our_cfg.fcr.rtrans_tout))) { 803 l2c_fcr_adj_monitor_retran_timeout(p_ccb); 804 } 805 806 #if (L2CAP_ERTM_STATS == TRUE) 807 p_ccb->fcrb.connect_tick_count = time_get_os_boottime_ms(); 808 #endif 809 /* See if we can forward anything on the hold queue */ 810 if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) { 811 l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL); 812 } 813 } 814 } 815 816 L2CAP_TRACE_API("L2CAP - Calling Config_Rsp_Cb(), CID: 0x%04x", 817 p_ccb->local_cid); 818 (*p_ccb->p_rcb->api.pL2CA_ConfigCfm_Cb)(p_ccb->local_cid, p_cfg); 819 break; 820 821 case L2CEVT_L2CAP_CONFIG_RSP_NEG: /* Peer config error rsp */ 822 /* Disable the Timer */ 823 alarm_cancel(p_ccb->l2c_ccb_timer); 824 825 /* If failure was channel mode try to renegotiate */ 826 if (!l2c_fcr_renegotiate_chan(p_ccb, p_cfg)) { 827 L2CAP_TRACE_API( 828 "L2CAP - Calling Config_Rsp_Cb(), CID: 0x%04x, Failure: %d", 829 p_ccb->local_cid, p_cfg->result); 830 (*p_ccb->p_rcb->api.pL2CA_ConfigCfm_Cb)(p_ccb->local_cid, p_cfg); 831 } 832 break; 833 834 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */ 835 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS, 836 l2c_ccb_timer_timeout, p_ccb); 837 p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP; 838 L2CAP_TRACE_API( 839 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x Conf Needed", 840 p_ccb->local_cid); 841 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, true); 842 break; 843 844 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */ 845 l2cu_process_our_cfg_req(p_ccb, p_cfg); 846 l2cu_send_peer_config_req(p_ccb, p_cfg); 847 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS, 848 l2c_ccb_timer_timeout, p_ccb); 849 break; 850 851 case L2CEVT_L2CA_CONFIG_RSP: /* Upper layer config rsp */ 852 l2cu_process_our_cfg_rsp(p_ccb, p_cfg); 853 854 /* Not finished if continuation flag is set */ 855 if ((p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT) || 856 (p_cfg->result == L2CAP_CFG_PENDING)) { 857 /* Send intermediate response; remain in cfg state */ 858 l2cu_send_peer_config_rsp(p_ccb, p_cfg); 859 break; 860 } 861 862 /* Local config done; clear cached configuration in case reconfig takes 863 * place later */ 864 p_ccb->peer_cfg.mtu_present = false; 865 p_ccb->peer_cfg.flush_to_present = false; 866 p_ccb->peer_cfg.qos_present = false; 867 868 p_ccb->config_done |= IB_CFG_DONE; 869 870 if (p_ccb->config_done & OB_CFG_DONE) { 871 /* Verify two sides are in compatible modes before continuing */ 872 if (p_ccb->our_cfg.fcr.mode != p_ccb->peer_cfg.fcr.mode) { 873 l2cu_send_peer_disc_req(p_ccb); 874 L2CAP_TRACE_WARNING( 875 "L2CAP - Calling Disconnect_Ind_Cb(Incompatible CFG), CID: " 876 "0x%04x No Conf Needed", 877 p_ccb->local_cid); 878 l2cu_release_ccb(p_ccb); 879 (*disconnect_ind)(local_cid, false); 880 break; 881 } 882 883 p_ccb->config_done |= RECONFIG_FLAG; 884 p_ccb->chnl_state = CST_OPEN; 885 l2c_link_adjust_chnl_allocation(); 886 alarm_cancel(p_ccb->l2c_ccb_timer); 887 } 888 889 l2cu_send_peer_config_rsp(p_ccb, p_cfg); 890 891 /* If using eRTM and waiting for an ACK, restart the ACK timer */ 892 if (p_ccb->fcrb.wait_ack) l2c_fcr_start_timer(p_ccb); 893 894 #if (L2CAP_ERTM_STATS == TRUE) 895 p_ccb->fcrb.connect_tick_count = time_get_os_boottime_ms(); 896 #endif 897 898 /* See if we can forward anything on the hold queue */ 899 if ((p_ccb->chnl_state == CST_OPEN) && 900 (!fixed_queue_is_empty(p_ccb->xmit_hold_q))) { 901 l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL); 902 } 903 break; 904 905 case L2CEVT_L2CA_CONFIG_RSP_NEG: /* Upper layer config reject */ 906 l2cu_send_peer_config_rsp(p_ccb, p_cfg); 907 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS, 908 l2c_ccb_timer_timeout, p_ccb); 909 break; 910 911 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */ 912 l2cu_send_peer_disc_req(p_ccb); 913 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP; 914 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS, 915 l2c_ccb_timer_timeout, p_ccb); 916 break; 917 918 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 919 L2CAP_TRACE_API("L2CAP - Calling DataInd_Cb(), CID: 0x%04x", 920 p_ccb->local_cid); 921 #if (L2CAP_NUM_FIXED_CHNLS > 0) 922 if (p_ccb->local_cid >= L2CAP_FIRST_FIXED_CHNL && 923 p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL) { 924 if (p_ccb->local_cid < L2CAP_BASE_APPL_CID) { 925 if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL] 926 .pL2CA_FixedData_Cb) 927 (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL] 928 .pL2CA_FixedData_Cb)(p_ccb->local_cid, 929 p_ccb->p_lcb->remote_bd_addr, 930 (BT_HDR*)p_data); 931 else 932 osi_free(p_data); 933 break; 934 } 935 } 936 #endif 937 (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR*)p_data); 938 break; 939 940 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 941 if (p_ccb->config_done & OB_CFG_DONE) 942 l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_data); 943 else 944 osi_free(p_data); 945 break; 946 947 case L2CEVT_TIMEOUT: 948 l2cu_send_peer_disc_req(p_ccb); 949 L2CAP_TRACE_API( 950 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", 951 p_ccb->local_cid); 952 l2cu_release_ccb(p_ccb); 953 (*disconnect_ind)(local_cid, false); 954 break; 955 } 956 } 957 958 /******************************************************************************* 959 * 960 * Function l2c_csm_open 961 * 962 * Description This function handles events when the channel is in 963 * OPEN state. 964 * 965 * Returns void 966 * 967 ******************************************************************************/ 968 static void l2c_csm_open(tL2C_CCB* p_ccb, uint16_t event, void* p_data) { 969 uint16_t local_cid = p_ccb->local_cid; 970 tL2CAP_CFG_INFO* p_cfg; 971 tL2C_CHNL_STATE tempstate; 972 uint8_t tempcfgdone; 973 uint8_t cfg_result; 974 uint16_t* credit; 975 976 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: OPEN evt: %s", p_ccb->local_cid, 977 l2c_csm_get_event_name(event)); 978 979 switch (event) { 980 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */ 981 L2CAP_TRACE_API( 982 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", 983 p_ccb->local_cid); 984 l2cu_release_ccb(p_ccb); 985 if (p_ccb->p_rcb) 986 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(local_cid, false); 987 break; 988 989 case L2CEVT_LP_QOS_VIOLATION_IND: /* QOS violation */ 990 /* Tell upper layer. If service guaranteed, then clear the channel */ 991 if (p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb) 992 (*p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)( 993 p_ccb->p_lcb->remote_bd_addr); 994 break; 995 996 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request */ 997 p_cfg = (tL2CAP_CFG_INFO*)p_data; 998 999 tempstate = p_ccb->chnl_state; 1000 tempcfgdone = p_ccb->config_done; 1001 p_ccb->chnl_state = CST_CONFIG; 1002 p_ccb->config_done &= ~IB_CFG_DONE; 1003 1004 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS, 1005 l2c_ccb_timer_timeout, p_ccb); 1006 1007 cfg_result = l2cu_process_peer_cfg_req(p_ccb, p_cfg); 1008 if (cfg_result == L2CAP_PEER_CFG_OK) { 1009 (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg); 1010 } 1011 1012 /* Error in config parameters: reset state and config flag */ 1013 else if (cfg_result == L2CAP_PEER_CFG_UNACCEPTABLE) { 1014 alarm_cancel(p_ccb->l2c_ccb_timer); 1015 p_ccb->chnl_state = tempstate; 1016 p_ccb->config_done = tempcfgdone; 1017 l2cu_send_peer_config_rsp(p_ccb, p_cfg); 1018 } else /* L2CAP_PEER_CFG_DISCONNECT */ 1019 { 1020 /* Disconnect if channels are incompatible 1021 * Note this should not occur if reconfigure 1022 * since this should have never passed original config. 1023 */ 1024 l2cu_disconnect_chnl(p_ccb); 1025 } 1026 break; 1027 1028 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */ 1029 if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE) { 1030 /* Make sure we are not in sniff mode */ 1031 { 1032 tBTM_PM_PWR_MD settings; 1033 memset((void*)&settings, 0, sizeof(settings)); 1034 settings.mode = BTM_PM_MD_ACTIVE; 1035 BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, 1036 &settings); 1037 } 1038 } 1039 1040 p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP; 1041 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS, 1042 l2c_ccb_timer_timeout, p_ccb); 1043 L2CAP_TRACE_API( 1044 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x Conf Needed", 1045 p_ccb->local_cid); 1046 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, true); 1047 break; 1048 1049 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 1050 if ((p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_DataInd_Cb)) 1051 (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, 1052 (BT_HDR*)p_data); 1053 break; 1054 1055 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */ 1056 if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE) { 1057 /* Make sure we are not in sniff mode */ 1058 { 1059 tBTM_PM_PWR_MD settings; 1060 memset((void*)&settings, 0, sizeof(settings)); 1061 settings.mode = BTM_PM_MD_ACTIVE; 1062 BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, 1063 &settings); 1064 } 1065 } 1066 1067 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) 1068 l2cble_send_peer_disc_req(p_ccb); 1069 else 1070 l2cu_send_peer_disc_req(p_ccb); 1071 1072 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP; 1073 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS, 1074 l2c_ccb_timer_timeout, p_ccb); 1075 break; 1076 1077 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 1078 l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_data); 1079 l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL); 1080 break; 1081 1082 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */ 1083 p_ccb->chnl_state = CST_CONFIG; 1084 p_ccb->config_done &= ~CFG_DONE_MASK; 1085 l2cu_process_our_cfg_req(p_ccb, (tL2CAP_CFG_INFO*)p_data); 1086 l2cu_send_peer_config_req(p_ccb, (tL2CAP_CFG_INFO*)p_data); 1087 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS, 1088 l2c_ccb_timer_timeout, p_ccb); 1089 break; 1090 1091 case L2CEVT_TIMEOUT: 1092 /* Process the monitor/retransmission time-outs in flow control/retrans 1093 * mode */ 1094 if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) 1095 l2c_fcr_proc_tout(p_ccb); 1096 break; 1097 1098 case L2CEVT_ACK_TIMEOUT: 1099 l2c_fcr_proc_ack_tout(p_ccb); 1100 break; 1101 1102 case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT: 1103 L2CAP_TRACE_DEBUG("%s Sending credit", __func__); 1104 credit = (uint16_t*)p_data; 1105 l2cble_send_flow_control_credit(p_ccb, *credit); 1106 break; 1107 1108 case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT: 1109 credit = (uint16_t*)p_data; 1110 L2CAP_TRACE_DEBUG("%s Credits received %d", __func__, *credit); 1111 if ((p_ccb->peer_conn_cfg.credits + *credit) > L2CAP_LE_CREDIT_MAX) { 1112 /* we have received credits more than max coc credits, 1113 * so disconnecting the Le Coc Channel 1114 */ 1115 l2cble_send_peer_disc_req(p_ccb); 1116 } else { 1117 p_ccb->peer_conn_cfg.credits += *credit; 1118 1119 tL2CA_CREDITS_RECEIVED_CB* cr_cb = 1120 p_ccb->p_rcb->api.pL2CA_CreditsReceived_Cb; 1121 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE && (cr_cb)) { 1122 (*cr_cb)(p_ccb->local_cid, *credit, p_ccb->peer_conn_cfg.credits); 1123 } 1124 l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL); 1125 } 1126 break; 1127 } 1128 } 1129 1130 /******************************************************************************* 1131 * 1132 * Function l2c_csm_w4_l2cap_disconnect_rsp 1133 * 1134 * Description This function handles events when the channel is in 1135 * CST_W4_L2CAP_DISCONNECT_RSP state. 1136 * 1137 * Returns void 1138 * 1139 ******************************************************************************/ 1140 static void l2c_csm_w4_l2cap_disconnect_rsp(tL2C_CCB* p_ccb, uint16_t event, 1141 void* p_data) { 1142 tL2CA_DISCONNECT_CFM_CB* disconnect_cfm = 1143 p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb; 1144 uint16_t local_cid = p_ccb->local_cid; 1145 1146 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: W4_L2CAP_DISC_RSP evt: %s", 1147 p_ccb->local_cid, l2c_csm_get_event_name(event)); 1148 1149 switch (event) { 1150 case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */ 1151 l2cu_release_ccb(p_ccb); 1152 if (disconnect_cfm) { 1153 L2CAP_TRACE_API("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", 1154 local_cid); 1155 (*disconnect_cfm)(local_cid, L2CAP_DISC_OK); 1156 } 1157 break; 1158 1159 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */ 1160 l2cu_send_peer_disc_rsp(p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, 1161 p_ccb->remote_cid); 1162 l2cu_release_ccb(p_ccb); 1163 if (disconnect_cfm) { 1164 L2CAP_TRACE_API("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", 1165 local_cid); 1166 (*disconnect_cfm)(local_cid, L2CAP_DISC_OK); 1167 } 1168 break; 1169 1170 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */ 1171 case L2CEVT_TIMEOUT: /* Timeout */ 1172 l2cu_release_ccb(p_ccb); 1173 if (disconnect_cfm) { 1174 L2CAP_TRACE_API("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", 1175 local_cid); 1176 (*disconnect_cfm)(local_cid, L2CAP_DISC_TIMEOUT); 1177 } 1178 break; 1179 1180 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 1181 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 1182 osi_free(p_data); 1183 break; 1184 } 1185 } 1186 1187 /******************************************************************************* 1188 * 1189 * Function l2c_csm_w4_l2ca_disconnect_rsp 1190 * 1191 * Description This function handles events when the channel is in 1192 * CST_W4_L2CA_DISCONNECT_RSP state. 1193 * 1194 * Returns void 1195 * 1196 ******************************************************************************/ 1197 static void l2c_csm_w4_l2ca_disconnect_rsp(tL2C_CCB* p_ccb, uint16_t event, 1198 void* p_data) { 1199 tL2CA_DISCONNECT_IND_CB* disconnect_ind = 1200 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb; 1201 uint16_t local_cid = p_ccb->local_cid; 1202 1203 L2CAP_TRACE_EVENT("L2CAP - LCID: 0x%04x st: W4_L2CA_DISC_RSP evt: %s", 1204 p_ccb->local_cid, l2c_csm_get_event_name(event)); 1205 1206 switch (event) { 1207 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */ 1208 L2CAP_TRACE_API( 1209 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", 1210 p_ccb->local_cid); 1211 l2cu_release_ccb(p_ccb); 1212 (*disconnect_ind)(local_cid, false); 1213 break; 1214 1215 case L2CEVT_TIMEOUT: 1216 l2cu_send_peer_disc_rsp(p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, 1217 p_ccb->remote_cid); 1218 L2CAP_TRACE_API( 1219 "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", 1220 p_ccb->local_cid); 1221 l2cu_release_ccb(p_ccb); 1222 (*disconnect_ind)(local_cid, false); 1223 break; 1224 1225 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper disconnect request */ 1226 case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper disconnect response */ 1227 l2cu_send_peer_disc_rsp(p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, 1228 p_ccb->remote_cid); 1229 l2cu_release_ccb(p_ccb); 1230 break; 1231 1232 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 1233 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 1234 osi_free(p_data); 1235 break; 1236 } 1237 } 1238 1239 /******************************************************************************* 1240 * 1241 * Function l2c_csm_get_event_name 1242 * 1243 * Description This function returns the event name. 1244 * 1245 * NOTE conditionally compiled to save memory. 1246 * 1247 * Returns pointer to the name 1248 * 1249 ******************************************************************************/ 1250 static const char* l2c_csm_get_event_name(uint16_t event) { 1251 switch (event) { 1252 case L2CEVT_LP_CONNECT_CFM: /* Lower layer connect confirm */ 1253 return ("LOWER_LAYER_CONNECT_CFM"); 1254 case L2CEVT_LP_CONNECT_CFM_NEG: /* Lower layer connect confirm (failed) */ 1255 return ("LOWER_LAYER_CONNECT_CFM_NEG"); 1256 case L2CEVT_LP_CONNECT_IND: /* Lower layer connect indication */ 1257 return ("LOWER_LAYER_CONNECT_IND"); 1258 case L2CEVT_LP_DISCONNECT_IND: /* Lower layer disconnect indication */ 1259 return ("LOWER_LAYER_DISCONNECT_IND"); 1260 case L2CEVT_LP_QOS_CFM: /* Lower layer QOS confirmation */ 1261 return ("LOWER_LAYER_QOS_CFM"); 1262 case L2CEVT_LP_QOS_CFM_NEG: /* Lower layer QOS confirmation (failed)*/ 1263 return ("LOWER_LAYER_QOS_CFM_NEG"); 1264 case L2CEVT_LP_QOS_VIOLATION_IND: /* Lower layer QOS violation indication */ 1265 return ("LOWER_LAYER_QOS_VIOLATION_IND"); 1266 1267 case L2CEVT_SEC_COMP: /* Security cleared successfully */ 1268 return ("SECURITY_COMPLETE"); 1269 case L2CEVT_SEC_COMP_NEG: /* Security procedure failed */ 1270 return ("SECURITY_COMPLETE_NEG"); 1271 1272 case L2CEVT_L2CAP_CONNECT_REQ: /* Peer connection request */ 1273 return ("PEER_CONNECT_REQ"); 1274 case L2CEVT_L2CAP_CONNECT_RSP: /* Peer connection response */ 1275 return ("PEER_CONNECT_RSP"); 1276 case L2CEVT_L2CAP_CONNECT_RSP_PND: /* Peer connection response pending */ 1277 return ("PEER_CONNECT_RSP_PND"); 1278 case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer connection response (failed) */ 1279 return ("PEER_CONNECT_RSP_NEG"); 1280 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer configuration request */ 1281 return ("PEER_CONFIG_REQ"); 1282 case L2CEVT_L2CAP_CONFIG_RSP: /* Peer configuration response */ 1283 return ("PEER_CONFIG_RSP"); 1284 case L2CEVT_L2CAP_CONFIG_RSP_NEG: /* Peer configuration response (failed) */ 1285 return ("PEER_CONFIG_RSP_NEG"); 1286 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */ 1287 return ("PEER_DISCONNECT_REQ"); 1288 case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */ 1289 return ("PEER_DISCONNECT_RSP"); 1290 case L2CEVT_L2CAP_DATA: /* Peer data */ 1291 return ("PEER_DATA"); 1292 1293 case L2CEVT_L2CA_CONNECT_REQ: /* Upper layer connect request */ 1294 return ("UPPER_LAYER_CONNECT_REQ"); 1295 case L2CEVT_L2CA_CONNECT_RSP: /* Upper layer connect response */ 1296 return ("UPPER_LAYER_CONNECT_RSP"); 1297 case L2CEVT_L2CA_CONNECT_RSP_NEG: /* Upper layer connect response (failed)*/ 1298 return ("UPPER_LAYER_CONNECT_RSP_NEG"); 1299 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config request */ 1300 return ("UPPER_LAYER_CONFIG_REQ"); 1301 case L2CEVT_L2CA_CONFIG_RSP: /* Upper layer config response */ 1302 return ("UPPER_LAYER_CONFIG_RSP"); 1303 case L2CEVT_L2CA_CONFIG_RSP_NEG: /* Upper layer config response (failed) */ 1304 return ("UPPER_LAYER_CONFIG_RSP_NEG"); 1305 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper layer disconnect request */ 1306 return ("UPPER_LAYER_DISCONNECT_REQ"); 1307 case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper layer disconnect response */ 1308 return ("UPPER_LAYER_DISCONNECT_RSP"); 1309 case L2CEVT_L2CA_DATA_READ: /* Upper layer data read */ 1310 return ("UPPER_LAYER_DATA_READ"); 1311 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data write */ 1312 return ("UPPER_LAYER_DATA_WRITE"); 1313 case L2CEVT_TIMEOUT: /* Timeout */ 1314 return ("TIMEOUT"); 1315 case L2CEVT_SEC_RE_SEND_CMD: 1316 return ("SEC_RE_SEND_CMD"); 1317 case L2CEVT_L2CAP_INFO_RSP: /* Peer information response */ 1318 return ("L2CEVT_L2CAP_INFO_RSP"); 1319 case L2CEVT_ACK_TIMEOUT: 1320 return ("L2CEVT_ACK_TIMEOUT"); 1321 case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT: /* Upper layer send credit packet 1322 */ 1323 return ("SEND_FLOW_CONTROL_CREDIT"); 1324 case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT: /* Peer send credit packet */ 1325 return ("RECV_FLOW_CONTROL_CREDIT"); 1326 1327 default: 1328 return ("???? UNKNOWN EVENT"); 1329 } 1330 } 1331 1332 /******************************************************************************* 1333 * 1334 * Function l2c_enqueue_peer_data 1335 * 1336 * Description Enqueues data destined for the peer in the ccb. Handles 1337 * FCR segmentation and checks for congestion. 1338 * 1339 * Returns void 1340 * 1341 ******************************************************************************/ 1342 void l2c_enqueue_peer_data(tL2C_CCB* p_ccb, BT_HDR* p_buf) { 1343 uint8_t* p; 1344 1345 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) { 1346 p_buf->event = 0; 1347 } else { 1348 /* Save the channel ID for faster counting */ 1349 p_buf->event = p_ccb->local_cid; 1350 1351 /* Step back to add the L2CAP header */ 1352 p_buf->offset -= L2CAP_PKT_OVERHEAD; 1353 p_buf->len += L2CAP_PKT_OVERHEAD; 1354 1355 /* Set the pointer to the beginning of the data */ 1356 p = (uint8_t*)(p_buf + 1) + p_buf->offset; 1357 1358 /* Now the L2CAP header */ 1359 UINT16_TO_STREAM(p, p_buf->len - L2CAP_PKT_OVERHEAD); 1360 UINT16_TO_STREAM(p, p_ccb->remote_cid); 1361 } 1362 1363 if (p_ccb->xmit_hold_q == NULL) { 1364 L2CAP_TRACE_ERROR( 1365 "%s: empty queue: p_ccb = %p p_ccb->in_use = %d p_ccb->chnl_state = %d " 1366 "p_ccb->local_cid = %u p_ccb->remote_cid = %u", 1367 __func__, p_ccb, p_ccb->in_use, p_ccb->chnl_state, p_ccb->local_cid, 1368 p_ccb->remote_cid); 1369 } 1370 fixed_queue_enqueue(p_ccb->xmit_hold_q, p_buf); 1371 1372 l2cu_check_channel_congestion(p_ccb); 1373 1374 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) 1375 /* if new packet is higher priority than serving ccb and it is not overrun */ 1376 if ((p_ccb->p_lcb->rr_pri > p_ccb->ccb_priority) && 1377 (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota > 0)) { 1378 /* send out higher priority packet */ 1379 p_ccb->p_lcb->rr_pri = p_ccb->ccb_priority; 1380 } 1381 #endif 1382 1383 /* if we are doing a round robin scheduling, set the flag */ 1384 if (p_ccb->p_lcb->link_xmit_quota == 0) l2cb.check_round_robin = true; 1385 } 1386