/*      Title:          SCF fsm c file          */
/*      Writter:        Liang Hongbin           */
/*      Version:        1.0                     */
/*      Date:           2003-09-18              */
/*      ------------------------------          */
#include "../../public/src/include/includes.h"
#include "../../xapp/src/ixap.h"
#include "../../xapp/src/capp/cap_msg.h"
#include "./include/scfdef.h"
#include "./include/scfmsg.h"
#include "./include/scfpub.h"

extern SCF_Buffer	scf_buffer;
SCSM_DATA  	scsm_data[SCF_MAX_DLG_NUM];

CAP_Message scfOpenResponse={
	{0,16},
	CAP_FLAG,
	{0,0,0},
	{0,0,0},
	0xff,//CAP_O_OPEN,
	0x03,//RESPONSE,
	{2,  //RESULT=accept
	1,  //
	1,	//acn tag
	2,	//len
	50,	//acn
	2,	//acn version
	0,}	//end flag
};

CAP_Message scfEnd={
	{0,12},
	CAP_FLAG,
	{0,0,0},
	{0,0,0},
	0xfe,//CAP_O_END,
	0x01,//REQUEST,
	{1,  //release method
	0,  //optional part
	0,}
};

CAP_Message scfPAbort={
	{0,11},
	CAP_FLAG,
	{0,0,0},
	{0,0,0},
	CAP_O_PABORT,
	0x02,//INDICATE,
	{0,  //provider reason
	0,}  //      
};        
          
CAP_Message scfUAbort={
	{0,12},
	CAP_FLAG,
	{0,0,0},
	{0,0,0},
	CAP_O_UABORT,
	0x01,//request,
	{1,  //user error
	0,0,}  //      
};        
/*---------------------------------------------------------*/
void scfSendOpenResponse(unsigned char acn,unsigned char acn_v,unsigned short dlgid)
{
	CAP_Message capmsg;

	//tcap_change_local_ssn(dlgid,147,146);	
	memcpy(&capmsg,&scfOpenResponse,18);
    capmsg.dialogue_id[0] = dlgid>>8;
    capmsg.dialogue_id[1] = dlgid;
	capmsg.msgContent[4] = acn;
	capmsg.msgContent[5] = acn_v;
    cap_send_comdata((unsigned char *)&capmsg);                 	
}

void scfSendOprDataToXAP(unsigned short dlgid,unsigned char *dataflow)
{
	SCSM_DATA   *scf_ptr;

    if(dlgid >= SCF_MAX_DLG_NUM) 
        return;
    scf_ptr = &scsm_data[dlgid];        
	if(!scf_ptr->FirstResponse){
		scfSendOpenResponse(scf_ptr->acn,scf_ptr->acn_v,dlgid);
		scf_ptr->FirstResponse = 1;
	}
	if(scf_ptr->endFlag)
	{
		
	}
	cap_send_oprdata(dataflow);
}
/*---------------------------------------------------------*/
void ResetTscf_ssf(unsigned short dlgid)
{
    SCSM_DATA   *scf_ptr;

    if(dlgid >= SCF_MAX_DLG_NUM) 
        return;
    scf_ptr = &scsm_data[dlgid];        
    scf_ptr->Tscf_ssf = 0;
}

void ResetTscf_ssfExpiryTime(unsigned int dlgid)
{
        SCSM_DATA    *scf_ptr;

        if(dlgid >= SCF_MAX_DLG_NUM) 
                return;
        scf_ptr = &scsm_data[dlgid];   
        scf_ptr->Tscf_ssfExpiryTimes = 0;
}

void SendPAbortToSL(unsigned short dlgid)
{
	CAP_Message capmsg;
    
    memcpy(&capmsg,&scfPAbort, 14);
    capmsg.dialogue_id[0] = dlgid>>8;
    capmsg.dialogue_id[1] = dlgid;
    PutScfMsg(capmsg);	
}

void SendUAbortToXAP(unsigned short dlgid,u_char u_error)
{
	CAP_Message capmsg;
    
    memcpy(&capmsg,&scfUAbort, 14);
    capmsg.dialogue_id[0] = dlgid>>8;
    capmsg.dialogue_id[1] = dlgid;
	capmsg.msgContent[0] = u_error;
//	capmsg.msgContent[0] = 1;
    cap_send_comdata((unsigned char *)&capmsg);                 	
}

void SendEndToXAP(unsigned short dlgid)
{
	CAP_Message capmsg;
	
	memcpy(&capmsg,&scfEnd,14);
    capmsg.dialogue_id[0] = dlgid>>8;
    capmsg.dialogue_id[1] = dlgid;
    cap_send_comdata((unsigned char *)&capmsg);                 	
}
/*-------------------------------------------------*/
int scfWaitingNotificationOrRequest(unsigned short dlgid)
{
    int             edp,endflag=0;
    int             retval,msglen,ocode=0;
    SCSM_DATA       *scf_ptr;
    CAP_Message     capmsg;
    CapArg          capArg;
    
    if(dlgid>=SCF_MAX_DLG_NUM) return SCF_IDLE;
    
    scf_ptr = &scsm_data[dlgid];
    retval = scf_ptr->State;
    if (cap_get_comdata((unsigned char *)&capmsg,dlgid))
    {	
		if(capmsg.msgOperaCode !=0xFA)
		{
        	PutScfMsg(capmsg);
        	return SCF_IDLE;
		}
    }

    if (GetScfMsg(&capmsg,dlgid))
    {
        switch(capmsg.msgOperaCode)
        {
            case CAP_OC_ActivityTest:                
			case CAP_OC_Connect:
                break;
            case CAP_OC_ApplyCharging:                
                scf_ptr->Pending ++;
                break;
            case CAP_OC_ReleaseCall:
            case CAP_OC_ReleaseSMS:                
                endflag = 1;
                retval = SCF_IDLE;
                break;
            default: //release call ,,,
			break;
                //scfDebugMsg("Received error operation in WaitingNotificationOrRequest");
                //SendPAbortToSL(dlgid);
                SendEndToXAP(dlgid);
                return SCF_IDLE;
                break;
        }
        capmsg.msgContent[0] = cap_get_invokeid(dlgid);
        scfSendOprDataToXAP(dlgid,(unsigned char *)&capmsg);
        if (endflag)
        {
            SendEndToXAP(dlgid);
	        retval = SCF_IDLE;  
		}                
    }
    if(cap_get_comdata((unsigned char *)&capmsg,dlgid))    
    {
		if(capmsg.msgOperaCode != 0xFA)
		{
    		PutScfMsg(capmsg);
    		retval = SCF_IDLE;
		}
	}else if(cap_get_oprdata((unsigned char *)&capmsg,dlgid))
	{
    
        PutScfMsg(capmsg);
        ocode = capmsg.msgOperaCode;
		msglen = capmsg.msgContent[3]*256+capmsg.msgContent[4];
		if(msglen>256){
			retval = SCF_IDLE;
			SendPAbortToSL(dlgid);
        	SendEndToXAP(dlgid);
			return retval;
		}
        switch(ocode)
        {
            case CAP_OC_ApplyChargingReport:                
                scf_ptr->Pending --;
                if (scf_ptr->Pending == 0 && scf_ptr->EDPs == 0){
                    endflag = 1;
                    retval = SCF_IDLE;
                }
                break;
            case CAP_OC_EventReportBCSM:
                //revised later, liang hongbin  2002-09-26
                // if more EDP requested more EDPs should be taken into account
                if(decode_capmsg(&capmsg.msgContent[5],msglen,ocode,3,&capArg)<=0)
					break;
                edp = capArg.msg_list.eventReportBCSMArg.eventTypeBCSM;                    
                scf_ptr->EDPs --;
				
                if(scf_ptr->EDP_flag[edp] == (0xF0 | capp_interrupted))
                {
                    ResetTscf_ssf(dlgid);
                    ResetTscf_ssfExpiryTime(dlgid);
                    retval = SCF_PREPARING_SSF_INSTRUCTIONS;
                }
                else
                {       
                    if(scf_ptr->Pending == 0 && scf_ptr->EDPs == 0){
                    	endflag = 1;
                        retval = SCF_IDLE;
                    }
                }
	
                break;
            case CAP_OC_EventReportSMS:
                if(decode_capmsg(&capmsg.msgContent[5],msglen,ocode,3,&capArg)<=0) 
					break;
                edp = capArg.msg_list.eventReportSMSArg.eventTypeSMS;

                scf_ptr->EDPs --;
                if(scf_ptr->EDP_flag[edp] == (0xF0 | capp_interrupted))
                {
                    ResetTscf_ssf(dlgid);
                    ResetTscf_ssfExpiryTime(dlgid);
                    retval = SCF_PREPARING_SSF_INSTRUCTIONS;
                }
                else
                {
                    if(scf_ptr->Pending == 0 && scf_ptr->EDPs == 0){
                    	endflag = 1;
                        retval = SCF_IDLE;
                    }
                    
                }

                break;
            case CAP_OC_ActivityTest:               
                break;
            default:
            	endflag = 1;
                retval = SCF_IDLE;                
                //scfDebugMsg("Receive error operation in capWaitingNotificationOrRequest");                
                break;            
        }
        if(endflag){
        	SendPAbortToSL(dlgid);
        	SendEndToXAP(dlgid);
        }
    }
    return retval;
}

int scfPreparingSsfInstructions(unsigned short dlgid)
{
    SCSM_DATA    *scf_ptr;
    CAP_Message  capmsg,*pcapmsg;
    CapArg       capArg;
    int          retval,len,i,endflag=0,
                 edp,edp_flag=0x00,edpnum=0x00;
	CapRequestReportBCSMEvent *capRRE;
	CapRequestReportSMSEvent  *capRRSE;
	
	if(dlgid>=SCF_MAX_DLG_NUM) return 0;                                          
    scf_ptr = &scsm_data[dlgid];
    retval = scf_ptr->State;
    
    if (scf_ptr->Tscf_ssf ++ > TIMER_SHORT)
    {
        ResetTscf_ssf(dlgid);
        if (scf_ptr->Tscf_ssfExpiryTimes ++ >= 2)
        {
        	//scfDebugMsg("SCF timer expires while preparing ssf instructions!");        
        	//send cap_p_about to PPS
        	//send cap_p_about to XAP
        	SendPAbortToSL(dlgid);
        	SendEndToXAP(dlgid);
        	return SCF_IDLE; //end
        }        
    }
    if(cap_get_comdata((unsigned char *)&capmsg,dlgid))
    {
		  	if(capmsg.msgOperaCode != 0xFA)
			{ 
        		PutScfMsg(capmsg);
        		return SCF_IDLE;
			}
    }
	if(!cap_check_sendopr(dlgid)) return retval;
    pcapmsg = &capmsg;
    if(GetScfMsg(pcapmsg,dlgid))
    {        
        switch (pcapmsg->msgOperaCode)
        {
            case CAP_OC_ApplyCharging:                
                scf_ptr->Pending ++;
                break;
            case CAP_OC_RequestReportBCSMEvent:                
                len = pcapmsg->msgContent[3]*256 + pcapmsg->msgContent[4];
                if(decode_capmsg(&pcapmsg->msgContent[5],
                				len,
                				CAP_OC_RequestReportBCSMEvent,
								3,
                				&capArg)<=0)
						break;
				capRRE = &capArg.msg_list.requestReportBCSMEventArg;                				
                edpnum = capRRE->bcsmEvents_num; 

                for (i = 0;i < edpnum;i ++)
                {
                    edp = capRRE->bcsmEvents[i].eventTypeBCSM;
                    switch(edp)
                    {
                        case capp_oAnswer:
                        case capp_tAnswer:
                            scf_ptr->EDPs ++;
                            break;
                        default:
                            edp_flag = 0x01;
                            break;
                    }
                    if (edp == capp_oDisconnect || edp == capp_tDisconnect)
                        scf_ptr->EDP_flag[edp] = 0xF0 | capp_interrupted;
                    else
                        scf_ptr->EDP_flag[edp] = 0xF0 | capRRE->bcsmEvents[i].monitorMode;
                }
                scf_ptr->EDPs += edp_flag; 

                break;
            case CAP_OC_RequestReportSMSEvent:
                len = pcapmsg->msgContent[3]*256 + pcapmsg->msgContent[4];
                if(decode_capmsg(&pcapmsg->msgContent[5],
                				len,
                				CAP_OC_RequestReportSMSEvent,
								3,
                				&capArg)<=0)
						break;
			    capRRSE = &capArg.msg_list.requestReportSMSEventArg;           				
                edpnum = capRRSE->sMSEvents_num; 

                for (i = 0;i < edpnum;i ++)
                {
                    edp = capRRSE->sMSEvents[i].eventTypeSMS;
                    switch(edp)
                    {
                        case capp_osmsFailure:
                        case capp_osmsSubmitted:
                            scf_ptr->EDPs = 1;
                            break;
                    }
                    scf_ptr->EDP_flag[edp] = 
                    	0xF0 | capRRSE->sMSEvents[i].monitorMode;
                }

                break;
            case CAP_OC_Continue:
            case CAP_OC_ContinueSMS:                
                if (scf_ptr->EDPs > 0 || scf_ptr->Pending > 0)
                        retval = SCF_WAITING_NOTIFICATION_OR_REQUEST;
                else
                {
                        endflag = 1;
                        retval = SCF_IDLE;
                }
                break;
            case CAP_OC_ReleaseCall:
            case CAP_OC_ReleaseSMS:
                //if (scf_ptr->EDPs > 0 || scf_ptr->Pending > 0)
                //      retval = SCF_WAITING_NOTIFICATION_OR_REQUEST;
                //else{
                        endflag = 1;
                        retval = SCF_IDLE;
                //} 
                break;
            case CAP_OC_Cancel:
                retval = SCF_IDLE;
                break;
            case CAP_OC_ActivityTest:
                break;
			case CAP_OC_EstablishTemporaryConnection:
				retval = SCF_WAITING_DISCONNECT_FORWARD_CONNECT;
				break;
			case CAP_O_UABORT:
				SendUAbortToXAP(dlgid,pcapmsg->msgContent[0]);
				return SCF_IDLE;
				break;
			case CAP_OC_InitialDP:
                 endflag = 1;
                 retval = SCF_IDLE;
			break;
			case CAP_OC_Connect:
                if (scf_ptr->EDPs > 0 || scf_ptr->Pending > 0)
                        retval = SCF_WAITING_NOTIFICATION_OR_REQUEST;
                else
                {
                        endflag = 1;
                        retval = SCF_IDLE;
                }
			break;
			case CAP_O_END:
            	SendEndToXAP(dlgid);
                return (retval = SCF_IDLE);
			break;
            default:               
            //	SendEndToXAP(dlgid);
              //  return (retval = SCF_IDLE);
                break;
        }
        if (endflag)
        {
			if(pcapmsg->msgContent[2] == 0x02)	 
	 		  	pcapmsg->msgContent[0]=scf_ptr->invokeid;
			else				 
 	      		pcapmsg->msgContent[0]=cap_get_invokeid(dlgid);         	    
			scf_ptr->endFlag = 1;
            scfSendOprDataToXAP(dlgid,(unsigned char *)pcapmsg);
//            SendEndToXAP(dlgid);
  //          retval = SCF_IDLE;  
			retval = SCF_SEND_END;
        }
        else
        {   
			if(pcapmsg->msgContent[2] == 0x02)	 
	 		  	pcapmsg->msgContent[0]=scf_ptr->invokeid;
			else				 
 	      		pcapmsg->msgContent[0]=cap_get_invokeid(dlgid);         	    
            scfSendOprDataToXAP(dlgid,(unsigned char *)pcapmsg);
        }
        
        ResetTscf_ssf(dlgid);
      //ResetTimer(dlgid);
    }   
    return retval;
}

int scfVPSProc(unsigned short dlgid)
{
    SCSM_DATA      *scf_ptr;
    CAP_Message    *pcapmsg,capmsg;       
	
	if(dlgid>=SCF_MAX_DLG_NUM) return SCF_IDLE;
    scf_ptr = &scsm_data[dlgid];
    
    if (scf_ptr->Tinit++ >= TIMER_INIT)
    {
 	 	//scfDebugMsg("SCF timer expires while waiting
 		//send cap_p_about to PPS                     
 		//send cap_p_about to XAP                     
 		SendPAbortToSL(dlgid);
 		SendEndToXAP(dlgid);
 		return SCF_IDLE; //end
    }
    if(cap_get_comdata((unsigned char *)&capmsg,dlgid))
    {
		if(capmsg.msgOperaCode !=0xFA){
			PutScfMsg(capmsg);
        	return SCF_IDLE;
		}
    }
    pcapmsg = &capmsg;
    if(GetScfMsg(pcapmsg,dlgid))
    {        
        if (pcapmsg->msgOperaCode != CAP_OC_PlayAnnouncement 
				&& pcapmsg->msgOperaCode != 0xb1)
        {
            //scfDebugMsg("Receive error msg from uplayer in VPS proc");
            return SCF_IDLE;
        }
        pcapmsg->msgContent[0] = cap_get_invokeid(dlgid); 
        scfSendOprDataToXAP(dlgid,(unsigned char *)pcapmsg);
        return SCF_SEND_END;
    }
    return SCF_VPS_PROC;
}

int scfInitProc(unsigned short dlgid)
{
    SCSM_DATA    *scf_ptr;
    CAP_Message  capmsg;        
    int          retval;

    
    scf_ptr = &scsm_data[dlgid];
    
    retval = scf_ptr->State;
    if (scf_ptr->Tinit++ >= TIMER_INIT)
    {
        //scfDebugMsg("SCF timer expires while waiting for Initial Message!");        
        //send cap_p_about to PPS
        //send cap_p_about to XAP
        SendPAbortToSL(dlgid);
        SendEndToXAP(dlgid);
        return SCF_IDLE; //end
    }
    
    if(cap_get_comdata((unsigned char *)&capmsg,dlgid))
    {
		if(capmsg.msgOperaCode !=0xFA){
    		PutScfMsg(capmsg);
    		return SCF_IDLE;
		}
    }else if(cap_get_oprdata((unsigned char *)&capmsg,dlgid))
    {
		scf_ptr->invokeid = capmsg.msgContent[0];
    	switch(capmsg.msgOperaCode)
    	{
    		case CAP_OC_InitialDP:
            case CAP_OC_InitialDPSMS:
                PutScfMsg(capmsg);
                ResetTscf_ssf(dlgid);
                retval = SCF_PREPARING_SSF_INSTRUCTIONS;
                break;
            case CAP_OC_VPSOprRequest:
				PutScfMsg(capmsg);                
                retval = SCF_VPS_PROC;                            
            	break;
			case CAP_OC_AssistRequestInstructions:
				PutScfMsg(capmsg);				
				retval = SCF_WAITING_PLAYANNOUNCEMENT;//???
				break;            	
            default:
            	SendPAbortToSL(dlgid);
            	SendEndToXAP(dlgid);
            	retval = SCF_IDLE;
            	break;
    	}    	
    }else if(GetScfMsg(&capmsg,dlgid))
    {
    	capmsg.msgContent[0] = cap_get_invokeid(dlgid);
    	cap_send_comdata((unsigned char *)&capmsg);
    	return SCF_IDLE;
    }       
    return retval;
}

/*
int scfDetermineMode(unsigned short dlgid)
{
	SCSM_DATA   *scf_ptr;
	int			retval, len;
	int			invokeid, DisconnectFromSRF=0;
	CAP_Message capmsg;
	CapArg		capArg;
	CapPlayAnnouncement				   *capPA;
	CapPromptAndCollectUserInformation *capPCUI;
	
	if(dlgid>=SCF_MAX_DLG_NUM) return SCF_IDLE;
	scf_ptr = &scsm_data[dlgid];
	retval = scf_ptr->State;
	
	if(scf_ptr->Twm++>TIMER_SHORT){
		SendPAbortToSL(dlgid);
		SendEndToXAP(dlgid);
		return SCF_IDLE;
	}
	if(cap_get_comdata((unsigned char *)&capmsg,dlgid))
	{
		if(capmsg.msgOperaCode !=0xFA){
			PutScfMsg(capmsg);
			return SCF_IDLE;
		}
	}
	if(GetScfMsg(&capmsg,dlgid))
	{
		switch(capmsg.msgOperaCode)
		{
			case CAP_OC_ConnectToResource:
			break;
			case CAP_OC_PlayAnnouncement:
				len = capmsg.msgContent[3]*256 + capmsg.msgContent[4];
                decode_capmsg(&capmsg.msgContent[5],
                				len,
                				CAP_OC_PlayAnnouncement,
								3,
                				&capArg);
				capPA = &capArg.msg_list.playAnnouncementArg;
				if(capPA->optional_flag & 0x01)
				{
					DisconnectFromSRF = 
						1 - capPA->disconnectFromIPForbidden;	
				}else{
					DisconnectFromSRF = 0;
				}
			break;	
			case CAP_OC_PromptAndCollectUserInformation:	
				len = capmsg.msgContent[3]*256 + capmsg.msgContent[4];
                decode_capmsg(&capmsg.msgContent[5],
                				len,
                				CAP_OC_PromptAndCollectUserInformation,
								3,
                				&capArg);
				capPCUI = &capArg.msg_list.promptAndCollectUserInformationArg;
				if(capPCUI->optional_flag & 0x01)
				{
					DisconnectFromSRF = 
						1 - capPCUI->disconnectFromIPForbidden;
				}else{
					DisconnectFromSRF = 0;
				}
					
//				retval = SCF_WAITING_RESPONSE_FROM_SRF;
			break;
			case CAP_OC_EstablishTemporaryConnection:
				scf_ptr->Twm = 0;
				scf_ptr->Tassist = 0;
				//correlationID = dlgid;
				retval = SCF_WAITING_DISCONNECT_FORWARD_CONNECT;
			break;
			case CAP_OC_Connect:
			break;
			default:				
				SendPAbortToSL(dlgid);
				SendEndToXAP(dlgid);
				return SCF_IDLE;
			break;
		}
		invokeid = cap_get_invokeid(dlgid);
		capmsg.msgContent[0] = invokeid;
		scfSendOprDataToXAP(dlgid,(unsigned char *)&capmsg);
		
		if(DisconnectFromSRF)
		{
			scf_ptr->DisconnectFromSRF = 1; 
			scf_ptr->DisconnectLinkID = invokeid;
		}
	}
	
	return retval;
}
*/
int scfWaitinDisconnectForwardConnection(unsigned short dlgid)
{
	SCSM_DATA   	*scf_ptr;
	int				retval,
					invokeid;
	int				ocode,endflag=0;
	CAP_Message 	capmsg;

		
	if(dlgid>=SCF_MAX_DLG_NUM) return SCF_IDLE;
	scf_ptr = &scsm_data[dlgid];
	retval = scf_ptr->State;
	
	if(scf_ptr->Tassist++>(TIMER_SHORT*8)){		
		return SCF_PREPARING_SSF_INSTRUCTIONS;		
	}

	if(cap_get_comdata((unsigned char *)&capmsg,dlgid))
	{
		if(capmsg.msgOperaCode !=0xFA)
		{
			PutScfMsg(capmsg);
			return SCF_IDLE;
		}
	}

	if(GetScfMsg(&capmsg,dlgid))
	{
		switch(capmsg.msgOperaCode)
		{
			case CAP_OC_DisconnectForwardConnection:
				retval = SCF_PREPARING_SSF_INSTRUCTIONS;		
			break;
            case CAP_OC_ActivityTest:                
				scf_ptr->Tassist=0;		
			break;
			case CAP_OC_ReleaseCall:
                endflag = 1;
                retval = SCF_IDLE;
			break;
			case CAP_O_UABORT:
				SendUAbortToXAP(dlgid,capmsg.msgContent[0]);
				return SCF_IDLE;
			break;
			default:
			break;
				//SendPAbortToSL(dlgid);
				SendEndToXAP(dlgid);
				return SCF_IDLE;
			break;
		}
		invokeid = cap_get_invokeid(dlgid);
//		capmsg.dialogue_id[0] = dlgid>>8;
//		capmsg.dialogue_id[1] = dlgid;
		capmsg.msgContent[0] = invokeid;
		if(endflag){
			scfSendOprDataToXAP(dlgid,(unsigned char *)&capmsg);
            SendEndToXAP(dlgid);
            retval = SCF_IDLE;  
		}else{
			scfSendOprDataToXAP(dlgid,(unsigned char *)&capmsg);
		}
	}	
	endflag = 0;
	if(cap_get_oprdata((unsigned char *)&capmsg,dlgid))
	{
    
        PutScfMsg(capmsg);
        ocode = capmsg.msgOperaCode;
        switch(ocode)
        {
            case CAP_OC_EventReportBCSM:
                //revised later, liang hongbin  2002-09-26
                // if more EDP requested more EDPs should be taken into account
				/*
                decode_capmsg(&capmsg.msgContent[5],msglen,ocode,3,&capArg);
                edp = capArg.msg_list.eventReportBCSMArg.eventTypeBCSM;                    
                scf_ptr->EDPs --;
                if(scf_ptr->EDP_flag[edp] == (0xF0 | capp_interrupted))
                {
                    ResetTscf_ssf(dlgid);
                    ResetTscf_ssfExpiryTime(dlgid);
                    retval = SCF_PREPARING_SSF_INSTRUCTIONS;
                }
                else
                {       
                    if(scf_ptr->Pending == 0 && scf_ptr->EDPs == 0){
                    	endflag = 1;
                        retval = SCF_IDLE;
                    }
                }
				*/
                break;
            case CAP_OC_ActivityTest:               
		    case  CAP_OC_EstablishTemporaryConnection: 
				scf_ptr->Tassist=0;		
                break;
            default:
            	endflag = 1;
                retval = SCF_IDLE;                
                break;            
        }
        if(endflag){
        	SendPAbortToSL(dlgid);
        	SendEndToXAP(dlgid);
        }
    }
	return retval;
}

/*-----------------------------------------------------*/
int scfWaitingPlayAnnouncement(unsigned short dlgid)
{
	SCSM_DATA   *scf_ptr;
	int			retval;
	int			invokeid;
	CAP_Message capmsg;
	
	if(dlgid>=SCF_MAX_DLG_NUM) return SCF_IDLE;
	scf_ptr = &scsm_data[dlgid];
	retval = scf_ptr->State;

	if(scf_ptr->Tassist++>TIMER_LONG)
	{		
        SendPAbortToSL(dlgid);
        SendEndToXAP(dlgid);
		scf_ptr->endFlag = 1;
		return SCF_IDLE;
	}	
	if(cap_get_comdata((unsigned char *)&capmsg,dlgid))
	{
		if(capmsg.msgOperaCode !=0xFA)
		{
			PutScfMsg(capmsg);
			return SCF_IDLE;
		}
	}
	
		
	if(cap_get_oprdata((unsigned char *)&capmsg,dlgid))
	{
		scf_ptr->Tassist = 0;
		switch(capmsg.msgOperaCode)
		{
			case CAP_OC_SpecializedResourceReport:	
			break;	
			case CAP_OC_PromptAndCollectUserInformation:
			break;
			default:
				return retval;
			break;			
		}		
		capmsg.dialogue_id[0] = dlgid>>8;
		capmsg.dialogue_id[1] = dlgid;
		PutScfMsg(capmsg);
	}else if(GetScfMsg(&capmsg,dlgid))
	{
		scf_ptr->Tassist = 0;
		switch(capmsg.msgOperaCode)
		{
			case CAP_O_UABORT:
				SendUAbortToXAP(dlgid,capmsg.msgContent[0]);
				scf_ptr->endFlag = 1;
				return SCF_IDLE;			
			break;
			case CAP_O_END:
        		SendEndToXAP(dlgid);
				scf_ptr->endFlag = 1;
				return SCF_IDLE;
			break;
			default:
			break;
		}	
		if(capmsg.msgContent[2] == 0x02) //u_error
		{
			invokeid = scf_ptr->invokeid;
		}
		else				
			invokeid = cap_get_invokeid(dlgid);
		capmsg.dialogue_id[0] = dlgid>>8;
		capmsg.dialogue_id[1] = dlgid;
		capmsg.msgContent[0] = invokeid;
		scfSendOprDataToXAP(dlgid,(unsigned char *)&capmsg);
	}
		
	return retval;	
}

int scfSendTCEnd(u_short dlgid)
{
	int retval = 0;
    	CAP_Message    *pcapmsg,capmsg;       

	if(cap_check_sendcom(dlgid))
	{
		pcapmsg = &capmsg;
	    memcpy(pcapmsg,&scfEnd,14);
	    pcapmsg->dialogue_id[0] = dlgid>>8;
	    pcapmsg->dialogue_id[1] = dlgid;	
	    cap_send_comdata((unsigned char *)pcapmsg);                
		retval = 1;
	}
	return retval;
}
/*-----------------------------------------------------*/

int scsm_init()
{
    icap_reg_ssn(SSN_SCF);
    return 1;
}

int ClearThreadData(unsigned short dlgid)
{
	if(dlgid>=SCF_MAX_DLG_NUM) return 0;
	memset(&scsm_data[dlgid],0,sizeof(SCSM_DATA));
	return 1;
}


int scsmGetOpen()
{
    register int 	id;
    unsigned short 	dlgid;
    CAP_Message 	capmsg;
    
    for(id=0;id<64;id++)
    {
    	if(!cap_get_open((unsigned char *)&capmsg,SSN_SCF))
        	return 1;
/*
		if(capmsg.msgOperaCode != CAP_O_OPEN)
			continue;
*/
		dlgid = capmsg.dialogue_id[0]*256+capmsg.dialogue_id[1];		             		
        if(dlgid>=SCF_MAX_DLG_NUM)
           	continue;
        if(scsm_data[dlgid].State != SCF_IDLE)
        	continue;   	
        	
        ClearPortSub(dlgid);      
        ClearThreadData(dlgid);
     
        PutScfOpen(capmsg);
        
        scsm_data[dlgid].State = SCF_INIT;
		scsm_data[dlgid].acn = capmsg.msgContent[0];
		scsm_data[dlgid].acn_v = capmsg.msgContent[1];
    }
    return 1;
}


int scf_fsm(unsigned short dlgid)
{        
	SCSM_DATA *scf_ptr;
	
    scf_ptr = &scsm_data[dlgid];
 
    switch (scf_ptr->State)
    {
        case SCF_IDLE:                    
            break;
        case SCF_INIT:
        	scf_ptr->State = scfInitProc(dlgid);
        	break;
        case SCF_PREPARING_SSF_INSTRUCTIONS:
            scf_ptr->State = scfPreparingSsfInstructions(dlgid);
            break;
        case SCF_WAITING_NOTIFICATION_OR_REQUEST:
            scf_ptr->State = scfWaitingNotificationOrRequest(dlgid);
            break;
        case SCF_WAITING_DISCONNECT_FORWARD_CONNECT:
            scf_ptr->State = scfWaitinDisconnectForwardConnection(dlgid);
            break;
		case SCF_WAITING_PLAYANNOUNCEMENT:
			scf_ptr->State = scfWaitingPlayAnnouncement(dlgid);
			break;
        case SCF_VPS_PROC:
            scf_ptr->State = scfVPSProc(dlgid);
            break;
		case SCF_SEND_END:
			scfSendTCEnd(dlgid);
			scf_ptr->State = SCF_IDLE;
			break;
        default:
            scf_ptr->State = SCF_IDLE;
            break;
    }
    return 0;
}

int scsm()
{
    register int id;
    
    scsmGetOpen();
    
    for(id=0;id<SCF_MAX_DLG_NUM;id++)
    {
    	scf_fsm(id);
    }
    return 1;
}
