Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.bin / tip / libacu / t3000.c
1 /*
2  * Copyright (c) 1992, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * @(#)t3000.c  8.1 (Berkeley) 6/6/93
34  */
35
36 /*
37  * Routines for calling up on a Telebit T3000 modem.
38  * Derived from Courier driver.
39  */
40 #include "tipconf.h"
41 #include "tip.h"
42 #include "acucommon.h"
43 #include <stdio.h>
44
45 #define MAXRETRY        5
46
47 static  void sigALRM();
48 static  int timeout = 0;
49 static  int connected = 0;
50 static  jmp_buf timeoutbuf, intbuf;
51 static  int t3000_sync();
52
53 t3000_dialer(num, acu)
54         register char *num;
55         char *acu;
56 {
57         register char *cp;
58 #if ACULOG
59         char line[80];
60 #endif
61         static int t3000_connect(), t3000_swallow();
62
63         if (boolean(value(VERBOSE)))
64                 printf("Using \"%s\"\n", acu);
65
66         acu_hupcl ();
67         /*
68          * Get in synch.
69          */
70         if (!t3000_sync()) {
71 badsynch:
72                 printf("can't synchronize with t3000\n");
73 #if ACULOG
74                 logent(value(HOST), num, "t3000", "can't synch up");
75 #endif
76                 return (0);
77         }
78         t3000_write(FD, "AT E0\r", 6);  /* turn off echoing */
79         sleep(1);
80 #ifdef DEBUG
81         if (boolean(value(VERBOSE)))
82                 t3000_verbose_read();
83 #endif
84         ioctl(FD, TIOCFLUSH, 0);        /* flush any clutter */
85         t3000_write(FD, "AT E0 H0 Q0 X4 V1\r", 18);
86         if (!t3000_swallow("\r\nOK\r\n"))
87                 goto badsynch;
88         fflush(stdout);
89         t3000_write(FD, "AT D", 4);
90         for (cp = num; *cp; cp++)
91                 if (*cp == '=')
92                         *cp = ',';
93         t3000_write(FD, num, strlen(num));
94         t3000_write(FD, "\r", 1);
95         connected = t3000_connect();
96 #if ACULOG
97         if (timeout) {
98                 sprintf(line, "%d second dial timeout",
99                         number(value(DIALTIMEOUT)));
100                 logent(value(HOST), num, "t3000", line);
101         }
102 #endif
103         if (timeout)
104                 t3000_disconnect();
105         return (connected);
106 }
107
108 t3000_disconnect()
109 {
110          /* first hang up the modem*/
111         ioctl(FD, TIOCCDTR, 0);
112         sleep(1);
113         ioctl(FD, TIOCSDTR, 0);
114         t3000_sync();                           /* reset */
115         close(FD);
116 }
117
118 t3000_abort()
119 {
120         t3000_write(FD, "\r", 1);       /* send anything to abort the call */
121         t3000_disconnect();
122 }
123
124 static void
125 sigALRM()
126 {
127         printf("\07timeout waiting for reply\n");
128         timeout = 1;
129         longjmp(timeoutbuf, 1);
130 }
131
132 static int
133 t3000_swallow(match)
134   register char *match;
135   {
136         sig_t f;
137         char c;
138
139         f = signal(SIGALRM, sigALRM);
140         timeout = 0;
141         do {
142                 if (*match =='\0') {
143                         signal(SIGALRM, f);
144                         return (1);
145                 }
146                 if (setjmp(timeoutbuf)) {
147                         signal(SIGALRM, f);
148                         return (0);
149                 }
150                 alarm(number(value(DIALTIMEOUT)));
151                 read(FD, &c, 1);
152                 alarm(0);
153                 c &= 0177;
154 #ifdef DEBUG
155                 if (boolean(value(VERBOSE)))
156                         putchar(c);
157 #endif
158         } while (c == *match++);
159 #ifdef DEBUG
160         if (boolean(value(VERBOSE)))
161                 fflush(stdout);
162 #endif
163         signal(SIGALRM, SIG_DFL);
164         return (0);
165 }
166
167 #ifndef B19200          /* XXX */
168 #define B19200  EXTA
169 #define B38400  EXTB
170 #endif
171
172 struct tbaud_msg {
173         char *msg;
174         int baud;
175         int baud2;
176 } tbaud_msg[] = {
177         "",             B300,   0,
178         " 1200",        B1200,  0,
179         " 2400",        B2400,  0,
180         " 4800",        B4800,  0,
181         " 9600",        B9600,  0,
182         " 14400",       B19200, B9600,
183         " 19200",       B19200, B9600,
184         " 38400",       B38400, B9600,
185         " 57600",       B38400, B9600,
186         " 7512",        B9600,  0,
187         " 1275",        B2400,  0,
188         " 7200",        B9600,  0,
189         " 12000",       B19200, B9600,
190         0,              0,      0,
191 };
192
193 static int
194 t3000_connect()
195 {
196         char c;
197         int nc, nl, n;
198         char dialer_buf[64];
199         struct tbaud_msg *bm;
200         sig_t f;
201
202         if (t3000_swallow("\r\n") == 0)
203                 return (0);
204         f = signal(SIGALRM, sigALRM);
205 again:
206         nc = 0; nl = sizeof(dialer_buf)-1;
207         bzero(dialer_buf, sizeof(dialer_buf));
208         timeout = 0;
209         for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
210                 if (setjmp(timeoutbuf))
211                         break;
212                 alarm(number(value(DIALTIMEOUT)));
213                 n = read(FD, &c, 1);
214                 alarm(0);
215                 if (n <= 0)
216                         break;
217                 c &= 0x7f;
218                 if (c == '\r') {
219                         if (t3000_swallow("\n") == 0)
220                                 break;
221                         if (!dialer_buf[0])
222                                 goto again;
223                         if (strcmp(dialer_buf, "RINGING") == 0 &&
224                             boolean(value(VERBOSE))) {
225 #ifdef DEBUG
226                                 printf("%s\r\n", dialer_buf);
227 #endif
228                                 goto again;
229                         }
230                         if (strncmp(dialer_buf, "CONNECT",
231                                     sizeof("CONNECT")-1) != 0)
232                                 break;
233                         for (bm = tbaud_msg ; bm->msg ; bm++)
234                                 if (strcmp(bm->msg,
235                                     dialer_buf+sizeof("CONNECT")-1) == 0) {
236                                         if (!(acu_setspeed (bm->baud) || (bm->baud2 && acu_setspeed (bm->baud2))))
237                                                 goto error;
238                                         signal(SIGALRM, f);
239 #ifdef DEBUG
240                                         if (boolean(value(VERBOSE)))
241                                                 printf("%s\r\n", dialer_buf);
242 #endif
243                                         return (1);
244                                 }
245                         break;
246                 }
247                 dialer_buf[nc] = c;
248 #ifdef notdef
249                 if (boolean(value(VERBOSE)))
250                         putchar(c);
251 #endif
252         }
253 error1:
254         printf("%s\r\n", dialer_buf);
255 error:
256         signal(SIGALRM, f);
257         return (0);
258 }
259
260 /*
261  * This convoluted piece of code attempts to get
262  * the t3000 in sync.
263  */
264 static int
265 t3000_sync()
266 {
267         int already = 0;
268         int len;
269         char buf[40];
270
271         while (already++ < MAXRETRY) {
272                 ioctl(FD, TIOCFLUSH, 0);        /* flush any clutter */
273                 t3000_write(FD, "\rAT Z\r", 6); /* reset modem */
274                 bzero(buf, sizeof(buf));
275                 sleep(2);
276                 ioctl(FD, FIONREAD, &len);
277 #if 1
278 if (len == 0) len = 1;
279 #endif
280                 if (len) {
281                         len = read(FD, buf, sizeof(buf));
282 #ifdef DEBUG
283                         buf[len] = '\0';
284                         printf("t3000_sync: (\"%s\")\n\r", buf);
285 #endif
286                         if (index(buf, '0') ||
287                            (index(buf, 'O') && index(buf, 'K')))
288                                 return(1);
289                 }
290                 /*
291                  * If not strapped for DTR control,
292                  * try to get command mode.
293                  */
294                 sleep(1);
295                 t3000_write(FD, "+++", 3);
296                 sleep(1);
297                 /*
298                  * Toggle DTR to force anyone off that might have left
299                  * the modem connected.
300                  */
301                 ioctl(FD, TIOCCDTR, 0);
302                 sleep(1);
303                 ioctl(FD, TIOCSDTR, 0);
304         }
305         t3000_write(FD, "\rAT Z\r", 6);
306         return (0);
307 }
308
309 t3000_write(fd, cp, n)
310 int fd;
311 char *cp;
312 int n;
313 {
314 #ifdef notdef
315         if (boolean(value(VERBOSE)))
316                 write(1, cp, n);
317 #endif
318         acu_flush ();
319         t3000_nap();
320         for ( ; n-- ; cp++) {
321                 write(fd, cp, 1);
322                 acu_flush ();
323                 t3000_nap();
324         }
325 }
326
327 #ifdef DEBUG
328 t3000_verbose_read()
329 {
330         int n = 0;
331         char buf[BUFSIZ];
332
333         if (ioctl(FD, FIONREAD, &n) < 0)
334                 return;
335         if (n <= 0)
336                 return;
337         if (read(FD, buf, n) != n)
338                 return;
339         write(1, buf, n);
340 }
341 #endif
342
343 t3000_nap()
344 {
345         acu_nap (50);
346 }
347
348 /* end of t3000.c */