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 state machine and action routines for multiplexer 22 * channel of the RFCOMM unit 23 * 24 ******************************************************************************/ 25 #include <string.h> 26 #include "gki.h" 27 #include "bt_types.h" 28 #include "rfcdefs.h" 29 #include "l2cdefs.h" 30 #include "port_api.h" 31 #include "port_int.h" 32 #include "l2c_api.h" 33 #include "rfc_int.h" 34 35 #define L2CAP_SUCCESS 0 36 #define L2CAP_ERROR 1 37 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 rfc_mx_sm_state_idle (tRFC_MCB *p_mcb, UINT16 event, void *p_data); 43 static void rfc_mx_sm_state_wait_conn_cnf (tRFC_MCB *p_mcb, UINT16 event, void *p_data); 44 static void rfc_mx_sm_state_configure (tRFC_MCB *p_mcb, UINT16 event, void *p_data); 45 static void rfc_mx_sm_sabme_wait_ua (tRFC_MCB *p_mcb, UINT16 event, void *p_data); 46 static void rfc_mx_sm_state_wait_sabme (tRFC_MCB *p_mcb, UINT16 event, void *p_data); 47 static void rfc_mx_sm_state_connected (tRFC_MCB *p_mcb, UINT16 event, void *p_data); 48 static void rfc_mx_sm_state_disc_wait_ua (tRFC_MCB *p_mcb, UINT16 event, void *p_data); 49 50 static void rfc_mx_send_config_req (tRFC_MCB *p_mcb); 51 static void rfc_mx_conf_ind (tRFC_MCB *p_mcb, tL2CAP_CFG_INFO *p_cfg); 52 static void rfc_mx_conf_cnf (tRFC_MCB *p_mcb, tL2CAP_CFG_INFO *p_cfg); 53 54 55 56 /******************************************************************************* 57 ** 58 ** Function rfc_mx_sm_execute 59 ** 60 ** Description This function sends multiplexor events through the state 61 ** machine. 62 ** 63 ** Returns void 64 ** 65 *******************************************************************************/ 66 void rfc_mx_sm_execute (tRFC_MCB *p_mcb, UINT16 event, void *p_data) 67 { 68 switch (p_mcb->state) 69 { 70 case RFC_MX_STATE_IDLE: 71 rfc_mx_sm_state_idle (p_mcb, event, p_data); 72 break; 73 74 case RFC_MX_STATE_WAIT_CONN_CNF: 75 rfc_mx_sm_state_wait_conn_cnf (p_mcb, event, p_data); 76 break; 77 78 case RFC_MX_STATE_CONFIGURE: 79 rfc_mx_sm_state_configure (p_mcb, event, p_data); 80 break; 81 82 case RFC_MX_STATE_SABME_WAIT_UA: 83 rfc_mx_sm_sabme_wait_ua (p_mcb, event, p_data); 84 break; 85 86 case RFC_MX_STATE_WAIT_SABME: 87 rfc_mx_sm_state_wait_sabme (p_mcb, event, p_data); 88 break; 89 90 case RFC_MX_STATE_CONNECTED: 91 rfc_mx_sm_state_connected (p_mcb, event, p_data); 92 break; 93 94 case RFC_MX_STATE_DISC_WAIT_UA: 95 rfc_mx_sm_state_disc_wait_ua (p_mcb, event, p_data); 96 break; 97 98 } 99 } 100 101 102 /******************************************************************************* 103 ** 104 ** Function rfc_mx_sm_state_idle 105 ** 106 ** Description This function handles events when the multiplexer is in 107 ** IDLE state. This state exists when connection is being 108 ** initially established. 109 ** 110 ** Returns void 111 ** 112 *******************************************************************************/ 113 void rfc_mx_sm_state_idle (tRFC_MCB *p_mcb, UINT16 event, void *p_data) 114 { 115 RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_idle - evt:%d", event); 116 switch (event) 117 { 118 case RFC_MX_EVENT_START_REQ: 119 120 /* Initialize L2CAP MTU */ 121 p_mcb->peer_l2cap_mtu = L2CAP_DEFAULT_MTU - RFCOMM_MIN_OFFSET - 1; 122 123 if ((p_mcb->lcid = L2CA_ConnectReq (BT_PSM_RFCOMM, p_mcb->bd_addr)) == 0) 124 { 125 PORT_StartCnf (p_mcb, RFCOMM_ERROR); 126 return; 127 } 128 /* Save entry for quicker access to mcb based on the LCID */ 129 rfc_save_lcid_mcb (p_mcb, p_mcb->lcid); 130 131 p_mcb->state = RFC_MX_STATE_WAIT_CONN_CNF; 132 return; 133 134 case RFC_MX_EVENT_START_RSP: 135 case RFC_MX_EVENT_CONN_CNF: 136 case RFC_MX_EVENT_CONF_IND: 137 case RFC_MX_EVENT_CONF_CNF: 138 RFCOMM_TRACE_ERROR2 ("Mx error state %d event %d", p_mcb->state, event); 139 return; 140 141 case RFC_MX_EVENT_CONN_IND: 142 143 rfc_timer_start (p_mcb, RFCOMM_CONN_TIMEOUT); 144 L2CA_ConnectRsp (p_mcb->bd_addr, *((UINT8 *)p_data), p_mcb->lcid, L2CAP_CONN_OK, 0); 145 146 rfc_mx_send_config_req (p_mcb); 147 148 p_mcb->state = RFC_MX_STATE_CONFIGURE; 149 return; 150 151 case RFC_EVENT_SABME: 152 break; 153 154 case RFC_EVENT_UA: 155 case RFC_EVENT_DM: 156 return; 157 158 case RFC_EVENT_DISC: 159 rfc_send_dm (p_mcb, RFCOMM_MX_DLCI, TRUE); 160 return; 161 162 case RFC_EVENT_UIH: 163 rfc_send_dm (p_mcb, RFCOMM_MX_DLCI, FALSE); 164 return; 165 } 166 RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); 167 } 168 169 170 /******************************************************************************* 171 ** 172 ** Function rfc_mx_sm_state_wait_conn_cnf 173 ** 174 ** Description This function handles events when the multiplexer is 175 ** waiting for Connection Confirm from L2CAP. 176 ** 177 ** Returns void 178 ** 179 *******************************************************************************/ 180 void rfc_mx_sm_state_wait_conn_cnf (tRFC_MCB *p_mcb, UINT16 event, void *p_data) 181 { 182 RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_wait_conn_cnf - evt:%d", event); 183 switch (event) 184 { 185 case RFC_MX_EVENT_START_REQ: 186 RFCOMM_TRACE_ERROR2 ("Mx error state %d event %d", p_mcb->state, event); 187 return; 188 189 /* There is some new timing so that Config Ind comes before security is completed 190 so we are still waiting fo the confirmation. */ 191 case RFC_MX_EVENT_CONF_IND: 192 rfc_mx_conf_ind (p_mcb, (tL2CAP_CFG_INFO *)p_data); 193 return; 194 195 case RFC_MX_EVENT_CONN_CNF: 196 if (*((UINT16 *)p_data) != L2CAP_SUCCESS) 197 { 198 p_mcb->state = RFC_MX_STATE_IDLE; 199 200 PORT_StartCnf (p_mcb, *((UINT16 *)p_data)); 201 return; 202 } 203 p_mcb->state = RFC_MX_STATE_CONFIGURE; 204 rfc_mx_send_config_req (p_mcb); 205 return; 206 207 case RFC_MX_EVENT_DISC_IND: 208 p_mcb->state = RFC_MX_STATE_IDLE; 209 PORT_CloseInd (p_mcb); 210 return; 211 212 case RFC_EVENT_TIMEOUT: 213 p_mcb->state = RFC_MX_STATE_IDLE; 214 L2CA_DisconnectReq (p_mcb->lcid); 215 216 /* we gave up outgoing connection request then try peer's request */ 217 if (p_mcb->pending_lcid) 218 { 219 UINT16 i; 220 UINT8 idx; 221 222 RFCOMM_TRACE_DEBUG2 ("RFCOMM MX retry as acceptor in collision case - evt:%d in state:%d", event, p_mcb->state); 223 224 rfc_save_lcid_mcb (NULL, p_mcb->lcid); 225 p_mcb->lcid = p_mcb->pending_lcid; 226 rfc_save_lcid_mcb (p_mcb, p_mcb->lcid); 227 228 p_mcb->is_initiator = FALSE; 229 230 /* update direction bit */ 231 for (i = 0; i < RFCOMM_MAX_DLCI; i += 2) 232 { 233 if ((idx = p_mcb->port_inx[i]) != 0) 234 { 235 p_mcb->port_inx[i] = 0; 236 p_mcb->port_inx[i+1] = idx; 237 rfc_cb.port.port[idx - 1].dlci += 1; 238 RFCOMM_TRACE_DEBUG2 ("RFCOMM MX - DLCI:%d -> %d", i, rfc_cb.port.port[idx - 1].dlci); 239 } 240 } 241 242 rfc_mx_sm_execute (p_mcb, RFC_MX_EVENT_CONN_IND, &(p_mcb->pending_id)); 243 } 244 else 245 { 246 PORT_CloseInd (p_mcb); 247 } 248 return; 249 } 250 RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); 251 } 252 253 254 /******************************************************************************* 255 ** 256 ** Function rfc_mx_sm_state_configure 257 ** 258 ** Description This function handles events when the multiplexer in the 259 ** configuration state. 260 ** 261 ** Returns void 262 ** 263 *******************************************************************************/ 264 void rfc_mx_sm_state_configure (tRFC_MCB *p_mcb, UINT16 event, void *p_data) 265 { 266 RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_configure - evt:%d", event); 267 switch (event) 268 { 269 case RFC_MX_EVENT_START_REQ: 270 case RFC_MX_EVENT_CONN_CNF: 271 272 RFCOMM_TRACE_ERROR2 ("Mx error state %d event %d", p_mcb->state, event); 273 return; 274 275 case RFC_MX_EVENT_CONF_IND: 276 rfc_mx_conf_ind (p_mcb, (tL2CAP_CFG_INFO *)p_data); 277 return; 278 279 case RFC_MX_EVENT_CONF_CNF: 280 rfc_mx_conf_cnf (p_mcb, (tL2CAP_CFG_INFO *)p_data); 281 return; 282 283 case RFC_MX_EVENT_DISC_IND: 284 p_mcb->state = RFC_MX_STATE_IDLE; 285 PORT_CloseInd (p_mcb); 286 return; 287 288 case RFC_EVENT_TIMEOUT: 289 p_mcb->state = RFC_MX_STATE_IDLE; 290 L2CA_DisconnectReq (p_mcb->lcid); 291 292 PORT_StartCnf (p_mcb, RFCOMM_ERROR); 293 return; 294 } 295 RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); 296 } 297 298 299 /******************************************************************************* 300 ** 301 ** Function rfc_mx_sm_sabme_wait_ua 302 ** 303 ** Description This function handles events when the multiplexer sent 304 ** SABME and is waiting for UA reply. 305 ** 306 ** Returns void 307 ** 308 *******************************************************************************/ 309 void rfc_mx_sm_sabme_wait_ua (tRFC_MCB *p_mcb, UINT16 event, void *p_data) 310 { 311 RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_sabme_wait_ua - evt:%d", event); 312 switch (event) 313 { 314 case RFC_MX_EVENT_START_REQ: 315 case RFC_MX_EVENT_CONN_CNF: 316 RFCOMM_TRACE_ERROR2 ("Mx error state %d event %d", p_mcb->state, event); 317 return; 318 319 /* workaround: we don't support reconfig */ 320 /* commented out until we support reconfig 321 case RFC_MX_EVENT_CONF_IND: 322 rfc_mx_conf_ind (p_mcb, (tL2CAP_CFG_INFO *)p_data); 323 return; 324 325 case RFC_MX_EVENT_CONF_CNF: 326 rfc_mx_conf_cnf (p_mcb, (tL2CAP_CFG_INFO *)p_data); 327 return; 328 */ 329 330 case RFC_MX_EVENT_DISC_IND: 331 p_mcb->state = RFC_MX_STATE_IDLE; 332 PORT_CloseInd (p_mcb); 333 return; 334 335 case RFC_EVENT_UA: 336 rfc_timer_stop (p_mcb); 337 338 p_mcb->state = RFC_MX_STATE_CONNECTED; 339 p_mcb->peer_ready = TRUE; 340 341 PORT_StartCnf (p_mcb, RFCOMM_SUCCESS); 342 return; 343 344 case RFC_EVENT_DM: 345 rfc_timer_stop (p_mcb); 346 /* Case falls through */ 347 348 case RFC_MX_EVENT_CONF_IND: /* workaround: we don't support reconfig */ 349 case RFC_MX_EVENT_CONF_CNF: /* workaround: we don't support reconfig */ 350 case RFC_EVENT_TIMEOUT: 351 p_mcb->state = RFC_MX_STATE_IDLE; 352 L2CA_DisconnectReq (p_mcb->lcid); 353 354 PORT_StartCnf (p_mcb, RFCOMM_ERROR); 355 return; 356 } 357 RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); 358 } 359 360 /******************************************************************************* 361 ** 362 ** Function rfc_mx_sm_state_wait_sabme 363 ** 364 ** Description This function handles events when the multiplexer is 365 ** waiting for SABME on the acceptor side after configuration 366 ** 367 ** Returns void 368 ** 369 *******************************************************************************/ 370 void rfc_mx_sm_state_wait_sabme (tRFC_MCB *p_mcb, UINT16 event, void *p_data) 371 { 372 RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_wait_sabme - evt:%d", event); 373 switch (event) 374 { 375 case RFC_MX_EVENT_DISC_IND: 376 p_mcb->state = RFC_MX_STATE_IDLE; 377 PORT_CloseInd (p_mcb); 378 return; 379 380 case RFC_EVENT_SABME: 381 /* if we gave up outgoing connection request */ 382 if (p_mcb->pending_lcid) 383 { 384 p_mcb->pending_lcid = 0; 385 386 rfc_send_ua (p_mcb, RFCOMM_MX_DLCI); 387 388 rfc_timer_stop (p_mcb); 389 p_mcb->state = RFC_MX_STATE_CONNECTED; 390 p_mcb->peer_ready = TRUE; 391 392 /* MX channel collision has been resolved, continue to open ports */ 393 PORT_StartCnf (p_mcb, RFCOMM_SUCCESS); 394 } 395 else 396 { 397 rfc_timer_stop (p_mcb); 398 PORT_StartInd (p_mcb); 399 } 400 return; 401 402 case RFC_MX_EVENT_START_RSP: 403 if (*((UINT16 *)p_data) != RFCOMM_SUCCESS) 404 rfc_send_dm (p_mcb, RFCOMM_MX_DLCI, TRUE); 405 else 406 { 407 rfc_send_ua (p_mcb, RFCOMM_MX_DLCI); 408 409 p_mcb->state = RFC_MX_STATE_CONNECTED; 410 p_mcb->peer_ready = TRUE; 411 } 412 return; 413 414 case RFC_MX_EVENT_CONF_IND: /* workaround: we don't support reconfig */ 415 case RFC_MX_EVENT_CONF_CNF: /* workaround: we don't support reconfig */ 416 case RFC_EVENT_TIMEOUT: 417 p_mcb->state = RFC_MX_STATE_IDLE; 418 L2CA_DisconnectReq (p_mcb->lcid); 419 420 PORT_CloseInd (p_mcb); 421 return; 422 } 423 RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); 424 } 425 426 427 /******************************************************************************* 428 ** 429 ** Function rfc_mx_sm_state_connected 430 ** 431 ** Description This function handles events when the multiplexer is 432 ** in the CONNECTED state 433 ** 434 ** Returns void 435 ** 436 *******************************************************************************/ 437 void rfc_mx_sm_state_connected (tRFC_MCB *p_mcb, UINT16 event, void *p_data) 438 { 439 RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_connected - evt:%d", event); 440 441 switch (event) 442 { 443 case RFC_EVENT_TIMEOUT: 444 case RFC_MX_EVENT_CLOSE_REQ: 445 rfc_timer_start (p_mcb, RFC_DISC_TIMEOUT); 446 p_mcb->state = RFC_MX_STATE_DISC_WAIT_UA; 447 rfc_send_disc (p_mcb, RFCOMM_MX_DLCI); 448 return; 449 450 case RFC_MX_EVENT_DISC_IND: 451 p_mcb->state = RFC_MX_STATE_IDLE; 452 PORT_CloseInd (p_mcb); 453 return; 454 455 case RFC_EVENT_DISC: 456 /* Reply with UA. If initiator bring down L2CAP connection */ 457 /* If server wait for some time if client decide to reinitiate channel */ 458 rfc_send_ua (p_mcb, RFCOMM_MX_DLCI); 459 if (p_mcb->is_initiator) 460 { 461 L2CA_DisconnectReq (p_mcb->lcid); 462 } 463 /* notify all ports that connection is gone */ 464 PORT_CloseInd (p_mcb); 465 return; 466 } 467 RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); 468 } 469 470 471 /******************************************************************************* 472 ** 473 ** Function rfc_mx_sm_state_disc_wait_ua 474 ** 475 ** Description This function handles events when the multiplexer sent 476 ** DISC and is waiting for UA reply. 477 ** 478 ** Returns void 479 ** 480 *******************************************************************************/ 481 void rfc_mx_sm_state_disc_wait_ua (tRFC_MCB *p_mcb, UINT16 event, void *p_data) 482 { 483 BT_HDR *p_buf; 484 485 RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_disc_wait_ua - evt:%d", event); 486 switch (event) 487 { 488 case RFC_EVENT_UA: 489 case RFC_EVENT_DM: 490 case RFC_EVENT_TIMEOUT: 491 L2CA_DisconnectReq (p_mcb->lcid); 492 493 if (p_mcb->restart_required) 494 { 495 /* Start Request was received while disconnecting. Execute it again */ 496 if ((p_mcb->lcid = L2CA_ConnectReq (BT_PSM_RFCOMM, p_mcb->bd_addr)) == 0) 497 { 498 PORT_StartCnf (p_mcb, RFCOMM_ERROR); 499 return; 500 } 501 /* Save entry for quicker access to mcb based on the LCID */ 502 rfc_save_lcid_mcb (p_mcb, p_mcb->lcid); 503 504 /* clean up before reuse it */ 505 while ((p_buf = (BT_HDR *)GKI_dequeue(&p_mcb->cmd_q)) != NULL) 506 GKI_freebuf(p_buf); 507 508 rfc_timer_start (p_mcb, RFC_MCB_INIT_INACT_TIMER); 509 510 p_mcb->is_initiator = TRUE; 511 p_mcb->restart_required = FALSE; 512 p_mcb->local_cfg_sent = FALSE; 513 p_mcb->peer_cfg_rcvd = FALSE; 514 515 p_mcb->state = RFC_MX_STATE_WAIT_CONN_CNF; 516 return; 517 } 518 rfc_release_multiplexer_channel (p_mcb); 519 return; 520 521 case RFC_EVENT_DISC: 522 rfc_send_ua (p_mcb, RFCOMM_MX_DLCI); 523 return; 524 525 case RFC_EVENT_UIH: 526 GKI_freebuf (p_data); 527 rfc_send_dm (p_mcb, RFCOMM_MX_DLCI, FALSE); 528 return; 529 530 case RFC_MX_EVENT_START_REQ: 531 p_mcb->restart_required = TRUE; 532 return; 533 534 case RFC_MX_EVENT_DISC_IND: 535 p_mcb->state = RFC_MX_STATE_IDLE; 536 PORT_CloseInd (p_mcb); 537 return; 538 539 case RFC_MX_EVENT_CLOSE_REQ: 540 return; 541 542 case RFC_MX_EVENT_QOS_VIOLATION_IND: 543 break; 544 } 545 RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); 546 } 547 548 549 /******************************************************************************* 550 ** 551 ** Function rfc_mx_send_config_req 552 ** 553 ** Description This function handles L2CA_ConnectInd message from the 554 ** L2CAP. Accept connection. 555 ** 556 *******************************************************************************/ 557 static void rfc_mx_send_config_req (tRFC_MCB *p_mcb) 558 { 559 tL2CAP_CFG_INFO cfg; 560 561 RFCOMM_TRACE_EVENT0 ("rfc_mx_send_config_req"); 562 563 memset (&cfg, 0, sizeof (tL2CAP_CFG_INFO)); 564 565 cfg.mtu_present = TRUE; 566 cfg.mtu = L2CAP_MTU_SIZE; 567 568 /* Defaults set by memset 569 cfg.flush_to_present = FALSE; 570 cfg.qos_present = FALSE; 571 cfg.fcr_present = FALSE; 572 cfg.fcr.mode = L2CAP_FCR_BASIC_MODE; 573 cfg.fcs_present = FALSE; 574 cfg.fcs = N/A when fcs_present is FALSE; 575 */ 576 L2CA_ConfigReq (p_mcb->lcid, &cfg); 577 } 578 579 580 /******************************************************************************* 581 ** 582 ** Function rfc_mx_conf_cnf 583 ** 584 ** Description This function handles L2CA_ConfigCnf message from the 585 ** L2CAP. If result is not success tell upper layer that 586 ** start has not been accepted. If initiator send SABME 587 ** on DLCI 0. T1 is still running. 588 ** 589 *******************************************************************************/ 590 static void rfc_mx_conf_cnf (tRFC_MCB *p_mcb, tL2CAP_CFG_INFO *p_cfg) 591 { 592 RFCOMM_TRACE_EVENT2 ("rfc_mx_conf_cnf p_cfg:%08x res:%d ", p_cfg, (p_cfg) ? p_cfg->result : 0); 593 594 if (p_cfg->result != L2CAP_CFG_OK) 595 { 596 if (p_mcb->is_initiator) 597 { 598 PORT_StartCnf (p_mcb, p_cfg->result); 599 L2CA_DisconnectReq (p_mcb->lcid); 600 } 601 rfc_release_multiplexer_channel (p_mcb); 602 return; 603 } 604 605 p_mcb->local_cfg_sent = TRUE; 606 if ((p_mcb->state == RFC_MX_STATE_CONFIGURE) && p_mcb->peer_cfg_rcvd) 607 { 608 if (p_mcb->is_initiator) 609 { 610 p_mcb->state = RFC_MX_STATE_SABME_WAIT_UA; 611 rfc_send_sabme (p_mcb, RFCOMM_MX_DLCI); 612 rfc_timer_start (p_mcb, RFC_T1_TIMEOUT); 613 } 614 else 615 { 616 p_mcb->state = RFC_MX_STATE_WAIT_SABME; 617 rfc_timer_start (p_mcb, RFC_T2_TIMEOUT); 618 } 619 } 620 } 621 622 623 /******************************************************************************* 624 ** 625 ** Function rfc_mx_conf_ind 626 ** 627 ** Description This function handles L2CA_ConfigInd message from the 628 ** L2CAP. Send the L2CA_ConfigRsp message. 629 ** 630 *******************************************************************************/ 631 static void rfc_mx_conf_ind (tRFC_MCB *p_mcb, tL2CAP_CFG_INFO *p_cfg) 632 { 633 /* Save peer L2CAP MTU if present */ 634 /* RFCOMM adds 3-4 bytes in the beginning and 1 bytes FCS */ 635 if (p_cfg->mtu_present) 636 p_mcb->peer_l2cap_mtu = p_cfg->mtu - RFCOMM_MIN_OFFSET - 1; 637 else 638 p_mcb->peer_l2cap_mtu = L2CAP_DEFAULT_MTU - RFCOMM_MIN_OFFSET - 1; 639 640 p_cfg->mtu_present = FALSE; 641 p_cfg->flush_to_present = FALSE; 642 p_cfg->qos_present = FALSE; 643 644 p_cfg->result = L2CAP_CFG_OK; 645 646 L2CA_ConfigRsp (p_mcb->lcid, p_cfg); 647 648 p_mcb->peer_cfg_rcvd = TRUE; 649 if ((p_mcb->state == RFC_MX_STATE_CONFIGURE) && p_mcb->local_cfg_sent) 650 { 651 if (p_mcb->is_initiator) 652 { 653 p_mcb->state = RFC_MX_STATE_SABME_WAIT_UA; 654 rfc_send_sabme (p_mcb, RFCOMM_MX_DLCI); 655 rfc_timer_start (p_mcb, RFC_T1_TIMEOUT); 656 } 657 else 658 { 659 p_mcb->state = RFC_MX_STATE_WAIT_SABME; 660 rfc_timer_start (p_mcb, RFC_T2_TIMEOUT); 661 } 662 } 663 } 664