Advertisement
Guest User

Serial.cpp

a guest
Jun 16th, 2013
240
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 34.82 KB | None | 0 0
  1. // Serial.cpp - Implementation of the CSerial class
  2. //
  3. // Copyright (C) 1999-2003 Ramon de Klein ([email protected])
  4. //
  5. // This library is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU Lesser General Public
  7. // License as published by the Free Software Foundation; either
  8. // version 2.1 of the License, or (at your option) any later version.
  9. //
  10. // This library is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. // Lesser General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU Lesser General Public
  16. // License along with this library; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18.  
  19.  
  20. //////////////////////////////////////////////////////////////////////
  21. // Include the standard header files
  22.  
  23. #define STRICT
  24. #include <crtdbg.h>
  25. #include <tchar.h>
  26. #include <windows.h>
  27.  
  28.  
  29. //////////////////////////////////////////////////////////////////////
  30. // Include module headerfile
  31.  
  32. #include "Serial.h"
  33.  
  34.  
  35. //////////////////////////////////////////////////////////////////////
  36. // Disable warning C4127: conditional expression is constant, which
  37. // is generated when using the _RPTF and _ASSERTE macros.
  38.  
  39. #pragma warning(disable: 4127)
  40.  
  41.  
  42. //////////////////////////////////////////////////////////////////////
  43. // Enable debug memory manager
  44.  
  45. #ifdef _DEBUG
  46.  
  47. #ifdef THIS_FILE
  48. #undef THIS_FILE
  49. #endif
  50.  
  51. static const char THIS_FILE[] = __FILE__;
  52. #define new DEBUG_NEW
  53.  
  54. #endif
  55.  
  56.  
  57. //////////////////////////////////////////////////////////////////////
  58. // Helper methods
  59.  
  60. inline void CSerial::CheckRequirements (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) const
  61. {
  62. #ifdef SERIAL_NO_OVERLAPPED
  63.  
  64. // Check if an overlapped structure has been specified
  65. if (lpOverlapped || (dwTimeout != INFINITE))
  66. {
  67. // Quit application
  68. ::MessageBox(0,_T("Overlapped I/O and time-outs are not supported, when overlapped I/O is disabled."),_T("Serial library"), MB_ICONERROR | MB_TASKMODAL);
  69. ::DebugBreak();
  70. ::ExitProcess(0xFFFFFFF);
  71. }
  72.  
  73. #endif
  74.  
  75. #ifdef SERIAL_NO_CANCELIO
  76.  
  77. // Check if 0 or INFINITE time-out has been specified, because
  78. // the communication I/O cannot be cancelled.
  79. if ((dwTimeout != 0) && (dwTimeout != INFINITE))
  80. {
  81. // Quit application
  82. ::MessageBox(0,_T("Timeouts are not supported, when SERIAL_NO_CANCELIO is defined"),_T("Serial library"), MB_ICONERROR | MB_TASKMODAL);
  83. ::DebugBreak();
  84. ::ExitProcess(0xFFFFFFF);
  85. }
  86.  
  87. #endif // SERIAL_NO_CANCELIO
  88.  
  89. // Avoid warnings
  90. (void) dwTimeout;
  91. (void) lpOverlapped;
  92. }
  93.  
  94. inline BOOL CSerial::CancelCommIo (void)
  95. {
  96. #ifdef SERIAL_NO_CANCELIO
  97. // CancelIo shouldn't have been called at this point
  98. ::DebugBreak();
  99. return FALSE;
  100. #else
  101.  
  102. // Cancel the I/O request
  103. return ::CancelIo(m_hFile);
  104.  
  105. #endif // SERIAL_NO_CANCELIO
  106. }
  107.  
  108.  
  109. //////////////////////////////////////////////////////////////////////
  110. // Code
  111.  
  112. CSerial::CSerial ()
  113. : m_lLastError(ERROR_SUCCESS)
  114. , m_hFile(0)
  115. , m_eEvent(EEventNone)
  116. , m_dwEventMask(0)
  117. #ifndef SERIAL_NO_OVERLAPPED
  118. , m_hevtOverlapped(0)
  119. #endif
  120. {
  121. }
  122.  
  123. CSerial::~CSerial ()
  124. {
  125. // If the device is already closed,
  126. // then we don't need to do anything.
  127. if (m_hFile)
  128. {
  129. // Display a warning
  130. _RPTF0(_CRT_WARN,"CSerial::~CSerial - Serial port not closed\n");
  131.  
  132. // Close implicitly
  133. Close();
  134. }
  135. }
  136.  
  137. CSerial::EPort CSerial::CheckPort (LPCTSTR lpszDevice)
  138. {
  139. // Try to open the device
  140. HANDLE hFile = ::CreateFile(lpszDevice,
  141. GENERIC_READ|GENERIC_WRITE,
  142. 0,
  143. 0,
  144. OPEN_EXISTING,
  145. 0,
  146. 0);
  147.  
  148. // Check if we could open the device
  149. if (hFile == INVALID_HANDLE_VALUE)
  150. {
  151. // Display error
  152. switch (::GetLastError())
  153. {
  154. case ERROR_FILE_NOT_FOUND:
  155. // The specified COM-port does not exist
  156. return EPortNotAvailable;
  157.  
  158. case ERROR_ACCESS_DENIED:
  159. // The specified COM-port is in use
  160. return EPortInUse;
  161.  
  162. default:
  163. // Something else is wrong
  164. return EPortUnknownError;
  165. }
  166. }
  167.  
  168. // Close handle
  169. ::CloseHandle(hFile);
  170.  
  171. // Port is available
  172. return EPortAvailable;
  173. }
  174.  
  175. LONG CSerial::Open (LPCTSTR lpszDevice, DWORD dwInQueue, DWORD dwOutQueue, bool fOverlapped)
  176. {
  177. // Reset error state
  178. m_lLastError = ERROR_SUCCESS;
  179.  
  180. // Check if the port isn't already opened
  181. if (m_hFile)
  182. {
  183. m_lLastError = ERROR_ALREADY_INITIALIZED;
  184. _RPTF0(_CRT_WARN,"CSerial::Open - Port already opened\n");
  185. return m_lLastError;
  186. }
  187.  
  188. // Open the device
  189. m_hFile = ::CreateFile(lpszDevice,
  190. GENERIC_READ|GENERIC_WRITE,
  191. 0,
  192. 0,
  193. OPEN_EXISTING,
  194. fOverlapped?FILE_FLAG_OVERLAPPED:0,
  195. 0);
  196. if (m_hFile == INVALID_HANDLE_VALUE)
  197. {
  198. // Reset file handle
  199. m_hFile = 0;
  200.  
  201. // Display error
  202. m_lLastError = ::GetLastError();
  203. _RPTF0(_CRT_WARN, "CSerial::Open - Unable to open port\n");
  204. return m_lLastError;
  205. }
  206.  
  207. #ifndef SERIAL_NO_OVERLAPPED
  208. // We cannot have an event handle yet
  209. _ASSERTE(m_hevtOverlapped == 0);
  210.  
  211. // Create the event handle for internal overlapped operations (manual reset)
  212. if (fOverlapped)
  213. {
  214. m_hevtOverlapped = ::CreateEvent(0,true,false,0);
  215. if (m_hevtOverlapped == 0)
  216. {
  217. // Obtain the error information
  218. m_lLastError = ::GetLastError();
  219. _RPTF0(_CRT_WARN,"CSerial::Open - Unable to create event\n");
  220.  
  221. // Close the port
  222. ::CloseHandle(m_hFile);
  223. m_hFile = 0;
  224.  
  225. // Return the error
  226. return m_lLastError;
  227. }
  228. }
  229. #else
  230.  
  231. // Overlapped flag shouldn't be specified
  232. _ASSERTE(!fOverlapped);
  233.  
  234. #endif
  235.  
  236. // Setup the COM-port
  237. if (dwInQueue || dwOutQueue)
  238. {
  239. // Make sure the queue-sizes are reasonable sized. Win9X systems crash
  240. // if the input queue-size is zero. Both queues need to be at least
  241. // 16 bytes large.
  242. _ASSERTE(dwInQueue >= 16);
  243. _ASSERTE(dwOutQueue >= 16);
  244.  
  245. if (!::SetupComm(m_hFile,dwInQueue,dwOutQueue))
  246. {
  247. // Display a warning
  248. long lLastError = ::GetLastError();
  249. _RPTF0(_CRT_WARN,"CSerial::Open - Unable to setup the COM-port\n");
  250.  
  251. // Close the port
  252. Close();
  253.  
  254. // Save last error from SetupComm
  255. m_lLastError = lLastError;
  256. return m_lLastError;
  257. }
  258. }
  259.  
  260. // Setup the default communication mask
  261. SetMask();
  262.  
  263. // Non-blocking reads is default
  264. SetupReadTimeouts(EReadTimeoutNonblocking);
  265.  
  266. // Setup the device for default settings
  267. COMMCONFIG commConfig = {0};
  268. DWORD dwSize = sizeof(commConfig);
  269. commConfig.dwSize = dwSize;
  270. if (::GetDefaultCommConfig(lpszDevice,&commConfig,&dwSize))
  271. {
  272. // Set the default communication configuration
  273. if (!::SetCommConfig(m_hFile,&commConfig,dwSize))
  274. {
  275. // Display a warning
  276. _RPTF0(_CRT_WARN,"CSerial::Open - Unable to set default communication configuration.\n");
  277. }
  278. }
  279. else
  280. {
  281. // Display a warning
  282. _RPTF0(_CRT_WARN,"CSerial::Open - Unable to obtain default communication configuration.\n");
  283. }
  284.  
  285. // Return successful
  286. return m_lLastError;
  287. }
  288.  
  289. LONG CSerial::Close (void)
  290. {
  291. // Reset error state
  292. m_lLastError = ERROR_SUCCESS;
  293.  
  294. // If the device is already closed,
  295. // then we don't need to do anything.
  296. if (m_hFile == 0)
  297. {
  298. // Display a warning
  299. _RPTF0(_CRT_WARN,"CSerial::Close - Method called when device is not open\n");
  300. return m_lLastError;
  301. }
  302.  
  303. #ifndef SERIAL_NO_OVERLAPPED
  304. // Free event handle
  305. if (m_hevtOverlapped)
  306. {
  307. ::CloseHandle(m_hevtOverlapped);
  308. m_hevtOverlapped = 0;
  309. }
  310. #endif
  311.  
  312. // Close COM port
  313. ::CloseHandle(m_hFile);
  314. m_hFile = 0;
  315.  
  316. // Return successful
  317. return m_lLastError;
  318. }
  319.  
  320. LONG CSerial::Setup (EBaudrate eBaudrate, EDataBits eDataBits, EParity eParity, EStopBits eStopBits)
  321. {
  322. // Reset error state
  323. m_lLastError = ERROR_SUCCESS;
  324.  
  325. // Check if the device is open
  326. if (m_hFile == 0)
  327. {
  328. // Set the internal error code
  329. m_lLastError = ERROR_INVALID_HANDLE;
  330.  
  331. // Issue an error and quit
  332. _RPTF0(_CRT_WARN,"CSerial::Setup - Device is not opened\n");
  333. return m_lLastError;
  334. }
  335.  
  336. // Obtain the DCB structure for the device
  337. CDCB dcb;
  338. if (!::GetCommState(m_hFile,&dcb))
  339. {
  340. // Obtain the error code
  341. m_lLastError = :: GetLastError();
  342.  
  343. // Display a warning
  344. _RPTF0(_CRT_WARN,"CSerial::Setup - Unable to obtain DCB information\n");
  345. return m_lLastError;
  346. }
  347.  
  348. // Set the new data
  349. dcb.BaudRate = DWORD(eBaudrate);
  350. dcb.ByteSize = BYTE(eDataBits);
  351. dcb.Parity = BYTE(eParity);
  352. dcb.StopBits = BYTE(eStopBits);
  353.  
  354. // Determine if parity is used
  355. dcb.fParity = (eParity != EParNone);
  356.  
  357. // Set the new DCB structure
  358. if (!::SetCommState(m_hFile,&dcb))
  359. {
  360. // Obtain the error code
  361. m_lLastError = ::GetLastError();
  362.  
  363. // Display a warning
  364. _RPTF0(_CRT_WARN,"CSerial::Setup - Unable to set DCB information\n");
  365. return m_lLastError;
  366. }
  367.  
  368. // Return successful
  369. return m_lLastError;
  370. }
  371.  
  372. LONG CSerial::SetEventChar (BYTE bEventChar, bool fAdjustMask)
  373. {
  374. // Reset error state
  375. m_lLastError = ERROR_SUCCESS;
  376.  
  377. // Check if the device is open
  378. if (m_hFile == 0)
  379. {
  380. // Set the internal error code
  381. m_lLastError = ERROR_INVALID_HANDLE;
  382.  
  383. // Issue an error and quit
  384. _RPTF0(_CRT_WARN,"CSerial::SetEventChar - Device is not opened\n");
  385. return m_lLastError;
  386. }
  387.  
  388. // Obtain the DCB structure for the device
  389. CDCB dcb;
  390. if (!::GetCommState(m_hFile,&dcb))
  391. {
  392. // Obtain the error code
  393. m_lLastError = ::GetLastError();
  394.  
  395. // Display a warning
  396. _RPTF0(_CRT_WARN,"CSerial::SetEventChar - Unable to obtain DCB information\n");
  397. return m_lLastError;
  398. }
  399.  
  400. // Set the new event character
  401. dcb.EvtChar = char(bEventChar);
  402.  
  403. // Adjust the event mask, to make sure the event will be received
  404. if (fAdjustMask)
  405. {
  406. // Enable 'receive event character' event. Note that this
  407. // will generate an EEventNone if there is an asynchronous
  408. // WaitCommEvent pending.
  409. SetMask(GetEventMask() | EEventRcvEv);
  410. }
  411.  
  412. // Set the new DCB structure
  413. if (!::SetCommState(m_hFile,&dcb))
  414. {
  415. // Obtain the error code
  416. m_lLastError = ::GetLastError();
  417.  
  418. // Display a warning
  419. _RPTF0(_CRT_WARN,"CSerial::SetEventChar - Unable to set DCB information\n");
  420. return m_lLastError;
  421. }
  422.  
  423. // Return successful
  424. return m_lLastError;
  425. }
  426.  
  427. LONG CSerial::SetMask (DWORD dwEventMask)
  428. {
  429. // Reset error state
  430. m_lLastError = ERROR_SUCCESS;
  431.  
  432. // Check if the device is open
  433. if (m_hFile == 0)
  434. {
  435. // Set the internal error code
  436. m_lLastError = ERROR_INVALID_HANDLE;
  437.  
  438. // Issue an error and quit
  439. _RPTF0(_CRT_WARN,"CSerial::SetMask - Device is not opened\n");
  440. return m_lLastError;
  441. }
  442.  
  443. // Set the new mask. Note that this will generate an EEventNone
  444. // if there is an asynchronous WaitCommEvent pending.
  445. if (!::SetCommMask(m_hFile,dwEventMask))
  446. {
  447. // Obtain the error code
  448. m_lLastError = ::GetLastError();
  449.  
  450. // Display a warning
  451. _RPTF0(_CRT_WARN,"CSerial::SetMask - Unable to set event mask\n");
  452. return m_lLastError;
  453. }
  454.  
  455. // Save event mask and return successful
  456. m_dwEventMask = dwEventMask;
  457. return m_lLastError;
  458. }
  459.  
  460. LONG CSerial::WaitEvent (LPOVERLAPPED lpOverlapped, DWORD dwTimeout)
  461. {
  462. // Check if time-outs are supported
  463. CheckRequirements(lpOverlapped,dwTimeout);
  464.  
  465. // Reset error state
  466. m_lLastError = ERROR_SUCCESS;
  467.  
  468. // Check if the device is open
  469. if (m_hFile == 0)
  470. {
  471. // Set the internal error code
  472. m_lLastError = ERROR_INVALID_HANDLE;
  473.  
  474. // Issue an error and quit
  475. _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Device is not opened\n");
  476. return m_lLastError;
  477. }
  478.  
  479. #ifndef SERIAL_NO_OVERLAPPED
  480.  
  481. // Check if an overlapped structure has been specified
  482. if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE)))
  483. {
  484. // Set the internal error code
  485. m_lLastError = ERROR_INVALID_FUNCTION;
  486.  
  487. // Issue an error and quit
  488. _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Overlapped I/O is disabled, specified parameters are illegal.\n");
  489. return m_lLastError;
  490. }
  491.  
  492. // Wait for the event to happen
  493. OVERLAPPED ovInternal;
  494. if (!lpOverlapped && m_hevtOverlapped)
  495. {
  496. // Setup our own overlapped structure
  497. memset(&ovInternal,0,sizeof(ovInternal));
  498. ovInternal.hEvent = m_hevtOverlapped;
  499.  
  500. // Use our internal overlapped structure
  501. lpOverlapped = &ovInternal;
  502. }
  503.  
  504. // Make sure the overlapped structure isn't busy
  505. _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped));
  506.  
  507. // Wait for the COM event
  508. if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),lpOverlapped))
  509. {
  510. // Set the internal error code
  511. long lLastError = ::GetLastError();
  512.  
  513. // Overlapped operation in progress is not an actual error
  514. if (lLastError != ERROR_IO_PENDING)
  515. {
  516. // Save the error
  517. m_lLastError = lLastError;
  518.  
  519. // Issue an error and quit
  520. _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait for COM event\n");
  521. return m_lLastError;
  522. }
  523.  
  524. // We need to block if the client didn't specify an overlapped structure
  525. if (lpOverlapped == &ovInternal)
  526. {
  527. // Wait for the overlapped operation to complete
  528. switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout))
  529. {
  530. case WAIT_OBJECT_0:
  531. // The overlapped operation has completed
  532. break;
  533.  
  534. case WAIT_TIMEOUT:
  535. // Cancel the I/O operation
  536. CancelCommIo();
  537.  
  538. // The operation timed out. Set the internal error code and quit
  539. m_lLastError = ERROR_TIMEOUT;
  540. return m_lLastError;
  541.  
  542. default:
  543. // Set the internal error code
  544. m_lLastError = ::GetLastError();
  545.  
  546. // Issue an error and quit
  547. _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait until COM event has arrived\n");
  548. return m_lLastError;
  549. }
  550. }
  551. }
  552. else
  553. {
  554. // The operation completed immediatly. Just to be sure
  555. // we'll set the overlapped structure's event handle.
  556. if (lpOverlapped)
  557. ::SetEvent(lpOverlapped->hEvent);
  558. }
  559. #else
  560.  
  561. // Wait for the COM event
  562. if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),0))
  563. {
  564. // Set the internal error code
  565. m_lLastError = ::GetLastError();
  566.  
  567. // Issue an error and quit
  568. _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait for COM event\n");
  569. return m_lLastError;
  570. }
  571.  
  572. #endif
  573.  
  574. // Return successfully
  575. return m_lLastError;
  576. }
  577.  
  578.  
  579. LONG CSerial::SetupHandshaking (EHandshake eHandshake)
  580. {
  581. // Reset error state
  582. m_lLastError = ERROR_SUCCESS;
  583.  
  584. // Check if the device is open
  585. if (m_hFile == 0)
  586. {
  587. // Set the internal error code
  588. m_lLastError = ERROR_INVALID_HANDLE;
  589.  
  590. // Issue an error and quit
  591. _RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Device is not opened\n");
  592. return m_lLastError;
  593. }
  594.  
  595. // Obtain the DCB structure for the device
  596. CDCB dcb;
  597. if (!::GetCommState(m_hFile,&dcb))
  598. {
  599. // Obtain the error code
  600. m_lLastError = ::GetLastError();
  601.  
  602. // Display a warning
  603. _RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Unable to obtain DCB information\n");
  604. return m_lLastError;
  605. }
  606.  
  607. // Set the handshaking flags
  608. switch (eHandshake)
  609. {
  610. case EHandshakeOff:
  611. dcb.fOutxCtsFlow = false; // Disable CTS monitoring
  612. dcb.fOutxDsrFlow = false; // Disable DSR monitoring
  613. dcb.fDtrControl = DTR_CONTROL_DISABLE; // Disable DTR monitoring
  614. dcb.fOutX = false; // Disable XON/XOFF for transmission
  615. dcb.fInX = false; // Disable XON/XOFF for receiving
  616. dcb.fRtsControl = RTS_CONTROL_DISABLE; // Disable RTS (Ready To Send)
  617. break;
  618.  
  619. case EHandshakeHardware:
  620. dcb.fOutxCtsFlow = true; // Enable CTS monitoring
  621. dcb.fOutxDsrFlow = true; // Enable DSR monitoring
  622. dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; // Enable DTR handshaking
  623. dcb.fOutX = false; // Disable XON/XOFF for transmission
  624. dcb.fInX = false; // Disable XON/XOFF for receiving
  625. dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; // Enable RTS handshaking
  626. break;
  627.  
  628. case EHandshakeSoftware:
  629. dcb.fOutxCtsFlow = false; // Disable CTS (Clear To Send)
  630. dcb.fOutxDsrFlow = false; // Disable DSR (Data Set Ready)
  631. dcb.fDtrControl = DTR_CONTROL_DISABLE; // Disable DTR (Data Terminal Ready)
  632. dcb.fOutX = true; // Enable XON/XOFF for transmission
  633. dcb.fInX = true; // Enable XON/XOFF for receiving
  634. dcb.fRtsControl = RTS_CONTROL_DISABLE; // Disable RTS (Ready To Send)
  635. break;
  636.  
  637. default:
  638. // This shouldn't be possible
  639. _ASSERTE(false);
  640. m_lLastError = E_INVALIDARG;
  641. return m_lLastError;
  642. }
  643.  
  644. // Set the new DCB structure
  645. if (!::SetCommState(m_hFile,&dcb))
  646. {
  647. // Obtain the error code
  648. m_lLastError = ::GetLastError();
  649.  
  650. // Display a warning
  651. _RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Unable to set DCB information\n");
  652. return m_lLastError;
  653. }
  654.  
  655. // Return successful
  656. return m_lLastError;
  657. }
  658.  
  659. LONG CSerial::SetupReadTimeouts (EReadTimeout eReadTimeout)
  660. {
  661. // Reset error state
  662. m_lLastError = ERROR_SUCCESS;
  663.  
  664. // Check if the device is open
  665. if (m_hFile == 0)
  666. {
  667. // Set the internal error code
  668. m_lLastError = ERROR_INVALID_HANDLE;
  669.  
  670. // Issue an error and quit
  671. _RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Device is not opened\n");
  672. return m_lLastError;
  673. }
  674.  
  675. // Determine the time-outs
  676. COMMTIMEOUTS cto;
  677. if (!::GetCommTimeouts(m_hFile,&cto))
  678. {
  679. // Obtain the error code
  680. m_lLastError = ::GetLastError();
  681.  
  682. // Display a warning
  683. _RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Unable to obtain timeout information\n");
  684. return m_lLastError;
  685. }
  686.  
  687. // Set the new timeouts
  688. switch (eReadTimeout)
  689. {
  690. case EReadTimeoutBlocking:
  691. cto.ReadIntervalTimeout = 0;
  692. cto.ReadTotalTimeoutConstant = 0;
  693. cto.ReadTotalTimeoutMultiplier = 0;
  694. break;
  695. case EReadTimeoutNonblocking:
  696. cto.ReadIntervalTimeout = MAXDWORD;
  697. cto.ReadTotalTimeoutConstant = 0;
  698. cto.ReadTotalTimeoutMultiplier = 0;
  699. break;
  700. default:
  701. // This shouldn't be possible
  702. _ASSERTE(false);
  703. m_lLastError = E_INVALIDARG;
  704. return m_lLastError;
  705. }
  706.  
  707. // Set the new DCB structure
  708. if (!::SetCommTimeouts(m_hFile,&cto))
  709. {
  710. // Obtain the error code
  711. m_lLastError = ::GetLastError();
  712.  
  713. // Display a warning
  714. _RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Unable to set timeout information\n");
  715. return m_lLastError;
  716. }
  717.  
  718. // Return successful
  719. return m_lLastError;
  720. }
  721.  
  722. CSerial::EBaudrate CSerial::GetBaudrate (void)
  723. {
  724. // Reset error state
  725. m_lLastError = ERROR_SUCCESS;
  726.  
  727. // Check if the device is open
  728. if (m_hFile == 0)
  729. {
  730. // Set the internal error code
  731. m_lLastError = ERROR_INVALID_HANDLE;
  732.  
  733. // Issue an error and quit
  734. _RPTF0(_CRT_WARN,"CSerial::GetBaudrate - Device is not opened\n");
  735. return EBaudUnknown;
  736. }
  737.  
  738. // Obtain the DCB structure for the device
  739. CDCB dcb;
  740. if (!::GetCommState(m_hFile,&dcb))
  741. {
  742. // Obtain the error code
  743. m_lLastError = ::GetLastError();
  744.  
  745. // Display a warning
  746. _RPTF0(_CRT_WARN,"CSerial::GetBaudrate - Unable to obtain DCB information\n");
  747. return EBaudUnknown;
  748. }
  749.  
  750. // Return the appropriate baudrate
  751. return EBaudrate(dcb.BaudRate);
  752. }
  753.  
  754. CSerial::EDataBits CSerial::GetDataBits (void)
  755. {
  756. // Reset error state
  757. m_lLastError = ERROR_SUCCESS;
  758.  
  759. // Check if the device is open
  760. if (m_hFile == 0)
  761. {
  762. // Set the internal error code
  763. m_lLastError = ERROR_INVALID_HANDLE;
  764.  
  765. // Issue an error and quit
  766. _RPTF0(_CRT_WARN,"CSerial::GetDataBits - Device is not opened\n");
  767. return EDataUnknown;
  768. }
  769.  
  770. // Obtain the DCB structure for the device
  771. CDCB dcb;
  772. if (!::GetCommState(m_hFile,&dcb))
  773. {
  774. // Obtain the error code
  775. m_lLastError = ::GetLastError();
  776.  
  777. // Display a warning
  778. _RPTF0(_CRT_WARN,"CSerial::GetDataBits - Unable to obtain DCB information\n");
  779. return EDataUnknown;
  780. }
  781.  
  782. // Return the appropriate bytesize
  783. return EDataBits(dcb.ByteSize);
  784. }
  785.  
  786. CSerial::EParity CSerial::GetParity (void)
  787. {
  788. // Reset error state
  789. m_lLastError = ERROR_SUCCESS;
  790.  
  791. // Check if the device is open
  792. if (m_hFile == 0)
  793. {
  794. // Set the internal error code
  795. m_lLastError = ERROR_INVALID_HANDLE;
  796.  
  797. // Issue an error and quit
  798. _RPTF0(_CRT_WARN,"CSerial::GetParity - Device is not opened\n");
  799. return EParUnknown;
  800. }
  801.  
  802. // Obtain the DCB structure for the device
  803. CDCB dcb;
  804. if (!::GetCommState(m_hFile,&dcb))
  805. {
  806. // Obtain the error code
  807. m_lLastError = ::GetLastError();
  808.  
  809. // Display a warning
  810. _RPTF0(_CRT_WARN,"CSerial::GetParity - Unable to obtain DCB information\n");
  811. return EParUnknown;
  812. }
  813.  
  814. // Check if parity is used
  815. if (!dcb.fParity)
  816. {
  817. // No parity
  818. return EParNone;
  819. }
  820.  
  821. // Return the appropriate parity setting
  822. return EParity(dcb.Parity);
  823. }
  824.  
  825. CSerial::EStopBits CSerial::GetStopBits (void)
  826. {
  827. // Reset error state
  828. m_lLastError = ERROR_SUCCESS;
  829.  
  830. // Check if the device is open
  831. if (m_hFile == 0)
  832. {
  833. // Set the internal error code
  834. m_lLastError = ERROR_INVALID_HANDLE;
  835.  
  836. // Issue an error and quit
  837. _RPTF0(_CRT_WARN,"CSerial::GetStopBits - Device is not opened\n");
  838. return EStopUnknown;
  839. }
  840.  
  841. // Obtain the DCB structure for the device
  842. CDCB dcb;
  843. if (!::GetCommState(m_hFile,&dcb))
  844. {
  845. // Obtain the error code
  846. m_lLastError = ::GetLastError();
  847.  
  848. // Display a warning
  849. _RPTF0(_CRT_WARN,"CSerial::GetStopBits - Unable to obtain DCB information\n");
  850. return EStopUnknown;
  851. }
  852.  
  853. // Return the appropriate stopbits
  854. return EStopBits(dcb.StopBits);
  855. }
  856.  
  857. DWORD CSerial::GetEventMask (void)
  858. {
  859. // Reset error state
  860. m_lLastError = ERROR_SUCCESS;
  861.  
  862. // Check if the device is open
  863. if (m_hFile == 0)
  864. {
  865. // Set the internal error code
  866. m_lLastError = ERROR_INVALID_HANDLE;
  867.  
  868. // Issue an error and quit
  869. _RPTF0(_CRT_WARN,"CSerial::GetEventMask - Device is not opened\n");
  870. return 0;
  871. }
  872.  
  873. // Return the event mask
  874. return m_dwEventMask;
  875. }
  876.  
  877. BYTE CSerial::GetEventChar (void)
  878. {
  879. // Reset error state
  880. m_lLastError = ERROR_SUCCESS;
  881.  
  882. // Check if the device is open
  883. if (m_hFile == 0)
  884. {
  885. // Set the internal error code
  886. m_lLastError = ERROR_INVALID_HANDLE;
  887.  
  888. // Issue an error and quit
  889. _RPTF0(_CRT_WARN,"CSerial::GetEventChar - Device is not opened\n");
  890. return 0;
  891. }
  892.  
  893. // Obtain the DCB structure for the device
  894. CDCB dcb;
  895. if (!::GetCommState(m_hFile,&dcb))
  896. {
  897. // Obtain the error code
  898. m_lLastError = ::GetLastError();
  899.  
  900. // Display a warning
  901. _RPTF0(_CRT_WARN,"CSerial::GetEventChar - Unable to obtain DCB information\n");
  902. return 0;
  903. }
  904.  
  905. // Set the new event character
  906. return BYTE(dcb.EvtChar);
  907. }
  908.  
  909. CSerial::EHandshake CSerial::GetHandshaking (void)
  910. {
  911. // Reset error state
  912. m_lLastError = ERROR_SUCCESS;
  913.  
  914. // Check if the device is open
  915. if (m_hFile == 0)
  916. {
  917. // Set the internal error code
  918. m_lLastError = ERROR_INVALID_HANDLE;
  919.  
  920. // Issue an error and quit
  921. _RPTF0(_CRT_WARN,"CSerial::GetHandshaking - Device is not opened\n");
  922. return EHandshakeUnknown;
  923. }
  924.  
  925. // Obtain the DCB structure for the device
  926. CDCB dcb;
  927. if (!::GetCommState(m_hFile,&dcb))
  928. {
  929. // Obtain the error code
  930. m_lLastError = ::GetLastError();
  931.  
  932. // Display a warning
  933. _RPTF0(_CRT_WARN,"CSerial::GetHandshaking - Unable to obtain DCB information\n");
  934. return EHandshakeUnknown;
  935. }
  936.  
  937. // Check if hardware handshaking is being used
  938. if ((dcb.fDtrControl == DTR_CONTROL_HANDSHAKE) && (dcb.fRtsControl == RTS_CONTROL_HANDSHAKE))
  939. return EHandshakeHardware;
  940.  
  941. // Check if software handshaking is being used
  942. if (dcb.fOutX && dcb.fInX)
  943. return EHandshakeSoftware;
  944.  
  945. // No handshaking is being used
  946. return EHandshakeOff;
  947. }
  948.  
  949. LONG CSerial::Write (const void* pData, size_t iLen, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout)
  950. {
  951. // Check if time-outs are supported
  952. CheckRequirements(lpOverlapped,dwTimeout);
  953.  
  954. // Overlapped operation should specify the pdwWritten variable
  955. _ASSERTE(!lpOverlapped || pdwWritten);
  956.  
  957. // Reset error state
  958. m_lLastError = ERROR_SUCCESS;
  959.  
  960. // Use our own variable for read count
  961. DWORD dwWritten;
  962. if (pdwWritten == 0)
  963. {
  964. pdwWritten = &dwWritten;
  965. }
  966.  
  967. // Reset the number of bytes written
  968. *pdwWritten = 0;
  969.  
  970. // Check if the device is open
  971. if (m_hFile == 0)
  972. {
  973. // Set the internal error code
  974. m_lLastError = ERROR_INVALID_HANDLE;
  975.  
  976. // Issue an error and quit
  977. _RPTF0(_CRT_WARN,"CSerial::Write - Device is not opened\n");
  978. return m_lLastError;
  979. }
  980.  
  981. #ifndef SERIAL_NO_OVERLAPPED
  982.  
  983. // Check if an overlapped structure has been specified
  984. if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE)))
  985. {
  986. // Set the internal error code
  987. m_lLastError = ERROR_INVALID_FUNCTION;
  988.  
  989. // Issue an error and quit
  990. _RPTF0(_CRT_WARN,"CSerial::Write - Overlapped I/O is disabled, specified parameters are illegal.\n");
  991. return m_lLastError;
  992. }
  993.  
  994. // Wait for the event to happen
  995. OVERLAPPED ovInternal;
  996. if (!lpOverlapped && m_hevtOverlapped)
  997. {
  998. // Setup our own overlapped structure
  999. memset(&ovInternal,0,sizeof(ovInternal));
  1000. ovInternal.hEvent = m_hevtOverlapped;
  1001.  
  1002. // Use our internal overlapped structure
  1003. lpOverlapped = &ovInternal;
  1004. }
  1005.  
  1006. // Make sure the overlapped structure isn't busy
  1007. _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped));
  1008.  
  1009. // Write the data
  1010. if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,lpOverlapped))
  1011. {
  1012. // Set the internal error code
  1013. long lLastError = ::GetLastError();
  1014.  
  1015. // Overlapped operation in progress is not an actual error
  1016. if (lLastError != ERROR_IO_PENDING)
  1017. {
  1018. // Save the error
  1019. m_lLastError = lLastError;
  1020.  
  1021. // Issue an error and quit
  1022. _RPTF0(_CRT_WARN,"CSerial::Write - Unable to write the data\n");
  1023. return m_lLastError;
  1024. }
  1025.  
  1026. // We need to block if the client didn't specify an overlapped structure
  1027. if (lpOverlapped == &ovInternal)
  1028. {
  1029. // Wait for the overlapped operation to complete
  1030. switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout))
  1031. {
  1032. case WAIT_OBJECT_0:
  1033. // The overlapped operation has completed
  1034. if (!::GetOverlappedResult(m_hFile,lpOverlapped,pdwWritten,FALSE))
  1035. {
  1036. // Set the internal error code
  1037. m_lLastError = ::GetLastError();
  1038.  
  1039. _RPTF0(_CRT_WARN,"CSerial::Write - Overlapped completed without result\n");
  1040. return m_lLastError;
  1041. }
  1042. break;
  1043.  
  1044. case WAIT_TIMEOUT:
  1045. // Cancel the I/O operation
  1046. CancelCommIo();
  1047.  
  1048. // The operation timed out. Set the internal error code and quit
  1049. m_lLastError = ERROR_TIMEOUT;
  1050. return m_lLastError;
  1051.  
  1052. default:
  1053. // Set the internal error code
  1054. m_lLastError = ::GetLastError();
  1055.  
  1056. // Issue an error and quit
  1057. _RPTF0(_CRT_WARN,"CSerial::Write - Unable to wait until data has been sent\n");
  1058. return m_lLastError;
  1059. }
  1060. }
  1061. }
  1062. else
  1063. {
  1064. // The operation completed immediatly. Just to be sure
  1065. // we'll set the overlapped structure's event handle.
  1066. if (lpOverlapped)
  1067. ::SetEvent(lpOverlapped->hEvent);
  1068. }
  1069.  
  1070. #else
  1071.  
  1072. // Write the data
  1073. if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,0))
  1074. {
  1075. // Set the internal error code
  1076. m_lLastError = ::GetLastError();
  1077.  
  1078. // Issue an error and quit
  1079. _RPTF0(_CRT_WARN,"CSerial::Write - Unable to write the data\n");
  1080. return m_lLastError;
  1081. }
  1082.  
  1083. #endif
  1084.  
  1085. // Return successfully
  1086. return m_lLastError;
  1087. }
  1088.  
  1089. LONG CSerial::Write (LPCSTR pString, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout)
  1090. {
  1091. // Check if time-outs are supported
  1092. CheckRequirements(lpOverlapped,dwTimeout);
  1093.  
  1094. // Determine the length of the string
  1095. return Write(pString,strlen(pString),pdwWritten,lpOverlapped,dwTimeout);
  1096. }
  1097.  
  1098. LONG CSerial::Read (void* pData, size_t iLen, DWORD* pdwRead, LPOVERLAPPED lpOverlapped, DWORD dwTimeout)
  1099. {
  1100. // Check if time-outs are supported
  1101. CheckRequirements(lpOverlapped,dwTimeout);
  1102.  
  1103. // Overlapped operation should specify the pdwRead variable
  1104. _ASSERTE(!lpOverlapped || pdwRead);
  1105.  
  1106. // Reset error state
  1107. m_lLastError = ERROR_SUCCESS;
  1108.  
  1109. // Use our own variable for read count
  1110. DWORD dwRead;
  1111. if (pdwRead == 0)
  1112. {
  1113. pdwRead = &dwRead;
  1114. }
  1115.  
  1116. // Reset the number of bytes read
  1117. *pdwRead = 0;
  1118.  
  1119. // Check if the device is open
  1120. if (m_hFile == 0)
  1121. {
  1122. // Set the internal error code
  1123. m_lLastError = ERROR_INVALID_HANDLE;
  1124.  
  1125. // Issue an error and quit
  1126. _RPTF0(_CRT_WARN,"CSerial::Read - Device is not opened\n");
  1127. return m_lLastError;
  1128. }
  1129.  
  1130. #ifdef _DEBUG
  1131. // The debug version fills the entire data structure with
  1132. // 0xDC bytes, to catch buffer errors as soon as possible.
  1133. memset(pData,0xDC,iLen);
  1134. #endif
  1135.  
  1136. #ifndef SERIAL_NO_OVERLAPPED
  1137.  
  1138. // Check if an overlapped structure has been specified
  1139. if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE)))
  1140. {
  1141. // Set the internal error code
  1142. m_lLastError = ERROR_INVALID_FUNCTION;
  1143.  
  1144. // Issue an error and quit
  1145. _RPTF0(_CRT_WARN,"CSerial::Read - Overlapped I/O is disabled, specified parameters are illegal.\n");
  1146. return m_lLastError;
  1147. }
  1148.  
  1149. // Wait for the event to happen
  1150. OVERLAPPED ovInternal;
  1151. if (lpOverlapped == 0)
  1152. {
  1153. // Setup our own overlapped structure
  1154. memset(&ovInternal,0,sizeof(ovInternal));
  1155. ovInternal.hEvent = m_hevtOverlapped;
  1156.  
  1157. // Use our internal overlapped structure
  1158. lpOverlapped = &ovInternal;
  1159. }
  1160.  
  1161. // Make sure the overlapped structure isn't busy
  1162. _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped));
  1163.  
  1164. // Read the data
  1165. if (!::ReadFile(m_hFile,pData,iLen,pdwRead,lpOverlapped))
  1166. {
  1167. // Set the internal error code
  1168. long lLastError = ::GetLastError();
  1169.  
  1170. // Overlapped operation in progress is not an actual error
  1171. if (lLastError != ERROR_IO_PENDING)
  1172. {
  1173. // Save the error
  1174. m_lLastError = lLastError;
  1175.  
  1176. // Issue an error and quit
  1177. _RPTF0(_CRT_WARN,"CSerial::Read - Unable to read the data\n");
  1178. return m_lLastError;
  1179. }
  1180.  
  1181. // We need to block if the client didn't specify an overlapped structure
  1182. if (lpOverlapped == &ovInternal)
  1183. {
  1184. // Wait for the overlapped operation to complete
  1185. switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout))
  1186. {
  1187. case WAIT_OBJECT_0:
  1188. // The overlapped operation has completed
  1189. if (!::GetOverlappedResult(m_hFile,lpOverlapped,pdwRead,FALSE))
  1190. {
  1191. // Set the internal error code
  1192. m_lLastError = ::GetLastError();
  1193.  
  1194. _RPTF0(_CRT_WARN,"CSerial::Read - Overlapped completed without result\n");
  1195. return m_lLastError;
  1196. }
  1197. break;
  1198.  
  1199. case WAIT_TIMEOUT:
  1200. // Cancel the I/O operation
  1201. CancelCommIo();
  1202.  
  1203. // The operation timed out. Set the internal error code and quit
  1204. m_lLastError = ERROR_TIMEOUT;
  1205. return m_lLastError;
  1206.  
  1207. default:
  1208. // Set the internal error code
  1209. m_lLastError = ::GetLastError();
  1210.  
  1211. // Issue an error and quit
  1212. _RPTF0(_CRT_WARN,"CSerial::Read - Unable to wait until data has been read\n");
  1213. return m_lLastError;
  1214. }
  1215. }
  1216. }
  1217. else
  1218. {
  1219. // The operation completed immediatly. Just to be sure
  1220. // we'll set the overlapped structure's event handle.
  1221. if (lpOverlapped)
  1222. ::SetEvent(lpOverlapped->hEvent);
  1223. }
  1224.  
  1225. #else
  1226.  
  1227. // Read the data
  1228. if (!::ReadFile(m_hFile,pData,iLen,pdwRead,0))
  1229. {
  1230. // Set the internal error code
  1231. m_lLastError = ::GetLastError();
  1232.  
  1233. // Issue an error and quit
  1234. _RPTF0(_CRT_WARN,"CSerial::Read - Unable to read the data\n");
  1235. return m_lLastError;
  1236. }
  1237.  
  1238. #endif
  1239.  
  1240. // Return successfully
  1241. return m_lLastError;
  1242. }
  1243.  
  1244. LONG CSerial::Purge()
  1245. {
  1246. // Reset error state
  1247. m_lLastError = ERROR_SUCCESS;
  1248.  
  1249. // Check if the device is open
  1250. if (m_hFile == 0)
  1251. {
  1252. // Set the internal error code
  1253. m_lLastError = ERROR_INVALID_HANDLE;
  1254.  
  1255. // Issue an error and quit
  1256. _RPTF0(_CRT_WARN,"CSerial::Purge - Device is not opened\n");
  1257. return m_lLastError;
  1258. }
  1259.  
  1260. if (!::PurgeComm(m_hFile, PURGE_TXCLEAR | PURGE_RXCLEAR))
  1261. {
  1262. // Set the internal error code
  1263. m_lLastError = ::GetLastError();
  1264. _RPTF0(_CRT_WARN,"CSerial::Purge - Overlapped completed without result\n");
  1265. }
  1266.  
  1267. // Return successfully
  1268. return m_lLastError;
  1269. }
  1270.  
  1271. LONG CSerial::Break (void)
  1272. {
  1273. // Reset error state
  1274. m_lLastError = ERROR_SUCCESS;
  1275.  
  1276. // Check if the device is open
  1277. if (m_hFile == 0)
  1278. {
  1279. // Set the internal error code
  1280. m_lLastError = ERROR_INVALID_HANDLE;
  1281.  
  1282. // Issue an error and quit
  1283. _RPTF0(_CRT_WARN,"CSerial::Break - Device is not opened\n");
  1284. return m_lLastError;
  1285. }
  1286.  
  1287. // Set the RS-232 port in break mode for a little while
  1288. ::SetCommBreak(m_hFile);
  1289. ::Sleep(100);
  1290. ::ClearCommBreak(m_hFile);
  1291.  
  1292. // Return successfully
  1293. return m_lLastError;
  1294. }
  1295.  
  1296. CSerial::EEvent CSerial::GetEventType (void)
  1297. {
  1298. #ifdef _DEBUG
  1299. // Check if the event is within the mask
  1300. if ((m_eEvent & m_dwEventMask) == 0)
  1301. _RPTF2(_CRT_WARN,"CSerial::GetEventType - Event %08Xh not within mask %08Xh.\n", m_eEvent, m_dwEventMask);
  1302. #endif
  1303.  
  1304. // Obtain the event (mask unwanted events out)
  1305. EEvent eEvent = EEvent(m_eEvent & m_dwEventMask);
  1306.  
  1307. // Reset internal event type
  1308. m_eEvent = EEventNone;
  1309.  
  1310. // Return the current cause
  1311. return eEvent;
  1312. }
  1313.  
  1314. CSerial::EError CSerial::GetError (void)
  1315. {
  1316. // Reset error state
  1317. m_lLastError = ERROR_SUCCESS;
  1318.  
  1319. // Check if the device is open
  1320. if (m_hFile == 0)
  1321. {
  1322. // Set the internal error code
  1323. m_lLastError = ERROR_INVALID_HANDLE;
  1324.  
  1325. // Issue an error and quit
  1326. _RPTF0(_CRT_WARN,"CSerial::GetError - Device is not opened\n");
  1327. return EErrorUnknown;
  1328. }
  1329.  
  1330. // Obtain COM status
  1331. DWORD dwErrors = 0;
  1332. if (!::ClearCommError(m_hFile,&dwErrors,0))
  1333. {
  1334. // Set the internal error code
  1335. m_lLastError = ::GetLastError();
  1336.  
  1337. // Issue an error and quit
  1338. _RPTF0(_CRT_WARN,"CSerial::GetError - Unable to obtain COM status\n");
  1339. return EErrorUnknown;
  1340. }
  1341.  
  1342. // Return the error
  1343. return EError(dwErrors);
  1344. }
  1345.  
  1346. bool CSerial::GetCTS (void)
  1347. {
  1348. // Reset error state
  1349. m_lLastError = ERROR_SUCCESS;
  1350.  
  1351. // Obtain the modem status
  1352. DWORD dwModemStat = 0;
  1353. if (!::GetCommModemStatus(m_hFile,&dwModemStat))
  1354. {
  1355. // Obtain the error code
  1356. m_lLastError = ::GetLastError();
  1357.  
  1358. // Display a warning
  1359. _RPTF0(_CRT_WARN,"CSerial::GetCTS - Unable to obtain the modem status\n");
  1360. return false;
  1361. }
  1362.  
  1363. // Determine if CTS is on
  1364. return (dwModemStat & MS_CTS_ON) != 0;
  1365. }
  1366.  
  1367. bool CSerial::GetDSR (void)
  1368. {
  1369. // Reset error state
  1370. m_lLastError = ERROR_SUCCESS;
  1371.  
  1372. // Obtain the modem status
  1373. DWORD dwModemStat = 0;
  1374. if (!::GetCommModemStatus(m_hFile,&dwModemStat))
  1375. {
  1376. // Obtain the error code
  1377. m_lLastError = ::GetLastError();
  1378.  
  1379. // Display a warning
  1380. _RPTF0(_CRT_WARN,"CSerial::GetDSR - Unable to obtain the modem status\n");
  1381. return false;
  1382. }
  1383.  
  1384. // Determine if DSR is on
  1385. return (dwModemStat & MS_DSR_ON) != 0;
  1386. }
  1387.  
  1388. bool CSerial::GetRing (void)
  1389. {
  1390. // Reset error state
  1391. m_lLastError = ERROR_SUCCESS;
  1392.  
  1393. // Obtain the modem status
  1394. DWORD dwModemStat = 0;
  1395. if (!::GetCommModemStatus(m_hFile,&dwModemStat))
  1396. {
  1397. // Obtain the error code
  1398. m_lLastError = ::GetLastError();
  1399.  
  1400. // Display a warning
  1401. _RPTF0(_CRT_WARN,"CSerial::GetRing - Unable to obtain the modem status");
  1402. return false;
  1403. }
  1404.  
  1405. // Determine if Ring is on
  1406. return (dwModemStat & MS_RING_ON) != 0;
  1407. }
  1408.  
  1409. bool CSerial::GetRLSD (void)
  1410. {
  1411. // Reset error state
  1412. m_lLastError = ERROR_SUCCESS;
  1413.  
  1414. // Obtain the modem status
  1415. DWORD dwModemStat = 0;
  1416. if (!::GetCommModemStatus(m_hFile,&dwModemStat))
  1417. {
  1418. // Obtain the error code
  1419. m_lLastError = ::GetLastError();
  1420.  
  1421. // Display a warning
  1422. _RPTF0(_CRT_WARN,"CSerial::GetRLSD - Unable to obtain the modem status");
  1423. return false;
  1424. }
  1425.  
  1426. // Determine if RLSD is on
  1427. return (dwModemStat & MS_RLSD_ON) != 0;
  1428. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement