// diagno.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "diagno.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

#include "diagnost.h"
#include "diagnres.h" 
#include "communic.h"
#include <ctype.h>
#include "abibase.h"

extern BOOL SetupCommunication(UINT pData);
extern BOOL SetCommType(int nTempCommType);
STATUS AbiGetFwId(UCHAR *uchMajor,  UCHAR *uchMinor);

extern BOOL ReadLoadOption(void);
extern BOOL WriteLoadOption(void);

CString strAppPath;

int nPortAddr = 0x300;         
int nPortType = 0; // 0 -> Parallel(PCE)
                   // 1 -> LPT1
                   // 2 -> LPT2
                   // 3 -> LPT3          
                   // 4 -> COM1
                   // 5 -> COM2
                   // 6 -> COM3
                   // 7 -> COM4
                   
const char * DefPortAddr[8] = {
    "280",  //PCE
    "378",  //LPT1
    "3BC",  //LPT2
    "3BC",  //LPT3
    "3F8",  //COM1
    "2F8",  //COM2
    "0",    //COM3
    "0"     //COM4
};                                       

int nBaudRate = 0;   

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
static void CutTailWS(char * psz)
{
    int l = strlen(psz);
    if(!l)  return;     
    psz += l - 1;
    while(isspace(*psz))    -- psz;
    *(psz+1) = '\0';
}                

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   SkipHeadWS
//
//  Description: Skip head white space of the string
//
//  Input:  
//      psz -- the string
//
//  Output: None
//
//  Return: the string that been processed
//
/////////////////////////////////////////////////////////////////////////////
static char * SkipHeadWS(char * psz)
{
    while(isspace(*psz))    ++ psz;
    return psz;
}              
                     
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
static BOOL Hex2Num(char * psz, DWORD & dwVal)
{
    char * p = psz;
                   
    int l = strlen(p);
    if(l == 0)  return FALSE;
                              
    DWORD dw = 1;                              
    dwVal = 0;      
    p += l - 1;
    for(int i = 0; i < l; i ++, p --, dw *= 16) {
        if(*p >= '0' && *p <= '9')  dwVal += (*p - '0') * dw;
        else if(*p >= 'a' && *p <= 'f') dwVal += (*p - 'a' + 10) * dw;
        else if(*p >= 'A' && *p <= 'F') dwVal += (*p - 'A' + 10) * dw;
        else    return FALSE;
    }
    return TRUE;    
}

/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: Transfer a string to a decimal number
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
static BOOL Dec2Num(char * psz, DWORD & dwVal)
{
    char * p = psz;
                   
    int l = strlen(p);
    if(l == 0)  return FALSE;
                              
    DWORD dw = 1;                              
    dwVal = 0;      
    p += l - 1;
    for(int i = 0; i < l; i ++, p --, dw *= 10) {
        if(*p < '0' || *p > '9')    return FALSE;
        dwVal += (*p - '0') * dw;
    }
    return TRUE;    
}                     
                     
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   
//
//  Description: 
//
//  Input:  
//
//  Output: 
//
//  Return: 
//
/////////////////////////////////////////////////////////////////////////////
BOOL Str2Num(char * psz, DWORD & dwVal)
{
    char * p = SkipHeadWS(psz);

    CutTailWS(p);                   
                 
    if(*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) {
        p += 2;
        return  Hex2Num(p, dwVal);
    }                               
    else return Dec2Num(p, dwVal);
}               
               
/////////////////////////////////////////////////////////////////////////////
//
//  Name:   ReadCommInfo
//
//  Description: Read communication information from .ini file
//
//  Input:  None
//
//  Output: None
//
//  Return: FALSE -- Fail to read.
//          TRUE  -- Read Ok.
//
/////////////////////////////////////////////////////////////////////////////
BOOL ReadCommInfo(void)
{
    nPortType = AfxGetApp()->GetProfileInt("COMM", "Type", 0);
    if(nPortType < 0 || nPortType > 2) {
//        AfxMessageBox(IDS_PRM_INITCOMMTYPE);
        return FALSE;
    }
    
    CString str = AfxGetApp()->GetProfileString("COMM", "Addr", 
        DefPortAddr[nPortType]);
    sscanf(str, "%x", &nPortAddr);
    return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
//
//  Name:   WriteCommInfo
//
//  Description: Write communication information to .ini file
//
//  Input:  None
//
//  Output: None
//
//  Return: None
//
/////////////////////////////////////////////////////////////////////////////
void WriteCommInfo(void)
{   
    AfxGetApp()->WriteProfileInt("COMM", "Type", nPortType);
    char ach[20];
    wsprintf(ach, "%X", nPortAddr);
    AfxGetApp()->WriteProfileString("COMM", "Addr", ach);
}                    

BOOL CommDlg(void)
{
    AfxGetApp()->DoWaitCursor(-1);
    CCommunicationDialog dlg;
    int nRet = dlg.DoModal() == IDOK;
    AfxGetApp()->DoWaitCursor(1);
    return nRet;
}   

/////////////////////////////////////////////////////////////////////////////
// CDiagnoApp

BEGIN_MESSAGE_MAP(CDiagnoApp, CWinApp)
    //{{AFX_MSG_MAP(CDiagnoApp)
    ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
        // NOTE - the ClassWizard will add and remove mapping macros here.
        //    DO NOT EDIT what you see in these blocks of generated code!
    //}}AFX_MSG_MAP
    // Standard file based document commands
    ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
    ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDiagnoApp construction

CDiagnoApp::CDiagnoApp()
{
    // TODO: add construction code here,
    // Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CDiagnoApp object

CDiagnoApp NEAR theApp;

/////////////////////////////////////////////////////////////////////////////
// CDiagnoApp initialization
extern BOOL isEpSldRunning;           
extern BOOL isFirstTime;
extern BOOL isOldFw;
extern BOOL isCanHWReset;
extern BOOL CALLBACK EnumWndProcx(HWND hwnd,LPARAM lParam);

           
BOOL CDiagnoApp::InitInstance()
{
    // Standard initialization
    // If you are not using these features and wish to reduce the size
    //  of your final executable, you should remove from the following
    //  the specific initialization routines you do not need.
    
    // Prevent from loading the second instance.
    if (m_hPrevInstance) {
        MessageBeep(-1);
        return FALSE;
    }                     

    SetDialogBkColor();        // Set dialog background color to gray
    LoadIcon (IDR_MAINFRAME);        
   //added by john 
   if (isFirstTime) {
        EnumWindows(EnumWndProcx,NULL);
        if(isEpSldRunning) {                    
            isEpSldRunning = FALSE;
            int nTmp = AfxMessageBox("      EasyPack is being runned!\nDo You Really want to go on with it?",
                                      MB_YESNO);
            if (IDNO == nTmp)   return FALSE;
                else isFirstTime = FALSE;
        }
    }       
   
   
    // Read communication information from the private profile       
    if(!ReadCommInfo()) {  
        //DelLabel();
        AfxMessageBox("Please enter the communication type and address");
        if(!CommDlg()) { 
            AfxMessageBox(IDS_PRM_INITCOMMTYPE);
            return  0;
        }
    }

    BOOL fPortEcho;
KKK:
    // Set communication type
    if ( nPortType == 0 )     // PCE
         fPortEcho = SetCommType(1);
    else if ( nPortType > 0 && nPortType <= 3 )     // LPT1->LPT3
         fPortEcho = SetCommType(2);

    if ( fPortEcho == TRUE) {
        // Set port address
        fPortEcho = SetupCommunication(nPortAddr);
    }

    if (fPortEcho == FALSE) {
        AfxMessageBox("Setup Communication Error!");
        if( !CommDlg() )
            return 0;
        else goto KKK;
    }
    
    WriteCommInfo();
 
 //check the fw version;                                    
 BYTE uchMajor,uchMinor;
 if (ICE_OK != AbiGetFwId(&uchMajor,&uchMinor)) {
    AfxMessageBox("Fail in getting FW-ID");
    isOldFw = TRUE;
 } else {
    switch(uchMajor) {
        case 0x12:if(uchMinor < 0x15) isOldFw = TRUE;
                  if(uchMinor > 0x16) isCanHWReset = TRUE;
                break;
        case 0x22:
        case 0x32:if(uchMinor < 0x13) isOldFw = TRUE;
                  if(uchMinor > 0x12) isCanHWReset = TRUE;
                break;
        case 0x42:if(uchMinor < 0x08) isOldFw = TRUE;     
                  if(uchMinor > 0x07) isCanHWReset = TRUE;
                break;
    }
    if (isOldFw) AfxMessageBox("Warning: You are using the old FW Version!\nSo Only a part function is supported.");
 }  
 
 CDiagnosticBox *diagnosticBox = new CDiagnosticBox;
    
    
    diagnosticBox->DoModal();
    delete diagnosticBox;  

    ::PostQuitMessage(WM_QUIT);
    return FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
    CAboutDlg();

// Dialog Data
    //{{AFX_DATA(CAboutDlg)
    enum { IDD = IDD_ABOUTBOX };
    //}}AFX_DATA

// Implementation
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //{{AFX_MSG(CAboutDlg)
        // No message handlers
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
    //{{AFX_DATA_INIT(CAboutDlg)
    //}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CAboutDlg)
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    //{{AFX_MSG_MAP(CAboutDlg)
        // No message handlers
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

// App command to run the dialog
void CDiagnoApp::OnAppAbout()
{
    CAboutDlg aboutDlg;
    aboutDlg.DoModal();
}

/////////////////////////////////////////////////////////////////////////////
// CDiagnoApp commands
