コード例 #1
0
ファイル: rfc_mx_fsm.c プロジェクト: Abocer/android-4.2_r1
/*******************************************************************************
**
** Function         rfc_mx_conf_ind
**
** Description      This function handles L2CA_ConfigInd message from the
**                  L2CAP.  Send the L2CA_ConfigRsp message.
**
*******************************************************************************/
static void rfc_mx_conf_ind (tRFC_MCB *p_mcb, tL2CAP_CFG_INFO *p_cfg)
{
    /* Save peer L2CAP MTU if present */
    /* RFCOMM adds 3-4 bytes in the beginning and 1 bytes FCS */
    if (p_cfg->mtu_present)
        p_mcb->peer_l2cap_mtu = p_cfg->mtu - RFCOMM_MIN_OFFSET - 1;
    else
        p_mcb->peer_l2cap_mtu = L2CAP_DEFAULT_MTU - RFCOMM_MIN_OFFSET - 1;

    p_cfg->mtu_present      = FALSE;
    p_cfg->flush_to_present = FALSE;
    p_cfg->qos_present      = FALSE;

    p_cfg->result = L2CAP_CFG_OK;

    L2CA_ConfigRsp (p_mcb->lcid, p_cfg);

    p_mcb->peer_cfg_rcvd = TRUE;
    if ((p_mcb->state == RFC_MX_STATE_CONFIGURE) && p_mcb->local_cfg_sent)
    {
        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);
        }
    }
}
コード例 #2
0
ファイル: rfc_mx_fsm.c プロジェクト: Abocer/android-4.2_r1
/*******************************************************************************
**
** 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);
        }
    }
}
コード例 #3
0
ファイル: rfc_mx_fsm.c プロジェクト: Abocer/android-4.2_r1
/*******************************************************************************
**
** 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);
}
コード例 #4
0
ファイル: rfc_utils.c プロジェクト: danathughes/esp-idf
/*******************************************************************************
**
** Function         rfc_alloc_multiplexer_channel
**
** Description      This function returns existing or new control block for
**                  the BD_ADDR.
**
*******************************************************************************/
tRFC_MCB *rfc_alloc_multiplexer_channel (BD_ADDR bd_addr, BOOLEAN is_initiator)
{
    int i, j;
    tRFC_MCB *p_mcb = NULL;
    RFCOMM_TRACE_DEBUG("rfc_alloc_multiplexer_channel: bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
                       bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
    RFCOMM_TRACE_DEBUG("rfc_alloc_multiplexer_channel:is_initiator:%d", is_initiator);

    for (i = 0; i < MAX_BD_CONNECTIONS; i++) {
        RFCOMM_TRACE_DEBUG("rfc_alloc_multiplexer_channel rfc_cb.port.rfc_mcb[%d].state:%d",
                           i, rfc_cb.port.rfc_mcb[i].state);
        RFCOMM_TRACE_DEBUG("(rfc_cb.port.rfc_mcb[i].bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
                           rfc_cb.port.rfc_mcb[i].bd_addr[0], rfc_cb.port.rfc_mcb[i].bd_addr[1],
                           rfc_cb.port.rfc_mcb[i].bd_addr[2], rfc_cb.port.rfc_mcb[i].bd_addr[3],
                           rfc_cb.port.rfc_mcb[i].bd_addr[4], rfc_cb.port.rfc_mcb[i].bd_addr[5]);

        if ((rfc_cb.port.rfc_mcb[i].state != RFC_MX_STATE_IDLE)
                && (!memcmp (rfc_cb.port.rfc_mcb[i].bd_addr, bd_addr, BD_ADDR_LEN))) {
            /* Multiplexer channel found do not change anything */
            /* If there was an inactivity timer running stop it now */
            if (rfc_cb.port.rfc_mcb[i].state == RFC_MX_STATE_CONNECTED) {
                rfc_timer_stop (&rfc_cb.port.rfc_mcb[i]);
            }
            RFCOMM_TRACE_DEBUG("rfc_alloc_multiplexer_channel:is_initiator:%d, found, state:%d, p_mcb:%p",
                               is_initiator, rfc_cb.port.rfc_mcb[i].state, &rfc_cb.port.rfc_mcb[i]);
            return (&rfc_cb.port.rfc_mcb[i]);
        }
    }

    /* connection with bd_addr does not exist */
    for (i = 0, j = rfc_cb.rfc.last_mux + 1; i < MAX_BD_CONNECTIONS; i++, j++) {
        if (j >= MAX_BD_CONNECTIONS) {
            j = 0;
        }

        p_mcb = &rfc_cb.port.rfc_mcb[j];
        if (rfc_cb.port.rfc_mcb[j].state == RFC_MX_STATE_IDLE) {
            /* New multiplexer control block */
            fixed_queue_free(p_mcb->cmd_q, NULL);
            memset (p_mcb, 0, sizeof (tRFC_MCB));
            memcpy (p_mcb->bd_addr, bd_addr, BD_ADDR_LEN);
            RFCOMM_TRACE_DEBUG("rfc_alloc_multiplexer_channel:is_initiator:%d, create new p_mcb:%p, index:%d",
                               is_initiator, &rfc_cb.port.rfc_mcb[j], j);

            p_mcb->cmd_q = fixed_queue_new(SIZE_MAX);

            p_mcb->is_initiator = is_initiator;

            rfc_timer_start (p_mcb, RFC_MCB_INIT_INACT_TIMER);

            rfc_cb.rfc.last_mux = (UINT8) j;
            return (p_mcb);
        }
    }
    return (NULL);
}
コード例 #5
0
ファイル: rfc_mx_fsm.c プロジェクト: Abocer/android-4.2_r1
/*******************************************************************************
**
** Function         rfc_mx_sm_state_idle
**
** Description      This function handles events when the multiplexer is in
**                  IDLE state. This state exists when connection is being
**                  initially established.
**
** Returns          void
**
*******************************************************************************/
void rfc_mx_sm_state_idle (tRFC_MCB *p_mcb, UINT16 event, void *p_data)
{
    RFCOMM_TRACE_EVENT1 ("rfc_mx_sm_state_idle - evt:%d", event);
    switch (event)
    {
    case RFC_MX_EVENT_START_REQ:

        /* Initialize L2CAP MTU */
        p_mcb->peer_l2cap_mtu = L2CAP_DEFAULT_MTU - RFCOMM_MIN_OFFSET - 1;

        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);

        p_mcb->state = RFC_MX_STATE_WAIT_CONN_CNF;
        return;

    case RFC_MX_EVENT_START_RSP:
    case RFC_MX_EVENT_CONN_CNF:
    case RFC_MX_EVENT_CONF_IND:
    case RFC_MX_EVENT_CONF_CNF:
        RFCOMM_TRACE_ERROR2 ("Mx error state %d event %d", p_mcb->state, event);
        return;

    case RFC_MX_EVENT_CONN_IND:

        rfc_timer_start (p_mcb, RFCOMM_CONN_TIMEOUT);
        L2CA_ConnectRsp (p_mcb->bd_addr, *((UINT8 *)p_data), p_mcb->lcid, L2CAP_CONN_OK, 0);

        rfc_mx_send_config_req (p_mcb);

        p_mcb->state = RFC_MX_STATE_CONFIGURE;
        return;

    case RFC_EVENT_SABME:
        break;

    case RFC_EVENT_UA:
    case RFC_EVENT_DM:
        return;

    case RFC_EVENT_DISC:
        rfc_send_dm (p_mcb, RFCOMM_MX_DLCI, TRUE);
        return;

    case RFC_EVENT_UIH:
        rfc_send_dm (p_mcb, RFCOMM_MX_DLCI, FALSE);
        return;
    }
    RFCOMM_TRACE_EVENT2 ("RFCOMM MX ignored - evt:%d in state:%d", event, p_mcb->state);
}
コード例 #6
0
/*******************************************************************************
**
** Function         RFCOMM_ConnectInd
**
** Description      This is a callback function called by L2CAP when
**                  L2CA_ConnectInd received.  Allocate multiplexer control block
**                  and dispatch the event to it.
**
*******************************************************************************/
void RFCOMM_ConnectInd (BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
{
    tRFC_MCB *p_mcb = rfc_alloc_multiplexer_channel(bd_addr, FALSE);
    UNUSED(psm);

    if ((p_mcb)&&(p_mcb->state != RFC_MX_STATE_IDLE))
    {
        /* if this is collision case */
        if ((p_mcb->is_initiator)&&(p_mcb->state == RFC_MX_STATE_WAIT_CONN_CNF))
        {
            p_mcb->pending_lcid = lcid;
            p_mcb->pending_id   = id;

            /* wait random timeout (2 - 12) to resolve collision */
            /* if peer gives up then local device rejects incoming connection and continues as initiator */
            /* if timeout, local device disconnects outgoing connection and continues as acceptor */
            RFCOMM_TRACE_DEBUG ("RFCOMM_ConnectInd start timer for collision, initiator's LCID(0x%x), acceptor's LCID(0x%x)",
                                  p_mcb->lcid, p_mcb->pending_lcid);

            rfc_timer_start(p_mcb, (UINT16)(GKI_get_tick_count()%10 + 2));
            return;
        }
        else
        {
            /* we cannot accept connection request from peer at this state */
            /* don't update lcid */
            p_mcb = NULL;
        }
    }
    else
    {
        /* store mcb even if null */
        rfc_save_lcid_mcb (p_mcb, lcid);
    }

    if (p_mcb == NULL)
    {
        L2CA_ConnectRsp (bd_addr, id, lcid, L2CAP_CONN_NO_RESOURCES, 0);
        return;
    }
    p_mcb->lcid     = lcid;

    rfc_mx_sm_execute (p_mcb, RFC_MX_EVENT_CONN_IND, &id);
}
コード例 #7
0
ファイル: rfc_utils.c プロジェクト: danathughes/esp-idf
/*******************************************************************************
**
** Function         rfc_check_mcb_active
**
** Description      Check if there are any opened ports on the MCB if not
**                  start MCB Inact timer.
**
** Returns          void
**
*******************************************************************************/
void rfc_check_mcb_active (tRFC_MCB *p_mcb)
{
    UINT16 i;

    for (i = 0; i < RFCOMM_MAX_DLCI; i++) {
        if (p_mcb->port_inx[i] != 0) {
            p_mcb->is_disc_initiator = FALSE;
            return;
        }
    }
    /* The last port was DISCed.  On the client side start disconnecting Mx */
    /* On the server side start inactivity timer */
    if (p_mcb->is_disc_initiator) {
        p_mcb->is_disc_initiator = FALSE;
        rfc_mx_sm_execute (p_mcb, RFC_MX_EVENT_CLOSE_REQ, NULL);
    } else {
        rfc_timer_start (p_mcb, RFC_MCB_RELEASE_INACT_TIMER);
    }
}
コード例 #8
0
ファイル: rfc_mx_fsm.c プロジェクト: Abocer/android-4.2_r1
/*******************************************************************************
**
** 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);
}