serialport.cpp
上传用户:hxj5298
上传日期:2007-01-03
资源大小:18k
文件大小:19k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2. Module : SERIALPORT.CPP
  3. Purpose: Implementation for an MFC wrapper class for serial ports
  4. Created: PJN / 31-05-1999
  5. History: PJN / 03-06-1999 1. Fixed problem with code using CancelIo which does not exist on 95.
  6.                           2. Fixed leaks which can occur in sample app when an exception is thrown
  7.          PJN / 16-06-1999 1. Fixed a bug whereby CString::ReleaseBuffer was not being called in 
  8.                              CSerialException::GetErrorMessage
  9.          PJN / 29-09-1999 1. Fixed a simple copy and paste bug in CSerialPort::SetDTR
  10. Copyright (c) 1999 by PJ Naughter.  
  11. All rights reserved.
  12. */
  13. /////////////////////////////////  Includes  //////////////////////////////////
  14. #include "stdafx.h"
  15. #include "serialport.h"
  16. #include "winerror.h"
  17. ///////////////////////////////// defines /////////////////////////////////////
  18. #ifdef _DEBUG
  19. #define new DEBUG_NEW
  20. #undef THIS_FILE
  21. static char THIS_FILE[] = __FILE__;
  22. #endif
  23. //////////////////////////////// Implementation ///////////////////////////////
  24. //Class which handles CancelIo function which must be constructed at run time
  25. //since it is not imeplemented on NT 3.51 or Windows 95. To avoid the loader
  26. //bringing up a message such as "Failed to load due to missing export...", the
  27. //function is constructed using GetProcAddress. The CSerialPort::CancelIo 
  28. //function then checks to see if the function pointer is NULL and if it is it 
  29. //throws an exception using the error code ERROR_CALL_NOT_IMPLEMENTED which
  30. //is what 95 would have done if it had implemented a stub for it in the first
  31. //place !!
  32. class _SERIAL_PORT_DATA
  33. {
  34. public:
  35. //Constructors /Destructors
  36.   _SERIAL_PORT_DATA();
  37.   ~_SERIAL_PORT_DATA();
  38.   HINSTANCE m_hKernel32;
  39.   typedef BOOL (CANCELIO)(HANDLE);
  40.   typedef CANCELIO* LPCANCELIO;
  41.   LPCANCELIO m_lpfnCancelIo;
  42. };
  43. _SERIAL_PORT_DATA::_SERIAL_PORT_DATA()
  44. {
  45.   m_hKernel32 = LoadLibrary(_T("KERNEL32.DLL"));
  46.   VERIFY(m_hKernel32 != NULL);
  47.   m_lpfnCancelIo = (LPCANCELIO) GetProcAddress(m_hKernel32, "CancelIo");
  48. }
  49. _SERIAL_PORT_DATA::~_SERIAL_PORT_DATA()
  50. {
  51.   FreeLibrary(m_hKernel32);
  52.   m_hKernel32 = NULL;
  53. }
  54. //The local variable which handle the function pointers
  55. _SERIAL_PORT_DATA _SerialPortData;
  56. ////////// Exception handling code
  57. void AfxThrowSerialException(DWORD dwError /* = 0 */)
  58. {
  59. if (dwError == 0)
  60. dwError = ::GetLastError();
  61. CSerialException* pException = new CSerialException(dwError);
  62. TRACE(_T("Warning: throwing CSerialException for error %dn"), dwError);
  63. THROW(pException);
  64. }
  65. BOOL CSerialException::GetErrorMessage(LPTSTR pstrError, UINT nMaxError, PUINT pnHelpContext)
  66. {
  67. ASSERT(pstrError != NULL && AfxIsValidString(pstrError, nMaxError));
  68. if (pnHelpContext != NULL)
  69. *pnHelpContext = 0;
  70. LPTSTR lpBuffer;
  71. BOOL bRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  72.                       NULL,  m_dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
  73.                       (LPTSTR) &lpBuffer, 0, NULL);
  74. if (bRet == FALSE)
  75. *pstrError = '';
  76. else
  77. {
  78. lstrcpyn(pstrError, lpBuffer, nMaxError);
  79. bRet = TRUE;
  80. LocalFree(lpBuffer);
  81. }
  82. return bRet;
  83. }
  84. CString CSerialException::GetErrorMessage()
  85. {
  86.   CString rVal;
  87.   LPTSTR pstrError = rVal.GetBuffer(4096);
  88.   GetErrorMessage(pstrError, 4096, NULL);
  89.   rVal.ReleaseBuffer();
  90.   return rVal;
  91. }
  92. CSerialException::CSerialException(DWORD dwError)
  93. {
  94. m_dwError = dwError;
  95. }
  96. CSerialException::~CSerialException()
  97. {
  98. }
  99. IMPLEMENT_DYNAMIC(CSerialException, CException)
  100. #ifdef _DEBUG
  101. void CSerialException::Dump(CDumpContext& dc) const
  102. {
  103. CObject::Dump(dc);
  104. dc << "m_dwError = " << m_dwError;
  105. }
  106. #endif
  107. ////////// The actual serial port code
  108. CSerialPort::CSerialPort()
  109. {
  110.   m_hComm = INVALID_HANDLE_VALUE;
  111.   m_bOverlapped = FALSE;
  112. }
  113. CSerialPort::~CSerialPort()
  114. {
  115.   Close();
  116. }
  117. IMPLEMENT_DYNAMIC(CSerialPort, CObject)
  118. #ifdef _DEBUG
  119. void CSerialPort::Dump(CDumpContext& dc) const
  120. {
  121. CObject::Dump(dc);
  122. dc << _T("m_hComm = ") << m_hComm << _T("n");
  123.   dc << _T("m_bOverlapped = ") << m_bOverlapped;
  124. }
  125. #endif
  126. void CSerialPort::Open(int nPort, DWORD dwBaud, Parity parity, BYTE DataBits, StopBits stopbits, FlowControl fc, BOOL bOverlapped)
  127. {
  128.   //Validate our parameters
  129.   ASSERT(nPort>0 && nPort<=255);
  130.   //Call CreateFile to open up the comms port
  131.   CString sPort;
  132.   sPort.Format(_T("\\.\COM%d"), nPort);
  133.   m_hComm = CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, bOverlapped ? FILE_FLAG_OVERLAPPED : 0, NULL);
  134.   if (m_hComm == INVALID_HANDLE_VALUE)
  135.   {
  136.     TRACE(_T("Failed to open up the comms portn"));
  137.     AfxThrowSerialException();
  138.   }
  139.   
  140.   m_bOverlapped = bOverlapped;
  141.   //Get the current state prior to changing it
  142.   DCB dcb;
  143.   GetState(dcb);
  144.   //Setup the baud rate
  145.   dcb.BaudRate = dwBaud; 
  146.   //Setup the Parity
  147.   switch (parity)
  148.   {
  149.     case EvenParity:  dcb.Parity = EVENPARITY;  break;
  150.     case MarkParity:  dcb.Parity = MARKPARITY;  break;
  151.     case NoParity:    dcb.Parity = NOPARITY;    break;
  152.     case OddParity:   dcb.Parity = ODDPARITY;   break;
  153.     case SpaceParity: dcb.Parity = SPACEPARITY; break;
  154.     default:          ASSERT(FALSE);            break;
  155.   }
  156.   //Setup the data bits
  157.   dcb.ByteSize = DataBits;
  158.   //Setup the stop bits
  159.   switch (stopbits)
  160.   {
  161.     case OneStopBit:           dcb.StopBits = ONESTOPBIT;   break;
  162.     case OnePointFiveStopBits: dcb.StopBits = ONE5STOPBITS; break;
  163.     case TwoStopBits:          dcb.StopBits = TWOSTOPBITS;  break;
  164.     default:                   ASSERT(FALSE);               break;
  165.   }
  166.   //Setup the flow control 
  167.   dcb.fDsrSensitivity = FALSE;
  168.   switch (fc)
  169.   {
  170.     case NoFlowControl:
  171.     {
  172.       dcb.fOutxCtsFlow = FALSE;
  173.       dcb.fOutxDsrFlow = FALSE;
  174.       dcb.fOutX = FALSE;
  175.       dcb.fInX = FALSE;
  176.       break;
  177.     }
  178.     case CtsRtsFlowControl:
  179.     {
  180.       dcb.fOutxCtsFlow = TRUE;
  181.       dcb.fOutxDsrFlow = FALSE;
  182.       dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
  183.       dcb.fOutX = FALSE;
  184.       dcb.fInX = FALSE;
  185.       break;
  186.     }
  187.     case CtsDtrFlowControl:
  188.     {
  189.       dcb.fOutxCtsFlow = TRUE;
  190.       dcb.fOutxDsrFlow = FALSE;
  191.       dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
  192.       dcb.fOutX = FALSE;
  193.       dcb.fInX = FALSE;
  194.       break;
  195.     }
  196.     case DsrRtsFlowControl:
  197.     {
  198.       dcb.fOutxCtsFlow = FALSE;
  199.       dcb.fOutxDsrFlow = TRUE;
  200.       dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
  201.       dcb.fOutX = FALSE;
  202.       dcb.fInX = FALSE;
  203.       break;
  204.     }
  205.     case DsrDtrFlowControl:
  206.     {
  207.       dcb.fOutxCtsFlow = FALSE;
  208.       dcb.fOutxDsrFlow = TRUE;
  209.       dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
  210.       dcb.fOutX = FALSE;
  211.       dcb.fInX = FALSE;
  212.       break;
  213.     }
  214.     case XonXoffFlowControl:
  215.     {
  216.       dcb.fOutxCtsFlow = FALSE;
  217.       dcb.fOutxDsrFlow = FALSE;
  218.       dcb.fOutX = TRUE;
  219.       dcb.fInX = TRUE;
  220.       dcb.XonChar = 0x11;
  221.       dcb.XoffChar = 0x13;
  222.       dcb.XoffLim = 100;
  223.       dcb.XonLim = 100;
  224.       break;
  225.     }
  226.     default:
  227.     {
  228.       ASSERT(FALSE);
  229.       break;
  230.     }
  231.   }
  232.   
  233.   //Now that we have all the settings in place, make the changes
  234.   SetState(dcb);
  235. }
  236. void CSerialPort::Close()
  237. {
  238.   if (IsOpen())
  239.   {
  240.     BOOL bSuccess = CloseHandle(m_hComm);
  241.     m_hComm = INVALID_HANDLE_VALUE;
  242.     if (!bSuccess)
  243.       TRACE(_T("Failed to close up the comms port, GetLastError:%dn"), GetLastError());
  244.     m_bOverlapped = FALSE;
  245.   }
  246. }
  247. void CSerialPort::Attach(HANDLE hComm)
  248. {
  249.   Close();
  250.   m_hComm = hComm;  
  251. }
  252. HANDLE CSerialPort::Detach()
  253. {
  254.   HANDLE hrVal = m_hComm;
  255.   m_hComm = INVALID_HANDLE_VALUE;
  256.   return hrVal;
  257. }
  258. DWORD CSerialPort::Read(void* lpBuf, DWORD dwCount)
  259. {
  260.   ASSERT(IsOpen());
  261.   ASSERT(!m_bOverlapped);
  262.   DWORD dwBytesRead = 0;
  263.   if (!ReadFile(m_hComm, lpBuf, dwCount, &dwBytesRead, NULL))
  264.   {
  265.     TRACE(_T("Failed in call to ReadFilen"));
  266.     AfxThrowSerialException();
  267.   }
  268.   return dwBytesRead;
  269. }
  270. BOOL CSerialPort::Read(void* lpBuf, DWORD dwCount, OVERLAPPED& overlapped)
  271. {
  272.   ASSERT(IsOpen());
  273.   ASSERT(m_bOverlapped);
  274.   ASSERT(overlapped.hEvent);
  275.   DWORD dwBytesRead = 0;
  276.   BOOL bSuccess = ReadFile(m_hComm, lpBuf, dwCount, &dwBytesRead, &overlapped);
  277.   if (!bSuccess)
  278.   {
  279.     if (GetLastError() != ERROR_IO_PENDING)
  280.     {
  281.       TRACE(_T("Failed in call to ReadFilen"));
  282.       AfxThrowSerialException();
  283.     }
  284.   }
  285.   return bSuccess;
  286. }
  287. DWORD CSerialPort::Write(const void* lpBuf, DWORD dwCount)
  288. {
  289.   ASSERT(IsOpen());
  290.   ASSERT(!m_bOverlapped);
  291.   DWORD dwBytesWritten = 0;
  292.   if (!WriteFile(m_hComm, lpBuf, dwCount, &dwBytesWritten, NULL))
  293.   {
  294.     TRACE(_T("Failed in call to WriteFilen"));
  295.     AfxThrowSerialException();
  296.   }
  297.   return dwBytesWritten;
  298. }
  299. BOOL CSerialPort::Write(const void* lpBuf, DWORD dwCount, OVERLAPPED& overlapped)
  300. {
  301.   ASSERT(IsOpen());
  302.   ASSERT(m_bOverlapped);
  303.   ASSERT(overlapped.hEvent);
  304.   DWORD dwBytesWritten = 0;
  305.   BOOL bSuccess = WriteFile(m_hComm, lpBuf, dwCount, &dwBytesWritten, &overlapped);
  306.   if (!bSuccess)
  307.   {
  308.     if (GetLastError() != ERROR_IO_PENDING)
  309.     {
  310.       TRACE(_T("Failed in call to WriteFilen"));
  311.       AfxThrowSerialException();
  312.     }
  313.   }
  314.   return bSuccess;
  315. }
  316. void CSerialPort::GetOverlappedResult(OVERLAPPED& overlapped, DWORD& dwBytesTransferred, BOOL bWait)
  317. {
  318.   ASSERT(IsOpen());
  319.   ASSERT(m_bOverlapped);
  320.   ASSERT(overlapped.hEvent);
  321.   DWORD dwBytesWritten = 0;
  322.   if (!::GetOverlappedResult(m_hComm, &overlapped, &dwBytesTransferred, bWait))
  323.   {
  324.     if (GetLastError() != ERROR_IO_PENDING)
  325.     {
  326.       TRACE(_T("Failed in call to GetOverlappedResultn"));
  327.       AfxThrowSerialException();
  328.     }
  329.   }
  330. }
  331. void CSerialPort::_OnCompletion(DWORD dwErrorCode, DWORD dwCount, LPOVERLAPPED lpOverlapped)
  332. {
  333.   //Validate our parameters
  334.   ASSERT(lpOverlapped);
  335.   //Convert back to the C++ world
  336.   CSerialPort* pSerialPort = (CSerialPort*) lpOverlapped->hEvent;
  337.   ASSERT(pSerialPort->IsKindOf(RUNTIME_CLASS(CSerialPort)));
  338.   //Call the C++ function
  339.   pSerialPort->OnCompletion(dwErrorCode, dwCount, lpOverlapped);
  340. }
  341. void CSerialPort::OnCompletion(DWORD /*dwErrorCode*/, DWORD /*dwCount*/, LPOVERLAPPED lpOverlapped)
  342. {
  343.   //Just free up the memory which was previously allocated for the OVERLAPPED structure
  344.   delete lpOverlapped;
  345.   //Your derived classes can do something useful in OnCompletion, but don't forget to
  346.   //call CSerialPort::OnCompletion to ensure the memory is freed up
  347. }
  348. void CSerialPort::CancelIo()
  349. {
  350.   ASSERT(IsOpen());
  351.   if (_SerialPortData.m_lpfnCancelIo == NULL)
  352.   {
  353.     TRACE(_T("CancelIo function is not supported on this OS. You need to be running at least NT 4 or Win 98 to use this functionn"));
  354.     AfxThrowSerialException(ERROR_CALL_NOT_IMPLEMENTED);  
  355.   }
  356.   if (!::_SerialPortData.m_lpfnCancelIo(m_hComm))
  357.   {
  358.     TRACE(_T("Failed in call to CancelIOn"));
  359.     AfxThrowSerialException();
  360.   }
  361. }
  362. void CSerialPort::WriteEx(const void* lpBuf, DWORD dwCount)
  363. {
  364.   ASSERT(IsOpen());
  365.   OVERLAPPED* pOverlapped = new OVERLAPPED;
  366.   ZeroMemory(pOverlapped, sizeof(OVERLAPPED));
  367.   pOverlapped->hEvent = (HANDLE) this;
  368.   if (!WriteFileEx(m_hComm, lpBuf, dwCount, pOverlapped, _OnCompletion))
  369.   {
  370.     delete pOverlapped;
  371.     TRACE(_T("Failed in call to WriteFileExn"));
  372.     AfxThrowSerialException();
  373.   }
  374. }
  375. void CSerialPort::ReadEx(void* lpBuf, DWORD dwCount)
  376. {
  377.   ASSERT(IsOpen());
  378.   OVERLAPPED* pOverlapped = new OVERLAPPED;
  379.   ZeroMemory(pOverlapped, sizeof(OVERLAPPED));
  380.   pOverlapped->hEvent = (HANDLE) this;
  381.   if (!ReadFileEx(m_hComm, lpBuf, dwCount, pOverlapped, _OnCompletion))
  382.   {
  383.     delete pOverlapped;
  384.     TRACE(_T("Failed in call to ReadFileExn"));
  385.     AfxThrowSerialException();
  386.   }
  387. }
  388. void CSerialPort::TransmitChar(char cChar)
  389. {
  390.   ASSERT(IsOpen());
  391.   if (!TransmitCommChar(m_hComm, cChar))
  392.   {
  393.     TRACE(_T("Failed in call to TransmitCommCharn"));
  394.     AfxThrowSerialException();
  395.   }
  396. }
  397. void CSerialPort::GetConfig(COMMCONFIG& config)
  398. {
  399.   ASSERT(IsOpen());
  400.   DWORD dwSize = sizeof(COMMCONFIG);
  401.   if (!GetCommConfig(m_hComm, &config, &dwSize))
  402.   {
  403.     TRACE(_T("Failed in call to GetCommConfign"));
  404.     AfxThrowSerialException();
  405.   }
  406. }
  407. void CSerialPort::SetConfig(COMMCONFIG& config)
  408. {
  409.   ASSERT(IsOpen());
  410.   DWORD dwSize = sizeof(COMMCONFIG);
  411.   if (!SetCommConfig(m_hComm, &config, dwSize))
  412.   {
  413.     TRACE(_T("Failed in call to SetCommConfign"));
  414.     AfxThrowSerialException();
  415.   }
  416. }
  417. void CSerialPort::SetBreak()
  418. {
  419.   ASSERT(IsOpen());
  420.   if (!SetCommBreak(m_hComm))
  421.   {
  422.     TRACE(_T("Failed in call to SetCommBreakn"));
  423.     AfxThrowSerialException();
  424.   }
  425. }
  426. void CSerialPort::ClearBreak()
  427. {
  428.   ASSERT(IsOpen());
  429.   if (!ClearCommBreak(m_hComm))
  430.   {
  431.     TRACE(_T("Failed in call to SetCommBreakn"));
  432.     AfxThrowSerialException();
  433.   }
  434. }
  435. void CSerialPort::ClearError(DWORD& dwErrors)
  436. {
  437.   ASSERT(IsOpen());
  438.   if (!ClearCommError(m_hComm, &dwErrors, NULL))
  439.   {
  440.     TRACE(_T("Failed in call to ClearCommErrorn"));
  441.     AfxThrowSerialException();
  442.   }
  443. }
  444. void CSerialPort::GetDefaultConfig(int nPort, COMMCONFIG& config)
  445. {
  446.   //Validate our parameters
  447.   ASSERT(nPort>0 && nPort<=255);
  448.   //Create the device name as a string
  449.   CString sPort;
  450.   sPort.Format(_T("COM%d"), nPort);
  451.   DWORD dwSize = sizeof(COMMCONFIG);
  452.   if (!GetDefaultCommConfig(sPort, &config, &dwSize))
  453.   {
  454.     TRACE(_T("Failed in call to GetDefaultCommConfign"));
  455.     AfxThrowSerialException();
  456.   }
  457. }
  458. void CSerialPort::SetDefaultConfig(int nPort, COMMCONFIG& config)
  459. {
  460.   //Validate our parameters
  461.   ASSERT(nPort>0 && nPort<=255);
  462.   //Create the device name as a string
  463.   CString sPort;
  464.   sPort.Format(_T("COM%d"), nPort);
  465.   DWORD dwSize = sizeof(COMMCONFIG);
  466.   if (!SetDefaultCommConfig(sPort, &config, dwSize))
  467.   {
  468.     TRACE(_T("Failed in call to GetDefaultCommConfign"));
  469.     AfxThrowSerialException();
  470.   }
  471. }
  472. void CSerialPort::GetStatus(COMSTAT& stat)
  473. {
  474.   ASSERT(IsOpen());
  475.   DWORD dwErrors;
  476.   if (!ClearCommError(m_hComm, &dwErrors, &stat))
  477.   {
  478.     TRACE(_T("Failed in call to ClearCommErrorn"));
  479.     AfxThrowSerialException();
  480.   }
  481. }
  482. void CSerialPort::GetState(DCB& dcb)
  483. {
  484.   ASSERT(IsOpen());
  485.   if (!GetCommState(m_hComm, &dcb))
  486.   {
  487.     TRACE(_T("Failed in call to GetCommStaten"));
  488.     AfxThrowSerialException();
  489.   }
  490. }
  491. void CSerialPort::SetState(DCB& dcb)
  492. {
  493.   ASSERT(IsOpen());
  494.   if (!SetCommState(m_hComm, &dcb))
  495.   {
  496.     TRACE(_T("Failed in call to SetCommStaten"));
  497.     AfxThrowSerialException();
  498.   }
  499. }
  500. void CSerialPort::Escape(DWORD dwFunc)
  501. {
  502.   ASSERT(IsOpen());
  503.   if (!EscapeCommFunction(m_hComm, dwFunc))
  504.   {
  505.     TRACE(_T("Failed in call to EscapeCommFunctionn"));
  506.     AfxThrowSerialException();
  507.   }
  508. }
  509. void CSerialPort::ClearDTR()
  510. {
  511.   Escape(CLRDTR);
  512. }
  513. void CSerialPort::ClearRTS()
  514. {
  515.   Escape(CLRRTS);
  516. }
  517. void CSerialPort::SetDTR()
  518. {
  519.   Escape(SETDTR);
  520. }
  521. void CSerialPort::SetRTS()
  522. {
  523.   Escape(SETRTS);
  524. }
  525. void CSerialPort::SetXOFF()
  526. {
  527.   Escape(SETXOFF);
  528. }
  529. void CSerialPort::SetXON()
  530. {
  531.   Escape(SETXON);
  532. }
  533. void CSerialPort::GetProperties(COMMPROP& properties)
  534. {
  535.   ASSERT(IsOpen());
  536.   if (!GetCommProperties(m_hComm, &properties))
  537.   {
  538.     TRACE(_T("Failed in call to GetCommPropertiesn"));
  539.     AfxThrowSerialException();
  540.   }
  541. }
  542. void CSerialPort::GetModemStatus(DWORD& dwModemStatus)
  543. {
  544.   ASSERT(IsOpen());
  545.   if (!GetCommModemStatus(m_hComm, &dwModemStatus))
  546.   {
  547.     TRACE(_T("Failed in call to GetCommModemStatusn"));
  548.     AfxThrowSerialException();
  549.   }
  550. }
  551. void CSerialPort::SetMask(DWORD dwMask)
  552. {
  553.   ASSERT(IsOpen());
  554.   if (!SetCommMask(m_hComm, dwMask))
  555.   {
  556.     TRACE(_T("Failed in call to SetCommMaskn"));
  557.     AfxThrowSerialException();
  558.   }
  559. }
  560. void CSerialPort::GetMask(DWORD& dwMask)
  561. {
  562.   ASSERT(IsOpen());
  563.   if (!GetCommMask(m_hComm, &dwMask))
  564.   {
  565.     TRACE(_T("Failed in call to GetCommMaskn"));
  566.     AfxThrowSerialException();
  567.   }
  568. }
  569. void CSerialPort::Flush()
  570. {
  571.   ASSERT(IsOpen());
  572.   if (!FlushFileBuffers(m_hComm))
  573.   {
  574.     TRACE(_T("Failed in call to FlushFileBuffersn"));
  575.     AfxThrowSerialException();
  576.   }
  577. }
  578. void CSerialPort::Purge(DWORD dwFlags)
  579. {
  580.   ASSERT(IsOpen());
  581.   if (!PurgeComm(m_hComm, dwFlags))
  582.   {
  583.     TRACE(_T("Failed in call to PurgeCommn"));
  584.     AfxThrowSerialException();
  585.   }
  586. }
  587. void CSerialPort::TerminateOutstandingWrites()
  588. {
  589.   Purge(PURGE_TXABORT);
  590. }
  591. void CSerialPort::TerminateOutstandingReads()
  592. {
  593.   Purge(PURGE_RXABORT);
  594. }
  595. void CSerialPort::ClearWriteBuffer()
  596. {
  597.   Purge(PURGE_TXCLEAR);
  598. }
  599. void CSerialPort::ClearReadBuffer()
  600. {
  601.   Purge(PURGE_RXCLEAR);
  602. }
  603. void CSerialPort::Setup(DWORD dwInQueue, DWORD dwOutQueue)
  604. {
  605.   ASSERT(IsOpen());
  606.   if (!SetupComm(m_hComm, dwInQueue, dwOutQueue))
  607.   {
  608.     TRACE(_T("Failed in call to SetupCommn"));
  609.     AfxThrowSerialException();
  610.   }
  611. }
  612. void CSerialPort::SetTimeouts(COMMTIMEOUTS& timeouts)
  613. {
  614.   ASSERT(IsOpen());
  615.   if (!SetCommTimeouts(m_hComm, &timeouts))
  616.   {
  617.     TRACE(_T("Failed in call to SetCommTimeoutsn"));
  618.     AfxThrowSerialException();
  619.   }
  620. }
  621. void CSerialPort::GetTimeouts(COMMTIMEOUTS& timeouts)
  622. {
  623.   ASSERT(IsOpen());
  624.   if (!GetCommTimeouts(m_hComm, &timeouts))
  625.   {
  626.     TRACE(_T("Failed in call to GetCommTimeoutsn"));
  627.     AfxThrowSerialException();
  628.   }
  629. }
  630. void CSerialPort::Set0Timeout()
  631. {
  632.   COMMTIMEOUTS Timeouts;
  633.   ZeroMemory(&Timeouts, sizeof(COMMTIMEOUTS));
  634.   Timeouts.ReadIntervalTimeout = MAXDWORD;
  635.   Timeouts.ReadTotalTimeoutMultiplier = 0;
  636.   Timeouts.ReadTotalTimeoutConstant = 0;
  637.   Timeouts.WriteTotalTimeoutMultiplier = 0;
  638.   Timeouts.WriteTotalTimeoutConstant = 0;
  639.   SetTimeouts(Timeouts);
  640. }
  641. void CSerialPort::Set0WriteTimeout()
  642. {
  643.   COMMTIMEOUTS Timeouts;
  644.   GetTimeouts(Timeouts);
  645.   Timeouts.WriteTotalTimeoutMultiplier = 0;
  646.   Timeouts.WriteTotalTimeoutConstant = 0;
  647.   SetTimeouts(Timeouts);
  648. }
  649. void CSerialPort::Set0ReadTimeout()
  650. {
  651.   COMMTIMEOUTS Timeouts;
  652.   GetTimeouts(Timeouts);
  653.   Timeouts.ReadIntervalTimeout = MAXDWORD;
  654.   Timeouts.ReadTotalTimeoutMultiplier = 0;
  655.   Timeouts.ReadTotalTimeoutConstant = 0;
  656.   SetTimeouts(Timeouts);
  657. }
  658. void CSerialPort::WaitEvent(DWORD& dwMask)
  659. {
  660.   ASSERT(IsOpen());
  661.   ASSERT(!m_bOverlapped);
  662.   if (!WaitCommEvent(m_hComm, &dwMask, NULL))
  663.   {
  664.     TRACE(_T("Failed in call to WaitCommEventn"));
  665.     AfxThrowSerialException();
  666.   }
  667. }
  668. void CSerialPort::WaitEvent(DWORD& dwMask, OVERLAPPED& overlapped)
  669. {
  670.   ASSERT(IsOpen());
  671.   ASSERT(m_bOverlapped);
  672.   ASSERT(overlapped.hEvent);
  673.   if (!WaitCommEvent(m_hComm, &dwMask, &overlapped))
  674.   {
  675.     if (GetLastError() != ERROR_IO_PENDING)
  676.     {
  677.       TRACE(_T("Failed in call to WaitCommEventn"));
  678.       AfxThrowSerialException();
  679.     }
  680.   }
  681. }