xref: /freebsd/usr.bin/tip/libacu/t3000.c (revision 8e6b01171e30297084bb0b4457c4183c2746aacc)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifndef lint
35 static char sccsid[] = "@(#)t3000.c	8.1 (Berkeley) 6/6/93";
36 #endif /* not lint */
37 
38 /*
39  * Routines for calling up on a Telebit T3000 modem.
40  * Derived from Courier driver.
41  */
42 #include "tipconf.h"
43 #include "tip.h"
44 #include "acucommon.h"
45 #include <stdio.h>
46 
47 #define	MAXRETRY	5
48 
49 static	void sigALRM();
50 static	int timeout = 0;
51 static	int connected = 0;
52 static	jmp_buf timeoutbuf, intbuf;
53 static	int t3000_sync();
54 
55 t3000_dialer(num, acu)
56 	register char *num;
57 	char *acu;
58 {
59 	register char *cp;
60 #if ACULOG
61 	char line[80];
62 #endif
63 	static int t3000_connect(), t3000_swallow();
64 
65 	if (boolean(value(VERBOSE)))
66 		printf("Using \"%s\"\n", acu);
67 
68 	acu_hupcl ();
69 	/*
70 	 * Get in synch.
71 	 */
72 	if (!t3000_sync()) {
73 badsynch:
74 		printf("can't synchronize with t3000\n");
75 #if ACULOG
76 		logent(value(HOST), num, "t3000", "can't synch up");
77 #endif
78 		return (0);
79 	}
80 	t3000_write(FD, "AT E0\r", 6);	/* turn off echoing */
81 	sleep(1);
82 #ifdef DEBUG
83 	if (boolean(value(VERBOSE)))
84 		t3000_verbose_read();
85 #endif
86 	ioctl(FD, TIOCFLUSH, 0);	/* flush any clutter */
87 	t3000_write(FD, "AT E0 H0 Q0 X4 V1\r", 18);
88 	if (!t3000_swallow("\r\nOK\r\n"))
89 		goto badsynch;
90 	fflush(stdout);
91 	t3000_write(FD, "AT D", 4);
92 	for (cp = num; *cp; cp++)
93 		if (*cp == '=')
94 			*cp = ',';
95 	t3000_write(FD, num, strlen(num));
96 	t3000_write(FD, "\r", 1);
97 	connected = t3000_connect();
98 #if ACULOG
99 	if (timeout) {
100 		sprintf(line, "%d second dial timeout",
101 			number(value(DIALTIMEOUT)));
102 		logent(value(HOST), num, "t3000", line);
103 	}
104 #endif
105 	if (timeout)
106 		t3000_disconnect();
107 	return (connected);
108 }
109 
110 t3000_disconnect()
111 {
112 	 /* first hang up the modem*/
113 	ioctl(FD, TIOCCDTR, 0);
114 	sleep(1);
115 	ioctl(FD, TIOCSDTR, 0);
116 	t3000_sync();				/* reset */
117 	close(FD);
118 }
119 
120 t3000_abort()
121 {
122 	t3000_write(FD, "\r", 1);	/* send anything to abort the call */
123 	t3000_disconnect();
124 }
125 
126 static void
127 sigALRM()
128 {
129 	printf("\07timeout waiting for reply\n");
130 	timeout = 1;
131 	longjmp(timeoutbuf, 1);
132 }
133 
134 static int
135 t3000_swallow(match)
136   register char *match;
137   {
138 	sig_t f;
139 	char c;
140 
141 	f = signal(SIGALRM, sigALRM);
142 	timeout = 0;
143 	do {
144 		if (*match =='\0') {
145 			signal(SIGALRM, f);
146 			return (1);
147 		}
148 		if (setjmp(timeoutbuf)) {
149 			signal(SIGALRM, f);
150 			return (0);
151 		}
152 		alarm(number(value(DIALTIMEOUT)));
153 		read(FD, &c, 1);
154 		alarm(0);
155 		c &= 0177;
156 #ifdef DEBUG
157 		if (boolean(value(VERBOSE)))
158 			putchar(c);
159 #endif
160 	} while (c == *match++);
161 #ifdef DEBUG
162 	if (boolean(value(VERBOSE)))
163 		fflush(stdout);
164 #endif
165 	signal(SIGALRM, SIG_DFL);
166 	return (0);
167 }
168 
169 #ifndef B19200		/* XXX */
170 #define	B19200	EXTA
171 #define	B38400	EXTB
172 #endif
173 
174 struct tbaud_msg {
175 	char *msg;
176 	int baud;
177 	int baud2;
178 } tbaud_msg[] = {
179 	"",		B300,	0,
180 	" 1200",	B1200,	0,
181 	" 2400",	B2400,	0,
182 	" 4800",	B4800,	0,
183 	" 9600",	B9600,	0,
184 	" 14400",	B19200,	B9600,
185 	" 19200",	B19200,	B9600,
186 	" 38400",	B38400,	B9600,
187 	" 57600",	B38400,	B9600,
188 	" 7512",	B9600,	0,
189 	" 1275",	B2400,	0,
190 	" 7200",	B9600,	0,
191 	" 12000",	B19200,	B9600,
192 	0,		0,	0,
193 };
194 
195 static int
196 t3000_connect()
197 {
198 	char c;
199 	int nc, nl, n;
200 	char dialer_buf[64];
201 	struct tbaud_msg *bm;
202 	sig_t f;
203 
204 	if (t3000_swallow("\r\n") == 0)
205 		return (0);
206 	f = signal(SIGALRM, sigALRM);
207 again:
208 	nc = 0; nl = sizeof(dialer_buf)-1;
209 	bzero(dialer_buf, sizeof(dialer_buf));
210 	timeout = 0;
211 	for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
212 		if (setjmp(timeoutbuf))
213 			break;
214 		alarm(number(value(DIALTIMEOUT)));
215 		n = read(FD, &c, 1);
216 		alarm(0);
217 		if (n <= 0)
218 			break;
219 		c &= 0x7f;
220 		if (c == '\r') {
221 			if (t3000_swallow("\n") == 0)
222 				break;
223 			if (!dialer_buf[0])
224 				goto again;
225 			if (strcmp(dialer_buf, "RINGING") == 0 &&
226 			    boolean(value(VERBOSE))) {
227 #ifdef DEBUG
228 				printf("%s\r\n", dialer_buf);
229 #endif
230 				goto again;
231 			}
232 			if (strncmp(dialer_buf, "CONNECT",
233 				    sizeof("CONNECT")-1) != 0)
234 				break;
235 			for (bm = tbaud_msg ; bm->msg ; bm++)
236 				if (strcmp(bm->msg,
237 				    dialer_buf+sizeof("CONNECT")-1) == 0) {
238 					if (!(acu_setspeed (bm->baud) || (bm->baud2 && acu_setspeed (bm->baud2))))
239 						goto error;
240 					signal(SIGALRM, f);
241 #ifdef DEBUG
242 					if (boolean(value(VERBOSE)))
243 						printf("%s\r\n", dialer_buf);
244 #endif
245 					return (1);
246 				}
247 			break;
248 		}
249 		dialer_buf[nc] = c;
250 #ifdef notdef
251 		if (boolean(value(VERBOSE)))
252 			putchar(c);
253 #endif
254 	}
255 error1:
256 	printf("%s\r\n", dialer_buf);
257 error:
258 	signal(SIGALRM, f);
259 	return (0);
260 }
261 
262 /*
263  * This convoluted piece of code attempts to get
264  * the t3000 in sync.
265  */
266 static int
267 t3000_sync()
268 {
269 	int already = 0;
270 	int len;
271 	char buf[40];
272 
273 	while (already++ < MAXRETRY) {
274 		ioctl(FD, TIOCFLUSH, 0);	/* flush any clutter */
275 		t3000_write(FD, "\rAT Z\r", 6);	/* reset modem */
276 		bzero(buf, sizeof(buf));
277 		sleep(2);
278 		ioctl(FD, FIONREAD, &len);
279 #if 1
280 if (len == 0) len = 1;
281 #endif
282 		if (len) {
283 			len = read(FD, buf, sizeof(buf));
284 #ifdef DEBUG
285 			buf[len] = '\0';
286 			printf("t3000_sync: (\"%s\")\n\r", buf);
287 #endif
288 			if (index(buf, '0') ||
289 		   	   (index(buf, 'O') && index(buf, 'K')))
290 				return(1);
291 		}
292 		/*
293 		 * If not strapped for DTR control,
294 		 * try to get command mode.
295 		 */
296 		sleep(1);
297 		t3000_write(FD, "+++", 3);
298 		sleep(1);
299 		/*
300 		 * Toggle DTR to force anyone off that might have left
301 		 * the modem connected.
302 		 */
303 		ioctl(FD, TIOCCDTR, 0);
304 		sleep(1);
305 		ioctl(FD, TIOCSDTR, 0);
306 	}
307 	t3000_write(FD, "\rAT Z\r", 6);
308 	return (0);
309 }
310 
311 t3000_write(fd, cp, n)
312 int fd;
313 char *cp;
314 int n;
315 {
316 #ifdef notdef
317 	if (boolean(value(VERBOSE)))
318 		write(1, cp, n);
319 #endif
320 	acu_flush ();
321 	t3000_nap();
322 	for ( ; n-- ; cp++) {
323 		write(fd, cp, 1);
324 		acu_flush ();
325 		t3000_nap();
326 	}
327 }
328 
329 #ifdef DEBUG
330 t3000_verbose_read()
331 {
332 	int n = 0;
333 	char buf[BUFSIZ];
334 
335 	if (ioctl(FD, FIONREAD, &n) < 0)
336 		return;
337 	if (n <= 0)
338 		return;
339 	if (read(FD, buf, n) != n)
340 		return;
341 	write(1, buf, n);
342 }
343 #endif
344 
345 t3000_nap()
346 {
347 	acu_nap (50);
348 }
349 
350 /* end of t3000.c */
351