コード例 #1
0
/*******************************************************************************
**
** Function         PORT_DlcEstablishInd
**
** Description      This function is called from the RFCOMM layer when peer
**                  device wants to establish a new DLC.  If this is not the
**                  first message in the establishment procedure port_handle
**                  has a handle to the port control block otherwise the control
**                  block should be found based on the muliplexer channel and
**                  dlci.  The block should be allocated allocated before
**                  meaning that application already made open.
**
*******************************************************************************/
void PORT_DlcEstablishInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu)
{
    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);

    RFCOMM_TRACE_DEBUG ("PORT_DlcEstablishInd p_mcb:%p, dlci:%d mtu:%di, p_port:%p", p_mcb, dlci, mtu, p_port);
    RFCOMM_TRACE_DEBUG ("PORT_DlcEstablishInd p_mcb addr:%02x:%02x:%02x:%02x:%02x:%02x",
                        p_mcb->bd_addr[0], p_mcb->bd_addr[1], p_mcb->bd_addr[2],
                        p_mcb->bd_addr[3], p_mcb->bd_addr[4], p_mcb->bd_addr[5]);

    if (!p_port) {
        /* This can be a first request for this port */
        p_port = port_find_dlci_port (dlci);
        if (!p_port) {
            RFCOMM_DlcEstablishRsp (p_mcb, dlci, 0, RFCOMM_ERROR);
            return;
        }
        p_mcb->port_inx[dlci] = p_port->inx;
    }

    /* If L2CAP's mtu less then RFCOMM's take it */
    if (mtu && (mtu < p_port->peer_mtu)) {
        p_port->peer_mtu = mtu;
    }

    /* If there was an inactivity timer running for MCB stop it */
    rfc_timer_stop (p_mcb);

    RFCOMM_DlcEstablishRsp (p_mcb, dlci, p_port->mtu, RFCOMM_SUCCESS);

    /* This is the server side.  If application wants to know when connection */
    /* is established, thats the place */
    if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECTED)) {
        (p_port->p_callback)(PORT_EV_CONNECTED, p_port->inx);
    }

    if (p_port->p_mgmt_callback) {
        p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx);
    }

    p_port->state = PORT_STATE_OPENED;
}
コード例 #2
0
/*******************************************************************************
**
** Function         PORT_PortNegInd
**
** Description      This function is called from the RFCOMM layer when peer
**                  device wants to set parameters of the port.  As per the spec
**                  this message has to be sent before the first data packet
**                  and can be sent before establish.  The block should be
**                  allocated before meaning that application already made open.
**
*******************************************************************************/
void PORT_PortNegInd (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_STATE *p_pars,
                      UINT16 param_mask)
{
    tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);

    RFCOMM_TRACE_EVENT ("PORT_PortNegInd");

    if (!p_port) {
        /* This can be a first request for this port */
        p_port = port_find_dlci_port (dlci);
        if (!p_port) {
            RFCOMM_PortNegRsp (p_mcb, dlci, p_pars, 0);
            return;
        }
        p_mcb->port_inx[dlci] = p_port->inx;
    }

    /* Check if the flow control is acceptable on local side */
    p_port->peer_port_pars = *p_pars;
    RFCOMM_PortNegRsp (p_mcb, dlci, p_pars, param_mask);
}
コード例 #3
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);
}
コード例 #4
0
/*******************************************************************************
**
** Function         RFCOMM_BufDataInd
**
** Description      This is a callback function called by L2CAP when
**                  data RFCOMM frame is received.  Parse the frames, check
**                  the checksum and dispatch event to multiplexer or port
**                  state machine depending on the frame destination.
**
*******************************************************************************/
void RFCOMM_BufDataInd (UINT16 lcid, BT_HDR *p_buf)
{
    tRFC_MCB *p_mcb = rfc_find_lcid_mcb (lcid);
    tPORT    *p_port;
    UINT8    event;


    if (!p_mcb)
    {
        RFCOMM_TRACE_WARNING ("RFCOMM_BufDataInd LCID:0x%x", lcid);
        GKI_freebuf (p_buf);
        return;
    }

    event = rfc_parse_data (p_mcb, &rfc_cb.rfc.rx_frame, p_buf);

    /* If the frame did not pass validation just ignore it */
    if (event == RFC_EVENT_BAD_FRAME)
    {
        GKI_freebuf (p_buf);
        return;
    }

    if (rfc_cb.rfc.rx_frame.dlci == RFCOMM_MX_DLCI)
    {
        /* Take special care of the Multiplexer Control Messages */
        if (event == RFC_EVENT_UIH)
        {
            rfc_process_mx_message (p_mcb, p_buf);
            return;
        }

        /* Other multiplexer events go to state machine */
        rfc_mx_sm_execute (p_mcb, event, NULL);
        GKI_freebuf (p_buf);
        return;
    }

    /* The frame was received on the data channel DLCI, verify that DLC exists */
    if (((p_port = port_find_mcb_dlci_port (p_mcb, rfc_cb.rfc.rx_frame.dlci)) == NULL)
     || (!p_port->rfc.p_mcb))
    {
        /* If this is a SABME on the new port, check if any appl is waiting for it */
        if (event != RFC_EVENT_SABME)
        {
            if (( p_mcb->is_initiator && !rfc_cb.rfc.rx_frame.cr)
             || (!p_mcb->is_initiator &&  rfc_cb.rfc.rx_frame.cr))
                rfc_send_dm (p_mcb, rfc_cb.rfc.rx_frame.dlci, rfc_cb.rfc.rx_frame.pf);
            GKI_freebuf (p_buf);
            return;
        }

        if ((p_port = port_find_dlci_port (rfc_cb.rfc.rx_frame.dlci)) == NULL)
        {
            rfc_send_dm (p_mcb, rfc_cb.rfc.rx_frame.dlci, TRUE);
            GKI_freebuf (p_buf);
            return;
        }
        p_mcb->port_inx[rfc_cb.rfc.rx_frame.dlci] = p_port->inx;
        p_port->rfc.p_mcb = p_mcb;
    }

    if (event == RFC_EVENT_UIH)
    {
        if (p_buf->len > 0)
            rfc_port_sm_execute (p_port, event, p_buf);
        else
            GKI_freebuf (p_buf);

        if (rfc_cb.rfc.rx_frame.credit != 0)
            rfc_inc_credit (p_port, rfc_cb.rfc.rx_frame.credit);

        return;
    }
    rfc_port_sm_execute (p_port, event,  NULL);
    GKI_freebuf (p_buf);
}