//////////////////////////////////////////////////
//Title    : scoc_if.c
//Auhtor   : Liu Wei
//Desc     : SCOC interface implementation  
//Created  : 2007-05-07
//Revision :
//
//Revision :
//
//////////////////////////////////////////////////

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

// fix multiple definition====================================
SP_Entity tSpEntity;
SP_Entity *pSp;
//

void spWatchDogStatic ( u8 uDebugStaticMask );

void coInit ( u32 sysID, u32 localIP, u32 alterIP  )
{
    pSp = &tSpEntity;

    memset ( pSp, 0, sizeof ( SP_Entity ) );
    spPoolInit (  );
    pSp->dLocalIP = localIP;
	pSp->dAlterIP = alterIP;
	pSp->dSysID = sysID + 1;
}

void cr2coFailHandle ( Intra_Msg * pIntraMsg, u8 uAnsiFlag, u8 uMsgtype )
{
    Intra_Msg tCo2CrMsg;

    memset ( &tCo2CrMsg, 0, sizeof ( Intra_Msg ) );
    switch ( uMsgtype )
    {
	case SP_MSG_RLSD:
		pIntraMsg->cause = REA_PCREF_IS;
    case SP_MSG_RLC:
        memcpy ( &tCo2CrMsg.aDLR, &pIntraMsg->aSLR, SP_REF_LEN );
        memcpy ( &tCo2CrMsg.aSLR, &pIntraMsg->aDLR, SP_REF_LEN );
        break;
    case SP_MSG_ERR:
        tCo2CrMsg.cause = REA_PDISC_IS;
        break;
    case SP_MSG_CREF:
        tCo2CrMsg.cause = REA_PCREF_LE;
        break;
    default:
//        WxcAssert ( 0, "cr2coFailHandle internal error" );
        break;
    }

    tCo2CrMsg.msgsource = FROM_SCOC;
    tCo2CrMsg.msgtype = uMsgtype;
    tCo2CrMsg.msgclass = pIntraMsg->msgclass;
    tCo2CrMsg.NetID = pIntraMsg->CDA.NetID;
    tCo2CrMsg.OPC = SCCP_Param.spc[tCo2CrMsg.NetID];
    
    //scrc_route ( &tCo2CrMsg, uAnsiFlag );
    
    tCo2CrMsg.CDA.DPC = tCo2CrMsg.DPC =  pIntraMsg->OPC;
    
    tCo2CrMsg.SLS = pIntraMsg->SLS;
    tCo2CrMsg.CDA.ip = 0xffffffff; 
    send_msg ( &tCo2CrMsg, uAnsiFlag);
    spWatchDogStatic ( CO_TO_CR );
    return;
}

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

int cr2co ( Intra_Msg * pIntraMsg, u8 uAnsiFlag )
{
    int nRet;
    u8 *pStr;
    SP_PriPoolEle pPri;

    spWatchDogStatic ( CR_TO_CO_APT );

//    WxcAssert ( pIntraMsg->msgtype < SP_MSG_MAX, "SCCP cr2co unexpected msgtype" );
	if(pIntraMsg->msgtype >= SP_MSG_MAX)
		spShowErr(1, "SCCP cr2co unexpected msgtype" );

    spGetMsgStr ( pIntraMsg->msgtype, pStr );

    switch ( pIntraMsg->msgtype )
    {
    case SP_MSG_CR:
//        if( ( coGetConnId ( pIntraMsg->aSLR ) >= 0 ) || ( ( nRet = coNewConnId ( R_CR ) ) < 0 ) )
	if( (nRet = coNewConnId ( R_CR )) < 0 )
        {
            spLogDebug ( SCCPDB_ERR, "[cr2co]No resourece for %s", pStr );
            cr2coFailHandle ( pIntraMsg, uAnsiFlag, SP_MSG_CREF );
            return 0 ;
        }
        break;
    case SP_MSG_RLSD:
        nRet = coGetConnId ( pIntraMsg->aDLR );
        if( nRet < 0 )
        {
            spLogDebug ( SCCPDB_ERR, "[sr2co]recv %s msg in init state, cr2co return  error ", pStr );
            cr2coFailHandle ( pIntraMsg, uAnsiFlag, SP_MSG_RLC );
             return 0 ;
        }
        break;
    case SP_MSG_RF:
        nRet = coGetConnId ( pIntraMsg->aDLR );
        if( nRet < 0 )
        {
            spLogDebug ( SCCPDB_ERR, "[sr2co]recv RF msg in init state, co2cr return cref ", pStr );
            cr2coFailHandle ( pIntraMsg, uAnsiFlag, SP_MSG_CREF );
             return 0 ;
        }
        break;
	case SP_MSG_IT:
		nRet = coGetConnId ( pIntraMsg->aDLR );
		if( nRet < 0 )
		{
			spLogDebug ( SCCPDB_ERR, "[sr2co]recv IT msg in init state,discard " );
			cr2coFailHandle ( pIntraMsg, uAnsiFlag, SP_MSG_RLSD );
			return 0 ;
		}
		break;
    case SP_MSG_RLC:
        nRet = coGetConnId ( pIntraMsg->aDLR );
        if( nRet < 0 )
             return 0 ;
        break;
    default:
        nRet = coGetConnId ( pIntraMsg->aDLR );
        if( nRet < 0 )
        {
            spLogDebug ( SCCPDB_ERR, "[sr2co]recv %s msg in init state", pStr );
            if( memcmp ( pIntraMsg->aSLR, "/0/0/0", SP_REF_LEN ) )
            {
                spLogDebug ( SCCPDB_ERR, "[sr2co]recv %s msg in init state, co2cr return  error ", pStr );
//                cr2coFailHandle ( pIntraMsg, uAnsiFlag, SP_MSG_RLSD );
            }
             return 0 ;
        }
        break;
    }
    pPri.tCrPri.wConnId = nRet;
    pPri.tCrPri.uUiPri = pIntraMsg->msgtype + SPUI_PRI_MAX;
    pPri.tCrPri.uAnsiFlag = uAnsiFlag;
    memcpy ( &pPri.tCrPri.tIntraMsg, pIntraMsg, sizeof ( Intra_Msg ) );

    spPoolPut ( &pPri, pInCoPool );
    spWatchDogStatic ( CR_TO_CO );
    return 1;

}

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

void co2cr ( u16 wConnId, u8 uMsgType )
{
    CO_ConnSection *pCS;
	Intra_Msg tCo2CrMsg;

    spWatchDogStatic ( CO_TO_CR_APT );

//    WxcAssert ( wConnId < CO_CS_MPORT, "SCCP co2cr unexpected connection id" );
	if(wConnId >= CO_CS_MPORT)
		spShowErr(1,  "SCCP co2cr unexpected connection id" );
//    WxcAssert ( uMsgType < SP_MSG_MAX, "SCCP cr2co unexpected msgtype" );
	if(uMsgType >= SP_MSG_MAX)
		spShowErr(1,  "SCCP cr2co unexpected msgtype" );

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

    memset ( &tCo2CrMsg, 0, sizeof ( Intra_Msg ) );
    tCo2CrMsg.msgsource = FROM_SCOC;
    tCo2CrMsg.msgtype   = uMsgType;
    tCo2CrMsg.msgclass  = pCS->uClass;
    tCo2CrMsg.NetID     = pCS->uNetId;

    switch ( uMsgType )
    {
    case SP_MSG_CR:
        
        tCo2CrMsg.msglen = 0;

        if( pCS->tUD.uDataLen )
        {
            tCo2CrMsg.msglen = pCS->tUD.uDataLen % 256;
            memcpy ( &tCo2CrMsg.data, pCS->tUD.aUserData, tCo2CrMsg.msglen );
        }
        memcpy( &tCo2CrMsg.CDA , &pCS->tCDA , sizeof(SCCP_ADDR) );
        tCo2CrMsg.CGA.NetID = tCo2CrMsg.CDA.NetID = tCo2CrMsg.NetID ;
 //       WxcAssert ( tCo2CrMsg.NetID <= 3, "co2cr: NetID is error " );
 	if(tCo2CrMsg.NetID > 3)
		spShowErr(1, "co2cr: NetID is error " );
        tCo2CrMsg.OPC = SCCP_Param.spc[tCo2CrMsg.NetID];
        tCo2CrMsg.CDA.DPC = tCo2CrMsg.DPC = pCS->nDPC;
        memcpy ( &tCo2CrMsg.aSLR, &pCS->aSLR, SP_REF_LEN );
        tCo2CrMsg.SLS = pCS->uSLS;
        scrc_route ( &tCo2CrMsg, pCS->uAnsiFlag );
        spWatchDogStatic ( CO_TO_CR );
        return;
    case SP_MSG_CC:
        memcpy ( &tCo2CrMsg.aSLR, &pCS->aSLR, SP_REF_LEN );
        memcpy ( &tCo2CrMsg.aDLR, &pCS->aDLR, SP_REF_LEN );
        break;
    case SP_MSG_CREF:
        memcpy ( &tCo2CrMsg.aDLR, &pCS->aDLR, SP_REF_LEN );
        tCo2CrMsg.cause = pCS->eREA;
        break;
    case SP_MSG_RLSD:
        memcpy ( &tCo2CrMsg.aSLR, &pCS->aSLR, SP_REF_LEN );
        memcpy ( &tCo2CrMsg.aDLR, &pCS->aDLR, SP_REF_LEN );
        //tCo2CrMsg.cause = pCS->eREA;
        tCo2CrMsg.cause = 0;//sometime get unexpect value 0x0c, so change it to 0
        break;
    case SP_MSG_RLC:
        memcpy ( &tCo2CrMsg.aSLR, &pCS->aSLR, SP_REF_LEN );
        memcpy ( &tCo2CrMsg.aDLR, &pCS->aDLR, SP_REF_LEN );
        break;
    case SP_MSG_DT1:
        memcpy ( &tCo2CrMsg.aDLR, &pCS->aDLR, SP_REF_LEN );
        memcpy ( &tCo2CrMsg.aSLR, &pCS->aSLR, SP_REF_LEN );
        tCo2CrMsg.EOD = 0;
        tCo2CrMsg.msglen = 0;
        if( pCS->tUD.uDataLen )
        {
            tCo2CrMsg.msglen = pCS->tUD.uDataLen % 256;
            memcpy ( &tCo2CrMsg.data, pCS->tUD.aUserData, tCo2CrMsg.msglen );
        }
        break;
    case SP_MSG_IT:
        memcpy ( &tCo2CrMsg.aSLR, &pCS->aSLR, SP_REF_LEN );
        memcpy ( &tCo2CrMsg.aDLR, &pCS->aDLR, SP_REF_LEN );
        break;
    case SP_MSG_ERR:
        spLogDebug ( SCCPDB_ERR, "Need to supported SP_MSG_ERR now!" );
        break;
    case SP_MSG_DT2:
    case SP_MSG_AK:
    case SP_MSG_ED:
    case SP_MSG_EA:
    case SP_MSG_RSR:
    case SP_MSG_RSC:
        spLogDebug ( SCCPDB_ERR, "do not supported now!" );
        break;
    }
    
    tCo2CrMsg.CGA.NetID = tCo2CrMsg.CDA.NetID = tCo2CrMsg.NetID ;
    tCo2CrMsg.OPC = SCCP_Param.spc[tCo2CrMsg.NetID];
    if( pCS->uSide == CO_INST_SIDE_ORG )
      tCo2CrMsg.CDA.DPC = tCo2CrMsg.DPC = pCS->nDPC;
    else if( pCS->uSide == CO_INST_SIDE_DST )
      tCo2CrMsg.CDA.DPC =  tCo2CrMsg.DPC = pCS->nOPC;
     
    tCo2CrMsg.SLS = pCS->uSLS;
//    WxcAssert ( tCo2CrMsg.NetID <= 3, "co2cr: NetID is error " );
	if(tCo2CrMsg.NetID > 3)
		spShowErr(1, "co2cr: NetID is error " );
    tCo2CrMsg.OPC = SCCP_Param.spc[tCo2CrMsg.NetID];
	if( pCS->uSide == CO_INST_SIDE_DST && pCS->nDPC)
		tCo2CrMsg.OPC = pCS->nDPC;
	else if(pCS->uSide == CO_INST_SIDE_ORG && pCS->nOPC)
		tCo2CrMsg.OPC = pCS->nOPC;
    tCo2CrMsg.CDA.ip = 0xffffffff; 
    send_msg ( &tCo2CrMsg, pCS->uAnsiFlag);
    spWatchDogStatic ( CO_TO_CR );
    return;
}

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

void co2ul ( u16 wConnId, u8 uPri )
{
    u8 *pStr;
    CO_ConnSection *pCS;
    SP_UiPriUnion *pUnPri;
    SP_PriPoolEle tPoolEle, *pPri;

    spWatchDogStatic ( CO_SUBMIT_UL_APT );
//    WxcAssert ( wConnId < CO_CS_MPORT, "SCCP co2cr unexpected connection id" );
	if(wConnId >= CO_CS_MPORT)
		spShowErr(1, "SCCP co2cr unexpected connection id" );

    pPri = &tPoolEle;
    pUnPri = ( SP_UiPriUnion * ) & pPri->tUiPri.tPriUnion;

    pCS = &pSp->tCo.tCSInst[wConnId];
    pPri->tUiPri.uUiPri = uPri;
    pPri->tUiPri.uAnsiFlag = pCS->uAnsiFlag;
    pPri->tUiPri.wConnId = wConnId;

    spGetUlPrimitiveStr ( uPri, pStr );

    switch ( uPri )
    {
    case N_UNITDATA_IND:
    case N_NOTICE_IND:
        spLogDebug ( SCCPDB_ERR, "SP=>UL: Unsupported UDT primitive now :%s", pStr );
        break;
    case N_CONNECT_IND:
		pUnPri->tPriNConnInd.tUD.uDataLen = 0;
		if( pCS->tUD.uDataLen )
		{
			pUnPri->tPriNConnInd.uOptFlag = 0x04;
			memcpy ( &pUnPri->tPriNConnInd.tUD, &pCS->tUD, sizeof ( SP_UD ) );
		}
		else
			pUnPri->tPriNConnInd.uOptFlag = 0;
        memcpy ( &pUnPri->tPriNConnInd.tCDA, &pCS->tCDA, sizeof ( SCCP_ADDR ) );
		memcpy ( &pUnPri->tPriNConnInd.aSLR, &pCS->aDLR, SP_REF_LEN );
		pUnPri->tPriNConnInd.uSLS = pCS->uSLS;
		pUnPri->tPriNConnInd.OPC = pCS->nOPC;
		pUnPri->tPriNConnInd.NetID = pCS->uNetId;
        break;
    case N_CONNECT_CFM:
        pUnPri->tPriNConnCfm.tUD.uDataLen = 0;
        if( pCS->tUD.uDataLen )
        {
            pUnPri->tPriNConnCfm.uOptFlag = 0x04;
            memcpy ( &pUnPri->tPriNConnCfm.tUD, &pCS->tUD, sizeof ( SP_UD ) );
        }
		else
			pUnPri->tPriNConnCfm.uOptFlag = 0;
        break;
	case N_DISCONNECT_IND:
		pUnPri->tPriNDisconnInd.tUD.uDataLen = 0;
		if( pCS->tUD.uDataLen )
		{
			pUnPri->tPriNDisconnInd.uOptFlag = 0x04;
			memcpy ( &pUnPri->tPriNDisconnInd.tUD, &pCS->tUD, sizeof ( SP_UD ) );
		}
		else
			pUnPri->tPriNDisconnInd.uOptFlag = 0;
        pUnPri->tPriNDisconnInd.eOR = pCS->eOR;
        pUnPri->tPriNDisconnInd.eREA = pCS->eREA;
        break;
    case N_DATA_IND:
        memcpy ( &pUnPri->tPriNDataInd.tUD, &pCS->tUD, sizeof ( SP_UD ) );
        break;
    case N_DATAAK_IND:
    case N_EDATA_IND:
    case N_RESET_IND:
    case N_RESET_CFM:
    case N_INFORM_IND:
    case RELAY:
        spLogDebug ( SCCPDB_ERR, "SP=>UL: Unsupported the primitive now :%s", pStr );
        break;
    default:
        spLogDebug ( SCCPDB_ERR, "SP=>UL: Unknow primtive :%s", pStr );
        break;
    }

    spShowPrimitive ( &pPri->tUiPri, 0 );
    spWatchDogStatic ( WDS_RECV_PRI );

    //add to put messages into corresponding pool for Upper lyaer to get
	switch ( pCS->tCDA.SSN )
	{
	case SSN_AIF:                                                    //AIF
    	spPoolPut ( &tPoolEle, pOutCoPool[0] );
		spLogDebug ( SCCPDB_USER, "co2ul put AIF message into OutCoPool[0]" );
		break;
	case SSN_RANAP:                                                  //RANAP
    	spPoolPut ( &tPoolEle, pOutCoPool[1] );
		spLogDebug ( SCCPDB_USER, "co2ul put RANAP message into OutCoPool[1]" );
		break;
	default:
		spLogDebug ( SCCPDB_ERR, "SP=>UL: Unexpected SSN :%d", pCS->tCDA.SSN );
		break;
	}
    spWatchDogStatic ( CO_SUBMIT_UL );
    return;
}

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

void co2scmg (  )
{

}

void co2co ( u16 wConnId, u8 uPri )
{
    SP_PriPoolEle pPri;

    memset ( &pPri, 0, sizeof ( SP_PriPoolEle ) );

//    WxcAssert ( wConnId < CO_CS_MPORT, "SCCP coTimerOut unexpected connection id" );
	if(wConnId >= CO_CS_MPORT)
		spShowErr(1,  "SCCP coTimerOut unexpected connection id" );
//    WxcAssert ( ( uPri > SPCR_PRI_MAX && uPri < SPTM_PRI_MAX ), "SCCP coTimerOut unexpected msgtype" );
	if(!( uPri > SPCR_PRI_MAX && uPri < SPTM_PRI_MAX ))
		spShowErr(1, "SCCP coTimerOut unexpected msgtype" );
    pPri.tUiPri.uUiPri = uPri;
    pPri.tUiPri.wConnId = wConnId;

    spPoolPut ( &pPri, pInCoPool );
}

int spCheckAudit (  )
{
    return 1;
}

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

int coAssignSLS ( u8 wConnId )
{
    return ( wConnId & 0x0F );
}

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

void coAssignLR ( u16 wConnId, u8 * pLR )
{
//    WxcAssert ( wConnId < CO_CS_MPORT, "SCCP coNewCS unexpected connection id" );
	if(wConnId >= CO_CS_MPORT)
		spShowErr(1, "SCCP coNewCS unexpected connection id" );

    *( pLR ) = pSp->dSysID;
    *( pLR + 1 ) = wConnId >> 8;
    *( pLR + 2 ) = wConnId & 0xFF;
}

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

int coAssignClass ( u8 wConnId )
{
    //do not support class 3 now
    return 2;
}

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

int coAssignCredit ( u8 wConnId )
{
    //credit not supported now
    return 0;
}

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

int coNewCS ( u16 wConnId, SCCP_ADDR * pAddr )
{
    CO_ConnSection *pCS;
    
//    WxcAssert ( wConnId < CO_CS_MPORT, "SCCP coNewCS unexpected connection id" );
	if(wConnId >= CO_CS_MPORT)
		spShowErr(1,  "SCCP coNewCS unexpected connection id" );

    pCS = &pSp->tCo.tCSInst[wConnId];
    pCS->uSLS = coAssignSLS ( wConnId );
    coAssignLR ( wConnId, pCS->aSLR );
    memcpy ( &pCS->tCDA, pAddr, sizeof ( SCCP_ADDR ) );
    pCS->uClass = coAssignClass ( wConnId );
    pCS->uCredit = coAssignCredit ( wConnId );

    return 1;
}

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

void coFreeCS ( u16 wConnId )
{
    CO_DataBlock *pCo;
    CO_ConnSection *pCS = &pSp->tCo.tCSInst[wConnId];
    
    pCo = &pSp->tCo;

//    WxcAssert ( wConnId < CO_CS_MPORT, "SCCP coNewCS un	expected connection id" );
	if(wConnId >= CO_CS_MPORT)
		spShowErr(1,  "SCCP coNewCS un	expected connection id" );
    memset ( pCS, 0, sizeof ( CO_ConnSection ) );
    pCo->wConnIdCount--;
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////
void coFillCS ( SP_PriPoolEle * pPri )
{
    SP_CrPriPara *pCrPri;
    CO_ConnSection *pCS;

    pCrPri = ( SP_CrPriPara * ) & pPri->tCrPri;

//    WxcAssert ( ( pCrPri->wConnId < CO_CS_MPORT ), "SCCP coFillCS unexpect connection id" );
	if(! ( pCrPri->wConnId < CO_CS_MPORT ))
		spShowErr(1, "SCCP coFillCS unexpect connection id" );
//    WxcAssert ( ( pCrPri->uUiPri < SPTM_PRI_MAX ), "SCCP coFillCS unexpect primitive" );
	if(! ( pCrPri->uUiPri < SPTM_PRI_MAX ))
		spShowErr(1, "SCCP coFillCS unexpect primitive" );

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

    pCS->uPri = pCrPri->uUiPri;
    pCS->uAnsiFlag = pCrPri->uAnsiFlag;

    if( pCS->uPri > SPCR_PRI_MAX )      //Internal primitive
    {
        return;
    }
    else if( pCS->uPri > SPUI_PRI_MAX ) //CR/SCMG message primitive
    {
        Intra_Msg *pMsg;

        pMsg = &pCrPri->tIntraMsg;
        if( pMsg->msglen )
        {
//            WxcAssert ( pMsg->msglen < 255, "coFillCS Message length overflow" );
		if(pMsg->msglen >= 255)
			spShowErr(1, "coFillCS Message length overflow" );
            pCS->tUD.uDataLen = pMsg->msglen % 256;
            memcpy ( &pCS->tUD.aUserData, &pMsg->data, pCS->tUD.uDataLen );
        }
		else
			pCS->tUD.uDataLen = 0;

        switch ( pCS->uPri )
        {
        case R_CR:             /* connection request         */
            memcpy ( &pCS->tCDA, &pMsg->CDA, sizeof ( SCCP_ADDR ) );
            //memcpy ( &pCS->tCGA, &pMsg->CGA, sizeof ( SCCP_ADDR ) );
            pCS->nDPC = pMsg->DPC;
            pCS->nOPC = pMsg->OPC;
            pCS->uNetId = pMsg->NetID;
			pCS->uSLS = pMsg->SLS;
            memcpy ( &pCS->aDLR, &pMsg->aSLR, SP_REF_LEN );
            break;
        case R_CR2:            /* connection request type 2  */
            break;
        case R_CC:             /* connection confirm         */
        	pCS->uClass = pMsg->msgclass;
            memcpy ( &pCS->aDLR, &pMsg->aSLR, SP_REF_LEN );
            break;
        case R_CREF:           /* connection refused         */
            pCS->eREA = pMsg->cause;
            break;
        case R_RLSD:           /* release request            */
            pCS->eREA = pMsg->cause;
            break;
        case R_RLC:            /* release confirm            */
            break;
        case R_DT1:            /* Data Form 1                */
            break;
        case R_DT2:            /* Data Form 2                */
            break;
        case R_AK:             /* Data acknowledge           */
            break;
        case R_ED:             /* Expedited data             */
            break;
        case R_EA:             /* Expedited data acknowledge */
            break;
        case R_RSR:            /* Reset request              */
            break;
        case R_RSC:            /* Reset confirm              */
            break;
        case R_ERR:            /* PDU error                  */
            break;
        case R_IT:             /* Inactivity test            */
            break;
        case R_RF:             /* Routing Fail               */
            break;
        case R_RLS_ERR:        /* Release err                */
            break;
        default:
            break;
        }
    }
    else                        //upper layer primitive
    {
        SP_UiPriUnion *pUnPri;

        pUnPri = ( SP_UiPriUnion * ) & pPri->tUiPri.tPriUnion;
        switch ( pCS->uPri )
        {
        case N_CONNECT_REQ:
            memcpy ( &pCS->tCDA, &pUnPri->tPriNConnReq.tCDA, sizeof ( SCCP_ADDR ) );
            if( pUnPri->tPriNConnReq.uOptFlag & 0x08 )
            {
                memcpy ( &pCS->tUD, &pUnPri->tPriNConnReq.tUD, sizeof ( SP_UD ) );
            }
            pCS->nDPC = pCS->tCDA.DPC;
            pCS->uNetId = pUnPri->tPriNConnReq.tCDA.NetID;
            break;
        case N_CONNECT_RSP:
            break;
        case N_DISCONNECT_REQ:
            pCS->eREA = pUnPri->tPriNDisconnReq.eREA;
            pCS->eOR = NSU;
            break;
        case N_DATA_REQ:
            memcpy ( &pCS->tUD, &pUnPri->tPriNDataReq.tUD, sizeof ( SP_UD ) );
            break;
        case N_DATAAK_REQ:
        case N_EDATA_REQ:
        case N_RESET_REQ:
        case N_RESET_RSP:
        case N_INFORM_REQ:
            break;
        default:
            break;
        }
    }
}

///////////////////////////////////////////////////////////////////////////
//                                                                      ///
///////////////////////////////////////////////////////////////////////////
int coCheckCS ( u16 wConnId, u8 uCState, u8 uSide )
{
#ifdef DEBUG
//    WxcAssert ( ( uCState < CO_STATUS_MAX ), "SCCP coFsm unexpect connection section state" );
	if(!( uCState < CO_STATUS_MAX ))
		spShowErr(1,  "SCCP coFsm unexpect connection section state" );

//    WxcAssert ( ( uSide < CO_INST_SIDE_MAX ), "SCCP coFsm unexpect connection section state" );
	if(!( uSide < CO_INST_SIDE_MAX ))
		spShowErr(1,  "SCCP coFsm unexpect connection section state" );
#else
    if( uCState >= CO_STATUS_MAX )
    {
        spLogStateError ( wConnId, ERR_FSM_DISCARD );
        //spCoRecover ( wConnId, CO_FATAL_STATE );
        return 0;
    }

    if( uSide >= CO_INST_SIDE_MAX )
    {
        spLogStateError ( wConnId, ERR_FSM_UNEXPECT_SIDE );
        //spCoRecover ( wConnId, CO_FATAL_SIDE );
        return 0;
    }
#endif
    return 1;
}

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

void coTimerOut ( u16 wConnId, u8 uPri )
{
    SP_PriPoolEle pPri;

//    WxcAssert ( wConnId < CO_CS_MPORT, "SCCP coTimerOut unexpected connection id" );
	if(wConnId >= CO_CS_MPORT)
		spShowErr(1, "SCCP coTimerOut unexpected connection id" );
//    WxcAssert ( ( uPri > SPCR_PRI_MAX && uPri < SPTM_PRI_MAX ), "SCCP coTimerOut unexpected msgtype" );
	if(!( uPri > SPCR_PRI_MAX && uPri < SPTM_PRI_MAX ))
		spShowErr(1, "SCCP coTimerOut unexpected msgtype" );


    spLogTimerOut( wConnId , uPri );
    memset ( &pPri, 0, sizeof ( SP_PriPoolEle ) );

    pPri.tUiPri.uUiPri = uPri;
    pPri.tUiPri.wConnId = wConnId;

    spPoolPut ( &pPri, pInCoPool );

}

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

void coTimerMng (  )
{
    u16 wConnId;
    CO_ConnSection *pCS;
    CO_Timer *pTmSet;
   // u8 uPri;
    

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

        if( CO_STATUS_INIT == pCS->uCState )
        {
            continue;
        }

        pTmSet = &pCS->tmSCOC;

        if( pTmSet->tmConnEst && ++pTmSet->tmConnEst > T_CONNEST_MAX )
        {
        	pTmSet->tmConnEst = 0;
            coTimerOut ( wConnId, T_CONNEST_OUT );
        }
        if( pTmSet->tmIas && ++pTmSet->tmIas > T_IAS_MAX )
        {
        	pTmSet->tmIas = 0;
            coTimerOut ( wConnId, T_IAS_OUT );
        }
        if( pTmSet->tmIar && ++pTmSet->tmIar > T_IAR_MAX )
        {
        	pTmSet->tmIar = 0;
            coTimerOut ( wConnId, T_IAR_OUT );
        }
        if( pTmSet->tmRepeatRel && ++pTmSet->tmRepeatRel > T_REPEATE_RLS_MAX )
        {
        	pTmSet->tmRepeatRel = 0;
            coTimerOut ( wConnId, T_REPEATE_RLS_OUT );
        }
        if( pTmSet->tmRel && ++pTmSet->tmRel > T_RLS_MAX )
        {
        	pTmSet->tmRel = 0;
            coTimerOut ( wConnId, T_RLS_OUT );
        }
        if( pTmSet->tmReset && ++pTmSet->tmReset > T_RESET_MAX )
        {
        	pTmSet->tmReset = 0;
            coTimerOut ( wConnId, T_RESET_OUT );
        }
        if( pTmSet->tmGuard && ++pTmSet->tmGuard > T_GUARD_MAX )
        {
        	pTmSet->tmGuard = 0;
            coTimerOut ( wConnId, T_GUARD_OUT );
        }
        if( pTmSet->tmInternal && ++pTmSet->tmInternal > T_INTERNAL_MAX )
        {
        	pTmSet->tmInternal = 0;
            coTimerOut ( wConnId, T_INTERNAL_OUT );
        }
    }
}

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

int coNewConnId ( u8 uPri )
{
    static u16 wConnId = 0;
    CO_DataBlock *pCo;
	CO_ConnSection *pCS;
	u16 tmpConnId = wConnId;

    pCo = &pSp->tCo;

    if( pCo->wConnIdCount >= CO_CS_MPORT )
    {
        spLogDebug ( SCCPDB_ERR, "No resource for new connection" );
        return -1;
    }

//    WxcAssert ( ( uPri == N_CONNECT_REQ || uPri == R_CR ), "Unexpect primitive while allocating new connection" );
	if(!( uPri == N_CONNECT_REQ || uPri == R_CR ))
		spShowErr(1,  "Unexpect primitive while allocating new connection" );

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

        if( CO_STATUS_INIT == pCS->uCState )
        {
			memset ( pCS, 0, sizeof ( CO_ConnSection ) );
            pCS->uCState = CO_STATUS_IDLE;

            if( R_CR == uPri )
            {
                pCS->uSide = CO_INST_SIDE_DST;
            }
            else if( N_CONNECT_REQ == uPri )
            {
                pCS->uSide = CO_INST_SIDE_ORG;
            }
            pCo->wConnIdCount++;
            return wConnId;
        }
    }

    spLogDebug ( SCCPDB_ERR, "No resource for new connection" );
    return -1;
}

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

int coGetConnId ( u8 *pSLR )
{
    u16 wConnId;
//    CO_ConnSection *pCS;

//    for ( wConnId = 0; wConnId < CO_CS_MPORT; wConnId++ )
//    {
//        pCS = &pSp->tCo.tCSInst[wConnId];
        if( memcmp ( pSLR, "\0\0\0", SP_REF_LEN ))
        {
        	wConnId = (pSLR[1]<<8)+pSLR[2];
        	if(wConnId >= CO_CS_MPORT)
        		return -1;
        	else 	
        		return wConnId;
        }
//    }
    return -1;
}

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

int coCheckConnId ( SP_UiPriPara * pUiPriParam )
{
//    WxcAssert ( ( pUiPriParam->wConnId < CO_CS_MPORT ), "SCCP coCheckConnId unexpect connection id" );
	if(! ( pUiPriParam->wConnId < CO_CS_MPORT ))
		spShowErr(1, "SCCP coCheckConnId unexpect connection id" );
    if( pSp->tCo.tCSInst[pUiPriParam->wConnId].uCState > 0 )
    {
        return 1;
    }
    return 0;
}

///////////////////////////////////////////////////////////////////////////
//  Name     : coCheckResource                                          ///
//  Function : Check Resouce for a coming connection                    ///
//  Return   : Have been check in cr2co function, so always return 1    ///
///////////////////////////////////////////////////////////////////////////
int coCheckResource (  )
{
    //Have been check in cr2co function, so always return 1 
    return 1;
}

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

void spWatchDogStatic ( u8 uDebugStaticMask )
{
    CO_DebugStatic *pDs = &pSp->tCo.tCoDebugStatic;

    switch ( uDebugStaticMask )
    {
    case GET_IN_POOL:
        pDs->dGetInPool++;
        break;
    case PUT_IN_POOL:
        pDs->dPutInPool++;
        break;
    case READ_IN_POOL:
        pDs->dReadInPool++;
        break;
    case WRITE_IN_POOL:
        pDs->dWriteInPool++;
        break;
    case GET_OUT_POOL:
        pDs->dGetOutPool++;
        break;
    case PUT_OUT_POOL:
        pDs->dPutOutPool++;
        break;
    case PUT_ELE_APT:
        pDs->dPutEleApt++;
        break;
    case PUT_ELE_SUC:
        pDs->dPutEleSuc++;
        break;
    case UL_POST_CO_APT:
        pDs->dUlPostCoApt++;
        break;
    case UL_POST_CO:
        pDs->dUlPostCo++;
        break;
    case CO_SUBMIT_UL_APT:
        pDs->dCoSubmitUlApt++;
        break;
    case CO_SUBMIT_UL:
        pDs->dCoSubmitUl++;
        break;
    case CO_TO_CR_APT:
        pDs->dCo2CrApt++;
        break;
    case CO_TO_CR:
        pDs->dCo2Cr++;
        break;
    case CR_TO_CO_APT:
        pDs->dCr2CoApt++;
        break;
    case CR_TO_CO:
        pDs->dCr2Co++;
        break;
    case SP_TIMER_OUT:
    	pDs->dTimerOut++;
        break;
    default:
        break;
    }
}

//add by Roy for dual server message redirect
void coRedirect(SP_UiPriPara * pUiPriParam)
{
	Intra_Msg tmpMsg;
	
	memset (&tmpMsg, 0, sizeof(Intra_Msg));
	tmpMsg.msglen = 0;

	if (pUiPriParam->uUiPri == N_UNITDATA_IND)
	{
		if( pUiPriParam->tPriUnion.tPriNUDataInd.tUD.uDataLen )
		{
			tmpMsg.msglen = pUiPriParam->tPriUnion.tPriNUDataInd.tUD.uDataLen % 256;
			memcpy ( &tmpMsg.data, pUiPriParam->tPriUnion.tPriNUDataInd.tUD.aUserData, tmpMsg.msglen );
		}
		memcpy( &tmpMsg.CDA , &pUiPriParam->tPriUnion.tPriNUDataInd.tCDA , sizeof(SCCP_ADDR) );
		memcpy( &tmpMsg.CGA , &pUiPriParam->tPriUnion.tPriNUDataInd.tCGA , sizeof(SCCP_ADDR) );
//		WxcAssert ( tmpMsg.NetID <= 3, "co2cr: NetID is error " );
		if(tmpMsg.NetID > 3)
			spShowErr(1,  "co2cr: NetID is error " );
		tmpMsg.OPC = pUiPriParam->tPriUnion.tPriNUDataInd.tCGA.DPC;
		tmpMsg.SLS = pUiPriParam->tPriUnion.tPriNUDataInd.uSLS;	
		tmpMsg.msgtype = UDT_MSG;
	}
	else{
		if( pUiPriParam->tPriUnion.tPriNConnInd.tUD.uDataLen )
		{
			tmpMsg.msglen = pUiPriParam->tPriUnion.tPriNConnInd.tUD.uDataLen % 256;
			memcpy ( &tmpMsg.data, pUiPriParam->tPriUnion.tPriNConnInd.tUD.aUserData, tmpMsg.msglen );
		}
		memcpy( &tmpMsg.CDA , &pUiPriParam->tPriUnion.tPriNConnInd.tCDA , sizeof(SCCP_ADDR) );
		memcpy ( &tmpMsg.aSLR, &pUiPriParam->tPriUnion.tPriNConnInd.aSLR, SP_REF_LEN );
//		WxcAssert ( tmpMsg.NetID <= 3, "co2cr: NetID is error " );
		if(tmpMsg.NetID > 3)
			spShowErr(1,  "co2cr: NetID is error " );
		tmpMsg.OPC = pUiPriParam->tPriUnion.tPriNConnInd.OPC;
		tmpMsg.SLS = pUiPriParam->tPriUnion.tPriNConnInd.uSLS;	
		tmpMsg.msgtype = CR_MSG;

		//remove the connection
		memset(&pSp->tCo.tCSInst[pUiPriParam->wConnId], 0, sizeof(CO_ConnSection));
		pSp->tCo.wConnIdCount--;
	}
	tmpMsg.NetID = tmpMsg.CDA.NetID;
	tmpMsg.CDA.ip = pSp->dAlterIP; 
	tmpMsg.msgsource = FROM_MTP;
	tmpMsg.redirectFlag = 1;

	spLogDebug ( SCCPDB_TIME, "AIF ==> SCCP : Message redirect request" );
	send_msg ( &tmpMsg, pUiPriParam->uAnsiFlag);
}
