📄 win16.cpp
字号:
if ( error_status < RS232_SUCCESS )
return error_status;
SetCommBreak( handle );
timer = ReadTime() + milliseconds;
while ( ReadTime() < timer )
IdleFunction();
ClearCommBreak( handle );
return RS232_SUCCESS;
}
// The four Modem Status routines all take advantage of directly
// peeking at the MSR byte inside the driver. They just mask off
// the bit they are interested in, and return a logical result to
// the calling routine.
int Win16Port::Cd( void )
{
if ( error_status < RS232_SUCCESS )
return error_status;
return ( *modem_status_register & MSR_CD ) != 0;
}
int Win16Port::Ri( void )
{
if ( error_status < RS232_SUCCESS )
return error_status;
return ( *modem_status_register & MSR_RI ) != 0;
}
int Win16Port::Cts( void )
{
if ( error_status < RS232_SUCCESS )
return error_status;
return ( *modem_status_register & MSR_CTS ) != 0;
}
int Win16Port::Dsr( void )
{
if ( error_status < RS232_SUCCESS )
return error_status;
return ( *modem_status_register & MSR_DSR ) != 0;
}
// The four line status routines and the software overrrun error
// detect routine all get their information from the
// Windows API function GetCommError(). It returns all the line
// status bits, rearranged by Windows just for fun.
int Win16Port::SoftwareOverrunError( int clear )
{
COMSTAT comstat;
int return_value;
if ( error_status < RS232_SUCCESS )
return error_status;
line_status |= GetCommError( handle, &comstat );
return_value = ( ( line_status & CE_RXOVER ) != 0 );
if ( clear != UNCHANGED && clear != 0 )
line_status &= ~CE_RXOVER;
return return_value;
}
int Win16Port::ParityError( int reset )
{
COMSTAT comstat;
int return_value;
if ( error_status < RS232_SUCCESS )
return error_status;
line_status |= GetCommError( handle, &comstat );
return_value = ( ( line_status & CE_RXPARITY ) != 0 );
if ( reset != UNCHANGED && reset != 0 )
line_status &= ~CE_RXPARITY;
return return_value;
}
int Win16Port::BreakDetect( int reset )
{
COMSTAT comstat;
int return_value;
if ( error_status < RS232_SUCCESS )
return error_status;
line_status |= GetCommError( handle, &comstat );
return_value = ( ( line_status & CE_BREAK ) != 0 );
if ( reset != UNCHANGED && reset != 0 )
line_status &= ~CE_BREAK;
return return_value;
}
int Win16Port::FramingError( int reset )
{
COMSTAT comstat;
int return_value;
if ( error_status < RS232_SUCCESS )
return error_status;
line_status |= GetCommError( handle, &comstat );
return_value = ( ( line_status & CE_FRAME ) != 0 );
if ( reset != UNCHANGED && reset != 0 )
line_status &= ~CE_FRAME;
return return_value;
}
int Win16Port::HardwareOverrunError( int reset )
{
COMSTAT comstat;
int return_value;
if ( error_status < RS232_SUCCESS )
return error_status;
line_status |= GetCommError( handle, &comstat );
return_value = ( ( line_status & CE_OVERRUN ) != 0 );
if ( reset != UNCHANGED && reset != 0 )
line_status &= ~CE_OVERRUN;
return return_value;
}
// All of the handshaking functions rely on write_settings() to do
// the dirty work of actually changing the settings. They then
// return the current setting to the caller.
int Win16Port::XonXoffHandshaking( int setting )
{
if ( error_status < RS232_SUCCESS )
return error_status;
if ( setting != UNCHANGED ) {
settings.XonXoff = ( setting != 0 );
write_settings();
}
return( settings.XonXoff );
}
int Win16Port::RtsCtsHandshaking( int setting )
{
if ( error_status < RS232_SUCCESS )
return error_status;
if ( setting != UNCHANGED ) {
settings.RtsCts = ( setting != 0 );
write_settings();
}
return( settings.RtsCts );
}
int Win16Port::DtrDsrHandshaking( int setting )
{
if ( error_status < RS232_SUCCESS )
return error_status;
if ( setting != UNCHANGED ) {
settings.DtrDsr = ( setting != 0 );
write_settings();
}
return( settings.DtrDsr );
}
// Setting DTR and RTS is done with a Windows API Escape code.
// The escape sequence is undocumented but widely known, and
// used by so much software it is unlikely to ever change.
int Win16Port::Dtr( int setting )
{
if ( error_status < RS232_SUCCESS )
return error_status;
if ( setting != UNCHANGED ) {
if ( settings.DtrDsr == 1 )
return WINDOWS_PORT_HANDSHAKE_LINE_IN_USE;
else {
if ( ( settings.Dtr = setting ) == 1 )
EscapeCommFunction( handle, SETDTR );
else
EscapeCommFunction( handle, CLRDTR );
}
}
return settings.Dtr;
}
int Win16Port::Rts( int setting )
{
if ( error_status < RS232_SUCCESS )
return error_status;
if ( setting != UNCHANGED ) {
if ( settings.RtsCts == 1 )
return WINDOWS_PORT_HANDSHAKE_LINE_IN_USE;
else {
if ( ( settings.Rts = setting ) == 1 )
EscapeCommFunction( handle, SETRTS );
else
EscapeCommFunction( handle, CLRRTS );
}
}
return settings.Rts;
}
// All the information needed to perform the following functions is
// found in the COMSTAT function returned by GetCommError().
int Win16Port::RXSpaceFree( void )
{
COMSTAT comstat;
if ( error_status < RS232_SUCCESS )
return error_status;
line_status |= GetCommError( handle, &comstat );
return INPUT_BUFFER_SIZE - comstat.cbInQue;
}
int Win16Port::TXSpaceUsed( void )
{
COMSTAT comstat;
if ( error_status < RS232_SUCCESS )
return error_status;
line_status |= GetCommError( handle, &comstat );
return comstat.cbOutQue;
}
// The Windows API provides a dedicated function to perform this task.
int Win16Port::FlushTXBuffer( void )
{
int status;
if ( error_status < RS232_SUCCESS )
return error_status;
status = FlushComm( handle, 0 );
if ( status != 0 )
return translate_windows_error( status );
return RS232_SUCCESS;
}
// The debug output includes a complete dump of the current DCB
// structure for the port, which describes virtually everything
// windows knows about the port. The only thing left out here
// which could be interesting in the COMSTAT structure.
int Win16Port::FormatDebugOutput( char *buffer, int line_number )
{
if ( buffer == 0 )
return( first_debug_output_line + 7 );
if ( line_number < first_debug_output_line )
return RS232::FormatDebugOutput( buffer, line_number );
switch( line_number - first_debug_output_line ) {
case 0 :
wsprintf( buffer,
(LPSTR) "Derived class: Win16Port "
"Ri: %2d Cts: %2d Cd: %2d Dsr: %2d "
"RX Overrun: %d",
Ri(), Cts(), Cd(), Dsr(),
SoftwareOverrunError() );
break;
case 1 :
wsprintf( buffer,
"TX Used: %5d RX Free: %5d "
"Parity Err: %d Break: %d "
"Overrun: %d Framing Err: %d",
TXSpaceUsed(), RXSpaceFree(),
ParityError(),
BreakDetect(),
HardwareOverrunError(),
FramingError() );
break;
case 2 :
wsprintf( buffer,
"DCB: RlsTimeout: %04x CtsTimeout: %04x "
"DsrTimeout: %04x fBinary: %1d",
dcb.RlsTimeout,
dcb.CtsTimeout,
dcb.DsrTimeout,
dcb.fBinary );
break;
case 3 :
wsprintf( buffer,
"DCB: fRtsDisable: %1d fParity: %1d "
"fOutxCtsFlow: %1d fOutxDsrFlow: %1d",
dcb.fRtsDisable,
dcb.fParity,
dcb.fOutxCtsFlow,
dcb.fOutxDsrFlow );
break;
case 4 :
wsprintf( buffer,
"DCB: fDtrDisable: %1d fOutX: %1d fInx: %1d "
"fPeChar: %1d fNull: %1d fChEvt: %1d",
dcb.fDtrDisable,
dcb.fOutX,
dcb.fInX,
dcb.fPeChar,
dcb.fNull,
dcb.fChEvt );
break;
case 5 :
wsprintf( buffer,
"DCB: fDtrflow: %1d fRtsflow: %1d XonChar: %02x "
"XoffChar: %02x XonLim: %04x XoffLim: %04x",
dcb.fDtrflow,
dcb.fRtsflow,
dcb.XonChar,
dcb.XoffChar,
dcb.XonLim,
dcb.XoffLim );
break;
case 6 :
wsprintf( buffer,
"DCB: PeChar: %02x EofChar: %02x EvtChar: %02x "
"TxDelay: %04x",
dcb.PeChar,
dcb.EofChar,
dcb.EvtChar,
dcb.TxDelay );
break;
default :
return RS232_ILLEGAL_LINE_NUMBER;
}
return RS232_SUCCESS;
}
char * Win16Port::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 WINDOWS_PORT_DEFAULT_PARAMETERS :
return "Default parameters in error";
case WINDOWS_PORT_NOT_OPEN :
return "Port not open";
case WINDOWS_PORT_ALREADY_OPEN :
return "Port already open";
case WINDOWS_PORT_HANDSHAKE_LINE_IN_USE :
return "Handshake line in use";
default :
return( "Undefined error" );
}
}
// For Win16 we need a pair of OS specific routines to handle a couple
// of timing issues properly. In a program that really uses the idle
// function you might want to replace this function with one that
// performs a PeekMessage() call
int RS232::IdleFunction( void )
{
return RS232_SUCCESS;
}
//
// ReadTime() returns the current time of day in milliseconds. It uses
// the Windows specific tick count function, instead of polling MS-DOS
// or the BIOS.
//
long ReadTime( void )
{
return GetTickCount();
}
// ******************** END OF WIN16.CPP ********************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -