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