xref: /csrg-svn/usr.bin/tip/aculib/hayes.c (revision 19817)
1*19817Sdist /*
2*19817Sdist  * Copyright (c) 1983 Regents of the University of California.
3*19817Sdist  * All rights reserved.  The Berkeley software License Agreement
4*19817Sdist  * specifies the terms and conditions for redistribution.
5*19817Sdist  */
6*19817Sdist 
718635Smiriam #ifndef lint
8*19817Sdist static char sccsid[] = "@(#)hayes.c	5.1 (Berkeley) 04/30/85";
9*19817Sdist #endif not lint
1018635Smiriam 
1118635Smiriam /*
1218635Smiriam  * Routines for calling up on a Hayes Modem
1318635Smiriam  * (based on the old VenTel driver).
1418635Smiriam  * The modem is expected to be strapped for "echo".
1518635Smiriam  * Also, the switches enabling the DTR and CD lines
1618635Smiriam  * must be set correctly.
1718635Smiriam  * NOTICE:
1818635Smiriam  * The easy way to hang up a modem is always simply to
1918635Smiriam  * clear the DTR signal. However, if the +++ sequence
2018635Smiriam  * (which switches the modem back to local mode) is sent
2118635Smiriam  * before modem is hung up, removal of the DTR signal
2218635Smiriam  * has no effect (except that it prevents the modem from
2318635Smiriam  * recognizing commands).
2418635Smiriam  * (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984)
2518635Smiriam  */
2618635Smiriam /*
2718635Smiriam  * TODO:
2818635Smiriam  * It is probably not a good idea to switch the modem
2918635Smiriam  * state between 'verbose' and terse (status messages).
3018635Smiriam  * This should be kicked out and we should use verbose
3118635Smiriam  * mode only. This would make it consistent with normal
3218635Smiriam  * interactive use thru the command 'tip dialer'.
3318635Smiriam  */
3418635Smiriam #include "tip.h"
3518635Smiriam 
3618635Smiriam #define	min(a,b)	((a < b) ? a : b)
3718635Smiriam 
3818635Smiriam static	int sigALRM();
3918635Smiriam static	int timeout = 0;
4018635Smiriam static	jmp_buf timeoutbuf;
4118635Smiriam static 	char gobble();
4218635Smiriam #define DUMBUFLEN	40
4318635Smiriam static char dumbuf[DUMBUFLEN];
4418635Smiriam 
4518635Smiriam #define	DIALING		1
4618635Smiriam #define IDLE		2
4718635Smiriam #define CONNECTED	3
4818635Smiriam #define	FAILED		4
4918635Smiriam static	int state = IDLE;
5018635Smiriam 
5118635Smiriam hay_dialer(num, acu)
5218635Smiriam 	register char *num;
5318635Smiriam 	char *acu;
5418635Smiriam {
5518635Smiriam 	register char *cp;
5618635Smiriam 	register int connected = 0;
5718635Smiriam 	char dummy;
5818635Smiriam #ifdef ACULOG
5918635Smiriam 	char line[80];
6018635Smiriam #endif
6118635Smiriam 	if (hay_sync() == 0)		/* make sure we can talk to the modem */
6218635Smiriam 		return(0);
6318635Smiriam 	if (boolean(value(VERBOSE)))
6418635Smiriam 		printf("\ndialing...");
6518635Smiriam 	fflush(stdout);
6618635Smiriam 	ioctl(FD, TIOCHPCL, 0);
6718635Smiriam 	ioctl(FD, TIOCFLUSH, 0);	/* get rid of garbage */
6818635Smiriam 	write(FD, "ATv0\r", 5);	/* tell modem to use short status codes */
6918635Smiriam 	gobble("\r");
7018635Smiriam 	gobble("\r");
7118635Smiriam 	write(FD, "ATTD", 4);	/* send dial command */
7218635Smiriam 	write(FD, num, strlen(num));
7318635Smiriam 	state = DIALING;
7418635Smiriam 	write(FD, "\r", 1);
7518635Smiriam 	connected = 0;
7618635Smiriam 	if (gobble("\r")) {
7718635Smiriam 		if ((dummy = gobble("01234")) != '1')
7818635Smiriam 			error_rep(dummy);
7918635Smiriam 		else
8018635Smiriam 			connected = 1;
8118635Smiriam 	}
8218635Smiriam 	if (connected)
8318635Smiriam 		state = CONNECTED;
8418635Smiriam 	else {
8518635Smiriam 		state = FAILED;
8618635Smiriam 		return (connected);	/* lets get out of here.. */
8718635Smiriam 	}
8818635Smiriam 	ioctl(FD, TIOCFLUSH, 0);
8918635Smiriam #ifdef ACULOG
9018635Smiriam 	if (timeout) {
9118635Smiriam 		sprintf(line, "%d second dial timeout",
9218635Smiriam 			number(value(DIALTIMEOUT)));
9318635Smiriam 		logent(value(HOST), num, "hayes", line);
9418635Smiriam 	}
9518635Smiriam #endif
9618635Smiriam 	if (timeout)
9718635Smiriam 		hay_disconnect();	/* insurance */
9818635Smiriam 	return (connected);
9918635Smiriam }
10018635Smiriam 
10118635Smiriam 
10218635Smiriam hay_disconnect()
10318635Smiriam {
10418635Smiriam 	char c;
10518635Smiriam 	int len, rlen;
10618635Smiriam 
10718635Smiriam 	/* first hang up the modem*/
10818635Smiriam #ifdef DEBUG
10918635Smiriam 	printf("\rdisconnecting modem....\n\r");
11018635Smiriam #endif
11118635Smiriam 	ioctl(FD, TIOCCDTR, 0);
11218635Smiriam 	sleep(1);
11318635Smiriam 	ioctl(FD, TIOCSDTR, 0);
11418635Smiriam 	goodbye();
11518635Smiriam }
11618635Smiriam 
11718635Smiriam hay_abort()
11818635Smiriam {
11918635Smiriam 
12018635Smiriam 	char c;
12118635Smiriam 
12218635Smiriam 	write(FD, "\r", 1);	/* send anything to abort the call */
12318635Smiriam 	hay_disconnect();
12418635Smiriam }
12518635Smiriam 
12618635Smiriam static int
12718635Smiriam sigALRM()
12818635Smiriam {
12918635Smiriam 
13018635Smiriam 	printf("\07timeout waiting for reply\n\r");
13118635Smiriam 	timeout = 1;
13218635Smiriam 	longjmp(timeoutbuf, 1);
13318635Smiriam }
13418635Smiriam 
13518635Smiriam static char
13618635Smiriam gobble(match)
13718635Smiriam 	register char *match;
13818635Smiriam {
13918635Smiriam 	char c;
14018635Smiriam 	int (*f)();
14118635Smiriam 	int i, status = 0;
14218635Smiriam 
14318635Smiriam 	signal(SIGALRM, sigALRM);
14418635Smiriam 	timeout = 0;
14518635Smiriam #ifdef DEBUG
14618635Smiriam 	printf("\ngobble: waiting for %s\n", match);
14718635Smiriam #endif
14818635Smiriam 	do {
14918635Smiriam 		if (setjmp(timeoutbuf)) {
15018635Smiriam 			signal(SIGALRM, f);
15118635Smiriam 			return (0);
15218635Smiriam 		}
15318635Smiriam 		alarm(number(value(DIALTIMEOUT)));
15418635Smiriam 		read(FD, &c, 1);
15518635Smiriam 		alarm(0);
15618635Smiriam 		c &= 0177;
15718635Smiriam #ifdef DEBUG
15818635Smiriam 		printf("%c 0x%x ", c, c);
15918635Smiriam #endif
16018635Smiriam 		for (i = 0; i < strlen(match); i++)
16118635Smiriam 			if (c == match[i])
16218635Smiriam 				status = c;
16318635Smiriam 	} while (status == 0);
16418635Smiriam 	signal(SIGALRM, SIG_DFL);
16518635Smiriam #ifdef DEBUG
16618635Smiriam 	printf("\n");
16718635Smiriam #endif
16818635Smiriam 	return (status);
16918635Smiriam }
17018635Smiriam 
17118635Smiriam error_rep(c)
17218635Smiriam 	register char c;
17318635Smiriam {
17418635Smiriam 	printf("\n\r");
17518635Smiriam 	switch (c) {
17618635Smiriam 
17718635Smiriam 	case '0':
17818635Smiriam 		printf("OK");
17918635Smiriam 		break;
18018635Smiriam 
18118635Smiriam 	case '1':
18218635Smiriam 		printf("CONNECT");
18318635Smiriam 		break;
18418635Smiriam 
18518635Smiriam 	case '2':
18618635Smiriam 		printf("RING");
18718635Smiriam 		break;
18818635Smiriam 
18918635Smiriam 	case '3':
19018635Smiriam 		printf("NO CARRIER");
19118635Smiriam 		break;
19218635Smiriam 
19318635Smiriam 	case '4':
19418635Smiriam 		printf("ERROR in input");
19518635Smiriam 		break;
19618635Smiriam 
19718635Smiriam 	case '5':
19818635Smiriam 		printf("CONNECT 1200");
19918635Smiriam 		break;
20018635Smiriam 
20118635Smiriam 	default:
20218635Smiriam 		printf("Unknown Modem error: %c (0x%x)", c, c);
20318635Smiriam 	}
20418635Smiriam 	printf("\n\r");
20518635Smiriam 	return;
20618635Smiriam }
20718635Smiriam 
20818635Smiriam /*
20918635Smiriam  * set modem back to normal verbose status codes.
21018635Smiriam  */
21118635Smiriam goodbye()
21218635Smiriam {
21318635Smiriam 	int len, rlen;
21418635Smiriam 	char c;
21518635Smiriam 
21618635Smiriam 	ioctl(FD, TIOCFLUSH, &len);	/* get rid of trash */
21718635Smiriam 	if (hay_sync()) {
21818635Smiriam 		sleep(1);
21918635Smiriam #ifndef DEBUG
22018635Smiriam 		ioctl(FD, TIOCFLUSH, 0);
22118635Smiriam #endif
22218635Smiriam 		write(FD, "ATH0\r", 5);		/* insurance */
22318635Smiriam #ifndef DEBUG
22418635Smiriam 		c = gobble("03");
22518635Smiriam 		if (c != '0' && c != '3') {
22618635Smiriam 			printf("cannot hang up modem\n\r");
22718635Smiriam 			printf("please use 'tip dialer' to make sure the line is hung up\n\r");
22818635Smiriam 		}
22918635Smiriam #endif
23018635Smiriam 		sleep(1);
23118635Smiriam 		ioctl(FD, FIONREAD, &len);
23218635Smiriam #ifdef DEBUG
23318635Smiriam 		printf("goodbye1: len=%d -- ", len);
23418635Smiriam 		rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
23518635Smiriam 		dumbuf[rlen] = '\0';
23618635Smiriam 		printf("read (%d): %s\r\n", rlen, dumbuf);
23718635Smiriam #endif
23818635Smiriam 		write(FD, "ATv1\r", 5);
23918635Smiriam 		sleep(1);
24018635Smiriam #ifdef DEBUG
24118635Smiriam 		ioctl(FD, FIONREAD, &len);
24218635Smiriam 		printf("goodbye2: len=%d -- ", len);
24318635Smiriam 		rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
24418635Smiriam 		dumbuf[rlen] = '\0';
24518635Smiriam 		printf("read (%d): %s\r\n", rlen, dumbuf);
24618635Smiriam #endif
24718635Smiriam 	}
24818635Smiriam 	ioctl(FD, TIOCFLUSH, 0);	/* clear the input buffer */
24918635Smiriam 	ioctl(FD, TIOCCDTR, 0);		/* clear DTR (insurance) */
25018635Smiriam 	close(FD);
25118635Smiriam }
25218635Smiriam 
25318635Smiriam #define MAXRETRY	5
25418635Smiriam 
25518635Smiriam hay_sync()
25618635Smiriam {
25718635Smiriam 	int len, retry = 0;
25818635Smiriam 
25918635Smiriam 	while (retry++ <= MAXRETRY) {
26018635Smiriam 		write(FD, "AT\r", 3);
26118635Smiriam 		sleep(1);
26218635Smiriam 		ioctl(FD, FIONREAD, &len);
26318635Smiriam 		if (len) {
26418635Smiriam 			len = read(FD, dumbuf, min(len, DUMBUFLEN));
26518635Smiriam 			if (index(dumbuf, '0') ||
26618635Smiriam 		   	(index(dumbuf, 'O') && index(dumbuf, 'K')))
26718635Smiriam 				return(1);
26818635Smiriam #ifdef DEBUG
26918635Smiriam 			dumbuf[len] = '\0';
27018635Smiriam 			printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry);
27118635Smiriam #endif
27218635Smiriam 		}
27318635Smiriam 		ioctl(FD, TIOCCDTR, 0);
27418635Smiriam 		ioctl(FD, TIOCSDTR, 0);
27518635Smiriam 	}
27618635Smiriam 	printf("Cannot synchronize with hayes...\n\r");
27718635Smiriam 	return(0);
27818635Smiriam }
279