#include "p_apps.h"
#include "PalmChip.h"
#include "p_dsp.h"

#include "v_task.h"

#define _GDI_CONST
#include "gdiconst.h"

#include <reg52.h>

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

XCHAR Ac97_iHandsetOutputVol, Ac97_iHandsetInputVol, Ac97_iHandfreeInputVol, Ac97_iHandfreeOutputVol;
volatile DCHAR Task_iRingType;
XCHAR Task_iRingNumber;
BOOLEAN Task_bSupervisor = FALSE;


PXCHAR _pCommandLine;	// set options command line

#define MIN_PASSWORD_LEN	4
static CCHAR _cMinPassword[] = "1234";
static CCHAR _cUpgradeProtocol[][8] = {"ftp://", "tftp://", "http://"};
static CCHAR _cUpgradeProtocolLen[] = {6, 7, 7};

void _CheckPasswordLength(PXCHAR pPassword)
{
	if (p_strlen_x(pPassword) < MIN_PASSWORD_LEN)
	{
		p_strcpy_c2x(pPassword, _cMinPassword);
	}
}

void _CheckCodec()
{
#if defined CALL_N2P
	p_memset_x(Sys_pCodecType, CODEC_NULL, SYS_CODEC_NUM);
	Sys_pCodecType[0] = CODEC_G7231;
#elif defined CALL_WP
	p_memset_x(Sys_pCodecType, CODEC_NULL, SYS_CODEC_NUM);
	if (X_VAL(Sdram_pDataCache, OPTIONS_CODEC_TYPE) == CODEC_G7231)
	{
		Sys_pCodecType[0] = CODEC_G7231;
	}
	else
	{
		Sys_pCodecType[0] = CODEC_G729;
	}
#else
	DCHAR i, j, iNum, iType;
	BOOLEAN bDuplicate;

	p_memset_x(Sys_pCodecType, CODEC_NULL, SYS_CODEC_NUM);
	for (i = 0, iNum = 0; i < SYS_CODEC_NUM; i ++)
	{
		iType = X_VAL(Sdram_pDataCache, OPTIONS_CODEC_TYPE+i);
		if (iType >= CODEC_NULL)	continue;
#ifdef NO_LICENSE
		if (iType == CODEC_G7231 || iType == CODEC_G729)	continue;
#endif
		if (!iNum)
		{
			Sys_pCodecType[iNum] = iType;
			iNum ++;
		}
		else
		{
			bDuplicate = FALSE;
			for (j = 0; j < iNum; j ++)
			{
				if (iType == Sys_pCodecType[j])
				{
					bDuplicate = TRUE;
				}
			}
			if (!bDuplicate)
			{
				Sys_pCodecType[iNum] = iType;
				iNum ++;
			}
		}
	}
	if (!iNum)
	{
		Sys_pCodecType[0] = CODEC_G729;
	}
#endif
}

void SetUpgradeAddr()
{
	PXCHAR_D pCur;

	pCur = p_strchr_x(Sys_pUpgradeUrl, ':');
	Sys_pUpgradeAddr = Sys_pUpgradeUrl;
	if (pCur)
	{
		if (!p_memcmp_c2x(Sys_pUpgradeUrl, _cUpgradeProtocol[UPGRADE_PROTOCOL_FTP], _cUpgradeProtocolLen[UPGRADE_PROTOCOL_FTP]))
		{
			Sys_iUpgradeProtocol = UPGRADE_PROTOCOL_FTP;
			Sys_pUpgradeAddr += _cUpgradeProtocolLen[UPGRADE_PROTOCOL_FTP];
		}
		else if (!p_memcmp_c2x(Sys_pUpgradeUrl, _cUpgradeProtocol[UPGRADE_PROTOCOL_TFTP], _cUpgradeProtocolLen[UPGRADE_PROTOCOL_TFTP]))
		{
			Sys_iUpgradeProtocol = UPGRADE_PROTOCOL_TFTP;
			Sys_pUpgradeAddr += _cUpgradeProtocolLen[UPGRADE_PROTOCOL_TFTP];
		}
		else if (!p_memcmp_c2x(Sys_pUpgradeUrl, _cUpgradeProtocol[UPGRADE_PROTOCOL_HTTP], _cUpgradeProtocolLen[UPGRADE_PROTOCOL_HTTP]))
		{
			Sys_iUpgradeProtocol = UPGRADE_PROTOCOL_HTTP;
			Sys_pUpgradeAddr += _cUpgradeProtocolLen[UPGRADE_PROTOCOL_HTTP];
		}
		else
		{
			Sys_iUpgradeProtocol = UPGRADE_PROTOCOL_UNKNOWN;
		}
	}
	else
	{
		if (p_strlen_x(Sys_pUpgradeUrl))
		{
			Sys_iUpgradeProtocol = UPGRADE_PROTOCOL_FTP;
		}
		else
		{
			Sys_iUpgradeProtocol = UPGRADE_PROTOCOL_UNKNOWN;
		}
	}
}

//
// load and save options
//
void SysReadOptions()
{
	SdramReadOptions();

	p_memcpy_mac(Local_pMacAddress, (PXCHAR)(Sdram_pDataCache+OPTIONS_MAC_ADDR));
	p_memcpy_ip(Local_pIPAddress, (PXCHAR)(Sdram_pDataCache+OPTIONS_IP_ADDR));
	p_memcpy_ip(Local_pSubnetMask, (PXCHAR)(Sdram_pDataCache+OPTIONS_SUBNET_MASK));
	p_memcpy_ip(Local_pRouteIP, (PXCHAR)(Sdram_pDataCache+OPTIONS_ROUTER_ADDR));
	p_memcpy_ip(Dns_pServerIP, (PXCHAR)(Sdram_pDataCache+OPTIONS_DNS_ADDR));
	p_memcpy_ip(Dns_pServerIP2, (PXCHAR)(Sdram_pDataCache+OPTIONS_DNS_ADDR2));

	Sys_iIPType = X_VAL(Sdram_pDataCache, OPTIONS_IP_TYPE);
	VLAN_bEnable = X_VAL(Sdram_pDataCache, OPTIONS_VLAN_ENABLE) ? TRUE : FALSE;
	VLAN_iID = PXCHAR2USHORT((PXCHAR)(Sdram_pDataCache + OPTIONS_VLAN_ID));

#ifndef HW_MODEM
	if (Sys_iIPType == IP_TYPE_MODEM)
	{
		Sys_iIPType = IP_TYPE_DHCP;
	}
#endif

	p_memcpy_x2x_0(PPP_pID, (PXCHAR)(Sdram_pDataCache+OPTIONS_PPP_ID), PPP_ID_LEN);
	p_memcpy_x2x_0(PPP_pPassword, (PXCHAR)(Sdram_pDataCache+OPTIONS_PPP_PASSWORD), PPP_PASSWORD_LEN);

#if defined CALL_H323 || defined CALL_SIP || defined CALL_MGCP
	Sys_iServiceType = X_VAL(Sdram_pDataCache, OPTIONS_SERVICE_TYPE);
	Sys_iNatTraversal = X_VAL(Sdram_pDataCache, OPTIONS_NAT_TRAVERSAL);
	p_memcpy_x2x_0(Sys_pNatAddr, (PXCHAR)(Sdram_pDataCache+OPTIONS_NAT_DNS), MAX_DNS_ADDR_LEN);
	Sys_iNatTTL = PXCHAR2USHORT((PXCHAR)(Sdram_pDataCache+OPTIONS_NAT_TTL));
#else
	Sys_iServiceType = SERVICE_TYPE_COMMON;
	Sys_iNatTraversal = NAT_TRAVERSAL_DISABLE;
	p_memset_x(Sys_pNatAddr, 0, MAX_DNS_ADDR_LEN);
	Sys_iNatTTL = 0;
#endif
	p_memcpy_x2x_0(Sys_pAccount, (PXCHAR)(Sdram_pDataCache+OPTIONS_ACCOUNT), MAX_ACCOUNT_LEN);
	p_memcpy_x2x_0(Sys_pPin, (PXCHAR)(Sdram_pDataCache+OPTIONS_PIN), MAX_PIN_LEN);

#if defined CALL_H323 || defined CALL_SIP || defined CALL_IAX2
	Sys_bUseService = X_VAL(Sdram_pDataCache, OPTIONS_USE_GK);
#else
	Sys_bUseService = TRUE;
#endif

#if defined CALL_H323 || defined CALL_MGCP
	Sys_iLocalType = X_VAL(Sdram_pDataCache, OPTIONS_LOCAL_ALIAS);
#endif
#if defined CALL_SIP || defined CALL_IAX2 
	Sys_iCallType = X_VAL(Sdram_pDataCache, OPTIONS_CALL_TYPE);
#endif
	Sys_iDtmfType = X_VAL(Sdram_pDataCache, OPTIONS_DTMF_TYPE);
#if defined CALL_SIP || defined CALL_MGCP
	Sys_iDtmfPayloadType = X_VAL(Sdram_pDataCache, OPTIONS_DTMF_PTYPE);
#endif
	Sys_iIlbcPType = X_VAL(Sdram_pDataCache, OPTIONS_ILBC_PTYPE);

	Task_iRingNumber = X_VAL(Sdram_pDataCache, OPTIONS_RING_NUMBER);
	Ac97_iHandsetInputVol = X_VAL(Sdram_pDataCache, OPTIONS_HANDSET_INPUT);
	Ac97_iHandsetOutputVol = X_VAL(Sdram_pDataCache, OPTIONS_HANDSET_OUTPUT);

#ifdef _USE_FXS
	Task_iRingType = RING_TYPE_DTMF;
	Ac97_iHandfreeInputVol = 0;
	Ac97_iHandfreeOutputVol = 0;
#else
	Task_iRingType = X_VAL(Sdram_pDataCache, OPTIONS_RING_TYPE);
	Ac97_iHandfreeInputVol = X_VAL(Sdram_pDataCache, OPTIONS_HANDFREE_INPUT);
	Ac97_iHandfreeOutputVol = X_VAL(Sdram_pDataCache, OPTIONS_HANDFREE_OUTPUT);
#endif

#ifdef _USE_FAKE_FXO
	Sys_iDualMode = X_VAL(Sdram_pDataCache, OPTIONS_DUAL_MODE);
	p_memcpy_x2x_0(Sys_pDualModePrefix, (PXCHAR)(Sdram_pDataCache+OPTIONS_DUALMODE_PREFIX), MAX_DUALMODE_PREFIX_LEN);
#else
	Sys_iDualMode = 0;
	p_memset_x(Sys_pDualModePrefix, 0, MAX_DUALMODE_PREFIX_LEN);
#endif

#if defined CALL_H323 || defined CALL_SIP  || defined CALL_MGCP || defined CALL_IAX2 || defined CALL_N2P
	Sys_iRegisterPort = PXCHAR2USHORT((PXCHAR)(Sdram_pDataCache+OPTIONS_RAS_PORT));
#endif
#ifdef CALL_H323
	Sys_iSignalPort = PXCHAR2USHORT((PXCHAR)(Sdram_pDataCache+OPTIONS_Q931_PORT));
	Sys_iControlPort = PXCHAR2USHORT((PXCHAR)(Sdram_pDataCache+OPTIONS_H245_PORT));
#endif
#ifndef CALL_IAX2
	Sys_iRtpPort = PXCHAR2USHORT((PXCHAR)(Sdram_pDataCache+OPTIONS_RTP_PORT));
#endif
#if defined CALL_H323 || defined CALL_SIP  || defined CALL_MGCP || defined CALL_EPN || defined CALL_IAX2
	Rtp_iTos = X_VAL(Sdram_pDataCache, OPTIONS_RTP_TOS);
#endif
#ifdef CALL_N2P
	p_strcpy_x2x(Sys_pLocalNumber, Sys_pAccount);
#else
	p_memcpy_x2x_0(Sys_pLocalNumber, (PXCHAR)(Sdram_pDataCache+OPTIONS_PHONE_NUMBER), PHONE_NUMBER_LEN);
#endif
#if defined CALL_SIP || defined CALL_N2P
	p_memcpy_x2x_0(Sys_pServiceID, (PXCHAR)(Sdram_pDataCache+OPTIONS_SERVICE_ID), MAX_SERVICE_ID_LEN);
#else
	p_memset_x(Sys_pServiceID, 0, MAX_SERVICE_ID_LEN);
#endif
	p_memcpy_x2x_0(Sys_pServiceAddr, (PXCHAR)(Sdram_pDataCache+OPTIONS_SERVICE_DNS), MAX_DNS_ADDR_LEN);
	Sys_iRegisterTTL = PXCHAR2USHORT((PXCHAR)(Sdram_pDataCache+OPTIONS_REGISTER_TTL));

	Udp_iOutputDebug = X_VAL(Sdram_pDataCache, OPTIONS_OUTPUT_DEBUG);

	_CheckCodec();
	Sys_iAudioFrames = X_VAL(Sdram_pDataCache, OPTIONS_AUDIO_FRAMES);
#if defined CALL_WP
	if (Sys_iAudioFrames < 2)	Sys_iAudioFrames = 2;
#endif

	p_memcpy_x2x_0(Sys_pPassword, (PXCHAR)(Sdram_pDataCache+OPTIONS_PASSWORD), MAX_PASSWORD_LEN);
	_CheckPasswordLength(Sys_pPassword);
	p_memcpy_x2x_0(Sys_pSuperPassword, (PXCHAR)(Sdram_pDataCache+OPTIONS_SUPER_PASSWORD), MAX_SUPERPASSWORD_LEN);
	_CheckPasswordLength(Sys_pSuperPassword);

	p_memcpy_x2x_0(Sys_pCountryCode, (PXCHAR)(Sdram_pDataCache+OPTIONS_COUNTRY_CODE), MAX_COUNTRY_CODE_LEN);
	p_memcpy_x2x_0(Sys_pIntlPrefix, (PXCHAR)(Sdram_pDataCache+OPTIONS_INTL_PREFIX), MAX_INTL_PREFIX_LEN);
	Sys_iUseDialPlan = X_VAL(Sdram_pDataCache, OPTIONS_USE_DIALPLAN);
	p_memcpy_x2x_0(Sys_pAreaCode, (PXCHAR)(Sdram_pDataCache+OPTIONS_AREA_CODE), MAX_AREA_CODE_LEN);
	p_memcpy_x2x_0(Sys_pLongPrefix, (PXCHAR)(Sdram_pDataCache+OPTIONS_LONG_PREFIX), MAX_LONG_PREFIX_LEN);
	Sys_iInnerLine = X_VAL(Sdram_pDataCache, OPTIONS_INNER_LINE);

	p_memcpy_x2x_0(Sys_pInnerLinePrefix, (PXCHAR)(Sdram_pDataCache+OPTIONS_INNERLINE_PREFIX), MAX_INNERLINE_PREFIX_LEN);

	p_memcpy_x2x_0(Sys_pDialNumber, (PXCHAR)(Sdram_pDataCache+OPTIONS_DIAL_NUMBER), DIAL_NUMBER_LEN);

	Sys_iForwardType = X_VAL(Sdram_pDataCache, OPTIONS_FWD_TYPE);
	p_memcpy_x2x_0(Sys_pForwardNumber, (PXCHAR)(Sdram_pDataCache+OPTIONS_FWD_NUMBER), FORWARD_NUMBER_LEN);

	Dsp_iOptions = X_VAL(Sdram_pDataCache, OPTIONS_DSP_OPTION);

	Sys_iUpgradeType = X_VAL(Sdram_pDataCache, OPTIONS_UPGRADE_TYPE);
	p_memcpy_x2x_0(Sys_pUpgradeUrl, (PXCHAR)(Sdram_pDataCache+OPTIONS_UPGRADE_DNS), MAX_DNS_ADDR_LEN);
	SetUpgradeAddr();

	p_memcpy_x2x(Sys_pProgramButtons, (PXCHAR)(Sdram_pDataCache+OPTIONS_PROGRAM_BUTTONS), PROGRAM_BUTTONS_NUM);
	Sys_iHttpsPort = PXCHAR2USHORT((PXCHAR)(Sdram_pDataCache+OPTIONS_HTTPS_PORT));
	Sys_iNetRetry = X_VAL(Sdram_pDataCache, OPTIONS_NETWORK_RETRY);
	Sys_iJitterSize = X_VAL(Sdram_pDataCache, OPTIONS_JITTER_SIZE);

	Sys_iTimeZone = X_VAL(Sdram_pDataCache, OPTIONS_TIME_ZONE);
	p_memcpy_ip(Sys_pNtsIP, (PXCHAR)(Sdram_pDataCache+OPTIONS_NTS_ADDR));
	Sys_lCurrentTime = PXCHAR2ULONG((PXCHAR)(Sdram_pDataCache+OPTIONS_REALTIME));
	p_srand((USHORT)(Sys_lCurrentTime+p_randseed_from_mac()));

#ifdef CALL_MGCP
	Sys_bUseDigitMap = TRUE;
#else
#ifdef CALL_IAX2
	if (Sys_iCallType & REMOTE_DIALPLAN_OR)
	{
		Sys_bUseDigitMap = FALSE;
	}
	else
#endif
	{
		if (!Sys_bUseService && !p_strlen_x(Sys_pServiceAddr))
		{
			Sys_bUseDigitMap = FALSE; // do not use digit map on direct ip calls
		}
		else
		{
			if (Sys_iDigitMapNum)
			{
				Sys_bUseDigitMap = X_VAL(Sdram_pDataCache, OPTIONS_USE_DIGITMAP);
			}
			else
			{
				Sys_bUseDigitMap = FALSE;
			}
		}
	}
#endif

#ifdef CALL_H323
#ifdef OEM_POLYLINK
	Sys_iServiceType = H323_SERVICE_TYPE_AUVTECH;
#endif
	if (Sys_iServiceType == H323_SERVICE_TYPE_AUVTECH || Sys_iServiceType == H323_SERVICE_TYPE_TXTC 
		|| Sys_iServiceType == H323_SERVICE_TYPE_YIYANG || Sys_iServiceType == H323_SERVICE_TYPE_SOYO)  
	{
		Sys_iNatTraversal = NAT_TRAVERSAL_DISABLE;
	}
#endif

#ifdef CALL_H323 
#ifdef OEM_IPN
	Sys_iServiceType = H323_SERVICE_TYPE_IPN;
	Sys_iNatTraversal = H323_NAT_TRAVERSAL_CITRON;
	p_strcpy_c2x(Sys_pUpgradeUrl, (PCCHAR)"ftp://www.19909.net");
	Sys_pUpgradeAddr = Sys_pUpgradeUrl + _cUpgradeProtocolLen[UPGRADE_PROTOCOL_FTP];
	Sys_iUpgradeProtocol = UPGRADE_PROTOCOL_FTP;
#endif
#endif

#ifdef CALL_SIP
#ifdef OEM_MEDIARING
	Sys_iServiceType = SIP_SERVICE_TYPE_MEDIARING;
#elif defined OEM_RINGCHAT
	Sys_iServiceType = SIP_SERVICE_TYPE_RINGCHAT;
#endif
#endif

	Sys_iAudioType = Sys_pCodecType[0];
	Sys_iNatPort = HTTP_SERVER_PORT;
#ifdef CALL_H323
	if (Sys_iNatTraversal == H323_NAT_TRAVERSAL_AIVGR)
	{
		Sys_iNatPort = AIVGR_DST_PORT;
	}

	if (Sys_bUseService)
	{
		Sys_iServicePort = GK_RAS_PORT;
	}
	else
	{
		Sys_iServicePort = H2250_LISTEN_PORT;
	}
#elif defined CALL_SIP
	Sys_iServicePort = SIP_SERVER_PORT;
	if (Sys_iNatTraversal > SIP_NAT_TRAVERSAL_STUN)
	{
		Sys_iNatTraversal = NAT_TRAVERSAL_DISABLE;
	}
	if (Sys_iNatTraversal == SIP_NAT_TRAVERSAL_STUN)
	{
		Sys_iNatPort = STUN_SERVER_PORT;
	}
#elif defined CALL_MGCP
	if (Sys_iNatTraversal > NAT_TRAVERSAL_ENABLE)
	{
		Sys_iNatTraversal = NAT_TRAVERSAL_DISABLE;
	}
	Sys_iServicePort = MGCP_SERVER_PORT;
#elif defined CALL_N2P
	Sys_iServicePort = N2P_SERVER_PORT;
#elif defined CALL_WP
	Sys_iServicePort = WP_SERVER_PORT;
#elif defined CALL_IAX2
	Sys_iServicePort = IAX2_SERVER_PORT;
#elif defined CALL_EPN
	Sys_iServicePort = EPN_SERVER_PORT;
#endif

}

void WriteTcpipOptions()
{
	p_memcpy_mac((PXCHAR)(Sdram_pDataCache + OPTIONS_MAC_ADDR), Local_pMacAddress);
	p_memcpy_ip((PXCHAR)(Sdram_pDataCache + OPTIONS_IP_ADDR), Local_pIPAddress);
	p_memcpy_ip((PXCHAR)(Sdram_pDataCache + OPTIONS_SUBNET_MASK), Local_pSubnetMask);
	p_memcpy_ip((PXCHAR)(Sdram_pDataCache + OPTIONS_ROUTER_ADDR), Local_pRouteIP);
	p_memcpy_ip((PXCHAR)(Sdram_pDataCache + OPTIONS_DNS_ADDR), Dns_pServerIP);
	p_memcpy_ip((PXCHAR)(Sdram_pDataCache + OPTIONS_DNS_ADDR2), Dns_pServerIP2);

	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_PPP_ID), PPP_pID, PPP_ID_LEN);
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_PPP_PASSWORD), PPP_pPassword, PPP_PASSWORD_LEN);

#ifdef VER_IPH_E00
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache + OPTIONS_FWD_NUMBER), Sys_pForwardNumber, FORWARD_NUMBER_LEN);
#endif

	X_VAL(Sdram_pDataCache, OPTIONS_IP_TYPE) = Sys_iIPType;
	X_VAL(Sdram_pDataCache, OPTIONS_VLAN_ENABLE) = VLAN_bEnable ? 1 : 0;
	USHORT2PXCHAR(VLAN_iID, (PXCHAR)(Sdram_pDataCache + OPTIONS_VLAN_ID));
}

void SysWriteOptions()
{
	SdramReadOptions();
	WriteTcpipOptions();

	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_PASSWORD), Sys_pPassword, MAX_PASSWORD_LEN);
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_SUPER_PASSWORD), Sys_pSuperPassword, MAX_SUPERPASSWORD_LEN);

	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_CODEC_TYPE), Sys_pCodecType, SYS_CODEC_NUM);

#if defined CALL_H323 || defined CALL_SIP || defined CALL_IAX2
	X_VAL(Sdram_pDataCache, OPTIONS_USE_GK) = Sys_bUseService;
#endif
#if defined CALL_H323 || defined CALL_MGCP
	X_VAL(Sdram_pDataCache, OPTIONS_LOCAL_ALIAS) = Sys_iLocalType;
#endif
#if defined CALL_SIP || defined CALL_IAX2 
	X_VAL(Sdram_pDataCache, OPTIONS_CALL_TYPE) = Sys_iCallType;
#endif
	X_VAL(Sdram_pDataCache, OPTIONS_DTMF_TYPE) = Sys_iDtmfType;
#if defined CALL_SIP || defined CALL_MGCP
	X_VAL(Sdram_pDataCache, OPTIONS_DTMF_PTYPE) = Sys_iDtmfPayloadType;
#endif
	X_VAL(Sdram_pDataCache, OPTIONS_ILBC_PTYPE) = Sys_iIlbcPType;
#if defined CALL_H323 || defined CALL_SIP || defined CALL_MGCP
	X_VAL(Sdram_pDataCache, OPTIONS_NAT_TRAVERSAL) = Sys_iNatTraversal;
	X_VAL(Sdram_pDataCache, OPTIONS_SERVICE_TYPE) = Sys_iServiceType;
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_NAT_DNS), Sys_pNatAddr, MAX_DNS_ADDR_LEN);
	USHORT2PXCHAR(Sys_iNatTTL, (PXCHAR)(Sdram_pDataCache+OPTIONS_NAT_TTL));
#endif
#if defined CALL_H323 || defined CALL_SIP  || defined CALL_MGCP || defined CALL_IAX2 || defined CALL_N2P
	USHORT2PXCHAR(Sys_iRegisterPort, (PXCHAR)(Sdram_pDataCache+OPTIONS_RAS_PORT));
#endif
#ifdef CALL_H323
	USHORT2PXCHAR(Sys_iSignalPort, (PXCHAR)(Sdram_pDataCache+OPTIONS_Q931_PORT));
	USHORT2PXCHAR(Sys_iControlPort, (PXCHAR)(Sdram_pDataCache+OPTIONS_H245_PORT));
#endif
#if defined CALL_H323 || defined CALL_SIP  || defined CALL_MGCP || defined CALL_EPN || defined CALL_IAX2
	X_VAL(Sdram_pDataCache, OPTIONS_RTP_TOS) = Rtp_iTos;
#endif
#ifndef CALL_N2P
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache + OPTIONS_PHONE_NUMBER), Sys_pLocalNumber, PHONE_NUMBER_LEN);
#endif
#ifndef CALL_IAX2
	USHORT2PXCHAR(Sys_iRtpPort, (PXCHAR)(Sdram_pDataCache+OPTIONS_RTP_PORT));
#endif
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_ACCOUNT), Sys_pAccount, MAX_ACCOUNT_LEN);
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_PIN), Sys_pPin, MAX_PIN_LEN);
#if defined CALL_SIP || defined CALL_N2P
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_SERVICE_ID), Sys_pServiceID, MAX_SERVICE_ID_LEN);
#endif
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_SERVICE_DNS), Sys_pServiceAddr, MAX_DNS_ADDR_LEN);
	USHORT2PXCHAR(Sys_iRegisterTTL, (PXCHAR)(Sdram_pDataCache+OPTIONS_REGISTER_TTL));

	X_VAL(Sdram_pDataCache, OPTIONS_FWD_TYPE) = Sys_iForwardType;
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache + OPTIONS_FWD_NUMBER), Sys_pForwardNumber, FORWARD_NUMBER_LEN);

	X_VAL(Sdram_pDataCache, OPTIONS_RING_NUMBER) = Task_iRingNumber;
	X_VAL(Sdram_pDataCache, OPTIONS_RING_TYPE) = Task_iRingType;

	X_VAL(Sdram_pDataCache, OPTIONS_DSP_OPTION) = Dsp_iOptions;
	X_VAL(Sdram_pDataCache, OPTIONS_HANDFREE_OUTPUT) = Ac97_iHandfreeOutputVol;
	X_VAL(Sdram_pDataCache, OPTIONS_HANDSET_INPUT) = Ac97_iHandsetInputVol;
	X_VAL(Sdram_pDataCache, OPTIONS_HANDFREE_INPUT) = Ac97_iHandfreeInputVol;
	X_VAL(Sdram_pDataCache, OPTIONS_HANDSET_OUTPUT) = Ac97_iHandsetOutputVol;
	X_VAL(Sdram_pDataCache, OPTIONS_OUTPUT_DEBUG) = Udp_iOutputDebug;
	X_VAL(Sdram_pDataCache, OPTIONS_AUDIO_FRAMES) = Sys_iAudioFrames;

	X_VAL(Sdram_pDataCache, OPTIONS_USE_DIALPLAN) = Sys_iUseDialPlan;

	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_COUNTRY_CODE), Sys_pCountryCode, MAX_COUNTRY_CODE_LEN);
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_INTL_PREFIX), Sys_pIntlPrefix, MAX_INTL_PREFIX_LEN);
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_AREA_CODE), Sys_pAreaCode, MAX_AREA_CODE_LEN);
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_LONG_PREFIX), Sys_pLongPrefix, MAX_LONG_PREFIX_LEN);
	X_VAL(Sdram_pDataCache, OPTIONS_INNER_LINE) = Sys_iInnerLine;
	X_VAL(Sdram_pDataCache, OPTIONS_DUAL_MODE) = Sys_iDualMode;

	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_DUALMODE_PREFIX), Sys_pDualModePrefix, MAX_DUALMODE_PREFIX_LEN);
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_INNERLINE_PREFIX), Sys_pInnerLinePrefix, MAX_INNERLINE_PREFIX_LEN);

	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_DIAL_NUMBER), Sys_pDialNumber, DIAL_NUMBER_LEN);

	X_VAL(Sdram_pDataCache, OPTIONS_UPGRADE_TYPE) = Sys_iUpgradeType;
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_UPGRADE_DNS), Sys_pUpgradeUrl, MAX_DNS_ADDR_LEN);
	p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+OPTIONS_PROGRAM_BUTTONS), Sys_pProgramButtons, PROGRAM_BUTTONS_NUM);
	X_VAL(Sdram_pDataCache, OPTIONS_PHONE_ATTR) = Sys_iPhoneAttr;
	USHORT2PXCHAR(Sys_iHttpsPort, (PXCHAR)(Sdram_pDataCache+OPTIONS_HTTPS_PORT));
	X_VAL(Sdram_pDataCache, OPTIONS_NETWORK_RETRY) = Sys_iNetRetry;
	X_VAL(Sdram_pDataCache, OPTIONS_JITTER_SIZE) = Sys_iJitterSize;

	X_VAL(Sdram_pDataCache, OPTIONS_TIME_ZONE) = Sys_iTimeZone;
	p_memcpy_ip((PXCHAR)(Sdram_pDataCache+OPTIONS_NTS_ADDR), Sys_pNtsIP);
	ULONG2PUCHAR(Sys_lCurrentTime, (PXCHAR)(Sdram_pDataCache+OPTIONS_REALTIME));

	X_VAL(Sdram_pDataCache, OPTIONS_USE_DIGITMAP) = Sys_bUseDigitMap;	

	SdramWriteOptions();
}

UCHAR _GetAlternateSettingsSdramLo(UCHAR iIndex)
{
	DCHAR iSdramLo;

	iSdramLo = iIndex;
	if (!iSdramLo || iSdramLo > ALTERNATE_SETTING_NUM)
	{
		iSdramLo = ORIG_SETTING_SDRAM_LO;
	}
	else
	{
		iSdramLo --;
		iSdramLo <<= 1;
		iSdramLo += ALTERNATE_SETTING_LO;
	}
	return iSdramLo;
}

void SysLoadOptions(UCHAR iOptions)
{
	DCHAR iIndex;

	iIndex = iOptions;

	SdramReadAll((USHORT)(OPTIONS_SDRAM_POS+_GetAlternateSettingsSdramLo(iIndex)));
#ifndef VER_IPH_E00
	if (iIndex)
	{
		WriteTcpipOptions();
	}
#endif
	SdramWriteAll(OPTIONS_SDRAM_POS+OPTIONS_SDRAM_LO);
	SysReadOptions();	
}

void SysStoreOptions(UCHAR iOptions)
{
	DCHAR iIndex;

	iIndex = iOptions;

	SysWriteOptions();	
	SdramReadAll(OPTIONS_SDRAM_POS+OPTIONS_SDRAM_LO);
	SdramWriteAll((USHORT)(OPTIONS_SDRAM_POS+_GetAlternateSettingsSdramLo(iIndex)));

	if (iIndex)
	{
#ifndef VER_IPH_E00
		SysLoadOptions(0);	// reload orginal settings after store an alternate setting
#endif
	}
}

BOOLEAN IsPassword(PXCHAR pSrc)
{
	SdramReadOptions();
	if (!p_strlen_x(Sys_pSuperPassword))
	{
		p_strcpy_c2x((PXCHAR)(Sdram_pDataCache+OPTIONS_SUPER_PASSWORD), (PCCHAR)"12345678");
	}
	if (!p_strcmp_x2x(Sys_pSuperPassword, pSrc))
	{
		Task_bSupervisor = TRUE;
		return TRUE;
	}
	if (p_strcmp_x2x(Sys_pPassword, pSrc))
	{
		return FALSE;
	}

#ifdef VER_IPH_E00
	Task_bSupervisor = FALSE;
#else
	Task_bSupervisor = (Udp_iOutputDebug ? TRUE : FALSE);
#endif
	return TRUE;
}

//
// update options and restart
//

#ifdef GUI_UPGRADE_RING
void OnUpdateRingFile(ULONG lFileLength)
{
	DSHORT iLength;

	if (lFileLength > MAX_PCMRING_SIZE)
	{
		iLength = MAX_PCMRING_SIZE;
	}
	else
	{
		iLength = (USHORT)lFileLength;
	}
	SdramReadFlags();
	USHORT2PXCHAR(iLength, (PXCHAR)(Sdram_pDataCache+FLAGS_RING_SIZE));
	SdramWriteFlags();
	OnSwitchUpgrade(RING_UPGRADE_PAGE);
}
#endif

void OnUpdateOptions()
{
	OnSwitchUpgrade(OPTIONS_UPGRADE_PAGE);
}

void OnSwitchUpgrade(UCHAR iUpgradePage)
{
	DCHAR iPage;

	iPage = iUpgradePage;
	if (!CheckFileVersion(iPage))	return;

	SdramReadFlags();
	X_VAL(Sdram_pDataCache, FLAGS_UPGRADE_MODE) = TCPIP_UPGRADE_MODE;
	X_VAL(Sdram_pDataCache, FLAGS_UPGRADE_PAGE) = iPage;
	SdramWriteFlags();

	OnLogoff();
	DisplayString(g_cUpdating, 0);
	DisplayString(g_cPercentStart, 1);

#ifdef MT28F016
	XBYTE[IO_HI_ENABLE] |= 0x20;
//	XBYTE[IO_HI_DOUT] |= 0x20;	// PIO13 = 1
#ifdef VER_WG3051
	XBYTE[IO_HI_DOUT] |= 0x20; // PIO13 = 1
#else
	XBYTE[IO_HI_DOUT] &= 0xdf;	// PIO13 = 0
#endif
#endif
	RunUpgrade();
}

void OnReboot()
{
	OnLogoff();

	EA = 0;		// disable all interrupts
	SwitchPage(0);
}

