1 /* $NetBSD: courier.c,v 1.15 2006/04/03 02:25:27 perry Exp $ */
4 * Copyright (c) 1986, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)courier.c 8.1 (Berkeley) 6/6/93";
37 __RCSID("$NetBSD: courier.c,v 1.15 2006/04/03 02:25:27 perry Exp $");
41 * Routines for calling up on a Courier modem.
42 * Derived from Hayes driver.
48 static int timeout
= 0;
49 static int connected
= 0;
50 static jmp_buf timeoutbuf
;
52 static int cour_connect(void);
53 static void cour_nap(void);
54 static void cour_napx(int);
55 static int cour_swallow(const char *);
56 static int coursync(void);
58 static void cour_verbose_read(void);
60 static void cour_write(int, const char *, int);
61 static void sigALRM(int);
64 cour_dialer(char *num
, char *acu
)
69 if (boolean(value(VERBOSE
)))
70 (void)printf("Using \"%s\"\n", acu
);
72 (void)tcgetattr(FD
, &cntrl
);
73 cntrl
.c_cflag
|= HUPCL
;
74 (void)tcsetattr(FD
, TCSAFLUSH
, &cntrl
);
80 (void)printf("can't synchronize with courier\n");
83 cour_write(FD
, "AT E0\r", 6); /* turn off echoing */
86 if (boolean(value(VERBOSE
)))
89 (void)tcflush(FD
, TCIOFLUSH
);
90 cour_write(FD
, "AT C1 E0 H0 Q0 X6 V1\r", 21);
91 if (!cour_swallow("\r\nOK\r\n"))
94 cour_write(FD
, "AT D", 4);
95 for (cp
= num
; *cp
; cp
++)
98 cour_write(FD
, num
, (int)strlen(num
));
99 cour_write(FD
, "\r", 1);
100 connected
= cour_connect();
107 cour_disconnect(void)
110 /* first hang up the modem*/
111 (void)ioctl(FD
, TIOCCDTR
, 0);
113 (void)ioctl(FD
, TIOCSDTR
, 0);
114 (void)coursync(); /* reset */
122 cour_write(FD
, "\r", 1); /* send anything to abort the call */
128 sigALRM(int dummy __unused
)
131 (void)printf("\07timeout waiting for reply\n");
133 longjmp(timeoutbuf
, 1);
137 cour_swallow(const char * volatile match
)
142 f
= signal(SIGALRM
, sigALRM
);
146 (void)signal(SIGALRM
, f
);
149 if (setjmp(timeoutbuf
)) {
150 (void)signal(SIGALRM
, f
);
153 (void)alarm((unsigned)number(value(DIALTIMEOUT
)));
154 (void)read(FD
, &c
, 1);
158 if (boolean(value(VERBOSE
)))
161 } while (c
== *match
++);
163 if (boolean(value(VERBOSE
)))
164 (void)fflush(stdout
);
166 (void)signal(SIGALRM
, SIG_DFL
);
178 { " 9600/ARQ", B9600
},
193 if (cour_swallow("\r\n") == 0)
195 f
= signal(SIGALRM
, sigALRM
);
197 (void)memset(dialer_buf
, 0, sizeof(dialer_buf
));
199 for (nc
= 0, nl
= sizeof(dialer_buf
) - 1 ; nl
> 0 ; nc
++, nl
--) {
200 if (setjmp(timeoutbuf
))
202 (void)alarm((unsigned)number(value(DIALTIMEOUT
)));
209 if (cour_swallow("\n") == 0)
213 if (strcmp(dialer_buf
, "RINGING") == 0 &&
214 boolean(value(VERBOSE
))) {
216 (void)printf("%s\r\n", dialer_buf
);
220 if (strncmp(dialer_buf
, "CONNECT",
221 sizeof("CONNECT")-1) != 0)
223 for (bm
= baud_msg
; bm
->msg
; bm
++)
225 dialer_buf
+sizeof("CONNECT")-1) == 0) {
226 struct termios cntrl
;
228 (void)tcgetattr(FD
, &cntrl
);
229 (void)cfsetospeed(&cntrl
, bm
->baud
);
230 (void)cfsetispeed(&cntrl
, bm
->baud
);
231 (void)tcsetattr(FD
, TCSAFLUSH
, &cntrl
);
232 (void)signal(SIGALRM
, f
);
234 if (boolean(value(VERBOSE
)))
235 (void)printf("%s\r\n", dialer_buf
);
243 if (boolean(value(VERBOSE
)))
247 (void)printf("%s\r\n", dialer_buf
);
248 (void)signal(SIGALRM
, f
);
253 * This convoluted piece of code attempts to get
254 * the courier in sync.
263 while (already
++ < MAXRETRY
) {
264 (void)tcflush(FD
, TCIOFLUSH
);
265 cour_write(FD
, "\rAT Z\r", 6); /* reset modem */
266 (void)memset(buf
, 0, sizeof(buf
));
268 (void)ioctl(FD
, FIONREAD
, &len
);
270 len
= read(FD
, buf
, sizeof(buf
));
273 (void)printf("coursync: (\"%s\")\n\r", buf
);
275 if (strchr(buf
, '0') ||
276 (strchr(buf
, 'O') && strchr(buf
, 'K')))
280 * If not strapped for DTR control,
281 * try to get command mode.
284 cour_write(FD
, "+++", 3);
287 * Toggle DTR to force anyone off that might have left
288 * the modem connected.
290 (void)ioctl(FD
, TIOCCDTR
, 0);
292 (void)ioctl(FD
, TIOCSDTR
, 0);
294 cour_write(FD
, "\rAT Z\r", 6);
299 cour_write(int fd
, const char *cp
, int n
)
303 if (boolean(value(VERBOSE
)))
304 (void)write(1, cp
, n
);
308 for ( ; n
-- ; cp
++) {
309 (void)write(fd
, cp
, 1);
317 cour_verbose_read(void)
322 if (ioctl(FD
, FIONREAD
, &n
) < 0)
326 if (read(FD
, buf
, n
) != n
)
328 (void)write(1, buf
, n
);
332 #define setsa(sa, a) \
333 sa.sa_handler = a; (void)sigemptyset(&sa.sa_mask); sa.sa_flags = 0
335 static int napms
= 50; /* Give the courier 50 milliseconds between characters */
343 struct itimerval itv
, oitv
;
344 struct itimerval
*itp
= &itv
;
345 struct sigaction sa
, osa
;
348 timerclear(&itp
->it_interval
);
349 timerclear(&itp
->it_value
);
350 if (setitimer(ITIMER_REAL
, itp
, &oitv
) < 0)
353 (void)sigemptyset(&sm
);
354 (void)sigaddset(&sm
, SIGALRM
);
355 (void)sigprocmask(SIG_BLOCK
, &sm
, &osm
);
357 itp
->it_value
.tv_sec
= napms
/1000;
358 itp
->it_value
.tv_usec
= ((napms
%1000)*1000);
360 setsa(sa
, cour_napx
);
361 (void)sigaction(SIGALRM
, &sa
, &osa
);
363 (void)setitimer(ITIMER_REAL
, itp
, NULL
);
366 (void)sigdelset(&sm
, SIGALRM
);
368 for (ringring
= 0; !ringring
; )
369 (void)sigsuspend(&sm
);
371 (void)sigaction(SIGALRM
, &osa
, NULL
);
372 (void)setitimer(ITIMER_REAL
, &oitv
, NULL
);
373 (void)sigprocmask(SIG_SETMASK
, &osm
, NULL
);
378 cour_napx(int dummy __unused
)