#ifdef TEST_RIO
#include "stdafx.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#else // !TEST_RIO
//mech
#endif // TEST_RIO

const char g_szPortFormat[] = "\\\\.\\com%d";

C232Comm::C232Comm()
    : m_hCom(INVALID_HANDLE_VALUE), m_nPort(0)
{
}

C232Comm::~C232Comm()
{
    Close();
}

BOOL C232Comm::Open(int nPort, DWORD dwBaudRate/* = CBR_9600*/, BYTE byParity/* = NOPARITY*/, BYTE bByteSize/* = 8*/, BYTE byStopBits/* = ONESTOPBIT*/)
{
    m_nPort = nPort;

    char sz[32];

    sprintf(sz, g_szPortFormat, m_nPort);
    m_hCom = CreateFile(sz, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (IsValid()) {
 	    m_cp.wPacketLength = sizeof(COMMPROP); /* get comm properties */
        if (GetCommProperties(m_hCom, &m_cp)) {
            if (GetCommState(m_hCom, &m_dcb)) {
                m_dcb.BaudRate = (DWORD)dwBaudRate;
                m_dcb.ByteSize = bByteSize; // ONESTOPBIT TWOSTOPBITS
                m_dcb.Parity = byParity; // NOPARITY EVENPARITY ODDPARITY
                m_dcb.StopBits = byStopBits;

                m_dcb.fOutxCtsFlow = 0;  
                m_dcb.fOutxDsrFlow = 0;  
                m_dcb.fRtsControl = 0;  
                m_dcb.fDtrControl = DTR_CONTROL_ENABLE; // HANDSHAKE; // 9;

                m_dcb.fOutX = 0;
                m_dcb.fInX = 0;

                if (SetCommState(m_hCom, &m_dcb)) {
  	                memset(&m_commTimeOuts, 0, sizeof(m_commTimeOuts));

	                m_commTimeOuts.ReadIntervalTimeout = MAXDWORD;
                    m_commTimeOuts.ReadTotalTimeoutMultiplier = 0;
                    m_commTimeOuts.ReadTotalTimeoutConstant = 0;
                    m_commTimeOuts.WriteTotalTimeoutMultiplier = 5;
                    m_commTimeOuts.WriteTotalTimeoutConstant = 5;
 
                    if (SetupComm(m_hCom, 2048*5, 1024)) {
                        if (SetCommTimeouts(m_hCom , &m_commTimeOuts)) {
                            if (GetCommTimeouts(m_hCom , &m_commTimeOuts)) {
                                if (GetCommState(m_hCom, &m_dcb)) {
                                    m_dcb.fDtrControl = DTR_CONTROL_DISABLE;
                                    Sleep(10);
                                    SetCommState(m_hCom, &m_dcb);

                                    return TRUE;
                                }
                            }
                        }
                    } else {
                    }	
                } else {
                }
            } else {
            }
        } else {
        }
        locProcessCommError();
        Close();
    } else {
#ifdef _DEBUG
        char errBuf[256];

        wsprintf(errBuf, "Error: CreateFile(%s, ...) = %08x\n", sz, GetLastError());
        OutputDebugString(errBuf);
#endif
    }

    return FALSE;
}

void C232Comm::Close()
{
    if (IsValid()) {
        CloseHandle(m_hCom);
        m_hCom = INVALID_HANDLE_VALUE;
    }
}

int C232Comm::rxCom(void* pData, int nLen)
{
    if (!ReadFile(m_hCom, pData, (DWORD)nLen, (LPDWORD)&nLen, (LPOVERLAPPED)NULL)) {
        locProcessCommError();
        return -1;
    }
    /* clean out any pending bytes in the receive buffer */
    // PurgeComm(m_hCom, PURGE_RXCLEAR);

    return nLen;
}

BOOL C232Comm::rxComLoop(void* pData, int nLen)
{
    while(nLen > 0) {
        int nRead = rxCom(pData, nLen);
	    if (nRead == -1)
            return FALSE;
        nLen -= nRead;
        pData = &((BYTE*)pData)[nRead];
    }
    gosASSERT(nLen == 0);

    return TRUE;
}

int C232Comm::txCom(const void* pData, int nLen)
{
    gosASSERT(IsValid());

    if (!WriteFile(m_hCom, pData, (DWORD)nLen, (LPDWORD)&nLen, NULL)) {
        locProcessCommError();
        return -1;
    }

    return nLen;
}

int C232Comm::txComLoop(const void* pData, int nLen)
{
    gosASSERT(IsValid());
    while(nLen > 0) {
        int nSent = txCom(pData, nLen);
	    if (nSent == -1)
            return FALSE;
        nLen -= nSent;
        pData = &((BYTE*)pData)[nSent];
    }
    gosASSERT(nLen == 0);

    return TRUE;
}

void C232Comm::locProcessCommError()
{
    gosASSERT(IsValid());
#ifdef _DEBUG
    char buf[512];
    wsprintf(buf, "Port=%d, ErrorCode=%08x\n", m_nPort, GetLastError());
#endif
    DWORD dwError;
    COMSTAT cs;
    /* clear error */
    ClearCommError(m_hCom, &dwError, &cs);
#ifdef _DEBUG
    OutputDebugString(buf);
#endif
}

int C232Comm::CommunicationConfig(HWND hWndParent)
{   
    if (IsValid()) {
        DWORD dwCC = sizeof(m_cc);
        m_cc.dwSize = dwCC;

        if (GetCommConfig(m_hCom, &m_cc, &dwCC)) {
            char sz[32];

            sprintf(sz, g_szPortFormat, m_nPort);
            if (CommConfigDialog(sz, hWndParent, &m_cc)) {
                if (SetCommState(m_hCom, &m_cc.dcb)) {
                    // write new settings 
                    return +1;
                }
                locProcessCommError();
                return 0;
            }
            locProcessCommError();
            return -1;
        } else {
            locProcessCommError();
            return -2;
        }
    } else {
         gosASSERT(!"error: C232Comm::Open() must be called before\n");
         return -3;
    }
}
