#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;
};