📄 irdaport.cpp
字号:
//////////////////////////////////////////////////////////////////////
//
// IRDA Port class, a class for IRDA support.
//
// Copyright (c) 2003, Strigl Daniel.
//
// License:
// --------
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this source code; if not, write to the Free
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
// MA 02111-1307 USA.
//
// Author: Strigl Daniel, http://www.hh-system.com/danielstrigl
//
//////////////////////////////////////////////////////////////////////
//
// IrdaPort.cpp: implementation of the CIrdaPort class
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "IrdaPort.h"
#include <atlconv.h>
//////////////////////////////////////////////////////////////////////
// CIrdaPort construction/destruction
//////////////////////////////////////////////////////////////////////
CIrdaPort::CIrdaPort()
{
m_hPort = INVALID_HANDLE_VALUE;
}
CIrdaPort::~CIrdaPort()
{
Close();
}
IMPLEMENT_DYNAMIC(CIrdaPort, CObject);
//////////////////////////////////////////////////////////////////////
// CIrdaPort diagnostics
//////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
void CIrdaPort::AssertValid() const
{
CObject::AssertValid();
}
void CIrdaPort::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << "m_hPort = " << m_hPort;
}
#endif // _DEBUG
//////////////////////////////////////////////////////////////////////
// CIrdaPort functions
//////////////////////////////////////////////////////////////////////
#if defined(UNDER_CE) // for Pocket PC application
UINT CIrdaPort::FindPortIndex()
{
// Look into the registry for the infrared port number
UINT uiPort = 0;
HKEY hKey = NULL;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Drivers\\BuiltIn\\IrDA"), 0, 0, &hKey) == ERROR_SUCCESS && hKey != NULL)
{
DWORD dwSize = 0;
if (RegQueryValueEx(hKey, _T("Index"), NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS)
{
if ((dwSize > 0) && (dwSize <= sizeof(DWORD)))
{
DWORD dwData = 0;
if (RegQueryValueEx(hKey, _T("Index"), NULL, NULL, (LPBYTE) &dwData, &dwSize) == ERROR_SUCCESS)
{
uiPort = (UINT) dwData;
}
}
}
RegCloseKey(hKey);
}
if (uiPort != 0)
return uiPort;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Comm\\IrDA"), 0, 0, &hKey) == ERROR_SUCCESS && hKey != NULL)
{
DWORD dwSize = 0;
if (RegQueryValueEx(hKey, _T("Port"), NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS)
{
if ((dwSize > 0) && (dwSize <= sizeof(DWORD)))
{
DWORD dwData = 0;
if (RegQueryValueEx(hKey, _T("Port"), NULL, NULL, (LPBYTE) &dwData, &dwSize) == ERROR_SUCCESS)
{
uiPort = (UINT) dwData;
}
}
}
RegCloseKey(hKey);
}
if (uiPort != 0)
return uiPort;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Comm\\IrDA\\Linkage"), 0, 0, &hKey) == ERROR_SUCCESS && hKey != NULL)
{
DWORD dwSize = 0;
if (RegQueryValueEx(hKey, _T("Bind"), NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS)
{
if ((dwSize >= sizeof(TCHAR)) && (dwSize % sizeof(TCHAR) == 0))
{
LPTSTR pszSubKey = new TCHAR[dwSize / sizeof(TCHAR) + 1];
if (RegQueryValueEx(hKey, _T("Bind"), NULL, NULL, (LPBYTE) pszSubKey, &dwSize) == ERROR_SUCCESS)
{
pszSubKey[dwSize / sizeof(TCHAR)] = _T('\0');
CString strSubKey;
strSubKey.Format(_T("Comm\\%s\\Parms"), pszSubKey);
// AfxMessageBox(strSubKey);
HKEY hNewKey = NULL;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, strSubKey, 0, 0, &hNewKey) == ERROR_SUCCESS && hNewKey != NULL)
{
dwSize = 0;
if (RegQueryValueEx(hNewKey, _T("Port"), NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS)
{
if ((dwSize > 0) && (dwSize <= sizeof(DWORD)))
{
DWORD dwData = 0;
if (RegQueryValueEx(hNewKey, _T("Port"), NULL, NULL, (LPBYTE) &dwData, &dwSize) == ERROR_SUCCESS)
{
uiPort = (UINT) dwData;
}
}
}
RegCloseKey(hNewKey);
}
}
delete [] pszSubKey;
}
}
RegCloseKey(hKey);
}
if (uiPort != 0)
return uiPort;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Drivers\\BuiltIn\\IrCOMM"), 0, 0, &hKey) == ERROR_SUCCESS && hKey != NULL)
{
DWORD dwSize = 0;
if (RegQueryValueEx(hKey, _T("Index"), NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS)
{
if ((dwSize > 0) && (dwSize <= sizeof(DWORD)))
{
DWORD dwData = 0;
if (RegQueryValueEx(hKey, _T("Index"), NULL, NULL, (LPBYTE) &dwData, &dwSize) == ERROR_SUCCESS)
{
uiPort = (UINT) dwData;
}
}
}
RegCloseKey(hKey);
}
return uiPort;
}
#endif // #if defined(UNDER_CE)
BOOL CIrdaPort::Open(UINT uiPort)
{
ASSERT(uiPort > 0 && uiPort <= 255);
Close();
// Open the IRDA port
CString strPort;
strPort.Format(_T("COM%d:"), uiPort);
m_hPort = CreateFile((LPCTSTR) strPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (m_hPort == INVALID_HANDLE_VALUE)
{
return FALSE;
}
// Set the size of the input and output buffer
VERIFY(SetupComm(m_hPort, 2048, 2048));
// Terminates all outstanding read and write operations and clear the buffers
VERIFY(PurgeComm(m_hPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR));
// Reinitializes all IRDA port settings
DCB dcb;
dcb.DCBlength = sizeof(DCB);
VERIFY(GetCommState(m_hPort, &dcb));
dcb.BaudRate = CBR_9600;
dcb.fBinary = TRUE;
dcb.fParity = TRUE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;
dcb.fTXContinueOnXoff = TRUE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fAbortOnError = FALSE;
// dcb.fDummy2
// dcb.wReserved
// dcb.XonLim
// dcb.XoffLim
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
// dcb.XonChar
// dcb.XoffChar
// dcb.ErrorChar
// dcb.EofChar
// dcb.EvtChar
// dcb.wReserved1
VERIFY(SetCommState(m_hPort, &dcb));
// Set the timeouts for all read and write operations
COMMTIMEOUTS timeouts;
VERIFY(GetCommTimeouts(m_hPort, &timeouts));
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 100;
timeouts.WriteTotalTimeoutConstant = 0;
VERIFY(SetCommTimeouts(m_hPort, &timeouts));
// Set the serial port to infrared (IR) mode
#if defined(UNDER_CE) // for Pocket PC application
EscapeCommFunction(m_hPort, SETIR);
#endif // #if defined(UNDER_CE)
return TRUE;
}
void CIrdaPort::Close()
{
// Close the IRDA port
if (IsOpen())
{
VERIFY(PurgeComm(m_hPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR));
#if defined(UNDER_CE) // for Pocket PC application
EscapeCommFunction(m_hPort, CLRIR);
#endif // #if defined(UNDER_CE)
VERIFY(CloseHandle(m_hPort));
m_hPort = INVALID_HANDLE_VALUE;
}
}
BOOL CIrdaPort::IsOpen() const
{
return m_hPort != INVALID_HANDLE_VALUE;
}
DWORD CIrdaPort::Read(void* pData, DWORD dwCount) const
{
ASSERT(IsOpen());
DWORD dwBytesRead = 0;
ReadFile(m_hPort, pData, dwCount, &dwBytesRead, NULL);
return dwBytesRead;
}
BOOL CIrdaPort::ReadWithTimeout(void* pData, DWORD dwCount, DWORD dwTimeout /*= 5000*/) const
{
ASSERT(pData);
ASSERT(dwCount > 0);
ASSERT(IsOpen());
DWORD n = 0;
DWORD dwStart = GetTickCount();
while (n < dwCount)
{
if ((GetTickCount() - dwStart) >= dwTimeout)
{
return FALSE;
}
DWORD dwRead = Read(static_cast<BYTE*>(pData) + n, sizeof(BYTE));
if (dwRead > 0)
{
dwStart = GetTickCount();
n += dwRead;
}
}
return TRUE;
}
DWORD CIrdaPort::Write(const void* pData, DWORD dwCount) const
{
ASSERT(IsOpen());
DWORD dwBytesWritten = 0;
WriteFile(m_hPort, pData, dwCount, &dwBytesWritten, NULL);
return dwBytesWritten;
}
BOOL CIrdaPort::WriteWithTimeout(const void* pData, DWORD dwCount, DWORD dwTimeout /*= 5000*/) const
{
ASSERT(pData);
ASSERT(dwCount > 0);
ASSERT(IsOpen());
DWORD n = 0;
DWORD dwStart = GetTickCount();
while (n < dwCount)
{
if ((GetTickCount() - dwStart) >= dwTimeout)
{
return FALSE;
}
DWORD dwWritten = Write(static_cast<const BYTE*>(pData) + n, sizeof(BYTE));
if (dwWritten > 0)
{
dwStart = GetTickCount();
n += dwWritten;
}
}
return TRUE;
}
BOOL CIrdaPort::WaitForResponse(CString& strResponse, DWORD dwTimeout /*= 5000*/) const
{
ASSERT(IsOpen());
BOOL bData = FALSE;
unsigned char cCurrentChar = '\0';
unsigned char cLastChar = '\0';
unsigned char cLastLastChar = '\0';
strResponse.Empty();
DWORD dwStartTicks = GetTickCount();
while (TRUE)
{
// Has the timeout occured?
if ((GetTickCount() - dwStartTicks) >= dwTimeout)
{
return FALSE;
}
// Receive the data from the serial port
if (Read(&cCurrentChar, sizeof(cCurrentChar)) > 0)
{
// Reset the idle timeout since data was received
dwStartTicks = GetTickCount();
if (isprint(cCurrentChar) && cLastLastChar == 0x0D && cLastChar == 0x0A && !bData)
{
bData = TRUE; // Received start sequence (<CR><LF>)
}
else if (isprint(cLastLastChar) && cLastChar == 0x0D && cCurrentChar == 0x0A && bData)
{
break; // Received end sequence (<CR><LF>)
}
// Add the character to the string
if (bData && isprint(cCurrentChar))
{
char szANSI[2] = { cCurrentChar, '\0' };
strResponse += CString(szANSI);
}
cLastLastChar = cLastChar;
cLastChar = cCurrentChar;
}
else
{
Sleep(10);
}
} // while (TRUE)
return TRUE;
}
BOOL CIrdaPort::Send(const CString& strSend, DWORD dwTimeout /*= 5000*/) const
{
ASSERT(IsOpen());
USES_CONVERSION; // Need for T2CA() macro
VERIFY(PurgeComm(m_hPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR));
CString str(strSend);
str += _T("\r"); // Add <CR> at the end of the string
return WriteWithTimeout(T2CA((LPCTSTR) str), str.GetLength(), dwTimeout);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -