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