#include "p_apps.h"
#include "PalmChip.h"
#include "v_task.h"
#include "p_tcpip.h"
#include "ac97.h"

#ifdef _USE_FAKE_FXO

BOOLEAN Line_b1S1OStatus = FALSE;

static volatile BOOLEAN _bRingInDetected = FALSE;
static volatile BOOLEAN _bOffHookDetected = FALSE;
static XCHAR _iRinginTimer;

void DualModeStartup()
{
	XBYTE[IO_HI_INTEN] |= RINGIN_OR_MASK;
	XBYTE[IO_HI_EDGE] |= RINGIN_OR_MASK;
	XBYTE[IO_HI_INVERT] |= RINGIN_OR_MASK;

	if (Sys_iDualMode == DUAL_MODE_PSTN_FIRST)
	{
		SwitchToFXO(TRUE);
	}
	else
	{
		SwitchToFXO(FALSE);
	}
}

void DualModeHandleTimer()
{
	if (_iRinginTimer)
	{
		_iRinginTimer --;
	}
	else
	{
	   	XBYTE[IO_HI_INTEN] |= OFFHOOK_OR_MASK;
	}
}

void CheckDualModePrefix()
{
	if (Sys_iDualMode == DUAL_MODE_IP_FIRST)
	{
		if (!p_strcmp_x2x(Key_pBuf, Sys_pDualModePrefix))
		{
			KeypadClear();
			SwitchToFXO(TRUE);
		}
	}
}

void CheckDualModeStatus()
{
	if (Sys_iDualMode == DUAL_MODE_IP_FIRST)
	{
		if (!Line_b1S1OStatus)
		{
			SwitchToFXO(FALSE);
		}
	}
	else if (Sys_iDualMode == DUAL_MODE_PSTN_FIRST)
	{
		if (Line_b1S1OStatus)
		{
			SwitchToFXO(TRUE);
			}
	}
}

BOOLEAN _GetOffHookStatus()
{
	BOOLEAN bUp;
       
	XBYTE[IO_HI_ENABLE] &= OFFHOOK_AND_MASK;
	if ((XBYTE[IO_HI_DIN] & OFFHOOK_OR_MASK))
	{
		bUp = FALSE;
		XBYTE[IO_HI_INVERT] |= OFFHOOK_OR_MASK;	// Set irq to negative edge
	}
	else
	{
		bUp = TRUE;
		XBYTE[IO_HI_INVERT] &= OFFHOOK_AND_MASK;	// Set irq to positive edge
	}
	return bUp;
}

void SwitchToFXO(BOOLEAN bFXO)		
{
	if (bFXO)		// Switch to FXO port
	{
#ifdef VER_PA168P
		Cam_LedOff(1);
#else
		Cam_LedOn(1);
#endif
		DebugCString((PCCHAR)"switch to pstn");
		Line_b1S1OStatus = FALSE;
		XBYTE[IO_HI_INTEN] |= OFFHOOK_OR_MASK;
#if defined OEM_HUAWEI3COM
		Led_On(PSTN_LIGHT);
		Led_Off(IP_LIGHT);
#endif
	}
	else			// Switch to FXS port
	{
#ifdef VER_PA168P
		Cam_LedOn(1);
#else
		Cam_LedOff(1);
#endif

		DebugCString((PCCHAR)"switch to ip");
		Line_b1S1OStatus = TRUE;
		XBYTE[IO_HI_INTEN] &= OFFHOOK_AND_MASK;
#if defined OEM_HUAWEI3COM
		Led_On(IP_LIGHT);
		Led_Off(PSTN_LIGHT);
#endif
	}
}

void _RingInRun()
{
//	_ClearAllInt();
	XBYTE[IO_LO_INTCLR] = 0xff;	// Clear all io edge irq
	XBYTE[IO_HI_INTCLR] = 0xff;	// Clear all io edge irq
	XBYTE[IO_HHI_INTCLR] = 0xff;	// Clear all io edge irq

//	SwitchToFXO(TRUE);
	DebugCString((PCCHAR)"Ringin interrupt");
	if (IsFunctionMode())
	{
		SwitchToFXO(TRUE);
	}
	_iRinginTimer = 4;
	PIO_bHandsetUp = TRUE;
	PIO_iHookFlashTimer = 0;
    XBYTE[IO_HI_INTEN] &= OFFHOOK_AND_MASK;			// enable irq
	_bRingInDetected = FALSE;
    XBYTE[IO_HI_INTEN] |= RINGIN_OR_MASK;			// enable ringin irq
}

void _OffHookRun()
{
	BOOLEAN bUp;

//	_HandleKeyJitters();
	SysSleep(20000);	// wait for 20ms
	bUp = _GetOffHookStatus();

//	if (Line_b1S1OStatus || _iRinginTimer) goto End4;
	if (Line_b1S1OStatus) goto End4;

	if (PIO_bHandsetUp == bUp)
	{
		if (!bUp && Sys_iDualMode == DUAL_MODE_IP_FIRST)
		{
			SwitchToFXO(FALSE);
			OnHandset();
		}
	}

	if (PIO_bHandsetUp != bUp)
	{
		OutputVal(bUp, IDS_CHECK_POINT_6);
//		_ClearAllInt();
		XBYTE[IO_LO_INTCLR] = 0xff;	// Clear all io edge irq
		XBYTE[IO_HI_INTCLR] = 0xff;	// Clear all io edge irq
		XBYTE[IO_HHI_INTCLR] = 0xff;	// Clear all io edge irq

		PIO_bHandsetUp = bUp;
		if (bUp)
		{
			if (PIO_iHookFlashTimer < 20 && PIO_iHookFlashTimer > 1)
			{
				// it is hook flash event.
				PIO_iHookFlashTimer = 0;
				PIO_bHandsetUp = FALSE;
				if (Sys_iDualMode == DUAL_MODE_PSTN_FIRST)
				{
					SwitchToFXO(FALSE);
					goto End4;
				}
				else
				{
					OnHookFlash();
				}
			}
#if defined OEM_HUAWEI3COM
			Led_On(PSTN_LIGHT);
#endif
		}
		else
		{
#if defined OEM_HUAWEI3COM
			Led_Off(PSTN_LIGHT);
#endif
			OutputVal(6, IDS_CHECK_POINT_7);
			PIO_iHookFlashTimer = 1;
		}
	}
	DebugCString((PCCHAR)"OffHook interrupt");
    XBYTE[IO_HI_INTEN] |= OFFHOOK_OR_MASK;			// enable irq
End4:
	_bOffHookDetected = FALSE;
}

void DualModeRun()
{
	if (_bRingInDetected)
	{
		_RingInRun();
	}
	if (_bOffHookDetected)
	{
		_OffHookRun();
	}
}

void HandleRingIn()
{
	DCHAR iVal;

	XBYTE[IO_HI_ENABLE] &= RINGIN_AND_MASK;
	iVal = XBYTE[IO_HI_DIN] & RINGIN_OR_MASK;
	if (!iVal)		// When Ringin is low, it means there is a ring coming
	{
		XBYTE[IO_HI_INTCLR] |= RINGIN_OR_MASK;	// Clear io edge irq
		XBYTE[IO_HI_INTEN] &= RINGIN_AND_MASK;		// disable irq until key is processed
		_bRingInDetected = TRUE;
	}
}

void HandleOffHook()
{
	DCHAR iVal;

	XBYTE[IO_HI_ENABLE] &= OFFHOOK_AND_MASK;
	iVal = XBYTE[IO_HI_DIN] & OFFHOOK_OR_MASK;
	if (XBYTE[IO_HI_INVERT] & OFFHOOK_OR_MASK)
	{
		if (!iVal)
		{
			goto End1;
		}
	}
	else
	{
		if (iVal)
		{
			goto End1;
		}
	}
	return;

End1:
	XBYTE[IO_HI_INTCLR] |= OFFHOOK_OR_MASK;	// Clear io edge irq
	XBYTE[IO_HI_INTEN] &= OFFHOOK_AND_MASK;		// disable irq until key is processed
	_bOffHookDetected = TRUE;
}

#endif
