hayes.c revision 1.6 1 /* $NetBSD: hayes.c,v 1.6 1997/02/11 09:24:17 mrg Exp $ */
2
3 /*
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)hayes.c 8.1 (Berkeley) 6/6/93";
39 #endif
40 static char rcsid[] = "$NetBSD: hayes.c,v 1.6 1997/02/11 09:24:17 mrg Exp $";
41 #endif /* not lint */
42
43 /*
44 * Routines for calling up on a Hayes Modem
45 * (based on the old VenTel driver).
46 * The modem is expected to be strapped for "echo".
47 * Also, the switches enabling the DTR and CD lines
48 * must be set correctly.
49 * NOTICE:
50 * The easy way to hang up a modem is always simply to
51 * clear the DTR signal. However, if the +++ sequence
52 * (which switches the modem back to local mode) is sent
53 * before modem is hung up, removal of the DTR signal
54 * has no effect (except that it prevents the modem from
55 * recognizing commands).
56 * (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984)
57 */
58 /*
59 * TODO:
60 * It is probably not a good idea to switch the modem
61 * state between 'verbose' and terse (status messages).
62 * This should be kicked out and we should use verbose
63 * mode only. This would make it consistent with normal
64 * interactive use thru the command 'tip dialer'.
65 */
66 #include "tip.h"
67
68 #include <termios.h>
69 #include <sys/ioctl.h>
70
71 #define min(a,b) ((a < b) ? a : b)
72
73 static void sigALRM();
74 static int timeout = 0;
75 static jmp_buf timeoutbuf;
76 static char gobble();
77 #define DUMBUFLEN 40
78 static char dumbuf[DUMBUFLEN];
79
80 #define DIALING 1
81 #define IDLE 2
82 #define CONNECTED 3
83 #define FAILED 4
84 static int state = IDLE;
85
86 hay_dialer(num, acu)
87 register char *num;
88 char *acu;
89 {
90 register char *cp;
91 register int connected = 0;
92 char dummy;
93 struct termios cntrl;
94 #ifdef ACULOG
95 char line[80];
96 #endif
97 if (hay_sync() == 0) /* make sure we can talk to the modem */
98 return(0);
99 if (boolean(value(VERBOSE)))
100 printf("\ndialing...");
101 fflush(stdout);
102 tcgetattr(FD, &cntrl);
103 cntrl.c_cflag |= HUPCL;
104 tcsetattr(FD, TCSANOW, &cntrl);
105 tcflush(FD, TCIOFLUSH);
106 write(FD, "ATv0\r", 5); /* tell modem to use short status codes */
107 gobble("\r");
108 gobble("\r");
109 write(FD, "ATTD", 4); /* send dial command */
110 for (cp = num; *cp; cp++)
111 if (*cp == '=')
112 *cp = ',';
113 write(FD, num, strlen(num));
114 state = DIALING;
115 write(FD, "\r", 1);
116 connected = 0;
117 if (gobble("\r")) {
118 if ((dummy = gobble("01234")) != '1')
119 error_rep(dummy);
120 else
121 connected = 1;
122 }
123 if (connected)
124 state = CONNECTED;
125 else {
126 state = FAILED;
127 return (connected); /* lets get out of here.. */
128 }
129 tcflush(FD, TCIOFLUSH);
130 #ifdef ACULOG
131 if (timeout) {
132 (void)snprintf(line, sizeof line, "%d second dial timeout",
133 number(value(DIALTIMEOUT)));
134 logent(value(HOST), num, "hayes", line);
135 }
136 #endif
137 if (timeout)
138 hay_disconnect(); /* insurance */
139 return (connected);
140 }
141
142
143 hay_disconnect()
144 {
145 char c;
146 int len, rlen;
147
148 /* first hang up the modem*/
149 #ifdef DEBUG
150 printf("\rdisconnecting modem....\n\r");
151 #endif
152 ioctl(FD, TIOCCDTR, 0);
153 sleep(1);
154 ioctl(FD, TIOCSDTR, 0);
155 goodbye();
156 }
157
158 hay_abort()
159 {
160
161 char c;
162
163 write(FD, "\r", 1); /* send anything to abort the call */
164 hay_disconnect();
165 }
166
167 static void
168 sigALRM()
169 {
170
171 printf("\07timeout waiting for reply\n\r");
172 timeout = 1;
173 longjmp(timeoutbuf, 1);
174 }
175
176 static char
177 gobble(match)
178 register char *match;
179 {
180 char c;
181 sig_t f;
182 int i, status = 0;
183
184 f = signal(SIGALRM, sigALRM);
185 timeout = 0;
186 #ifdef DEBUG
187 printf("\ngobble: waiting for %s\n", match);
188 #endif
189 do {
190 if (setjmp(timeoutbuf)) {
191 signal(SIGALRM, f);
192 return (0);
193 }
194 alarm(number(value(DIALTIMEOUT)));
195 read(FD, &c, 1);
196 alarm(0);
197 c &= 0177;
198 #ifdef DEBUG
199 printf("%c 0x%x ", c, c);
200 #endif
201 for (i = 0; i < strlen(match); i++)
202 if (c == match[i])
203 status = c;
204 } while (status == 0);
205 signal(SIGALRM, SIG_DFL);
206 #ifdef DEBUG
207 printf("\n");
208 #endif
209 return (status);
210 }
211
212 error_rep(c)
213 register char c;
214 {
215 printf("\n\r");
216 switch (c) {
217
218 case '0':
219 printf("OK");
220 break;
221
222 case '1':
223 printf("CONNECT");
224 break;
225
226 case '2':
227 printf("RING");
228 break;
229
230 case '3':
231 printf("NO CARRIER");
232 break;
233
234 case '4':
235 printf("ERROR in input");
236 break;
237
238 case '5':
239 printf("CONNECT 1200");
240 break;
241
242 default:
243 printf("Unknown Modem error: %c (0x%x)", c, c);
244 }
245 printf("\n\r");
246 return;
247 }
248
249 /*
250 * set modem back to normal verbose status codes.
251 */
252 goodbye()
253 {
254 int len, rlen;
255 char c;
256
257 tcflush(FD, TCIOFLUSH);
258 if (hay_sync()) {
259 sleep(1);
260 #ifndef DEBUG
261 tcflush(FD, TCIOFLUSH);
262 #endif
263 write(FD, "ATH0\r", 5); /* insurance */
264 #ifndef DEBUG
265 c = gobble("03");
266 if (c != '0' && c != '3') {
267 printf("cannot hang up modem\n\r");
268 printf("please use 'tip dialer' to make sure the line is hung up\n\r");
269 }
270 #endif
271 sleep(1);
272 ioctl(FD, FIONREAD, &len);
273 #ifdef DEBUG
274 printf("goodbye1: len=%d -- ", len);
275 rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
276 dumbuf[rlen] = '\0';
277 printf("read (%d): %s\r\n", rlen, dumbuf);
278 #endif
279 write(FD, "ATv1\r", 5);
280 sleep(1);
281 #ifdef DEBUG
282 ioctl(FD, FIONREAD, &len);
283 printf("goodbye2: len=%d -- ", len);
284 rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
285 dumbuf[rlen] = '\0';
286 printf("read (%d): %s\r\n", rlen, dumbuf);
287 #endif
288 }
289 tcflush(FD, TCIOFLUSH);
290 ioctl(FD, TIOCCDTR, 0); /* clear DTR (insurance) */
291 close(FD);
292 }
293
294 #define MAXRETRY 5
295
296 hay_sync()
297 {
298 int len, retry = 0;
299
300 while (retry++ <= MAXRETRY) {
301 write(FD, "AT\r", 3);
302 sleep(1);
303 ioctl(FD, FIONREAD, &len);
304 if (len) {
305 len = read(FD, dumbuf, min(len, DUMBUFLEN));
306 if (index(dumbuf, '0') ||
307 (index(dumbuf, 'O') && index(dumbuf, 'K')))
308 return(1);
309 #ifdef DEBUG
310 dumbuf[len] = '\0';
311 printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry);
312 #endif
313 }
314 ioctl(FD, TIOCCDTR, 0);
315 ioctl(FD, TIOCSDTR, 0);
316 }
317 printf("Cannot synchronize with hayes...\n\r");
318 return(0);
319 }
320