home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.wwiv.com
/
ftp.wwiv.com.zip
/
ftp.wwiv.com
/
pub
/
INTERNET
/
UPC2S1.ZIP
/
ULIBOS2.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-03
|
41KB
|
1,298 lines
/*--------------------------------------------------------------------*/
/* u l i b o s 2 . c */
/* */
/* OS/2 serial port support for UUCICO */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* Changes Copyright (c) 1989-1993 by Kendra Electronic */
/* Wonderworks. */
/* */
/* All rights reserved except those explicitly granted by the */
/* UUPC/extended license agreement. */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* RCS Information */
/*--------------------------------------------------------------------*/
/*
* $Id: ulibos2.c 1.23 1993/10/03 22:09:09 ahd Exp $
* $Log: ulibos2.c $
* Revision 1.23 1993/10/03 22:09:09 ahd
* Use unsigned long to display speed
*
* Revision 1.22 1993/10/01 01:17:44 ahd
* Drop unneeded special case for port in use message
*
* Revision 1.21 1993/09/29 05:25:21 ahd
* Don't die after duplicate port close
*
* Revision 1.20 1993/09/29 04:52:03 ahd
* Use unique handler for port suspending
*
* Revision 1.19 1993/09/27 04:04:06 ahd
* Normalize references to modem speed to avoid incorrect displays
*
* Revision 1.18 1993/09/25 03:07:56 ahd
* Convert to standard OS/2 error message call
*
* Revision 1.17 1993/09/24 03:43:27 ahd
* Use OS/2 error message routine
*
* Revision 1.16 1993/09/21 01:42:13 ahd
* Use standard MAXPACK limit for save buffer size
*
* Revision 1.15 1993/09/20 04:46:34 ahd
* OS/2 2.x support (BC++ 1.0 support)
* TCP/IP support from Dave Watt
* 't' protocol support
*
* Revision 1.14 1993/05/30 15:25:50 ahd
* Multiple driver support
*
* Revision 1.13 1993/05/30 00:08:03 ahd
* Multiple communications driver support
* Delete trace functions
*
* Revision 1.12 1993/05/09 03:41:47 ahd
* Make swrite accept constant input strings
*
* Revision 1.11 1993/04/11 00:34:11 ahd
* Global edits for year, TEXT, etc.
*
* Revision 1.10 1993/04/10 21:25:16 dmwatt
* Add Windows/NT support
*
* Revision 1.9 1993/04/05 04:32:19 ahd
* Additional traps for modem dropping out
*
* Revision 1.8 1993/04/04 04:57:01 ahd
* Add configurable OS/2 priority values
*
* Revision 1.7 1992/12/30 13:02:55 dmwatt
* Dual path for Windows/NT and OS/2
*
* Revision 1.6 1992/12/11 12:45:11 ahd
* Correct RTS handshake
*
* Revision 1.5 1992/12/04 01:00:27 ahd
* Add copyright message, reblock other comments
*
* Revision 1.4 1992/11/29 22:09:10 ahd
* Add new define for BC++ OS/2 build
*
* Revision 1.3 1992/11/19 03:00:39 ahd
* drop rcsid
*
* Revision 1.2 1992/11/15 20:11:48 ahd
* Add English display of modem status and error bits
*
*/
/*--------------------------------------------------------------------*/
/* System include files */
/*--------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include <time.h>
/*--------------------------------------------------------------------*/
/* OS/2 include files */
/*--------------------------------------------------------------------*/
#define INCL_DOSDEVIOCTL
#define INCL_BASE
#define INCL_NOPMAPI
#include <os2.h>
#include <limits.h>
#ifndef __OS2__
typedef USHORT APIRET ; // Define older API return type
#endif
/*--------------------------------------------------------------------*/
/* UUPC/extended include files */
/*--------------------------------------------------------------------*/
#include "lib.h"
#include "ulib.h"
#include "ssleep.h"
#include "catcher.h"
#include "pos2err.h"
#include "commlib.h"
#include "usrcatch.h"
/*--------------------------------------------------------------------*/
/* Global variables */
/*--------------------------------------------------------------------*/
currentfile();
static boolean carrierDetect = FALSE; /* Modem is not connected */
static boolean hangupNeeded = FALSE;
static unsigned short currentSpeed = 0;
#define FAR_NULL ((PVOID) 0L)
/*--------------------------------------------------------------------*/
/* Definitions of control structures for DOS API */
/*--------------------------------------------------------------------*/
static HFILE com_handle;
static struct _LINECONTROL com_attrib;
static struct _MODEMSTATUS com_signals;
static struct _DCBINFO com_dcbinfo;
static void ShowError( const USHORT status );
static void ShowModem( const BYTE status );
/*--------------------------------------------------------------------*/
/* n o p e n l i n e */
/* */
/* Open the serial port for I/O */
/*--------------------------------------------------------------------*/
int nopenline(char *name, BPS baud, const boolean direct )
{
APIRET rc;
USHORT com_error;
#ifdef __OS2__
ULONG ParmLengthInOut;
ULONG DataLengthInOut;
ULONG action;
#else
USHORT action;
#endif
if (portActive) /* Was the port already active? */
closeline(); /* Yes --> Shutdown it before open */
#ifdef UDEBUG
printmsg(15, "nopenline: %s, %lu", name, baud);
#endif
/*--------------------------------------------------------------------*/
/* Validate the port format */
/*--------------------------------------------------------------------*/
if (!equaln(name, "COM", 3 ))
{
printmsg(0,"nopenline: Communications port begin with COM, was %s",
name);
panic();
}
/*--------------------------------------------------------------------*/
/* Perform the open */
/*--------------------------------------------------------------------*/
rc = DosOpen( name,
&com_handle,
&action,
0L,
0 ,
FILE_OPEN ,
OPEN_FLAGS_FAIL_ON_ERROR |
OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE, 0L );
/*--------------------------------------------------------------------*/
/* Check the open worked. We translation the common obvious */
/* error of file in use to english, for all other errors are we */
/* report the raw error code. */
/*--------------------------------------------------------------------*/
if ( rc )
{
printOS2error( name, rc );
return TRUE;
}
/*--------------------------------------------------------------------*/
/* Reset any errors on the communications port */
/*--------------------------------------------------------------------*/
#ifdef __OS2__
ParmLengthInOut = 0;
DataLengthInOut = sizeof(com_error);
rc = DosDevIOCtl( com_handle, IOCTL_ASYNC, ASYNC_GETCOMMERROR,
NULL,0L,&ParmLengthInOut,(PVOID) &com_error,sizeof(com_error),
&DataLengthInOut);
#else
rc = DosDevIOCtl( &com_error, FAR_NULL, ASYNC_GETCOMMERROR ,
IOCTL_ASYNC, com_handle);
#endif
if (rc)
{
printmsg(0,
"nopenline: Unable to read errors for %s, error bits %x",
name, (int) com_error );
printOS2error( "DosDevIOCtl", rc );
} /*if */
else if ( com_error )
ShowError( com_error );
/*--------------------------------------------------------------------*/
/* Set baud rate */
/*--------------------------------------------------------------------*/
SIOSpeed(baud);
/*--------------------------------------------------------------------*/
/* Set line attributes */
/*--------------------------------------------------------------------*/
#ifdef UDEBUG
printmsg(15,"nopenline: Getting attributes");
#endif
#ifdef __OS2__
ParmLengthInOut = 0;
DataLengthInOut = sizeof(com_attrib);
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_GETLINECTRL,
NULL,
0L,
&ParmLengthInOut,
(PVOID) &com_attrib,
sizeof(com_attrib),
&DataLengthInOut); // Get old attributes from device
#else
rc = DosDevIOCtl( &com_attrib,
FAR_NULL,
ASYNC_GETLINECTRL,
IOCTL_ASYNC,
com_handle); // Get old attributes from device
#endif
if (rc)
{
printmsg(0,"nopenline: Unable to get line attributes for %s",name);
printOS2error( "DosDevIOCtl", rc );
panic();
} /*if */
com_attrib.bDataBits = 0x08; /* Use eight bit path for data */
com_attrib.bParity = 0x00; /* No parity */
com_attrib.bStopBits = 0x00; /* 1 Stop Bit */
#ifdef UDEBUG
printmsg(15,"nopenline: Setting attributes");
#endif
#ifdef __OS2__
ParmLengthInOut = sizeof(com_attrib);
DataLengthInOut = 0;
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_SETLINECTRL,
(PVOID) &com_attrib,
sizeof(com_attrib),
&ParmLengthInOut,
NULL,
0L,
&DataLengthInOut);
#else
rc = DosDevIOCtl( FAR_NULL,
&com_attrib,
ASYNC_SETLINECTRL,
IOCTL_ASYNC,
com_handle);
#endif
if (rc)
{
printmsg(0,"nopenline: Unable to set line attributes for %s",name);
printOS2error( "DosDevIOCtl", rc );
panic();
} /*if */
/*--------------------------------------------------------------------*/
/* Disable software (XON/XOFF) flow control and enable */
/* hardware (CTS) for flow control */
/*--------------------------------------------------------------------*/
#ifdef UDEBUG
printmsg(15,"nopenline: Getting flow control information");
#endif
#ifdef __OS2__
ParmLengthInOut = 0;
DataLengthInOut = sizeof(com_dcbinfo);
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_GETDCBINFO,
NULL,
0L,
&ParmLengthInOut,
(PVOID) &com_dcbinfo,
sizeof(com_dcbinfo),
&DataLengthInOut); // Get old attributes from device
#else
rc = DosDevIOCtl( &com_dcbinfo,
FAR_NULL,
ASYNC_GETDCBINFO,
IOCTL_ASYNC,
com_handle); // Get old attributes from device
#endif
if (rc)
{
printmsg(0,"nopenline: Unable to get line attributes for %s",name);
printOS2error( "DosDevIOCtl", rc );
panic();
} /*if */
com_dcbinfo.usWriteTimeout = 2999; /* Write timeout 30 seconds */
com_dcbinfo.usReadTimeout = 24; /* Read timeout .25 seconds */
com_dcbinfo.fbCtlHndShake = (BYTE)
(direct ? 0 : MODE_CTS_HANDSHAKE);
com_dcbinfo.fbFlowReplace = 0;
/* Unless rquested */
com_dcbinfo.fbTimeout = MODE_READ_TIMEOUT | MODE_NO_WRITE_TIMEOUT;
#ifdef UDEBUG
printmsg(15,"nopenline: Setting dcb information");
#endif
#ifdef __OS2__
ParmLengthInOut = sizeof(com_dcbinfo);
DataLengthInOut = 0;
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_SETDCBINFO,
(PVOID) &com_dcbinfo,
sizeof(com_dcbinfo),
&ParmLengthInOut,
NULL,
0L,
&DataLengthInOut);
#else
rc = DosDevIOCtl( FAR_NULL,
&com_dcbinfo,
ASYNC_SETDCBINFO,
IOCTL_ASYNC,
com_handle);
#endif
if ( rc )
{
printmsg(0,"nopenline: Unable to set flow control for %s",name);
printOS2error( "DosDevIOCtl", rc );
panic();
} /*if */
/*--------------------------------------------------------------------*/
/* Raise Data Terminal Ready */
/*--------------------------------------------------------------------*/
com_signals.fbModemOn = DTR_ON | RTS_ON ;
com_signals.fbModemOff = 0xff;
#ifdef UDEBUG
printmsg(15,"nopenline: Raising RTS/DTR");
#endif
#ifdef __OS2__
ParmLengthInOut = sizeof(com_signals);
DataLengthInOut = sizeof(com_error);
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_SETMODEMCTRL,
(PVOID)&com_signals,
sizeof(com_signals),
&ParmLengthInOut,
(PVOID) &com_error,
sizeof(com_error),
&DataLengthInOut);
#else
rc = DosDevIOCtl( &com_error,
&com_signals,
ASYNC_SETMODEMCTRL,
IOCTL_ASYNC,
com_handle);
#endif
if (rc)
{
printmsg(0,
"nopenline: Unable to raise DTR/RTS for %s, error bits %#x",
name, (int) com_error );
printOS2error( "DosDevIOCtl", rc );
panic();
} /*if */
traceStart( name ); // Enable logging
portActive = TRUE; /* record status for error handler */
carrierDetect = FALSE; /* Modem is not connected */
/*--------------------------------------------------------------------*/
/* Wait for port to stablize */
/*--------------------------------------------------------------------*/
ddelay(500); /* Allow port to stablize */
return 0;
} /*nopenline*/
/*--------------------------------------------------------------------*/
/* n s r e a d */
/* */
/* Read from the serial port */
/* */
/* Non-blocking read essential to "g" protocol. See "dcpgpkt.c" */
/* for description. */
/* */
/* This all changes in a multi-tasking system. Requests for I/O */
/* should get queued and an event flag given. Then the */
/* requesting process (e.g. gmachine()) waits for the event flag */
/* to fire processing either a read or a write. Could be */
/* implemented on VAX/VMS or DG but not MS-DOS. */
/* */
/* OS/2 we could multitask, but we just let the system provide */
/* a timeout for us with very little CPU usage. */
/*--------------------------------------------------------------------*/
unsigned int nsread(char *output, unsigned int wanted, unsigned int timeout)
{
APIRET rc;
static char save[MAXPACK];
static USHORT bufsize = 0;
time_t stop_time ;
time_t now ;
USHORT com_error;
#ifdef __OS2__
ULONG ParmLengthInOut;
ULONG DataLengthInOut;
#endif
/*--------------------------------------------------------------------*/
/* Determine if our internal buffer has the data */
/*--------------------------------------------------------------------*/
if (bufsize >= wanted)
{
memmove( output, save, wanted );
bufsize -= wanted;
if ( bufsize ) /* Any data left over? */
memmove( save, &save[wanted], bufsize ); /* Yes --> Save it*/
return wanted + bufsize;
} /* if */
/*--------------------------------------------------------------------*/
/* Reset any errors on the communications port */
/*--------------------------------------------------------------------*/
#ifdef __OS2__
ParmLengthInOut = 0;
DataLengthInOut = sizeof(com_error);
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_GETCOMMERROR,
NULL,
0L,
&ParmLengthInOut,
(PVOID) &com_error,
sizeof(com_error),
&DataLengthInOut);
#else
rc = DosDevIOCtl( &com_error,
FAR_NULL,
ASYNC_GETCOMMERROR ,
IOCTL_ASYNC,
com_handle);
#endif
if (rc )
{
printmsg(0,"nsread: Unable to read port errors");
printOS2error( "DosDevIOCtl", rc );
} /*if */
else if ( com_error )
ShowError( com_error );
/*--------------------------------------------------------------------*/
/* Determine when to stop processing */
/*--------------------------------------------------------------------*/
if ( timeout == 0 )
{
stop_time = 0;
now = 1; /* Any number greater than stop time */
}
else {
time( & now );
stop_time = now + timeout;
}
/*--------------------------------------------------------------------*/
/* Try to read any needed data into the buffer */
/*--------------------------------------------------------------------*/
do {
USHORT needed = (USHORT) wanted - bufsize;
USHORT port_timeout;
#ifdef __OS2__
ULONG received = 0;
#else
USHORT received = 0;
#endif
/*--------------------------------------------------------------------*/
/* Handle an aborted program */
/*--------------------------------------------------------------------*/
if ( raised )
return 0;
if ( terminate_processing )
{
static boolean recurse = FALSE;
if ( ! recurse )
{
printmsg(2,"nsread: User aborted processing");
recurse = TRUE;
}
return 0;
}
/*--------------------------------------------------------------------*/
/* Compute a new timeout for the read, if needed */
/*--------------------------------------------------------------------*/
if (stop_time > now )
{
port_timeout = (USHORT) (stop_time - now) / needed * 100;
if (port_timeout < 100)
port_timeout = 100;
}
else
port_timeout = 0;
if ( port_timeout != com_dcbinfo.usReadTimeout )
{
com_dcbinfo.usReadTimeout = port_timeout;
#ifdef __OS2__
ParmLengthInOut = sizeof(com_dcbinfo);
DataLengthInOut = 0;
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_SETDCBINFO,
(PVOID) &com_dcbinfo,
sizeof(com_dcbinfo),
&ParmLengthInOut,
NULL,
0L,
&DataLengthInOut);
#else
rc = DosDevIOCtl(FAR_NULL,
&com_dcbinfo,
ASYNC_SETDCBINFO,
IOCTL_ASYNC,
com_handle);
#endif
if ( rc )
{
printmsg(0,"nsread: Unable to set timeout for comm port");
printOS2error( "DosDevIOCtl", rc );
panic();
} /* if */
} /* if */
#ifdef UDEBUG
printmsg(15,"nsread: Port time out is %ud seconds/100",
port_timeout);
#endif
/*--------------------------------------------------------------------*/
/* Read the data from the serial port */
/*--------------------------------------------------------------------*/
rc = DosRead( com_handle, &save[bufsize], needed, &received );
if ( rc == ERROR_INTERRUPT)
{
printmsg(2,"Read Interrupted");
return 0;
}
else if ( rc != 0 )
{
printmsg(0,"nsread: Read from comm port for %d bytes failed.",
needed);
printOS2error( "DosRead", rc );
bufsize = 0;
return 0;
}
#ifdef UDEBUG
printmsg(15,"nsread: Want %d characters, received %d, total %d in buffer",
(int) wanted, (int) received, (int) bufsize + received);
#endif
/*--------------------------------------------------------------------*/
/* Log the newly received data */
/*--------------------------------------------------------------------*/
traceData( &save[bufsize], received, FALSE );
/*--------------------------------------------------------------------*/
/* If we got the data, return it to the caller */
/*--------------------------------------------------------------------*/
bufsize += received;
if ( bufsize == wanted )
{
memmove( output, save, bufsize);
bufsize = 0;
if (debuglevel > 14)
fwrite(output,1,bufsize,stdout);
return wanted;
} /* if */
/*--------------------------------------------------------------------*/
/* Update the clock for the next pass */
/*--------------------------------------------------------------------*/
if (stop_time > 0)
time( &now );
} while (stop_time > now);
/*--------------------------------------------------------------------*/
/* We don't have enough data; report what we do have */
/*--------------------------------------------------------------------*/
return bufsize;
} /*nsread*/
/*--------------------------------------------------------------------*/
/* n s w r i t e */
/* */
/* Write to the serial port */
/*--------------------------------------------------------------------*/
int nswrite(const char *input, unsigned int len)
{
char *data = (char *) input;
#ifdef __OS2__
ULONG bytes;
#else
size_t bytes;
#endif
APIRET rc;
hangupNeeded = TRUE; /* Flag that the port is now dirty */
/*--------------------------------------------------------------------*/
/* Write the data out as the queue becomes available */
/*--------------------------------------------------------------------*/
rc = DosWrite( com_handle, data , len, &bytes);
if (rc)
{
printOS2error( "DosWrite", rc );
return bytes;
} /*if */
/*--------------------------------------------------------------------*/
/* Log the data written */
/*--------------------------------------------------------------------*/
traceData( data, len, TRUE);
/*--------------------------------------------------------------------*/
/* Return bytes written to the port to the caller */
/*--------------------------------------------------------------------*/
return len;
} /* nswrite */
/*--------------------------------------------------------------------*/
/* n s s e n d b r k */
/* */
/* send a break signal out the serial port */
/*--------------------------------------------------------------------*/
void nssendbrk(unsigned int duration)
{
#ifdef __OS2__
ULONG ParmLengthInOut;
ULONG DataLengthInOut;
#endif
USHORT com_error;
#ifdef UDEBUG
printmsg(12, "ssendbrk: %d", duration);
#endif
#ifdef __OS2__
ParmLengthInOut = 0;
DataLengthInOut = sizeof(com_error);
DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_SETBREAKON,
NULL,
0L,
&ParmLengthInOut,
(PVOID) &com_error,
sizeof(com_error),
&DataLengthInOut);
#else
DosDevIOCtl( &com_error,
FAR_NULL,
ASYNC_SETBREAKON,
IOCTL_ASYNC,
com_handle);
#endif
if ( com_error )
ShowError( com_error );
ddelay( duration == 0 ? 200 : duration);
#ifdef __OS2__
ParmLengthInOut = 0;
DataLengthInOut = sizeof(com_error);
DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_SETBREAKOFF,
NULL,
0L,
&ParmLengthInOut,
(PVOID) &com_error,
sizeof(com_error),
&DataLengthInOut);
#else
DosDevIOCtl( &com_error,
FAR_NULL,
ASYNC_SETBREAKOFF,
IOCTL_ASYNC,
com_handle);
#endif
if ( com_error )
ShowError( com_error );
} /*nssendbrk*/
/*--------------------------------------------------------------------*/
/* n c l o s e l i n e */
/* */
/* Close the serial port down */
/*--------------------------------------------------------------------*/
void ncloseline(void)
{
APIRET rc;
USHORT com_error;
#ifdef __OS2__
ULONG ParmLengthInOut;
ULONG DataLengthInOut;
#endif
if ( ! portActive )
{
printmsg(0,"ncloseline: Internal error, port already closed");
return;
}
portActive = FALSE; /* flag port closed for error handler */
hangupNeeded = FALSE; /* Don't fiddle with port any more */
/*--------------------------------------------------------------------*/
/* Lower DTR */
/*--------------------------------------------------------------------*/
com_signals.fbModemOn = 0x00;
com_signals.fbModemOff = DTR_OFF | RTS_OFF;
#ifdef __OS2__
ParmLengthInOut = sizeof(com_signals);
DataLengthInOut = sizeof(com_error);
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_SETMODEMCTRL,
(PVOID)&com_signals,
sizeof(com_signals),
&ParmLengthInOut,
(PVOID) &com_error,
sizeof(com_error),
&DataLengthInOut);
#else
rc = DosDevIOCtl( &com_error,
&com_signals,
ASYNC_SETMODEMCTRL,
IOCTL_ASYNC,
com_handle);
#endif
if ( rc )
{
printmsg(0,"ncloseline: Unable to lower DTR/RTS for port");
printOS2error( "DosDevIOCtl", rc );
}
else if ( com_error )
ShowError( com_error );
/*--------------------------------------------------------------------*/
/* Actually close the port */
/*--------------------------------------------------------------------*/
rc = DosClose( com_handle );
if ( rc != 0 )
printOS2error( "DosClose", rc );
/*--------------------------------------------------------------------*/
/* Stop logging the data to disk */
/*--------------------------------------------------------------------*/
traceStop();
} /* ncloseline */
/*--------------------------------------------------------------------*/
/* n h a n g u p */
/* */
/* Hangup the telephone by dropping DTR. Works with HAYES and */
/* many compatibles. */
/* 14 May 89 Drew Derbyshire */
/*--------------------------------------------------------------------*/
void nhangup( void )
{
#ifdef __OS2__
ULONG ParmLengthInOut;
ULONG DataLengthInOut;
#endif
USHORT com_error;
APIRET rc;
if (!hangupNeeded)
return;
hangupNeeded = FALSE;
/*--------------------------------------------------------------------*/
/* Drop DTR */
/*--------------------------------------------------------------------*/
com_signals.fbModemOn = 0x00;
com_signals.fbModemOff = DTR_OFF;
#ifdef __OS2__
ParmLengthInOut = sizeof(com_signals);
DataLengthInOut = sizeof(com_error);
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_SETMODEMCTRL,
(PVOID)&com_signals,
sizeof(com_signals),
&ParmLengthInOut,
(PVOID) &com_error,
sizeof(com_error),
&DataLengthInOut);
#else
rc = DosDevIOCtl( &com_error,
&com_signals,
ASYNC_SETMODEMCTRL,
IOCTL_ASYNC,
com_handle);
#endif
if ( rc )
{
printmsg(0,"hangup: Unable to lower DTR for comm port");
printOS2error( "DosDevIOCtl", rc );
} /*if */
else if ( com_error )
ShowError( com_error );
/*--------------------------------------------------------------------*/
/* Wait for the telephone to hangup */
/*--------------------------------------------------------------------*/
printmsg(3,"hangup: Dropped DTR");
carrierDetect = FALSE; /* Modem is not connected */
ddelay(500); /* Really only need 250 milliseconds */
/*--------------------------------------------------------------------*/
/* Bring DTR back up */
/*--------------------------------------------------------------------*/
com_signals.fbModemOn = DTR_ON;
com_signals.fbModemOff = 0xff;
#ifdef __OS2__
ParmLengthInOut = sizeof(com_signals);
DataLengthInOut = sizeof(com_error);
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC, ASYNC_SETMODEMCTRL,
(PVOID)&com_signals,
sizeof(com_signals),
&ParmLengthInOut,
(PVOID) &com_error,
sizeof(com_error),
&DataLengthInOut);
#else
rc = DosDevIOCtl( &com_error,
&com_signals,
ASYNC_SETMODEMCTRL,
IOCTL_ASYNC,
com_handle);
#endif
if ( rc )
{
printmsg(0,"hangup: Unable to raise DTR for comm port");
printOS2error( "DosDevIOCtl", rc );
} /*if */
else if ( com_error )
ShowError( com_error );
ddelay(2000); /* Now wait for the poor thing to recover */
} /* nhangup */
/*--------------------------------------------------------------------*/
/* n S I O S p e e d */
/* */
/* Re-specify the speed of an opened serial port */
/* */
/* Dropped the DTR off/on calls because this makes a Hayes drop */
/* the line if configured properly, and we don't want the modem */
/* to drop the phone on the floor if we are performing */
/* autobaud. */
/* */
/* (Configured properly = standard method of making a Hayes */
/* hang up the telephone, especially when you can't get it into */
/* command state because it is at the wrong speed or whatever.) */
/*--------------------------------------------------------------------*/
void nSIOSpeed(BPS baud)
{
APIRET rc;
#ifdef __OS2__
ULONG ParmLengthInOut;
ULONG DataLengthInOut;
struct
{
ULONG baud; // this structure is needed to set the extended
BYTE fraction; // baud rate using function 41h DosDevIOCtl
} com_baud;
#else
USHORT speed = (USHORT) baud;
#endif
#ifdef UDEBUG
printmsg(15,"SIOSpeed: Setting baud rate to %lu",
(unsigned long) baud);
#endif
#ifdef __OS2__
/*--------------------------------------------------------------------*/
/* OS/2 2.x Format of call for DosDevIOCtl accepts baud */
/* rates greater than 19200. */
/*--------------------------------------------------------------------*/
com_baud.baud = baud;
com_baud.fraction = 0;
ParmLengthInOut = sizeof(com_baud);
DataLengthInOut = 0;
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_SETBAUDRATE,
(PVOID) &com_baud,
sizeof(com_baud),
&ParmLengthInOut,
NULL,
0L,
&DataLengthInOut);
#else
rc = DosDevIOCtl( FAR_NULL,
&speed,
ASYNC_SETBAUDRATE,
IOCTL_ASYNC,
com_handle);
#endif
if (rc)
{
printmsg(0,"SIOSPeed: Unable to set baud rate for port to %lu",
baud);
printOS2error( "DosDevIOCtl", rc );
panic();
} /*if */
currentSpeed = (unsigned short) baud;
} /* nSIOSpeed */
/*--------------------------------------------------------------------*/
/* n f l o w c o n t r o l */
/* */
/* Enable/Disable in band (XON/XOFF) flow control */
/*--------------------------------------------------------------------*/
void nflowcontrol( boolean flow )
{
APIRET rc;
#ifdef __OS2__
ULONG ParmLengthInOut;
ULONG DataLengthInOut;
#endif
if ( flow )
com_dcbinfo.fbFlowReplace = (char)
(com_dcbinfo.fbFlowReplace |
(MODE_AUTO_TRANSMIT | MODE_AUTO_RECEIVE));
else
com_dcbinfo.fbFlowReplace = (char)
(com_dcbinfo.fbFlowReplace &
(0xff - MODE_AUTO_TRANSMIT - MODE_AUTO_RECEIVE));
#ifdef __OS2__
ParmLengthInOut = sizeof(com_dcbinfo);
DataLengthInOut = 0;
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_SETDCBINFO,
(PVOID) &com_dcbinfo,
sizeof(com_dcbinfo),
&ParmLengthInOut,
NULL,
0L,
&DataLengthInOut);
#else
rc = DosDevIOCtl( FAR_NULL,
&com_dcbinfo,
ASYNC_SETDCBINFO,
IOCTL_ASYNC,
com_handle);
#endif
if ( rc )
{
printmsg(0,"flowcontrol: Unable to set flow control");
printOS2error( "DosDevIOCtl", rc );
panic();
} /*if */
} /* nflowcontrol */
/*--------------------------------------------------------------------*/
/* n G e t S p e e d */
/* */
/* Report current speed of communications connection */
/*--------------------------------------------------------------------*/
BPS nGetSpeed( void )
{
return currentSpeed;
} /* nGetSpeed */
/*--------------------------------------------------------------------*/
/* n C D */
/* */
/* Return status of carrier detect */
/*--------------------------------------------------------------------*/
boolean nCD( void )
{
boolean previousCarrierDetect = carrierDetect;
APIRET rc;
#ifdef __OS2__
ULONG ParmLengthInOut;
ULONG DataLengthInOut;
#endif
BYTE status;
static BYTE oldstatus = (BYTE) 0xDEAD;
#ifdef __OS2__
ParmLengthInOut = 0;
DataLengthInOut = sizeof(status);
rc = DosDevIOCtl( com_handle,
IOCTL_ASYNC,
ASYNC_GETMODEMINPUT,
NULL,
0L,
&ParmLengthInOut,
(PVOID) &status,
sizeof(status),
&DataLengthInOut);
#else
rc = DosDevIOCtl( &status,
0L,
ASYNC_GETMODEMINPUT,
IOCTL_ASYNC,
com_handle );
#endif
if ( rc )
{
printmsg(0,"CD: Unable to get modem status");
printOS2error( "DosDevIOCtl", rc );
} /*if */
if ( status != oldstatus )
{
ShowModem( status );
oldstatus = status;
}
/*--------------------------------------------------------------------*/
/* If we previously had carrier detect but have lost it, we */
/* report it was lost. If we do not yet have carrier detect, */
/* we return success because we may not have connected yet. */
/*--------------------------------------------------------------------*/
carrierDetect = status && DCD_ON;
if (previousCarrierDetect)
return carrierDetect;
else
return (status && DSR_ON);
} /* nCD */
/*--------------------------------------------------------------------*/
/* S h o w M o d e m */
/* */
/* Report current modem status */
/*--------------------------------------------------------------------*/
#define mannounce(flag, bits, text ) ((flag & bits) ? text : "" )
static void ShowModem( const BYTE status )
{
if ( debuglevel < 4 )
return;
printmsg(0, "ShowModem: %#02x%s%s%s%s",
(int) status,
mannounce(DCD_ON, status, " Carrier Detect"),
mannounce(RI_ON, status, " Ring Indicator"),
mannounce(DSR_ON, status, " Data Set Ready"),
mannounce(CTS_ON, status, " Clear to Send"));
} /* ShowModem */
/*--------------------------------------------------------------------*/
/* S h o w E r r o r */
/* */
/* Report modem error bits in English (more or less) */
/*--------------------------------------------------------------------*/
static void ShowError( const USHORT status )
{
printmsg(2, "Port Error: %#04x%s%s%s%s",
(int) status,
mannounce(RX_QUE_OVERRUN, status, " Queue Overrrun"),
mannounce(RX_HARDWARE_OVERRUN, status, " Hardware Overrun"),
mannounce(PARITY_ERROR, status, " Parity Error"),
mannounce(FRAMING_ERROR, status, " Framing Error"));
} /* ShowError */