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