📄 serialcommlayer.cpp
字号:
if ((*lpfdwEvtMask & EV_ERR) != 0)
{
#ifdef __RCC_DEBUG__
DisplayMessage("链接检测到错误");
#endif
// Which error was it?
if(!ClearCommError( hCommFile, &dwErrors, NULL))
{
dwLastError = GetLastError();
// Its possible for this error to occur if the
// service provider has closed the port. Time to end.
if(dwLastError == ERROR_INVALID_HANDLE)
return FALSE;
PostHangupCall();
return FALSE;
}
// Its possible that multiple errors occured and were handled
// in the last ClearCommError. Because all errors were signaled
// individually, but cleared all at once, pending comm events
// can yield EV_ERR while dwErrors equals 0. Ignore this event.
if(!ReceiveError( dwErrors ))
return FALSE;
}
dwModemEvent = 0;
if ((*lpfdwEvtMask & EV_RLSD) != 0)
{
dwModemEvent = MDM_CONN;
#ifdef __RCC_DEBUG__
DisplayMessage("链接检测到");
#endif
}
if ((*lpfdwEvtMask & EV_RING) != 0)
{
dwModemEvent = dwModemEvent | MDM_RING;
#ifdef __RCC_DEBUG__
DisplayMessage("检测到RING");
#endif
}
if( dwModemEvent != 0 )
{
if(!ModemStateChange( dwModemEvent ))
{
return FALSE;
}
}
if(((*lpfdwEvtMask & EV_ERR)==0) && (dwModemEvent==0))
{
// Should not have gotten here.
PostHangupCall();
}
return TRUE;
}
//
// FUNCTION: HandleReadEvent(LPOVERLAPPED, LPSTR, DWORD, LPDWORD)
//
// PURPOSE: Retrieves and handles data when there is data ready.
//
// PARAMETERS:
// lpOverlappedRead - address of overlapped structure to use.
// lpszInputBuffer - Buffer to place incoming bytes.
// dwSizeofBuffer - size of lpszInputBuffer.
// lpnNumberOfBytesRead - address of DWORD to place the number of read bytes.
//
// RETURN VALUE:
// TRUE if able to successfully retrieve and handle the available data.
// FALSE if unable to retrieve or handle the data.
//
// COMMENTS:
//
// This function is another helper function for the Read Thread. This
// is the function that is called when there is data available after
// an overlapped ReadFile has been setup. It retrieves the data and
// handles it.
//
//
BOOL CCommReadThread::HandleReadEvent(LPOVERLAPPED lpOverlappedRead,LPSTR lpszInputBuffer,
DWORD dwSizeOfBuffer,LPDWORD lpnNumberOfBytesRead)
{
DWORD dwLastError;
if (GetOverlappedResult( hCommFile,
lpOverlappedRead, lpnNumberOfBytesRead, TRUE ))
{
return HandleReadData( lpszInputBuffer, *lpnNumberOfBytesRead );
}
// Error in GetOverlappedResult; handle it.
dwLastError = GetLastError();
// if(dwLastError == ERROR_IO_INCOMPLETE)
// {
// return TRUE;
// }
// Its possible for this error to occur if the
// service provider has closed the port. Time to end.
if(dwLastError == ERROR_INVALID_HANDLE)
{
return FALSE;
}
// Unexpected error come here. No idea what could cause this to happen.
PostHangupCall();
return TRUE;
}
//
// FUNCTION: HandleReadData(LPCSTR, DWORD)
//
// PURPOSE: Deals with data after its been read from the comm file.
//
// PARAMETERS:
// lpszInputBuffer - Buffer to place incoming bytes.
// dwSizeofBuffer - size of lpszInputBuffer.
//
// RETURN VALUE:
// TRUE if able to successfully handle the data.
// FALSE if unable to allocate memory or handle the data.
//
// COMMENTS:
//
// This function is yet another helper function for the Read Thread.
// It LocalAlloc()s a buffer, copies the new data to this buffer and
// calls PostWriteToDisplayCtl to let the EditCtls module deal with
// the data. Its assumed that PostWriteToDisplayCtl posts the message
// rather than dealing with it right away so that the Read Thread
// is free to get right back to waiting for data. Its also assumed
// that the EditCtls module is responsible for LocalFree()ing the
// pointer that is passed on.
//
//
BOOL CCommReadThread::HandleReadData(LPCSTR lpszInputBuffer,DWORD dwSizeOfBuffer)
{
LPSTR lpszPostedBytes;
// If we got data and didn't just time out empty...
if( dwSizeOfBuffer != 0)
{
// Do something with the bytes read.
lpszPostedBytes = new char[dwSizeOfBuffer+1];
if (lpszPostedBytes == NULL)
{
// Out of memory
PostHangupCall();
}
memcpy((void *)lpszPostedBytes,lpszInputBuffer,dwSizeOfBuffer );
lpszPostedBytes[dwSizeOfBuffer] = 0;
return ReceiveData( lpszPostedBytes, dwSizeOfBuffer );
}
return FALSE;
}
BOOL CCommReadThread::ReceiveData(LPSTR lpNewString,DWORD dwSizeOfNewString)
{
if(!PostMessage( hComm32Window, PWM_GOTCOMMDATA,
WPARAM(dwSizeOfNewString), LPARAM(lpNewString) ))
{
PostHangupCall();
return FALSE;
}
return TRUE;
}
BOOL CCommReadThread::ReceiveError(DWORD EvtMask)
{
if(!PostMessage( hComm32Window, PWM_RECEIVEERROR, 0, LPARAM(EvtMask)))
{
PostHangupCall();
return FALSE;
}
return TRUE;
}
BOOL CCommReadThread::ModemStateChange(DWORD ModemEvent)
{
if(!PostMessage( hComm32Window, WM_RCCNOTIFY, MAKEWPARAM(RCC_BIN_STATE,0), LPARAM(ModemEvent)))
{
PostHangupCall();
return FALSE;
}
return TRUE;
}
void CCommReadThread::PostHangupCall(void)
{
PostMessage( hComm32Window, PWM_REQUESTHANGUP, 0, 0 );
}
//(******************************************************************************)
// WRITE THREAD
//(******************************************************************************)
//
// PROCEDURE: TWriteThread.Execute
//
// PURPOSE: The starting point for the Write thread.
//
// PARAMETERS:
// lpvParam - unused.
//
// RETURN VALUE:
// DWORD - unused.
//
// COMMENTS:
//
// The Write thread uses a PeekMessage loop to wait for a string to write,
// and when it gets one, it writes it to the Comm port. If the CloseEvent
// object is signaled, then it exits. The use of messages to tell the
// Write thread what to write provides a natural desynchronization between
// the UI and the Write thread.
//
//
int CCommWriteThread::Run()
{
// TODO: Add your specialized code here and/or call the base class
MSG msg;
DWORD dwHandleSignaled;
OVERLAPPED overlappedWrite;
BOOL CompleteOneWriteRequire;
// Needed for overlapped I/O.
memset( &overlappedWrite, sizeof(overlappedWrite), 0 );// {0, 0, 0, 0, NULL}
overlappedWrite.hEvent = CreateEvent( NULL, TRUE, TRUE, NULL );
if(overlappedWrite.hEvent == 0)
{
PostHangupCall();
goto EndWriteThread;
}
CompleteOneWriteRequire = TRUE;
// This is the main loop. Loop until we break out.
while(TRUE)
{
if(!PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
{
// If there are no messages pending, wait for a message or
// the CloseEvent.
SendDataEmpty = TRUE;
if(CompleteOneWriteRequire)
{
if(!PostMessage( hComm32Window, PWM_SENDDATAEMPTY, 0, 0 ))
{
PostHangupCall();
goto EndWriteThread;
}
}
CompleteOneWriteRequire = FALSE;
dwHandleSignaled = MsgWaitForMultipleObjects(1, &hCloseEvent, FALSE,
INFINITE, QS_ALLINPUT);
switch(dwHandleSignaled)
{
case WAIT_OBJECT_0: // CloseEvent signaled!
// Time to exit.
goto EndWriteThread;
case WAIT_OBJECT_0 + 1: // New message was received.
// Get the message that woke us up by looping again.
continue;
case WAIT_FAILED: // Wait failed. Shouldn't happen.
PostHangupCall();
goto EndWriteThread;
default:// This case should never occur.
PostHangupCall();
goto EndWriteThread;
}
}
// Make sure the CloseEvent isn't signaled while retrieving messages.
if(WaitForSingleObject(hCloseEvent,0) != WAIT_TIMEOUT)
goto EndWriteThread;
// Process the message.
// This could happen if a dialog is created on this thread.
// This doesn't occur in this sample, but might if modified.
if(msg.hwnd != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
// Handle the message.
switch(msg.message)
{
case PWM_COMMWRITE: // New string to write to Comm port.
// Write the string to the comm port. HandleWriteData
// does not return until the whole string has been written,
// an error occurs or until the CloseEvent is signaled.
if(!HandleWriteData( &overlappedWrite,
(LPSTR)msg.lParam, (DWORD)msg.wParam ))
{
// If it failed, either we got a signal to end or there
// really was a failure.
LocalFree( HLOCAL(msg.lParam) );
goto EndWriteThread;
}
CompleteOneWriteRequire = TRUE;
// Data was sent in a LocalAlloc()d buffer. Must free it.
LocalFree( HLOCAL(msg.lParam) );
break;
}
}//{main loop}
// Thats the end. Now clean up.
EndWriteThread:
PostHangupCall();
PurgeComm(hCommFile, PURGE_TXABORT | PURGE_TXCLEAR);
SendDataEmpty = TRUE;
CloseHandle(overlappedWrite.hEvent);
return 0; //CWinThread::Run();
}
//
// FUNCTION: HandleWriteData(LPOVERLAPPED, LPCSTR, DWORD)
//
// PURPOSE: Writes a given string to the comm file handle.
//
// PARAMETERS:
// lpOverlappedWrite - Overlapped structure to use in WriteFile
// pDataToWrite - String to write.
// dwNumberOfBytesToWrite - Length of String to write.
//
// RETURN VALUE:
// TRUE if all bytes were written. False if there was a failure to
// write the whole string.
//
// COMMENTS:
//
// This function is a helper function for the Write Thread. It
// is this call that actually writes a string to the comm file.
// Note that this call blocks and waits for the Write to complete
// or for the CloseEvent object to signal that the thread should end.
// Another possible reason for returning FALSE is if the comm port
// is closed by the service provider.
//
//
BOOL CCommWriteThread::HandleWriteData(LPOVERLAPPED lpOverlappedWrite,LPSTR pDataToWrite,
DWORD dwNumberOfBytesToWrite)
{
DWORD dwLastError,dwNumberOfBytesWritten,
dwWhereToStartWriting,dwHandleSignaled;
HANDLE HandlesToWaitFor[2];
dwNumberOfBytesWritten = 0;
dwWhereToStartWriting = 0; // Start at the beginning.
HandlesToWaitFor[0] = hCloseEvent;
HandlesToWaitFor[1] = lpOverlappedWrite->hEvent;
// Keep looping until all characters have been written.
do
{
// Start the overlapped I/O.
if(!WriteFile( hCommFile,
&(pDataToWrite[ dwWhereToStartWriting ]),
dwNumberOfBytesToWrite, &dwNumberOfBytesWritten,
lpOverlappedWrite ))
{
// WriteFile failed. Expected; lets handle it.
dwLastError = GetLastError();
// Its possible for this error to occur if the
// service provider has closed the port. Time to end.
if(dwLastError == ERROR_INVALID_HANDLE)
return FALSE;
// Unexpected error. No idea what.
if (dwLastError != ERROR_IO_PENDING)
{
PostHangupCall();
return FALSE;
}
// This is the expected ERROR_IO_PENDING case.
// Wait for either overlapped I/O completion,
// or for the CloseEvent to get signaled.
dwHandleSignaled = WaitForMultipleObjects(2, HandlesToWaitFor,
FALSE, INFINITE);
switch(dwHandleSignaled)
{
case WAIT_OBJECT_0: // CloseEvent signaled!
// Time to exit.
return FALSE;
case WAIT_OBJECT_0 + 1: // Wait finished.
// Time to get the results of the WriteFile
if(!GetOverlappedResult(hCommFile,
lpOverlappedWrite,
&dwNumberOfBytesWritten, TRUE))
{
dwLastError = GetLastError();
// Its possible for this error to occur if the
// service provider has closed the port.
if(dwLastError == ERROR_INVALID_HANDLE)
return FALSE;
// No idea what could cause another error.
PostHangupCall();
return FALSE;
}
break;
case WAIT_FAILED: // Wait failed. Shouldn't happen.
PostHangupCall();
return FALSE;
default:// This case should never occur.
PostHangupCall();
return FALSE;
}//end of case
}// end of WriteFile failure
// Some data was written. Make sure it all got written.
dwNumberOfBytesToWrite-= dwNumberOfBytesWritten;
dwWhereToStartWriting+= dwNumberOfBytesWritten;
}while(dwNumberOfBytesToWrite > 0); // Write the whole thing!
// }while(dwNumberOfBytesToWrite <= 0); // Write the whole thing!
// Wrote the whole string.
return TRUE;
}
void CCommWriteThread::PostHangupCall(void)
{
PostMessage( hComm32Window, PWM_REQUESTHANGUP, 0, 0 );
}
/////////////////////////////////////////////////////////////////////////////
// CRCCComm
CRCCComm::CRCCComm()
{
hCloseEvent = INVALID_HANDLE;
hCommFile = INVALID_HANDLE;
ReadThread = NULL;
WriteThread = NULL;
CommNo = 1;
RCCMode = MODE_MODEM;
Init();
}
CRCCComm::CRCCComm(int PortNo)
{
hCloseEvent = INVALID_HANDLE;
hCommFile = INVALID_HANDLE;
ReadThread = NULL;
WriteThread = NULL;
CommNo = PortNo;
RCCMode = MODE_MODEM;
Init();
}
void CRCCComm::SetPortNo(int PortNo)
{
if(RCCStatus == RCC_STAT_INIT)
{
CommNo = PortNo;
}
}
void CRCCComm::Init()
{
RCCStatus = RCC_STAT_INIT;
LastError = RCC_ERROR_SUCCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -