[comp.dcom.modems] checkblazer.c -- get spectrum data from last connection

murfs@caeco.uucp (Steve Murphy) (04/21/88)

Here's something (checkblazer.c) maybe someone might find useful. Enjoy.
  --murf
------------------------------------------------------------------------
#include <sys/types.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>
#ifdef	USG
#include <termio.h>
#endif
#ifndef	USG
#include <sgtty.h>
#endif
#include <sys/stat.h>
#define OUTPUTDIR "/usr/spool/uucp"
#define DEFSTARTSPEED EXTA
	/* A program to grab Telebit TrailBlazer Status Data and dump to ascii files */

	/* by Steve Murphy */

	/* Some say the globals, etc. seem similar to some used in a particular
	   version of uucp. This is, of course, purely accidental, but those with
	   discernment may be able to take advantage of this accident.
	   People with discernment usually take advantage of "accidents".

	   Wouldn't it be nice if, while closing the modem in uucp, you generated
	   data files that showed the status of the connection?

	   */

	/* For the rest of us: this little standalone will,

	   IF the proper command line args are supplied,

	   IF the modem is set up with just the right defaults in its regs,
	   (I have E0 F1 M1 Q6 T V1 X3, and s51=5, for example)

	   extract all the S70 type registers revealing the status of the last
	   connection made, fast or slow (depending on the regs) */

	/* This data is dumped out to files in x,y pairs suitable for progs like
	   gnuplot, or just echoed back to the user if non-array oriented. */

	/* I developed my own hp7475A interface to GNUPLOT and use it to generate
	   nice-looking and informative pen-plots of connections. This info is really
	   informative at times about what kind of problems I'm seeing. */

	/* here's an example GNUPLOT.INI.telebit file to display the files generated
	   on an hp pen plot:

	   set term hp74
	   set samples 2048
	   set output "hp.noise.telebit"
	   plot [0:4000] [-80:10] "blazer_noise.telebit" with lines,
	   				"blazer_rbits.telebit" with impulses,
					"blazer_tbits.telebit" with lines
	   quit

	   This will display the noise profile on the bottom and the two bitrates overlay
	   each other above.

	   Because This generates several files if run with several sys names,
	   I generated a pile of these GNUPLOT.INI files, AND
	   I have a generic GNUPLOT.INI submitter:
	   file: plotsys (mode 666)
	   contents follows:
#
echo $argv[1]
cp GNUPLOT.INI.$argv[1] .gnuplot
gnuplot

And, of course, a lpr -Php hp.noise.telebit (in this case) would
be the next thing (go stick paper in the plotter first!)

Now, some clever person could do this much more neatly with sed scripts,
I'm sure. Have at it. Have fun. Go for it.
	   */

	/* As usual, This will most likely require modification to run on your modems.
	   I set up my registers like few others on the net, because of constraints beyond
	   my control.

	   I doubt that this will work on anything but sun 3's.

	   Releasing even this peice of junk is charity on my part; Don't bother me with
	   anything but something better -- I didn't generate this for money, really,
	   and so I really can't support it either. It may be a little work for you to make
	   it run, but hey, I think I did more than you, OK?

	   Purpose: For those who want to grab this kind of data bad enough to make this
	   work, but not bad enough, obviously, to write their own from scratch

	   Encouragement: This code actually runs on my machine (sun3/160) with my OS
	   (SunOS3.2) with my modems (Telebit Trailblazer Plus, rev 3 roms. */
	
jmp_buf Sjbuf;
jmp_buf Pipebuf;

#define STBNULL 0
#define CF_DIAL 5
#define BAND (4000.0/512.0)

int blazer_slow=0, blazer_fast = 0;
int onesys = 0;
int turntime = 30 * 60;	/* 30 minutes expressed in seconds */
char *ttyn = NULL;
extern int errno;
char devSel[200],Rmtname[200];

#ifdef	USG
struct termio Savettyb;
#endif
#ifndef	USG
struct sgttyb Savettyb;
#endif

alarmtr()
{
	signal(SIGALRM, alarmtr);
	longjmp(Sjbuf, 1);
}

expect(str,fd)
char *str;
{
	char *p = str;
	char bug[10];
	
	if (setjmp(Sjbuf))
	{
		fprintf(stderr, "TIMEOUT\n");
		return CF_DIAL;
	}
	signal(SIGALRM, alarmtr);
	alarm(10);
 again:
	while( *p &&  read( fd,bug,1) == 1 && *p == bug[0] )
		p++;
	if ( !*p )
	{
		alarm(0);
		return 0;
	}
	else
	{
		p = str;
		goto again;
	}
}

logent( what, arg1,arg2,arg3,arg4)
char *what,*arg1,*arg2,*arg3,*arg4;
{
	FILE *lo;
	char buff[300];
	
/* 	lo = fopen("/usr/spool/uucp/LOGFILE","a"); For those who enjoy permanent records
	if( !lo )
		return; */
	sprintf(buff,what,arg1,arg2,arg3,arg4);
	printf(buff);
/*	fprintf(lo,"checkblazer: %s",buff); to go a log file 
	fclose( lo ); */
	return;
}

main(argc, argv)
int argc;
register char *argv[];
{
	int seq,localbits,Ifn;
	char *q, tty_port[100];

	if( argc < 4)
	{
		fprintf(stderr,"usage: checkblazer SLOW|FAST device label\n");
		exit(0);
	}
	Ifn = setreuid(geteuid(),geteuid());
	if( Ifn )
	{
		logent("Couldn't setuid to %d\n",geteuid());
	}
	Ifn = setregid(getegid(),getegid());
	if( Ifn )
	{
		logent("Couldn't setgid to %d\n",getegid());
	}
	
	ttyn = tty_port;
	if( !strcmp(argv[1],"SLOW") || !strcmp(argv[1],"slow") )
		blazer_slow = 1;
	else
		blazer_fast =1;
	
	strcpy(tty_port,argv[2]);
	strcpy(Rmtname,argv[3]);
	
	if( ttyn )
		strcpy(devSel, ttyn);
	else
		strcpy(devSel,"");
	
	cleanup(0);
}


cleanup(code)
{
	int dh = -1;
	char dcname[40];
	
	sleep(2);
	strcpy(dcname,devSel);
	if (setjmp(Sjbuf))
	{
		logent( "TIMEOUT\n");
		return CF_DIAL;
	}
	signal(SIGALRM, alarmtr);
	alarm(10);
	dh = open(dcname, 2); /* read/write */
	alarm(0);
	
	/* modem is open */
	if (dh >= 0)
	{
		char spdy[30];
#ifdef	USG
		ioctl(dh, TCGETA, &Savettyb);
		Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7;
		Savettyb.c_oflag |= OPOST;
		Savettyb.c_lflag |= (ISIG|ICANON|ECHO);
#else !USG
		ioctl(dh, TIOCGETP, &Savettyb);
		Savettyb.sg_flags |= ECHO;
		Savettyb.sg_flags &= ~RAW;
		Savettyb.sg_ispeed = Savettyb.sg_ospeed = DEFSTARTSPEED;
		(void) ioctl(dh, TIOCHPCL, STBNULL);
#endif !USG
#ifdef	USG
		ioctl(dh, TCSETA, &Savettyb);
#else	!USG
		ioctl(dh, TIOCSETP, &Savettyb);
#endif !USG
		sleep(1);
		if( blazer_slow )
			blazer_status_slow(dh);
		
		if( blazer_fast )
			blazer_status_fast(dh);
		close(dh);
		if( !strcmp("/dev/cua",devSel) )
			strcpy(spdy,"/dev/ttya");
		else
			strcpy(spdy,"/dev/ttyb");
	}
	else
	{
		logent("CAN'T OPEN %s\n",dcname);
		exit(dh);
	}
}

blazer_status_slow(fd)
{
	
	char *cp,sss[300],qqq[100],*cq;
	char freq_offset[40],line_qual[40];
	int i;
	
	write(fd, "ATS77?\r", 7);
	/* freq offset */
	cp = freq_offset;
	while (read(fd, cp ,1) == 1)
	{
		if (*cp > 0x20 )
			break;
	}
	while (++cp < &freq_offset[39] && read(fd, cp, 1) == 1 
		   && *cp != '\n')
		;
	cq = qqq -1;
	while (++cq < &qqq[99] && read(fd, cq, 1) == 1 /* collect OK */
		   && *cq != '\n')
		;
	*cp-- = '\0';
	if (*cp == '\r')
		*cp = '\0';
	
	/* line quality */
	write(fd, "ATS78?\r", 7);
	cp = line_qual;
	while (read(fd, cp ,1) == 1)
	{
		if (*cp > ' ')
			break;
	}
	while (++cp < &line_qual[39] && read(fd, cp, 1) == 1 
		   && *cp != '\n')
		;
	cq = qqq;
	while (++cq < &qqq[99] && read(fd, cq, 1) == 1 /* collect OK */
		   && *cq != '\n')
		;
	*cp-- = '\0';
	if (*cp == '\r')
		*cp = '\0';
	sprintf(sss,"Modem reports freq offset=%s, Line Quality=%s\n",
			freq_offset,line_qual);
	logent( sss );
}

blazer_status_fast(fd)
{
	char freq_offset[40],line_qual[40],tdr[20],rdr[20],retrans[20],
	packacc[20];
	char *cp,sss[300],*cq,qqq[100];
	double noise[512];
	struct sgttyb mode1;
	int i,bitpersec[512];
	
	
	/* freq offset */
	write(fd, "ATS77?\r", 7);
 syncup:
	cp = freq_offset;
	while (read(fd, cp ,1) == 1)
	{
		if (*cp > ' ')
			break;
	}
	while (++cp < &freq_offset[39] && read(fd, cp, 1) == 1 
		   && *cp != '\n')
		;
	if( freq_offset[0] != '+' && freq_offset[0] != '-')
		goto syncup;
 sync_1:
	cq = qqq-1;
	while (++cq < &qqq[99] && read(fd, cq, 1) == 1 /* collect OK */
		   && *cq != '\n')
		;
	if( strcmp(qqq,"OK\n") )
		goto sync_1;
	
	*cp-- = '\0';
	if (*cp == '\r')
		*cp = '\0';
	
	/* transmit data rate */
	write(fd, "ATS70?\r", 7);
	cp = tdr;
	while (read(fd, cp ,1) == 1)
	{
		if (*cp > ' ')
			break;
	}
	while (++cp < &tdr[19] && read(fd, cp, 1) == 1 
		   && *cp != '\n')
		;
 sync_2:
	cq = qqq-1;
	while (++cq < &qqq[99] && read(fd, cq, 1) == 1 /* collect OK */
		   && *cq != '\n')
		;
	if( strcmp(qqq,"OK\n") )
		goto sync_2;
	*cp-- = '\0';
	if (*cp == '\r')
		*cp = '\0';
	
	/* receive data rate */
	write(fd, "ATS72?\r", 7);
	cp = rdr;
	while (read(fd, cp ,1) == 1)
	{
		if (*cp > ' ')
			break;
	}
	while (++cp < &rdr[19] && read(fd, cp, 1) == 1 
		   && *cp != '\n')
		;
 sync_5:
	cq = qqq-1;
	while (++cq < &qqq[99] && read(fd, cq, 1) == 1 /* collect OK */
		   && *cq != '\n')
		;
	if( strcmp(qqq,"OK\n") )
		goto sync_5;
	*cp-- = '\0';
	if (*cp == '\r')
		*cp = '\0';
	
	/* packets retransmitted  */
	write(fd, "ATS74?\r", 7);
	cp = retrans;
	while (read(fd, cp ,1) == 1)
	{
		if (*cp > ' ')
			break;
	}
	while (++cp < &retrans[19] && read(fd, cp, 1) == 1 
		   && *cp != '\n')
		;
 sync_3:
	cq = qqq-1;
	while (++cq < &qqq[99] && read(fd, cq, 1) == 1 /* collect OK */
		   && *cq != '\n')
		;
	if( strcmp(qqq,"OK\n") )
		goto sync_3;
	*cp-- = '\0';
	if (*cp == '\r')
		*cp = '\0';
	
	/* packets accepted  */
	write(fd, "ATS75?\r", 7);
	cp = packacc;
	while (read(fd, cp ,1) == 1)
	{
		if (*cp > ' ')
			break;
	}
	while (++cp < &packacc[19] && read(fd, cp, 1) == 1 
		   && *cp != '\n')
		;
 sync_4:
	cq = qqq-1;
	while (++cq < &qqq[99] && read(fd, cq, 1) == 1 /* collect OK */
		   && *cq != '\n')
		;
	if( strcmp(qqq,"OK\n") )
		goto sync_4;
	*cp-- = '\0';
	if (*cp == '\r')
		*cp = '\0';
	
	write(fd, "ATS58=4\r", 8);
	if (expect("OK",fd) != 0)
		logent( "TB did not respond to ATS58=4\n",devSel);
	
	ioctl(fd,TIOCGETP,&mode1);
	mode1.sg_flags |= CBREAK|TANDEM;
	ioctl(fd,TIOCSETP,&mode1); 
	
	if (setjmp(Sjbuf))
	{
		logent( "TIMEOUT\n");
		close(fd);
		return CF_DIAL;
	}
	signal(SIGALRM, alarmtr);
	alarm(30);

	/* noise sprectrum  */

	sleep(1);
	write(fd, "ATS76?\r", 7);
	if(1)
	{
		FILE *graphout;
		sprintf(sss,"%s/blazer_noise.%s",OUTPUTDIR,Rmtname);
		graphout = (FILE *)fopen(sss,"w");
		for( i=0; i<511; i++)
		{
			double atof();
			cp = sss;
			while (read(fd, cp ,1) == 1)
			{
				if (*cp > ' ')
					break;
			}
			while (++cp < &sss[20] && read(fd, cp, 1) == 1 
				   && *cp != '\n' && *cp != ' ')
				;
			*cp-- = '\0';
			if (*cp == '\r')
				*cp = '\0';
			noise[i] = atof(sss);
			if( graphout )
			{
				fprintf(graphout,"%g	%g\n",(double)(i+1)*BAND,noise[i]);
				fflush(graphout);
			}
		}
		if(graphout)
			fclose(graphout);
		if(1)
		{
			double nmax, nmin, nave;
			nmax = -50000.0;
			nmin = 50000.0;
			nave = 0;
			for( i=0; i<511; i++)
			{
				if( noise[i] > nmax )
					nmax = noise[i];
				if( noise[i] < nmin )
					nmin = noise[i];
				nave += noise[i];
			}
			nave /= 511.0;
			sprintf(sss,"noise:min=%g,max=%g,ave=%g\n",nmin,nmax,nave);
			logent( sss);
		}
	}
	cq = qqq;
	while (++cq < &qqq[99] && read(fd, cq, 1) == 1/* collect OK */
		   && *cq != '\n')
		;
	alarm(0);

	alarm(30);
	/* transmit sprectrum  */
	sleep(1);
	write(fd, "ATS71?\r", 7);
	if(1)
	{
		FILE *graphout;
		sprintf(sss,"%s/blazer_tbits.%s",OUTPUTDIR,Rmtname);
		graphout = (FILE *)fopen(sss,"w");
		for( i=0; i<511; i++)
		{
			cp = sss;
			while (read(fd, cp ,1) == 1)
			{
				if (*cp > ' ')
					break;
			}
			while (++cp < &sss[20] && read(fd, cp, 1) == 1 
				   && *cp != '\n' && *cp != ' ')
				;
			*cp-- = '\0';
			if (*cp == '\r')
				*cp = '\0';
			bitpersec[i] = atoi(sss);
			if( graphout )
			{
				fprintf(graphout,"%g	%d\n",(double)(i+1)*BAND,bitpersec[i]);
				fflush(graphout);
			}
		}
		if(graphout)
			fclose(graphout);
		if(1)
		{
			double nmax, nmin, nave;
			int nfirst, nlast,ntotal;
			
			nmax = -50000.0;
			nmin = 50000.0;
			nave = 0;
			nfirst = -1;
			nlast = ntotal = 0;
			
			for( i=0; i<511; i++)
			{
				if( bitpersec[i] && nfirst == -1 )
					nfirst = i;
				if( bitpersec[i] && bitpersec[i-1] )
					nlast = i;
				if( bitpersec[i] > nmax )
					nmax = bitpersec[i];
				if( bitpersec[i] < nmin )
					nmin = bitpersec[i];
				nave += bitpersec[i];
				ntotal += bitpersec[i];
			}
			nave /= 511.0;
			sprintf(sss,"tbits:min=%g,max=%g,ave=%g, lo=%g,hi=%g,total=%d\n",nmin,nmax,nave,
					(double)(nfirst+1)*BAND,(double)(nlast+1)*BAND,ntotal);
			logent( sss );
		}
	}
	cq = qqq;
	while (++cq < &qqq[99] && read(fd, cq, 1) == 1/* collect OK */
		   && *cq != '\n')
		;
	alarm(0);

	alarm(30);
	/* rec bit sprectrum  */
	sleep(1);
	write(fd, "ATS73?\r", 7);
	if(1)
	{
		FILE *graphout;
		sprintf(sss,"%s/blazer_rbits.%s",OUTPUTDIR,Rmtname);
		graphout = (FILE *)fopen(sss,"w");
		for( i=0; i<511; i++)
		{
			cp = sss;
			while (read(fd, cp ,1) == 1)
			{
				if (*cp > ' ')
					break;
			}
			while (++cp < &sss[20] && read(fd, cp, 1) == 1 
				   && *cp != '\n' && *cp != ' ')
				;
			*cp-- = '\0';
			if (*cp == '\r')
				*cp = '\0';
			bitpersec[i] = atoi(sss);
			if( graphout )
			{
				fprintf(graphout,"%g	%d\n",(double)(i+1)*BAND,bitpersec[i]);
				fflush(graphout);
			}
		}
		if(graphout)
			fclose(graphout);
		if(1)
		{
			double nmax, nmin, nave;
			int nfirst, nlast,ntotal;
			
			nmax = -50000.0;
			nmin = 50000.0;
			nave = 0;
			nfirst = -1;
			nlast = ntotal = 0;
			
			for( i=0; i<511; i++)
			{
				if( bitpersec[i] && nfirst == -1 )
					nfirst = i;
				if( bitpersec[i] && bitpersec[i-1] )
					nlast = i;
				if( bitpersec[i] > nmax )
					nmax = bitpersec[i];
				if( bitpersec[i] < nmin )
					nmin = bitpersec[i];
				nave += bitpersec[i];
				ntotal += bitpersec[i];
			}
			nave /= 511.0;
			sprintf(sss,"rbits:min=%g,max=%g,ave=%g, lo=%g,hi=%g,total=%d\n",nmin,nmax,nave,
					(double)(nfirst+1)*BAND,(double)(nlast+1)*BAND,ntotal);
			logent( sss);
		}
	}
	cq = qqq;
	while (++cq < &qqq[99] && read(fd, cq, 1) == 1/* collect OK */
		   && *cq != '\n')
		;
	alarm(0);
	
	sleep(3);
	write(fd, "ATZ\r", 4); /* this'll return the modem to normal */
	if (expect("OK",fd) != 0)
		logent( "HSM did not respond to ATZ\n",devSel);
	
	/*ioctl(fd,TIOCGETP,&mode1);*/ /* turn off XON/XOFF */
	/* mode1.sg_flags &= ~TANDEM | RAW; why bother?
	   ioctl(fd,TIOCSETP,&mode1); */
	sprintf(sss,"Foff=%s,tdr=%s,rdr=%s,retrans=%s,acc=%s\n",
			freq_offset,tdr,rdr,retrans,packacc);
	logent( sss);
	sleep(4);
}
-- 
	Steve Murphy, 	CAECO, Inc., 7090 South Union Park Avenue,
			Suite 200, Midvale, UT 84047
			(801)255-8880
	<WORLD>!{byuadam,utah-cs,nrc-ut,wicat}!caeco!murf