hayes.c revision 1.4 1 /* $NetBSD: hayes.c,v 1.4 1995/10/29 00:49:54 pk 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.4 1995/10/29 00:49:54 pk 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 write(FD, num, strlen(num));
111 state = DIALING;
112 write(FD, "\r", 1);
113 connected = 0;
114 if (gobble("\r")) {
115 if ((dummy = gobble("01234")) != '1')
116 error_rep(dummy);
117 else
118 connected = 1;
119 }
120 if (connected)
121 state = CONNECTED;
122 else {
123 state = FAILED;
124 return (connected); /* lets get out of here.. */
125 }
126 tcflush(FD, TCIOFLUSH);
127 #ifdef ACULOG
128 if (timeout) {
129 sprintf(line, "%d second dial timeout",
130 number(value(DIALTIMEOUT)));
131 logent(value(HOST), num, "hayes", line);
132 }
133 #endif
134 if (timeout)
135 hay_disconnect(); /* insurance */
136 return (connected);
137 }
138
139
140 hay_disconnect()
141 {
142 char c;
143 int len, rlen;
144
145 /* first hang up the modem*/
146 #ifdef DEBUG
147 printf("\rdisconnecting modem....\n\r");
148 #endif
149 ioctl(FD, TIOCCDTR, 0);
150 sleep(1);
151 ioctl(FD, TIOCSDTR, 0);
152 goodbye();
153 }
154
155 hay_abort()
156 {
157
158 char c;
159
160 write(FD, "\r", 1); /* send anything to abort the call */
161 hay_disconnect();
162 }
163
164 static void
165 sigALRM()
166 {
167
168 printf("\07timeout waiting for reply\n\r");
169 timeout = 1;
170 longjmp(timeoutbuf, 1);
171 }
172
173 static char
174 gobble(match)
175 register char *match;
176 {
177 char c;
178 sig_t f;
179 int i, status = 0;
180
181 f = signal(SIGALRM, sigALRM);
182 timeout = 0;
183 #ifdef DEBUG
184 printf("\ngobble: waiting for %s\n", match);
185 #endif
186 do {
187 if (setjmp(timeoutbuf)) {
188 signal(SIGALRM, f);
189 return (0);
190 }
191 alarm(number(value(DIALTIMEOUT)));
192 read(FD, &c, 1);
193 alarm(0);
194 c &= 0177;
195 #ifdef DEBUG
196 printf("%c 0x%x ", c, c);
197 #endif
198 for (i = 0; i < strlen(match); i++)
199 if (c == match[i])
200 status = c;
201 } while (status == 0);
202 signal(SIGALRM, SIG_DFL);
203 #ifdef DEBUG
204 printf("\n");
205 #endif
206 return (status);
207 }
208
209 error_rep(c)
210 register char c;
211 {
212 printf("\n\r");
213 switch (c) {
214
215 case '0':
216 printf("OK");
217 break;
218
219 case '1':
220 printf("CONNECT");
221 break;
222
223 case '2':
224 printf("RING");
225 break;
226
227 case '3':
228 printf("NO CARRIER");
229 break;
230
231 case '4':
232 printf("ERROR in input");
233 break;
234
235 case '5':
236 printf("CONNECT 1200");
237 break;
238
239 default:
240 printf("Unknown Modem error: %c (0x%x)", c, c);
241 }
242 printf("\n\r");
243 return;
244 }
245
246 /*
247 * set modem back to normal verbose status codes.
248 */
249 goodbye()
250 {
251 int len, rlen;
252 char c;
253
254 tcflush(FD, TCIOFLUSH);
255 if (hay_sync()) {
256 sleep(1);
257 #ifndef DEBUG
258 tcflush(FD, TCIOFLUSH);
259 #endif
260 write(FD, "ATH0\r", 5); /* insurance */
261 #ifndef DEBUG
262 c = gobble("03");
263 if (c != '0' && c != '3') {
264 printf("cannot hang up modem\n\r");
265 printf("please use 'tip dialer' to make sure the line is hung up\n\r");
266 }
267 #endif
268 sleep(1);
269 ioctl(FD, FIONREAD, &len);
270 #ifdef DEBUG
271 printf("goodbye1: len=%d -- ", len);
272 rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
273 dumbuf[rlen] = '\0';
274 printf("read (%d): %s\r\n", rlen, dumbuf);
275 #endif
276 write(FD, "ATv1\r", 5);
277 sleep(1);
278 #ifdef DEBUG
279 ioctl(FD, FIONREAD, &len);
280 printf("goodbye2: len=%d -- ", len);
281 rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
282 dumbuf[rlen] = '\0';
283 printf("read (%d): %s\r\n", rlen, dumbuf);
284 #endif
285 }
286 tcflush(FD, TCIOFLUSH);
287 ioctl(FD, TIOCCDTR, 0); /* clear DTR (insurance) */
288 close(FD);
289 }
290
291 #define MAXRETRY 5
292
293 hay_sync()
294 {
295 int len, retry = 0;
296
297 while (retry++ <= MAXRETRY) {
298 write(FD, "AT\r", 3);
299 sleep(1);
300 ioctl(FD, FIONREAD, &len);
301 if (len) {
302 len = read(FD, dumbuf, min(len, DUMBUFLEN));
303 if (index(dumbuf, '0') ||
304 (index(dumbuf, 'O') && index(dumbuf, 'K')))
305 return(1);
306 #ifdef DEBUG
307 dumbuf[len] = '\0';
308 printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry);
309 #endif
310 }
311 ioctl(FD, TIOCCDTR, 0);
312 ioctl(FD, TIOCSDTR, 0);
313 }
314 printf("Cannot synchronize with hayes...\n\r");
315 return(0);
316 }
317