xref: /freebsd/usr.bin/tip/libacu/ventel.c (revision 5e3934b15a2741b2de6b217e77dc9d798d740804)
1fa92e883SRuslan Ermilov /*	$OpenBSD: ventel.c,v 1.12 2006/03/17 19:17:13 moritz Exp $	*/
20f3bdf5dSMark Murray /*	$NetBSD: ventel.c,v 1.6 1997/02/11 09:24:21 mrg Exp $	*/
30f3bdf5dSMark Murray 
4*8a16b7a1SPedro F. Giffuni /*-
5*8a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
6*8a16b7a1SPedro F. Giffuni  *
718cc36fbSJordan K. Hubbard  * Copyright (c) 1983, 1993
818cc36fbSJordan K. Hubbard  *	The Regents of the University of California.  All rights reserved.
918cc36fbSJordan K. Hubbard  *
1018cc36fbSJordan K. Hubbard  * Redistribution and use in source and binary forms, with or without
1118cc36fbSJordan K. Hubbard  * modification, are permitted provided that the following conditions
1218cc36fbSJordan K. Hubbard  * are met:
1318cc36fbSJordan K. Hubbard  * 1. Redistributions of source code must retain the above copyright
1418cc36fbSJordan K. Hubbard  *    notice, this list of conditions and the following disclaimer.
1518cc36fbSJordan K. Hubbard  * 2. Redistributions in binary form must reproduce the above copyright
1618cc36fbSJordan K. Hubbard  *    notice, this list of conditions and the following disclaimer in the
1718cc36fbSJordan K. Hubbard  *    documentation and/or other materials provided with the distribution.
18fa92e883SRuslan Ermilov  * 3. Neither the name of the University nor the names of its contributors
1918cc36fbSJordan K. Hubbard  *    may be used to endorse or promote products derived from this software
2018cc36fbSJordan K. Hubbard  *    without specific prior written permission.
2118cc36fbSJordan K. Hubbard  *
2218cc36fbSJordan K. Hubbard  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2318cc36fbSJordan K. Hubbard  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2418cc36fbSJordan K. Hubbard  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2518cc36fbSJordan K. Hubbard  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2618cc36fbSJordan K. Hubbard  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2718cc36fbSJordan K. Hubbard  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2818cc36fbSJordan K. Hubbard  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2918cc36fbSJordan K. Hubbard  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3018cc36fbSJordan K. Hubbard  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3118cc36fbSJordan K. Hubbard  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3218cc36fbSJordan K. Hubbard  * SUCH DAMAGE.
3318cc36fbSJordan K. Hubbard  */
3418cc36fbSJordan K. Hubbard 
3518cc36fbSJordan K. Hubbard /*
3618cc36fbSJordan K. Hubbard  * Routines for calling up on a Ventel Modem
3718cc36fbSJordan K. Hubbard  * The Ventel is expected to be strapped for local echo (just like uucp)
3818cc36fbSJordan K. Hubbard  */
3918cc36fbSJordan K. Hubbard #include "tip.h"
400f3bdf5dSMark Murray #include <termios.h>
410f3bdf5dSMark Murray #include <sys/ioctl.h>
4218cc36fbSJordan K. Hubbard 
4318cc36fbSJordan K. Hubbard #define	MAXRETRY	5
4418cc36fbSJordan K. Hubbard 
45fa92e883SRuslan Ermilov static	int dialtimeout = 0;
4618cc36fbSJordan K. Hubbard static	jmp_buf timeoutbuf;
4718cc36fbSJordan K. Hubbard 
48fa92e883SRuslan Ermilov static void	echo(char *);
49fa92e883SRuslan Ermilov static void	sigALRM(int);
50fa92e883SRuslan Ermilov static int	gobble(char, char *);
51fa92e883SRuslan Ermilov static int	vensync(int);
520f3bdf5dSMark Murray 
5318cc36fbSJordan K. Hubbard /*
5418cc36fbSJordan K. Hubbard  * some sleep calls have been replaced by this macro
5518cc36fbSJordan K. Hubbard  * because some ventel modems require two <cr>s in less than
5618cc36fbSJordan K. Hubbard  * a second in order to 'wake up'... yes, it is dirty...
5718cc36fbSJordan K. Hubbard  */
5818cc36fbSJordan K. Hubbard #define delay(num,denom) busyloop(CPUSPEED*num/denom)
5918cc36fbSJordan K. Hubbard #define CPUSPEED 1000000	/* VAX 780 is 1MIPS */
600f3bdf5dSMark Murray #define DELAY(n) do { long N = (n); while (--N > 0); } while (0)
610f3bdf5dSMark Murray #define busyloop(n) do { DELAY(n); } while (0)
6218cc36fbSJordan K. Hubbard 
630f3bdf5dSMark Murray int
ven_dialer(char * num,char * acu)64fa92e883SRuslan Ermilov ven_dialer(char *num, char *acu)
6518cc36fbSJordan K. Hubbard {
660f3bdf5dSMark Murray 	char *cp;
670f3bdf5dSMark Murray 	int connected = 0;
680f3bdf5dSMark Murray 	char *msg, line[80];
690f3bdf5dSMark Murray 	struct termios	cntrl;
7018cc36fbSJordan K. Hubbard 
7118cc36fbSJordan K. Hubbard 	/*
7218cc36fbSJordan K. Hubbard 	 * Get in synch with a couple of carriage returns
7318cc36fbSJordan K. Hubbard 	 */
7418cc36fbSJordan K. Hubbard 	if (!vensync(FD)) {
7518cc36fbSJordan K. Hubbard 		printf("can't synchronize with ventel\n");
760f3bdf5dSMark Murray #ifdef ACULOG
7718cc36fbSJordan K. Hubbard 		logent(value(HOST), num, "ventel", "can't synch up");
7818cc36fbSJordan K. Hubbard #endif
7918cc36fbSJordan K. Hubbard 		return (0);
8018cc36fbSJordan K. Hubbard 	}
8118cc36fbSJordan K. Hubbard 	if (boolean(value(VERBOSE)))
8218cc36fbSJordan K. Hubbard 		printf("\ndialing...");
8318cc36fbSJordan K. Hubbard 	fflush(stdout);
840f3bdf5dSMark Murray 	tcgetattr(FD, &cntrl);
850f3bdf5dSMark Murray 	cntrl.c_cflag |= HUPCL;
860f3bdf5dSMark Murray 	tcsetattr(FD, TCSANOW, &cntrl);
8718cc36fbSJordan K. Hubbard 	echo("#k$\r$\n$D$I$A$L$:$ ");
8818cc36fbSJordan K. Hubbard 	for (cp = num; *cp; cp++) {
8918cc36fbSJordan K. Hubbard 		delay(1, 10);
9018cc36fbSJordan K. Hubbard 		write(FD, cp, 1);
9118cc36fbSJordan K. Hubbard 	}
9218cc36fbSJordan K. Hubbard 	delay(1, 10);
9318cc36fbSJordan K. Hubbard 	write(FD, "\r", 1);
9418cc36fbSJordan K. Hubbard 	gobble('\n', line);
9518cc36fbSJordan K. Hubbard 	if (gobble('\n', line))
9618cc36fbSJordan K. Hubbard 		connected = gobble('!', line);
970f3bdf5dSMark Murray 	tcflush(FD, TCIOFLUSH);
980f3bdf5dSMark Murray #ifdef ACULOG
99fa92e883SRuslan Ermilov 	if (dialtimeout) {
100fa92e883SRuslan Ermilov 		(void)snprintf(line, sizeof line, "%ld second dial timeout",
10118cc36fbSJordan K. Hubbard 			number(value(DIALTIMEOUT)));
10218cc36fbSJordan K. Hubbard 		logent(value(HOST), num, "ventel", line);
10318cc36fbSJordan K. Hubbard 	}
10418cc36fbSJordan K. Hubbard #endif
105fa92e883SRuslan Ermilov 	if (dialtimeout)
10618cc36fbSJordan K. Hubbard 		ven_disconnect();	/* insurance */
107fa92e883SRuslan Ermilov 	if (connected || dialtimeout || !boolean(value(VERBOSE)))
10818cc36fbSJordan K. Hubbard 		return (connected);
10918cc36fbSJordan K. Hubbard 	/* call failed, parse response for user */
1100f3bdf5dSMark Murray 	cp = strchr(line, '\r');
11118cc36fbSJordan K. Hubbard 	if (cp)
11218cc36fbSJordan K. Hubbard 		*cp = '\0';
113fa92e883SRuslan Ermilov 	for (cp = line; (cp = strchr(cp, ' ')) != NULL; cp++)
11418cc36fbSJordan K. Hubbard 		if (cp[1] == ' ')
11518cc36fbSJordan K. Hubbard 			break;
11618cc36fbSJordan K. Hubbard 	if (cp) {
11718cc36fbSJordan K. Hubbard 		while (*cp == ' ')
11818cc36fbSJordan K. Hubbard 			cp++;
11918cc36fbSJordan K. Hubbard 		msg = cp;
12018cc36fbSJordan K. Hubbard 		while (*cp) {
12118cc36fbSJordan K. Hubbard 			if (isupper(*cp))
12218cc36fbSJordan K. Hubbard 				*cp = tolower(*cp);
12318cc36fbSJordan K. Hubbard 			cp++;
12418cc36fbSJordan K. Hubbard 		}
12518cc36fbSJordan K. Hubbard 		printf("%s...", msg);
12618cc36fbSJordan K. Hubbard 	}
12718cc36fbSJordan K. Hubbard 	return (connected);
12818cc36fbSJordan K. Hubbard }
12918cc36fbSJordan K. Hubbard 
1300f3bdf5dSMark Murray void
ven_disconnect(void)131fa92e883SRuslan Ermilov ven_disconnect(void)
13218cc36fbSJordan K. Hubbard {
13318cc36fbSJordan K. Hubbard 	close(FD);
13418cc36fbSJordan K. Hubbard }
13518cc36fbSJordan K. Hubbard 
1360f3bdf5dSMark Murray void
ven_abort(void)137fa92e883SRuslan Ermilov ven_abort(void)
13818cc36fbSJordan K. Hubbard {
13918cc36fbSJordan K. Hubbard 	write(FD, "\03", 1);
14018cc36fbSJordan K. Hubbard 	close(FD);
14118cc36fbSJordan K. Hubbard }
14218cc36fbSJordan K. Hubbard 
14318cc36fbSJordan K. Hubbard static void
echo(char * s)144fa92e883SRuslan Ermilov echo(char *s)
14518cc36fbSJordan K. Hubbard {
14618cc36fbSJordan K. Hubbard 	char c;
14718cc36fbSJordan K. Hubbard 
148fa92e883SRuslan Ermilov 	while ((c = *s++) != '\0')
149fa92e883SRuslan Ermilov 		switch (c) {
15018cc36fbSJordan K. Hubbard 		case '$':
15118cc36fbSJordan K. Hubbard 			read(FD, &c, 1);
15218cc36fbSJordan K. Hubbard 			s++;
15318cc36fbSJordan K. Hubbard 			break;
15418cc36fbSJordan K. Hubbard 
15518cc36fbSJordan K. Hubbard 		case '#':
15618cc36fbSJordan K. Hubbard 			c = *s++;
15718cc36fbSJordan K. Hubbard 			write(FD, &c, 1);
15818cc36fbSJordan K. Hubbard 			break;
15918cc36fbSJordan K. Hubbard 
16018cc36fbSJordan K. Hubbard 		default:
16118cc36fbSJordan K. Hubbard 			write(FD, &c, 1);
16218cc36fbSJordan K. Hubbard 			read(FD, &c, 1);
16318cc36fbSJordan K. Hubbard 		}
16418cc36fbSJordan K. Hubbard }
16518cc36fbSJordan K. Hubbard 
166fa92e883SRuslan Ermilov /*ARGSUSED*/
16718cc36fbSJordan K. Hubbard static void
sigALRM(int signo)168fa92e883SRuslan Ermilov sigALRM(int signo)
16918cc36fbSJordan K. Hubbard {
17018cc36fbSJordan K. Hubbard 	printf("\07timeout waiting for reply\n");
171fa92e883SRuslan Ermilov 	dialtimeout = 1;
17218cc36fbSJordan K. Hubbard 	longjmp(timeoutbuf, 1);
17318cc36fbSJordan K. Hubbard }
17418cc36fbSJordan K. Hubbard 
17518cc36fbSJordan K. Hubbard static int
gobble(char match,char response[])176fa92e883SRuslan Ermilov gobble(char match, char response[])
17718cc36fbSJordan K. Hubbard {
1780f3bdf5dSMark Murray 	char *cp = response;
17918cc36fbSJordan K. Hubbard 	sig_t f;
18018cc36fbSJordan K. Hubbard 	char c;
18118cc36fbSJordan K. Hubbard 
18218cc36fbSJordan K. Hubbard 	f = signal(SIGALRM, sigALRM);
183fa92e883SRuslan Ermilov 	dialtimeout = 0;
18418cc36fbSJordan K. Hubbard 	do {
18518cc36fbSJordan K. Hubbard 		if (setjmp(timeoutbuf)) {
18618cc36fbSJordan K. Hubbard 			signal(SIGALRM, f);
18718cc36fbSJordan K. Hubbard 			*cp = '\0';
18818cc36fbSJordan K. Hubbard 			return (0);
18918cc36fbSJordan K. Hubbard 		}
19018cc36fbSJordan K. Hubbard 		alarm(number(value(DIALTIMEOUT)));
19118cc36fbSJordan K. Hubbard 		read(FD, cp, 1);
19218cc36fbSJordan K. Hubbard 		alarm(0);
19318cc36fbSJordan K. Hubbard 		c = (*cp++ &= 0177);
19418cc36fbSJordan K. Hubbard #ifdef notdef
19518cc36fbSJordan K. Hubbard 		if (boolean(value(VERBOSE)))
19618cc36fbSJordan K. Hubbard 			putchar(c);
19718cc36fbSJordan K. Hubbard #endif
19818cc36fbSJordan K. Hubbard 	} while (c != '\n' && c != match);
19918cc36fbSJordan K. Hubbard 	signal(SIGALRM, SIG_DFL);
20018cc36fbSJordan K. Hubbard 	*cp = '\0';
20118cc36fbSJordan K. Hubbard 	return (c == match);
20218cc36fbSJordan K. Hubbard }
20318cc36fbSJordan K. Hubbard 
20418cc36fbSJordan K. Hubbard #define min(a,b)	((a)>(b)?(b):(a))
20518cc36fbSJordan K. Hubbard /*
20618cc36fbSJordan K. Hubbard  * This convoluted piece of code attempts to get
20718cc36fbSJordan K. Hubbard  * the ventel in sync.  If you don't have FIONREAD
20818cc36fbSJordan K. Hubbard  * there are gory ways to simulate this.
20918cc36fbSJordan K. Hubbard  */
21018cc36fbSJordan K. Hubbard static int
vensync(int fd)211fa92e883SRuslan Ermilov vensync(int fd)
21218cc36fbSJordan K. Hubbard {
21318cc36fbSJordan K. Hubbard 	int already = 0, nread;
21418cc36fbSJordan K. Hubbard 	char buf[60];
21518cc36fbSJordan K. Hubbard 
21618cc36fbSJordan K. Hubbard 	/*
21718cc36fbSJordan K. Hubbard 	 * Toggle DTR to force anyone off that might have left
21818cc36fbSJordan K. Hubbard 	 * the modem connected, and insure a consistent state
21918cc36fbSJordan K. Hubbard 	 * to start from.
22018cc36fbSJordan K. Hubbard 	 *
22118cc36fbSJordan K. Hubbard 	 * If you don't have the ioctl calls to diddle directly
22218cc36fbSJordan K. Hubbard 	 * with DTR, you can always try setting the baud rate to 0.
22318cc36fbSJordan K. Hubbard 	 */
22418cc36fbSJordan K. Hubbard 	ioctl(FD, TIOCCDTR, 0);
22518cc36fbSJordan K. Hubbard 	sleep(1);
22618cc36fbSJordan K. Hubbard 	ioctl(FD, TIOCSDTR, 0);
22718cc36fbSJordan K. Hubbard 	while (already < MAXRETRY) {
22818cc36fbSJordan K. Hubbard 		/*
22918cc36fbSJordan K. Hubbard 		 * After reseting the modem, send it two \r's to
23018cc36fbSJordan K. Hubbard 		 * autobaud on. Make sure to delay between them
23118cc36fbSJordan K. Hubbard 		 * so the modem can frame the incoming characters.
23218cc36fbSJordan K. Hubbard 		 */
23318cc36fbSJordan K. Hubbard 		write(fd, "\r", 1);
23418cc36fbSJordan K. Hubbard 		delay(1,10);
23518cc36fbSJordan K. Hubbard 		write(fd, "\r", 1);
23618cc36fbSJordan K. Hubbard 		sleep(2);
23718cc36fbSJordan K. Hubbard 		if (ioctl(fd, FIONREAD, (caddr_t)&nread) < 0) {
2380f3bdf5dSMark Murray 			perror("tip: ioctl");
23918cc36fbSJordan K. Hubbard 			continue;
24018cc36fbSJordan K. Hubbard 		}
24118cc36fbSJordan K. Hubbard 		while (nread > 0) {
24218cc36fbSJordan K. Hubbard 			read(fd, buf, min(nread, 60));
24318cc36fbSJordan K. Hubbard 			if ((buf[nread - 1] & 0177) == '$')
24418cc36fbSJordan K. Hubbard 				return (1);
24518cc36fbSJordan K. Hubbard 			nread -= min(nread, 60);
24618cc36fbSJordan K. Hubbard 		}
24718cc36fbSJordan K. Hubbard 		sleep(1);
24818cc36fbSJordan K. Hubbard 		already++;
24918cc36fbSJordan K. Hubbard 	}
25018cc36fbSJordan K. Hubbard 	return (0);
25118cc36fbSJordan K. Hubbard }
252