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