[comp.dcom.modems] Telebit TrailBlazer dialer

nerd@percival.UUCP (Michael Galassi) (02/22/88)

By popular request I'm re-posting this, I was going to mail the updated
version but got enough requests within 24 hours of my original posting
that I feel the nets cost as a whole will be lower if I post the whole
darn thing again rather than mail out many copies to individuals.  As
I state in the comments at the start of tb.c (the dialer) the original
structure of the routine came from the ucb distribution but has gone
through so much that I don't think there are any problems with proprietary
code being posted.

If you find any problems with this and make any changes to this beyond
tuning for your specific site I would very much apreciate getting diffs
or a copy of the whole thing, god knows there are probably a dozen better
ways of doing things than the way I have chosen.

Last note, my comments are probably full of spelling errors, I don't
realy care to know about it, they are your problem if you care to read
them, you do have an alternative.

-- 
        Michael Galassi           | If my opinions happen to be the same as
...!tektronix!tessi!percival!nerd | my employer's it is ONLY a coincidence,
...!uunet!littlei!percival!nerd   | of cource coincidences DO happen.

#--- cut this line and all the above out then feed to /bin/{k,}sh ---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	tb.c
# This archive created: Sun Feb 21 12:42:22 1988
export PATH; PATH=/bin:$PATH
echo shar: extracting "'tb.c'" '(7515 characters)'
if test -f 'tb.c'
then
	echo shar: will not over-write existing file "'tb.c'"
else
sed 's/^X//' << \SHAR_EOF > 'tb.c'
X/*
X *	Telebit TrailBlazer dialer, two routines here get used
X *	by uucp:
X *
X * tbopn(telno, flds, dev)
X * char *telno;
X * char *flds[];
X * struct Devices *dev;
X *
X *	action
X *		dials the number in telno on the TrailBlazer connected
X *		to port dev and sets the baud rate acordingly.
X *	returns
X *		file descriptor for /dev/ttyXX or CF_DIAL if dial was
X *		un-successfull.
X *
X * tbcls(fd)
X * int fd;
X *
X *	action
X *		hangs up the trailblazer by lowering dtr for a couple
X *		of seconds and in the process forces all the registers
X *		to their original state for things like dialin etc...
X *		also closes the device.
X *	returns
X *		nada, nothing, niente, rien (for bonus points, how many
X *		spelling errors are in those 4 words?)
X *
X * History
X *	drop dtr and flush tty often so I don't have to worry
X *	about autobauding and all that junk
X *	02/14/88 -mng
X *	dumped almost everything, now using numeric codes instead
X *	of verbal result codes, much easier to do a switch on the
X *	values returned from the modems that way, also easier to
X *	fetch the result codes, just go as long as I get digits.
X *	01/20/88 -mng
X *	stole the structure of the hayes dialer from ucb for this
X *	puppy, sort of works
X *	01/10/88 -mng
X *	nerd@percival  (..!tektronix!reed!percival!nerd)
X *
X *
X *	to run uucico with this dialer I set the Trailblazer's registers
X *	as follows (result of "atn?" command):
X
XE0 F1 M1 Q1 T V1 X1     Version BA4.00
XS00=001 S01=000 S02=255 S03=013 S04=010 S05=008 S06=002 S07=060 S08=002 S09=006
XS10=007 S11=070 S12=050
XS45=255 S47=004 S48=000 S49=000
XS50=000 S51=005 S52=002 S53=003 S54=001 S55=000 S56=017 S57=019 S58=003 S59=000
XS60=000 S61=000 S62=003 S63=001 S64=001 S65=000 S66=000 S67=000 S68=255
XS90=000 S91=000 S92=001 S95=002
XS100=000 S101=000 S102=000 S104=000
XS110=001 S111=255 S112=001
XS121=000
XN0:
XN1:
XN2:
XN3:
XN4:
XN5:
XN6:
XN7:
XN8:
XN9:
X
X *
X */
X
X#include "../condevs.h"
X
X#ifdef TELEBIT
X
X#include <ctype.h>
X#include <sys/ioctl.h>
X
X#define TBTMOUTHS 60	/* high speed timeout */
X#define TBTMOUTLS 30	/* low speed timeout */
X#define PEPBAUD 19200	/* interface speed for PEP connections */
X
Xtbopn(telno, flds, dev)
Xchar *telno;
Xchar *flds[];
Xstruct Devices *dev;
X{
X	extern errno;
X	char dcname[20];
X	char cbuf[MAXPH];
X	register char *cp;
X	register int i;
X	int dh = -1, rings;
X
X	sprintf(dcname, "/dev/%s", dev->D_line);
X	DEBUG(4, "dc - %s\n", dcname);
X	if (setjmp(Sjbuf)) {
X		logent(dcname, "TIMEOUT");
X		if (dh >= 0)
X			tbcls(dh);
X		return (CF_DIAL);
X	}
X	signal(SIGALRM, alarmtr);
X	getnextfd();
X	alarm(10);
X	dh = open(dcname, 2); /* read/write */
X	alarm(0);
X
X	/* modem is open */
X	next_fd = -1;
X	if (dh < 0) {
X		logent(dcname, "CAN'T OPEN");
X		return (CF_DIAL);
X	}
X/*
X *	this forces the trailblazer to reset, guarantees me that
X *	it will be at 19.2 KBpS when I want it there and that all
X *	its buffers will be cleared.  Probably don't need all the
X *	sleep calls here but who's in a hurry (did I tell you about
X *	the young and old bulls? :-)
X */
X	ioctl(dh, TIOCCDTR, 0);
X	sleep(1);
X	ioctl(dh, TIOCSDTR, 0);
X	sleep(1);
X	ioctl(dh, TIOCFLUSH, 0);
X	sleep(1);
X/*
X *	do all conversation with the modem at high speed, saves me from
X *	a major headache and I can then use the result code from the modem
X *	to set the baud rate of the interface.
X */
X	fixline(dh, PEPBAUD);
X
X	if (dochat(dev, flds, dh)) {
X		logent(dcname, "CHAT FAILED");
X		tbcls(dh);
X		return (CF_DIAL);
X	}
X/*
X *	sending "at\r" to the TrailBlazer should give us its undivided
X *	attention and insure there is no crud left in any of the buffers
X *	on the modem or in the serial driver.  Given the default values
X *	of the modem there should be no result codes so I don't need the
X *	expect.
X */
X	write(dh, "at\r", 3);
X	sleep(1);
X/*
X *	now set the modem up to dial, make sure we get the right result
X *	codes back (extended numeric) and all that.  If we are going
X *	to try a PEP connection set the modem for this too.  Also we
X *	have to set a longer timeout for PEP mode as most TrailBlazers
X *	are configured to put out the PEP mating call after several
X *	seconds of the normal tones.
X */
X	if (dev->D_speed == PEPBAUD)
X		write(dh, "atq6v0e0h0x1s7=60s50=255s51=5s54=4s111=30\r", 42);
X	else
X		write(dh, "atq6v0e0h0x1s7=30s50=0s51=5s54=4\r", 33);
X
X	if (expect("0\r", dh) != 0) {
X		logent(dcname, "TrailBlazer seems dead");
X		tbcls(dh);
X		return (CF_DIAL);
X	}
X/*
X *	about time we got to dial
X */
X	write(dh, "atdt", 4);
X	write(dh, telno, strlen(telno));
X	write(dh, "\r", 1);
X
X	if (setjmp(Sjbuf)) {
X		logent(dcname, "TIMEOUT");
X		strcpy(devSel, dev->D_line);
X		tbcls(dh);
X		return (CF_DIAL);
X	}
X	signal(SIGALRM, alarmtr);
X/*
X *	set uucp to timeout about the same time the trailblazer will
X *	timeout if it can't connect
X */
X	if (dev->D_speed == PEPBAUD)
X		alarm(TBTMOUTHS);
X	else
X		alarm(TBTMOUTLS);
X	rings = 0;
X	do {
X/*
X *	read any garbage characters in until a digit is found
X */
X		cp = cbuf;
X		while (read(dh, cp, 1) == 1)
X			if (isdigit(*cp))
X				break;
X		++cp;
X/*
X *	now read characters in so long as they are numeric, this
X *	will hopefully be a connect or rring code
X */
X		while (read(dh, cp++, 1) == 1)
X			if (!isdigit(*cp))
X				break;
X		*cp = '\0';
X		i = atoi(cbuf);
X/*
X *	do something with the sacred words of our holly modem
X */
X		switch (i)    {
X/*
X *	someone is trying to call us, damn
X */
X			case 2:
X				tbcls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("ring"));
X/*
X *	modem gave up before we did
X */
X			case 3:
X				tbcls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("no carrier"));
X/*
X *	error, probably something with the number in L.sys
X */
X			case 4:
X				tbcls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("error"));
X/*
X *	something is wrong with the phone line
X */
X			case 6:
X				tbcls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("no dial tone"));
X/*
X *	we'll just have to catch this one later
X */
X			case 7:
X				tbcls(dh);
X				strcpy(devSel, dev->D_line);
X				return (FLog("busy"));
X/*
X *	the phone on the other end is ringing
X */
X			case 52:
X				DEBUG(4,"GOT: rring\n", CNULL);
X		}
X	} while ((i == 52) && (++rings < 6));
X	alarm(0);
X/*
X *	hopefully by the time we get here we will have a valid
X *	connect code and just have to set the baud rate acordingly
X */
X	switch (i)    {
X		case 3:
X			i = 300;	/* not on my system we don't! */
X			break;
X		case 5:
X			i = 1200;
X			break;
X		case 10:
X			i = 2400;
X			break;
X		case 50:
X			i = PEPBAUD;
X			break;
X/*
X *	rung too many times, assume no answer will come
X */
X		case 52:
X			tbcls(dh);
X			strcpy(devSel, dev->D_line);
X			return (FLog("no answer"));
X/*
X *	probably don't need this but there is no overhead for it
X */
X		default:
X			tbcls(dh);
X			strcpy(devSel, dev->D_line);
X			return (FLog(cbuf));
X	}
X/*
X *	since we have been at high speed so far make sure we scale
X *	down if need-be
X */
X	if (i != PEPBAUD)    {
X		fixline(dh, i);
X		DEBUG(4,"Baudrate reset to %d\n", i);
X	}
X
X	DEBUG(4, "telebit connect at %d bps\n", i);
X	return (dh);
X}
X
Xtbcls(fd)
Xint fd;
X{
X	char dcname[20];
X	
X	if (fd > 0) {
X		sprintf(dcname, "/dev/%s", devSel);
X		DEBUG(4, "Hanging up fd = %d\n", fd);
X/*
X *	code to drop DTR forces hangup and modem reset
X */
X		ioctl(fd, TIOCCDTR, 0);
X		sleep(2);
X		ioctl(fd, TIOCSDTR, 0);
X		sleep(2);
X		ioctl(fd, TIOCFLUSH, 0);
X		close(fd);
X/*
X *	remove any locks that may be on the device
X */
X		delock(devSel);
X	}
X}
X
XFLog(str)
Xchar *str;
X{
X/*
X *	not much of a routine but we repeated this sequence so often
X *	I decided to move it out of site.
X */
X	DEBUG(4,"\nGOT: %s\n", str);
X	logent(str, _FAILED);
X	return (CF_DIAL);
X}
X#endif TELEBIT
SHAR_EOF
if test 7515 -ne "`wc -c < 'tb.c'`"
then
	echo shar: error transmitting "'tb.c'" '(should have been 7515 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
-- 
        Michael Galassi           | If my opinions happen to be the same as
...!tektronix!tessi!percival!nerd | my employer's it is ONLY a coincidence,
...!uunet!littlei!percival!nerd   | of cource coincidences DO happen.