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