//////////////////////////////////////////////////
//Title    : scoc_fsm.c
//Auhtor   : Liu Wei
//Desc     : SCOC fsm implementation   
//Created  : 2007-04-22
//Revision :
//
//Revision :
//
//////////////////////////////////////////////////

#include "./include/sccp_pub.h"
#include "./include/sccp_func.h"

///////////////////////////////////////////////////////////////////////////
//  SCOC special State Machine                                                                  
///////////////////////////////////////////////////////////////////////////

extern void spLogStateError ( u16 wConnId, u8 uErrCode );

void coFsmDiscard ( u16 wConnId )
{
    spLogStateError ( wConnId, ERR_FSM_DISCARD );
}

void coFsmError ( u16 wConnId )
{
    spLogStateError ( wConnId, ERR_FSM_ERROR );
}

void coFsmFatal ( u16 wConnId )
{
    spLogStateError ( wConnId, ERR_FSM_FATAL );
}

void coFsmReserved ( u16 wConnId )
{
    spLogStateError ( wConnId, ERR_FSM_RESERVED );
}

///////////////////////////////////////////////////////////////////////////
//  SCOC State Machine declare --Q.714 Page 85 - Page 127                                                                
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
//  SCOC State Machine implementation --Q.714 Page 85 - Page 127                                                                
///////////////////////////////////////////////////////////////////////////

void _Below_fsm_is_supported_ (  )
{

}

///////////////////////////////////////////////////////////////////////////
//  origination node connection establishment procedures 
//      -- IDLE State                                                              
///////////////////////////////////////////////////////////////////////////

void coOCEP_IDLE ( u16 wConnId )
{
    CO_ConnSection *pCS;

    pCS = &pSp->tCo.tCSInst[wConnId];

    switch ( pCS->uPri )
    {
    case N_CONNECT_REQ:
        if( !coNewCS ( wConnId, &pCS->tCDA ) )
        {
            //have check resource in coNewConnId
            goto Err_Resource_Limited;
        }
        pCS->tmSCOC.tmConnEst = 1;
        co2cr ( wConnId, SP_MSG_CR );
        pCS->uCState = CO_STATUS_CPOG;
        return;
    case N_CONNECT_T1:
        //not supported now for ISUP
//        WxcAssert ( 0, "coOCEP_IDLE unexpected event, not supported now" );
        if( !coNewCS ( wConnId, &pCS->tCDA ) )
        {
            goto Err_Resource_Limited;
        }
        co2ul ( wConnId, RELAY );
        pCS->tmSCOC.tmConnEst = 1;
        pCS->uCState = CO_STATUS_CPOG;
        return;
    case R_RLSD:
        //have handled in cr2co
        //co2cr ( wConnId, SP_MSG_RLC );
        //pCS->uCState = CO_STATUS_INIT;
//        WxcAssert ( 0, "coOCEP_IDLE unexpected event" );
        return;
    case R_RLC:
    case R_IT:
        //have handled in cr2co
        //pCS->uCState = CO_STATUS_INIT;
//        WxcAssert ( 0, "coOCEP_IDLE unexpected event" );
        return;
    default:
    	//have handled in cr2co
        //if( coGetConnId ( pCS->aSLR ) < 0 )
        //{
        //    co2cr ( wConnId, SP_MSG_ERR );
        //}
        //pCS->uCState = CO_STATUS_INIT;
//        WxcAssert ( 0, "coOCEP_IDLE unexpected event" );
        return;
    }
  Err_Resource_Limited:
    {
        pCS->eREA = REA_PDISC_ACNN;
        co2ul ( wConnId, N_DISCONNECT_IND );
        pCS->uCState = CO_STATUS_INIT;
	pSp->tCo.wConnIdCount--;
    }
    return;
}

///////////////////////////////////////////////////////////////////////////
//  origination node connection establishment procedures 
//      -- Connection pending outgoing  state                                                             
///////////////////////////////////////////////////////////////////////////

void coOCEP_CPOG ( u16 wConnId )
{
    CO_ConnSection *pCS;

    pCS = &pSp->tCo.tCSInst[wConnId];

    switch ( pCS->uPri )
    {
    case N_DISCONNECT_REQ:
        pCS->uCState = CO_STATUS_WTCC;
        return;
    case T_CONNEST_OUT:
        goto Release_Resource_1;
    case R_RF:
        goto Release_Resource_0;
    case R_RLSD:
        co2cr ( wConnId, SP_MSG_RLC );
        goto Release_Resource_0;
    case R_CC:
        pCS->tmSCOC.tmConnEst = 0;
	pCS->tmSCOC.tmIas = 1;	
        pCS->tmSCOC.tmIar  = 1;
        //class credit dlr fill in coFillCS

        co2ul ( wConnId, N_CONNECT_CFM );
        pCS->uCState = CO_STATUS_ACTV;
        return;
    case R_CREF:
		pCS->tmSCOC.tmConnEst = 0;
		goto Release_Resource_1;
    default:
        goto Release_Resource_0;
    }
  Release_Resource_0:
    {
        pCS->tmSCOC.tmConnEst = 0;
    }
  Release_Resource_1:
    //freeze local reference P86
    {
        co2ul ( wConnId, N_DISCONNECT_IND );
        coFreeCS ( wConnId );
        pCS->uCState = CO_STATUS_INIT;
    }

    return;
}

///////////////////////////////////////////////////////////////////////////
//  origination node connection establishment procedures 
//      -- Wait Connection confirm  state                                                         
///////////////////////////////////////////////////////////////////////////

void coOCEP_WTCC ( u16 wConnId )
{
    CO_ConnSection *pCS;

    pCS = &pSp->tCo.tCSInst[wConnId];

    switch ( pCS->uPri )
    {
    case R_RLSD:
        co2cr ( wConnId, SP_MSG_RLC );
        goto Early_Release;
    case R_CC:
        pCS->tmSCOC.tmConnEst = 0;
        //dlr fill in coFillCS
        co2cr ( wConnId, SP_MSG_RLSD );
        pCS->tmSCOC.tmRel = 1;
        pCS->uCState = CO_STATUS_DSCP;
        return;
    case R_CREF:
    case R_RF:
        goto Early_Release;
    case T_CONNEST_OUT:
        //freeze local reference P87
        coFreeCS ( wConnId );
        pCS->uCState = CO_STATUS_INIT;
        return;
    default:
        //freeze local reference P87
        goto Early_Release;
    }
  Early_Release:
    {
        pCS->tmSCOC.tmConnEst = 0;
        coFreeCS ( wConnId );
        pCS->uCState = CO_STATUS_INIT;
    }
    return;
}

///////////////////////////////////////////////////////////////////////////
//  origination node connection release procedures 
//      -- active state                                                             
///////////////////////////////////////////////////////////////////////////

void coOCRP_ACTV ( u16 wConnId )
{
    CO_ConnSection *pCS;

    pCS = &pSp->tCo.tCSInst[wConnId];

    switch ( pCS->uPri )
    {
    case I_DISCONNECT:
        goto Disconnect_Pending_0;
    case N_DISCONNECT_REQ:
        goto Disconnect_Pending_1;
    case R_CC:
    case R_CREF:
    case R_RLC:
        return;
    case R_RLSD:
        co2ul ( wConnId, N_DISCONNECT_IND );
        //Freeze local reference P89
        pCS->tmSCOC.tmIar = 0;
        co2cr ( wConnId, SP_MSG_RLC );
        coFreeCS ( wConnId );
        pCS->uCState = CO_STATUS_INIT;
        return;
    case R_ERR:
        if( pCS->uClass == 2 )
        {
            goto Disconnect_Pending_0;
        }
        //Freeze local reference P89

        co2ul ( wConnId, N_DISCONNECT_IND );
        pCS->tmSCOC.tmIar = 0;
        coFreeCS ( wConnId );
        pCS->uCState = CO_STATUS_INIT;
        return;
    case T_IAR_OUT:
        goto Disconnect_Pending_1;
    case R_RF:
        co2ul ( wConnId, N_DISCONNECT_IND );
        pCS->tmSCOC.tmIar = 0;
        pCS->tmSCOC.tmRel = 1;
        pCS->uCState = CO_STATUS_DSCP;
        return;
    default:
    	return;
    }
  Disconnect_Pending_0:
    {
        co2ul ( wConnId, N_DISCONNECT_IND );
    }
  Disconnect_Pending_1:
    {
        pCS->tmSCOC.tmIar = 0;
        co2cr ( wConnId, SP_MSG_RLSD );
        pCS->tmSCOC.tmRel = 1;
        pCS->uCState = CO_STATUS_DSCP;
    }
    return;
}

///////////////////////////////////////////////////////////////////////////
//  origination node connection release procedures 
//      -- disconnection pending state                                                             
///////////////////////////////////////////////////////////////////////////

void coOCRP_DSCP ( u16 wConnId )
{
    CO_ConnSection *pCS;

    pCS = &pSp->tCo.tCSInst[wConnId];

    switch ( pCS->uPri )
    {
    case R_RLC:
    case R_RLS_ERR:
        goto Release;
    case R_RF:
        return;
    case T_RLS_OUT:
        co2cr ( wConnId, SP_MSG_RLSD );
        pCS->tmSCOC.tmInternal = 1;
        pCS->tmSCOC.tmRepeatRel = 1;
        return;
    case T_INTERNAL_OUT:
    	//unsupported now
        co2scmg (  );
        goto Release;
    case T_REPEATE_RLS_OUT:
        co2cr ( wConnId, SP_MSG_RLSD );
        pCS->tmSCOC.tmRepeatRel = 1;
        return;
    case R_RLSD:
		pCS->tmSCOC.tmIar = 0;
		co2cr ( wConnId, SP_MSG_RLC );
		return;		
    default:
        //discard message
        return;
    }
  Release:
    {
        //Freeze local reference P90
        pCS->tmSCOC.tmRel = 0;
        pCS->tmSCOC.tmInternal = 0;
        coFreeCS ( wConnId );
        pCS->uCState = CO_STATUS_INIT;
    }
    return;

}

///////////////////////////////////////////////////////////////////////////
//  distination node connection establishment procedures 
//      -- idle  state                                                             
///////////////////////////////////////////////////////////////////////////

void coDCEP_IDLE ( u16 wConnId )
{
    CO_ConnSection *pCS;

    pCS = &pSp->tCo.tCSInst[wConnId];

    switch ( pCS->uPri )
    {
    case R_CR:
        if( !coCheckResource (  ) )
        {
            goto Refuse_Connection;
        }
        goto Connecting;
    case R_RF:
        goto Refuse_Connection;
    case R_CR2:
    	//not supported now
//        WxcAssert ( 0, "coDCEP_IDLE unexpected event, not supported now" );
    	//if( set CREF ind )
    	if( 1 )
        {
            goto Refuse_Connection;
        }
        if( coCheckResource (  ) )
        {
            goto Connecting;
        }
        co2ul ( wConnId, N_DISCONNECT_IND );
        goto Refuse_Connection;
    case R_RLSD:
    	//have handled in cr2co
        //co2cr ( wConnId, SP_MSG_RLSD );
	pSp->tCo.wConnIdCount--;
        pCS->uCState = CO_STATUS_INIT;
 //       WxcAssert ( 0, "coDCEP_IDLE unexpected event" );
        return;
    case R_RLC:
    case R_IT:
    	//have handled in cr2co
	pSp->tCo.wConnIdCount--;
        pCS->uCState = CO_STATUS_INIT;
 //       WxcAssert ( 0, "coDCEP_IDLE unexpected event" );
        return;
    default:
    	//have handled in cr2co
//    	WxcAssert ( 0, "coDCEP_IDLE unexpected event" );
        //if( coGetConnId ( pCS->aSLR ) < 0 )
        //{
        //    co2cr ( wConnId, SP_MSG_ERR );
        //}
        pSp->tCo.wConnIdCount--;
	pCS->uCState = CO_STATUS_INIT;
        return;

    }
  Refuse_Connection:
    {
        pCS->eREA = REA_PDISC_ACNN;
        co2cr ( wConnId, SP_MSG_CREF );
        pCS->uCState = CO_STATUS_INIT;
	pSp->tCo.wConnIdCount--;
        return;
    }
  Connecting:
    {
        coNewCS ( wConnId, &pCS->tCDA );
        co2ul ( wConnId, N_CONNECT_IND );
        pCS->uCState = CO_STATUS_CPIC;
	 pCS->tmSCOC.tmConnEst = 1;
    }
    return;
}

///////////////////////////////////////////////////////////////////////////
//  destination node connection establishment procedures 
//      -- connection pending incoming  state                                                             
///////////////////////////////////////////////////////////////////////////

void coDCEP_CPIC ( u16 wConnId )
{
    CO_ConnSection *pCS;

    pCS = &pSp->tCo.tCSInst[wConnId];

    switch ( pCS->uPri )
    {
    case N_CONNECT_RSP:
        //coNewCS ( wConnId  , &pCS->tCDA );
        co2cr ( wConnId, SP_MSG_CC );
	pCS->tmSCOC.tmIas = 1;	
        pCS->tmSCOC.tmIar = 1;
        pCS->uCState = CO_STATUS_ACTV;
	pCS->tmSCOC.tmConnEst = 0;
        return;
    case N_DISCONNECT_REQ:
        //P93
        co2cr ( wConnId, SP_MSG_CREF );
        coFreeCS ( wConnId );
        pCS->uCState = CO_STATUS_INIT;
	return;
    case T_CONNEST_OUT:
        //freeze local reference P87
        coFreeCS ( wConnId );
        pCS->uCState = CO_STATUS_INIT;
        return;
    default:
        //discard message
        return;
    }

}

///////////////////////////////////////////////////////////////////////////
//  distination node connection release procedures 
//      -- active state                                                             
///////////////////////////////////////////////////////////////////////////

void coDCRP_ACTV ( u16 wConnId )
{
    CO_ConnSection *pCS;


    pCS = &pSp->tCo.tCSInst[wConnId];

    switch ( pCS->uPri )
    {
    case N_DISCONNECT_REQ:
        goto Disconnect_1;
    case I_DISCONNECT:
        goto Disconnect_0;
    case R_CC:
    case R_CREF:
    case R_RLC:
        return;
    case R_RLSD:
        co2ul ( wConnId, N_DISCONNECT_IND );
        pCS->tmSCOC.tmIar = 0;
        co2cr ( wConnId, SP_MSG_RLC );
        coFreeCS ( wConnId );
        pCS->uCState = CO_STATUS_INIT;
        return;
    case R_ERR:
        if( pCS->uClass == 2 )
        {
            goto Disconnect_0;
        }
        co2ul ( wConnId, N_DISCONNECT_IND );
        pCS->tmSCOC.tmIar = 0;
        coFreeCS ( wConnId );
        pCS->uCState = CO_STATUS_INIT;
        return;
    case R_RF:
        goto Disconnect_0;
    case T_IAR_OUT:
        co2ul ( wConnId, N_DISCONNECT_IND );
        pCS->tmSCOC.tmIar = 0;
        pCS->tmSCOC.tmRel = 1;
        pCS->uCState = CO_STATUS_DSCP;
        return;
     default:
     	return;
    }
  Disconnect_0:
    {
        co2ul ( wConnId, N_DISCONNECT_IND );
    }
  Disconnect_1:
    {
        pCS->tmSCOC.tmIar = 0;
        co2cr ( wConnId, SP_MSG_RLSD );
        pCS->tmSCOC.tmRel = 1;
        pCS->uCState = CO_STATUS_DSCP;
    }

    return;
}

///////////////////////////////////////////////////////////////////////////
//  distination node connection release procedures 
//      -- disconnect pending state                                                             
///////////////////////////////////////////////////////////////////////////

void coDCRP_DSCP ( u16 wConnId )
{
    CO_ConnSection *pCS;

    pCS = &pSp->tCo.tCSInst[wConnId];

    switch ( pCS->uPri )
    {
    case R_RLC:
    case R_ERR:
        pCS->tmSCOC.tmRel= 0;
        pCS->tmSCOC.tmInternal = 0;
        coFreeCS ( wConnId );
        pCS->uCState = CO_STATUS_INIT;
        return;
    case R_RF:
        return;
    case T_INTERNAL_OUT:
        //notify management
        //inform maintaenance
        co2scmg (  );
        
        pCS->tmSCOC.tmRel = 0;
        pCS->tmSCOC.tmInternal= 0;
        coFreeCS ( wConnId );
        pCS->uCState = CO_STATUS_INIT;
        return;
    case T_RLS_OUT:
        co2cr ( wConnId, SP_MSG_RLSD );
        pCS->tmSCOC.tmRepeatRel = 1;
        pCS->tmSCOC.tmInternal = 1;
        return;
    case T_REPEATE_RLS_OUT:
        co2cr ( wConnId, SP_MSG_RLSD );
        pCS->tmSCOC.tmRepeatRel = 1;
        return;
    case R_RLSD:
		pCS->tmSCOC.tmIar = 0;
		co2cr ( wConnId, SP_MSG_RLC );
		return;		
    default:
        //discare message
        return;
    }

}

///////////////////////////////////////////////////////////////////////////
//  origination and distination node data transfer procedures 
//      -- active state                                                             
///////////////////////////////////////////////////////////////////////////

void coODDT_ACTV ( u16 wConnId )
{
    CO_ConnSection *pCS;

    pCS = &pSp->tCo.tCSInst[wConnId];

    switch ( pCS->uPri )
    {
    case N_DATA_REQ:
        co2cr ( wConnId, SP_MSG_DT1 );
        pCS->tmSCOC.tmIas = 1;
        return;
    case R_DT1:
    	pCS->tmSCOC.tmIar = 1;
        co2ul ( wConnId, N_DATA_IND );
        return;
    case R_DT2:
//    	WxcAssert ( 0, "coODDT_ACTV unsupport R_DT2 now" );
        //do not supported now
        return;
    case R_AK:
//    	WxcAssert ( 0, "coODDT_ACTV unsupport R_AK now" );
        //do not supported now
        return;
    case T_IAS_OUT:
        co2cr ( wConnId, SP_MSG_IT );
        pCS->tmSCOC.tmIas = 1;
        return;
    case R_IT:
        //P101
        if( !( pCS->uClass < 3 && coGetConnId ( pCS->aSLR ) >= 0 ) )
        {
            co2ul ( wConnId, N_DISCONNECT_IND );
            pCS->tmSCOC.tmIar = 0;
            co2cr ( wConnId, SP_MSG_RLSD );
            pCS->tmSCOC.tmRel = 1;
            pCS->uCState = CO_STATUS_DSCP;
            return;
        }
        else if( pCS->uClass == 2 )
        {
            pCS->tmSCOC.tmIar = 1;
        }
        else if( spCheckAudit (  ) )
        {
            pCS->tmSCOC.tmIar = 1;
        }
        else
        {
            co2co ( wConnId, I_RESET_REQ );
        }
        return;
    case I_CONGESTED:
    case I_UNCONGESTED:
//    	WxcAssert ( 0, "coODDT_ACTV unsupport I_CONGESTED/I_UNCONGESTED now" );
        //do not supported now
        return;
    default:
//    	WxcAssert ( 0, "coODDT_ACTV unexpected primitive now" );
        return;
    }

}

static void coODED_ACTV ( u16 wConnId );
static void coODRS_ACTV ( u16 wConnId );

///////////////////////////////////////////////////////////////////////////
//  Active FSM on origination , distination and intermedia node 
//      -- include establishment, data transfer , release procedures                                                             
///////////////////////////////////////////////////////////////////////////

void coODMP_ACTV ( u16 wConnId )
{
    CO_ConnSection *pCS;

    pCS = &pSp->tCo.tCSInst[wConnId];
    switch ( pCS->uPri )
    {
    case N_DISCONNECT_REQ:     //User->SCOC : N-DISCONNECT Request 
    case I_DISCONNECT:         //internal disconnect
    case R_CREF:               //SCRC->SCOC Connection refused
    case R_CC:                 //SCRC->SCOC Connection confirm
    case R_RLC:                //SCRC->SCOC Release complete
    case R_RLSD:               //SCRC->SCOC Released
    case R_ERR:                //SCRC->SCOC Error
    case T_IAR_OUT:        //Recieve inactivity timer expires
    case R_RF:                 //Routing Fail
        switch ( pCS->uSide )
        {
        case CO_INST_SIDE_ORG:
            coOCRP_ACTV ( wConnId );
            return;
        case CO_INST_SIDE_DST:
            coDCRP_ACTV ( wConnId );
            return;
            //case CO_INST_SDIE_MID: //do not supported middle node side now
        default:
            coFsmReserved ( wConnId );
            return;
        }
    case N_DATA_REQ:           //User->SCOC : N-Data Request 
    case R_DT1:                //SCRC->SCOC DT1
    case R_DT2:                //SCRC->SCOC DT2
    case R_AK:                 //SCRC->SCOC Data acknowledg
    case T_IAS_OUT:        //Send inactivity timer expires
    case R_IT:                 //SCRC->SCOC IT   
    case I_CONGESTED:          //Congested
    case I_UNCONGESTED:        //Uncongested     
        switch ( pCS->uSide )
        {
        case CO_INST_SIDE_ORG:
        case CO_INST_SIDE_DST:
            coODDT_ACTV ( wConnId );
            return;
            //case CO_INST_SDIE_MID: //do not supported middle node side now
        default:
            coFsmReserved ( wConnId );
            return;
        }
    case N_EDATA_REQ:          //User->SCOC : N-Data Request 
    case R_EA:                 //SCRC->SCOC EData acknowledg
    case R_ED:                 //SCRC->SCOC ED
        switch ( pCS->uSide )
        {
        case CO_INST_SIDE_ORG:
        case CO_INST_SIDE_DST:
            coODED_ACTV ( wConnId );
            return;
            //case CO_INST_SDIE_MID: //do not supported middle node side now
        default:
            coFsmReserved ( wConnId );
            return;
        }
    
    case N_RESET_REQ:          //User->SCOC : N-Reset Request 
    case I_RESET_REQ:          //SCRC->SCOC Reset Request
    case R_RSC:                //SCRC->SCOC Reset confirm
    case R_RSR:                //internal reset Request
        switch ( pCS->uSide )
        {
        case CO_INST_SIDE_ORG:
        case CO_INST_SIDE_DST:
            coODRS_ACTV ( wConnId );
            return;
            //case CO_INST_SDIE_MID: //do not supported middle node side now
        default:
            coFsmReserved ( wConnId );
            return;
        }
        //coODRS_ACTV ( wConnId );
    default:
        coFsmDiscard ( wConnId );
        return;
    }

}

void _Above_fsm_is_supported_ (  )
{

}

void _Below_fsm_is_Unsupported_ (  )
{

}

///////////////////////////////////////////////////////////////////////////
//  The Fsm below is not supporte now(SCCP R9.0.0)                                                           
///////////////////////////////////////////////////////////////////////////

void coODED_ACTV ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coODED_WSEA ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coODRS_ACTV ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coODRS_RSIC ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coODRS_RSOG ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coODRS_RSBH ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMCEP_ACTV ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMCEP_CONP ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMCRP_ACTV ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMCRP_DPOG ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMCRP_DPIC ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMCRP_DPBH ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMDTP_ACTV ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMEDP_ACTV ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMEDP_WSEA ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMRSP_ACTV ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMRSP_RSOG ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMRSP_RSIC ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coMRSP_RSBH ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////

void coODMP_RSTA ( u16 wConnId )
{
    coFsmReserved ( wConnId );
    return;
}

void _Above_fsm_is_Unsupported_ (  )
{

}

///////////////////////////////////////////////////////////////////////////
//  SCOC State Machine Matricies                                                                 
///////////////////////////////////////////////////////////////////////////

typedef void ( *coFsmFunc ) ( u16 wConnId );

#define CO_NODE_STYLE_MAX  3    //node type : origination,destination,intermediate

static const coFsmFunc coFsmFuncSuit[][CO_STATUS_MAX + 1] = {
    {                           //origination node stat machine
     coFsmDiscard,              //CO_STATUS_INIT : Transtion initialed
     coOCEP_IDLE,               //CO_STATUS_IDLE : status Idle
     coOCEP_WTCC,               //CO_STATUS_WTCC : Wait Connection confirm
     coODMP_ACTV,               //CO_STATUS_ACTV : Active
     coFsmError,                //CO_STATUS_CONP : Connection pending 
     coFsmError,                //CO_STATUS_CPIC : Connection pending incoming
     coOCEP_CPOG,               //CO_STATUS_CPOG : Connection pending outgoing
     coOCRP_DSCP,               //CO_STATUS_DSCP : Disconnect pending
     coFsmError,                //CO_STATUS_DPIC : Disconnect pending incoming
     coFsmError,                //CO_STATUS_DPOG : Disconnect pending outgoing
     coFsmError,                //CO_STATUS_DPBH : Disconnect pending both
     coFsmError,                //CO_STATUS_NMOP : Normal operation
     coODED_WSEA,               //CO_STATUS_WSEA : Wait for sending EA Message
     coODRS_RSOG,               //CO_STATUS_RSIC : Reset outgoing
     coODRS_RSIC,               //CO_STATUS_RSOG : Reset incoming
     coODRS_RSBH,               //CO_STATUS_RSBH : Reset both
     coFsmError,                //CO_STATUS_MTBK : Maintenance blocking
     coODMP_RSTA,               //CO_STATUS_RSTA : Restart   
     coFsmFatal,                //CO_STATUS_MAX
     },
    {                           //destination node stat machine
     coFsmDiscard,              //CO_STATUS_INIT : Transtion initialed
     coDCEP_IDLE,               //CO_STATUS_IDLE : status Idle
     coFsmError,                //CO_STATUS_WTCC : Wait Connection confirm
     coODMP_ACTV,               //CO_STATUS_ACTV : Active
     coFsmError,                //CO_STATUS_CONP : Connection pending 
     coDCEP_CPIC,               //CO_STATUS_CPIC : Connection pending incoming
     coFsmError,                //CO_STATUS_CPOG : Connection pending outgoing
     coDCRP_DSCP,               //CO_STATUS_DSCP : Disconnect pending
     coFsmError,                //CO_STATUS_DPIC : Disconnect pending incoming
     coFsmError,                //CO_STATUS_DPOG : Disconnect pending outgoing
     coFsmError,                //CO_STATUS_DPBH : Disconnect pending both
     coFsmError,                //CO_STATUS_NMOP : Normal operation
     coODED_WSEA,               //CO_STATUS_WSEA : Wait for sending EA Message
     coODRS_RSOG,               //CO_STATUS_RSIC : Reset outgoing
     coODRS_RSIC,               //CO_STATUS_RSOG : Reset incoming
     coODRS_RSBH,               //CO_STATUS_RSBH : Reset both
     coFsmError,                //CO_STATUS_MTBK : Maintenance blocking
     coODMP_RSTA,               //CO_STATUS_RSTA : Restart    
     coFsmFatal,                //CO_STATUS_MAX
     },
    {                           //intermedia node stat machine
     coFsmDiscard,              //CO_STATUS_INIT : Transtion initialed
     coFsmError,                //CO_STATUS_IDLE : status Idle
     coFsmError,                //CO_STATUS_WTCC : Wait Connection confirm
     coODMP_ACTV,               //CO_STATUS_ACTV : Active
     coMCEP_CONP,               //CO_STATUS_CONP : Connection pending 
     coFsmError,                //CO_STATUS_CPIC : Connection pending incoming
     coFsmError,                //CO_STATUS_CPOG : Connection pending outgoing
     coFsmError,                //CO_STATUS_DSCP : Disconnect pending
     coFsmError,                //CO_STATUS_DPIC : Disconnect pending incoming
     //coMCEP_DPIC,       //CO_STATUS_DPIC : Disconnect pending incoming
     coFsmError,                //CO_STATUS_DPOG : Disconnect pending outgoing
     //coMCEP_DPOG,       //CO_STATUS_DPOG : Disconnect pending outgoing
     coFsmError,                //CO_STATUS_DPBH : Disconnect pending both
     //coMCEP_DPBH,       //CO_STATUS_DPBH : Disconnect pending both
     coFsmError,                //CO_STATUS_NMOP : Normal operation
     coMEDP_WSEA,               //CO_STATUS_WSEA : Wait for sending EA Message
     coMRSP_RSOG,               //CO_STATUS_RSIC : Reset outgoing
     coMRSP_RSIC,               //CO_STATUS_RSOG : Reset incoming
     coMRSP_RSBH,               //CO_STATUS_RSBH : Reset both
     coFsmError,                //CO_STATUS_MTBK : Maintenance blocking
     coODMP_RSTA,               //CO_STATUS_RSTA : Restart    
     coFsmFatal,                //CO_STATUS_MAX
     },
};

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////
int coCheckStatus( u32 wConnId)
{
	int stat = pSp->tCo.tCSInst[wConnId].uCState;

//	WxcAssert(stat < CO_STATUS_MAX, "SCOC Fatal error, unexpected status");
	if(stat >= CO_STATUS_MAX)
		spShowErr(1, "SCOC Fatal error, unexpected status");
	return (stat < CO_STATUS_MAX);
}

void coFsm (  )
{
//    u8  nLoop;
    u16 wConnId;
    SP_PriPoolEle tPri;
    CO_ConnSection *pCS;

//    for ( nLoop = 0; nLoop < 16; nLoop++ )
	while ( spPoolGet ( &tPri, pInCoPool ) )
    {
//        if( !spPoolGet ( &tPri, pInCoPool ) )
//        {
//            break;
//        }
        
        coFillCS ( &tPri );
        
        pCS = &pSp->tCo.tCSInst[tPri.tCrPri.wConnId];
        
        if( CO_STATUS_INIT == pCS->uCState || 
        	!coCheckCS ( tPri.tCrPri.wConnId, pCS->uCState, pCS->uSide ) )
        {
            continue;
        }

        if( pCS->uPri )
        {
			if ( coCheckStatus(tPri.tCrPri.wConnId) )
				( *coFsmFuncSuit[pCS->uSide][pCS->uCState] ) ( tPri.tCrPri.wConnId );
			else{
				coFreeCS(tPri.tCrPri.wConnId);
			}
        }
        pCS->uPri = 0;
    }

    for ( wConnId = 0; wConnId < CO_CS_MPORT; wConnId++ )
    {
        pCS = &pSp->tCo.tCSInst[wConnId];

        if( CO_STATUS_INIT == pCS->uCState || !coCheckCS ( wConnId, pCS->uCState, pCS->uSide ) )
        {
            continue;
        }

        if( pCS->uPri )
        {
			if ( coCheckStatus(tPri.tCrPri.wConnId) )
				( *coFsmFuncSuit[pCS->uSide][pCS->uCState] ) ( wConnId );
			else{
				coFreeCS(tPri.tCrPri.wConnId);
			}
        }
        pCS->uPri = 0;
    }

	///////////////////////Below is used for test////////////////////////
/*	register_ssn ( 142, 4 );
	int i;
	SP_UiPriPara tmp;
	for ( i = 3; i < 5; i++ )
	{
		while ( SpSubmit ( &tmp, i ) )
		{
			printf ( "uUiPri: %d\n", tmp.uUiPri);
			printf ( "uAnsiFlag: 0x%X\n", tmp.uAnsiFlag);
			printf ( "wConnId: %d\n", tmp.wConnId);
			printf ( "NetID : %d RI : %d SSN : %d\n", tmp.tPriUnion.tPriNConnInd.tCDA.NetID
						, tmp.tPriUnion.tPriNConnInd.tCDA.RI, tmp.tPriUnion.tPriNConnInd.tCDA.SSN );
			printf ( "PriNConnectInd: 0x%X\n", tmp.tPriUnion.tPriNConnInd);
		}
	}*/
}
