Пример #1
0
/*******************************************************************************
**
** Function     smp_sm_event
**
** Description  Handle events to the state machine. It looks up the entry
**              in the smp_entry_table array.
**              If it is a valid entry, it gets the state table.Set the next state,
**              if not NULL state.Execute the action function according to the
**              state table. If the state returned by action function is not NULL
**              state, adjust the new state to the returned state.If (api_evt != MAX),
**              call callback function.
**
** Returns      void.
**
*******************************************************************************/
void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data)
{
    UINT8           curr_state = p_cb->state;
    tSMP_SM_TBL     state_table;
    UINT8           action, entry, i;
    tSMP_ENTRY_TBL  entry_table =  smp_entry_table[p_cb->role];

    SMP_TRACE_EVENT("main smp_sm_event");
    if (curr_state >= SMP_STATE_MAX)
    {
        SMP_TRACE_DEBUG( "Invalid state: %d", curr_state) ;
        return;
    }

    SMP_TRACE_DEBUG( "SMP Role: %s State: [%s (%d)], Event: [%s (%d)]",\
                      (p_cb->role == 0x01) ?"Slave" : "Master", smp_get_state_name( p_cb->state),
                      p_cb->state, smp_get_event_name(event), event) ;

    /* look up the state table for the current state */
    /* lookup entry /w event & curr_state */
    /* If entry is ignore, return.
     * Otherwise, get state table (according to curr_state or all_state) */
    if ((event <= SMP_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE ))
    {
        if (entry & SMP_ALL_TBL_MASK)
        {
            entry &= ~SMP_ALL_TBL_MASK;
            state_table = smp_all_table;
        }
        else
            state_table = smp_state_table[curr_state][p_cb->role];
    }
    else
    {
        SMP_TRACE_DEBUG( "Ignore event [%s (%d)] in state [%s (%d)]",
                          smp_get_event_name(event), event, smp_get_state_name(curr_state),
                          curr_state);
        return;
    }

    /* Get possible next state from state table. */

    smp_set_state(state_table[entry-1][SMP_SME_NEXT_STATE]);

    /* If action is not ignore, clear param, exec action and get next state.
     * The action function may set the Param for cback.
     * Depending on param, call cback or free buffer. */
    /* execute action */
    /* execute action functions */
    for (i = 0; i < SMP_NUM_ACTIONS; i++)
    {
        if ((action = state_table[entry-1][i]) != SMP_SM_NO_ACTION)
        {
            (*smp_sm_action[action])(p_cb, (tSMP_INT_DATA *)p_data);
        }
        else
        {
            break;
        }
    }
    SMP_TRACE_DEBUG( "result state = %s", smp_get_state_name( p_cb->state ) ) ;
}
Пример #2
0
/*******************************************************************************
**
** Function     smp_sm_event
**
** Description  Handle events to the state machine. It looks up the entry
**              in the smp_entry_table array.
**              If it is a valid entry, it gets the state table.Set the next state,
**              if not NULL state.Execute the action function according to the
**              state table. If the state returned by action function is not NULL
**              state, adjust the new state to the returned state.If (api_evt != MAX),
**              call callback function.
**
** Returns      void.
**
*******************************************************************************/
void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data)
{
    UINT8           curr_state = p_cb->state;
    tSMP_SM_TBL     state_table;
    UINT8           action, entry, i;
    tSMP_ENTRY_TBL  entry_table =  smp_entry_table[p_cb->role];

    SMP_TRACE_EVENT0("main smp_sm_event");
    if (curr_state >= SMP_ST_MAX)
    {
        SMP_TRACE_DEBUG1( "Invalid state: %d", curr_state) ;
        return;
    }

    SMP_TRACE_DEBUG5( "SMP Role: %s State: [%s (%d)], Event: [%s (%d)]",\
                      (p_cb->role == 0x01) ?"Slave" : "Master", smp_get_state_name( p_cb->state),
                      p_cb->state, smp_get_event_name(event), event) ;

    /* look up the state table for the current state */
    /* lookup entry /w event & curr_state */
    /* If entry is ignore, return.
     * Otherwise, get state table (according to curr_state or all_state) */
    if ((event < SMP_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE ))
    {
        if (entry & SMP_ALL_TBL_MASK)
        {
            entry &= ~SMP_ALL_TBL_MASK;
            state_table = smp_all_table;
        }
        else
            state_table = smp_state_table[curr_state][p_cb->role];
    }
    else
    {
#ifdef BLUETOOTH_RTK
        if(event == SMP_MASTER_ID_EVT && p_cb->state == SMP_ST_ENC_PENDING) {
            SMP_TRACE_EVENT1("need to pending event(%d) until SMP_BOND_REQ_EVT", event);
            master_id_pending.pending = TRUE;
            master_id_pending.p_cb = p_cb;
            master_id_pending.event = event;
            master_id_pending.p_data = GKI_getbuf(sizeof(BT_OCTET16)+sizeof(BT_OCTET8));
            memcpy(master_id_pending.p_data, p_data, sizeof(BT_OCTET16)+sizeof(BT_OCTET8));
        } else if(event == SMP_ENCRPTION_INFO_EVT && p_cb->state == SMP_ST_ENC_PENDING) {
            SMP_TRACE_EVENT1("need to pending event(%d) until SMP_BOND_REQ_EVT", event);
            enc_info_pending.pending = TRUE;
            enc_info_pending.p_cb = p_cb;
            enc_info_pending.event = event;
            enc_info_pending.p_data = GKI_getbuf(sizeof(BT_OCTET16));
            memcpy(enc_info_pending.p_data, p_data, sizeof(BT_OCTET16));
        } else
#endif
        SMP_TRACE_DEBUG4( "Ignore event [%s (%d)] in state [%s (%d)]",
                          smp_get_event_name(event), event, smp_get_state_name(curr_state), curr_state);
        return;
    }

    /* Get possible next state from state table. */

    smp_set_state(state_table[entry-1][SMP_SME_NEXT_STATE]);

    /* If action is not ignore, clear param, exec action and get next state.
     * The action function may set the Param for cback.
     * Depending on param, call cback or free buffer. */
    /* execute action */
    /* execute action functions */
    for (i = 0; i < SMP_NUM_ACTIONS; i++)
    {
        if ((action = state_table[entry-1][i]) != SMP_SM_NO_ACTION)
        {
            (*smp_sm_action[action])(p_cb, (tSMP_INT_DATA *)p_data);
        }
        else
        {
            break;
        }
    }
    SMP_TRACE_DEBUG1( "result state = %s", smp_get_state_name( p_cb->state ) ) ;

#ifdef BLUETOOTH_RTK
    if(event == SMP_BOND_REQ_EVT && enc_info_pending.pending == TRUE) {
        SMP_TRACE_EVENT0("to process pending event SMP_ENCRPTION_INFO_EVT");
        smp_sm_event(enc_info_pending.p_cb, enc_info_pending.event, enc_info_pending.p_data);
        enc_info_pending.pending = FALSE;
        GKI_freebuf(enc_info_pending.p_data);
    }

    if(event == SMP_BOND_REQ_EVT && master_id_pending.pending == TRUE) {
        SMP_TRACE_EVENT0("to process pending event SMP_ID_INFO_EVT");
        smp_sm_event(master_id_pending.p_cb, master_id_pending.event, master_id_pending.p_data);
        master_id_pending.pending = FALSE;
        GKI_freebuf(master_id_pending.p_data);
    }

    if(event == SMP_L2CAP_CONN_EVT && p_cb->state == SMP_ST_IDLE) {
        SMP_TRACE_EVENT0("clean enc_info_pending");
        memset(&enc_info_pending, 0 , sizeof(enc_info_pending));
        memset(&master_id_pending, 0 , sizeof(master_id_pending));
    }
#endif
}