From pa.dec.com!decwrl!uunet!sparky!kent Sun Aug 11 15:43:35 PDT 1991
Article: 2587 of comp.sources.misc
Newsgroups: comp.sources.misc
Path: pa.dec.com!decwrl!uunet!sparky!kent
From: Warren Tucker <wht@n4hgf.Mt-Park.GA.US>
Subject:  v21i077:  ecu - ECU async comm package rev 3.10, Part25/37
Message-ID: <1991Aug4.163101.18787@sparky.IMD.Sterling.COM>
X-Md4-Signature: 18c456f139b784eda36937ac6fb2a3dd
Sender: kent@sparky.IMD.Sterling.COM (Kent Landfield)
Organization: Sterling Software, IMD
References: <csm-v21i053=ecu.215539@sparky.imd.sterling.com>
Date: Sun, 4 Aug 1991 16:31:01 GMT
Approved: kent@sparky.imd.sterling.com
Lines: 1589

Submitted-by: Warren Tucker <wht@n4hgf.Mt-Park.GA.US>
Posting-number: Volume 21, Issue 77
Archive-name: ecu/part25
Environment: SCO, XENIX, ISC
Supersedes: ecu3: Volume 16, Issue 25-59

---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is ecu310.25 (part 25 of ecu310)
# do not concatenate these parts, unpack them in order with /bin/sh
# file sea/sealink.doc continued
#
if touch 2>&1 | fgrep 'amc' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 25; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
	echo 'x - still skipping sea/sealink.doc'
else
echo 'x - continuing file sea/sealink.doc'
sed 's/^X//' << 'SHAR_EOF' >> 'sea/sealink.doc' &&
X     protocol.  The code provided should serve to document the details  and
X     fine  points  of  implementing SEAlink.  We will,  however,  present a
X     brief synopsis of how SEAlink adds sliding windows to XMODEM,  and why
X     XMODEM doesn't mind.
X
X     First of all,  SEAlink adds a block number to the ACK and NAK used  in
X     XMODEM.(1)  We  thus  create  "ACK/NAK  packets",  with  the following
X     structure:
X
X         Byte 0:   ACK, NAK, or C
X         Byte 1:   Block number
X         Byte 2:   One's compliment of block number
X
X     This is identical in form to the first three bytes of a  data  packet,
X     except that the SOH has been replaced with an ACK or NAK.(2)
X
X     From the receiver's point of view,  it does not matter if  the  trans-
X     mitter  is using sliding window or not.  The receiver simply sends ACK
X     and NAK packets as appropriate.  Any XMODEM driver tested to date will
X     simply ignore this excess data behind the ACK or NAK.
X
X     From the transmitter's point of view,  it just barely matters  if  the
X     receiver can handle sliding window.  The transmitter always acts as if
X     it  is  sending sliding window,  but varies the window size.  If it is
X     seeing valid block numbers and check values behind the  received  ACKs
X     and NAKs,  it sets the window size to six blocks.  Otherwise,  it sets
X     the  window  size  to  one  block.  The  result is that it only "sends
X     ahead" if the receiver can handle it.
X
X     It  should  be  a fairly simple matter to apply the underlying SEAlink
X     logic to almost any variant of XMODEM.
X
X
X     The  SEAlink  routines  provided  in  this package are also capable of
X     passing system dependent information,  such as true file size and time
X     of  last modification.  This data is passed in a special header block.
X     The header block looks exactly like any other block, except that it is
X     block number zero.
X
X     This is still backwards compatible with XMODEM,  as a SEAlink receiver
X     does  not  mind if block zero is missing,  and any XMODEM receiver yet
X     tested will regard block zero as a duplicate block and ACK it.
X
X     The data portion of block zero contains the following fields:
X
X
X         Offset    Size      Contents
X         ======    ====      ========
X
X            0        4       Original file length.
X            4        4       Date  and  time  file  was  last mofified,  in
X                             seconds since 1979.
X            8       17       Original  file  name,  as  a  null  terminated
X                             string.
X           25       15       Name  of  transmitting  program,   as  a  null
X                             terminated string.
X           40       88       Null filler and expansion area.
X
X
X     (1) XMODEM/CRC uses a "C" in place of  a  NAK  to  indicate  CRC  error
X         detection.  SEAlink  follows  this convention,  and supports either
X         checksum or CRC.  For brevity,  this document will use the term NAK
X         to mean either a true NAK (hex 15) or a C (hex 43).
X     (2) See previous footnote.
X
X     Any field which the transmitter cannot support should be  set  to  all
X     zeros.  Conversly,  the  receiver  should ignore any null fields.  The
X     receiver may ignore any field which he cannot support.
X
X
X
X     The  routines  enclosed  in  this package should be reasonably easy to
X     implement in your application.  We have attempted to exclude  compiler
X     dependent and system dependent logic from these routines.
X
X
X     You will need to alter our references to our communications driver  to
X     conform  to  your  own driver.  The communications related routines we
X     use are:
X
X         com_putc(c)         Output character c to comm port.
X
X         int com_getc(t)     Get character from comm port within  t  tenths
X                             of   a  second.   Return  EOF  if  time  limit
X                             expires.
X
X         com_dump()          Discard any pending output without sending it.
X
X
X     In  addition,  we  use  the  following  routines for controlling timed
X     loops:
X
X         long timerset(t)    Set a timer.  Returns a timer value which will
X                             expire in t tenths of a second.
X
X         int timeup(z)       Check a timer.  Returns true if  timer  z  has
X                             expired yet, or false otherwise.
X
X
X     These routines also make reference to the following functions for
X     system dependent information, which is optional:
X
X         filestat(name,&fs)  Read directory entry for  a  file  and  return
X                             system dependent information.
X
X         setstamp(f,dtg)     Set a file's date/time of last modification.
X
X
X
X
X     The SEAlink  implementation  provided  in  this  package  is  used  by
X     invoking the two primary routines:
X
X
X         int xmtfile(name)             /* transmit a file */
X         char *name;                   /* name of file to transmit */
X
X     This  routine is used to send a file.  One file is sent at a time.  If
X     the  name  is blank (name is null or *name points to a null),  then an
X     end of transmission marker is sent.
X
X     This routine returns a one if the file is successfully transmitted, or
X     a zero if a fatal error occurs.
X
X
X         char *rcvfile(name)           /* receive a file */
X         char *name;                   /* name of file (optional) */
X
X     This routine is used to receive a file.  One file is  received.  If  a
X     name is specified for the file,  then that name WILL be used,  and any
X     name  sent  by  the transmitter will be ignored.  If the name is blank
X     (name is null or *name points to a null),  then the  transmitter  must
X     provide a name for the file.
X
X     This routine returns a pointer to  the  name  of  the  file  that  was
X     received.  If the file transfer is not successful, then a null pointer
X     is returned.
X
X     The  pointer  returned  by  rcvfile()  points to a static data buffer.
X     This does not have to be freed (and should not be),  but  it  will  be
X     overwritten the next time rcvfile() is called.
X
X     The  rcvfile()  function  works  on a temporary file whose name is the
X     same as the final file,  but with a dash ("-") added at the beginning.
X     If  a  file  transfer  is  aborted,  then  this temporary file will be
X     retained.  An aborted file transfer will not harm a pre-existing  file
X     of the same name.
X
X
X
X     These  routines  can  be  used  for  either  single  or  multiple file
X     transfers.
X
X     To  send  multiple  files,  send  each  file one by one until either a
X     transmit fails or all files are sent.  If all  files  are  sent,  then
X     signal the end by calling xmtfile() with a null pointer.
X
X     To receive multiple files,  call rcvfile() repeatedly until it returns
X     a null pointer.
X
X
X
X     This  package includes a demonstration program named CLINK (pronounced
X     "clink"),  which is a  simple  TTY  program  for  doing  SEAlink  file
X     transfers.  CLINK  does  not  perform  any  sort of terminal emulation
X     whatsoever.  However,  she will make use of the ANSI.SYS screen driver
X     if you have it installed.
X
X
X     CLINK may be used in either of two ways: interactive mode or command
X     mode.
X
X     To use CLINK in the interactive mode, give the command "CLINK" with no
X     arguments.  Press  the  "ESCape"  key to give a command to CLINK.  The
X     command "?" (question mark) instructs CLINK to tell you what  commands
X     she understands.
X
X     To  use  CLINK  in the command mode,  give the command "CLINK" with an
X     argument.  There are three arguments you can give CLINK in the command
X     mode.  These are:
X
X      1) Receive files;  Do this with a command of the form:
X
X              CLINK R
X
X         CLINK  will  attempt  to receive one or more files from COM1,  and
X         will terminate as soon as all files  are  received,  or  when  the
X         transfer aborts.
X
X      2) Transmit files; Do this with a command of the form:
X
X              CLINK T <filename> ...
X
X         CLINK  will  attempt  to transmit the listed files over COM1,  and
X         will terminate as soon as all files are sent,  or the transfer  is
X         aborted.  <filename> may be one or more file names with or without
X         drive and path specifiers.  Wildcards may be used.
X
X      3) Give help;  If you type:
X
X              CLINK ?
X
X         or any invalid command,  CLINK will display a  brief  reminder  of
X         what arguments she understands in command mode.
X
X     In all cases, CLINK in the command mode will not alter the serial port
X     other than to set eight data bits,  one stop bit,  and no parity.  Any
X     previously installed serial drivers will be  replaced,  and  the  baud
X     rate will not be changed.
X
X
X
X     CLINK comes with her own serial driver built in for the IBM PC  family
X     and true compatibles,  but she is capable of using any standard FOSSIL
X     driver.
X
SHAR_EOF
echo 'File sea/sealink.doc is complete' &&
$TOUCH -am 0429171591 'sea/sealink.doc' &&
chmod 0644 sea/sealink.doc ||
echo 'restore of sea/sealink.doc failed'
Wc_c="`wc -c < 'sea/sealink.doc'`"
test 11247 -eq "$Wc_c" ||
	echo 'sea/sealink.doc: original size 11247, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= sea/sealink.imp ==============
if test -f 'sea/sealink.imp' -a X"$1" != X"-c"; then
	echo 'x - skipping sea/sealink.imp (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting sea/sealink.imp (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'sea/sealink.imp' &&
X    SEAlink - Sliding window file transfer protocol
X
X    XENIX System V version by Scott Reynolds
X    additional XENIX modifications by Sanford Zelkovitz, without whose help
X    this couldn't have been accomplished
X
X    Based on:
X
X    MS-DOS Version 1.16, created on 01/15/87 at 01:40:52
X(C) COPYRIGHT 1986,87 by System Enhancement Associates; ALL RIGHTS RESERVED
X    By:  Thom Henderson
X
X    Description:
X
X	This file contains a set of routines to illustrate the SEAlink
X	sliding window file transfer protocol.  SEAlink is fully backward
X	compatible to XMODEM, and can be easily adapted to most XMODEM
X	variants.
X
X	The intent of SEAlink is to provide a file transfer protocol that
X	does not suffer from propagation delays, such as are introduced
X	by satellite relays or packet switched networks.
X
X    Instructions:
X
X	Two routines are provided to implement SEAlink file transfers.
X
X	int xmtfile(name)		/+ transmit a file +/
X	char *name;			/+ name of file to transmit +/
X
X	This routine is used to send a file.  One file is sent at a time.
X	If the name is blank (name is null or *name points to a null),
X	then only an end of transmission marker is sent.
X
X	This routine returns a one if the file is successfully
X	transmitted, or a zero if a fatal error occurs.
X
X	char *rcvfile(name)		/+ receive a file +/
X	char *name;			/+ name of file (optional) +/
X
X	This routine is used to receive a file.  One file is received.
X	The name, if given, takes precedence and will be the name of
X	the resulting file.  If the name is blank (name is null or *name
X	points to a null), then the name given by the transmitter is used.
X	If the transmitter does not give a name, then the file transfer
X	is aborted.
X
X	This routine returns a pointer to the name of the file that
X	was received.  If the file transfer is not successful, then
X	a null pointer is returned.
X
X	The pointer returned by rcvfile() points to a static data buffer.
X	This does not have to be freed (and should not be), but it will
X	be overwritten the next time rcvfile() is called.
X
X	The rcvfile() function works on a temporary file whose name is
X	the same as the final file, but with a period (".") added at the
X	beginning.  If a file transfer is aborted, then this temporary
X	file will be retained.  An aborted file transfer will not harm
X	a pre-existing file of the same name.
X
X    Programming notes:
X
X	These routines can be used for either single or multiple file
X	transfers.
X
X	To send multiple files, send each one one at a time until either
X	a transmit fails or all files are sent.  If all files are sent,
X	then signal the end by calling xmtfile() with a null pointer.
X
X	To receive multiple files, call rcvfile() repeatedly until it
X	returns a null pointer.
X
X	These routines pass a "block zero", which contains information
X	about the original file name, size, and date/time of last
X	modification.  If you cannot implement block zero, then you can
X	leave it out.  If you cannot set any given field in block zero
X	when transmitting, then you should leave it set to zeros.  If you
X	cannot use any given field of block zero when receiving, then
X	you should ignore it.
X
X	These routines are fully compatible with XMODEM, including the
X	original checksum method and later CRC adaptations.  It can be
X	easily adapted to Modem7 protocol by adding a Modem7 filename
X	transfer shell, though we do not recommend it.  The underlying
X	logic, of course, can be adapted to almost any variant of XMODEM.
X
X    License:
X
X	You are granted a license to use this code in your programs, and
X	to adapt it to your particular situation and needs, subject only
X	to the following conditions:
X
X	1)   You must refer to it as the SEAlink protocol, and you must
X     	give credit to System Enhancement Associates.
X
X	2)   If you modify it in such a way that your version cannot
X     	converse with the original code as supplied by us, then
X     	you should refer to it as "SEAlink derived", or as a
X     	"variation of SEAlink", or words to that effect.
X
X	In short, we're not asking for any money, but we'd like to
X	get some credit for our work.
X
X    Language:
X
X	Computer Innovations C86
X	Adapted for IBM PC XENIX 2.00.2 C using UNIX System V compatible calls
X
X    Notes on XENIX modifications:
X
X	The com_getc() routine has a minimum delay of .1 seconds, due
X	to the nature of the read() system call.  Attempts to eliminate
X	this delay have proven more costly than leaving it in.
X
X	CRC maintenance functions were added to the original code, as
X	they are not library calls under XENIX.
X
X	All output is performed through file descriptor 0, and is done
X	in blocks using the write() system call rather than individual
X	character writes.  File descriptor 1 may be selected by invoking
X	the program with a "-1" argument.
X
X	Most low level routines utilize register class variables to
X	decrease overhead and improve overall system response slightly.
X
X	A rudimentary command line processor was added to the original
X	routines to drive the transmitter and receiver.  The two
X	options, "s" and "r", are for sending and receiving respectively.
X
X	When invoked without proper arguments the program will display
X	a short message including usage notes.
X
X	-- Scott Reynolds, Sysop U.S.S. Enterprise BBS, (906)228-9460
SHAR_EOF
$TOUCH -am 0429171591 'sea/sealink.imp' &&
chmod 0644 sea/sealink.imp ||
echo 'restore of sea/sealink.imp failed'
Wc_c="`wc -c < 'sea/sealink.imp'`"
test 5213 -eq "$Wc_c" ||
	echo 'sea/sealink.imp: original size 5213, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gendial/install_dialer ==============
if test -f 'gendial/install_dialer' -a X"$1" != X"-c"; then
	echo 'x - skipping gendial/install_dialer (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gendial/install_dialer (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gendial/install_dialer' &&
X:
X#+----------------------------------------------------------
X# install_dialer -  ECU gendial modem dial installation
X#+----------------------------------------------------------
X#+:EDITS:
X#:04-30-1991-16:07-root@n4hgf-add header and ls -l
X
X	echo Installing dialer $2 in $1
X	rm -f $1/$2 $1/$2~
X	if [ -f $1/$2 ]
X	then
X		mv $1/$2 $1/$2~
X	fi
X	cp $2 $1/$2
X	strip $1/$2
X	if [ -x /usr/bin/mcs ]; then /usr/bin/mcs -d $1/$2; fi
X	chown uucp $1/$2; chgrp uucp $1/$2
X	chmod 711 $1/$2
X	ls -l $1/$2
SHAR_EOF
$TOUCH -am 0430160891 'gendial/install_dialer' &&
chmod 0755 gendial/install_dialer ||
echo 'restore of gendial/install_dialer failed'
Wc_c="`wc -c < 'gendial/install_dialer'`"
test 488 -eq "$Wc_c" ||
	echo 'gendial/install_dialer: original size 488, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gendial/dceHA24.c ==============
if test -f 'gendial/dceHA24.c' -a X"$1" != X"-c"; then
	echo 'x - skipping gendial/dceHA24.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gendial/dceHA24.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gendial/dceHA24.c' &&
X/*+-------------------------------------------------------------------------
X	dceHA24.c - DCE-specific portion of generic SCO UUCP dialer
X	Driver for generic Hayes-style 2400 baud modem
X	wht@n4hgf.Mt-Park.GA.US
X
X Necessary DCE switch setting or other configuration:
X   enable onhook upon loss of DTR
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:07-25-1991-12:58-wht@n4hgf-ECU release 3.10 */
X/*:04-16-1991-18:18-wht@n4hgf-creation from template */
X
X#include "dialer.h"
X
X/*
X * DCE_DTR_low_msec - milliseconds to hold DTR low to ensure DCE
X *                    sees the transition; this value may be changed
X *                    as necessary before each call to ltoggleDTR(),
X * but, generally, a constant value will do.
X */
Xlong DCE_DTR_low_msec = 500L;
X
X/*
X * DCE_DTR_high_msec - milliseconds DTR must remain high before the
X *                     DCE may be expected to be ready to be commanded
X */
Xlong DCE_DTR_high_msec = 1500L;
X
X/*
X * DCE_write_pase_msec - milliseconds to pause between each character
X *                       sent to the DCE (zero if streaming I/O is
X *                       permitted); this value may be changed as
X * necessary before each call to lwrite(), but, generally, a constant
X * value will do.  Note that this value is used to feed a value to nap(),
X * which has a granularity of .010 seconds on UNIX/386, .020 on XENIX/286
X * and .050 seconds on XENIX/86.
X */
Xlong DCE_write_pace_msec = 40;
X
X/*
X * DCE_name     - short name for DCE
X * DCE_revision - revision number for this module
X */
Xchar *DCE_name = "generic AT-cmd 2400";
Xchar *DCE_revision = "1.10";
X
X/*
X * DCE_hangup_CBAUD - baud rate to use for hanging up DCE
X *                    and readying it for dial in access
X *                    (BXXX mask); use a value of zero if the speed
X *                    specified by the invoker is to be used.
X * This value is useful for DCEs such as the early Hayes 2400
X * which are so unfortunately compatible with their 1200 predecessor
X * that they refuse to answer at 2400 baud unless you last spoke to
X * them at that rate. For such bad boys, use B2400 below.
X */
Xint DCE_hangup_CBAUD = B2400;
X
X/*
X * DCE_results - a table of DCE response strings and a token
X *               code for each; when you call lread() or lread_ignore(),
X *               if the read routine detects one of the strings,
X * the appropriate code is returned.  If no string matches, then
X * lread()/lread_ignore examines the DCE result string for a
X * numeric value; if one is found, the numeric value or'd with
X * 0x4000 is returned (in this way, e.g., you can read "modem
X * S registers."  If nothing agrees with this search, lread()
X * will abort the program with RC|FAIL|RCE_TIMOUT, lread_ignore()
X * will return -1.  You may use any value between 0 and 0x3FFFFFFF.
X * This module is the only consumer  of the codes, although they
X * are decoded by gendial.c's _lread()
X */
X#define rfConnect		0x00400000
X#define rfMASK			0x000000FF
X
X#define rOk				0
X#define rNoCarrier		1
X#define rError			2
X#define rNoDialTone		3
X#define rBusy			4
X#define rNoAnswer		5
X#define rConnect300		(7 | rfConnect)
X#define rConnect1200	(8 | rfConnect)
X#define rConnect2400	(9 | rfConnect)
X
XDCE_RESULT DCE_results[] =
X{
X	{ "OK",						rOk,			},
X	{ "NO CARRIER",				rNoCarrier,		},
X	{ "ERROR",					rError			},
X	{ "NO DIALTONE",			rNoDialTone,	},
X	{ "BUSY",					rBusy			},
X	{ "NO ANSWER",				rNoAnswer		},
X	{ "CONNECT",				rConnect300		},
X	{ "CONNECT 1200",			rConnect1200	},
X	{ "CONNECT 2400",			rConnect2400	},
X	{ (char *)0,				-1				}		/* end table */
X};
X
X/*+-------------------------------------------------------------------------
X	DCE_baud_to_CBAUD(baud) - check for valid baud rates supported by DCE
X
X  DCE dependent function must validate baud rates supported by DCE
X  returns baud rate in struct termio c_cflag fashion
X  or terminates program with error
X--------------------------------------------------------------------------*/
Xint
XDCE_baud_to_CBAUD(baud)
Xunsigned int baud;
X{
X	switch(baud)
X	{
X		case 50:   return(B50);		/* delete the ones you dont handle */
X		case 75:   return(B75);
X		case 110:  return(B110);
X		case 134:  return(B134);
X		case 150:  return(B150);
X		case 300:  return(B300);
X		case 1200: return(B1200);
X		case 2400: return(B2400);
X		case 4800: return(B4800);
X		case 9600: return(B9600);
X
X#if defined(B19200)
X		case 19200: return(B19200);
X#else
X#ifdef EXTA
X		case 19200: return(EXTA);
X#endif
X#endif
X
X#if defined(B38400)
X		case 38400: return(B38400);
X#else
X#ifdef EXTB
X		case 38400: return(EXTB);
X#endif
X#endif
X
X	}
X	myexit(RC_FAIL | RCE_SPEED);
X}	/* end of DCE_baud_to_CBAUD */
X
X/*+-------------------------------------------------------------------------
X	DCE_hangup() - issue hangup command to DCE
X
XThis function should do whatever is necessary to ensure
X1) any active connection is terminated
X2) the DCE is ready to receive an incoming call if DTR is asserted
X3) the DCE will not accept an incoming call if DTR is false
X
XThe function should return when done.
X
XYou must set any switches necessary to make modem hang up on loss of DTR
X--------------------------------------------------------------------------*/
Xvoid
XDCE_hangup()
X{
Xint itmp;
Xint maxretry = 4;
X
X	DEBUG(3,"--> reseting %s\n",DCE_name);
X
X	ltoggleDTR(0L);
X
X	/*
X	 * set up modem
X	 */
X	for(itmp = 0; itmp < maxretry; itmp++)
X	{
X		lwrite("ATS0=1M0Q0V1X3\r");
X		if(lread(2) == rOk)
X			break;
X	}
X	if(itmp == maxretry)
X	{
X		DEBUG(1,"failed to reset modem\n",0);
X		myexit(RC_FAIL | RCE_TIMOUT);
X	}
X
X	/*
X	 * shut up - no result codes
X	 */
X	lwrite("ATQ1\r");
X
X}	/* end of DCE_hangup */
X
X/*+-------------------------------------------------------------------------
X	DCE_dial(telno) - dial a remote DCE
X
XThis function should connect to the remote DCE and use any success
Xindication to modify the tty baud rate if necessary before returning.
X
XUpon successful connection, return 0.
X
XUpon unsuccessful connection, return RC_FAIL or'd with an appropriate
XRCE_XXX value from dialer.h.
X
Xlwrite() is used to write to the DCE.
X
Xlread() and lread_ignore() are used to read from the DCE.  Read timeouts
Xfrom calling lread() will result automatically in the proper error
Xtermination of the program.  Read timeouts from calling lread_ignore()
Xreturn -1; you handle the execption here.
X
XAny necessary coding of phone numbers, switch settings or other
Xconfiguration necessary for this function to succeed should be
Xdocumented at the top of the module.
X--------------------------------------------------------------------------*/
Xint
XDCE_dial(telno)
Xchar *telno;
X{
Xchar cmd[128];
Xchar phone[50];
Xint timeout;
Xint result;
Xchar *cptr;
Xchar *dialout_default = "ATS0=0S7=40Q0M0V1E0X3\r";
X#define MDVALID	 "0123456789NnSs*#,!/()-"
Xint itmp;
Xint maxretry = 4;
X
X/* if root, let him see number, otherwise just say "remote system" */
X	DEBUG(1,"DIALING %s\n", (uid) ? "remote system" : telno);
X
X	ltoggleDTR(0L);
X
X	translate("=,-,",telno);
X	if(strspn(telno,MDVALID) != strlen(telno))
X	{
X		DEBUG(1,"phone number has invalid characters\n",0);
X		return(RC_FAIL | RCE_PHNO);
X	}
X	if(decode_phone_number(telno,phone,sizeof(phone)))
X	{
X		DEBUG(1,"phone number too long\n",0);
X		return(RC_FAIL | RCE_PHNO);
X	}
X
X	/*
X	 * wake up modem
X	 */
X	DEBUG(6,"--> waking up modem\n",0);
X	for(itmp = 0; itmp < maxretry; itmp++)
X	{
X		lwrite(dialout_default);
X		if(lread(2) == rOk)
X			break;
X	}
X	if(itmp == maxretry)
X	{
X		DEBUG(1,"DIAL INIT FAILED\n",0);
X		myexit(RC_FAIL | RCE_TIMOUT);
X	}
X
X	/*
X	 * calculate a timeout for the connect
X	 * allow a minimum of 40 seconds
X	 * if long distance (North American calculation here)
X	 * make it 132 (S7 is calculated as timeout * .9)
X	 */
X	timeout = 40;
X	if((phone[0] == '1') && (phone[0] != '0'))
X		timeout = 132;
X	if((timeout < 90) && (dialer_codes['V' - 'A'] || dialer_codes['P' - 'A']))
X		timeout = 90;
X	for(cptr = phone; cptr = strchr(cptr,','); cptr++)
X		timeout += 2;	/* add extra time for pause characters */
X	DEBUG(6,"timeout waiting for connect = %d seconds\n",timeout);
X
X/* indicate non-root should not see DTE->DCE traffic */
X	secure = 1;
X
X/*
X * build and issue the actual dialing command
X * if root, let him see number, otherwise just say "remote system"
X */
X	DEBUG(1,"--> dialing %s\n", (!ecu_calling & uid) ? "remote system" : telno);
X#ifdef WHT
X	if(!strncmp(*gargv,"ECU",3))
X		dialer_codes['S' - 'A'] = 1;
X#endif
X	sprintf(cmd,"ATM%dS7=%dDT%s\r",
X		((dialer_codes['S' - 'A']) && !(dialer_codes['N' - 'A'])) ? 1 : 0,
X		(timeout * 9) / 10,
X		phone);
X
X	/* cmd string can only be 40 characters including "AT" */
X	if(strlen(cmd) > 40)
X	{
X		DEBUG(1,"phone number string too long\n",0);
X		cleanup(RC_FAIL | RCE_PHNO);
X	}
X	lwrite(cmd);
X
X/* indicate non-root can see DTE->DCE traffic */
X	secure = 0;
X
X/* wait for connect */
X	result = lread(timeout);
X	if(!(result & rfConnect))
X	{
X		switch(result & rfMASK)
X		{
X		case rNoCarrier:
X			return(RC_FAIL | RCE_NOCARR);
X		case rNoDialTone:
X			return(RC_FAIL | RCE_NOTONE);
X		case rBusy:
X			return(RC_FAIL | RCE_BUSY);
X		case rNoAnswer:
X			return(RC_FAIL | RCE_ANSWER);
X		case rError:
X		default:
X			return(RC_FAIL | RCE_NULL);
X		}
X	}
X
X/* indicate non-root can see DTE->DCE traffic */
X	secure = 0;
X	return(0);		/* succeeded */
X
X}	/* end of DCE_dial */
X
X/**********************************************************
X*  You probably do not need to modify the code below here *
X**********************************************************/
X
X/*+-------------------------------------------------------------------------
X	DCE_abort(sig) - dial attempt aborted
X
X sig =  0 if non-signal abort (read timeout, most likely)
X     != 0 if non-SIGALRM signal caught
X
X extern int dialing set  1 if dialing request was active,
X                    else 0 if hangup request was active
X
XThis is a chance for the DCE-specific code to do anything it
Xneeds to cl,ean up after a failure.  Note that if a dialing
Xcall fails, it is the responsibility of the higher-level
Xprogram calling the dialer to call it again with a hangup request, so
Xthis function is usually a no-op.
X--------------------------------------------------------------------------*/
Xvoid
XDCE_abort(sig)
Xint sig;
X{
X	DEBUG(10,"DCE_abort(%d);\n",sig);
X}	/* end of DCE_abort */
X
X/*+-------------------------------------------------------------------------
X	DCE_exit(exitcode) - "last chance for gas" in this incarnation
X
XThe independent portion of the dialer program calls this routine in
Xlieu of exit() in every case except one (see DCE_argv_hook() below).
XNormally, this function just passes it's argument to exit(), but
Xany necessary post-processing can be done.  The function must,
Xhowever, eventually call exit(exitcode);
X--------------------------------------------------------------------------*/
Xvoid
XDCE_exit(exitcode)
Xint exitcode;
X{
X	DEBUG(10,"DCE_exit(%d);\n",exitcode);
X	exit(exitcode);
X}	/* end of DCE_exit */
X
X/*+-------------------------------------------------------------------------
X	DCE_argv_hook(argc,argv,optind,unrecognized_switches)
X
XThis hook gives DCE-specific code a chance to look over the entire
Xcommand line, such as for -z Telebit processing.
X
Xargc andf argv are the same values passed to main(),
X
Xoptind is the value of optind at the end of normal getopt processing.
X
Xunrecognized_switches is the count of switches not handled by main().
XSpecifically, -h and -x are standard switches.
X
XNormally, this function should just return RC_FAIL|RCE_ARGS if there are
Xany unrecognized switches, otherwise zero.  If you keep your nose clean
Xthough, you can do anything you need to do here and exit the program.
X
XNote: only simple switches (with no argument) may be used with this
Xfacility if the functrion is to return,' since main()'s getopt() will
Xstop processing switches if it runs into an unrecognized switch with an
Xargument.
X
XIf the function returns a non-zero value, then the value will be passed
XDIRECTLY to exit() with no further ado.  Thus, a non-zero value must be
Xof the format expected by dialer program callers, with RC_FAIL set as a
Xminimum.
X--------------------------------------------------------------------------*/
Xint
XDCE_argv_hook(argc,argv,optind,unrecognized_switches)
Xint argc;
Xchar **argv;
Xint optind;
Xint unrecognized_switches;
X{
X	if(unrecognized_switches)
X		return(RC_FAIL | RCE_ARGS);
X	return(0);
X}	/* end of DCE_argv_hook */
X
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
$TOUCH -am 0725125891 'gendial/dceHA24.c' &&
chmod 0644 gendial/dceHA24.c ||
echo 'restore of gendial/dceHA24.c failed'
Wc_c="`wc -c < 'gendial/dceHA24.c'`"
test 12305 -eq "$Wc_c" ||
	echo 'gendial/dceHA24.c: original size 12305, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gendial/dceMC9624.c ==============
if test -f 'gendial/dceMC9624.c' -a X"$1" != X"-c"; then
	echo 'x - skipping gendial/dceMC9624.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gendial/dceMC9624.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gendial/dceMC9624.c' &&
X/* CHK=0xB3C9 */
X/*+-------------------------------------------------------------------------
X	dceMC9624.c - DCE-specific portion of generic SCO UUCP dialer
X	Driver for Microcom AX/9624c (assuming DTMF dialing only)
X	wht@n4hgf.Mt-Park.GA.US
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:07-25-1991-12:58-wht@n4hgf-ECU release 3.10 */
X/*:03-12-1991-19:11-wht@n4hgf-if ecu dialing, show complete call progress */
X/*:01-05-1991-13:48-root@n4hgf-ATZ during reset - modem is flakey */
X/*:11-29-1990-18:31-r@n4hgf-revision/1st releasable */
X/*:07-24-1990-15:36-wht@n4hgf-add speaker on/off */
X/*:07-20-1990-00:10-wht@n4hgf-creation */
X
X#include "dialer.h"
X
X/*
X * DCE_DTR_low_msec - milliseconds to hold DTR low to ensure DCE
X *                    sees the transition; this value may be changed
X *                    as necessary before each call to ltoggleDTR(),
X * but, generally, a constant value will do.
X */
Xlong DCE_DTR_low_msec = 500;
X
X/*
X * DCE_DTR_high_msec - milliseconds DTR must remain high before the
X *                     DCE may be expected to be ready to be commanded
X */
Xlong DCE_DTR_high_msec = 500;
X
X/*
X * DCE_write_pase_msec - milliseconds to pause between each character
X *                       sent to the DCE (zero if streaming I/O is
X *                       permitted); this value may be changed as
X * necessary before each call to lwrite(), but, generally, a constant
X * value will do.  Note that this value is used to feed a value to nap(),
X * which has a granularity of .010 seconds on UNIX/386, .020 on XENIX/286
X * and .050 seconds on XENIX/86.
X */
Xlong DCE_write_pace_msec = 0;
X
X/*
X * DCE_name     - short name for DCE
X * DCE_revision - revision number for this module
X */
Xchar *DCE_name = "Microcom AX/9624c";
Xchar *DCE_revision = "1.10";
X
X/*
X * DCE_hangup_CBAUD - baud rate to use for hanging up DCE
X *                    and readying it for dial in access
X *                    (BXXX mask); use a value of zero if the speed
X *                    specified by the invoker is to be used.
X * This value is useful for DCEs such as the early Hayes 2400
X * which are so unfortunately compatible with their 1200 predecessor
X * that they refuse to answer at 2400 baud unless you last spoke to
X * them at that rate. For such bad boys, use B2400 below.
X */
Xint DCE_hangup_CBAUD = 0;
X/* int DCE_hangup_CBAUD = B2400; */
X
X/*
X * DCE_results - a table of DCE response strings and a token
X *               code for each; when you call lread() or lread_ignore(),
X *               if the read routine detects one of the strings,
X * the appropriate code is returned.  If no string matches, then
X * lread()/lread_ignore examines the DCE result string for a
X * numeric value; if one is found, the numeric value or'd with
X * 0x40000000 is returned (in this way, e.g., you can read "modem
X * S registers").  If nothing agrees with this search, lread()
X * will abort the program with RC|FAIL|RCE_TIMOUT, lread_ignore()
X * will return -1.  You may use any value between 0 and 0x3FFFFFFF.
X * This module is the only consumer  of the codes, although they
X * are decoded by gendial.c's _lread()
X */
X
X/* flag bits */
X#define rfConnect		0x00800000
X#define rfREL			0x00400000
X#define rfMASK			0x0000FFFF	/* mask off rfBits */
X
X/* unique codes */
X#define rOk				0
X#define rNoCarrier		1
X#define rError			2
X#define rNoDialTone 	3
X#define rBusy			4
X#define rNoAnswer		5
X#define rConnect300		(  300  | rfConnect)
X#define rConnect1200	( 1200  | rfConnect)
X#define rConnect2400	( 1200  | rfConnect)
X#define rConnect4800	( 4800  | rfConnect)
X#define rConnect9600	( 9600  | rfConnect)
X#define rConnect300R	(  300  | rfConnect | rfREL)
X#define rConnect1200R	( 1200  | rfConnect | rfREL)
X#define rConnect2400R	( 2400  | rfConnect | rfREL)
X#define rConnect4800R	( 4800  | rfConnect | rfREL)
X#define rConnect9600R	( 9600  | rfConnect | rfREL)
X
XDCE_RESULT DCE_results[] =
X{
X	{ "OK",						rOk,			},
X	{ "NO CARRIER",				rNoCarrier,		},
X	{ "ERROR",					rError			},
X	{ "NO DIALTONE",			rNoDialTone,	},
X	{ "BUSY",					rBusy			},
X	{ "NO ANSWER",				rNoAnswer		},
X	{ "CONNECT 300/REL",		rConnect300R	},
X	{ "CONNECT 1200/REL",		rConnect1200R	},
X	{ "CONNECT 2400/REL",		rConnect2400R	},
X	{ "CONNECT 4800/REL",		rConnect4800R	},
X	{ "CONNECT 9600/REL",		rConnect9600R	},
X	{ "CONNECT 300",			rConnect300		},
X	{ "CONNECT 1200",			rConnect1200	},
X	{ "CONNECT 2400",			rConnect2400	},
X	{ "CONNECT 4800",			rConnect4800 	},
X	{ "CONNECT 9600",			rConnect9600	},
X	{ (char *)0,				-1				}		/* end table */
X};
X
X/*+-------------------------------------------------------------------------
X	DCE_baud_to_CBAUD(baud) - check for valid baud rates supported by DCE
X
X  DCE dependent function must validate baud rates supported by DCE
X  returns baud rate in struct termio c_cflag fashion
X  or terminates program with error
X--------------------------------------------------------------------------*/
Xint
XDCE_baud_to_CBAUD(baud)
Xunsigned int baud;
X{
X	switch(baud)
X	{
X		case 110:  return(B110);
X		case 300:  return(B300);
X		case 1200: return(B1200);
X		case 2400: return(B2400);
X		case 4800: return(B4800);
X		case 9600: return(B9600);
X
X#if defined(B19200)
X		case 19200: return(B19200);
X#else
X#ifdef EXTA
X		case 19200: return(EXTA);
X#endif
X#endif
X
X	}
X	myexit(RC_FAIL | RCE_SPEED);
X}	/* end of DCE_baud_to_CBAUD */
X
X/*+-------------------------------------------------------------------------
X	sync_Microcom() - sync modem with our DTE speed
X--------------------------------------------------------------------------*/
Xvoid
Xsync_Microcom()
X{
Xregister int maxretry = 4;
X
X	while(maxretry--)
X	{
X		lflush();
X		DCE_write_pace_msec = 20;
X		lwrite("ATQ0E1V1\r");
X		DCE_write_pace_msec = 0;
X		if(lread_ignore(2) == rOk)
X			return;
X	}
X
X	DEBUG(1,"Microcom SYNC FAILED\n",0);
X	myexit(RC_FAIL | RCE_TIMOUT);
X
X}	/* end of sync_Microcom */
X
X/*+-------------------------------------------------------------------------
X	DCE_hangup() - issue hangup command to DCE
X
XThis function should do whatever is necessary to ensure
X1) any active connection is terminated
X2) the DCE is ready to receive an incoming call if DTR is asserted
X3) the DCE will not accept an incoming call if DTR is false
X
XThe function should return when done.
X
XAny necessary switch setting or other configuration necessary for this
Xfunction to succeed should be documented at the top of the module.
X--------------------------------------------------------------------------*/
Xvoid
XDCE_hangup()
X{
Xchar *reset_it = "ATZ\r";
Xchar *dialin = "ATS0=1Q1E0M0\\N3\\Q1\\G1%C1%P2\r";
X
X	DEBUG(7,"--> reseting %s\n",dce_name);
X
X	ltoggleDTR(2000L);
X	sync_Microcom();
X	lwrite(reset_it);
X	lread_ignore(5);
X	lwrite(dialin);
X	nap(500L);
X
X}	/* end of DCE_hangup */
X
X/*+-------------------------------------------------------------------------
X	DCE_dial(telno) - dial a remote DCE
X
XThis function should connect to the remote DCE and use any success
Xindication to modify the tty baud rate if necessary before returning.
X
XUpon successful connection, return 0.
X
XUpon unsuccessful connection, return RC_FAIL or'd with an appropriate
XRCE_XXX value from dialer.h.
X
Xlwrite() is used to write to the DCE.
X
Xlread() and lread_ignore() are used to read from the DCE.  Read timeouts
Xfrom calling lread() will result automatically in the proper error
Xtermination of the program.  Read timeouts from calling lread_ignore()
Xreturn -1; you handle the execption here.
X
XAny necessary coding of phone numbers, switch settings or other
Xconfiguration necessary for this function to succeed should be
Xdocumented at the top of the module.
X
XMicrocom Plus-specific comments:
X--------------------------------------------------------------------------*/
Xint
XDCE_dial(telno)
Xchar *telno;
X{
Xchar cmd[128];
Xint timeout;
Xint result;
Xchar *cptr;
Xchar phone[42];
X#define MDVALID "0123456789NnSs,*#()-"
Xchar *setup      = "ATQ0E1V1X4S0=0&D2&C1%C1%P2";
Xchar *setup_REL  = "\\N3\\Q1\\G1";
Xchar *setup_NORM = "\\N0\\Q0\\G0";
X
X/* preliminary setup */
X	translate("=,-,",telno);
X	if(strspn(telno,MDVALID) != strlen(telno))
X	{
X		DEBUG(1,"phone number has invalid characters\n",0);
X		return(RC_FAIL | RCE_PHNO);
X	}
X	if(decode_phone_number(telno,phone,sizeof(phone)))
X	{
X		DEBUG(1,"phone number too long\n",0);
X		return(RC_FAIL | RCE_PHNO);
X	}
X
X/*
X * calculate a timeout for the connect
X * allow a minimum of 40 seconds, if reliable, 50
X * also if long distance (North American calculation here)
X * make it 132
X */
X	timeout = 40;
X	if(hiCBAUD > B2400)
X		timeout = 50;
X	if((phone[0] == '1') && (phone[0] != '0'))
X		timeout = 132;
X	for(cptr = phone; cptr = strchr(cptr,','); cptr++)
X		timeout += 2;	/* add extra time for pause characters */
X	DEBUG(6,"timeout waiting for connect = %d seconds\n",timeout);
X
X/*
X * build and issue the dialout setup command
X * 9624's S7 timing is way off (S7 is calculated as timeout * .6)
X */
X	DEBUG(1,"--> issuing setup command\n",0);
X	sprintf(cmd,"%s%sS7=%d\r",
X		setup,
X		(hiCBAUD > B2400) ? setup_REL : setup_NORM,
X		(timeout * 6) / 10);
X
X	sync_Microcom();
X	lwrite(cmd);
X	if(lread(2) != rOk)
X		return(RC_FAIL | RCE_NULL);
X
X/* indicate non-root should not see DTE->DCE traffic */
X	secure = 1;
X
X/*
X * build and issue the actual dialing command
X * if root, let him see number, otherwise just say "remote system"
X */
X#ifdef WHT
X	if(!strncmp(*gargv,"ECU",3))
X		dialer_codes['S' - 'A'] = 1;
X#endif
X	DEBUG(1,"--> dialing %s\n", (!ecu_calling & uid) ? "remote system" : phone);
X	sprintf(cmd,"ATS2=1M%dDT%s\r",
X		((dialer_codes['S' - 'A']) && !(dialer_codes['N' - 'A'])) ? 1 : 0,
X		phone);
X
X	/* cmd string can only be 40 characters including "AT" */
X	if(strlen(cmd) > 40)
X	{
X		DEBUG(1,"phone number string too long\n",0);
X		cleanup(RC_FAIL | RCE_PHNO);
X	}
X
X	lwrite(cmd);
X
X/* indicate non-root can see DTE->DCE traffic */
X	secure = 0;
X
X/* wait for connect */
X	result = lread(timeout);
X	if(!(result & rfConnect))
X	{
X		switch(result & rfMASK)
X		{
X		case rNoDialTone:
X			return(RC_FAIL | RCE_NOTONE);
X		case rBusy:
X			return(RC_FAIL | RCE_BUSY);
X		case rNoAnswer:
X		case rNoCarrier:	/* with ATX4, NO CARRIER == NO ANSWER
X							 * since BUSY and NO DIAL TONE are reported
X							 */
X			return(RC_FAIL | RCE_ANSWER);
X		default:
X			return(RC_FAIL | RCE_NULL);
X		}
X	}
X
X	return(0);		/* succeeded */
X
X}	/* end of DCE_dial */
X
X/**********************************************************
X*  You probably do not need to modify the code below here *
X**********************************************************/
X
X/*+-------------------------------------------------------------------------
X	DCE_abort(sig) - dial attempt aborted
X
X sig =  0 if non-signal abort (read timeout, most likely)
X     != 0 if non-SIGALRM signal caught
X
X extern int dialing set  1 if dialing request was active,
X                    else 0 if hangup request was active
X
XThis is a chance for the DCE-specific code to do anything it
Xneeds to cl,ean up after a failure.  Note that if a dialing
Xcall fails, it is the responsibility of the higher-level
Xprogram calling the dialer to call it again with a hangup request, so
Xthis function is usually a no-op.
X--------------------------------------------------------------------------*/
Xvoid
XDCE_abort(sig)
Xint sig;
X{
X	DEBUG(10,"DCE_abort(%d);\n",sig);
X}	/* end of DCE_abort */
X
X/*+-------------------------------------------------------------------------
X	DCE_exit(exitcode) - "last chance for gas" in this incarnation
X
XThe independent portion of the dialer program calls this routine in
Xlieu of exit() in every case except one (see DCE_argv_hook() below).
XNormally, this function just passes it's argument to exit(), but
Xany necessary post-processing can be done.  The function must,
Xhowever, eventually call exit(exitcode);
X--------------------------------------------------------------------------*/
Xvoid
XDCE_exit(exitcode)
Xint exitcode;
X{
X	DEBUG(10,"DCE_exit(%d);\n",exitcode);
X	exit(exitcode);
X}	/* end of DCE_exit */
X
X/*+-------------------------------------------------------------------------
X	DCE_argv_hook(argc,argv,optind,unrecognized_switches)
X
XThis hook gives DCE-specific code a chance to look over the entire
Xcommand line, such as for -z processing.
X
Xargc andf argv are the same values passed to main(),
X
Xoptind is the value of optind at the end of normal getopt processing.
X
Xunrecognized_switches is the count of switches not handled by main().
XSpecifically, -h and -x are standard switches.
X
XNormally, this function should just return RC_FAIL|RCE_ARGS if there are
Xany unrecognized switches, otherwise zero.  If you keep your nose clean
Xthough, you can do anything you need to do here and exit the program.
X
XNote: only simple switches (with no argument) may be used with this
Xfacility if the functrion is to return,' since main()'s getopt() will
Xstop processing switches if it runs into an unrecognized switch with an
Xargument.
X
XIf the function returns a non-zero value, then the value will be passed
XDIRECTLY to exit() with no further ado.  Thus, a non-zero value must be
Xof the format expected by dialer program callers, with RC_FAIL set as a
Xminimum.
X--------------------------------------------------------------------------*/
Xint
XDCE_argv_hook(argc,argv,optind,unrecognized_switches)
Xint argc;
Xchar **argv;
Xint optind;
Xint unrecognized_switches;
X{
X	if(unrecognized_switches)
X		return(RC_FAIL | RCE_ARGS);
X	return(0);
X}	/* end of DCE_argv_hook */
X
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
$TOUCH -am 0725125891 'gendial/dceMC9624.c' &&
chmod 0644 gendial/dceMC9624.c ||
echo 'restore of gendial/dceMC9624.c failed'
Wc_c="`wc -c < 'gendial/dceMC9624.c'`"
test 13317 -eq "$Wc_c" ||
	echo 'gendial/dceMC9624.c: original size 13317, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gendial/dceMPAD.c ==============
if test -f 'gendial/dceMPAD.c' -a X"$1" != X"-c"; then
	echo 'x - skipping gendial/dceMPAD.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gendial/dceMPAD.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gendial/dceMPAD.c' &&
X/* CHK=0xFF53 */
X/*+-------------------------------------------------------------------------
X	dceMPAD.c - DCE-specific portion of generic SCO UUCP dialer
X	Driver for ATT Tridom MPAD VSAT modem emulation
X	wht@n4hgf.Mt-Park.GA.US
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:07-25-1991-12:58-wht@n4hgf-ECU release 3.10 */
X/*:03-12-1991-19:11-wht@n4hgf-if ecu dialing, show complete call progress */
X/*:11-29-1990-18:31-r@n4hgf-revision/1st releasable */
X/*:11-29-1990-17:48-wht@n4hgf-creation */
X
X#include "dialer.h"
X
X/*
X * DCE_DTR_low_msec - milliseconds to hold DTR low to ensure DCE
X *                    sees the transition; this value may be changed
X *                    as necessary before each call to ltoggleDTR(),
X * but, generally, a constant value will do.
X */
Xlong DCE_DTR_low_msec = 50;
X
X/*
X * DCE_DTR_high_msec - milliseconds DTR must remain high before the
X *                     DCE may be expected to be ready to be commanded
X */
Xlong DCE_DTR_high_msec = 50;
X
X/*
X * DCE_write_pase_msec - milliseconds to pause between each character
X *                       sent to the DCE (zero if streaming I/O is
X *                       permitted); this value may be changed as
X * necessary before each call to lwrite(), but, generally, a constant
X * value will do.  Note that this value is used to feed a value to nap(),
X * which has a granularity of .010 seconds on UNIX/386, .020 on XENIX/286
X * and .050 seconds on XENIX/86.
X */
Xlong DCE_write_pace_msec = 0;
X
X/*
X * DCE_name     - short name for DCE
X * DCE_revision - revision number for this module
X */
Xchar *DCE_name = "ATT Tridom MPAD";
Xchar *DCE_revision = "1.10";
X
X/*
X * DCE_hangup_CBAUD - baud rate to use for hanging up DCE
X *                    and readying it for dial in access
X *                    (BXXX mask); use a value of zero if the speed
X *                    specified by the invoker is to be used.
X * This value is useful for DCEs such as the early Hayes 2400
X * which are so unfortunately compatible with their 1200 predecessor
X * that they refuse to answer at 2400 baud unless you last spoke to
X * them at that rate. For such bad boys, use B2400 below.
X */
Xint DCE_hangup_CBAUD = 0;
X/* int DCE_hangup_CBAUD = B2400; */
X
X/*
X * DCE_results - a table of DCE response strings and a token
X *               code for each; when you call lread() or lread_ignore(),
X *               if the read routine detects one of the strings,
X * the appropriate code is returned.  If no string matches, then
X * lread()/lread_ignore examines the DCE result string for a
X * numeric value; if one is found, the numeric value or'd with
X * 0x40000000 is returned (in this way, e.g., you can read "modem
X * S registers").  If nothing agrees with this search, lread()
X * will abort the program with RC|FAIL|RCE_TIMOUT, lread_ignore()
X * will return -1.  You may use any value between 0 and 0x3FFFFFFF.
X * This module is the only consumer  of the codes, although they
X * are decoded by gendial.c's _lread()
X */
X
X/* flag bits */
X#define rfConnect		0x00800000
X#define rfMASK			0x0000FFFF	/* mask off rfBits */
X
X/* unique codes */
X#define rOk				0
X#define rNoCarrier		1
X#define rError			2
X#define rNoDialTone 	3
X#define rBusy			4
X#define rNoAnswer		5
X#define rRring			6
X#define rConnect300		(  300  | rfConnect)
X#define rConnect1200	( 1200  | rfConnect)
X#define rConnect2400	( 2400  | rfConnect)
X#define rConnect4800	( 4800  | rfConnect)
X#define rConnect9600	( 9600  | rfConnect)
X#define rConnect9600	( 9600  | rfConnect)
X#define rConnect19200	(19200  | rfConnect)
X#define rConnect38400	(38400  | rfConnect)
X
XDCE_RESULT DCE_results[] =
X{
X	{ "OK",					rOk,			},
X	{ "NO CARRIER",			rNoCarrier,		},
X	{ "ERROR",				rError			},
X	{ "BUSY",				rBusy			},
X	{ "NO ANSWER",			rNoAnswer		},
X    { "NO DIAL TONE",       rNoDialTone     },
X    { "KDIR SENDX ERROR",   rNoDialTone     },  /* MPAD software error */
X    { "KDIR UNRESPONSIVE",  rNoDialTone     },
X    { "KDIR BUSY",          rBusy           },
X    { "KDIR BAD REQUEST",   rError          },  /* number 0 or >11 length */
X    { "NO SUCH NUMBER",     rNoAnswer       },
X    { "KDIR LOGIC ERROR",   rNoDialTone     },  /* MPAD software error */
X    { "KDIR NOT AVAIL",     rNoDialTone     },
X    { "TP4 STATE ERROR",    rNoDialTone     },  /* rain fade */
X    { "TP4 GIVE UP",        rBusy           },  /* rain fade */
X    { "TP4 ERROR RESP",     rBusy           },  /* transient problem */
X    { "NET DEACT",          rNoDialTone     },  /* net op deactivated port */
X	{ "CONNECT 300",		rConnect300		},
X	{ "CONNECT 1200",		rConnect1200	},
X	{ "CONNECT 4800",		rConnect4800	},
X	{ "CONNECT 9600",		rConnect9600	},
X	{ "CONNECT 19200",		rConnect19200	},
X	{ "CONNECT 38400",		rConnect38400	},
X	{ (char *)0,			-1				}		/* end table */
X};
X
X/*+-------------------------------------------------------------------------
X	DCE_baud_to_CBAUD(baud) - check for valid baud rates supported by DCE
X
X  DCE dependent function must validate baud rates supported by DCE
X  returns baud rate in struct termio c_cflag fashion
X  or terminates program with error
X--------------------------------------------------------------------------*/
Xint
XDCE_baud_to_CBAUD(baud)
Xunsigned int baud;
X{
X	switch(baud)
X	{
X		case 110:  return(B110);
X		case 300:  return(B300);
X		case 1200: return(B1200);
X		case 2400: return(B2400);
X		case 9600: return(B9600);
X
X#if defined(B19200)
X		case 19200: return(B19200);
X#else
X#ifdef EXTA
X		case 19200: return(EXTA);
X#endif
X#endif
X
X#if defined(B38400)
X		case 38400: return(B38400);
X#else
X#ifdef EXTB
X		case 38400: return(EXTB);
X#endif
X#endif
X
X	}
X	myexit(RC_FAIL | RCE_SPEED);
X}	/* end of DCE_baud_to_CBAUD */
X
X/*+-------------------------------------------------------------------------
X	sync_MPAD() - sync modem with our DTE speed
X--------------------------------------------------------------------------*/
Xvoid
Xsync_MPAD()
X{
Xregister int maxretry = 8;
Xregister int count;
Xunsigned char rdchar;
X
X	while(maxretry--)
X	{
X		lflush();
X		write(fddce,"a",1);
X		count = 5;
X		while(count)	/* wait 50-200 msec for character, depending on HZ */
X		{
X			if(rdchk(fddce))
X				break;
X			nap(50L);
X			count--;
X		}
X		if(count && (read(fddce,&rdchar,1) == 1) && (rdchar == 'a'))
X			return;
X		write(fddce,"atq0v1e1\r",9);
X		nap(500L);
X	}
X
X	DEBUG(1,"MPAD SYNC FAILED\n",0);
X	myexit(RC_FAIL | RCE_TIMOUT);
X
X}	/* end of sync_MPAD */
X
X/*+-------------------------------------------------------------------------
X	init_MPAD() - init MPAD from scratch, assuming nothing
X--------------------------------------------------------------------------*/
Xvoid
Xinit_MPAD()
X{
Xregister itmp;
Xint maxretry = 4;
Xchar *init0 = "ATE0Q0V1X99S0=1S2=1\r";
X
X	DEBUG(7,"--> reseting %s\n",dce_name);
X	ltoggleDTR(0L);
X	sync_MPAD();
X
X	/*
X	 * set to factory default (bless them for this command)
X	 * and a few initial beachhead values
X	 */
X	for(itmp = 0; itmp < maxretry; itmp++)
X	{
X		lwrite(init0);
X		if(lread(2) == rOk)
X			break;
X	}
X	if(itmp == maxretry)
X	{
X		DEBUG(1,"reset failed\n",0);
X		myexit(RC_FAIL | RCE_TIMOUT);
X	}
X
X}	/* end of init_MPAD */
X
X/*+-------------------------------------------------------------------------
X	DCE_hangup() - issue hangup command to DCE
X
XThis function should do whatever is necessary to ensure
X1) any active connection is terminated
X2) the DCE is ready to receive an incoming call if DTR is asserted
X3) the DCE will not accept an incoming call if DTR is false
X
XThe function should return when done.
X
XAny necessary switch setting or other configuration necessary for this
Xfunction to succeed should be documented at the top of the module.
X--------------------------------------------------------------------------*/
Xvoid
XDCE_hangup()
X{
X	ltoggleDTR(0L);
X	init_MPAD();
X
X}	/* end of DCE_hangup */
X
X/*+-------------------------------------------------------------------------
X	DCE_dial(telno) - dial a remote DCE
X
XThis function should connect to the remote DCE and use any success
Xindication to modify the tty baud rate if necessary before returning.
X
XUpon successful connection, return 0.
SHAR_EOF
true || echo 'restore of gendial/dceMPAD.c failed'
fi
echo 'End of ecu310 part 25'
echo 'File gendial/dceMPAD.c is continued in part 26'
echo 26 > _shar_seq_.tmp
exit 0
--------------------------------------------------------------------
Warren Tucker, TuckerWare emory!n4hgf!wht or wht@n4hgf.Mt-Park.GA.US
Hacker Extraordinaire  d' async PADs,  pods,  proteins and protocols

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.


