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