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_ERROR2 ("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_ERROR2 ("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_EVENT2 ("L2CAP - LCID: 0x%04x st: CLOSED evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event)); 155 #else 156 L2CAP_TRACE_EVENT1 ("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_API1 ("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_API2 ("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_API2 ("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_API2 ("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_EVENT2 ("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_EVENT1 ("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_API1 ("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_API2 ("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_EVENT2 ("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_EVENT1 ("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_API1 ("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_API1 ("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_EVENT2 ("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_EVENT1 ("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_API1 ("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_API1 ("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_API1 ("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_API2 ("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_API1 ("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_EVENT2 ("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_EVENT1 ("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_API1 ("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_API1 ("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_API1 ("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_EVENT2 ("L2CAP - LCID: 0x%04x st: CONFIG evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event)); 712 #else 713 L2CAP_TRACE_EVENT1 ("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_API1 ("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_EVENT2 ("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_EVENT0 ("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_EVENT0 ("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_WARNING1 ("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_API1 ("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_API2 ("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_API1 ("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_WARNING1 ("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_API1 ("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_BASE_APPL_CID) 896 { 897 if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb) 898 (*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); 899 else 900 GKI_freebuf (p_data); 901 902 break; 903 } 904 #endif 905 (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR *)p_data); 906 break; 907 908 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 909 if (p_ccb->config_done & OB_CFG_DONE) 910 l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data); 911 else 912 GKI_freebuf (p_data); 913 break; 914 915 case L2CEVT_TIMEOUT: 916 l2cu_send_peer_disc_req (p_ccb); 917 L2CAP_TRACE_API1 ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid); 918 l2cu_release_ccb (p_ccb); 919 (*disconnect_ind)(local_cid, FALSE); 920 break; 921 } 922 } 923 924 925 /******************************************************************************* 926 ** 927 ** Function l2c_csm_open 928 ** 929 ** Description This function handles events when the channel is in 930 ** OPEN state. 931 ** 932 ** Returns void 933 ** 934 *******************************************************************************/ 935 static void l2c_csm_open (tL2C_CCB *p_ccb, UINT16 event, void *p_data) 936 { 937 UINT16 local_cid = p_ccb->local_cid; 938 tL2CAP_CFG_INFO *p_cfg; 939 tL2C_CHNL_STATE tempstate; 940 UINT8 tempcfgdone; 941 UINT8 cfg_result; 942 943 #if (BT_TRACE_VERBOSE == TRUE) 944 L2CAP_TRACE_EVENT2 ("L2CAP - LCID: 0x%04x st: OPEN evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event)); 945 #else 946 L2CAP_TRACE_EVENT1 ("L2CAP - st: OPEN evt: %d", event); 947 #endif 948 949 #if (L2CAP_UCD_INCLUDED == TRUE) 950 if ( local_cid == L2CAP_CONNECTIONLESS_CID ) 951 { 952 /* check if this event can be processed by UCD */ 953 if ( l2c_ucd_process_event (p_ccb, event, p_data) ) 954 { 955 /* The event is processed by UCD state machine */ 956 return; 957 } 958 } 959 #endif 960 961 switch (event) 962 { 963 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */ 964 L2CAP_TRACE_API1 ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", 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 #if BTM_PWR_MGR_INCLUDED == TRUE 1013 { 1014 tBTM_PM_PWR_MD 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 #else 1019 BTM_CancelSniffMode (p_ccb->p_lcb->remote_bd_addr); 1020 #endif 1021 // btla-specific -- 1022 1023 p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP; 1024 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT); 1025 L2CAP_TRACE_API1 ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x Conf Needed", p_ccb->local_cid); 1026 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, TRUE); 1027 break; 1028 1029 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 1030 (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR *)p_data); 1031 break; 1032 1033 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */ 1034 /* Make sure we are not in sniff mode */ 1035 #if BTM_PWR_MGR_INCLUDED == TRUE 1036 { 1037 tBTM_PM_PWR_MD settings; 1038 settings.mode = BTM_PM_MD_ACTIVE; 1039 BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings); 1040 } 1041 #else 1042 BTM_CancelSniffMode (p_ccb->p_lcb->remote_bd_addr); 1043 #endif 1044 1045 l2cu_send_peer_disc_req (p_ccb); 1046 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP; 1047 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT); 1048 break; 1049 1050 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 1051 l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data); 1052 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL); 1053 break; 1054 1055 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */ 1056 p_ccb->chnl_state = CST_CONFIG; 1057 p_ccb->config_done &= ~CFG_DONE_MASK; 1058 l2cu_process_our_cfg_req (p_ccb, (tL2CAP_CFG_INFO *)p_data); 1059 l2cu_send_peer_config_req (p_ccb, (tL2CAP_CFG_INFO *)p_data); 1060 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT); 1061 break; 1062 1063 case L2CEVT_TIMEOUT: 1064 /* Process the monitor/retransmission time-outs in flow control/retrans mode */ 1065 if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) 1066 l2c_fcr_proc_tout (p_ccb); 1067 break; 1068 1069 case L2CEVT_ACK_TIMEOUT: 1070 l2c_fcr_proc_ack_tout (p_ccb); 1071 break; 1072 } 1073 } 1074 1075 1076 /******************************************************************************* 1077 ** 1078 ** Function l2c_csm_w4_l2cap_disconnect_rsp 1079 ** 1080 ** Description This function handles events when the channel is in 1081 ** CST_W4_L2CAP_DISCONNECT_RSP state. 1082 ** 1083 ** Returns void 1084 ** 1085 *******************************************************************************/ 1086 static void l2c_csm_w4_l2cap_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data) 1087 { 1088 tL2CA_DISCONNECT_CFM_CB *disconnect_cfm = p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb; 1089 UINT16 local_cid = p_ccb->local_cid; 1090 1091 #if (BT_TRACE_VERBOSE == TRUE) 1092 L2CAP_TRACE_EVENT2 ("L2CAP - LCID: 0x%04x st: W4_L2CAP_DISC_RSP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event)); 1093 #else 1094 L2CAP_TRACE_EVENT1 ("L2CAP - st: W4_L2CAP_DISC_RSP evt: %d", event); 1095 #endif 1096 1097 switch (event) 1098 { 1099 case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */ 1100 l2cu_release_ccb (p_ccb); 1101 if (disconnect_cfm) 1102 { 1103 L2CAP_TRACE_API1 ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid); 1104 (*disconnect_cfm)(local_cid, L2CAP_DISC_OK); 1105 } 1106 break; 1107 1108 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */ 1109 l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid); 1110 l2cu_release_ccb (p_ccb); 1111 if (disconnect_cfm) 1112 { 1113 L2CAP_TRACE_API1 ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid); 1114 (*disconnect_cfm)(local_cid, L2CAP_DISC_OK); 1115 } 1116 break; 1117 1118 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */ 1119 case L2CEVT_TIMEOUT: /* Timeout */ 1120 l2cu_release_ccb (p_ccb); 1121 if (disconnect_cfm) 1122 { 1123 L2CAP_TRACE_API1 ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid); 1124 (*disconnect_cfm)(local_cid, L2CAP_DISC_TIMEOUT); 1125 } 1126 break; 1127 1128 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 1129 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 1130 GKI_freebuf (p_data); 1131 break; 1132 } 1133 } 1134 1135 1136 /******************************************************************************* 1137 ** 1138 ** Function l2c_csm_w4_l2ca_disconnect_rsp 1139 ** 1140 ** Description This function handles events when the channel is in 1141 ** CST_W4_L2CA_DISCONNECT_RSP state. 1142 ** 1143 ** Returns void 1144 ** 1145 *******************************************************************************/ 1146 static void l2c_csm_w4_l2ca_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data) 1147 { 1148 tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb; 1149 UINT16 local_cid = p_ccb->local_cid; 1150 1151 #if (BT_TRACE_VERBOSE == TRUE) 1152 L2CAP_TRACE_EVENT2 ("L2CAP - LCID: 0x%04x st: W4_L2CA_DISC_RSP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event)); 1153 #else 1154 L2CAP_TRACE_EVENT1 ("L2CAP - st: W4_L2CA_DISC_RSP evt: %d", event); 1155 #endif 1156 1157 switch (event) 1158 { 1159 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */ 1160 L2CAP_TRACE_API1 ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid); 1161 l2cu_release_ccb (p_ccb); 1162 (*disconnect_ind)(local_cid, FALSE); 1163 break; 1164 1165 case L2CEVT_TIMEOUT: 1166 l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid); 1167 L2CAP_TRACE_API1 ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid); 1168 l2cu_release_ccb (p_ccb); 1169 (*disconnect_ind)(local_cid, FALSE); 1170 break; 1171 1172 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper disconnect request */ 1173 case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper disconnect response */ 1174 l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid); 1175 l2cu_release_ccb (p_ccb); 1176 break; 1177 1178 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */ 1179 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */ 1180 GKI_freebuf (p_data); 1181 break; 1182 } 1183 } 1184 1185 1186 #if (BT_TRACE_VERBOSE == TRUE) 1187 /******************************************************************************* 1188 ** 1189 ** Function l2c_csm_get_event_name 1190 ** 1191 ** Description This function returns the event name. 1192 ** 1193 ** NOTE conditionally compiled to save memory. 1194 ** 1195 ** Returns pointer to the name 1196 ** 1197 *******************************************************************************/ 1198 static char *l2c_csm_get_event_name (UINT16 event) 1199 { 1200 switch (event) 1201 { 1202 case L2CEVT_LP_CONNECT_CFM: /* Lower layer connect confirm */ 1203 return ("LOWER_LAYER_CONNECT_CFM"); 1204 case L2CEVT_LP_CONNECT_CFM_NEG: /* Lower layer connect confirm (failed) */ 1205 return ("LOWER_LAYER_CONNECT_CFM_NEG"); 1206 case L2CEVT_LP_CONNECT_IND: /* Lower layer connect indication */ 1207 return ("LOWER_LAYER_CONNECT_IND"); 1208 case L2CEVT_LP_DISCONNECT_IND: /* Lower layer disconnect indication */ 1209 return ("LOWER_LAYER_DISCONNECT_IND"); 1210 case L2CEVT_LP_QOS_CFM: /* Lower layer QOS confirmation */ 1211 return ("LOWER_LAYER_QOS_CFM"); 1212 case L2CEVT_LP_QOS_CFM_NEG: /* Lower layer QOS confirmation (failed)*/ 1213 return ("LOWER_LAYER_QOS_CFM_NEG"); 1214 case L2CEVT_LP_QOS_VIOLATION_IND: /* Lower layer QOS violation indication */ 1215 return ("LOWER_LAYER_QOS_VIOLATION_IND"); 1216 1217 case L2CEVT_SEC_COMP: /* Security cleared successfully */ 1218 return ("SECURITY_COMPLETE"); 1219 case L2CEVT_SEC_COMP_NEG: /* Security procedure failed */ 1220 return ("SECURITY_COMPLETE_NEG"); 1221 1222 case L2CEVT_L2CAP_CONNECT_REQ: /* Peer connection request */ 1223 return ("PEER_CONNECT_REQ"); 1224 case L2CEVT_L2CAP_CONNECT_RSP: /* Peer connection response */ 1225 return ("PEER_CONNECT_RSP"); 1226 case L2CEVT_L2CAP_CONNECT_RSP_PND: /* Peer connection response pending */ 1227 return ("PEER_CONNECT_RSP_PND"); 1228 case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer connection response (failed) */ 1229 return ("PEER_CONNECT_RSP_NEG"); 1230 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer configuration request */ 1231 return ("PEER_CONFIG_REQ"); 1232 case L2CEVT_L2CAP_CONFIG_RSP: /* Peer configuration response */ 1233 return ("PEER_CONFIG_RSP"); 1234 case L2CEVT_L2CAP_CONFIG_RSP_NEG: /* Peer configuration response (failed) */ 1235 return ("PEER_CONFIG_RSP_NEG"); 1236 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */ 1237 return ("PEER_DISCONNECT_REQ"); 1238 case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */ 1239 return ("PEER_DISCONNECT_RSP"); 1240 case L2CEVT_L2CAP_DATA: /* Peer data */ 1241 return ("PEER_DATA"); 1242 1243 case L2CEVT_L2CA_CONNECT_REQ: /* Upper layer connect request */ 1244 return ("UPPER_LAYER_CONNECT_REQ"); 1245 case L2CEVT_L2CA_CONNECT_RSP: /* Upper layer connect response */ 1246 return ("UPPER_LAYER_CONNECT_RSP"); 1247 case L2CEVT_L2CA_CONNECT_RSP_NEG: /* Upper layer connect response (failed)*/ 1248 return ("UPPER_LAYER_CONNECT_RSP_NEG"); 1249 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config request */ 1250 return ("UPPER_LAYER_CONFIG_REQ"); 1251 case L2CEVT_L2CA_CONFIG_RSP: /* Upper layer config response */ 1252 return ("UPPER_LAYER_CONFIG_RSP"); 1253 case L2CEVT_L2CA_CONFIG_RSP_NEG: /* Upper layer config response (failed) */ 1254 return ("UPPER_LAYER_CONFIG_RSP_NEG"); 1255 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper layer disconnect request */ 1256 return ("UPPER_LAYER_DISCONNECT_REQ"); 1257 case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper layer disconnect response */ 1258 return ("UPPER_LAYER_DISCONNECT_RSP"); 1259 case L2CEVT_L2CA_DATA_READ: /* Upper layer data read */ 1260 return ("UPPER_LAYER_DATA_READ"); 1261 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data write */ 1262 return ("UPPER_LAYER_DATA_WRITE"); 1263 case L2CEVT_TIMEOUT: /* Timeout */ 1264 return ("TIMEOUT"); 1265 case L2CEVT_SEC_RE_SEND_CMD: 1266 return ("SEC_RE_SEND_CMD"); 1267 case L2CEVT_L2CAP_INFO_RSP: /* Peer information response */ 1268 return ("L2CEVT_L2CAP_INFO_RSP"); 1269 case L2CEVT_ACK_TIMEOUT: 1270 return ("L2CEVT_ACK_TIMEOUT"); 1271 1272 default: 1273 return ("???? UNKNOWN EVENT"); 1274 } 1275 } 1276 #endif /* (BT_TRACE_VERBOSE == TRUE) */ 1277 1278 1279 /******************************************************************************* 1280 ** 1281 ** Function l2c_enqueue_peer_data 1282 ** 1283 ** Description Enqueues data destined for the peer in the ccb. Handles 1284 ** FCR segmentation and checks for congestion. 1285 ** 1286 ** Returns void 1287 ** 1288 *******************************************************************************/ 1289 void l2c_enqueue_peer_data (tL2C_CCB *p_ccb, BT_HDR *p_buf) 1290 { 1291 UINT8 *p; 1292 1293 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) 1294 { 1295 p_buf->event = 0; 1296 } 1297 else 1298 { 1299 /* Save the channel ID for faster counting */ 1300 p_buf->event = p_ccb->local_cid; 1301 1302 /* Step back to add the L2CAP header */ 1303 p_buf->offset -= L2CAP_PKT_OVERHEAD; 1304 p_buf->len += L2CAP_PKT_OVERHEAD; 1305 1306 /* Set the pointer to the beginning of the data */ 1307 p = (UINT8 *)(p_buf + 1) + p_buf->offset; 1308 1309 /* Now the L2CAP header */ 1310 UINT16_TO_STREAM (p, p_buf->len - L2CAP_PKT_OVERHEAD); 1311 UINT16_TO_STREAM (p, p_ccb->remote_cid); 1312 } 1313 1314 GKI_enqueue (&p_ccb->xmit_hold_q, p_buf); 1315 1316 l2cu_check_channel_congestion (p_ccb); 1317 1318 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) 1319 /* if new packet is higher priority than serving ccb and it is not overrun */ 1320 if (( p_ccb->p_lcb->rr_pri > p_ccb->ccb_priority ) 1321 &&( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota > 0)) 1322 { 1323 /* send out higher priority packet */ 1324 p_ccb->p_lcb->rr_pri = p_ccb->ccb_priority; 1325 } 1326 #endif 1327 1328 /* if we are doing a round robin scheduling, set the flag */ 1329 if (p_ccb->p_lcb->link_xmit_quota == 0) 1330 l2cb.check_round_robin = TRUE; 1331 } 1332 1333 1334