📄 serial.cpp
字号:
OVERLAPPED ovInternal;
if (lpOverlapped == 0)
{
// Setup our own overlapped structure
memset(&ovInternal,0,sizeof(ovInternal));
ovInternal.hEvent = m_hevtOverlapped;
// Use our internal overlapped structure
lpOverlapped = &ovInternal;
}
// Make sure the overlapped structure isn't busy
_ASSERTE(HasOverlappedIoCompleted(lpOverlapped));
// Write the data
if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,lpOverlapped))
{
// Set the internal error code
long lLastError = ::GetLastError();
// Overlapped operation in progress is not an actual error
if (lLastError != ERROR_IO_PENDING)
{
// Save the error
m_lLastError = lLastError;
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::Write - Unable to write the data\n");
return m_lLastError;
}
// We need to block if the client didn't specify an overlapped structure
if (lpOverlapped == &ovInternal)
{
// Wait for the overlapped operation to complete
switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout))
{
case WAIT_OBJECT_0:
// The overlapped operation has completed
if (!::GetOverlappedResult(m_hFile,lpOverlapped,pdwWritten,FALSE))
{
// Set the internal error code
m_lLastError = ::GetLastError();
_RPTF0(_CRT_WARN,"CSerial::Write - Overlapped completed without result\n");
return m_lLastError;
}
break;
case WAIT_TIMEOUT:
// Cancel the I/O operation
CancelIo();
// The operation timed out. Set the internal error code and quit
m_lLastError = ERROR_TIMEOUT;
return m_lLastError;
default:
// Set the internal error code
m_lLastError = ::GetLastError();
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::Write - Unable to wait until data has been sent\n");
return m_lLastError;
}
}
}
else
{
// The operation completed immediatly. Just to be sure
// we'll set the overlapped structure's event handle.
::SetEvent(lpOverlapped->hEvent);
}
// Return successfully
return m_lLastError;
}
LONG CSerial::Write (LPCSTR pString, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout)
{
// Check if time-outs are supported
CheckTimeout(dwTimeout);
// Determine the length of the string
return Write(pString,strlen(pString),pdwWritten,lpOverlapped,dwTimeout);
}
LONG CSerial::Read (void* pData, size_t iLen, DWORD* pdwRead, LPOVERLAPPED lpOverlapped, DWORD dwTimeout)
{
// Check if time-outs are supported
CheckTimeout(dwTimeout);
// Overlapped operation should specify the pdwRead variable
_ASSERTE(!lpOverlapped || pdwRead);
// Reset error state
m_lLastError = ERROR_SUCCESS;
// Use our own variable for read count
DWORD dwRead;
if (pdwRead == 0)
{
pdwRead = &dwRead;
}
// Reset the number of bytes read
*pdwRead = 0;
// Check if the device is open
if (m_hFile == 0)
{
// Set the internal error code
m_lLastError = ERROR_INVALID_HANDLE;
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::Read - Device is not opened\n");
return m_lLastError;
}
// Wait for the event to happen
OVERLAPPED ovInternal;
if (lpOverlapped == 0)
{
// Setup our own overlapped structure
memset(&ovInternal,0,sizeof(ovInternal));
ovInternal.hEvent = m_hevtOverlapped;
// Use our internal overlapped structure
lpOverlapped = &ovInternal;
}
// Make sure the overlapped structure isn't busy
_ASSERTE(HasOverlappedIoCompleted(lpOverlapped));
#ifdef _DEBUG
// The debug version fills the entire data structure with
// 0xDC bytes, to catch buffer errors as soon as possible.
memset(pData,0xDC,iLen);
#endif
// Read the data
if (!::ReadFile(m_hFile,pData,iLen,pdwRead,lpOverlapped))
{
// Set the internal error code
long lLastError = ::GetLastError();
// Overlapped operation in progress is not an actual error
if (lLastError != ERROR_IO_PENDING)
{
// Save the error
m_lLastError = lLastError;
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::Read - Unable to read the data\n");
return m_lLastError;
}
// We need to block if the client didn't specify an overlapped structure
if (lpOverlapped == &ovInternal)
{
// Wait for the overlapped operation to complete
switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout))
{
case WAIT_OBJECT_0:
// The overlapped operation has completed
if (!::GetOverlappedResult(m_hFile,lpOverlapped,pdwRead,FALSE))
{
// Set the internal error code
m_lLastError = ::GetLastError();
_RPTF0(_CRT_WARN,"CSerial::Read - Overlapped completed without result\n");
return m_lLastError;
}
break;
case WAIT_TIMEOUT:
// Cancel the I/O operation
CancelIo();
// The operation timed out. Set the internal error code and quit
m_lLastError = ERROR_TIMEOUT;
return m_lLastError;
default:
// Set the internal error code
m_lLastError = ::GetLastError();
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::Read - Unable to wait until data has been read\n");
return m_lLastError;
}
}
}
else
{
// The operation completed immediatly. Just to be sure
// we'll set the overlapped structure's event handle.
::SetEvent(lpOverlapped->hEvent);
}
// Return successfully
return m_lLastError;
}
LONG CSerial::Purge()
{
// Reset error state
m_lLastError = ERROR_SUCCESS;
// Check if the device is open
if (m_hFile == 0)
{
// Set the internal error code
m_lLastError = ERROR_INVALID_HANDLE;
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::Purge - Device is not opened\n");
return m_lLastError;
}
if (!::PurgeComm(m_hFile, PURGE_TXCLEAR | PURGE_RXCLEAR))
{
// Set the internal error code
m_lLastError = ::GetLastError();
_RPTF0(_CRT_WARN,"CSerial::Purge - Overlapped completed without result\n");
}
// Return successfully
return m_lLastError;
}
LONG CSerial::Break (void)
{
// Reset error state
m_lLastError = ERROR_SUCCESS;
// Check if the device is open
if (m_hFile == 0)
{
// Set the internal error code
m_lLastError = ERROR_INVALID_HANDLE;
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::Break - Device is not opened\n");
return m_lLastError;
}
// Set the RS-232 port in break mode for a little while
::SetCommBreak(m_hFile);
::Sleep(100);
::ClearCommBreak(m_hFile);
// Return successfully
return m_lLastError;
}
CSerial::EEvent CSerial::GetEventType (void)
{
#ifdef _DEBUG
// Check if the event is within the mask
if ((m_eEvent & m_dwEventMask) == 0)
_RPTF2(_CRT_WARN,"CSerial::GetEventType - Event %08Xh not within mask %08Xh.\n", m_eEvent, m_dwEventMask);
#endif
// Obtain the event (mask unwanted events out)
EEvent eEvent = EEvent(m_eEvent & m_dwEventMask);
// Reset internal event type
m_eEvent = EEventNone;
// Return the current cause
return eEvent;
}
CSerial::EError CSerial::GetError (void)
{
// Reset error state
m_lLastError = ERROR_SUCCESS;
// Check if the device is open
if (m_hFile == 0)
{
// Set the internal error code
m_lLastError = ERROR_INVALID_HANDLE;
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::GetError - Device is not opened\n");
return EErrorUnknown;
}
// Obtain COM status
DWORD dwErrors = 0;
if (!::ClearCommError(m_hFile,&dwErrors,0))
{
// Set the internal error code
m_lLastError = ::GetLastError();
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::GetError - Unable to obtain COM status\n");
return EErrorUnknown;
}
// Return the error
return EError(dwErrors);
}
bool CSerial::GetCTS (void)
{
// Reset error state
m_lLastError = ERROR_SUCCESS;
// Obtain the modem status
DWORD dwModemStat = 0;
if (!::GetCommModemStatus(m_hFile,&dwModemStat))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::GetCTS - Unable to obtain the modem status\n");
return false;
}
// Determine if CTS is on
return (dwModemStat & MS_CTS_ON) != 0;
}
bool CSerial::GetDSR (void)
{
// Reset error state
m_lLastError = ERROR_SUCCESS;
// Obtain the modem status
DWORD dwModemStat = 0;
if (!::GetCommModemStatus(m_hFile,&dwModemStat))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::GetDSR - Unable to obtain the modem status\n");
return false;
}
// Determine if DSR is on
return (dwModemStat & MS_DSR_ON) != 0;
}
bool CSerial::GetRing (void)
{
// Reset error state
m_lLastError = ERROR_SUCCESS;
// Obtain the modem status
DWORD dwModemStat = 0;
if (!::GetCommModemStatus(m_hFile,&dwModemStat))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::GetRing - Unable to obtain the modem status");
return false;
}
// Determine if Ring is on
return (dwModemStat & MS_RING_ON) != 0;
}
bool CSerial::GetRLSD (void)
{
// Reset error state
m_lLastError = ERROR_SUCCESS;
// Obtain the modem status
DWORD dwModemStat = 0;
if (!::GetCommModemStatus(m_hFile,&dwModemStat))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::GetRLSD - Unable to obtain the modem status");
return false;
}
// Determine if RLSD is on
return (dwModemStat & MS_RLSD_ON) != 0;
}
#ifdef SERIAL_NO_CANCELIO
void CheckTimeout (DWORD dwTimeout)
{
if ((dwTimeout != 0) && (dwTimeout != INFINITE))
{
// Quit application
::MessageBox(0,_T("Timeouts are not supported, when SERIAL_WIN95_SUPPORT is defined"),_T("Serial library"), MB_ICONERROR | MB_TASKMODAL);
::DebugBreak();
::ExitProcess(0xFFFFFFF);
}
}
BOOL CSerial::CancelIo (void)
{
// CancelIo shouldn't have been called at this point
::DebugBreak();
return FALSE;
}
#endif // SERIAL_NO_CANCELIO
// --------------------------------------------------------
// Razne RS232 funkcije koje su naknadno dodate u klasu
// --------------------------------------------------------
void CSerial::TransmitChar(char cChar)
{
if ( IsOpen() ) {
if (!TransmitCommChar(m_hFile, cChar)) {
_RPTF0(_CRT_WARN,"CSerial::TransmitChar - Failed in call to TransmitCommChar\n");
}
}
}
void CSerial::Escape(DWORD dwFunc)
{
if ( IsOpen() ){
if (!EscapeCommFunction(m_hFile, dwFunc))
{
_RPTF0(_CRT_WARN,"CSerial::Escape - Failed in call to EscapeCommFunction\n");
}
}
}
void CSerial::ClearDTR(void)
{
Escape(CLRDTR);
}
void CSerial::ClearRTS(void)
{
Escape(CLRRTS);
}
void CSerial::SetDTR(void)
{
Escape(SETDTR);
}
void CSerial::SetRTS(void)
{
Escape(SETRTS);
}
void CSerial::SetXOFF(void)
{
Escape(SETXOFF);
}
void CSerial::SetXON(void)
{
Escape(SETXON);
}
void CSerial::SetBreak()
{
if (IsOpen()) {
if ( !SetCommBreak(m_hFile) ) {
_RPTF0(_CRT_WARN,"CSerial::SetBreak - Failed in call to SetCommBreak\n");
}
}
}
void CSerial::ClearBreak()
{
if (IsOpen()) {
if ( !ClearCommBreak(m_hFile) ) {
_RPTF0(_CRT_WARN,"CSerial::ClearBreak - Failed in call to ClearCommBreak\n");
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -