📄 win32port.cpp
字号:
}
return settings.Dtr;
}
//
// This is an implementation of the virtual Rts() function from
// the base class RS232. It doesn't have to do too much work, it
// merely updates the settings member and then calls the
// write_settings() member function to do all the work. It does
// check to see if RTS/CTS handshaking is in place, and if it is,
// it returns a non-fatal warning to the calling routine. If that
// doesn't happen, it updates the Rts member in the settings
// object and calls write_settings() to update the physical port.
// Note that it returns the current setting of the Rts member. If
// this function is called with no arguments by the end user, it
// doesn't do anything except return that value.
//
int Win32Port::Rts( int setting /* = UNCHANGED */ )
{
if ( error_status < RS232_SUCCESS )
return error_status;
if ( setting != UNCHANGED ) {
if ( settings.RtsCts == 1 )
return WIN32_HANDSHAKE_LINE_IN_USE;
settings.Rts = setting != 0;
RS232Error error = write_settings();
if ( error < RS232_SUCCESS )
return error;
}
return settings.Rts;
}
//
// This is the local implementation of the RS232 member function
// DtrDsrHandshaking. All it has to do is set the member in the
// settings function, then rely on the write_settings() member to
// do all the work. Note that setting this handshaking type to be
// true means that you no longer have direct control over the DTR
// output line. Any attempt to modify DTR will be futile until
// this handshaking value is turned back off.
//
// After finishing its work, this function returns the setting of
// DTR/DSR handshaking for the port. Note that if the user calls
// it with no arguments, it will skip all the setting work and
// just return the value of the current setting.
//
int Win32Port::DtrDsrHandshaking( int setting /* = UNCHANGED */ )
{
if ( error_status < RS232_SUCCESS )
return error_status;
if ( setting != UNCHANGED ) {
settings.DtrDsr = setting != 0;
RS232Error error = write_settings();
if ( error < RS232_SUCCESS )
return error;
}
return settings.DtrDsr;
}
//
// This is the local implementation of the RS232 member function
// RtsCtsHandshaking. All it has to do is set the member in the
// settings function, then rely on the write_settings() member to
// do all the work. Note that setting this handshaking type to be
// true means that you no longer have direct control over the RTS
// output line. Any attempt to modify RTS will be futile until
// this handshaking value is turned back off.
//
// After finishing its work, this function returns the setting of
// RTS/CTS handshaking for the port. Note that if the user calls
// it with no arguments, it will skip all the setting work and
// just return the value of the current setting.
//
int Win32Port::RtsCtsHandshaking( int setting )
{
if ( error_status < RS232_SUCCESS )
return error_status;
if ( setting != UNCHANGED ) {
settings.RtsCts = setting != 0;
RS232Error error = write_settings();
if ( error < RS232_SUCCESS )
return error;
}
return settings.RtsCts;
}
//
// This member function is called to either check or modify the
// current software handshaking state of the port. It doesn't have
// to do any of the hard work, that is all taken care of by the
// write_settings() member of the class. The function returns
// the current state of software handshaking in the port. Note that
// if it is called with no argument, it will skip over all of the
// code that modifies the value and simply return the current state.
//
int Win32Port::XonXoffHandshaking( int setting /* = UNCHANGED */ )
{
if ( error_status < RS232_SUCCESS )
return error_status;
if ( setting != UNCHANGED ) {
settings.XonXoff = setting != 0;
RS232Error error = write_settings();
if ( error < RS232_SUCCESS )
return error;
}
return settings.XonXoff;
}
//
// The following four functions implement the RS232 class
// member functions that return the values of the modem
// status lines. In this case all four functions are so similar
// that there is no point in documenting them individually.
//
// All of these functions simply look at a specific bit in the
// m_dwModemStatus word to see if their individual status line is
// set. The modem status word is read in every time we see a change
// in the status lines. We have set up WaitCommEvent so that it
// should signal an event every time one of the status lines
// changes.
//
// Note that you can set up a derived class so that your app is notified
// every time one of the lines change. This is particularly valuable
// for monitoring the RI line, as it may be difficult to catch an
// incoming ring in progress.
//
int Win32Port::Cd()
{
return ( MS_RLSD_ON & m_dwModemStatus ) != 0;
}
int Win32Port::Cts()
{
return ( MS_CTS_ON & m_dwModemStatus ) != 0;
}
int Win32Port::Dsr()
{
return ( MS_DSR_ON & m_dwModemStatus ) != 0;
}
int Win32Port::Ri()
{
return ( MS_RING_ON & m_dwModemStatus ) != 0;
}
//
// Just like the four modem status routines, the four line status
// error routines all take the same form. Each of the checks the
// m_dwErrors for their specific error bit, returning true if the
// bit is set and false if it is not. If the caller invoked the function
// with the clearing option, the bit in the cumulative line status
// error word will be cleared.
//
int Win32Port::ParityError( int clear /* = UNCHANGED */ )
{
int return_value;
if ( error_status < RS232_SUCCESS )
return error_status;
return_value = ( m_dwErrors & CE_RXPARITY ) != 0;
if ( clear != UNCHANGED && clear != 0 )
m_dwErrors &= ~CE_RXPARITY;
return return_value;
}
int Win32Port::FramingError( int clear /* = UNCHANGED */ )
{
int return_value;
if ( error_status < RS232_SUCCESS )
return error_status;
return_value = ( m_dwErrors & CE_FRAME ) != 0;
if ( clear != UNCHANGED && clear != 0 )
m_dwErrors &= ~CE_FRAME;
return return_value;
}
int Win32Port::HardwareOverrunError( int clear /* = UNCHANGED */ )
{
int return_value;
if ( error_status < RS232_SUCCESS )
return error_status;
return_value = ( m_dwErrors & CE_OVERRUN ) != 0;
if ( clear != UNCHANGED && clear != 0 )
m_dwErrors &= ~CE_OVERRUN;
return return_value;
}
int Win32Port::BreakDetect( int clear /* = UNCHANGED */ )
{
int return_value;
if ( error_status < RS232_SUCCESS )
return error_status;
return_value = ( m_dwErrors & CE_BREAK ) != 0;
if ( clear != UNCHANGED && clear != 0 )
m_dwErrors &= ~CE_BREAK;
return return_value;
}
//
// This routine acts just like the previous four. The only
// difference is the type of error being handled. The software
// overrun error is set when the driver receives a character
// but doesn't have room to store it. Unfortunately, there isn't
// an EV_XXXX routine to force this error to generate an event
// when it happens, so we end up checking the comm status
// after every input packet.
//
int Win32Port::SoftwareOverrunError( int clear /* = UNCHANGED */ )
{
int return_value;
if ( error_status < RS232_SUCCESS )
return error_status;
return_value = ( m_dwErrors & CE_RXOVER ) != 0;
if ( clear != UNCHANGED && clear != 0 )
m_dwErrors &= ~CE_RXOVER;
return return_value;
}
//
// This function is called to provoke the output thread into sending
// a break of a specified duration. We haven't set up any path by
// which to set the duration of the break, instead we just stored
// the desired duration in the object, and count on the output thread
// checking there to see what it should be. The output thread is
// continually checking for the m_hBreakRequestEvent, and when it sees
// it, it faithfully sends the break.
//
int Win32Port::Break( long milliseconds )
{
if ( milliseconds > 1000 )
m_iBreakDuration = 1000;
else
m_iBreakDuration = milliseconds;
SetEvent( m_hBreakRequestEvent );
return RS232_SUCCESS;
}
//
// The Peek() function is fairly close to read_buffer(). It takes
// whatever it can get out the input buffer, and returns a count
// of bytes read in ByteCount.
//
int Win32Port::Peek( void *buffer, unsigned int count )
{
if ( error_status < RS232_SUCCESS )
return error_status;
ByteCount = m_RxQueue.Peek( (char *) buffer, count );
( (char *) buffer )[ ByteCount ] = '\0';
return RS232_SUCCESS;
}
//
// The two FlushXxBuffer routines do the same things. Both calls
// have to take care to clear both the internal buffers used by
// the driver, plus the external buffers we keep in the class. One
// is done by a simple member of class MTQueue, the other by using
// a Win32 API call.
//
int Win32Port::FlushRXBuffer()
{
if ( error_status < RS232_SUCCESS )
return error_status;
m_RxQueue.Clear();
PurgeComm( m_hPort, PURGE_RXCLEAR );
if ( !m_bInputThreadReading )
SetEvent( m_hReadRequestEvent );
return RS232_SUCCESS;
}
int Win32Port::FlushTXBuffer()
{
if ( error_status < RS232_SUCCESS )
return error_status;
m_TxQueue.Clear();
PurgeComm( m_hPort, PURGE_TXCLEAR );
return RS232_SUCCESS;
}
//
// Since we have a few error codes that are unique to the Win32Port class,
// it makes sense to translate them ourselves when requested. That's what
// this function does. Note that most of the time it passes the job up to
// the base class.
//
char *Win32Port::ErrorName( int error )
{
if ( error < RS232_NEXT_FREE_ERROR && error >= RS232_ERROR )
return RS232::ErrorName( error );
if ( error < RS232_NEXT_FREE_WARNING && error >= RS232_WARNING )
return RS232::ErrorName( error );
if ( error >= RS232_SUCCESS )
return RS232::ErrorName( error );
switch ( error ) {
case WIN32_CHECK_WINDOWS_ERROR :
return "Check Windows error code in m_dwWindowsError";
case WIN32_SETTINGS_FAILURE :
return "Failure to set port parameters";
case WIN32_HANDSHAKE_LINE_IN_USE :
return "Handshake line is already in use";
default :
return( "Undefined error" );
}
}
//
// The last of our locally implemented versions of base class
// functions is FormatDebugOutput(). It should be fairly easy
// to figure out, it simply creates a line of output upon request.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -