xref: /csrg-svn/usr.bin/tip/aculib/hayes.c (revision 18635)
1*18635Smiriam #ifndef lint
2*18635Smiriam static char sccsid[] = "@(#)hayes.c	1.1 (Berkeley) 85/04/11 ";
3*18635Smiriam #endif
4*18635Smiriam 
5*18635Smiriam /*
6*18635Smiriam  * Routines for calling up on a Hayes Modem
7*18635Smiriam  * (based on the old VenTel driver).
8*18635Smiriam  * The modem is expected to be strapped for "echo".
9*18635Smiriam  * Also, the switches enabling the DTR and CD lines
10*18635Smiriam  * must be set correctly.
11*18635Smiriam  * NOTICE:
12*18635Smiriam  * The easy way to hang up a modem is always simply to
13*18635Smiriam  * clear the DTR signal. However, if the +++ sequence
14*18635Smiriam  * (which switches the modem back to local mode) is sent
15*18635Smiriam  * before modem is hung up, removal of the DTR signal
16*18635Smiriam  * has no effect (except that it prevents the modem from
17*18635Smiriam  * recognizing commands).
18*18635Smiriam  * (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984)
19*18635Smiriam  */
20*18635Smiriam /*
21*18635Smiriam  * TODO:
22*18635Smiriam  * It is probably not a good idea to switch the modem
23*18635Smiriam  * state between 'verbose' and terse (status messages).
24*18635Smiriam  * This should be kicked out and we should use verbose
25*18635Smiriam  * mode only. This would make it consistent with normal
26*18635Smiriam  * interactive use thru the command 'tip dialer'.
27*18635Smiriam  */
28*18635Smiriam #include "tip.h"
29*18635Smiriam 
30*18635Smiriam #define	min(a,b)	((a < b) ? a : b)
31*18635Smiriam 
32*18635Smiriam static	int sigALRM();
33*18635Smiriam static	int timeout = 0;
34*18635Smiriam static	jmp_buf timeoutbuf;
35*18635Smiriam static 	char gobble();
36*18635Smiriam #define DUMBUFLEN	40
37*18635Smiriam static char dumbuf[DUMBUFLEN];
38*18635Smiriam 
39*18635Smiriam #define	DIALING		1
40*18635Smiriam #define IDLE		2
41*18635Smiriam #define CONNECTED	3
42*18635Smiriam #define	FAILED		4
43*18635Smiriam static	int state = IDLE;
44*18635Smiriam 
45*18635Smiriam hay_dialer(num, acu)
46*18635Smiriam 	register char *num;
47*18635Smiriam 	char *acu;
48*18635Smiriam {
49*18635Smiriam 	register char *cp;
50*18635Smiriam 	register int connected = 0;
51*18635Smiriam 	char dummy;
52*18635Smiriam #ifdef ACULOG
53*18635Smiriam 	char line[80];
54*18635Smiriam #endif
55*18635Smiriam 	if (hay_sync() == 0)		/* make sure we can talk to the modem */
56*18635Smiriam 		return(0);
57*18635Smiriam 	if (boolean(value(VERBOSE)))
58*18635Smiriam 		printf("\ndialing...");
59*18635Smiriam 	fflush(stdout);
60*18635Smiriam 	ioctl(FD, TIOCHPCL, 0);
61*18635Smiriam 	ioctl(FD, TIOCFLUSH, 0);	/* get rid of garbage */
62*18635Smiriam 	write(FD, "ATv0\r", 5);	/* tell modem to use short status codes */
63*18635Smiriam 	gobble("\r");
64*18635Smiriam 	gobble("\r");
65*18635Smiriam 	write(FD, "ATTD", 4);	/* send dial command */
66*18635Smiriam 	write(FD, num, strlen(num));
67*18635Smiriam 	state = DIALING;
68*18635Smiriam 	write(FD, "\r", 1);
69*18635Smiriam 	connected = 0;
70*18635Smiriam 	if (gobble("\r")) {
71*18635Smiriam 		if ((dummy = gobble("01234")) != '1')
72*18635Smiriam 			error_rep(dummy);
73*18635Smiriam 		else
74*18635Smiriam 			connected = 1;
75*18635Smiriam 	}
76*18635Smiriam 	if (connected)
77*18635Smiriam 		state = CONNECTED;
78*18635Smiriam 	else {
79*18635Smiriam 		state = FAILED;
80*18635Smiriam 		return (connected);	/* lets get out of here.. */
81*18635Smiriam 	}
82*18635Smiriam 	ioctl(FD, TIOCFLUSH, 0);
83*18635Smiriam #ifdef ACULOG
84*18635Smiriam 	if (timeout) {
85*18635Smiriam 		sprintf(line, "%d second dial timeout",
86*18635Smiriam 			number(value(DIALTIMEOUT)));
87*18635Smiriam 		logent(value(HOST), num, "hayes", line);
88*18635Smiriam 	}
89*18635Smiriam #endif
90*18635Smiriam 	if (timeout)
91*18635Smiriam 		hay_disconnect();	/* insurance */
92*18635Smiriam 	return (connected);
93*18635Smiriam }
94*18635Smiriam 
95*18635Smiriam 
96*18635Smiriam hay_disconnect()
97*18635Smiriam {
98*18635Smiriam 	char c;
99*18635Smiriam 	int len, rlen;
100*18635Smiriam 
101*18635Smiriam 	/* first hang up the modem*/
102*18635Smiriam #ifdef DEBUG
103*18635Smiriam 	printf("\rdisconnecting modem....\n\r");
104*18635Smiriam #endif
105*18635Smiriam 	ioctl(FD, TIOCCDTR, 0);
106*18635Smiriam 	sleep(1);
107*18635Smiriam 	ioctl(FD, TIOCSDTR, 0);
108*18635Smiriam 	goodbye();
109*18635Smiriam }
110*18635Smiriam 
111*18635Smiriam hay_abort()
112*18635Smiriam {
113*18635Smiriam 
114*18635Smiriam 	char c;
115*18635Smiriam 
116*18635Smiriam 	write(FD, "\r", 1);	/* send anything to abort the call */
117*18635Smiriam 	hay_disconnect();
118*18635Smiriam }
119*18635Smiriam 
120*18635Smiriam static int
121*18635Smiriam sigALRM()
122*18635Smiriam {
123*18635Smiriam 
124*18635Smiriam 	printf("\07timeout waiting for reply\n\r");
125*18635Smiriam 	timeout = 1;
126*18635Smiriam 	longjmp(timeoutbuf, 1);
127*18635Smiriam }
128*18635Smiriam 
129*18635Smiriam static char
130*18635Smiriam gobble(match)
131*18635Smiriam 	register char *match;
132*18635Smiriam {
133*18635Smiriam 	char c;
134*18635Smiriam 	int (*f)();
135*18635Smiriam 	int i, status = 0;
136*18635Smiriam 
137*18635Smiriam 	signal(SIGALRM, sigALRM);
138*18635Smiriam 	timeout = 0;
139*18635Smiriam #ifdef DEBUG
140*18635Smiriam 	printf("\ngobble: waiting for %s\n", match);
141*18635Smiriam #endif
142*18635Smiriam 	do {
143*18635Smiriam 		if (setjmp(timeoutbuf)) {
144*18635Smiriam 			signal(SIGALRM, f);
145*18635Smiriam 			return (0);
146*18635Smiriam 		}
147*18635Smiriam 		alarm(number(value(DIALTIMEOUT)));
148*18635Smiriam 		read(FD, &c, 1);
149*18635Smiriam 		alarm(0);
150*18635Smiriam 		c &= 0177;
151*18635Smiriam #ifdef DEBUG
152*18635Smiriam 		printf("%c 0x%x ", c, c);
153*18635Smiriam #endif
154*18635Smiriam 		for (i = 0; i < strlen(match); i++)
155*18635Smiriam 			if (c == match[i])
156*18635Smiriam 				status = c;
157*18635Smiriam 	} while (status == 0);
158*18635Smiriam 	signal(SIGALRM, SIG_DFL);
159*18635Smiriam #ifdef DEBUG
160*18635Smiriam 	printf("\n");
161*18635Smiriam #endif
162*18635Smiriam 	return (status);
163*18635Smiriam }
164*18635Smiriam 
165*18635Smiriam error_rep(c)
166*18635Smiriam 	register char c;
167*18635Smiriam {
168*18635Smiriam 	printf("\n\r");
169*18635Smiriam 	switch (c) {
170*18635Smiriam 
171*18635Smiriam 	case '0':
172*18635Smiriam 		printf("OK");
173*18635Smiriam 		break;
174*18635Smiriam 
175*18635Smiriam 	case '1':
176*18635Smiriam 		printf("CONNECT");
177*18635Smiriam 		break;
178*18635Smiriam 
179*18635Smiriam 	case '2':
180*18635Smiriam 		printf("RING");
181*18635Smiriam 		break;
182*18635Smiriam 
183*18635Smiriam 	case '3':
184*18635Smiriam 		printf("NO CARRIER");
185*18635Smiriam 		break;
186*18635Smiriam 
187*18635Smiriam 	case '4':
188*18635Smiriam 		printf("ERROR in input");
189*18635Smiriam 		break;
190*18635Smiriam 
191*18635Smiriam 	case '5':
192*18635Smiriam 		printf("CONNECT 1200");
193*18635Smiriam 		break;
194*18635Smiriam 
195*18635Smiriam 	default:
196*18635Smiriam 		printf("Unknown Modem error: %c (0x%x)", c, c);
197*18635Smiriam 	}
198*18635Smiriam 	printf("\n\r");
199*18635Smiriam 	return;
200*18635Smiriam }
201*18635Smiriam 
202*18635Smiriam /*
203*18635Smiriam  * set modem back to normal verbose status codes.
204*18635Smiriam  */
205*18635Smiriam goodbye()
206*18635Smiriam {
207*18635Smiriam 	int len, rlen;
208*18635Smiriam 	char c;
209*18635Smiriam 
210*18635Smiriam 	ioctl(FD, TIOCFLUSH, &len);	/* get rid of trash */
211*18635Smiriam 	if (hay_sync()) {
212*18635Smiriam 		sleep(1);
213*18635Smiriam #ifndef DEBUG
214*18635Smiriam 		ioctl(FD, TIOCFLUSH, 0);
215*18635Smiriam #endif
216*18635Smiriam 		write(FD, "ATH0\r", 5);		/* insurance */
217*18635Smiriam #ifndef DEBUG
218*18635Smiriam 		c = gobble("03");
219*18635Smiriam 		if (c != '0' && c != '3') {
220*18635Smiriam 			printf("cannot hang up modem\n\r");
221*18635Smiriam 			printf("please use 'tip dialer' to make sure the line is hung up\n\r");
222*18635Smiriam 		}
223*18635Smiriam #endif
224*18635Smiriam 		sleep(1);
225*18635Smiriam 		ioctl(FD, FIONREAD, &len);
226*18635Smiriam #ifdef DEBUG
227*18635Smiriam 		printf("goodbye1: len=%d -- ", len);
228*18635Smiriam 		rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
229*18635Smiriam 		dumbuf[rlen] = '\0';
230*18635Smiriam 		printf("read (%d): %s\r\n", rlen, dumbuf);
231*18635Smiriam #endif
232*18635Smiriam 		write(FD, "ATv1\r", 5);
233*18635Smiriam 		sleep(1);
234*18635Smiriam #ifdef DEBUG
235*18635Smiriam 		ioctl(FD, FIONREAD, &len);
236*18635Smiriam 		printf("goodbye2: len=%d -- ", len);
237*18635Smiriam 		rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
238*18635Smiriam 		dumbuf[rlen] = '\0';
239*18635Smiriam 		printf("read (%d): %s\r\n", rlen, dumbuf);
240*18635Smiriam #endif
241*18635Smiriam 	}
242*18635Smiriam 	ioctl(FD, TIOCFLUSH, 0);	/* clear the input buffer */
243*18635Smiriam 	ioctl(FD, TIOCCDTR, 0);		/* clear DTR (insurance) */
244*18635Smiriam 	close(FD);
245*18635Smiriam }
246*18635Smiriam 
247*18635Smiriam #define MAXRETRY	5
248*18635Smiriam 
249*18635Smiriam hay_sync()
250*18635Smiriam {
251*18635Smiriam 	int len, retry = 0;
252*18635Smiriam 
253*18635Smiriam 	while (retry++ <= MAXRETRY) {
254*18635Smiriam 		write(FD, "AT\r", 3);
255*18635Smiriam 		sleep(1);
256*18635Smiriam 		ioctl(FD, FIONREAD, &len);
257*18635Smiriam 		if (len) {
258*18635Smiriam 			len = read(FD, dumbuf, min(len, DUMBUFLEN));
259*18635Smiriam 			if (index(dumbuf, '0') ||
260*18635Smiriam 		   	(index(dumbuf, 'O') && index(dumbuf, 'K')))
261*18635Smiriam 				return(1);
262*18635Smiriam #ifdef DEBUG
263*18635Smiriam 			dumbuf[len] = '\0';
264*18635Smiriam 			printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry);
265*18635Smiriam #endif
266*18635Smiriam 		}
267*18635Smiriam 		ioctl(FD, TIOCCDTR, 0);
268*18635Smiriam 		ioctl(FD, TIOCSDTR, 0);
269*18635Smiriam 	}
270*18635Smiriam 	printf("Cannot synchronize with hayes...\n\r");
271*18635Smiriam 	return(0);
272*18635Smiriam }
273