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