Non so cosa hai combinato col copia incolla ma l'originale sta così
Serial.h
// Serial.h - Definition of the CSerial class
//
// Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef __SERIAL_H
#define __SERIAL_H
//////////////////////////////////////////////////////////////////////
// The SERIAL_DEFAULT_OVERLAPPED defines if the default open mode uses
// overlapped I/O. When overlapped I/O is available (normal Win32
// platforms) it uses overlapped I/O. Windows CE doesn't allow the use
// of overlapped I/O, so it is disabled there by default.
#ifndef SERIAL_DEFAULT_OVERLAPPED
#ifndef SERIAL_NO_OVERLAPPED
#define SERIAL_DEFAULT_OVERLAPPED true
#else
#define SERIAL_DEFAULT_OVERLAPPED false
#endif
#endif
//////////////////////////////////////////////////////////////////////
//
// CSerial - Win32 wrapper for serial communications
//
// Serial communication often causes a lot of problems. This class
// tries to supply an easy to use interface to deal with serial
// devices.
//
// The class is actually pretty ease to use. You only need to open
// the COM-port, where you need to specify the basic serial
// communication parameters. You can also choose to setup handshaking
// and read timeout behaviour.
//
// The following serial classes are available:
//
// CSerial - Serial communication support.
// CSerialEx - Serial communication with listener thread for events
// CSerialSync - Serial communication with synchronized event handler
// CSerialWnd - Asynchronous serial support, which uses the Win32
// message queue for event notification.
// CSerialMFC - Preferred class to use in MFC-based GUI windows.
//
//
// Pros:
// -----
// - Easy to use (hides a lot of nasty Win32 stuff)
// - Fully ANSI and Unicode aware
//
// Cons:
// -----
// - Little less flexibility then native Win32 API, however you can
// use this API at the same time for features which are missing
// from this class.
// - Incompatible with Windows 95 or Windows NT v3.51 (or earlier),
// because CancelIo isn't support on these platforms. Define the
// SERIAL_NO_CANCELIO macro for support of these platforms as
// well. When this macro is defined, then only time-out values of
// 0 or INFINITE are valid.
//
//
// Copyright (C) 1999-2003 Ramon de Klein
// (Ramon.de.Klein@ict.nl)
class CSerial
{
// Class enumerations
public:
// Communication event
typedef enum
{
EEventUnknown = -1, // Unknown event
EEventNone = 0, // Event trigged without cause
EEventBreak = EV_BREAK, // A break was detected on input
EEventCTS = EV_CTS, // The CTS signal changed state
EEventDSR = EV_DSR, // The DSR signal changed state
EEventError = EV_ERR, // A line-status error occurred
EEventRing = EV_RING, // A ring indicator was detected
EEventRLSD = EV_RLSD, // The RLSD signal changed state
EEventRecv = EV_RXCHAR, // Data is received on input
EEventRcvEv = EV_RXFLAG, // Event character was received on input
EEventSend = EV_TXEMPTY, // Last character on output was sent
EEventPrinterError = EV_PERR, // Printer error occured
EEventRx80Full = EV_RX80FULL, // Receive buffer is 80 percent full
EEventProviderEvt1 = EV_EVENT1, // Provider specific event 1
EEventProviderEvt2 = EV_EVENT2, // Provider specific event 2
}
EEvent;
// Baudrate
typedef enum
{
EBaudUnknown = -1, // Unknown
EBaud110 = CBR_110, // 110 bits/sec
EBaud300 = CBR_300, // 300 bits/sec
EBaud600 = CBR_600, // 600 bits/sec
EBaud1200 = CBR_1200, // 1200 bits/sec
EBaud2400 = CBR_2400, // 2400 bits/sec
EBaud4800 = CBR_4800, // 4800 bits/sec
EBaud9600 = CBR_9600, // 9600 bits/sec
EBaud14400 = CBR_14400, // 14400 bits/sec
EBaud19200 = CBR_19200, // 19200 bits/sec (default)
EBaud38400 = CBR_38400, // 38400 bits/sec
EBaud56000 = CBR_56000, // 56000 bits/sec
EBaud57600 = CBR_57600, // 57600 bits/sec
EBaud115200 = CBR_115200, // 115200 bits/sec
EBaud128000 = CBR_128000, // 128000 bits/sec
EBaud256000 = CBR_256000, // 256000 bits/sec
}
EBaudrate;
// Data bits (5-8)
typedef enum
{
EDataUnknown = -1, // Unknown
EData5 = 5, // 5 bits per byte
EData6 = 6, // 6 bits per byte
EData7 = 7, // 7 bits per byte
EData8 = 8 // 8 bits per byte (default)
}
EDataBits;
// Parity scheme
typedef enum
{
EParUnknown = -1, // Unknown
EParNone = NOPARITY, // No parity (default)
EParOdd = ODDPARITY, // Odd parity
EParEven = EVENPARITY, // Even parity
EParMark = MARKPARITY, // Mark parity
EParSpace = SPACEPARITY // Space parity
}
EParity;
// Stop bits
typedef enum
{
EStopUnknown = -1, // Unknown
EStop1 = ONESTOPBIT, // 1 stopbit (default)
EStop1_5 = ONE5STOPBITS,// 1.5 stopbit
EStop2 = TWOSTOPBITS // 2 stopbits
}
EStopBits;
// Handshaking
typedef enum
{
EHandshakeUnknown = -1, // Unknown
EHandshakeOff = 0, // No handshaking
EHandshakeHardware = 1, // Hardware handshaking (RTS/CTS)
EHandshakeSoftware = 2 // Software handshaking (XON/XOFF)
}
EHandshake;
// Timeout settings
typedef enum
{
EReadTimeoutUnknown = -1, // Unknown
EReadTimeoutNonblocking = 0, // Always return immediately
EReadTimeoutBlocking = 1 // Block until everything is retrieved
}
EReadTimeout;
// Communication errors
typedef enum
{
EErrorUnknown = 0, // Unknown
EErrorBreak = CE_BREAK, // Break condition detected
EErrorFrame = CE_FRAME, // Framing error
EErrorIOE = CE_IOE, // I/O device error
EErrorMode = CE_MODE, // Unsupported mode
EErrorOverrun = CE_OVERRUN, // Character buffer overrun, next byte is lost
EErrorRxOver = CE_RXOVER, // Input buffer overflow, byte lost
EErrorParity = CE_RXPARITY,// Input parity error
EErrorTxFull = CE_TXFULL // Output buffer full
}
EError;
// Port availability
typedef enum
{
EPortUnknownError = -1, // Unknown error occurred
EPortAvailable = 0, // Port is available
EPortNotAvailable = 1, // Port is not present
EPortInUse = 2 // Port is in use
}
EPort;
// Construction
public:
CSerial();
virtual ~CSerial();
// Operations
public:
// Check if particular COM-port is available (static method).
static EPort CheckPort (LPCTSTR lpszDevice);
// Open the serial communications for a particular COM port. You
// need to use the full devicename (i.e. "COM1") to open the port.
// It's possible to specify the size of the input/output queues.
virtual LONG Open (LPCTSTR lpszDevice, DWORD dwInQueue = 0, DWORD dwOutQueue = 0, bool fOverlapped = SERIAL_DEFAULT_OVERLAPPED);
// Close the serial port.
virtual LONG Close ();
// Setup the communication settings such as baudrate, databits,
// parity and stopbits. The default settings are applied when the
// device has been opened. Call this function if these settings do
// not apply for your application. If you prefer to use integers
// instead of the enumerated types then just cast the integer to
// the required type. So the following two initializations are
// equivalent:
//
// Setup(EBaud9600,EData8,EParNone,EStop1)
//
// or
//
// Setup(EBaudrate(9600),EDataBits(8),EParity(NOPARITY),EStopBits(ONESTOPBIT))
//
// In the latter case, the types are not validated. So make sure
// that you specify the appropriate values.
virtual LONG Setup (EBaudrate eBaudrate = EBaud9600,
EDataBits eDataBits = EData8,
EParity eParity = EParNone,
EStopBits eStopBits = EStop1);
// Set/clear the event character. When this byte is being received
// on the serial port then the EEventRcvEv event is signalled,
// when the mask has been set appropriately. If the fAdjustMask flag
// has been set, then the event mask is automatically adjusted.
virtual LONG SetEventChar (BYTE bEventChar, bool fAdjustMask = true);
// Set the event mask, which indicates what events should be
// monitored. The WaitEvent method can only monitor events that
// have been enabled. The default setting only monitors the
// error events and data events. An application may choose to
// monitor CTS. DSR, RLSD, etc as well.
virtual LONG SetMask (DWORD dwMask = EEventBreak|EEventError|EEventRecv);
// The WaitEvent method waits for one of the events that are
// enabled (see SetMask).
virtual LONG WaitEvent (LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
// Setup the handshaking protocol. There are three forms of
// handshaking:
//
// 1) No handshaking, so data is always send even if the receiver
// cannot handle the data anymore. This can lead to data loss,
// when the sender is able to transmit data faster then the
// receiver can handle.
// 2) Hardware handshaking, where the RTS/CTS lines are used to
// indicate if data can be sent. This mode requires that both
// ports and the cable support hardware handshaking. Hardware
// handshaking is the most reliable and efficient form of
// handshaking available, but is hardware dependant.
// 3) Software handshaking, where the XON/XOFF characters are used
// to throttle the data. A major drawback of this method is that
// these characters cannot be used for data anymore.
virtual LONG SetupHandshaking (EHandshake eHandshake);
// Read operations can be blocking or non-blocking. You can use
// this method to setup wether to use blocking or non-blocking
// reads. Non-blocking reads is the default, which is required
// for most applications.
//
// 1) Blocking reads, which will cause the 'Read' method to block
// until the requested number of bytes have been read. This is
// useful if you know how many data you will receive.
// 2) Non-blocking reads, which will read as many bytes into your
// buffer and returns almost immediately. This is often the
// preferred setting.
virtual LONG SetupReadTimeouts (EReadTimeout eReadTimeout);
// Obtain communication settings
virtual EBaudrate GetBaudrate ();
virtual EDataBits GetDataBits ();
virtual EParity GetParity ();
virtual EStopBits GetStopBits ();
virtual EHandshake GetHandshaking ();
virtual DWORD GetEventMask ();
virtual BYTE GetEventChar ();
// Write data to the serial port. Note that we are only able to
// send ANSI strings, because it probably doesn't make sense to
// transmit Unicode strings to an application.
virtual LONG Write (const void* pData, size_t iLen, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
virtual LONG Write (LPCSTR pString, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
// Read data from the serial port. Refer to the description of
// the 'SetupReadTimeouts' for an explanation about (non) blocking
// reads and how to use this.
virtual LONG Read (void* pData, size_t iLen, DWORD* pdwRead = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE);
// Send a break
LONG Break ();
// Determine what caused the event to trigger
EEvent GetEventType ();
// Obtain the error
EError GetError ();
// Obtain the COMM and event handle
HANDLE GetCommHandle () { return m_hFile; }
// Check if com-port is opened
bool IsOpen () const { return (m_hFile != 0); }
// Obtain last error status
LONG GetLastError () const { return m_lLastError; }
// Obtain CTS/DSR/RING/RLSD settings
bool GetCTS ();
bool GetDSR ();
bool GetRing ();
bool GetRLSD ();
// Purge all buffers
LONG Purge ();
protected:
// Internal helper class which wraps DCB structure
class CDCB : public DCB
{
public:
CDCB() { DCBlength = sizeof(DCB); }
};
// Attributes
protected:
LONG m_lLastError; // Last serial error
HANDLE m_hFile; // File handle
EEvent m_eEvent; // Event type
DWORD m_dwEventMask; // Event mask
#ifndef SERIAL_NO_OVERLAPPED
HANDLE m_hevtOverlapped; // Event handle for internal overlapped operations
#endif
protected:
// Check the requirements
void CheckRequirements (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) const;
// CancelIo wrapper (for Win95 compatibility)
BOOL CancelCommIo ();
};
#endif // __SERIAL_H
Serial.cpp
// Serial.cpp - Implementation of the CSerial class
//
// Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//////////////////////////////////////////////////////////////////////
// Include the standard header files
#include "stdafx.h"
//////////////////////////////////////////////////////////////////////
// Include module headerfile
#include "Serial.h"
//////////////////////////////////////////////////////////////////////
// Disable warning C4127: conditional expression is constant, which
// is generated when using the _RPTF and _ASSERTE macros.
#pragma warning(disable: 4127)
//////////////////////////////////////////////////////////////////////
// Enable debug memory manager
#ifdef _DEBUG
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static const char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Helper methods
inline void CSerial::CheckRequirements (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) const
{
#ifdef SERIAL_NO_OVERLAPPED
// Check if an overlapped structure has been specified
if (lpOverlapped || (dwTimeout != INFINITE))
{
// Quit application
::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);
::DebugBreak();
::ExitProcess(0xFFFFFFF);
}
#endif
#ifdef SERIAL_NO_CANCELIO
// Check if 0 or INFINITE time-out has been specified, because
// the communication I/O cannot be cancelled.
if ((dwTimeout != 0) && (dwTimeout != INFINITE))
{
// Quit application
::MessageBox(0,_T("Timeouts are not supported, when SERIAL_NO_CANCELIO is defined"),_T("Serial library"), MB_ICONERROR | MB_TASKMODAL);
::DebugBreak();
::ExitProcess(0xFFFFFFF);
}
#endif // SERIAL_NO_CANCELIO
// Avoid warnings
(void) dwTimeout;
(void) lpOverlapped;
}
inline BOOL CSerial::CancelCommIo ()
{
#ifdef SERIAL_NO_CANCELIO
// CancelIo shouldn't have been called at this point
::DebugBreak();
return FALSE;
#else
// Cancel the I/O request
return ::CancelIo(m_hFile);
#endif // SERIAL_NO_CANCELIO
}
//////////////////////////////////////////////////////////////////////
// Code
CSerial::CSerial ()
: m_lLastError(ERROR_SUCCESS)
, m_hFile(0)
, m_eEvent(EEventNone)
, m_dwEventMask(0)
#ifndef SERIAL_NO_OVERLAPPED
, m_hevtOverlapped(0)
#endif
{
}
CSerial::~CSerial ()
{
// If the device is already closed,
// then we don't need to do anything.
if (m_hFile)
{
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::~CSerial - Serial port not closed\n");
// Close implicitly
Close();
}
}
CSerial::EPort CSerial::CheckPort (LPCTSTR lpszDevice)
{
// Try to open the device
HANDLE hFile = ::CreateFile(lpszDevice,
GENERIC_READ|GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0);
// Check if we could open the device
if (hFile == INVALID_HANDLE_VALUE)
{
// Display error
switch (::GetLastError())
{
case ERROR_FILE_NOT_FOUND:
// The specified COM-port does not exist
return EPortNotAvailable;
case ERROR_ACCESS_DENIED:
// The specified COM-port is in use
return EPortInUse;
default:
// Something else is wrong
return EPortUnknownError;
}
}
// Close handle
::CloseHandle(hFile);
// Port is available
return EPortAvailable;
}
LONG CSerial::Open (LPCTSTR lpszDevice, DWORD dwInQueue, DWORD dwOutQueue, bool fOverlapped)
{
// Reset error state
m_lLastError = ERROR_SUCCESS;
// Check if the port isn't already opened
if (m_hFile)
{
m_lLastError = ERROR_ALREADY_INITIALIZED;
_RPTF0(_CRT_WARN,"CSerial::Open - Port already opened\n");
return m_lLastError;
}
// Open the device
m_hFile = ::CreateFile(lpszDevice,
GENERIC_READ|GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
fOverlapped?FILE_FLAG_OVERLAPPED:0,
0);
if (m_hFile == INVALID_HANDLE_VALUE)
{
// Reset file handle
m_hFile = 0;
// Display error
m_lLastError = ::GetLastError();
_RPTF0(_CRT_WARN, "CSerial::Open - Unable to open port\n");
return m_lLastError;
}
#ifndef SERIAL_NO_OVERLAPPED
// We cannot have an event handle yet
_ASSERTE(m_hevtOverlapped == 0);
// Create the event handle for internal overlapped operations (manual reset)
if (fOverlapped)
{
m_hevtOverlapped = ::CreateEvent(0,true,false,0);
if (m_hevtOverlapped == 0)
{
// Obtain the error information
m_lLastError = ::GetLastError();
_RPTF0(_CRT_WARN,"CSerial::Open - Unable to create event\n");
// Close the port
::CloseHandle(m_hFile);
m_hFile = 0;
// Return the error
return m_lLastError;
}
}
#else
// Overlapped flag shouldn't be specified
_ASSERTE(!fOverlapped);
#endif
// Setup the COM-port
if (dwInQueue || dwOutQueue)
{
// Make sure the queue-sizes are reasonable sized. Win9X systems crash
// if the input queue-size is zero. Both queues need to be at least
// 16 bytes large.
_ASSERTE(dwInQueue >= 16);
_ASSERTE(dwOutQueue >= 16);
if (!::SetupComm(m_hFile,dwInQueue,dwOutQueue))
{
// Display a warning
long lLastError = ::GetLastError();
_RPTF0(_CRT_WARN,"CSerial::Open - Unable to setup the COM-port\n");
// Close the port
Close();
// Save last error from SetupComm
m_lLastError = lLastError;
return m_lLastError;
}
}
// Setup the default communication mask
SetMask();
// Non-blocking reads is default
SetupReadTimeouts(EReadTimeoutNonblocking);
// Setup the device for default settings
COMMCONFIG commConfig = {0};
DWORD dwSize = sizeof(commConfig);
commConfig.dwSize = dwSize;
if (::GetDefaultCommConfig(lpszDevice,&commConfig,&dwSize))
{
// Set the default communication configuration
if (!::SetCommConfig(m_hFile,&commConfig,dwSize))
{
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::Open - Unable to set default communication configuration.\n");
}
}
else
{
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::Open - Unable to obtain default communication configuration.\n");
}
// Return successful
return m_lLastError;
}
LONG CSerial::Close ()
{
// Reset error state
m_lLastError = ERROR_SUCCESS;
// If the device is already closed,
// then we don't need to do anything.
if (m_hFile == 0)
{
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::Close - Method called when device is not open\n");
return m_lLastError;
}
#ifndef SERIAL_NO_OVERLAPPED
// Free event handle
if (m_hevtOverlapped)
{
::CloseHandle(m_hevtOverlapped);
m_hevtOverlapped = 0;
}
#endif
// Close COM port
::CloseHandle(m_hFile);
m_hFile = 0;
// Return successful
return m_lLastError;
}
LONG CSerial::Setup (EBaudrate eBaudrate, EDataBits eDataBits, EParity eParity, EStopBits eStopBits)
{
// 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::Setup - Device is not opened\n");
return m_lLastError;
}
// 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::Setup - Unable to obtain DCB information\n");
return m_lLastError;
}
// Set the new data
dcb.BaudRate = DWORD(eBaudrate);
dcb.ByteSize = BYTE(eDataBits);
dcb.Parity = BYTE(eParity);
dcb.StopBits = BYTE(eStopBits);
// Determine if parity is used
dcb.fParity = (eParity != EParNone);
// Set the new DCB structure
if (!::SetCommState(m_hFile,&dcb))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::Setup - Unable to set DCB information\n");
return m_lLastError;
}
// Return successful
return m_lLastError;
}
LONG CSerial::SetEventChar (BYTE bEventChar, bool fAdjustMask)
{
// 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::SetEventChar - Device is not opened\n");
return m_lLastError;
}
// 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::SetEventChar - Unable to obtain DCB information\n");
return m_lLastError;
}
// Set the new event character
dcb.EvtChar = char(bEventChar);
// Adjust the event mask, to make sure the event will be received
if (fAdjustMask)
{
// Enable 'receive event character' event. Note that this
// will generate an EEventNone if there is an asynchronous
// WaitCommEvent pending.
SetMask(GetEventMask() | EEventRcvEv);
}
// Set the new DCB structure
if (!::SetCommState(m_hFile,&dcb))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::SetEventChar - Unable to set DCB information\n");
return m_lLastError;
}
// Return successful
return m_lLastError;
}
LONG CSerial::SetMask (DWORD dwEventMask)
{
// 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::SetMask - Device is not opened\n");
return m_lLastError;
}
// Set the new mask. Note that this will generate an EEventNone
// if there is an asynchronous WaitCommEvent pending.
if (!::SetCommMask(m_hFile,dwEventMask))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::SetMask - Unable to set event mask\n");
return m_lLastError;
}
// Save event mask and return successful
m_dwEventMask = dwEventMask;
return m_lLastError;
}
LONG CSerial::WaitEvent (LPOVERLAPPED lpOverlapped, DWORD dwTimeout)
{
// Check if time-outs are supported
CheckRequirements(lpOverlapped,dwTimeout);
// 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::WaitEvent - Device is not opened\n");
return m_lLastError;
}
#ifndef SERIAL_NO_OVERLAPPED
// Check if an overlapped structure has been specified
if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE)))
{
// Set the internal error code
m_lLastError = ERROR_INVALID_FUNCTION;
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::WaitEvent - Overlapped I/O is disabled, specified parameters are illegal.\n");
return m_lLastError;
}
// Wait for the event to happen
OVERLAPPED ovInternal;
if (!lpOverlapped && m_hevtOverlapped)
{
// 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(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped));
// Wait for the COM event
if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),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::WaitEvent - Unable to wait for COM event\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
break;
case WAIT_TIMEOUT:
// Cancel the I/O operation
CancelCommIo();
// 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::WaitEvent - Unable to wait until COM event has arrived\n");
return m_lLastError;
}
}
}
else
{
// The operation completed immediatly. Just to be sure
// we'll set the overlapped structure's event handle.
if (lpOverlapped)
::SetEvent(lpOverlapped->hEvent);
}
#else
// Wait for the COM event
if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),0))
{
// Set the internal error code
m_lLastError = ::GetLastError();
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait for COM event\n");
return m_lLastError;
}
#endif
// Return successfully
return m_lLastError;
}
LONG CSerial::SetupHandshaking (EHandshake eHandshake)
{
// 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::SetupHandshaking - Device is not opened\n");
return m_lLastError;
}
// 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::SetupHandshaking - Unable to obtain DCB information\n");
return m_lLastError;
}
// Set the handshaking flags
switch (eHandshake)
{
case EHandshakeOff:
dcb.fOutxCtsFlow = false; // Disable CTS monitoring
dcb.fOutxDsrFlow = false; // Disable DSR monitoring
dcb.fDtrControl = DTR_CONTROL_DISABLE; // Disable DTR monitoring
dcb.fOutX = false; // Disable XON/XOFF for transmission
dcb.fInX = false; // Disable XON/XOFF for receiving
dcb.fRtsControl = RTS_CONTROL_DISABLE; // Disable RTS (Ready To Send)
break;
case EHandshakeHardware:
dcb.fOutxCtsFlow = true; // Enable CTS monitoring
dcb.fOutxDsrFlow = true; // Enable DSR monitoring
dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; // Enable DTR handshaking
dcb.fOutX = false; // Disable XON/XOFF for transmission
dcb.fInX = false; // Disable XON/XOFF for receiving
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; // Enable RTS handshaking
break;
case EHandshakeSoftware:
dcb.fOutxCtsFlow = false; // Disable CTS (Clear To Send)
dcb.fOutxDsrFlow = false; // Disable DSR (Data Set Ready)
dcb.fDtrControl = DTR_CONTROL_DISABLE; // Disable DTR (Data Terminal Ready)
dcb.fOutX = true; // Enable XON/XOFF for transmission
dcb.fInX = true; // Enable XON/XOFF for receiving
dcb.fRtsControl = RTS_CONTROL_DISABLE; // Disable RTS (Ready To Send)
break;
default:
// This shouldn't be possible
_ASSERTE(false);
m_lLastError = E_INVALIDARG;
return m_lLastError;
}
// Set the new DCB structure
if (!::SetCommState(m_hFile,&dcb))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Unable to set DCB information\n");
return m_lLastError;
}
// Return successful
return m_lLastError;
}
LONG CSerial::SetupReadTimeouts (EReadTimeout eReadTimeout)
{
// 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::SetupReadTimeouts - Device is not opened\n");
return m_lLastError;
}
// Determine the time-outs
COMMTIMEOUTS cto;
if (!::GetCommTimeouts(m_hFile,&cto))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Unable to obtain timeout information\n");
return m_lLastError;
}
// Set the new timeouts
switch (eReadTimeout)
{
case EReadTimeoutBlocking:
cto.ReadIntervalTimeout = 0;
cto.ReadTotalTimeoutConstant = 0;
cto.ReadTotalTimeoutMultiplier = 0;
break;
case EReadTimeoutNonblocking:
cto.ReadIntervalTimeout = MAXDWORD;
cto.ReadTotalTimeoutConstant = 0;
cto.ReadTotalTimeoutMultiplier = 0;
break;
default:
// This shouldn't be possible
_ASSERTE(false);
m_lLastError = E_INVALIDARG;
return m_lLastError;
}
// Set the new DCB structure
if (!::SetCommTimeouts(m_hFile,&cto))
{
// Obtain the error code
m_lLastError = ::GetLastError();
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Unable to set timeout information\n");
return m_lLastError;
}
// Return successful
return m_lLastError;
}
CSerial::EBaudrate CSerial::GetBaudrate ()
{
// 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::GetBaudrate - Device is not opened\n");
return EBaudUnknown;
}
// 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 ()
{
// 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 ()
{
// 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 ()
{
// 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 ()
{
// 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;
}
// Return the event mask
return m_dwEventMask;
}
BYTE CSerial::GetEventChar ()
{
// 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 ()
{
// 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)
{
// Check if time-outs are supported
CheckRequirements(lpOverlapped,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;
}
#ifndef SERIAL_NO_OVERLAPPED
// Check if an overlapped structure has been specified
if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE)))
{
// Set the internal error code
m_lLastError = ERROR_INVALID_FUNCTION;
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::Write - Overlapped I/O is disabled, specified parameters are illegal.\n");
return m_lLastError;
}
// Wait for the event to happen
OVERLAPPED ovInternal;
if (!lpOverlapped && m_hevtOverlapped)
{
// 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(!m_hevtOverlapped || 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
CancelCommIo();
// 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.
if (lpOverlapped)
::SetEvent(lpOverlapped->hEvent);
}
#else
// Write the data
if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,0))
{
// Set the internal error code
m_lLastError = ::GetLastError();
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::Write - Unable to write the data\n");
return m_lLastError;
}
#endif
// Return successfully
return m_lLastError;
}
LONG CSerial::Write (LPCSTR pString, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout)
{
// Check if time-outs are supported
CheckRequirements(lpOverlapped,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
CheckRequirements(lpOverlapped,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;
}
#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
#ifndef SERIAL_NO_OVERLAPPED
// Check if an overlapped structure has been specified
if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE)))
{
// Set the internal error code
m_lLastError = ERROR_INVALID_FUNCTION;
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::Read - Overlapped I/O is disabled, specified parameters are illegal.\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(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped));
// 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
CancelCommIo();
// 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.
if (lpOverlapped)
::SetEvent(lpOverlapped->hEvent);
}
#else
// Read the data
if (!::ReadFile(m_hFile,pData,iLen,pdwRead,0))
{
// Set the internal error code
m_lLastError = ::GetLastError();
// Issue an error and quit
_RPTF0(_CRT_WARN,"CSerial::Read - Unable to read the data\n");
return m_lLastError;
}
#endif
// 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 ()
{
// 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 ()
{
#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 ()
{
// 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 ()
{
// 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 ()
{
// 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 ()
{
// 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 ()
{
// 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;
}
Infatti non ho errori io.