/******************************************************************************* ** ** 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 PORT_ParNegInd ** ** Description This function is called from the RFCOMM layer to change ** DLCI parameters (currently only MTU is negotiated). ** If can not find the port do not accept the request. ** Otherwise save the MTU size supported by the peer. ** *******************************************************************************/ void PORT_ParNegInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT8 cl, UINT8 k) { tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci); UINT8 our_cl; UINT8 our_k; RFCOMM_TRACE_EVENT ("PORT_ParNegInd dlci:%d mtu:%d", dlci, mtu); if (!p_port) { /* This can be a first request for this port */ p_port = port_find_dlci_port (dlci); if (!p_port) { /* If the port cannot be opened, send a DM. Per Errata 1205 */ rfc_send_dm(p_mcb, dlci, FALSE); /* check if this is the last port open, some headsets have problem, they don't disconnect if we send DM */ rfc_check_mcb_active( p_mcb ); RFCOMM_TRACE_EVENT( "PORT_ParNegInd: port not found" ); return; } p_mcb->port_inx[dlci] = p_port->inx; } memcpy (p_port->bd_addr, p_mcb->bd_addr, BD_ADDR_LEN); /* Connection is up and we know local and remote features, select MTU */ port_select_mtu (p_port); p_port->rfc.p_mcb = p_mcb; p_port->mtu = (p_port->mtu < mtu) ? p_port->mtu : mtu; p_port->peer_mtu = p_port->mtu; /* Negotiate the flow control mechanism. If flow control mechanism for */ /* mux has not been set yet, set it now. If either we or peer wants TS 07.10, */ /* use that. Otherwise both must want credit based, so use that. If flow is */ /* already defined for this mux, we respond with that value. */ if (p_mcb->flow == PORT_FC_UNDEFINED) { if ((PORT_FC_DEFAULT == PORT_FC_TS710) || (cl == RFCOMM_PN_CONV_LAYER_TYPE_1)) { p_mcb->flow = PORT_FC_TS710; } else { p_mcb->flow = PORT_FC_CREDIT; } } /* Regardless of our flow control mechanism, if the PN cl is zero, we must */ /* respond with zero. "A responding implementation must set this field to 14 */ /* if (and only if) the PN request was 15." This could happen if a PN is sent */ /* after the DLCI is already established-- the PN in that case must have cl = 0. */ /* See RFCOMM spec 5.5.3 */ if (cl == RFCOMM_PN_CONV_LAYER_TYPE_1) { our_cl = RFCOMM_PN_CONV_LAYER_TYPE_1; our_k = 0; } else if (p_mcb->flow == PORT_FC_CREDIT) { /* get credits */ port_get_credits (p_port, k); /* Set convergence layer and number of credits (k) */ our_cl = RFCOMM_PN_CONV_LAYER_CBFC_R; our_k = (p_port->credit_rx_max < RFCOMM_K_MAX) ? p_port->credit_rx_max : RFCOMM_K_MAX; p_port->credit_rx = our_k; } else { /* must not be using credit based flow control; use TS 7.10 */ our_cl = RFCOMM_PN_CONV_LAYER_TYPE_1; our_k = 0; } RFCOMM_ParNegRsp (p_mcb, dlci, p_port->mtu, our_cl, our_k); }