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