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

#include "./include/sccp_pub.h"

#ifdef LOOSE_COUPLING_MODE      //Loose coupling mode

extern inline int coCheckConnId ( SP_UiPriPara * pUiPriParam );
extern void coRedirect(SP_UiPriPara * pUiPriParam);

/* by simon at 23/9/25 */
extern DWORD ExistIP[64];
extern DWORD ExistIPNum;
extern SCOC_BUF ScocBuf;
extern LOCAL_SSN LocalSSN[256];
extern u8 ExistSSN[64];
extern u8 ExistSSNNum;
extern struct _dpc2sls
{
    int dpc;
    u8 sls;
} dpc2sls[256]; // used for sequence control, add by Roy Jiang, 2007-09-17
extern SCCP_OPT SCCP_Param;
extern u8 MNP_Flag[2];
extern SCCP_ROUTE RouteList[SCCP_ROUTE_NUM];
extern int RelatedSSNNum;
extern RL_SSN RelatedSSN[SCCP_RLSSN_NUM];
extern int RelatedSPCNum;
extern RL_SPC RelatedSPC[SCCP_RLSPC_NUM];
extern GTTATT_OMC GTTAttribute[SCCP_ROUTE_NUM];
extern SCCP_CSTA SccpCsta[96];
extern DWORD SccpCstaInd;
extern SCCP_Capture_Buf SCCPCapBuf;

///////////////////////////////////////////////////////////////////////////
//
// Name     : PostSp
// Function : Upper layer post request/response primitive to sccp
// Parameter: pUiPriParam [sccp UL primitive buffer pointer]
// Note     : Sccp Connid is implicit returned in "pUiPriParam" buffer  
//          : while N-Connect requesing 
// Return   : 0 Post Fail   1 Post Successful
//                                                                 
///////////////////////////////////////////////////////////////////////////

int PostSp ( SP_UiPriPara * pUiPriParam )
{
    int nRet;
    u8 *pPriStr;

    spShowPrimitive ( pUiPriParam, 1 );

    spWatchDogStatic ( UL_POST_CO_APT );

    switch ( pUiPriParam->uUiPri )
    {
    case N_UNITDATA_REQ:
        {
            SCLC_MSG tClMsg;

            tClMsg.msglen = pUiPriParam->tPriUnion.tPriNUDataReq.tUD.uDataLen;
            memcpy ( &tClMsg.msg, &pUiPriParam->tPriUnion.tPriNUDataReq.tUD.aUserData, tClMsg.msglen );
            memcpy ( &tClMsg.src_addr, &pUiPriParam->tPriUnion.tPriNUDataReq.tCGA, sizeof ( SCCP_ADDR ) );
            memcpy ( &tClMsg.dst_addr, &pUiPriParam->tPriUnion.tPriNUDataReq.tCDA, sizeof ( SCCP_ADDR ) );
			tClMsg.src_addr.DPC = SCCP_Param.spc[tClMsg.src_addr.NetID];
			tClMsg.sequence_control = 0;
			sclc_send ( &tClMsg );
			spWatchDogStatic ( UL_POST_CO );
            return 1;
        }
        //break;
	case N_UNITDATA_IND:
	case N_CONNECT_IND:
		//redirect to alternative server, add by Roy
		coRedirect(pUiPriParam);
		spWatchDogStatic ( UL_POST_CO );
		return 1;
		break;
    case N_CONNECT_REQ:
        nRet = coNewConnId ( N_CONNECT_REQ );
        if( nRet < 0 )
        {
            spLogDebug ( SCCPDB_ERR, "No resouces available !\n" );
            return 0;
        }
        pUiPriParam->wConnId = nRet;
        break;
    case N_CONNECT_RSP:
    case N_DISCONNECT_REQ:
    case N_DATA_REQ:
        if( !coCheckConnId ( pUiPriParam ) )
        {
            spLogDebug ( SCCPDB_ERR, "Invalid SCCP connection ID : %d", pUiPriParam->wConnId );
            return 0;
        }
        break;
    case N_DATAAK_REQ:
    case N_EDATA_REQ:
    case N_RESET_REQ:
    case N_RESET_RSP:
    case N_INFORM_REQ:
        spGetUlPrimitiveStr ( pUiPriParam->uUiPri, pPriStr );
        spLogDebug ( SCCPDB_ERR, "Unsupported the primitive now :%s", pPriStr );
        return 0;
    default:
        spGetUlPrimitiveStr ( pUiPriParam->uUiPri, pPriStr );
        spLogDebug ( SCCPDB_ERR, "Invalid primivtive recieved :%s ", pPriStr );
        return 0;
    }

    spWatchDogStatic ( UL_POST_CO );

    {
        SP_PriPoolEle tPoolEle;

        memset ( &tPoolEle, 0, sizeof ( SP_PriPoolEle ) );
        memcpy ( &tPoolEle.tUiPri, pUiPriParam, sizeof ( SP_UiPriPara ) );
        spPoolPut ( &tPoolEle, pInCoPool );
    }

    return 1;
}

///////////////////////////////////////////////////////////////////////////
//
// Name     : SpSubmit
// Function : Upper layer fetch indicate/confirm primitive submited form sccp
// Parameter: pUiPriParam [sccp UL primitive buffer pointer]
//            uUlSapId    [upper layer sap id [0 tcap 1 pps 2 smsc 3 aif ] ]
// Return   : 0 Fetch Fail   1 Fetch Successful
//                                                                 
///////////////////////////////////////////////////////////////////////////

int SpSubmit ( SP_UiPriPara * pUiPriParam, u8 uUlSapId )
{
    int nRet = 0;

    SCLC_MSG tClMsg;

    nRet = sclc_receive ( &tClMsg, uUlSapId );
    if( nRet )
    {
        pUiPriParam->tPriUnion.tPriNUDataInd.uSLS = tClMsg.sls;
        pUiPriParam->wConnId = 0xFFFF;
        pUiPriParam->uUiPri = N_UNITDATA_IND;
        pUiPriParam->tPriUnion.tPriNUDataInd.tUD.uDataLen = tClMsg.msglen;
        memcpy ( &pUiPriParam->tPriUnion.tPriNUDataInd.tUD.aUserData, &tClMsg.msg, tClMsg.msglen );
        memcpy ( &pUiPriParam->tPriUnion.tPriNUDataInd.tCGA, &tClMsg.src_addr, sizeof ( SCCP_ADDR ) );
        memcpy ( &pUiPriParam->tPriUnion.tPriNUDataInd.tCDA, &tClMsg.dst_addr, sizeof ( SCCP_ADDR ) );
        return nRet;
    }

    if( 3 == uUlSapId )
    {
        SP_PriPoolEle tPoolEle;


        nRet = spPoolGet ( &tPoolEle, pOutCoPool );
        memcpy ( pUiPriParam, &tPoolEle.tUiPri, sizeof ( SP_UiPriPara ) );

        return nRet;
    }
    return nRet;
}

#else

/////////////////////Below is reserved, do not need to read/////////////////////

#ifdef  TIGHT_COUPING_MODE      //Tight coupling mode

#error "Do not support Tight coupling mode ,please use \"LOOSE_COUPLING_MODE\" flag \n"

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

void Ul_Post_Sp ( SP_UiPriPara * pUiPriParam )
{
    SP_UiPriUnion *pPriUn;

    pPriUn = &pUlPri->tPriUnion;

    switch ( pUiPriParam->uUi_Pri )
    {
    case N_UNITDATA_REQ:       //reserved for sclc
        spUi_N_UnitDataReq ( &pPriUn->tPriNUDataReq.tCDA, &pPriUn->tPriNUDataReq.tCGA, &pPriUn->tPriNUDataReq.tSEQ, &pPriUn->tPriNUDataReq.tRO, &pPriUn->tPriNUDataReq.tUD );
        break;

    case N_CONNECT_REQ:
        spUi_N_ConnectReq ( &pPriUn->tPriNConnReq.tCDA, &pPriUn->tPriNConnReq.tCGA, &pPriUn->tPriNConnReq.tRCS, &pPriUn->tPriNConnReq.tEDS );
        break;

    case N_CONNECT_RSP:
        spUi_N_ConnectRsp ( &pPriUn->tPriNConnRsp.tRA, &pPriUn->tPriNConnRsp.tRCS, &pPriUn->tPriNConnRsp.tEDS );
        break;

    case N_DISCONNECT_REQ:
        spUi_N_DisconnectReq ( &pPriUn->tPriNDisconnReq.tRA, &pPriUn->tPriNDisconnReq.tREA, &pPriUn->tPriNDisconnReq.tUC, pPriUn->tPriNDisconnReq.tCI );
        break;

    case N_DATA_REQ:
        spUi_N_DataReq ( &pPriUn->tPriNDataReq.tCR, &pPriUn->tPriNDataReq.tUD, pPriUn->tPriNDataReq.tCI );
        break;

    case N_DATAAK_REQ:
        spUi_N_DataAkReq ( pPriUn->tPriNDataAkReq.tCI );
        break;

    case N_EDATA_REQ:
        spUi_N_EDataReq ( pPriUn->tPriNEDataReq.tCI, &pPriUn->tPriNEDataReq.tUD );
        break;

    case N_RESET_REQ:
        spUi_N_ResetReq ( &pPriUn->tPriNResetReq.tREA, pPriUn->tPriNResetReq.tCI );
        break;

    case N_RESET_RSP:
        spUi_N_ResetRsp ( pPriUn->tPriNResetRsp.tCI );
        break;

    case N_INFORM_REQ:
        spUi_N_InformReq ( &pPriUn->tPriNInformReq.tREA, &pPriUn->tPriNInformReq.tQOS, pPriUn->tPriNInformReq.tCI );
        break;

    default:
        spShowMsg ( SCCPDB_ERR, "SCCP <== AIF. UnKnow Primitive %s", GetUiPriStr ( pPriUn->uUi_Pri ) );
        return;
        break;

    }
    spShowMsg ( SCCPDB_AIF, "SCCP <== AIF. Primitive %s", GetUiPriStr ( pPriUn->uUi_Pri ) );
    return;
}

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

void Sp_Submit_Ul ( SP_UiPriPara * pUiPriParam )
{
    switch ( Ui_Pri )
    {
    case N_UNITDATA_IND:       //reserved for sclc

        break;

    case N_NOTICE_IND:

        break;

    case N_CONNECT_IND:

        break;

    case N_CONNECT_CFM:

        break;

    case N_DISCONNECT_IND:

        break;

    case N_DATA_IND:

        break;

    case N_DATAAK_IND:

        break;

    case N_EDATA_IND:

        break;

    case N_RESET_IND:

        break;

    case N_RESET_CFM:

        break;

    case N_INFORM_IND:

        break;

    default:

        break;

    }
    return 0;
}
#endif

/////////////////////Above is reserved, do not need to read/////////////////////

#endif
