📄 serial.cpp
字号:
}
// Obtain the DCB structure for the device
CDCB dcb;
if (!::GetCommState(m_hFile,&dcb))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::GetBaudrate - Unable to obtain DCB information\n");
return EBaudUnknown;
}
// Return the appropriate baudrate
return EBaudrate(dcb.BaudRate);
}
CSerial::EDataBits CSerial::GetDataBits (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::GetDataBits - Device is not opened\n");
return EDataUnknown;
}
// Obtain the DCB structure for the device
CDCB dcb;
if (!::GetCommState(m_hFile,&dcb))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::GetDataBits - Unable to obtain DCB information\n");
return EDataUnknown;
}
// Return the appropriate bytesize
return EDataBits(dcb.ByteSize);
}
CSerial::EParity CSerial::GetParity (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::GetParity - Device is not opened\n");
return EParUnknown;
}
// Obtain the DCB structure for the device
CDCB dcb;
if (!::GetCommState(m_hFile,&dcb))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::GetParity - Unable to obtain DCB information\n");
return EParUnknown;
}
// Check if parity is used
if (!dcb.fParity)
{
// No parity
return EParNone;
}
// Return the appropriate parity setting
return EParity(dcb.Parity);
}
CSerial::EStopBits CSerial::GetStopBits (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::GetStopBits - Device is not opened\n");
return EStopUnknown;
}
// Obtain the DCB structure for the device
CDCB dcb;
if (!::GetCommState(m_hFile,&dcb))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::GetStopBits - Unable to obtain DCB information\n");
return EStopUnknown;
}
// Return the appropriate stopbits
return EStopBits(dcb.StopBits);
}
DWORD CSerial::GetEventMask (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::GetEventMask - Device is not opened\n");
return 0;
}
// Obtain the COM mask
DWORD dwMask = 0;
if (!::GetCommMask(m_hFile, &dwMask))
{
// Set the internal error code
m_lLastError = ::GetLastError();
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::GetEventMask - Unable to get the event mask\n");
return 0;
}
// Return the event mask
return dwMask;
}
BYTE CSerial::GetEventChar (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::GetEventChar - Device is not opened\n");
return 0;
}
// Obtain the DCB structure for the device
CDCB dcb;
if (!::GetCommState(m_hFile,&dcb))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::GetEventChar - Unable to obtain DCB information\n");
return 0;
}
// Set the new event character
return BYTE(dcb.EvtChar);
}
CSerial::EHandshake CSerial::GetHandshaking (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::GetHandshaking - Device is not opened\n");
return EHandshakeUnknown;
}
// Obtain the DCB structure for the device
CDCB dcb;
if (!::GetCommState(m_hFile,&dcb))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::GetHandshaking - Unable to obtain DCB information\n");
return EHandshakeUnknown;
}
// Check if hardware handshaking is being used
if ((dcb.fDtrControl == DTR_CONTROL_HANDSHAKE) && (dcb.fRtsControl == RTS_CONTROL_HANDSHAKE))
return EHandshakeHardware;
// Check if software handshaking is being used
if (dcb.fOutX && dcb.fInX)
return EHandshakeSoftware;
// No handshaking is being used
return EHandshakeOff;
}
LONG CSerial::Write (const void* pData, size_t iLen, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout)
{
// Overlapped operation should specify the pdwWritten variable
_ASSERTE(!lpOverlapped || pdwWritten);
// Reset error state
m_lLastError = ERROR_SUCCESS;
// Use our own variable for read count
DWORD dwWritten;
if (pdwWritten == 0)
{
pdwWritten = &dwWritten;
}
// Reset the number of bytes written
*pdwWritten = 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::Write - 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));
// 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(m_hFile);
// 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)
{
// 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)
{
// 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(m_hFile);
// 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::Flush()
{
// 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;
}
if (!::PurgeComm(m_hFile, PURGE_TXCLEAR | PURGE_RXCLEAR))
{
// Set the internal error code
m_lLastError = ::GetLastError();
_RPTF0(_CRT_WARN,"CSerial::Read - Overlapped completed without result\n");
}
// Return successfully
return m_lLastError;
}
CSerial::EEvent CSerial::GetEventType (void)
{
// Obtain the event
EEvent eEvent = m_eEvent;
// 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -