/*******************************************************************************
**
** Function         bta_ag_sm_execute
**
** Description      State machine event handling function for AG
**
**
** Returns          void
**
*******************************************************************************/
void bta_ag_sm_execute(tBTA_AG_SCB *p_scb, UINT16 event, tBTA_AG_DATA *p_data)
{
    tBTA_AG_ST_TBL      state_table;
    UINT8               action;
    int                 i;
    UINT16  in_event = event;
    UINT8   in_state = p_scb->state;

    if (in_event != BTA_AG_API_RESULT_EVT || p_scb->state == BTA_AG_OPEN_ST)
    {
        #if BTA_AG_DEBUG == TRUE
            APPL_TRACE_IMP("AG evt (hdl 0x%04x): State %d (%s), Event 0x%04x (%s)",
                           bta_ag_scb_to_idx(p_scb),
                           p_scb->state, bta_ag_state_str(p_scb->state),
                           event, bta_ag_evt_str(event, p_data->api_result.result));
        #else
           APPL_TRACE_IMP("AG evt (hdl 0x%04x): State %d, Event 0x%04x",
                      bta_ag_scb_to_idx(p_scb), p_scb->state, event);
        #endif
    }

    event &= 0x00FF;
    if (event >= (BTA_AG_MAX_EVT & 0x00FF))
    {
        APPL_TRACE_ERROR("AG evt out of range, ignoring...");
        return;
    }

    /* look up the state table for the current state */
    state_table = bta_ag_st_tbl[p_scb->state];

    /* set next state */
    p_scb->state = state_table[event][BTA_AG_NEXT_STATE];

    /* execute action functions */
    for (i = 0; i < BTA_AG_ACTIONS; i++)
    {
        if ((action = state_table[event][i]) != BTA_AG_IGNORE)
        {
            (*bta_ag_action[action])(p_scb, p_data);
        }
        else
        {
            break;
        }
    }
    if (p_scb->state != in_state)
    {
        #if BTA_AG_DEBUG == TRUE
            APPL_TRACE_IMP("BTA AG State Change: [%s] -> [%s] after Event [%s]",
                      bta_ag_state_str(in_state),
                      bta_ag_state_str(p_scb->state),
                      bta_ag_evt_str(in_event, p_data->api_result.result));
        #else
            APPL_TRACE_IMP("BTA AG State Change: [%d] -> [%d]",
                              in_state, p_scb->state);
        #endif
    }
}
Esempio n. 2
0
/*******************************************************************************
**
** Function         bta_ag_api_result
**
** Description      Handle an API result event.
**
**
** Returns          void
**
*******************************************************************************/
static void bta_ag_api_result(tBTA_AG_DATA *p_data)
{
    tBTA_AG_SCB     *p_scb;
    int             i;

    if (p_data->hdr.layer_specific != BTA_AG_HANDLE_ALL)
    {
        if ((p_scb = bta_ag_scb_by_idx(p_data->hdr.layer_specific)) != NULL)
        {
            APPL_TRACE_IMP("bta_ag_api_result: p_scb 0x%08x ", p_scb);
            bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
        }
    }
    else
    {
        for (i = 0, p_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, p_scb++)
        {
            if (p_scb->in_use && p_scb->svc_conn)
            {
                APPL_TRACE_DEBUG("bta_ag_api_result p_scb 0x%08x ", p_scb);
                bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
            }
        }
    }
}
/*******************************************************************************
**
** Function         bta_ag_rfc_data
**
** Description      Read and process data from RFCOMM.
**
**
** Returns          void
**
*******************************************************************************/
void bta_ag_rfc_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
{
    UINT16  len;
    char    buf[BTA_AG_RFC_READ_MAX];
    UNUSED(p_data);

    memset(buf, 0, BTA_AG_RFC_READ_MAX);

    APPL_TRACE_DEBUG ("bta_ag_rfc_data");
    /* do the following */
    for(;;)
    {
        /* read data from rfcomm; if bad status, we're done */
        if (PORT_ReadData(p_scb->conn_handle, buf, BTA_AG_RFC_READ_MAX, &len) != PORT_SUCCESS)
        {
            break;
        }

        /* if no data, we're done */
        if (len == 0)
        {
            break;
        }

        /* run AT command interpreter on data */
        bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
        bta_ag_at_parse(&p_scb->at_cb, buf, len);
        if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) && bta_ag_sco_is_open(p_scb))
        {
            APPL_TRACE_IMP ("bta_ag_rfc_data, change link policy for SCO");
            bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
        }
        else
        {
            bta_sys_idle(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
        }
        /* no more data to read, we're done */
        if (len < BTA_AG_RFC_READ_MAX)
        {
            break;
        }
    }
}
/*******************************************************************************
**
** Function         bta_ag_ci_rx_data
**
** Description      Send result code
**
** Returns          void
**
*******************************************************************************/
void bta_ag_ci_rx_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
{
    UINT16 len;
    tBTA_AG_CI_RX_WRITE *p_rx_write_msg = (tBTA_AG_CI_RX_WRITE *)p_data;
    char *p_data_area = (char *)(p_rx_write_msg+1);     /* Point to data area after header */

    APPL_TRACE_DEBUG ("bta_ag_ci_rx_data:");
    /* send to RFCOMM */
    bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    PORT_WriteData(p_scb->conn_handle, p_data_area, strlen(p_data_area), &len);
    if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) && bta_ag_sco_is_open(p_scb))
    {
        APPL_TRACE_IMP ("bta_ag_rfc_data, change link policy for SCO");
        bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    }
    else
    {
        bta_sys_idle(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
    }
}
Esempio n. 5
0
/*******************************************************************************
**
** Function         bta_ag_hdl_event
**
** Description      Data gateway main event handling function.
**
**
** Returns          BOOLEAN
**
*******************************************************************************/
BOOLEAN bta_ag_hdl_event(BT_HDR *p_msg)
{
    tBTA_AG_SCB *p_scb;

    APPL_TRACE_DEBUG("bta_ag_hdl_event: Event 0x%04x ", p_msg->event);
    switch (p_msg->event)
    {
        /* handle enable event */
        case BTA_AG_API_ENABLE_EVT:
            bta_ag_api_enable((tBTA_AG_DATA *) p_msg);
            break;

        /* handle disable event */
        case BTA_AG_API_DISABLE_EVT:
            bta_ag_api_disable((tBTA_AG_DATA *) p_msg);
            break;

        /* handle register event */
        case BTA_AG_API_REGISTER_EVT:
            bta_ag_api_register((tBTA_AG_DATA *) p_msg);
            break;

        /* handle result event */
        case BTA_AG_API_RESULT_EVT:
            bta_ag_api_result((tBTA_AG_DATA *) p_msg);
            break;

        /* all others reference scb by handle */
        default:
            if ((p_scb = bta_ag_scb_by_idx(p_msg->layer_specific)) != NULL)
            {
                APPL_TRACE_IMP("bta_ag_hdl_event: p_scb 0x%08x ", p_scb);
                bta_ag_sm_execute(p_scb, p_msg->event, (tBTA_AG_DATA *) p_msg);
            }
            break;
    }
    return TRUE;
}
/*******************************************************************************
**
** Function         bta_av_ssm_execute
**
** Description      Stream state machine event handling function for AV
**
**
** Returns          void
**
*******************************************************************************/
void bta_av_ssm_execute(tBTA_AV_SCB *p_scb, UINT16 event, tBTA_AV_DATA *p_data)
{
    tBTA_AV_SST_TBL     state_table;
    UINT8               action;
    int                 i, xx;

    if(p_scb == NULL)
    {
        /* this stream is not registered */
        APPL_TRACE_EVENT("AV channel not registered");
        return;
    }

    /* In case incoming connection is for VDP, we need to swap scb.        */
    /* When ACP_CONNECT_EVT was received, we put first available scb to    */
    /* to Incoming state. Later, when STR_CONFIG_IND_EVT is coming, we     */
    /* know if it is A2DP or VDP.                                          */
    if ((p_scb->state == BTA_AV_INIT_SST) && (event == BTA_AV_STR_CONFIG_IND_EVT))
    {
        for (xx = 0; xx < BTA_AV_NUM_STRS; xx++)
        {
            if (bta_av_cb.p_scb[xx])
            {
                if (bta_av_cb.p_scb[xx]->state == BTA_AV_INCOMING_SST)
                {
                    bta_av_cb.p_scb[xx]->state = BTA_AV_INIT_SST;
                    bta_av_cb.p_scb[xx]->coll_mask = 0;
                    p_scb->state = BTA_AV_INCOMING_SST;
                    break;
                }
            }
        }
    }

if ((event != BTA_AV_STR_WRITE_CFM_EVT) && (event != BTA_AV_SRC_DATA_READY_EVT))
    {
        #if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
            APPL_TRACE_IMP("AV Sevent(0x%x)=0x%x(%s) state=%d(%s)",
               p_scb->hndl, event, bta_av_evt_code(event), p_scb->state, bta_av_sst_code(p_scb->state));
        #else
            APPL_TRACE_IMP("AV Sevent=0x%x state=%d", event, p_scb->state);
        #endif
    }

    /* look up the state table for the current state */
    state_table = bta_av_sst_tbl[p_scb->state];

    event -= BTA_AV_FIRST_SSM_EVT;

    /* set next state */
    p_scb->state = state_table[event][BTA_AV_SNEXT_STATE];

    /* execute action functions */
    for(i=0; i< BTA_AV_SACTIONS; i++)
    {
        if ((action = state_table[event][i]) != BTA_AV_SIGNORE)
        {
            (*p_scb->p_act_tbl[action])(p_scb, p_data);
        }
        else
            break;
    }

}
/*******************************************************************************
**
** Function         bta_ag_rfc_acp_open
**
** Description      Handle RFCOMM channel open when accepting connection.
**
**
** Returns          void
**
*******************************************************************************/
void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
{
    UINT16          lcid;
    int             i;
    tBTA_AG_SCB     *ag_scb, *other_scb;
    BD_ADDR         dev_addr;
    int             status;

    /* set role */
    p_scb->role = BTA_AG_ACP;

    APPL_TRACE_IMP ("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d",
                       p_scb->serv_handle[0], p_scb->serv_handle[1]);

    /* get bd addr of peer */
    if (PORT_SUCCESS != (status=PORT_CheckConnection(p_data->rfc.port_handle, dev_addr, &lcid)))
    {
        APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open error PORT_CheckConnection returned status %d", status);
    }

    /* Collision Handling */
    for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
    {
        if ((ag_scb->in_use) && (ag_scb->colli_tmr_on))
        {
            /* stop collision timer */
            ag_scb->colli_tmr_on = FALSE;
            bta_sys_stop_timer (&ag_scb->colli_timer);

            if (bdcmp (dev_addr, ag_scb->peer_addr) == 0)
            {
                /* If incoming and outgoing device are same, nothing more to do.            */
                /* Outgoing conn will be aborted because we have successful incoming conn.  */
            }
            else
            {
                /* Resume outgoing connection. */
                other_scb = bta_ag_get_other_idle_scb (p_scb);
                if (other_scb)
                {
                    bdcpy(other_scb->peer_addr, ag_scb->peer_addr);
                    other_scb->open_services = ag_scb->open_services;
                    other_scb->cli_sec_mask = ag_scb->cli_sec_mask;

                    bta_ag_resume_open (other_scb);
                }
            }

            break;
        }
    }

    bdcpy (p_scb->peer_addr, dev_addr);

    /* determine connected service from port handle */
    for (i = 0; i < BTA_AG_NUM_IDX; i++)
    {
        APPL_TRACE_DEBUG ("bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d",
                           i, p_scb->serv_handle[i], p_data->rfc.port_handle);

        if (p_scb->serv_handle[i] == p_data->rfc.port_handle)
        {
            p_scb->conn_service = i;
            p_scb->conn_handle = p_data->rfc.port_handle;
            break;
        }
    }

    APPL_TRACE_IMP ("bta_ag_rfc_acp_open: conn_service = %d conn_handle = %d",
                       p_scb->conn_service, p_scb->conn_handle);

    /* close any unopened server */
    bta_ag_close_servers(p_scb, (p_scb->reg_services & ~bta_ag_svc_mask[p_scb->conn_service]));

    /* do service discovery to get features */
    bta_ag_do_disc(p_scb, bta_ag_svc_mask[p_scb->conn_service]);

    /* continue with common open processing */
    bta_ag_rfc_open(p_scb, p_data);



}