/******************************************************************************* ** ** Function rfc_mx_sm_state_connected ** ** Description This function handles events when the multiplexer is ** in the CONNECTED state ** ** Returns void ** *******************************************************************************/ void rfc_mx_sm_state_connected (tRFC_MCB *p_mcb, UINT16 event, void *p_data) { RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_connected - evt:%d", event); switch (event) { case RFC_EVENT_TIMEOUT: case RFC_MX_EVENT_CLOSE_REQ: rfc_timer_start (p_mcb, RFC_DISC_TIMEOUT); p_mcb->state = RFC_MX_STATE_DISC_WAIT_UA; rfc_send_disc (p_mcb, RFCOMM_MX_DLCI); return; case RFC_MX_EVENT_DISC_IND: p_mcb->state = RFC_MX_STATE_IDLE; PORT_CloseInd (p_mcb); return; case RFC_EVENT_DISC: /* Reply with UA. If initiator bring down L2CAP connection */ /* If server wait for some time if client decide to reinitiate channel */ rfc_send_ua (p_mcb, RFCOMM_MX_DLCI); if (p_mcb->is_initiator) { L2CA_DisconnectReq (p_mcb->lcid); } /* notify all ports that connection is gone */ PORT_CloseInd (p_mcb); return; } RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state); }
/******************************************************************************* ** ** Function rfc_port_sm_sabme_wait_ua ** ** Description This function handles events when SABME on the DLC was ** sent and SM is waiting for UA or DM. ** ** Returns void ** *******************************************************************************/ void rfc_port_sm_sabme_wait_ua (tPORT *p_port, UINT16 event, void *p_data) { switch (event) { case RFC_EVENT_OPEN: case RFC_EVENT_ESTABLISH_RSP: RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event); return; case RFC_EVENT_CLOSE: rfc_port_timer_start (p_port, RFC_DISC_TIMEOUT); rfc_send_disc (p_port->rfc.p_mcb, p_port->dlci); p_port->rfc.expected_rsp = 0; p_port->rfc.state = RFC_STATE_DISC_WAIT_UA; return; case RFC_EVENT_CLEAR: rfc_port_closed (p_port); return; case RFC_EVENT_DATA: GKI_freebuf (p_data); break; case RFC_EVENT_UA: rfc_port_timer_stop (p_port); p_port->rfc.state = RFC_STATE_OPENED; PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_SUCCESS); return; case RFC_EVENT_DM: p_port->rfc.p_mcb->is_disc_initiator = TRUE; PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR); rfc_port_closed (p_port); return; case RFC_EVENT_DISC: rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci); PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR); rfc_port_closed (p_port); return; case RFC_EVENT_SABME: /* Continue to wait for the UA the SABME this side sent */ rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci); return; case RFC_EVENT_UIH: GKI_freebuf (p_data); return; case RFC_EVENT_TIMEOUT: p_port->rfc.state = RFC_STATE_CLOSED; PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR); return; } RFCOMM_TRACE_WARNING ("Port state sabme_wait_ua Event ignored %d", event); }
/******************************************************************************* ** ** Function PORT_ParNegCnf ** ** Description This function is called from the RFCOMM layer to change ** DLCI parameters (currently only MTU is negotiated). ** Save the MTU size supported by the peer. ** If the confirmation is received during the port opening ** procedure send EstablishRequest to continue. ** *******************************************************************************/ void PORT_ParNegCnf (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT8 cl, UINT8 k) { tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci); RFCOMM_TRACE_EVENT ("PORT_ParNegCnf dlci:%d mtu:%d cl: %d k: %d", dlci, mtu, cl, k); if (!p_port) return; /* Flow control mechanism not set yet. Negotiate flow control mechanism. */ if (p_mcb->flow == PORT_FC_UNDEFINED) { /* Our stack is configured for TS07.10 and they responded with credit-based. */ /* This is illegal-- negotiation fails. */ if ((PORT_FC_DEFAULT == PORT_FC_TS710) && (cl == RFCOMM_PN_CONV_LAYER_CBFC_R)) { rfc_send_disc (p_mcb, p_port->dlci); rfc_port_closed (p_port); return; } /* Our stack is configured for credit-based and they responded with credit-based. */ else if (cl == RFCOMM_PN_CONV_LAYER_CBFC_R) { p_mcb->flow = PORT_FC_CREDIT; } /* They responded with any other value. Treat this as negotiation to TS07.10. */ else { p_mcb->flow = PORT_FC_TS710; } } /* If mux flow control mechanism set, we honor that setting regardless of */ /* the CL value in their response. This allows us to gracefully accept any */ /* illegal PN negotiation scenarios. */ p_port->mtu = (p_port->mtu < mtu) ? p_port->mtu : mtu; p_port->peer_mtu = p_port->mtu; if (p_mcb->flow == PORT_FC_CREDIT) { port_get_credits (p_port, k); } if (p_port->state == PORT_STATE_OPENING) RFCOMM_DlcEstablishReq (p_mcb, p_port->dlci, p_port->mtu); }
/******************************************************************************* ** ** Function rfc_port_sm_opened ** ** Description This function handles events for the port in the OPENED ** state ** ** Returns void ** *******************************************************************************/ void rfc_port_sm_opened (tPORT *p_port, UINT16 event, void *p_data) { switch (event) { case RFC_EVENT_OPEN: RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event); return; case RFC_EVENT_CLOSE: rfc_port_timer_start (p_port, RFC_DISC_TIMEOUT); rfc_send_disc (p_port->rfc.p_mcb, p_port->dlci); p_port->rfc.expected_rsp = 0; p_port->rfc.state = RFC_STATE_DISC_WAIT_UA; return; case RFC_EVENT_CLEAR: rfc_port_closed (p_port); return; case RFC_EVENT_DATA: /* Send credits in the frame. Pass them in the layer specific member of the hdr. */ /* There might be an initial case when we reduced rx_max and credit_rx is still */ /* bigger. Make sure that we do not send 255 */ if ((p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) && (((BT_HDR *)p_data)->len < p_port->peer_mtu) && (!p_port->rx.user_fc) && (p_port->credit_rx_max > p_port->credit_rx)) { ((BT_HDR *)p_data)->layer_specific = (UINT8) (p_port->credit_rx_max - p_port->credit_rx); p_port->credit_rx = p_port->credit_rx_max; } else { ((BT_HDR *)p_data)->layer_specific = 0; } rfc_send_buf_uih (p_port->rfc.p_mcb, p_port->dlci, (BT_HDR *)p_data); rfc_dec_credit (p_port); return; case RFC_EVENT_UA: return; case RFC_EVENT_SABME: rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci); return; case RFC_EVENT_DM: PORT_DlcReleaseInd (p_port->rfc.p_mcb, p_port->dlci); rfc_port_closed (p_port); return; case RFC_EVENT_DISC: p_port->rfc.state = RFC_STATE_CLOSED; rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci); if (! fixed_queue_is_empty(p_port->rx.queue)) { /* give a chance to upper stack to close port properly */ RFCOMM_TRACE_DEBUG("port queue is not empty"); rfc_port_timer_start (p_port, RFC_DISC_TIMEOUT); } else { PORT_DlcReleaseInd (p_port->rfc.p_mcb, p_port->dlci); } return; case RFC_EVENT_UIH: rfc_port_uplink_data (p_port, (BT_HDR *)p_data); return; case RFC_EVENT_TIMEOUT: Port_TimeOutCloseMux( p_port->rfc.p_mcb ) ; RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event); return; } RFCOMM_TRACE_WARNING ("Port state opened Event ignored %d", event); }