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 40extern 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/********************************************************************************/ 45static void l2c_csm_closed (tL2C_CCB *p_ccb, UINT16 event, void *p_data); 46static void l2c_csm_orig_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data); 47static void l2c_csm_term_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data); 48static void l2c_csm_w4_l2cap_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data); 49static void l2c_csm_w4_l2ca_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data); 50static void l2c_csm_config (tL2C_CCB *p_ccb, UINT16 event, void *p_data); 51static void l2c_csm_open (tL2C_CCB *p_ccb, UINT16 event, void *p_data); 52static void l2c_csm_w4_l2cap_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data); 53static void l2c_csm_w4_l2ca_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data); 54 55#if (BT_TRACE_VERBOSE == TRUE) 56static 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*******************************************************************************/ 68void 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*******************************************************************************/ 125static 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 212Event uninit_use_in_call: Using uninitialized value "settings" (field "settings".timeout uninitialized) in call to function "BTM_SetPowerMode" [details] 213Event uninit_use_in_call: Using uninitialized value "settings.max" in call to function "BTM_SetPowerMode" [details] 214Event 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 275Event uninit_use_in_call: Using uninitialized value "settings" (field "settings".timeout uninitialized) in call to function "BTM_SetPowerMode" [details] 276Event uninit_use_in_call: Using uninitialized value "settings.max" in call to function "BTM_SetPowerMode" [details] 277Event 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*******************************************************************************/ 327static 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*******************************************************************************/ 445static 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*******************************************************************************/ 572static 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*******************************************************************************/ 702static 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*******************************************************************************/ 820static 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*******************************************************************************/ 1070static 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*******************************************************************************/ 1262static 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*******************************************************************************/ 1327static 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*******************************************************************************/ 1379static 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*******************************************************************************/ 1474void 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