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