/******************************************************************************* ** ** 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 ) ) ; }
/******************************************************************************* ** ** 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 }