/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:hys.c 12.1$ */
/* $ACIS:hys.c 12.1$ */
/* $Source: /ibm/acis/usr/src/usr.bin/uucp/aculib/RCS/hys.c,v $ */

#ifndef lint
static char *rcsid = "$Header:hys.c 12.1$";
#endif

#ifndef lint
static char sccsid[] = "@(#)hys.c	4.6 (Berkeley) 2/12/86";
#endif

#include "../condevs.h"
#include <ctype.h>

#ifdef HAYES
#ifdef USR2400
/*
 * The "correct" switch settings for a USR Courier 2400 are
 * 	Dialin/out:	0 0 1 1 0 0 0 1 0 0
 *	Dialout only:	0 0 1 1 1 1 0 1 0 0
 * where 0 = off and 1 = on
 */
#endif USR2400

/*
 *	hyspopn(telno, flds, dev) connect to hayes smartmodem (pulse call)
 *	hystopn(telno, flds, dev) connect to hayes smartmodem (tone call)
 *	char *flds[], *dev[];
 *
 *	return codes:
 *		>0  -  file number  -  ok
 *		CF_DIAL,CF_DEVICE  -  failed
 */

hyspopn(telno, flds, dev)
char *telno, *flds[];
struct Devices *dev;
{
	return hysopn(telno, flds, dev, 0);
}

hystopn(telno, flds, dev)
char *telno, *flds[];
struct Devices *dev;
{
	return hysopn(telno, flds, dev, 1);
}

/* ARGSUSED */
hysopn(telno, flds, dev, toneflag)
char *telno;
char *flds[];
struct Devices *dev;
int toneflag;
{
	extern errno;
	char dcname[20];
	char cbuf[MAXPH];
	register char *cp;
	register int i;
	int dh = -1, nrings = 0;

	sprintf(dcname, "/dev/%s", dev->D_line);
	DEBUG(4, "dc - %s\n", dcname);
	if (setjmp(Sjbuf)) {
		logent(dcname, "TIMEOUT");
		if (dh >= 0)
			hyscls(dh);
		return CF_DIAL;
	}
	signal(SIGALRM, alarmtr);
	getnextfd();
	alarm(10);
	dh = open(dcname, 2); /* read/write */
	alarm(0);

	/* modem is open */
	next_fd = -1;
	if (dh >= 0) {
		fixline(dh, dev->D_speed);
		if (dochat(dev, flds, dh)) {
			logent(dcname, "CHAT FAILED");
			hyscls(dh);
			return CF_DIAL;
		}
		write(dh, "ATV1E0H\r", 8);
		if (expect("OK\r\n", dh) != 0) {
			write(dh, "\rAT\r", 4);
			sleep(1);
			close(dh);
			sleep(1);
			dh = open(dcname, 2);
			sleep(1);
			close(dh);
			sleep(1);
			dh = open(dcname, 2);
			write(dh, "\rAT\r", 4);
			if (expect("OK\r\n", dh) != 0) {
				logent(dcname, "HSM seems really dead");
				hyscls(dh);
				return CF_DIAL;
			} else {
				write(dh, "ATV1E0H\r", 8);
				if (expect("OK\r\n", dh) != 0) {
					logent(dcname, "HSM seems sorta dead");
					hyscls(dh);
					return CF_DIAL;
				}
			}
		}

#ifdef USR2400
		write(dh, "ATX6S7=44\r", 10);
#else HAYES
		write(dh, "ATX1S7=44\r", 10);
#endif
		if (expect("OK\r\n", dh) != 0) {
			logent(dcname, "HSM seems dead");
			hyscls(dh);
			return CF_DIAL;
		}
		if (toneflag)
			write(dh, "\rATDT", 5);
		else
#ifdef USR2400
			write(dh, "\rATD", 4);
#else HAYES
			write(dh, "\rATDP", 5);
#endif HAYES
		write(dh, telno, strlen(telno));
		write(dh, "\r", 1);

		if (setjmp(Sjbuf)) {
			logent(dcname, "TIMEOUT");
			strcpy(devSel, dev->D_line);
			hyscls(dh);
			return CF_DIAL;
		}
		signal(SIGALRM, alarmtr);
		alarm(2*MAXMSGTIME);
		do {
			cp = cbuf;
			while (read(dh, cp ,1) == 1)
				if (*cp >= ' ')
					break;
			while (++cp < &cbuf[MAXPH] && read(dh, cp, 1) == 1 && *cp != '\n')
				;
			alarm(0);
			*cp-- = '\0';
			if (*cp == '\r')
				*cp = '\0';
			DEBUG(4,"\nGOT: %s", cbuf);
			alarm(MAXMSGTIME);
		} while (strncmp(rindex(cbuf,'R'), "RING", 4) == 0 && 
							nrings++ < 5);
		if (strncmp(cbuf, "CONNECT", 7) != 0) {
			logent(cbuf, _FAILED);
			strcpy(devSel, dev->D_line);
			hyscls(dh);
			return CF_DIAL;
		}
		i = atoi(&cbuf[8]);
		if (i > 0 && i != dev->D_speed) {	
			DEBUG(4,"Baudrate reset to %d\n", i);
			fixline(dh, i);
		}

	}
	if (dh < 0) {
		logent(dcname, "CAN'T OPEN");
		return dh;
	}
	DEBUG(4, "hayes ok\n", CNULL);
	return dh;
}

hyscls(fd)
int fd;
{
	char dcname[20];
#ifdef DROPDTR
	struct sgttyb hup, sav;
#else
	struct sgttyb sav;
#endif DROPDTR

	if (fd > 0) {
		sprintf(dcname, "/dev/%s", devSel);
		DEBUG(4, "Hanging up fd = %d\n", fd);
#ifdef DROPDTR
		/*
		 * code to drop DTR -- change to 0 baud then back to default.
		 */
		gtty(fd, &hup);
		gtty(fd, &sav);
		hup.sg_ispeed = B0;
		hup.sg_ospeed = B0;
		stty(fd, &hup);
		sleep(2);
		stty(fd, &sav);
		/*
		 * now raise DTR -- close the device & open it again.
		 */
		sleep(2);
		close(fd);
		sleep(2);
		fd = open(dcname, 2);
		stty(fd, &sav);
#else
		sleep(3);
		write(fd, "+++", 3);
#endif
		sleep(3);
		/*
		 * We fully expect the modem to not talk to us now.
		 */
		ExpectHopeful = 0;
		if (expect("OK\r\n", fd) != 0)
			DEBUG(4, "Modem didn't respond to escape sequence %s","+++");
		write(fd, "ATH\r\r", 5);
		sleep(1);
		if (expect("OK\r\n", fd) != 0) {
			gtty(fd, &sav);
			close(fd);
			sleep(2);
			fd = open(dcname, 2);
			sleep(1);
			stty(fd, &sav);
		}
		/*
		 * Now we should be on speaking terms with the modem
		 */
		ExpectHopeful = 1;
		write(fd, "ATV1E0\r", 7);
		if (expect("OK\r\n", fd) != 0)
			logent(devSel, "Modem did not respond to reset sequence");
		close(fd);
		sleep(2);
		delock(devSel);
	}
}
#endif HAYES
