#include "Page1.h"

#include "p_rtp.h"
#include "p_dsp.h"

#ifdef SYS_CITRON
#include "citron.h"
#endif

#ifdef SYS_AUVTECH
#include "auvtech.h"
#endif

#ifdef SYS_ASIAINFO
#include "asiainfo.h"
#endif

#ifdef SYS_YIYANG
#include "yiyang.h"
#endif

#ifdef SYS_RINGTEC
#include "ringtec.h"
#endif

#ifdef SYS_TXTC
#include "txtc.h"
#endif

#ifdef OEM_SKYCOM
#include "skycom.h"
#endif

#if defined OEM_MEDIARING || defined OEM_RINGCHAT
#include "mediaring.h"
#endif

#include "v_task.h"
#include "gdiconst.h"
//#include "PalmChip.h"

XCHAR Task_iDnsType = DNS_TYPE_NONE;

//#define CALL_CONNECT_TTL		61		// our answer setting max is 60 seconds
#define CALL_DISCONNECT_TTL		12
#define CALL_WAITING_TTL		4		// If call waiting, generate call waiting tone every 4 seconds
#define RING_BACK_TTL			3		// we generate ringback tone if there is no rtp ringback after 3 seconds

BOOLEAN	Task_bExtraDisplay = FALSE;

BOOLEAN Task_bSetupMode = FALSE;

BOOLEAN Task_bInbandDtmf;

#ifdef VER_IPH_E00
XCHAR	Rtp_bRcv;					// save boolean space
XLONG vida_iDurationTime = 0;
#endif

void Call_Initialize()
{
	Task_bCaller = FALSE;
	Task_bRingBack = FALSE;
	Task_bConnected = FALSE;
	Task_bConnecting = FALSE;
	Task_bDisconnecting = FALSE;

	Sys_iNetRetry = 30;
	if (Sys_iRegisterTTL <= 10)
	{
#ifdef CALL_SIP
		if (Sys_iServiceType == SIP_SERVICE_TYPE_NET2PHONE)
		{
			Sys_iRegisterTTL = 300;
		}
		else
#endif
		{
			Sys_iRegisterTTL = 60;
		}
	}

#ifdef CALL_H323
	// CONF ID and CALL ID
	p_rand_array((PXCHAR)Sdram_pDataCache, CALL_IDENTIFIER_LEN);
	SdramWriteData(PROTOCOL_SDRAM_POS+CONF_ID_SDRAM_LO, CALL_IDENTIFIER_LEN);
	X_VAL(Sdram_pDataCache, 0) ++;
	SdramWriteData(PROTOCOL_SDRAM_POS+CALL_ID_SDRAM_LO, CALL_IDENTIFIER_LEN);
	
	// set REMOTE_NUMBER_SDRAM_LO data length to 0
	SdramWriteData(OPTIONS_SDRAM_POS+REMOTE_NUMBER_SDRAM_LO, 0);

#ifdef SYS_RINGTEC		// RingTec System need CALL_ID and CONF_ID to do the encryption
	if (Sys_iServiceType == H323_SERVICE_TYPE_RINGTEC)
	{
		RingtecGenerateCipher();
	}
#endif
#endif

	Task_bExtraDisplay = FALSE;
#ifdef CALL_H323
	H323Initialize();
#elif defined CALL_SIP
	SipInitialize();
#elif defined CALL_MGCP
	MgcpInitialize();
#elif defined CALL_N2P
	N2pInitialize();
#elif defined CALL_WP
	WpInitialize();
#elif defined CALL_IAX2
	Iax2Initialize();
#elif defined CALL_EPN
	EpnInitialize();
#endif

#ifdef GUI_RTP
#ifdef VER_IPH_E00
	Rtp_bRcv = FALSE;
#endif
	RtpInitialize();
#endif

#ifdef CALL_H323
	Sys_iAudioType = (Sys_pCodecType[1] == CODEC_NULL) ? Sys_pCodecType[0] : CODEC_NULL;
#else
	Sys_iAudioType = Sys_pCodecType[0];
#endif

	if (PIO_bHandsetUp)
	{
#ifdef _USE_FXS_AG1170
		SlicActivePolarityReversal();
#elif defined _USE_FXS_AM79R70
		SlicActivePRMode();
#endif
	}

	if (!Task_bSetupMode)
	{
		KeypadClear();
	}
	KeyIO_bIndicated = FALSE;

	Sys_iScrollType = SCROLL_NULL;		// Andy
	p_memset_x(Sys_pRemoteNumber, 0, DIALED_MAX_LEN+1);
	p_memset_x(Sys_pPeerDisplay, 0, PHONE_NUMBER_LEN+1);

	Task_bCallHold = FALSE;
	Task_bOnHold = FALSE;
	Task_bCallTransfer = FALSE;
	Task_bCallWaiting = FALSE;

	Task_bInbandDtmf = FALSE;
	Call_lDuration = 0xffffffff;
	UIInitialize();
	DisplayNormalState();

#ifdef VER_IPH_E00
	VidaShowDuration(vida_iDurationTime);
#endif
}


void TaskInitialize()
{
	UpgradeInitialize();
	TelnetInitialize();

#ifdef _USE_RS232
	SerialInitialize();
#endif

#ifdef OEM_SKYCOM
	MoneyTcpInitialize();
#endif

	HttpInitialize();
	SntpInitialize();

#ifdef CALL_SIP
	StunInitialize();
#endif
	Call_Initialize();

	Task_bLogoned = FALSE;
	if (IsBroadcastIP(Sys_pNtsIP))
	{
		TaskLogon();
	}
	else
	{
		DisplayString(g_cTimeStart, 0);
		SntpStart();
	}
}


void TaskRestart(UCHAR iReason)
{
	XCHAR pBuf[DISPLAY_MAX_CHAR+1];

#ifdef CALL_H323
	if (Task_bCallTransfer)
	{
		Task_bCallTransfer = FALSE;
		H323Initialize();
		if (Sys_iAudioType != Sys_pCodecType[0])
		{
			Sys_iAudioType = Sys_pCodecType[0];
			Ac97Stop();
			Ac97Start();
		}
		Task_bCaller = TRUE;
		Task_bConnecting = TRUE;
		Task_bDisconnecting = FALSE;
		Task_iTimer = 0;
		if (H323Call(Sys_pPeerDisplay))
		{
			DisplayString(g_cCalling, 0);
			DisplayLine(Sys_pPeerDisplay, 1);
			return;
		}
	}
#endif

	OutputString(IDS_TASK_RESTART);
	if (Udp_iOutputDebug != DEBUG_LEVEL_FILE)
	{
		SoloFileCloseRead();
	}
	SysNormalSpeed();

#ifdef _USE_FAKE_FXO
	if (Sys_iDualMode == DUAL_MODE_PSTN_FIRST)
	{
		SwitchToFXO(TRUE);
	}
#endif

	Ac97StopRing();
	Ac97Stop();
	Call_lDuration ++;
	if (Call_lDuration)
	{
		GetTimeDisplay(Call_lDuration, (PUCHAR)pBuf);
		Display(pBuf, 1, 0, FALSE);
	}

	CallRecWriteStop();
	Call_Initialize();
	OnCheckHandset();

#ifdef CALL_SIP
	if (iReason == SIP_SIGNAL_REORDER)
	{
		if (IsCallMode() && !Task_bSetupMode)
		{
			DtmfCongestion();
		}
	}
#else
	if (iReason)
	{
		Task_iTimer = FUNCTION_TIME_OUT/2;
		Task_bExtraDisplay = TRUE;
		switch (iReason)
		{
#ifdef CALL_H323
		case 0x01:
			DisplayString(g_cUnknownNumber, 0);
			break;
		case 0x02:
			DisplayString(g_cServiceClearCall, 0);
			break;
		case 0x03:
			DisplayString(g_cLocalHangup, 0);
			break;
/*		case 0x04:
			DisplayString(g_cNetworkError, 0);
			break;
*/
		case 0x80:
		case 0x90:
			DisplayString(g_cPeerHangup, 0);
			break;
		case 0x81:
		case 0x84:	// Send special information tone
		case 0x85:	// Misdialled trunk prefix
		case 0x96:	// number changed
		case 0x9c:	// Invalid number format
			DisplayString(g_cInvalidNumber, 0);
			break;
		case 0x91:
			DisplayString(g_cPeerBusy, 0);
			break;
		case 0x92:	// No user responding
		case 0x93:	// No answer from user
		case 0x9f:	// Normal, unspecified
			DisplayString(g_cNoAnswer, 0);
			break;
		case 0x95:
			DisplayString(g_cPeerReject, 0);
			break;
#elif defined CALL_WP
		case WP_HANGUP_ENDTALK:
			DisplayString(g_cPeerHangup, 0);
			break;
		case WP_HANGUP_NOTLOGON:	
			DisplayString(g_cWaitLogon, 0);
			break;
		case WP_HANGUP_CALLLIMITED:
			DisplayString(g_cCallRestricted, 0);
			break;
		case WP_HANGUP_NOTENOUGHMONEY:
			DisplayString(g_cRecharge, 0);
			break;
		case WP_HANGUP_DATETIMEOUT:
			DisplayString(g_cAccountExpired, 0);
			break;
		case WP_HANGUP_GWNOTEXISTS:	
		case WP_HANGUP_GKBUSY:	
		case WP_HANGUP_GWBUSY:		
		case WP_HANGUP_GKERR:			
		case WP_HANGUP_GWERR:			
		case WP_HANGUP_GWCODECERR:	
			break;
		case WP_HANGUP_CH_BUSY:	
			DisplayString(g_cPeerBusy, 0);
			break;
		case WP_HANGUP_CH_NOTEXISTS:
			DisplayString(g_cUnknownNumber, 0);
			break;
		case WP_HANGUP_CH_ERR:
		case WP_HANGUP_PHNUMERR:
			DisplayString(g_cInvalidNumber, 0);
			break;
#endif
		}
	}
#endif

#ifdef CALL_H323
	if ((Sys_iNatTraversal == H323_NAT_TRAVERSAL_CITRON || Sys_iNatTraversal == H323_NAT_TRAVERSAL_AIVGR)
		&& Sys_bNATed && !IsCallMode() && Task_bLogoned)
	{
		H323NatConnect();
	}
#endif
}

#ifdef CALL_N2P
void _OnN2pBalance()
{
	DSHORT iVal;
	DCHAR iLen;

	iVal = N2p_iCallTime;
	iVal /= 60;
	p_itoa(iVal, N2p_pToken, 10);
	DisplayLine(N2p_pToken, 0);		// call time in minutes

	p_itoa(N2p_iBalance, N2p_pToken, 10);

	// cent 2 dollar convert
	iLen = p_strlen_x(N2p_pToken);
	N2p_pToken[iLen+1] = 0;
	N2p_pToken[iLen] = N2p_pToken[iLen-1];
	N2p_pToken[iLen-1] = N2p_pToken[iLen-2];
	N2p_pToken[iLen-2] = '.';

	DisplayLine(N2p_pToken, 1);		// balance in dollars
/*
	if (iVal == 500)
	{	// play balance when max call time (500 minutes) remain
		SdramPlayString(N2p_pToken);
	}
	else
	{
		SdramPlayNumber(iVal);
	}
*/
}
#endif

void TaskSignalMsg(UCHAR iType)
{
	switch (iType)
	{
/*	case SIGNAL_IP_CONFLICT:
		DisplayString(g_cDuplicatedIP, 0);
		SysSleep(5000000);
		break;
*/
#ifndef CALL_EPN
	case SIGNAL_START_RING:
		Ac97StartRing();
		break;
#endif

	case SIGNAL_STOP_RING:
		Ac97StopRing();
		break;
#if defined CALL_SIP || defined CALL_IAX2
	case SIGNAL_RING_BACK:
		DtmfRing();
		break;

	case SIGNAL_CALL_WAITING:
		DisplayString(g_cCallWaiting, 0);
		DisplayLine(Sys_pPeerDisplay, 1);
		Task_bCallWaiting = TRUE;
		DtmfPlayKey('#');
		break;

	case SIGNAL_STOP_WAITING:
		DisplayNormalState();
		Task_bCallWaiting = FALSE;
		break;
#else
	case SIGNAL_RING_BACK:
		SysRingBack();
		break;
#endif

#ifdef CALL_H323
	case SIGNAL_INCOMING_CALL:
		if (CanAcceptCall())
		{
			H323AnswerCall(TRUE);
			OnCalled();
		}
		else
		{
			H323AnswerCall(FALSE);
		}
		break;

	case SIGNAL_SERVICE_CONTROL:
#ifdef SYS_AUVTECH
		if (Sys_iServiceType == H323_SERVICE_TYPE_AUVTECH || Sys_iServiceType == H323_SERVICE_TYPE_SOYO)
		{
			AuvtechHandleSci();
		}
#endif
#ifdef SYS_CITRON
		if (Sys_iServiceType == H323_SERVICE_TYPE_CITRON)
		{
			CitronHandleSci();
		}
#endif
		break;

#endif // CALL_H323

#ifdef CALL_SIP
	case SIGNAL_INCOMING_CALL:
		if (CanAcceptCall())
		{
			SipAnswerCall(TRUE);
			OnCalled();
		}
		else
		{
			SipAnswerCall(FALSE);
		}
		break;

	case SIP_PEER_HANGUP:
		DisplayString(g_cPeerHangup, 0);
		Ac97StopRing();
		if (IsCallMode())
		{
			DtmfBusy();
		}
		break;

	case SIP_SIGNAL_BUSY:
		DisplayString(g_cCallTerminated, 0);
		if (IsCallMode())
		{
			DtmfBusy();
		}
		break;

	case SIP_SIGNAL_REORDER:
		DisplayString(g_cCallTerminated, 0);
		if (IsCallMode())
		{
			DtmfCongestion();
		}
		break;

	case SIP_UPDATE_STATE:
		if (Sip_iConnMode & SIP_MODE_SENDONLY)
		{
			Task_bOnHold = FALSE;
#ifdef OEM_263
			SoloFileCloseRead();
#endif
		}
		else
		{
			Task_bOnHold = TRUE;
#ifdef OEM_263
			SdramRingFile();	// ring file as call hold file
#endif
		}
		DisplayNormalState();
		break;

	case SIP_CALL_FORWARD:
		DisplayString(g_cCallForward, 0);
		break;

	case SIP_STOP_TONE:
		DtmfStopAll();
		break;
#endif // CALL_SIP

#ifdef CALL_MGCP
	case MGCP_EVENT_DTMF_0:
	case MGCP_EVENT_DTMF_1:
	case MGCP_EVENT_DTMF_2:
	case MGCP_EVENT_DTMF_3:
	case MGCP_EVENT_DTMF_4:
	case MGCP_EVENT_DTMF_5:
	case MGCP_EVENT_DTMF_6:
	case MGCP_EVENT_DTMF_7:
	case MGCP_EVENT_DTMF_8:
	case MGCP_EVENT_DTMF_9:
		DtmfPlayKey((UCHAR)(iType - MGCP_EVENT_DTMF_0 + '0'));
		break;
	case MGCP_EVENT_DTMF_STAR:
		DtmfPlayKey('*');
		break;
	case MGCP_EVENT_DTMF_POUND:
		DtmfPlayKey('#');
		break;

	case MGCP_EVENT_GENERIC_RT:
	case MGCP_EVENT_LINE_RT:
		Task_bCaller = TRUE;
//		SysRingBack();
		DtmfRing();
		break;

	case MGCP_EVENT_LINE_DL:
		Task_bCaller = TRUE;
		DisplayString(g_cPleaseDial, 0);
		DisplayString(g_cBlank, 1);
		DtmfDialTone();
		break;

	case MGCP_EVENT_LINE_E:
		DtmfBusy();
		break;

	case MGCP_EVENT_LINE_RO:
	case MGCP_EVENT_LINE_BZ:
		if (Sys_iServiceType == SERVICE_TYPE_ZTE)
		{
			TaskRestart(0);
		}
		DtmfBusy();
		break;

	case MGCP_EVENT_LINE_RG:
		OnCalled();
		break;

	case MGCP_EVENT_LINE_CI:
		CallRecWriteStart(Sys_pPeerDisplay, CALL_TYPE_MISSED);
		DisplayLine(Sys_pPeerDisplay, 1);
		break;

	case MGCP_EVENT_CRCX:
		Task_bConnecting = TRUE;
		if (Task_bCaller && Sys_iServiceType == SERVICE_TYPE_HUAWEI)
		{
			DisplayString(g_cCalling, 0);
		}
		break;

	case MGCP_CALL_CONNECTED:
		if (!Task_bConnected && Mgcp_iConnMode == MGCP_MODE_SENDRECV)
		{
			if (Task_bCaller && Sys_iServiceType == SERVICE_TYPE_HUAWEI)
			{
				p_strcpy_x2x(Sys_pRemoteNumber, Key_pBuf);
				KeypadClear();
				CallRecWriteStart(Sys_pRemoteNumber, CALL_TYPE_DIALED);
				SdramSaveData(OPTIONS_SDRAM_POS+KEY_PREVBUF_SDRAM_LO, Sys_pRemoteNumber, p_strlen_x(Sys_pRemoteNumber));
			}
			TaskConnected();
		}
		break;

	case MGCP_EVENT_DLCX:
		if (IsCallMode())
		{
			DisplayString(g_cPleaseHangup, 0);
			DisplayString(g_cBlank, 1);
			Task_bConnected = FALSE;
		}
		else
		{
			TaskRestart(0);
		}
		break;

	case MGCP_START_CALL:
		if (Sys_iServiceType != SERVICE_TYPE_HUAWEI)
		{
			CallRecWriteStart(Sys_pRemoteNumber, CALL_TYPE_DIALED);
			SdramSaveData(OPTIONS_SDRAM_POS+KEY_PREVBUF_SDRAM_LO, Sys_pRemoteNumber, p_strlen_x(Sys_pRemoteNumber));
			DisplayString(g_cCalling, 0);
			KeypadClear();
		}
		break;

	case MGCP_EVENT_HANGUP:
		TaskRestart(0);
		break;

	case MGCP_STOP_SIGNAL:
		if (!Task_bCaller)
		{
			Ac97StopRing();
		}
		break;

	case MGCP_SEND_DTMF0:
	case MGCP_SEND_DTMF1:
	case MGCP_SEND_DTMF2:
	case MGCP_SEND_DTMF3:
	case MGCP_SEND_DTMF4:
	case MGCP_SEND_DTMF5:
	case MGCP_SEND_DTMF6:
	case MGCP_SEND_DTMF7:
	case MGCP_SEND_DTMF8:
	case MGCP_SEND_DTMF9:
	case MGCP_SEND_DTMFSTAR:
	case MGCP_SEND_DTMFPOUND:
		OnOutgoingKey(p_getAsciiKey((UCHAR)(iType - MGCP_SEND_DTMF0)));
		break;	

	case MGCP_EVENT_LINE_Z_POS:		//huawei think L/z(+) is the polarity reverse signal
		if (Task_bConnected)
		{
			Call_lDuration = 1;
		}
		break;
#endif

#ifdef CALL_N2P
	case SIGNAL_INCOMING_CALL:
		if (CanAcceptCall())
		{
			N2pAnswerCall(TRUE);
			OnCalled();
		}
		else
		{
			N2pAnswerCall(FALSE);
		}
		break;

	case N2P_BALANCE:
		_OnN2pBalance();
		break;

#endif // CALL_N2P

#ifdef CALL_WP
	case SIGNAL_INCOMING_CALL:
		if (CanAcceptCall())
		{
			WpAnswerCall(TRUE);
			OnCalled();
		}
		else
		{
			WpAnswerCall(FALSE);
		}
		break;
#endif // CALL_WP

#ifdef CALL_IAX2
	case SIGNAL_INCOMING_CALL:
		if (CanAcceptCall())
		{
			Iax2AnswerCall(TRUE);
			OnCalled();
		}
		else
		{
			Iax2AnswerCall(FALSE);
		}
		break;

	case IAX2_START_CALL:
		Task_bConnecting = TRUE;
		CallRecWriteStart(Key_pBuf, CALL_TYPE_DIALED);
		SdramSaveData(OPTIONS_SDRAM_POS+KEY_PREVBUF_SDRAM_LO, Key_pBuf, p_strlen_x(Key_pBuf));
		DisplayString(g_cCalling, 0);
		KeypadClear();
		break;
/*
	case IAX2_CALL_TERMINATED:
		DisplayString(g_cCallTerminated, 0);
		if (IsCallMode())
		{
			DtmfBusy();
		}
		break;
*/
#endif // CALL_IAX2

#ifdef CALL_EPN
	case SIGNAL_START_RING:
		if (CanAcceptCall())
		{
			OnCalled();
		}
		else
		{
			TaskHangup();
		}
		break;

	case SIGNAL_INCOMING_CALL:
		if (CanAcceptCall())
		{
			EpnAnswerCall(TRUE);
		}
		else
		{
			EpnAnswerCall(FALSE);
		}
		break;
#endif // CALL_EPN
	}
}

void TaskLogon()
{
	DSHORT iPort;
	PXCHAR_D pIP;

	if (!Discover_bFinished)	return;
	if (Task_bLogoned)			return;

	if (Sys_iNatTraversal == NAT_TRAVERSAL_ENABLE)
	{
		SdramReadFlags();
		if (X_VAL(Sdram_pDataCache, FLAGS_PAGE12_ATTR) == PAGE12_CHANGED_IP)
		{
			OnReboot();		// find possible new public ip before log on again
		}
	}

	DisplayString(g_cLogon, 0);
	DisplayString(g_cPleaseWait, 1);

	Task_bNewMessage = FALSE;

	if (!p_strlen_x(Sys_pServiceAddr))
	{
#ifdef CALL_SIP
		if (p_strlen_x(Sys_pServiceID) && Sys_bUseService)
		{
			if (p_String2IP(Sys_pServiceID, Sys_pServiceIP))
			{
				if (IsValidIP(Sys_pServiceIP))
				{
					CheckNatAddr();
				}
			}
			else
			{
				p_strcpy_c2x((PXCHAR)Sdram_pDataCache, (PCCHAR)"_sip._udp.");
				p_strcat_x2x((PXCHAR)Sdram_pDataCache, Sys_pServiceID);
				Task_iDnsType = DNS_TYPE_SERVICE;
				DnsSend((PXCHAR)Sdram_pDataCache, TRUE);
			}
		}
		else
#endif
		{
			p_memset_ip_0(Sys_pServiceIP);
			p_memset_ip_0(Sys_pGWIP);
			CheckNatAddr();
		}
		return;
	}

	pIP = Sys_bUseService ? Sys_pServiceIP : Sys_pGWIP;

	iPort = ParseDnsAddr(Sys_pServiceAddr, pIP, (PXCHAR)Sdram_pDataCache);
	if (iPort)
	{
		Sys_iServicePort = iPort;
	}
	if (IsValidIP(pIP))
	{
		CheckNatAddr();
		return;
	}

	Task_iDnsType = DNS_TYPE_SERVICE;
	DnsSend((PXCHAR)Sdram_pDataCache, FALSE);
}

void TaskCall()
{
	if (!Task_bLogoned)	return;

#ifndef CALL_MGCP

#ifdef CALL_SIP
	if(Sys_iNatTraversal == SIP_NAT_TRAVERSAL_STUN)
	{
		StunCheckIPPort(STUN_TASK_CALL, Sys_iRtpPort);
		return;
	}
#endif

#ifdef CALL_H323
	if (!H323Call(Key_pBuf))
#elif defined CALL_SIP
	if (!SipCall(Key_pBuf))
#elif defined CALL_N2P
	if (!N2pCall())
#elif defined CALL_WP
	if (!WpCall())
#elif defined CALL_IAX2
	if (!Iax2Call(Key_pBuf))
#elif defined CALL_EPN
	if (!EpnCall())
#endif
	{
		TaskRestart(0);
//		goto End;
		return;
	}

#ifdef GUI_RTP
	RtpStartReceive(TRUE);
#endif
	Task_bCaller = TRUE;
	Task_bConnecting = TRUE;
	DisplayString(g_cCalling, 0);
#if defined CALL_SIP || defined CALL_IAX2
	KeypadClear();
#endif
//End:
#endif	// CALL_MGCP
//	KeypadClear();
}


void TaskHangup()
{
#ifndef CALL_MGCP
	if (IsFunctionMode())
	{
		TaskRestart(0);
		return;
	}

	OutputString(IDS_TASK_HANGUP);

	Task_iTimer = 0;
	Task_bConnecting = FALSE;
	Task_bDisconnecting = TRUE;
	Task_bConnected = FALSE;
	DspClearDecodeData();
#ifdef GUI_RTP
	RtpClose();
#endif

#ifdef CALL_H323
	H323Hangup();
#elif defined CALL_SIP
	SipHangup();
#elif defined CALL_N2P
	N2pHangup();
#elif defined CALL_WP
	WpHangup();
#elif defined CALL_IAX2
	Iax2Hangup();
#elif defined CALL_EPN
	EpnHangup();
#endif

#endif	// CALL_MGCP
}


void TaskLogoffCompleted()				
{
	Task_bLogoned = FALSE;
#ifdef VER_PA168P
	Led_Off(SECOND_LIGHT);
#endif
}

void TaskHandleTimer()
{
	Sys_lCurrentTime ++;
	if (Task_bLogoned)
	{
		if (Task_bConnected)
		{
#ifdef GUI_RTP
#ifndef CALL_SIP
			RtcpHandleTimer();
#endif
#endif
			Call_lDuration ++;
			if (Task_bCallWaiting)
			{
				if ((Call_lDuration % CALL_WAITING_TTL) == 0)
				{
					DtmfPlayKey('#');
				}
			}
		}
		else if (!IsUpgrading())
		{
#ifdef CALL_MGCP
			if (Task_bConnecting && Key_bCopied && Sys_iScrollType != SCROLL_NULL)
			{
				OnMgcpCall();
			}
			// MGCP doesn't need auto dial out
			if (IsCallMode() && Task_bCaller && Task_iTimer == Map_iTimeOut)
			{
				MgcpNotify(MGCP_EVENT_DTMF_T);
			}
#else	// CALL_MGCP
			if (IsCallMode() && IsFunctionMode() && !Ac97_bIVR && Task_iTimer == Map_iTimeOut)
			{
				if (p_strlen_x(Key_pBuf) && KeyIO_bIndicated)
				{
					if (Sys_bUseDigitMap)
					{
						if (OnMapMatch(TRUE))
						{
							OnCall();
						}
						else
						{
							Task_iTimer = 0;
						}
					}
					else
					{
						if(!Task_bSetupMode)
							OnCall();
					}
				}
				else
				{
					if(!Task_bSetupMode)
						DtmfBusy();
				}
			}

/*			if (Task_bConnecting && Task_iTimer > CALL_CONNECT_TTL)
			{
				TaskHangup();
			}
*/
			if (Task_bDisconnecting && Task_iTimer > CALL_DISCONNECT_TTL)
			{
				TaskRestart(0);
			}
#endif	// CALL_MGCP

			if (Task_bConnecting)
			{
				if (Task_bCaller)
				{
					if (Task_bRingBack && Task_iTimer == RING_BACK_TTL)
					{
						DtmfRing();		// generate ring back tone locally
					}
				}
				else
				{
#ifdef _USE_FXS
					SlicRingHandleTimer(Task_iTimer);
#endif	// _USE_FXS
					if ((Task_iTimer > Task_iRingNumber) && Task_iRingNumber)
					{
						if (Sys_iForwardType & FORWARD_NOANSWER_OR)
						{
#ifdef CALL_H323	
							H323CallForward();
#endif
#ifdef CALL_SIP
							SipCallForward();
#endif
						}
					}
				}
			}
		}
	}

	if (!IsUpgrading())
	{
#ifdef CALL_H323
		H323HandleTimer();
#elif defined CALL_SIP
		SipHandleTimer();
#elif defined CALL_MGCP
		MgcpHandleTimer();
#elif defined CALL_N2P
		N2pHandleTimer();
#elif defined CALL_WP
		WpHandleTimer();
#elif defined CALL_IAX2
		Iax2HandleTimer();
#elif defined CALL_EPN
		EpnHandleTimer();
#endif
	}

	if (IsFunctionMode())
	{
		UpgradeHandleTimer();
		SntpHandleTimer();
	}

#ifdef OEM_SKYCOM
	MoneyTcpHandleTimer(); 
	MomeryKeyHandleTimer();
#endif

#ifdef CALL_SIP
	if (Sys_iNatTraversal == SIP_NAT_TRAVERSAL_STUN)
	{
		StunHandleTimer();
	}
#endif

#ifdef SYS_YIYANG
	if (Sys_iServiceType == H323_SERVICE_TYPE_YIYANG)
	{
		YiyangTcpHandleTimer();
	}
#endif

	TelnetHandleTimer();
	HttpHandleTimer();
}

void TaskConnected()
{
	Ac97Stop();
	DisplayString(g_cConnected, 0);
#ifndef VER_IPH_E00
	DisplayString(g_cTimeStart, 1);
#else
	vida_iDurationTime = 0;
#endif

	Call_lDuration = 1;

	Task_bConnected = TRUE;
	Task_bConnecting = FALSE;
	Task_bRingBack = FALSE;

#ifdef _USE_FXS_AM79R70
	SlicActivePRMode();
#endif
#ifdef _USE_FXS_AG1170
	SlicActivePolarityReversal();
#endif

	if (Task_bCaller)
	{
		Sys_iScrollType = SCROLL_NULL;
	}
	DspClearDecodeData();

	SysHighSpeed();
	Ac97Start();
}

void TaskStartRtp()
{
#ifdef GUI_RTP
	BOOLEAN bSend, bRecv;
#endif

	if (Sys_iAudioType != Dsp_iType)
	{
		Ac97Stop();
		Ac97Start();
		if (Task_bConnecting)
		{
			if (Task_bCaller)
			{
				if (Task_bRingBack)
				{
					SysRingBack();
				}
			}
			else
			{
#ifdef _USE_FXS
				GetDateTimeDisplay((PXCHAR)Sdram_pDataCache, FALSE, Sys_lCurrentTime);
				OutputVals((PXCHAR)Sdram_pDataCache, 20);
				SdramWriteAll(OPTIONS_SDRAM_POS+CID_INFO_SDRAM_LO);	// Save to Sdram
#endif
				Ac97StopIVR();
				Ac97StartRing();
			}
		}
	}

	OutputVal(Sys_iAudioType, IDS_RTP_AUDIO_TYPE);
#if defined CALL_H323 || defined CALL_EPN
	Rtcp_iDstPort = (USHORT)(Rtp_iDstPort + 1);
#endif

#ifdef GUI_RTP
#ifdef CALL_SIP
	if (Sip_iConnMode & SIP_MODE_SENDONLY)
	{
		bSend = TRUE;
	}
	else
	{
		bSend = FALSE;
	}
	if (Sip_iConnMode & SIP_MODE_RECVONLY)
	{
		bRecv = TRUE;
	}
	else
	{
		bRecv = FALSE;
	}
#elif defined CALL_MGCP
	if (Mgcp_iConnMode == MGCP_MODE_SENDONLY || Mgcp_iConnMode == MGCP_MODE_SENDRECV || Mgcp_iConnMode == MGCP_MODE_CONFRNCE)
	{
		bSend = TRUE;
	}
	else
	{
		bSend = FALSE;
	}
	if (Mgcp_iConnMode == MGCP_MODE_SENDRECV || Mgcp_iConnMode == MGCP_MODE_RECVONLY || Mgcp_iConnMode == MGCP_MODE_CONFRNCE)
	{
		bRecv = TRUE;
	}
	else
	{
		bRecv = FALSE;
	}
#else
	bSend = TRUE;
	bRecv = TRUE;
#endif
	RtpOpen(bSend, bRecv);
	RtcpOpen();
#endif
	SysHighSpeed();

#ifdef CALL_H323
	H323Connected();
#endif
}

void TaskDnsCompleted()				
{
	DCHAR iType;

	iType = Task_iDnsType;
	Task_iDnsType = DNS_TYPE_NONE;

	switch (iType)
	{
	case DNS_TYPE_SERVICE:
		p_memcpy_ip((Sys_bUseService ? Sys_pServiceIP : Sys_pGWIP), Dns_pResolvedIP);
		CheckNatAddr();
#ifdef CALL_SIP
		if (Sys_iServiceType == SIP_SERVICE_TYPE_ITALKBB || Sys_iServiceType == SERVICE_TYPE_ZTE)
		{
			p_IP2String(Dns_pResolvedIP, Sys_pServiceID);
		}
#endif
		break;

	case DNS_TYPE_PROXY:
		p_memcpy_ip(Sys_pProxyServerIP, Dns_pResolvedIP);
		CheckProxy();
		break;

	case DNS_TYPE_SNTP:
		SntpSend(Dns_pResolvedIP);
		break;
	}
}
			
void TaskDnsFailed()				
{
	DCHAR iType;

	iType = Task_iDnsType;
	Task_iDnsType = DNS_TYPE_NONE;

	OutputString(IDS_DNS_FAILED);

	switch (iType)
	{
	case DNS_TYPE_SNTP:
		SntpRetry();
		break;
	}
}

void TaskLogonCompleted()				
{
	DisplayString(g_cReady, 0);
#if defined VER_IPH_E00_8B_F || defined VER_IPH_E00_8B_NF
	DisplayLine((PXCHAR)GetVersionText(), 1);
#else
	DisplayLine((PXCHAR)GetHardwareVersion(), 1);
#endif

	Task_bLogoned = TRUE;

	Led_Off(NORMAL_LIGHT);
#ifdef VER_PA168P
	Led_On(SECOND_LIGHT);
#endif
#if defined _USE_FAKE_FXO && defined OEM_HUAWEI3COM
	Led_On(SERVICE_LIGHT);
#endif

#ifdef CALL_H323
	if (Sys_iNatTraversal == H323_NAT_TRAVERSAL_CITRON)
	{
		CitronNatConnect();
	}
#ifdef SYS_ASIAINFO
	else if (Sys_iNatTraversal == H323_NAT_TRAVERSAL_AIVGR)
	{
		AIVGRNatConnect();
	}
#endif

#ifdef SYS_YIYANG
	if (Sys_iServiceType == H323_SERVICE_TYPE_YIYANG)
	{
		YiyangNatConnect();
		return;
	}
#endif
#endif
}

			
void TaskLogonFailed(UCHAR iError)				
{
	DisplayString(g_cLogon, 0);
	DisplayString(g_cFailed, 1);
	Task_bLogoned = FALSE;

#ifdef VER_PA168P
	Led_Off(SECOND_LIGHT);
#endif

	if (iError)
	{
		SysSleep(1000000);
#ifdef CALL_H323
#elif defined CALL_WP
		switch (iError)
		{
		case WP_RCJ_USERNOTEXISTS:
			DisplayString(g_cUnknownNumber, 1);
			break;
		case WP_RCJ_PSWERR:
			DisplayString(g_cInvalidPassword, 1);
			break;
		case WP_RCJ_USERUSED:
			DisplayString(g_cDuplicateNumber, 1);
			break;
		case WP_RCJ_GKBUSY:               //网守已满载,不能接受该用户的注册 (7-6)
		case WP_RCJ_GKNOTEXISTS:			//网守还未启动(如果网守设置为调度程序的监听地址,而网守还未启动,则返回该代码 ) 
		case WP_RCJ_SYSERR:
			break;
		case WP_RCJ_USERIDERR:             //用户号码错误          (7-8)
			DisplayString(g_cInvalidNumber, 1);
			break;
		case WP_RCJ_USERLOCKED:            //用户号码被系统锁定    (7-8)
		case WP_RCJ_USERIPLOCKED:          //用户IP被系统锁定      (7-8)
			DisplayString(g_cBlockedNumber, 1);
			break;

		}
#elif defined CALL_EPN
		switch (iError)
		{
		case EPN_REJ_CLIENTID_ERR:			//无效的端点标识，或者呼叫请求端点没有注册
			DisplayString(g_cUnknownNumber, 1);
			break;
		case EPN_REJ_DUPLICATEUSER:			//重复等录
			DisplayString(g_cDuplicateNumber, 1);
			break;
		case EPN_REJ_ACCOUNTPIN_ERR:		//无效的用户名/密码
			DisplayString(g_cInvalidPassword, 1);
			break;
		case EPN_REJ_CREDITNOTENOUGH:		//信用额度不足，或者没有执行请求动作的权限		
			DisplayString((PCCHAR)"Insufficient credit", 1);
			break;
		case EPN_REJ_BLOCKED:				//由于频繁无效登陆，暂时被禁止登陆
			DisplayString(g_cBlockedNumber, 1);
			break;
		}

#endif
	}
}

UCHAR TaskUserData(UCHAR iDataType, PXCHAR pData)
{
	PXCHAR_D pBuf;
	DCHAR iType;

	pBuf = pData;
	iType = iDataType;

	if (iType == USER_DATA_SOFTWARE_VER)
	{
		p_memcpy_c2x(pBuf, g_cSoftwareVersion, 4);
		return 4;
	}
	else if (iType == USER_DATA_HARDWARE_VER)
	{
		p_strcpy_x2x(pBuf, GetHardwareVersion());
		return p_strlen_x(pBuf);
	}

#ifdef CALL_SIP
	// add your specific User-Agent: header here
	// Be sure to use a specific service type to identify your service
	if (iType == SIP_USER_AGENT)
	{
		switch (Sys_iServiceType)
		{
		case SIP_SERVICE_TYPE_NET2PHONE:
			p_line_add_c((PCCHAR)"Koncept_");
			p_Mac2String(Local_pMacAddress, (PXCHAR)Sdram_pDataCache);
			p_line_add_x((PXCHAR)Sdram_pDataCache);
			break;
#ifdef	OEM_HUAWEI3COM
		case SERVICE_TYPE_HUAWEI:
			p_line_add_x(GetHardwareVersion());
			p_line_add_char('/');
			p_line_add_x(GetSoftwareVersion());
			p_line_add_c((PCCHAR)" mac/");
			p_Mac2String(Local_pMacAddress, (PXCHAR)Sdram_pDataCache);
			p_line_add_x((PXCHAR)Sdram_pDataCache);
			p_line_add_c((PCCHAR)" name/");
			p_line_add_x(Sys_pAccount);
			break;
#endif

		case SIP_SERVICE_TYPE_QMASTER:
			p_line_add_c((PCCHAR)"SIPSYS ");
			p_line_add_x(GetSoftwareVersion());
			break;

		default:
			p_line_add_x(GetVersionTextEx(TRUE, TRUE));
			break;
		}
	}
#if defined OEM_MEDIARING || defined OEM_RINGCHAT
	else if (iType == SIP_MEDIARING_ENCRYPT)
	{
		if (Sys_iServiceType == SIP_SERVICE_TYPE_MEDIARING || Sys_iServiceType == SIP_SERVICE_TYPE_RINGCHAT)
		{
			MediaringEncrypt(pBuf);
		}
	}
#endif
#endif

#ifdef CALL_H323
	if (Sys_iNatTraversal == H323_NAT_TRAVERSAL_CITRON)
	{
		return CitronUserData(iType, pBuf);
	}
#ifdef SYS_AUVTECH 
	else if (Sys_iServiceType == H323_SERVICE_TYPE_AUVTECH || Sys_iServiceType == H323_SERVICE_TYPE_SOYO)
	{
		return AuvtechUserData(iType, pBuf);
	}
#endif
#ifdef SYS_TXTC 
	else if (Sys_iServiceType == H323_SERVICE_TYPE_TXTC)
	{
		return TxtcUserData(iType, pBuf);
	}
#endif
#ifdef SYS_ASIAINFO
	else if (Sys_iServiceType == H323_SERVICE_TYPE_ASIAINFO)
	{
		return AsiainfoUserData(iType, pBuf);
	}
#endif
#ifdef SYS_YIYANG
	else if (Sys_iServiceType == H323_SERVICE_TYPE_YIYANG)
	{
		return YiyangUserData(iType, pBuf);
	}
#endif
#endif
	return 0;
}

BOOLEAN TaskHandleData(UCHAR iDataType, PXCHAR pData, UCHAR iLength)
{
#ifdef CALL_MGCP
	pData = 0;
	iLength = 0;
	switch (iDataType)
	{
	case MGCP_HANDSET_HD:
	case MGCP_HANDSET_HU:
		OnHandFree();
		break;
	}
	return TRUE;

#else

	PXCHAR_D pBuf;
	DCHAR i, j, iType, iLen, iBackup;
	XCHAR pDisplayBuf[DISPLAY_MAX_CHAR+1];

	pBuf = pData;
	iType = iDataType;
	iLen = iLength;

	if (iType <= NONSTANDARD_NONSTANDARD)
	{
		iBackup = pBuf[iLen];
		pBuf[iLen] = 0;
	}

	switch (iType)
	{
	case HANDLE_DATA_CALLMODE:
		return IsCallMode();

	case HANDLE_DATA_PLAY:
		SdramPlayString(pBuf);
		break;

	case CALL_CREDIT_AMOUNT:
		// convert BMP string to ascii display
		for (i = 0, j = 0; i < iLen; i +=2, j ++)
		{
			pBuf[j] = pBuf[i+1];
		}
		pBuf[j] = 0;
		DisplayLine(pBuf, 0);
		break;

	case CALL_CREDIT_TIME:
		GetTimeDisplay(PXCHAR2ULONG((PXCHAR)Sdram_pDataCache), (PUCHAR)pDisplayBuf);
		DisplayLine(pDisplayBuf, 1);
		break;

	case HANDLE_DATA_DISPLAY:
		DisplayLine(pBuf, iLen);	// iLength used to select line number here
		break;

	case DTMF_START_KEY:
		if (!Task_bConnected)	return TRUE;
		if (Task_bInbandDtmf)	return TRUE;
		if (Task_bCallHold)	return TRUE;

		if (iLen)
		{
			DtmfPlayKey(pBuf[0]);
			Ac97_iDtmfDuration = 2000;
		}
		break;

	case DTMF_STOP_KEY:
		Ac97_iDtmfDuration = 0;
		break;

#ifdef SYS_CITRON
	case VOICE_MSG_HINT:
		p_memcpy_x2x(Key_pBuf, pBuf, iLen);
		OnCall();
		break;
	case UPGRADE_HINT:
		p_memcpy_x2x(Sys_pUpgradeAddr, pBuf, iLen);
		break;
#endif
#ifdef CALL_IAX2
	case VOICE_MSG_HINT:
		if (iLen)
		{
			Task_bNewMessage = TRUE;
			pBuf = (PXCHAR)Sdram_pDataCache;
			p_strcpy_c2x(pBuf, g_cNewMessage);
			p_strcat_c2x(pBuf, (PCCHAR)": ");
			i = p_strlen_x(pBuf);
			p_itoa((USHORT)iLen, (PXCHAR)(pBuf + i), 10);
			SdramWrite(OPTIONS_SDRAM_HI, MSG_HINT_SDRAM_LO, SRAM_DMA_HALF_DWORD);
			DisplayLine(pBuf, 1);
#ifdef BACKLIGHT_CTRL
//      L3ClockOn();
#ifdef INVERT_BACKLIGHT
      Cam_LedOn(0);
#else
      Cam_LedOff(0);
#endif
#endif
		}
		else
		{
			Task_bNewMessage = FALSE;
			DisplayString(g_cBlank, 1);
		}
		break;

	case IAX2_TRANSFER_HINT:
		p_memcpy_x2x_0(Key_pBuf, pBuf, iLen);
		OnCall();
		break;
#endif

#ifdef CALL_SIP
	case VOICE_MSG_HINT:
		if (iLen)
		{
			SdramReadString(PROTOCOL_SDRAM_POS+SIP_RECV_BODY);
			pBuf = (PXCHAR)Sdram_pDataCache;
			if (p_memcmp_nocase_c2x(pBuf, (PCCHAR)"Messages-Waiting", 16))
			{
				pBuf += 16;
				pBuf += p_count_char(pBuf, ':');
				if (p_memcmp_nocase_c2x(pBuf, (PCCHAR)"yes", 3))
				{
					Task_bNewMessage = TRUE;
					if (iLen > 1)
					{
						SdramReadString((USHORT)(PROTOCOL_SDRAM_POS+SIP_RECV_BODY + 1));
						if (iLen > 2)
						{
							if (p_memcmp_nocase_c2x((PXCHAR)Sdram_pDataCache, (PCCHAR)"Message-Account", 15))
							{
								SdramReadString((USHORT)(PROTOCOL_SDRAM_POS+SIP_RECV_BODY + 2));
							}
						}
					}
					else
					{
						p_strcpy_c2x((PXCHAR)Sdram_pDataCache, g_cNewMessage);
					}
					SdramWrite(OPTIONS_SDRAM_HI, MSG_HINT_SDRAM_LO, SRAM_DMA_HALF_DWORD);
					DisplayLine((PXCHAR)Sdram_pDataCache, 1);
#ifdef BACKLIGHT_CTRL
#ifdef INVERT_BACKLIGHT
					Cam_LedOn(0);
#else
					Cam_LedOff(0);
#endif
#endif
				}
				else
				{
					Task_bNewMessage = FALSE;
					DisplayString(g_cBlank, 1);
				}
			}
		}
		break;
	case SIP_MESSAGE_HINT:
		// the body of the MESSAGE req will be stored in SDRAM SIP_RECV_BODY
		// each line occupies one block and total number of line is in variable "iLen"
		if (iLen > 2)	iLen = 2;
		if (Sys_iServiceType == SIP_SERVICE_TYPE_QMASTER)
		{
			//Balance: 95.80/0.00/0/0
			//Rate: 8/0.20/60/RMB
			for (i = 0; i < iLen; i ++)
			{
				SdramReadString((USHORT)(PROTOCOL_SDRAM_POS+SIP_RECV_BODY + i));
				pBuf = p_strchr_x((PXCHAR)Sdram_pDataCache, ':');
				pBuf ++;
				pBuf += p_count_space(pBuf);
				DisplayLine(pBuf, i);
			}
		}
		else
		{
			for (i = 0; i < iLen; i ++)
			{
				SdramReadString(PROTOCOL_SDRAM_POS+SIP_RECV_BODY);
				pBuf = (PXCHAR)Sdram_pDataCache;
				// handle each line of your MESSAGE body here
				DisplayLine(pBuf, i);
			}
		}
		break;
	case SIP_INFO_HINT:
		// the body of the INFO req will be stored in SDRAM SIP_RECV_BODY
		// each line occupies one block and total number of line is in variable "iLen"
		for (i = 0; i < iLen; i ++)
		{
			SdramReadString(PROTOCOL_SDRAM_POS+SIP_RECV_BODY);
			pBuf = (PXCHAR)Sdram_pDataCache;
			// handle each line of your MESSAGE body here
		}
		break;
#endif

#ifdef CALL_H323
	case ADM_CFM_NONSTANDARD:
		if (Sys_iServiceType == H323_SERVICE_TYPE_ETALK)
		{
			eTalkHandleAdmCfm(pBuf);
		}
		else if (Sys_iServiceType == H323_SERVICE_TYPE_IPN)
		{
			IpnHandleAdmCfm(pBuf);
		}
		else if (Sys_iServiceType == H323_SERVICE_TYPE_IFONE)
		{ // I-FONE's system use ACF to indicate the avaiable time to call 
			if (pBuf[0] == 0x0c)
			{
				DisplayString((PCCHAR)"Remain Time", 0);
				DisplayLine((PXCHAR)(pBuf+1), 1);
				SysSleep(2500000);
			}			
		}
		else if (Sys_iServiceType == SERVICE_TYPE_HUAWEI)
		{
			iLen = pBuf[1] + 2;		// pBuf[1] should be 0x0c, 00 0c XX XX XX ... XX 07 31 32 33 34 35 36 37
			if (iLen != 14)	return FALSE;
			i = iLen + 1;
			iLen = pBuf[iLen];
			p_memcpy_x2x_0(Sys_pRemoteNumber, (PXCHAR)(pBuf+i), iLen);
		}
#ifdef SYS_ASIAINFO
		else if (Sys_iServiceType == H323_SERVICE_TYPE_ASIAINFO)
		{
			AsiainfoHandleAdmCfm(pBuf);
		}
#endif
#ifdef SYS_YIYANG
		else if (Sys_iServiceType == H323_SERVICE_TYPE_YIYANG)
		{
			YiyangDecodeNonStandard(iType, pBuf, iLen);
		}
#endif
		break;

	case REG_CFM_NONSTANDARD:
		if (Sys_iNatTraversal == H323_NAT_TRAVERSAL_CITRON)
		{
			CitronHandleRegCfm(pBuf, iLen);
		}

		if (Sys_iServiceType == H323_SERVICE_TYPE_ETALK)
		{
			eTalkHandleRegCfm(pBuf);
		}
		else if (Sys_iServiceType == H323_SERVICE_TYPE_IPN)
		{
			IpnHandleRegCfm(pBuf);
		}
#ifdef SYS_TXTC
		else if (Sys_iServiceType == H323_SERVICE_TYPE_TXTC)
		{
			TxtcHandleRegCfm(pBuf);
		}
#endif
#ifdef SYS_YIYANG
		else if (Sys_iServiceType == H323_SERVICE_TYPE_YIYANG)
		{
			YiyangDecodeNonStandard(iType, pBuf, iLen);
		}
#endif
		break;

#ifdef SYS_TXTC
	case LOC_REQ_NONSTANDARD:
		if (Sys_iServiceType == H323_SERVICE_TYPE_TXTC)
		{
			if (IsFunctionMode())
			{
				TxtcHandleLocationReq(pBuf);
			}
		}
		break;
#endif

#ifdef SYS_AUVTECH
	case NONSTANDARD_NONSTANDARD:
		if (Sys_iServiceType == H323_SERVICE_TYPE_AUVTECH || Sys_iServiceType == H323_SERVICE_TYPE_SOYO)
		{
			if (IsFunctionMode())
			{
				AuvtechHandleNonstanard(pBuf);
			}
		}
		break;
#endif

	case REG_REJ_NONSTANDARD:
		break;

	case ADM_REJ_NONSTANDARD:
		break;

	case DEG_CFM_NONSTANDARD:
		if (Sys_iServiceType == H323_SERVICE_TYPE_IFONE)
		{ // I-FONE system use DCF to indicate the balance.
			if (pBuf[0] == 0x08)
			{
				SdramSaveData(OPTIONS_SDRAM_POS+BALANCE_SDRAM_LO, (PXCHAR)(pBuf+1), p_strlen_x(pBuf+1));
			}
		}
		break;
#endif
	}

	if (iType <= NONSTANDARD_NONSTANDARD)
	{
		pBuf[iLen] = iBackup;
	}

	return TRUE;
#endif // CALL_MGCP
}

BOOLEAN	TaskRunTcp()
{
	if (IsFunctionMode())
	{
		if (Udp_iOutputDebug)
		{
			if (UpgradeRun())		return TRUE;
		}
	}

	if (TelnetRun())		return TRUE;

#ifdef OEM_SKYCOM
	if(MoneyTcpRun())  return TRUE;
#endif

#ifdef SYS_YIYANG
	if (Sys_iServiceType == H323_SERVICE_TYPE_YIYANG)
	{
		if (YiyangTcpRun())	return TRUE;
	}
#endif

	if (HttpRun())		return TRUE;

#ifdef CALL_H323
	if (H323RunTcp())		return TRUE;
#elif defined CALL_SIP
//	if (SipRunTcp())		return TRUE;
#elif defined CALL_N2P
	if (N2pRunTcp())		return TRUE;
#elif defined CALL_WP
	if (WpRunTcp())		return TRUE;
#elif defined CALL_EPN
	if (EpnRunTcp())		return TRUE;
#endif

	return FALSE;
}

BOOLEAN TaskRunUdp()
{
#ifdef CALL_H323
	if (Adapter_iReceiveUdpPort == Sys_iRtpPort)
    {
		RtpRun();		// Handle rtp audio streams here
#ifdef VER_IPH_E00
		if (!Rtp_bRcv && Rtp_bOpened)
		{
			if (p_memcmp_ip(Adapter_pReceiveIPAddress, Sys_pRemoteIP) && Task_bConnected)
			{
				OutputIPPort(Adapter_pReceiveIPAddress, PXCHAR2USHORT((PXCHAR)Adapter_pReceivePacket), IDS_RTP_PORT);
				p_memcpy_ip(Sys_pRemoteIP, Adapter_pReceiveIPAddress);
				Rtp_iDstPort = PXCHAR2USHORT((PXCHAR)Adapter_pReceivePacket);
				Rtp_bOpened = FALSE;
				TaskStartRtp();
			}
			Rtp_bRcv = TRUE;
		}
#endif
		return TRUE;
    }
    if (Adapter_iReceiveUdpPort == Sys_iRtpPort+1)
    {
		RtcpRun();
		return TRUE;
    }

	if (H323RunUdp())		return TRUE;

#ifdef SYS_ASIAINFO
	if (AsiainfoRunUdp())	return TRUE;
#endif

#elif defined CALL_SIP
	if (Sys_iNatTraversal == SIP_NAT_TRAVERSAL_STUN)
	{
		if (StunRun())	return TRUE;
	}
	if (Adapter_iReceiveUdpPort == Sys_iRtpPort)
    {
		if (Rtp_iDstPort == PXCHAR2USHORT((PXCHAR)Adapter_pReceivePacket) && !p_memcmp_ip(Adapter_pReceiveIPAddress, Sys_pRemoteIP))
		{
			RtpRun();		// Handle rtp audio streams here
		}
		return TRUE;
    }
    if (Adapter_iReceiveUdpPort == Sys_iRtpPort+1)
    {
		RtcpRun();
		return TRUE;
    }
	if (SipRunUdp())		return TRUE;
#elif defined CALL_MGCP
	if (Adapter_iReceiveUdpPort == Sys_iRtpPort)
    {
		RtpRun();		// Handle rtp audio streams here
		return TRUE;
    }
    if (Adapter_iReceiveUdpPort == Sys_iRtpPort+1)
    {
		RtcpRun();
		return TRUE;
    }
	if (MgcpRunUdp())		return TRUE;
#elif defined CALL_N2P
	if (N2pRunUdp())		return TRUE;
#elif defined CALL_WP
	if (WpRunUdp())		return TRUE;
#elif defined CALL_EPN
	if (Adapter_iReceiveUdpPort == Sys_iRtpPort)
    {
		RtpRun();		// Handle rtp audio streams here
		return TRUE;
    }
    if (Adapter_iReceiveUdpPort == Sys_iRtpPort+1)
    {
		RtcpRun();
		return TRUE;
    }
#elif defined CALL_IAX2
	if (Iax2RunUdp())		return TRUE;
#endif

	if (IsFunctionMode())
	{
		if (Adapter_iReceiveUdpPort == SNTP_SRC_PORT)
		{
			SntpRun();
			return TRUE;
		}
	}

	if (Adapter_iReceiveUdpPort == UDP_DEBUG_SRC_PORT)
	{
		ReportRun();
		return TRUE;
	}

	// Unknown udp data, ignore
	return FALSE;
}

void TaskIncomingData(UCHAR iLength, PXCHAR pData)
{
	if (IsFunctionMode())	return;

#ifdef CALL_MGCP
	if (Task_bCaller)
	{
		if (Ac97_iDtmfCode < DTMF_SIGNAL_DIAL)
		{
			return;
		}
		if (IsInCall())
		{
			DtmfStopAll();
		}
	}
#else
	if (Task_bConnecting)
	{
		if (Task_bCaller)
		{
			Task_iTimer = RING_BACK_TTL + 1;	// avoid to start dtmf ringback
			DtmfStopRing();		// stop existing locally generated dtmf ringback tone
		}
		else
		{
			return;
		}
	}
	else if (Task_bDisconnecting)
	{
		return;
	}
#endif

	if (Task_bInbandDtmf)	return;

	if (Task_bCallHold)	return;
	if (Task_bCallTransfer)	return;
	if (!IsCallMode()) return;

	DspHandleDecodeData(iLength, pData);
}

void TaskIncomingKeys(UCHAR iLen, PXCHAR pKeyBuf)
{
	if (!Task_bConnected)	return;
	if (Task_bInbandDtmf)	return;
	if (Task_bCallHold)	return;

	if (iLen)
	{
		DtmfPlayKey(pKeyBuf[0]);
	}
}

void TaskWaitPacket()
{
	SysSleep(p_rand()&1023);
}
