Example #1
0
/*******************************************************************************
**
** 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);
}
Example #2
0
/*******************************************************************************
**
** 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);
}