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