シリアルポートを扱うクラス (CSerialPort) [ATL]

(2007.05.16)
#pragma once
 
// WAC.com Class Liblary for Visual C++
// Copyright (C) WAC.com Inc. All rights reserved.
//
// This file is a part of the WAC.com Class Liblary.
// The use and distribution terms for this software are covered by the
// Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
// which can be found in the file CPL.TXT at the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by
// the terms of this license. You must not remove this notice, or
// any other, from this software.
 
// '07.04.09 : コードの整備 (sha)
// '07.05.16 : コードの整備 (sha)
 
#include <atlfile.h>
#include <atlutil.h>
 
 
////////////////////////////////////////////////////////////////////////////////
// CDCB
 
class CDCB : public DCB
{
protected:
    typedef CDCB                                thisClass;
 
public:
    CDCB()
    {
        ::ZeroMemory(this, sizeof(DCB));
        this->DCBlength = sizeof(DCB);
    }
    CDCB(LPCTSTR lpDef)
    {
        HRESULT hr = S_OK;
 
        ::ZeroMemory(this, sizeof(DCB));
        this->DCBlength = sizeof(DCB);
 
        hr = thisClass::Build(lpDef);
        if (FAILED(hr))
        {
            // 無視する。。
        }
    }
 
public:
    HRESULT Build(LPCTSTR lpDef)
    {
        BOOL br = ::BuildCommDCB(lpDef, this);
        if (!br)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        return S_OK;
    }
};
 
 
////////////////////////////////////////////////////////////////////////////////
// CSerialPort
 
class CSerialPort
{
protected:
    typedef CSerialPort                            thisClass;
 
public:
    CSerialPort()
    {
        m_bIsSupportDCB = true;
    }
    virtual ~CSerialPort()
    {
        HRESULT hr = S_OK;
 
        hr = this->Close();
        if (FAILED(hr))
        {
            // 無視する。。
        }
    }
 
public:
    bool IsOpen()
    {
        // NOTE: CAtlFileを使用しているのでINVALID_HANDLE_VALUEではなく
        // NULLと比較する必要がある(CHandleで管理されている)
        return (m_file.m_h != NULL);
    }
    bool IsSupportDCB()
    {
        return m_bIsSupportDCB;
    }
 
public:
    HRESULT Open(LPCTSTR szPortName, DWORD dwDesiredAccess = GENERIC_READ | GENERIC_WRITE)
    {
        HRESULT hr = S_OK;
 
        if (this->IsOpen())
        {
            // 既にオープンしている場合は、エラーとする
            return E_FAIL;
        }
 
        hr = m_file.Create(szPortName, dwDesiredAccess, 0, OPEN_EXISTING);
        if (FAILED(hr))
        {
            return hr;
        }
 
        CDCB dcb;
        hr = this->GetState(&dcb);
        if (FAILED(hr))
        {
            m_bIsSupportDCB = false;
            hr = S_FALSE;
        }
 
        return hr;
    }
    HRESULT Close()
    {
        if (!this->IsOpen())
        {
            return S_FALSE;
        }
 
        m_file.Close();
 
        return S_OK;
    }
 
public:
    HRESULT Read(LPBYTE pBuffer, DWORD dwNumberOfBytesToRead, DWORD* pdwNumberOfBytesToRead)
    {
        if (pBuffer == NULL)
        {
            return E_POINTER;
        }
        if (pdwNumberOfBytesToRead == NULL)
        {
            return E_POINTER;
        }
 
        HRESULT hr = S_OK;
 
        if (!this->IsOpen())
        {
            return E_FAIL;
        }
 
        *pdwNumberOfBytesToRead = 0;
 
        if (m_bIsSupportDCB)
        {
            // キューのバイト数を読み取る
            DWORD dwErrors = 0;
            COMSTAT stat = { 0 };
            hr = this->ClearError(&dwErrors, &stat);
            if (FAILED(hr))
            {
                return hr;
            }
 
            DWORD dwNumberOfReceived = stat.cbInQue;
            DWORD dwReadCount = dwNumberOfReceived;
            if (dwNumberOfReceived > dwNumberOfBytesToRead)
            {
                dwReadCount = dwNumberOfBytesToRead;
            }
 
            if (dwReadCount > 0)
            {
                hr = m_file.Read(pBuffer, dwReadCount);
                if (FAILED(hr))
                {
                    return hr;
                }
 
                *pdwNumberOfBytesToRead = dwReadCount;
            }
        }
        else
        {
            // キューのバイト数を読み取らない
            DWORD dwBytesRead = 0;
            hr = m_file.Read(pBuffer, dwNumberOfBytesToRead, dwBytesRead);
            if (FAILED(hr))
            {
                return hr;
            }
 
            if (dwBytesRead > 0)
            {
                *pdwNumberOfBytesToRead = dwNumberOfBytesToRead;
            }
        }
 
        return S_OK;
    }
    HRESULT Write(LPBYTE pBuffer, DWORD dwNumberOfBytesToWrite)
    {
        if (pBuffer == NULL)
        {
            return E_POINTER;
        }
 
        HRESULT hr = S_OK;
 
        if (!this->IsOpen())
        {
            return E_FAIL;
        }
 
        hr = m_file.Write(pBuffer, dwNumberOfBytesToWrite);
        if (FAILED(hr))
        {
            return hr;
        }
 
        return S_OK;
    }
 
public:
    HRESULT SetTimeouts(LPCOMMTIMEOUTS lpCommTimeouts)
    {
        if (!this->IsOpen())
        {
            return E_FAIL;
        }
 
        BOOL br = ::SetCommTimeouts(m_file, lpCommTimeouts);
        if (br == FALSE)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        return S_OK;
    }
    HRESULT GetState(LPDCB lpDCB)
    {
        if (!this->IsOpen())
        {
            return E_FAIL;
        }
 
        BOOL br = ::GetCommState(m_file, lpDCB);
        if (!br)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        return S_OK;
    }
    HRESULT SetState(LPDCB lpDCB)
    {
        if (!this->IsOpen())
        {
            return E_FAIL;
        }
 
        BOOL br = ::SetCommState(m_file, lpDCB);
        if (!br)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        return S_OK;
    }
    HRESULT Setup(DWORD dwInQueue, DWORD dwOutQueue)
    {
        if (!this->IsOpen())
        {
            return E_FAIL;
        }
 
        BOOL br = ::SetupComm(m_file, dwInQueue, dwOutQueue);
        if (!br)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        return S_OK;
    }
    HRESULT ClearError(LPDWORD lpErrors, LPCOMSTAT lpStat)
    {
        if (!this->IsOpen())
        {
            return E_FAIL;
        }
 
        BOOL br = ::ClearCommError(m_file, lpErrors, lpStat);
        if (!br)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        return S_OK;
    }
 
protected:
    CAtlFile m_file;
    bool m_bIsSupportDCB;
};
一覧に戻る
© 2003 WAC.com All Right Reserved.