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