// PalmToolDlg.cpp : implementation file
//

#include "stdafx.h"
#include "PalmTool.h"
#include "PalmToolDlg.h"
#include "PhoneListDlg.h"
#include "HexFile.h"
#include "MergeBin.h"

#include "Global.h"

#include "Rs232Thread.h"

#include "PhoneSettingsDlg.h"
#include "ConvertFileDlg.h"
#include "HttpDlg.h"
#include "PhoneAddrDlg.h"
#include "..\\inc\\p_util.h"
#include "CovertStr.h"

#ifdef _DEBUG
//#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

static TCHAR szBinFilter[] = _T("Binary files (*.bin)|*.bin|All files (*.*)|*.*||");
static TCHAR szHexFilter[] = _T("MCS51 hex files (*.hex)|*.hex|All files (*.*)|*.*||");
static TCHAR szHFilter[] = _T("C Header files (*.h)|*.h|All files (*.*)|*.*||");
static TCHAR szDatFilter[] = _T("Data files (*.dat)|*.dat|All data files|*.dat;*.pcm;*.raw|All files (*.*)|*.*||");
static TCHAR szPcmFilter[] = _T("PCM files (*.pcm)|*.pcm|All data files|*.dat;*.pcm;*.raw|All files (*.*)|*.*||");
static TCHAR szTxtFilter[] = _T("Text files (*.txt)|*.txt|All Text files|*.txt;|All files (*.*)|*.*||");

#define DEFAULT_BAUDRATE		CBR_19200
#define SDRAM_MAX_LENGTH		640000
#define TCP_UPGRADE_SIZE		128

#define TCP_PROGRAM_SIZE		512

#define EVENT_PROTOCOL_TIMEOUT	3000

#define PALMTOOL_DST_PORT		60006
/////////////////////////////////////////////////////////////////////////////
// CPalmToolDlg dialog

CPalmToolDlg::CPalmToolDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CPalmToolDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CPalmToolDlg)
	m_iRs232Port = -1;
	m_bAudioSaveFile = FALSE;
	m_bAudioRealtime = FALSE;
	m_bAudioNoAcm = FALSE;
	m_bAudioRealtimeOut = FALSE;
	m_iPFlashPage = -1;
	m_iPFlashType = -1;
	m_iSaveSdramLength = 0;
	m_iCommType = -1;
	m_bUseHighRate = FALSE;
	m_bUseVAD = FALSE;
	m_bDebugIPOnly = FALSE;
	m_strPacketNum = _T("");
	m_iOffset = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_pUdpAudioThread = NULL;
	m_pUdpDebugThread = NULL;
	m_pRs232Thread = NULL;
	m_pRj45Thread = NULL;
	m_bRecvPacket = FALSE;
}

void CPalmToolDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPalmToolDlg)
	DDX_Control(pDX, IDC_AUDIO_TYPE, m_ctlAudioType);
	DDX_Control(pDX, IDC_PEER_IP, m_ctlPeerIP);
	DDX_Radio(pDX, IDC_RS232_PORT, m_iRs232Port);
	DDX_Check(pDX, IDC_AUDIO_SAVE_FILE, m_bAudioSaveFile);
	DDX_Check(pDX, IDC_AUDIO_REALTIME, m_bAudioRealtime);
	DDX_Check(pDX, IDC_AUDIO_NO_ACM, m_bAudioNoAcm);
	DDX_Check(pDX, IDC_AUDIO_REALTIME_OUT, m_bAudioRealtimeOut);
	DDX_Radio(pDX, IDC_PFLASH_PAGE, m_iPFlashPage);
	DDX_Radio(pDX, IDC_AM29LV002B, m_iPFlashType);
	DDX_Text(pDX, IDC_SAVE_SDRAM_LENGTH, m_iSaveSdramLength);
	DDV_MinMaxInt(pDX, m_iSaveSdramLength, 0, 640000);
	DDX_Radio(pDX, IDC_COMMUNICATION1, m_iCommType);
	DDX_Check(pDX, IDC_USE_HIGH_RATE, m_bUseHighRate);
	DDX_Check(pDX, IDC_USE_VAD, m_bUseVAD);
	DDX_Check(pDX, IDC_DEBUG_IP_ONLY, m_bDebugIPOnly);
	DDX_Text(pDX, IDC_PACKET_NUM, m_strPacketNum);
	DDX_Text(pDX, IDC_OFFSET, m_iOffset);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CPalmToolDlg, CDialog)
	//{{AFX_MSG_MAP(CPalmToolDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_UDP_AUDIO, OnUdpAudio)
	ON_BN_CLICKED(IDC_LOAD_SDRAM, OnLoadSdram)
	ON_BN_CLICKED(IDC_SAVE_SDRAM, OnSaveSdram)
	ON_BN_CLICKED(IDC_PHONE_SETTINGS, OnPhoneSettings)
	ON_BN_CLICKED(IDC_UPDATE_PFLASH, OnUpdatePflash)
	ON_BN_CLICKED(IDC_START_DEBUG, OnStartDebug)
	ON_CBN_SELCHANGE(IDC_AUDIO_TYPE, OnSelChangeAudioType)
	ON_BN_CLICKED(IDC_AUDIO_NO_ACM, OnAudioNoAcm)
	ON_BN_CLICKED(IDC_COMMUNICATION1, OnCommunication1)
	ON_BN_CLICKED(IDC_COMMUNICATION2, OnCommunication2)
	ON_BN_CLICKED(IDC_TEST_BUTTON, OnTestButton)
	ON_BN_CLICKED(IDC_CONVERT_FILE, OnConvertFile)
	ON_BN_CLICKED(IDC_UPDATE_PROGRAM, OnUpdateProgram)
	ON_BN_CLICKED(IDC_UPDATE_RING, OnUpdateRing)
	ON_BN_CLICKED(IDC_UPDATE_MAP, OnUpdateMap)
	ON_BN_CLICKED(IDC_UPDATE_ALTERNATE, OnUpdateAlternate)
	ON_BN_CLICKED(IDC_GENERATE_HTTPFILE, OnGenerateHttpfile)
	ON_BN_CLICKED(IDC_LIST_PHONES, OnListPhones)
	ON_BN_CLICKED(IDC_SAVE_SETTINGS, OnSaveSettings)
	ON_BN_CLICKED(IDC_LOAD_SETTINGS, OnLoadSettings)
	ON_BN_CLICKED(IDC_SAVE_ADDRESS, OnSaveAddress)
	ON_BN_CLICKED(IDC_LOAD_ADDRESS, OnLoadAddress)
	ON_BN_CLICKED(IDC_SAVE_PACKET, OnSavePacket)
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_UDP_SOCKET_DATA, OnUdpData)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPalmToolDlg message handlers

BOOL CPalmToolDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	m_iPFlashPage = AfxGetApp()->GetProfileInt(_T("PFlash"), _T("Page"), 1);
	m_iPFlashType = AfxGetApp()->GetProfileInt(_T("PFlash"), _T("Type"), 4);

	m_strRs232Port = AfxGetApp()->GetProfileString(_T("Rs232"), _T("Port"), _T("COM1"));
	m_iRs232Port = (m_strRs232Port == _T("COM1")) ? 0 : 1;

	m_iCommType = AfxGetApp()->GetProfileInt(_T("Comm"), _T("Type"), 1);

	m_uPeerIP = AfxGetApp()->GetProfileInt(_T("Peer"), _T("IPAddress"), 0xc0a80101);
	m_ctlPeerIP.SetAddress(m_uPeerIP);

	m_bAudioRealtime = (BOOL)AfxGetApp()->GetProfileInt(_T("UdpAudio"), _T("Realtime"), 1);
	m_bAudioSaveFile = (BOOL)AfxGetApp()->GetProfileInt(_T("UdpAudio"), _T("SaveFile"), 0);
	m_bAudioRealtimeOut = (BOOL)AfxGetApp()->GetProfileInt(_T("UdpAudio"), _T("RealtimeOut"), 1);
	m_bAudioNoAcm = (BOOL)AfxGetApp()->GetProfileInt(_T("UdpAudio"), _T("NoAcm"), 1);
	m_bUseVAD = (BOOL)AfxGetApp()->GetProfileInt(_T("UdpAudio"), _T("UseVAD"), 1);
	m_bUseHighRate = (BOOL)AfxGetApp()->GetProfileInt(_T("UdpAudio"), _T("UseHighRate"), 1);

	m_iSaveSdramLength = AfxGetApp()->GetProfileInt(_T("Sdram"), _T("SaveLength"), 0);

	m_ctlAudioType.AddString("8k pass through");
	m_ctlAudioType.AddString("ITU-T G.711 A Law");
	m_ctlAudioType.AddString("ITU-T G.711 MU Law");
	m_ctlAudioType.AddString("ITU-T G.721 ADPCM");
	m_ctlAudioType.AddString("GSM 6.10");
	m_ctlAudioType.AddString("ITU-T G.729 with Annex A&B");
	m_ctlAudioType.AddString("ITU-T G.723.1");
	m_ctlAudioType.AddString("ILBC 30ms");
	m_iAudioType = AfxGetApp()->GetProfileInt("Audio", "CodecType", 0);
	m_ctlAudioType.SetCurSel(m_iAudioType);

	m_strPacketNum = "0";
	m_iOffset = AfxGetApp()->GetProfileInt(_T("SavePacket"), _T("Offset"), 0);
	UpdateData(FALSE);
	OnSelChangeAudioType();
	OnCommunication1();
	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CPalmToolDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CPalmToolDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

/////////////////////////////////////////////////////////////////////////////
// CPalmToolDlg button handlers

void CPalmToolDlg::SaveSettings()
{
	UpdateData();

	AfxGetApp()->WriteProfileInt(_T("Comm"), _T("Type"), m_iCommType);

	// Update rs232 port
	m_strRs232Port = (m_iRs232Port == 0) ? _T("COM1") : _T("COM2");
	AfxGetApp()->WriteProfileString(_T("Rs232"), _T("Port"), m_strRs232Port);

	AfxGetApp()->WriteProfileInt(_T("UdpAudio"), _T("Realtime"), (int)m_bAudioRealtime);
	AfxGetApp()->WriteProfileInt(_T("UdpAudio"), _T("SaveFile"), (int)m_bAudioSaveFile);
	AfxGetApp()->WriteProfileInt(_T("UdpAudio"), _T("RealtimeOut"), (int)m_bAudioRealtimeOut);
	AfxGetApp()->WriteProfileInt(_T("UdpAudio"), _T("NoAcm"), (int)m_bAudioNoAcm);
	AfxGetApp()->WriteProfileInt(_T("UdpAudio"), _T("UseVAD"), (int)m_bUseVAD);
	AfxGetApp()->WriteProfileInt(_T("UdpAudio"), _T("UseHighRate"), (int)m_bUseHighRate);
	m_ctlPeerIP.GetAddress(m_uPeerIP);
	AfxGetApp()->WriteProfileInt(_T("Peer"), _T("IPAddress"), m_uPeerIP);
	m_iAudioType = m_ctlAudioType.GetCurSel();
	AfxGetApp()->WriteProfileInt("Audio", "CodecType", m_iAudioType);
	AfxGetApp()->WriteProfileInt(_T("PFlash"), _T("Page"), m_iPFlashPage);
	AfxGetApp()->WriteProfileInt(_T("PFlash"), _T("Type"), m_iPFlashType);

	AfxGetApp()->WriteProfileInt(_T("Sdram"), _T("SaveLength"), m_iSaveSdramLength);

	AfxGetApp()->WriteProfileInt(_T("UdpDebug"), _T("IPOnly"), (int)m_bDebugIPOnly);
}

BOOL CPalmToolDlg::BeginRs232()
{
	if (m_pRs232Thread != NULL)	return TRUE;

	m_pRs232Thread = new CRs232Thread;;
	m_pRs232Thread->CreateThread();
	WaitForSingleObject(CRs232Thread::m_hEventThreadCreated, INFINITE);

	if (m_comm.Open(m_pRs232Thread->m_pMainWnd->GetSafeHwnd(), DEFAULT_BAUDRATE, m_strRs232Port) == FALSE)
	{
		AfxMessageBox("Can not open rs232 port");
		delete m_pRs232Thread;
		m_pRs232Thread = NULL;
		return FALSE;
	}
	return TRUE;
}

void CPalmToolDlg::EndRs232()
{
	if (m_pRs232Thread != NULL)
	{
		m_comm.Close();

		::PostThreadMessage(m_pRs232Thread->m_nThreadID, WM_RS232_DISCONNECT, 0, 0);
		WaitForSingleObject(CRs232Thread::m_hEventThreadKilled, INFINITE);
		m_pRs232Thread = NULL;
	}
}

BOOL CPalmToolDlg::BeginRj45(BOOL bNormal)
{
	if (m_pRj45Thread != NULL)	return FALSE;

	AfxGetApp()->WriteProfileInt(_T("Peer"), _T("Port"), bNormal ? TCP_DEFAULT_PORT : (TCP_DEFAULT_PORT+1));

	m_pRj45Thread = new CRj45Thread;
	m_pRj45Thread->CreateThread();
	if (WaitForSingleObject(CRj45Thread::m_hEventProtocol, EVENT_PROTOCOL_TIMEOUT) == WAIT_TIMEOUT)
	{
		AfxMessageBox("Can not connect to Palm1");
		EndRj45();
		return FALSE;
	}
	return TRUE;
}

void CPalmToolDlg::EndRj45()
{
	if (m_pRj45Thread != NULL)
	{
		::PostThreadMessage(m_pRj45Thread->m_nThreadID, WM_RJ45_DISCONNECT, 0, 0);
		WaitForSingleObject(CRj45Thread::m_hEventThreadKilled, INFINITE);
		m_pRj45Thread = NULL;
	}
}

BOOL CPalmToolDlg::BeginUdpAudio()
{
	if (m_pUdpAudioThread == NULL)
	{
		m_pUdpAudioThread = new CUdpAudioThread;;
		m_pUdpAudioThread->CreateThread();
	}
	return TRUE;
}

void CPalmToolDlg::EndUdpAudio()
{
	if (m_pUdpAudioThread != NULL)
	{
		::PostThreadMessage(m_pUdpAudioThread->m_nThreadID, WM_UDP_AUDIO_DISCONNECT, 0, 0);
		WaitForSingleObject(CUdpAudioThread::m_hEventThreadKilled, INFINITE);
		m_pUdpAudioThread = NULL;
	}
}

BOOL CPalmToolDlg::BeginUdpDebug()
{
	if (m_pUdpDebugThread == NULL)
	{
		m_pUdpDebugThread = new CUdpDebugThread;;
		m_pUdpDebugThread->CreateThread();
	}
	return TRUE;
}

void CPalmToolDlg::EndUdpDebug()
{
	if (m_pUdpDebugThread != NULL)
	{
		::PostThreadMessage(m_pUdpDebugThread->m_nThreadID, WM_UDP_DEBUG_DISCONNECT, 0, 0);
		WaitForSingleObject(CUdpDebugThread::m_hEventThreadKilled, INFINITE);
		m_pUdpDebugThread = NULL;
	}
}

BOOL CPalmToolDlg::CheckUpdateFileName(CString strUpdateName)
{
	CString strName, strDefault;

	char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
	_splitpath(strUpdateName, drive, dir, fname, ext);

	strName.Format("%s%s", fname, ext);
	strName.MakeLower();
	strDefault.Format("page%d.hex", m_iPFlashPage);
	if (strName.Find(strDefault) == -1)
	{
		if (m_iPFlashType == 1)	// AM29LV002T
		{
			if (m_iPFlashPage == 2 && strName.Find("page4") != -1)
				return TRUE;
			if (m_iPFlashPage == 3 && strName.Find("page5") != -1)
				return TRUE;
		}

		if (AfxMessageBox("Are you sure about flash page?", MB_ICONQUESTION|MB_YESNO) == IDYES)
		{
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
	return TRUE;
}

BOOL CPalmToolDlg::CheckUpdateOptions()
{
	if (m_iCommType != 1)
	{
		AfxMessageBox("Only Tcpip connection can be used for this function");
		return FALSE;
	}
	return TRUE;
}

void CPalmToolDlg::GetEraseRange(int & iStart, int & iStop)
{
	if (m_iPFlashType == 0)	// AM29LV008B
	{
		if (m_iPFlashPage == 0)
		{
			iStart = 0;
			iStop = 4;
		}
		else
		{
			iStart = m_iPFlashPage + 3;
			iStop = iStart + 1;
		}
	}
	else if (m_iPFlashType == 1)	// AM29LV002T
	{
		if (m_iPFlashPage == 3)
		{
			iStart = 3;
			iStop = 7;
		}
		else
		{
			iStart = m_iPFlashPage;
			iStop = iStart + 1;
		}
	}
	else if (m_iPFlashType == 2 || m_iPFlashType == 5)	// MX29F040 and MT28F016
	{
		iStart = m_iPFlashPage;
		iStop = iStart + 1;
	}
	else if (m_iPFlashType == 3)	// AM29LV004T
	{
		if (m_iPFlashPage == 7)
		{
			iStart = 7;
			iStop = 11;
		}
		else
		{
			iStart = m_iPFlashPage;
			iStop = iStart + 1;
		}
	}
	else if (m_iPFlashType == 4)	// AM29LV008T
	{
		if (m_iPFlashPage == 15)
		{
			iStart = 15;
			iStop = 19;
		}
		else
		{
			iStart = m_iPFlashPage;
			iStop = iStart + 1;
		}
	}
}

void CPalmToolDlg::OnUpdatePflash() 
{
	CString strSrcName = AfxGetApp()->GetProfileString(_T("PFlashUpdate"), _T("SrcName"), _T("demo.hex"));
	CFileDialog dlgOpen(TRUE, _T("*.hex"), strSrcName, OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST, szHexFilter);
	int iLength;
	char * p, * pCur;

	if (dlgOpen.DoModal() != IDOK)
		return;

	strSrcName = dlgOpen.GetPathName();
	AfxGetApp()->WriteProfileString(_T("PFlashUpdate"), _T("SrcName"), strSrcName);

	SaveSettings();
	if (!CheckUpdateFileName(strSrcName))	return;		// Check for a safe update operation 

	p = (char *)malloc(HEXFILE_SIZE);
	memset(p, 0xff, HEXFILE_SIZE);
	iLength = ReadHexFile(strSrcName, p);

	if (iLength > 0)
	{
		if (m_iPFlashPage == 3 && m_iPFlashType == 1)	// AM29LV002T
		{	// Update phone settings
			CPhoneSettingsDlg::GetSettings((BYTE *)(p+0xc000));
		}
		else if (m_iPFlashPage == 0 && m_iPFlashType == 0)	// AM29LV008B
		{	// Update phone settings
			pCur = p+0x4000;
			if (pCur[0] == 0x00 && pCur[1] == 0x09 && pCur[2] == 0x45)
			{
				CPhoneSettingsDlg::GetSettings((BYTE *)(p+0x4000));
			}
			else
			{
				AfxMessageBox("Error Hex file to upgrade Palm1");
				free(p);
				return;
			}
		}
		else if (m_iPFlashPage == 7 && m_iPFlashType == 3)	// AM29LV004T
		{	// Update phone settings
			CPhoneSettingsDlg::GetSettings((BYTE *)(p+0xa000));
		}
		else if (m_iPFlashPage == 15 && m_iPFlashType == 4)	// AM29LV008T
		{	// Update phone settings
			CPhoneSettingsDlg::GetSettings((BYTE *)(p+0xa000));
		}
		else if (m_iPFlashPage == 7 && m_iPFlashType == 2)	// AM29F040
		{	// Update phone settings
			CPhoneSettingsDlg::GetSettings((BYTE *)(p+0x0200));
		}
		if (m_iCommType == 0)
		{
			Rs232LoadSdram(p, iLength, TRUE);
		}
		else if (m_iCommType == 1)
		{
			TcpipUpdate(p, iLength);
		}
	}
	else
	{
		AfxMessageBox("Error Hex file to upgrade Palm1");
	}
	free(p);
}

/* Upgrade protocol:
   Step1. PC make a TCP connection to Palm1's page0 program
   Step2. PC sends 128 bytes package data to Palm1
		  Palm1 send back 1 byte of "0xff"
   Step3. PC sends 1 byte data indicate which page to upgrade.
		  Palm1 send back 1 byte of "0xff"
   Step4. PC close the TCP connection indicate the update progress is over
*/        

void CPalmToolDlg::TcpipUpdate(char * p, int iLength) 
{
	int i, iStart, iStop;
	CString str;

	if (TcpipLoadSdram(p, iLength, m_iPFlashPage) == FALSE) return;

	// Wait Palm1 to finish its upgrade process
	GetEraseRange(iStart, iStop);
	m_progress.Create();
	m_progress.SetStep(1);
	m_progress.SetRange32(iStart, iStop);
//	for (i = iStart; i < iStop; i ++)
	for (i = iStop - 1; i >= iStart; i --)
	{
		str.Format(_T("Erase sector %d"), i);
		m_progress.SetStatus(str);
		m_progress.StepIt();
		Sleep(5000);		// Sleep 15 second for the erase sector operation
	}
	m_progress.DestroyWindow();
/*
	m_progress.Create();
	m_progress.SetStep(TCP_UPGRADE_SIZE);
	m_progress.SetRange32(0, iLength);
	for (i = 0; i < iLength; i += TCP_UPGRADE_SIZE)
	{
		str.Format(_T("Write program %d"), i);
		m_progress.SetStatus(str);
		m_progress.StepIt();
		Sleep(80);		// Sleep 0.35 ms for write operation
	}
	m_progress.DestroyWindow();
*/
}

BOOL CPalmToolDlg::TcpipLoadSdram(char * p, int iLength, int iPFlashPage)
{
	int i;
	CString str;
	char * pCur;

	// Step1
	if (BeginRj45(TRUE) == FALSE)	return FALSE;

	iLength += (TCP_UPGRADE_SIZE*2-1);
	iLength /= (TCP_UPGRADE_SIZE*2);
	iLength *= (TCP_UPGRADE_SIZE*2);

	// Step2
	m_progress.Create();
	m_progress.SetStep(TCP_UPGRADE_SIZE);
	m_progress.SetRange32(0, iLength);
	pCur = p;
	for (i = 0; i < iLength; i += TCP_UPGRADE_SIZE)
	{
		str.Format(_T("Loading data %d"), i);
		m_progress.SetStatus(str);
		::PostThreadMessage(m_pRj45Thread->m_nThreadID, WM_RJ45_DATA, (WPARAM)TCP_UPGRADE_SIZE, (LPARAM)pCur);
		if (WaitForSingleObject(CRj45Thread::m_hEventProtocol, EVENT_PROTOCOL_TIMEOUT) == WAIT_TIMEOUT)
		{
			AfxMessageBox("tcp connection failed");
			m_progress.DestroyWindow();
			EndRj45();
			return FALSE;
		}
		m_progress.StepIt();
		pCur += TCP_UPGRADE_SIZE;
	}
	m_progress.DestroyWindow();

	// Step3
	if (iPFlashPage != -1)
	{
		::PostThreadMessage(m_pRj45Thread->m_nThreadID, WM_RJ45_ERASE_PAGE, (WPARAM)iPFlashPage, 0);
		if (WaitForSingleObject(CRj45Thread::m_hEventProtocol, EVENT_PROTOCOL_TIMEOUT) == WAIT_TIMEOUT)
		{
			AfxMessageBox("tcp connection failed");
			EndRj45();
			return FALSE;
		}
	}

	// Step4
	EndRj45();
	return TRUE;
}

void CPalmToolDlg::OnUpdateRing() 
{
	CString strSrcName = AfxGetApp()->GetProfileString(_T("RingUpdate"), _T("SrcName"), _T("ring.dat"));
	CFileDialog dlgOpen(TRUE, _T("*.dat"), strSrcName, OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST, szDatFilter);
	CFile in;
	int iLength;
	char * p;

	if (dlgOpen.DoModal() != IDOK)
		return;

	strSrcName = dlgOpen.GetPathName();
	AfxGetApp()->WriteProfileString(_T("RingUpdate"), _T("SrcName"), strSrcName);

	SaveSettings();
	if (!CheckUpdateOptions())	return;

	if (!in.Open(strSrcName, CFile::modeRead))
	{
		AfxMessageBox("Can not open source file");
		return;
	}
	iLength = in.GetLength();
	p = (char *)malloc(iLength);
	in.Read(p, iLength);
	in.Close();

	if (TcpipLoadSdram(p, iLength, RING_UPGRADE_PAGE))
	{
		// We will check if it is really upgrading by making another tcp connection
		Sleep(500);
		m_pRj45Thread = new CRj45Thread;
		m_pRj45Thread->CreateThread();
		if (WaitForSingleObject(CRj45Thread::m_hEventProtocol, EVENT_PROTOCOL_TIMEOUT) == WAIT_TIMEOUT)
		{
			AfxMessageBox("Updating ... please wait until the update led stops flashing", MB_ICONINFORMATION|MB_OK);
		}
		else
		{
			AfxMessageBox("Invalid update ring method");
		}
		EndRj45();
	}
	free(p);
}

void CPalmToolDlg::OnUpdateMap() 
{
	CString strSrcName = AfxGetApp()->GetProfileString(_T("MapUpdate"), _T("SrcName"), _T("map.txt"));
	CFileDialog dlgOpen(TRUE, _T("*.txt"), strSrcName, OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST, szTxtFilter);
	CFile in;
	int iLength;
	char * p;

	if (dlgOpen.DoModal() != IDOK)
		return;

	strSrcName = dlgOpen.GetPathName();
	AfxGetApp()->WriteProfileString(_T("MapUpdate"), _T("SrcName"), strSrcName);

	SaveSettings();
	if (!CheckUpdateOptions())	return;

	if (!in.Open(strSrcName, CFile::modeRead))
	{
		AfxMessageBox("Can not open source file");
		return;
	}
	iLength = in.GetLength();
	p = (char *)malloc(iLength+2);
	in.Read(p, iLength);
	in.Close();
	p[iLength] = 0x0d;
	iLength ++;
	p[iLength] = 0x0a;
	iLength ++;

	if (TcpipLoadSdram(p, iLength, 	MAP_UPGRADE_PAGE))
	{
		// We will check if it is really upgrading by making another tcp connection
		Sleep(500);
		m_pRj45Thread = new CRj45Thread;
		m_pRj45Thread->CreateThread();
		if (WaitForSingleObject(CRj45Thread::m_hEventProtocol, EVENT_PROTOCOL_TIMEOUT) == WAIT_TIMEOUT)
		{
			AfxMessageBox("Updating ... please wait until the update led stops flashing", MB_ICONINFORMATION|MB_OK);
		}
		else
		{
			AfxMessageBox("Invalid update digitmap method");
		}
		EndRj45();
	}
	free(p);
}

void CPalmToolDlg::OnUpdateAlternate() 
{
	CString strSrcName = AfxGetApp()->GetProfileString(_T("AlternateUpdate"), _T("SrcName"), _T("setting.txt"));
	CFileDialog dlgOpen(TRUE, _T("*.txt"), strSrcName, OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST, szTxtFilter);
	CStdioFile in;
	CString strIn;
	int iLength, iCur;
	char * p, * pFlag;

	SaveSettings();
	if (!CheckUpdateOptions())	return;

	iLength = 4*PHONE_SETTINGS_SIZE;
	p = (char *)malloc(TOTAL_SETTINGS_SIZE);
	memset(p, 0, TOTAL_SETTINGS_SIZE);

	if (!TcpipSaveSdram(p, TRUE))	return;
	pFlag = p + 256;
	Sys_iProtocol = (int)pFlag[FLAGS_PROTOCOL];
	memcpy((void *)(p+PHONE_SETTINGS_SIZE), p, PHONE_SETTINGS_SIZE);
	memcpy((void *)(p+PHONE_SETTINGS_SIZE*2), p, PHONE_SETTINGS_SIZE*2);

	if (dlgOpen.DoModal() != IDOK)		return;

	strSrcName = dlgOpen.GetPathName();
	AfxGetApp()->WriteProfileString(_T("AlternateUpdate"), _T("SrcName"), strSrcName);
	if (!in.Open(strSrcName, CFile::modeRead|CFile::typeText))
	{
		AfxMessageBox("Can not open source file");
		return;
	}

	AfxGetApp()->BeginWaitCursor();
	iCur = 0;
	while (in.ReadString(strIn))
	{
		if (strIn.GetAt(0) == '[')
		{
			strIn.MakeUpper();
			if (strIn.Left(8) == "[SETTING")
				iCur = strIn.GetAt(8) - '1';

			if (iCur > 4)
			{
				AfxMessageBox("Invalid source file");
				return;
			}
		}
		else
		{
			if( !(CompareSettings((char *)(p+512*iCur), strIn)) )
				return;
		}
	}
	AfxGetApp()->EndWaitCursor();

	in.Close();

	if (TcpipLoadSdram(p, iLength, 	ALTERNATE_SETTING_UPGRADE_PAGE))
	{
		// We will check if it is really upgrading by making another tcp connection
		Sleep(500);
		m_pRj45Thread = new CRj45Thread;
		m_pRj45Thread->CreateThread();
		if (WaitForSingleObject(CRj45Thread::m_hEventProtocol, EVENT_PROTOCOL_TIMEOUT) == WAIT_TIMEOUT)
		{
			AfxMessageBox("Updating ... please wait until the update led stops flashing", MB_ICONINFORMATION|MB_OK);
		}
		else
		{
			AfxMessageBox("Invalid update method");
		}
		EndRj45();
	}
	free(p);
}

void CPalmToolDlg::OnLoadSdram() 
{
	CFile file;
	int iLength;
	char * p = NULL;
	CString strSrcName = AfxGetApp()->GetProfileString(_T("LoadSdram"), _T("SrcName"), _T("sdram.dat"));
	CFileDialog dlgOpen(TRUE, _T("*.dat"), strSrcName, OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST, szDatFilter);

	if (dlgOpen.DoModal() != IDOK)
		return;

	strSrcName = dlgOpen.GetPathName();
	AfxGetApp()->WriteProfileString(_T("LoadSdram"), _T("SrcName"), strSrcName);

	SaveSettings();

	// Read data from file
	if (!file.Open(strSrcName, CFile::modeRead))
	{
		AfxMessageBox("Can not open source file");
		return;
	}
	iLength = file.GetLength();
	if (iLength > SDRAM_MAX_LENGTH)		iLength = SDRAM_MAX_LENGTH;
	p = (char *)malloc(SDRAM_MAX_LENGTH);
	if (p == NULL)
	{
		AfxMessageBox("Can not malloc memory");
		file.Close();
		return;
	}
	file.Read(p, iLength);
	file.Close();

	if (m_iCommType == 0)
	{
		Rs232LoadSdram(p, iLength, FALSE);
	}
	else if (m_iCommType == 1)
	{
		TcpipLoadSdram(p, iLength, -1);
	}
	free(p);
}

/* Load data to sdram protocol:
   Step1. PC sends at least 8 bytes of "0x00" indicating Palm1 to begin write data to sdram,
          Palm1 echoes back 8 bytes of "0"
   Step2. PC sends bytes to write, first a "8", followed by 8 actualy bytes to write,
          Palm1 echoes back 8 bytes of "0x55"
   Step3. PC sends a "0xff" or "0xaa" indicate the write progress is over, if the byte
          is "0xaa", do upgrade
*/

BOOL CPalmToolDlg::Rs232LoadSdram(char * p, int iLength, BOOL bUpgrade)
{
	int i, j;
	CString str;

	// Open rs232 port
	if (!BeginRs232())
	{
		return FALSE;
	}

	// Step1
	BeginWaitCursor();
	for (i = 0; i < 8; i ++)
	{
		m_comm.Put((char)0x00);
	}
	if (WaitForSingleObject(CRs232Thread::m_hEventProtocol, 2000) == WAIT_TIMEOUT)
	{
		AfxMessageBox("Can not connect to Palm1");
		EndRs232();
		return FALSE;
	}
	EndWaitCursor();

	// Step2
	m_progress.Create();
	m_progress.SetStep(8);
	m_progress.SetRange32(0, iLength);
	for (i = 0; i < iLength; i += 8)
	{
		str.Format(_T("Write data %d"), i);
		m_progress.SetStatus(str);
		m_comm.Put(8);
		for (j = 0; j < 8; j ++)
		{
			m_comm.Put(p[i+j]);
			Sleep(0);
		}
		if (WaitForSingleObject(CRs232Thread::m_hEventProtocol, 1000) == WAIT_TIMEOUT)
		{
			AfxMessageBox("Write operation failed");
			m_progress.DestroyWindow();
			EndRs232();
			return FALSE;
		}
		m_progress.StepIt();
	}

	// Step3
	m_comm.Put(bUpgrade ? (char)0xaa : (char)0xff);
	Sleep(10);
	m_progress.DestroyWindow();

	EndRs232();
	return TRUE;
}

/* Save sdram data to a file protocol:
   Step1. PC sends at least 8 bytes of "0xff" indicating Palm1 to begin read data from sdram,
          Palm1 echoes back 8 bytes of "0xff"
   Step2. PC sends a "8" to indicate the read operation, Palm1 send 8 bytes data back, 
          until all data needed have been read
   Step3. PC sends a "0x00" indicate the read progress is over
*/

void CPalmToolDlg::OnSaveSdram() 
{
	char * p = NULL;
	CString strDstName = AfxGetApp()->GetProfileString(_T("SaveSdram"), _T("DstName"), _T("sdram.dat"));
	CFileDialog dlgSave(FALSE, _T("*.dat"), strDstName, OFN_PATHMUSTEXIST, szDatFilter);
	CFile file;

	if (dlgSave.DoModal() != IDOK)
		return;

	strDstName = dlgSave.GetPathName();
	AfxGetApp()->WriteProfileString(_T("SaveSdram"), _T("DstName"), strDstName);
	SaveSettings();

	p = (char *)malloc(SDRAM_MAX_LENGTH);
	if (p == NULL)
	{
		AfxMessageBox("Can not malloc memory");
		return;
	}

	if (m_iCommType == 0)
	{
		if (Rs232SaveSdram(p) == FALSE)		goto End;
	}
	else if (m_iCommType == 1)
	{
		if (TcpipSaveSdram(p, FALSE) == FALSE)		goto End;
	}

	file.Open(strDstName, CFile::modeCreate|CFile::modeWrite);
	file.Write(p, m_iSaveSdramLength);
	file.Close();

End:
	free(p);
}

BOOL CPalmToolDlg::Rs232SaveSdram(char * p)
{
	int i;
	CString str;

	if (!BeginRs232())	return FALSE;

	// Step1
	BeginWaitCursor();
	for (i = 0; i < 8; i ++)
	{
		m_comm.Put((char)0xff);
	}
	if (WaitForSingleObject(CRs232Thread::m_hEventProtocol, 2000) == WAIT_TIMEOUT)
	{
		AfxMessageBox("Can not connect to Palm1");
		EndRs232();
		return FALSE;
	}
	EndWaitCursor();

	// Step2
	::PostThreadMessage(m_pRs232Thread->m_nThreadID, WM_RS232_SAVING_FILE, TRUE, (LPARAM)p);
	Sleep(1);

	m_progress.Create();
	m_progress.SetStep(8);
	m_progress.SetRange32(0, m_iSaveSdramLength);
	for (i = 0; i < m_iSaveSdramLength; i += 8)
	{
		str.Format(_T("Reading data %d"), i);
		m_progress.SetStatus(str);
		m_comm.Put(8);
		if (WaitForSingleObject(CRs232Thread::m_hEventProtocol, 1000) == WAIT_TIMEOUT)
		{
			AfxMessageBox("Read operation failed");
			m_progress.DestroyWindow();
			EndRs232();
			return FALSE;
		}
		m_progress.StepIt();
	}

	// Step3
	m_comm.Put((char)0x00);
	::PostThreadMessage(m_pRs232Thread->m_nThreadID, WM_RS232_SAVING_FILE, FALSE, 0);
	Sleep(1);
	m_progress.DestroyWindow();

	return TRUE;
}

BOOL CPalmToolDlg::TcpipSaveSdram(char * p, BOOL bSettings)
{
	int i, iLength;
	CString str;
	char pSaveHint[] = "dh";	// data hint

	// Step1
	if (BeginRj45(TRUE) == FALSE)	return FALSE;

	if (bSettings)
	{
		pSaveHint[0] = 's';		// settings hint
		iLength = TOTAL_SETTINGS_SIZE;
	}
	else
	{
		iLength = m_iSaveSdramLength;
		iLength += (TCP_UPGRADE_SIZE*2-1);
		iLength /= (TCP_UPGRADE_SIZE*2);
		iLength *= (TCP_UPGRADE_SIZE*2);
	}

	// Step2
	::PostThreadMessage(m_pRj45Thread->m_nThreadID, WM_RJ45_BEGIN_READ, (WPARAM)TRUE, (LPARAM)p);

	// Step3
	m_progress.Create();
	m_progress.SetStep(TCP_UPGRADE_SIZE);
	m_progress.SetRange32(0, iLength);
	for (i = 0; i < iLength; i += TCP_UPGRADE_SIZE)
	{
		str.Format(_T("Reading data %d"), i);
		m_progress.SetStatus(str);
		::PostThreadMessage(m_pRj45Thread->m_nThreadID, WM_RJ45_DATA, (WPARAM)2, (LPARAM)pSaveHint);
		if (WaitForSingleObject(CRj45Thread::m_hEventProtocol, EVENT_PROTOCOL_TIMEOUT) == WAIT_TIMEOUT)
		{
			AfxMessageBox("tcp connection failed");
			m_progress.DestroyWindow();
			EndRj45();
			return FALSE;
		}
		m_progress.StepIt();
	}
	m_progress.DestroyWindow();

	// Step4
	::PostThreadMessage(m_pRj45Thread->m_nThreadID, WM_RJ45_BEGIN_READ, (WPARAM)FALSE, 0);

	// Step5
	EndRj45();
	return TRUE;
}

void CPalmToolDlg::OnUdpAudio() 
{
	if (m_pUdpAudioThread == NULL)
	{
		SaveSettings();

		if (m_bAudioSaveFile)
		{
			CString strDstName = AfxGetApp()->GetProfileString(_T("UdpAudio"), _T("DstName"), _T("udpaudio.dat"));
			CFileDialog dlgSave(FALSE, _T("*.dat"), strDstName, OFN_PATHMUSTEXIST, szDatFilter);
			if (dlgSave.DoModal() != IDOK)
				return;

			strDstName = dlgSave.GetPathName();
			AfxGetApp()->WriteProfileString(_T("UdpAudio"), _T("DstName"), strDstName);
		}

		BeginUdpAudio();
		CString str;
		str.LoadString(IDS_STOP_UDP_AUDIO);
		GetDlgItem(IDC_UDP_AUDIO)->SetWindowText(str);
		GetDlgItem(IDC_AUDIO_TYPE)->EnableWindow(FALSE);
		GetDlgItem(IDC_PEER_IP)->EnableWindow(FALSE);
	}
	else
	{
		EndUdpAudio();
		CString str;
		str.LoadString(IDS_START_UDP_AUDIO);
		GetDlgItem(IDC_UDP_AUDIO)->SetWindowText(str);
		GetDlgItem(IDC_AUDIO_TYPE)->EnableWindow(TRUE);
		GetDlgItem(IDC_PEER_IP)->EnableWindow(TRUE);
	}
}

void CPalmToolDlg::OnCancel() 
{
	if (m_pUdpAudioThread != NULL)
	{
		OnUdpAudio();
	}
	if (m_pUdpDebugThread != NULL)
	{
		OnStartDebug();
	}
	if (m_pRs232Thread != NULL)
	{
		OnStartDebug();
	}
	
	CDialog::OnCancel();
}

void CPalmToolDlg::OnUpdateProgram() 
{
	CString strSrcName = AfxGetApp()->GetProfileString(_T("ProgramUpdate"), _T("SrcName"), _T("demo.bin"));
	CFileDialog dlgOpen(TRUE, _T("*.bin"), strSrcName, OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST, szBinFilter);
	CFile in;
	int iLength;
	char * p;

	if (dlgOpen.DoModal() != IDOK)
		return;

	strSrcName = dlgOpen.GetPathName();
	AfxGetApp()->WriteProfileString(_T("ProgramUpdate"), _T("SrcName"), strSrcName);

	SaveSettings();
	if (!CheckUpdateOptions())	return;

	if (!in.Open(strSrcName, CFile::modeRead))
	{
		AfxMessageBox("Can not open source file");
		return;
	}
	iLength = in.GetLength();
/*	if (iLength != HEXFILE_SIZE*3)
	{
		AfxMessageBox("source file length error");
		in.Close();
		return;
	}
*/
	p = (char *)malloc(iLength);
	in.Read(p, iLength);
	in.Close();

	if (TcpipLoadSdram(p, iLength, PROGRAM_UPGRADE_PAGE))
	{
		// We will check if it is really upgrading by making another tcp connection
		Sleep(500);
		m_pRj45Thread = new CRj45Thread;
		m_pRj45Thread->CreateThread();
		if (WaitForSingleObject(CRj45Thread::m_hEventProtocol, EVENT_PROTOCOL_TIMEOUT) == WAIT_TIMEOUT)
		{
			AfxMessageBox("Updating ... please wait until the update led stops flashing", MB_ICONINFORMATION|MB_OK);
		}
		else
		{
			AfxMessageBox("Invalid update method");
		}
		EndRj45();
	}
	free(p);
}

void CPalmToolDlg::OnPhoneSettings() 
{
	char * p;

	SaveSettings();
	if (!CheckUpdateOptions())	return;

	p = (char *)malloc(TOTAL_SETTINGS_SIZE);
	memset(p, 0, TOTAL_SETTINGS_SIZE);

	if (TcpipSaveSdram(p, TRUE))
	{
		CPhoneSettingsDlg::SetSettings((BYTE *)p);
	}

	CPhoneSettingsDlg dlg;
	if (dlg.DoModal() != IDOK)	goto End;
	if (AfxMessageBox("Update settings to phone now?", MB_ICONQUESTION|MB_YESNO) != IDYES)
		goto End;

	CPhoneSettingsDlg::GetSettings((BYTE *)p);

	if (TcpipLoadSdram(p, TOTAL_SETTINGS_SIZE, OPTIONS_UPGRADE_PAGE))
	{
		// We will check if it is really upgrading by making another tcp connection
//		AfxMessageBox("Click Ok, Then wait about 15 seconds");
		Sleep(500);
		m_pRj45Thread = new CRj45Thread;
		m_pRj45Thread->CreateThread();
		if (WaitForSingleObject(CRj45Thread::m_hEventProtocol, EVENT_PROTOCOL_TIMEOUT) == WAIT_TIMEOUT)
		{
			AfxMessageBox("New settings updated", MB_ICONINFORMATION|MB_OK);
		}
		else
		{
			AfxMessageBox("Invalid settings method");
		}
		EndRj45();
	}

End:
	free(p);
}

void CPalmToolDlg::OnStartDebug() 
{
	SaveSettings();
	if (m_iCommType == 0)
	{
		if (m_pRs232Thread == NULL)
		{
			if (BeginRs232())
			{
				::PostThreadMessage(m_pRs232Thread->m_nThreadID, WM_RS232_START_DEBUG, 0, 0);
				EnableDebug(TRUE);
			}
		}
		else
		{
			EndRs232();
			EnableDebug(FALSE);
		}
	}
	else if (m_iCommType == 1)
	{
		if (m_pUdpDebugThread == NULL)
		{
			BeginUdpDebug();
			EnableDebug(TRUE);
		}
		else
		{
			EndUdpDebug();
			EnableDebug(FALSE);
		}
	}
}

void CPalmToolDlg::EnableDebug(BOOL bEnable)
{
	if (bEnable)
	{
		CString str;
		str.LoadString(IDS_STOP_DEBUG);
		GetDlgItem(IDC_START_DEBUG)->SetWindowText(str);
		GetDlgItem(IDC_UPDATE_PFLASH)->EnableWindow(FALSE);
		GetDlgItem(IDC_LOAD_SDRAM)->EnableWindow(FALSE);
		GetDlgItem(IDC_SAVE_SDRAM)->EnableWindow(FALSE);
		GetDlgItem(IDC_COMMUNICATION1)->EnableWindow(FALSE);
		GetDlgItem(IDC_COMMUNICATION2)->EnableWindow(FALSE);
		GetDlgItem(IDC_UDP_AUDIO)->EnableWindow(FALSE);
		GetDlgItem(IDC_PHONE_SETTINGS)->EnableWindow(FALSE);
	}
	else
	{
		CString str;
		str.LoadString(IDS_START_DEBUG);
		GetDlgItem(IDC_START_DEBUG)->SetWindowText(str);
		GetDlgItem(IDC_UPDATE_PFLASH)->EnableWindow(TRUE);
		GetDlgItem(IDC_LOAD_SDRAM)->EnableWindow(TRUE);
		GetDlgItem(IDC_SAVE_SDRAM)->EnableWindow(TRUE);
		GetDlgItem(IDC_COMMUNICATION1)->EnableWindow(TRUE);
		GetDlgItem(IDC_COMMUNICATION2)->EnableWindow(TRUE);
		GetDlgItem(IDC_UDP_AUDIO)->EnableWindow(TRUE);
		GetDlgItem(IDC_PHONE_SETTINGS)->EnableWindow(TRUE);
	}
}

void CPalmToolDlg::OnSelChangeAudioType() 
{
	UpdateData();
	m_iAudioType = m_ctlAudioType.GetCurSel();
	GetDlgItem(IDC_USE_VAD)->EnableWindow((m_iAudioType == 5 || m_iAudioType == 6) && m_bAudioNoAcm);
	GetDlgItem(IDC_USE_HIGH_RATE)->EnableWindow((m_iAudioType == 6) && m_bAudioNoAcm);
	if (m_iAudioType == 6)
	{
		m_iSaveSdramLength = 558816;
	}
	else if (m_iAudioType == 5)
	{
		m_iSaveSdramLength = 519092;
	}
	UpdateData(FALSE);
}

void CPalmToolDlg::OnAudioNoAcm() 
{
	OnSelChangeAudioType();
}

void CPalmToolDlg::OnCommunication1() 
{
	UpdateData();
	if (m_iCommType == 0)
	{
		GetDlgItem(IDC_RS232_PORT)->EnableWindow(TRUE);
		GetDlgItem(IDC_RS232_PORT2)->EnableWindow(TRUE);
	}
	else
	{
		GetDlgItem(IDC_RS232_PORT)->EnableWindow(FALSE);
		GetDlgItem(IDC_RS232_PORT2)->EnableWindow(FALSE);
	}
}

void CPalmToolDlg::OnCommunication2() 
{
	OnCommunication1();
}

void CPalmToolDlg::OnTestButton() 
{
/*	int i;
	CUdpSocket multicast;
	
	multicast.Enter(GetSafeHwnd(), 0, 0xe0010205);
	for (i = 0; i < 10; i ++)
	{
		char * p = (char *)malloc(32);
		sprintf(p, "Hello, world! -- %d", i);
		multicast.Write(p, strlen(p));
		Sleep(0);
	}
	multicast.Leave();
*/
}

void CPalmToolDlg::OnConvertFile() 
{
	SaveSettings();

	CConvertFileDlg dlg;
	dlg.DoModal();
}

void CPalmToolDlg::OnGenerateHttpfile() 
{
	SaveSettings();

	CHttpDlg dlg;
	dlg.DoModal();
}

void CPalmToolDlg::OnListPhones() 
{
	CPhoneListDlg dlg;
	ULONG uIP;

	SaveSettings();
	if (dlg.DoModal() == IDOK)
	{
//		AfxMessageBox(dlg.m_strSelectedIP);
		uIP = CTcpSocket::Name2IP(dlg.m_strSelectedIP);
		m_ctlPeerIP.SetAddress((UCHAR)uIP&0xff, (UCHAR)((uIP>>8)&0xff), (UCHAR)((uIP>>16)&0xff), (UCHAR)((uIP>>24)&0xff));
		UpdateData(FALSE);
	}
}

void CPalmToolDlg::OnSaveSettings() 
{
	char * p = NULL;
	CString strDstName = AfxGetApp()->GetProfileString(_T("SaveSettings"), _T("DstName"), _T("settings.txt"));
	CFileDialog dlgSave(FALSE, _T("*.txt"), strDstName, OFN_PATHMUSTEXIST, szTxtFilter);
	CStdioFile out;
	CString cStr;
	
	if (dlgSave.DoModal() != IDOK)
		return;

	p = (char *)malloc(TOTAL_SETTINGS_SIZE);
	memset(p, 0, TOTAL_SETTINGS_SIZE);

	strDstName = dlgSave.GetPathName();
	AfxGetApp()->WriteProfileString(_T("SaveSettings"), _T("DstName"), strDstName);
	SaveSettings();
	out.Open(strDstName, CFile::modeCreate|CFile::modeWrite|CFile::typeText);

	if (TcpipSaveSdram(p, TRUE) == FALSE)		goto End;

	ConvertSettings((char *)p, cStr, TOTAL_SETTINGS_SIZE);

	out.WriteString(cStr);
	out.Close();

End:
	free(p);
}

void CPalmToolDlg::OnLoadSettings() 
{
	char * p = NULL;
	CString strSrcName = AfxGetApp()->GetProfileString(_T("LoadSettings"), _T("SrcName"), _T("settings.txt"));
	CFileDialog dlgOpen(TRUE, _T("*.txt"), strSrcName, OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST, szTxtFilter);

	CStdioFile in;
	CString strIn;

	int iCur;
	char * pFlag;

	SaveSettings();
	if (!CheckUpdateOptions())	return;

	p = (char *)malloc(TOTAL_SETTINGS_SIZE);
	memset(p, 0, TOTAL_SETTINGS_SIZE);

	if (!TcpipSaveSdram(p, TRUE))	return;
	pFlag = p + 256;
	Sys_iProtocol = (int)pFlag[FLAGS_PROTOCOL];

	if (dlgOpen.DoModal() != IDOK)		return;

	strSrcName = dlgOpen.GetPathName();
	AfxGetApp()->WriteProfileString(_T("LoadSettings"), _T("SrcName"), strSrcName);

	if (!in.Open(strSrcName, CFile::modeRead|CFile::typeText))
	{
		AfxMessageBox("Can not open source file");
		return;
	}

	AfxGetApp()->BeginWaitCursor();
	iCur = 0;
	while (in.ReadString(strIn))
	{
		if (strIn.GetAt(0) == '[')
		{
			strIn.MakeUpper();
			if (strIn.Left(8) == "[SETTING")
			{
				iCur = strIn.GetAt(8) - ']';
			}
		}
		else
		{
			if( !(CompareSettings((char *)(p+512*iCur), strIn)) )
				return;
		}
	}
	AfxGetApp()->EndWaitCursor();

	in.Close();

	if (TcpipLoadSdram(p, TOTAL_SETTINGS_SIZE, 	OPTIONS_UPGRADE_PAGE))
	{
		// We will check if it is really upgrading by making another tcp connection
		Sleep(500);
		m_pRj45Thread = new CRj45Thread;
		m_pRj45Thread->CreateThread();
		if (WaitForSingleObject(CRj45Thread::m_hEventProtocol, EVENT_PROTOCOL_TIMEOUT) == WAIT_TIMEOUT)
		{
			AfxMessageBox("Updating ... please wait until the update led stops flashing", MB_ICONINFORMATION|MB_OK);
		}
		else
		{
			AfxMessageBox("Invalid update method");
		}
		EndRj45();
	}
	free(p);
}

void CPalmToolDlg::OnSaveAddress() 
{
	char * p = NULL;
	CString strDstName = AfxGetApp()->GetProfileString(_T("SaveAddress"), _T("DstName"), _T("address.txt"));
	CFileDialog dlgSave(FALSE, _T("*.txt"), strDstName, OFN_PATHMUSTEXIST, szTxtFilter);
	CStdioFile out;
	CString cStr;
	
	if (dlgSave.DoModal() != IDOK)
		return;

	p = (char *)malloc(TOTAL_SETTINGS_SIZE);
	memset(p, 0, TOTAL_SETTINGS_SIZE);

	strDstName = dlgSave.GetPathName();
	AfxGetApp()->WriteProfileString(_T("SaveAddress"), _T("DstName"), strDstName);
	SaveSettings();
	out.Open(strDstName, CFile::modeCreate|CFile::modeWrite|CFile::typeText);

	if (TcpipSaveSdram(p, TRUE) == FALSE)		goto End;

	CPhoneAddrDlg::ConvertAddress((BYTE *)p, cStr);

	out.WriteString(cStr);
	out.Close();

End:
	free(p);
}

void CPalmToolDlg::OnLoadAddress() 
{
	char * p = NULL;
	CString strSrcName = AfxGetApp()->GetProfileString(_T("LoadAddress"), _T("SrcName"), _T("address.txt"));
	CFileDialog dlgOpen(TRUE, _T("*.txt"), strSrcName, OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST, szTxtFilter);

	CStdioFile in;
	CString strIn;

	int iCur;
	int iDest;
	bool bSpeedDialName;

	SaveSettings();
	if (!CheckUpdateOptions())	return;

	p = (char *)malloc(TOTAL_SETTINGS_SIZE);
	memset(p, 0, TOTAL_SETTINGS_SIZE);

	if (!TcpipSaveSdram(p, TRUE))	return;

	if (dlgOpen.DoModal() != IDOK)		return;

	strSrcName = dlgOpen.GetPathName();
	AfxGetApp()->WriteProfileString(_T("LoadAddress"), _T("SrcName"), strSrcName);

	if (!in.Open(strSrcName, CFile::modeRead|CFile::typeText))
	{
		AfxMessageBox("Can not open source file");
		return;
	}

	AfxGetApp()->BeginWaitCursor();
	iCur = 0;
	while (in.ReadString(strIn))
	{
		if (strIn.Left(6) == "memory")
		{
			bSpeedDialName = TRUE;
		}
		else if (strIn.Left(6) == "number")
		{
			bSpeedDialName = FALSE;
		}

		iDest = strIn.Find(':');
		iCur = atoi(strIn.Mid(6, iDest - 6));

		if (!(CPhoneAddrDlg::WrietAddressBook((BYTE *)p, strIn, iCur-1, bSpeedDialName)))
			return;
	}
	AfxGetApp()->EndWaitCursor();

	in.Close();

	if (TcpipLoadSdram(p, TOTAL_SETTINGS_SIZE, 	OPTIONS_UPGRADE_PAGE))
	{
		// We will check if it is really upgrading by making another tcp connection
		Sleep(500);
		m_pRj45Thread = new CRj45Thread;
		m_pRj45Thread->CreateThread();
		if (WaitForSingleObject(CRj45Thread::m_hEventProtocol, EVENT_PROTOCOL_TIMEOUT) == WAIT_TIMEOUT)
		{
			AfxMessageBox("Updating ... please wait until the update led stops flashing", MB_ICONINFORMATION|MB_OK);
		}
		else
		{
			AfxMessageBox("Invalid update method");
		}
		EndRj45();
	}
	free(p);
}


void CPalmToolDlg::OnSavePacket() 
{
	if (m_bRecvPacket)
	{
		m_bRecvPacket = FALSE;
		m_rtp_udp.Leave();
		m_rtp_file.Close();
		CString str;
		str.LoadString(IDS_START_RECV_PACKET);
		GetDlgItem(IDC_SAVE_PACKET)->SetWindowText(str);
		UpdateData(FALSE);
	}
	else
	{
		CString strDstName = AfxGetApp()->GetProfileString(_T("SaveRtpData"), _T("DstName"), _T("data.dat"));
		CFileDialog dlgSave(FALSE, _T("*.dat"), strDstName, OFN_PATHMUSTEXIST, szDatFilter);

		if (dlgSave.DoModal() != IDOK)
		{
			return;
		}

		strDstName = dlgSave.GetPathName();
		AfxGetApp()->WriteProfileString(_T("SaveRtpData"), _T("DstName"), strDstName);

		if (!m_rtp_file.Open(strDstName, CFile::modeCreate|CFile::modeWrite))
		{
			AfxMessageBox("Can not open dst file");
			return;
		}
		UpdateData();
		m_rtp_udp.Enter(this->GetSafeHwnd(), WM_UDP_SOCKET_DATA, 0xc0a80101, PALMTOOL_DST_PORT);
		m_ctlPeerIP.GetAddress(m_uPeerIP);
		AfxGetApp()->WriteProfileInt(_T("Peer"), _T("IPAddress"), m_uPeerIP);
		AfxGetApp()->WriteProfileInt(_T("SavePacket"), _T("Offset"), m_iOffset);
		CString str;
		str.LoadString(IDS_STOP_RECV_PACKET);
		GetDlgItem(IDC_SAVE_PACKET)->SetWindowText(str);
		OutputDebugString(str);
		m_bRecvPacket = TRUE;
		m_iPacketNum = 0;
		m_strPacketNum.Format("%d", m_iPacketNum);
		UpdateData(FALSE);
	}
}

#if _MSC_VER >= 1300
LRESULT CPalmToolDlg::OnUdpData(WPARAM wParam, LPARAM lParam)
#else
void CPalmToolDlg::OnUdpData(WPARAM wParam, LPARAM lParam)
#endif
{
	ULONG uPeerIP = (ULONG)wParam;
	WSABUF * p = (WSABUF *)lParam;
	UCHAR * pData = (UCHAR *)p->buf;
	int iLength = p->len;

	uPeerIP = MAKELONG(MAKEWORD(HIBYTE(HIWORD(uPeerIP)), LOBYTE(HIWORD(uPeerIP))), MAKEWORD(HIBYTE(LOWORD(uPeerIP)), LOBYTE(LOWORD(uPeerIP))));
	if (uPeerIP == m_uPeerIP && iLength > m_iOffset)
	{
		iLength -= m_iOffset;
		pData += m_iOffset;
		m_rtp_file.Write(pData, iLength);
		m_iPacketNum ++;
		m_strPacketNum.Format("%d", m_iPacketNum);
		UpdateData(FALSE);
	}

	free(p->buf);
	free(p);
#if _MSC_VER >= 1300
	return 0;
#endif
}
