/******************************************************************************* ** ** Function rfc_mx_conf_cnf ** ** Description This function handles L2CA_ConfigCnf message from the ** L2CAP. If result is not success tell upper layer that ** start has not been accepted. If initiator send SABME ** on DLCI 0. T1 is still running. ** *******************************************************************************/ static void rfc_mx_conf_cnf (tRFC_MCB *p_mcb, tL2CAP_CFG_INFO *p_cfg) { RFCOMM_TRACE_EVENT2 ("rfc_mx_conf_cnf p_cfg:%08x res:%d ", p_cfg, (p_cfg) ? p_cfg->result : 0); if (p_cfg->result != L2CAP_CFG_OK) { if (p_mcb->is_initiator) { PORT_StartCnf (p_mcb, p_cfg->result); L2CA_DisconnectReq (p_mcb->lcid); } rfc_release_multiplexer_channel (p_mcb); return; } p_mcb->local_cfg_sent = TRUE; if ((p_mcb->state == RFC_MX_STATE_CONFIGURE) && p_mcb->peer_cfg_rcvd) { if (p_mcb->is_initiator) { p_mcb->state = RFC_MX_STATE_SABME_WAIT_UA; rfc_send_sabme (p_mcb, RFCOMM_MX_DLCI); rfc_timer_start (p_mcb, RFC_T1_TIMEOUT); } else { p_mcb->state = RFC_MX_STATE_WAIT_SABME; rfc_timer_start (p_mcb, RFC_T2_TIMEOUT); } } }
/******************************************************************************* ** ** Function PORT_StartCnf ** ** Description This function is called from the RFCOMM layer when ** establishing of the multiplexer channel is completed. ** Continue establishing of the connection for all ports that ** are in the OPENING state ** *******************************************************************************/ void PORT_StartCnf (tRFC_MCB *p_mcb, UINT16 result) { tPORT *p_port; int i; BOOLEAN no_ports_up = TRUE; RFCOMM_TRACE_EVENT ("PORT_StartCnf result:%d", result); p_port = &rfc_cb.port.port[0]; for (i = 0; i < MAX_RFC_PORTS; i++, p_port++) { if (p_port->rfc.p_mcb == p_mcb) { no_ports_up = FALSE; if (result == RFCOMM_SUCCESS) RFCOMM_ParNegReq (p_mcb, p_port->dlci, p_port->mtu); else { RFCOMM_TRACE_WARNING ("PORT_StartCnf failed result:%d", result); /* Warning: result is also set to 4 when l2cap connection fails due to l2cap connect cnf (no_resources) */ if( result == HCI_ERR_PAGE_TIMEOUT ) p_port->error = PORT_PAGE_TIMEOUT; else p_port->error = PORT_START_FAILED; rfc_release_multiplexer_channel (p_mcb); p_port->rfc.p_mcb = NULL; /* Send event to the application */ if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECT_ERR)) (p_port->p_callback)(PORT_EV_CONNECT_ERR, p_port->inx); if (p_port->p_mgmt_callback) p_port->p_mgmt_callback (PORT_START_FAILED, p_port->inx); port_release_port (p_port); } } } /* There can be a situation when after starting connection, user closes the */ /* port, we can catch it here to close multiplexor channel */ if (no_ports_up) { rfc_check_mcb_active (p_mcb); } }
/******************************************************************************* ** ** Function PORT_CloseInd ** ** Description This function is called from the RFCOMM layer when ** multiplexer connection is released. ** *******************************************************************************/ void PORT_CloseInd (tRFC_MCB *p_mcb) { tPORT *p_port; int i; RFCOMM_TRACE_EVENT ("PORT_CloseInd"); p_port = &rfc_cb.port.port[0]; for (i = 0; i < MAX_RFC_PORTS; i++, p_port++) { if (p_port->rfc.p_mcb == p_mcb) { port_rfc_closed (p_port, PORT_PEER_CONNECTION_FAILED); } } rfc_release_multiplexer_channel (p_mcb); }
/******************************************************************************* ** ** Function rfc_mx_sm_state_disc_wait_ua ** ** Description This function handles events when the multiplexer sent ** DISC and is waiting for UA reply. ** ** Returns void ** *******************************************************************************/ void rfc_mx_sm_state_disc_wait_ua (tRFC_MCB *p_mcb, UINT16 event, void *p_data) { BT_HDR *p_buf; RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_disc_wait_ua - evt:%d", event); switch (event) { case RFC_EVENT_UA: case RFC_EVENT_DM: case RFC_EVENT_TIMEOUT: L2CA_DisconnectReq (p_mcb->lcid); if (p_mcb->restart_required) { /* Start Request was received while disconnecting. Execute it again */ if ((p_mcb->lcid = L2CA_ConnectReq (BT_PSM_RFCOMM, p_mcb->bd_addr)) == 0) { PORT_StartCnf (p_mcb, RFCOMM_ERROR); return; } /* Save entry for quicker access to mcb based on the LCID */ rfc_save_lcid_mcb (p_mcb, p_mcb->lcid); /* clean up before reuse it */ while ((p_buf = (BT_HDR *)GKI_dequeue(&p_mcb->cmd_q)) != NULL) GKI_freebuf(p_buf); rfc_timer_start (p_mcb, RFC_MCB_INIT_INACT_TIMER); p_mcb->is_initiator = TRUE; p_mcb->restart_required = FALSE; p_mcb->local_cfg_sent = FALSE; p_mcb->peer_cfg_rcvd = FALSE; p_mcb->state = RFC_MX_STATE_WAIT_CONN_CNF; return; } rfc_release_multiplexer_channel (p_mcb); return; case RFC_EVENT_DISC: rfc_send_ua (p_mcb, RFCOMM_MX_DLCI); return; case RFC_EVENT_UIH: GKI_freebuf (p_data); rfc_send_dm (p_mcb, RFCOMM_MX_DLCI, FALSE); return; case RFC_MX_EVENT_START_REQ: p_mcb->restart_required = TRUE; return; case RFC_MX_EVENT_DISC_IND: p_mcb->state = RFC_MX_STATE_IDLE; PORT_CloseInd (p_mcb); return; case RFC_MX_EVENT_CLOSE_REQ: return; case RFC_MX_EVENT_QOS_VIOLATION_IND: break; } RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); }