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