2009年12月28日 星期一

CuPort - Opens I/O device.

// Opens I/O device.
class CuDevice : public CuPort
{
public:
    CuDevice();
    virtual ~CuDevice();
    virtual void OnRead(BYTE *pByte, int nSize);

};


CuDevice g_device;
DCB g_dcb;

g_device.Open(L"COM2:");
g_device.SetupComm(1024 * 1024 * 2, 2 * 1024);
g_device.GetCommState(&g_dcb);
....
g_device.SetCommState (&g_dcb);

COMMTIMEOUTS CommTimeouts;
g_device.GetCommTimeouts ( &CommTimeouts);
....
g_device.SetCommTimeouts ( &CommTimeouts);
g_device.StardReadThread();


// CuPort.h

class CuPort  
{
    CuWinThread *m_pReadThread;
    
    HANDLE m_hFile;

    int m_nReadBufferSize;
    BYTE *m_pReadBuffer;

public:

    BOOL ClearCommError(LPDWORD lpErrors, LPCOMSTAT lpStat);
    BOOL SetCommTimeouts(LPCOMMTIMEOUTS lpCommTimeouts);
    BOOL GetCommTimeouts(LPCOMMTIMEOUTS lpCommTimeouts);
    BOOL GetCommState(LPDCB lpDCB);
    BOOL SetupComm(DWORD dwInQueue, DWORD dwOutQueue);
    BOOL SetCommState(LPDCB lpDCB);
    BOOL Open(LPCTSTR szComPort);
    BOOL Close(void);

    CuPort();
    virtual ~CuPort();
    virtual void OnRead(BYTE *pByte, int nSize){};
    virtual void OnWrite(BYTE *pByte, int nSize);

    BOOL StardReadThread();
    static DWORD ProcessReadThread(LPVOID lpVoid);

private:
    void ResizeReadBuffer();

};



// CuPort.cpp

CuPort::CuPort():
m_hFile(INVALID_HANDLE_VALUE)
,m_pReadThread(NULL)
,m_nReadBufferSize(1024)
,m_pReadBuffer(NULL)
{
    ResizeReadBuffer();
}

CuPort::~CuPort()
{
    delete [] m_pReadBuffer;
    Close();
}

BOOL CuPort::Close()
{

    BOOL bResult = FALSE;
    if( m_hFile != INVALID_HANDLE_VALUE )
        bResult = ::CloseHandle (m_hFile);
    m_hFile = INVALID_HANDLE_VALUE;

    if( m_pReadThread )
    {
        m_pReadThread->SuspendThread();
        m_pReadThread->Delete();
    }
    m_pReadThread = NULL;

    return bResult;

}

BOOL CuPort::Open(LPCTSTR szComPort)
{

    Close();

    m_hFile = ::CreateFile(szComPort, GENERIC_READ | GENERIC_WRITE,0, NULL, OPEN_EXISTING, 0, NULL);
    
    return m_hFile == INVALID_HANDLE_VALUE ? FALSE : TRUE;
}

BOOL CuPort::SetCommState(LPDCB lpDCB)
{
    return ::SetCommState( m_hFile, lpDCB); 
}

BOOL CuPort::SetupComm(DWORD dwInQueue, DWORD dwOutQueue)
{
    return ::SetupComm( m_hFile, dwInQueue, dwOutQueue); 
}

BOOL CuPort::GetCommState(LPDCB lpDCB)
{
    return ::GetCommState (m_hFile, lpDCB);
}

BOOL CuPort::GetCommTimeouts(LPCOMMTIMEOUTS lpCommTimeouts)
{
    return ::GetCommTimeouts(m_hFile, lpCommTimeouts);
}

BOOL CuPort::SetCommTimeouts(LPCOMMTIMEOUTS lpCommTimeouts)
{
    return ::SetCommTimeouts(m_hFile, lpCommTimeouts);
}

BOOL CuPort::ClearCommError(LPDWORD lpErrors, LPCOMSTAT lpStat)
{
    return ::ClearCommError(m_hFile, lpErrors, lpStat );
}

BOOL CuPort::StardReadThread()
{
    m_pReadThread = _BeginThread((_THREADPROC)CuPort::ProcessReadThread, (LPVOID)this);
    return m_pReadThread == NULL ? FALSE : TRUE;
}

void CuPort::OnWrite(BYTE *pByte, int nSize)
{

    if( m_hFile == INVALID_HANDLE_VALUE )
        return;

    DWORD dBytes = 0;

    BYTE *pByteIndex = pByte;

    while( nSize )
    {
        ::WriteFile(m_hFile, pByteIndex, nSize, &dBytes, 0);
        Sleep(1);
        pByteIndex += dBytes;
        nSize -= dBytes;
    }

}

DWORD CuPort::ProcessReadThread(LPVOID lpVoid)
{
    CuPort *pPort = static_cast<CuPort*>(lpVoid);

    static DWORD Errors;
    static COMSTAT ComStat;//COMSTAT;
    static DWORD dBytes = 0;

    while(1)
    {
        do
        {
            Sleep(1);
            ::ReadFile(pPort->m_hFile, pPort->m_pReadBuffer, pPort->m_nReadBufferSize, &dBytes , 0);
        }while( !dBytes );

        // 如果讀的跟預備的BUFFER 一樣大
        // 就把BUFFER 再加大一倍

        pPort->OnRead(pPort->m_pReadBuffer, dBytes );

        if( dBytes ==  pPort->m_nReadBufferSize )
            pPort->ResizeReadBuffer();
    }

    return 0;
}


void CuPort::ResizeReadBuffer()
{
    delete [] m_pReadBuffer;
    m_nReadBufferSize *= 2;
    m_pReadBuffer = new BYTE[m_nReadBufferSize];
}


2 則留言:

  1. 久久沒看這份程式碼, 忽然又有想法, 想在弄一個 CuPortFile, 將 Read Write跟串列埠分開.

    回覆刪除
  2. 使用時, 除了直接使用外, 也可以使用繼承覆載OnRead,

    回覆刪除