xref: /csrg-svn/usr.bin/tip/aculib/ventel.c (revision 42770)
1 /*
2  * Copyright (c) 1983 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)ventel.c	5.3 (Berkeley) 06/01/90";
10 #endif /* not lint */
11 
12 /*
13  * Routines for calling up on a Ventel Modem
14  * The Ventel is expected to be strapped for local echo (just like uucp)
15  */
16 #include "tip.h"
17 
18 #define	MAXRETRY	5
19 
20 static	int sigALRM();
21 static	int timeout = 0;
22 static	jmp_buf timeoutbuf;
23 
24 /*
25  * some sleep calls have been replaced by this macro
26  * because some ventel modems require two <cr>s in less than
27  * a second in order to 'wake up'... yes, it is dirty...
28  */
29 #define delay(num,denom) busyloop(CPUSPEED*num/denom)
30 #define CPUSPEED 1000000	/* VAX 780 is 1MIPS */
31 #define	DELAY(n)	{ register long N = (n); while (--N > 0); }
32 busyloop(n) { DELAY(n); }
33 
34 ven_dialer(num, acu)
35 	register char *num;
36 	char *acu;
37 {
38 	register char *cp;
39 	register int connected = 0;
40 	char *msg, *index(), line[80];
41 
42 	/*
43 	 * Get in synch with a couple of carriage returns
44 	 */
45 	if (!vensync(FD)) {
46 		printf("can't synchronize with ventel\n");
47 #ifdef ACULOG
48 		logent(value(HOST), num, "ventel", "can't synch up");
49 #endif
50 		return (0);
51 	}
52 	if (boolean(value(VERBOSE)))
53 		printf("\ndialing...");
54 	fflush(stdout);
55 	ioctl(FD, TIOCHPCL, 0);
56 	echo("#k$\r$\n$D$I$A$L$:$ ");
57 	for (cp = num; *cp; cp++) {
58 		delay(1, 10);
59 		write(FD, cp, 1);
60 	}
61 	delay(1, 10);
62 	write(FD, "\r", 1);
63 	gobble('\n', line);
64 	if (gobble('\n', line))
65 		connected = gobble('!', line);
66 	ioctl(FD, TIOCFLUSH);
67 #ifdef ACULOG
68 	if (timeout) {
69 		sprintf(line, "%d second dial timeout",
70 			number(value(DIALTIMEOUT)));
71 		logent(value(HOST), num, "ventel", line);
72 	}
73 #endif
74 	if (timeout)
75 		ven_disconnect();	/* insurance */
76 	if (connected || timeout || !boolean(value(VERBOSE)))
77 		return (connected);
78 	/* call failed, parse response for user */
79 	cp = index(line, '\r');
80 	if (cp)
81 		*cp = '\0';
82 	for (cp = line; cp = index(cp, ' '); cp++)
83 		if (cp[1] == ' ')
84 			break;
85 	if (cp) {
86 		while (*cp == ' ')
87 			cp++;
88 		msg = cp;
89 		while (*cp) {
90 			if (isupper(*cp))
91 				*cp = tolower(*cp);
92 			cp++;
93 		}
94 		printf("%s...", msg);
95 	}
96 	return (connected);
97 }
98 
99 ven_disconnect()
100 {
101 
102 	close(FD);
103 }
104 
105 ven_abort()
106 {
107 
108 	write(FD, "\03", 1);
109 	close(FD);
110 }
111 
112 static int
113 echo(s)
114 	register char *s;
115 {
116 	char c;
117 
118 	while (c = *s++) switch (c) {
119 
120 	case '$':
121 		read(FD, &c, 1);
122 		s++;
123 		break;
124 
125 	case '#':
126 		c = *s++;
127 		write(FD, &c, 1);
128 		break;
129 
130 	default:
131 		write(FD, &c, 1);
132 		read(FD, &c, 1);
133 	}
134 }
135 
136 static int
137 sigALRM()
138 {
139 
140 	printf("\07timeout waiting for reply\n");
141 	timeout = 1;
142 	longjmp(timeoutbuf, 1);
143 }
144 
145 static int
146 gobble(match, response)
147 	register char match;
148 	char response[];
149 {
150 	register char *cp = response;
151 	char c;
152 	int (*f)();
153 
154 	signal(SIGALRM, sigALRM);
155 	timeout = 0;
156 	do {
157 		if (setjmp(timeoutbuf)) {
158 			signal(SIGALRM, f);
159 			*cp = '\0';
160 			return (0);
161 		}
162 		alarm(number(value(DIALTIMEOUT)));
163 		read(FD, cp, 1);
164 		alarm(0);
165 		c = (*cp++ &= 0177);
166 #ifdef notdef
167 		if (boolean(value(VERBOSE)))
168 			putchar(c);
169 #endif
170 	} while (c != '\n' && c != match);
171 	signal(SIGALRM, SIG_DFL);
172 	*cp = '\0';
173 	return (c == match);
174 }
175 
176 #define min(a,b)	((a)>(b)?(b):(a))
177 /*
178  * This convoluted piece of code attempts to get
179  * the ventel in sync.  If you don't have FIONREAD
180  * there are gory ways to simulate this.
181  */
182 static int
183 vensync(fd)
184 {
185 	int already = 0, nread;
186 	char buf[60];
187 
188 	/*
189 	 * Toggle DTR to force anyone off that might have left
190 	 * the modem connected, and insure a consistent state
191 	 * to start from.
192 	 *
193 	 * If you don't have the ioctl calls to diddle directly
194 	 * with DTR, you can always try setting the baud rate to 0.
195 	 */
196 	ioctl(FD, TIOCCDTR, 0);
197 	sleep(1);
198 	ioctl(FD, TIOCSDTR, 0);
199 	while (already < MAXRETRY) {
200 		/*
201 		 * After reseting the modem, send it two \r's to
202 		 * autobaud on. Make sure to delay between them
203 		 * so the modem can frame the incoming characters.
204 		 */
205 		write(fd, "\r", 1);
206 		delay(1,10);
207 		write(fd, "\r", 1);
208 		sleep(2);
209 		if (ioctl(fd, FIONREAD, (caddr_t)&nread) < 0) {
210 			perror("tip: ioctl");
211 			continue;
212 		}
213 		while (nread > 0) {
214 			read(fd, buf, min(nread, 60));
215 			if ((buf[nread - 1] & 0177) == '$')
216 				return (1);
217 			nread -= min(nread, 60);
218 		}
219 		sleep(1);
220 		already++;
221 	}
222 	return (0);
223 }
224 
225