xref: /freebsd/usr.bin/tip/libacu/ventel.c (revision 0f3bdf5df978c1d74d4b5e0429ced9613debcc3c)
10f3bdf5dSMark Murray /*	$OpenBSD: ventel.c,v 1.7 2001/11/19 19:02:16 mpech Exp $	*/
20f3bdf5dSMark Murray /*	$NetBSD: ventel.c,v 1.6 1997/02/11 09:24:21 mrg Exp $	*/
30f3bdf5dSMark Murray 
40f3bdf5dSMark Murray /*
50f3bdf5dSMark Murray  * Copyright (c) 1983, 1993
60f3bdf5dSMark Murray  *	The Regents of the University of California.  All rights reserved.
70f3bdf5dSMark Murray  *
80f3bdf5dSMark Murray  * Redistribution and use in source and binary forms, with or without
90f3bdf5dSMark Murray  * modification, are permitted provided that the following conditions
100f3bdf5dSMark Murray  * are met:
110f3bdf5dSMark Murray  * 1. Redistributions of source code must retain the above copyright
120f3bdf5dSMark Murray  *    notice, this list of conditions and the following disclaimer.
130f3bdf5dSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
140f3bdf5dSMark Murray  *    notice, this list of conditions and the following disclaimer in the
150f3bdf5dSMark Murray  *    documentation and/or other materials provided with the distribution.
160f3bdf5dSMark Murray  * 3. All advertising materials mentioning features or use of this software
170f3bdf5dSMark Murray  *    must display the following acknowledgement:
180f3bdf5dSMark Murray  *	This product includes software developed by the University of
190f3bdf5dSMark Murray  *	California, Berkeley and its contributors.
200f3bdf5dSMark Murray  * 4. Neither the name of the University nor the names of its contributors
210f3bdf5dSMark Murray  *    may be used to endorse or promote products derived from this software
220f3bdf5dSMark Murray  *    without specific prior written permission.
230f3bdf5dSMark Murray  *
240f3bdf5dSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
250f3bdf5dSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
260f3bdf5dSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
270f3bdf5dSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
280f3bdf5dSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
290f3bdf5dSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
300f3bdf5dSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
310f3bdf5dSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
320f3bdf5dSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
330f3bdf5dSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
340f3bdf5dSMark Murray  * SUCH DAMAGE.
350f3bdf5dSMark Murray  */
360f3bdf5dSMark Murray 
370f3bdf5dSMark Murray #ifndef lint
380f3bdf5dSMark Murray #if 0
390f3bdf5dSMark Murray static char sccsid[] = "@(#)ventel.c	8.1 (Berkeley) 6/6/93";
400f3bdf5dSMark Murray #endif
410f3bdf5dSMark Murray static char rcsid[] = "$OpenBSD: ventel.c,v 1.7 2001/11/19 19:02:16 mpech Exp $";
420f3bdf5dSMark Murray #endif /* not lint */
430f3bdf5dSMark Murray 
440f3bdf5dSMark Murray /*
450f3bdf5dSMark Murray  * Routines for calling up on a Ventel Modem
460f3bdf5dSMark Murray  * The Ventel is expected to be strapped for local echo (just like uucp)
470f3bdf5dSMark Murray  */
480f3bdf5dSMark Murray #include "tip.h"
490f3bdf5dSMark Murray #include <termios.h>
500f3bdf5dSMark Murray #include <sys/ioctl.h>
510f3bdf5dSMark Murray 
520f3bdf5dSMark Murray #define	MAXRETRY	5
530f3bdf5dSMark Murray 
540f3bdf5dSMark Murray static	void sigALRM();
550f3bdf5dSMark Murray static	int timeout = 0;
560f3bdf5dSMark Murray static	jmp_buf timeoutbuf;
570f3bdf5dSMark Murray 
580f3bdf5dSMark Murray static	int gobble(), vensync();
590f3bdf5dSMark Murray static	void echo();
600f3bdf5dSMark Murray 
610f3bdf5dSMark Murray /*
620f3bdf5dSMark Murray  * some sleep calls have been replaced by this macro
630f3bdf5dSMark Murray  * because some ventel modems require two <cr>s in less than
640f3bdf5dSMark Murray  * a second in order to 'wake up'... yes, it is dirty...
650f3bdf5dSMark Murray  */
660f3bdf5dSMark Murray #define delay(num,denom) busyloop(CPUSPEED*num/denom)
670f3bdf5dSMark Murray #define CPUSPEED 1000000	/* VAX 780 is 1MIPS */
680f3bdf5dSMark Murray #define DELAY(n) do { long N = (n); while (--N > 0); } while (0)
690f3bdf5dSMark Murray #define busyloop(n) do { DELAY(n); } while (0)
700f3bdf5dSMark Murray 
710f3bdf5dSMark Murray int
720f3bdf5dSMark Murray ven_dialer(num, acu)
730f3bdf5dSMark Murray 	char *num;
740f3bdf5dSMark Murray 	char *acu;
750f3bdf5dSMark Murray {
760f3bdf5dSMark Murray 	char *cp;
770f3bdf5dSMark Murray 	int connected = 0;
780f3bdf5dSMark Murray 	char *msg, line[80];
790f3bdf5dSMark Murray 	struct termios	cntrl;
800f3bdf5dSMark Murray 
810f3bdf5dSMark Murray 	/*
820f3bdf5dSMark Murray 	 * Get in synch with a couple of carriage returns
830f3bdf5dSMark Murray 	 */
840f3bdf5dSMark Murray 	if (!vensync(FD)) {
850f3bdf5dSMark Murray 		printf("can't synchronize with ventel\n");
860f3bdf5dSMark Murray #ifdef ACULOG
870f3bdf5dSMark Murray 		logent(value(HOST), num, "ventel", "can't synch up");
880f3bdf5dSMark Murray #endif
890f3bdf5dSMark Murray 		return (0);
900f3bdf5dSMark Murray 	}
910f3bdf5dSMark Murray 	if (boolean(value(VERBOSE)))
920f3bdf5dSMark Murray 		printf("\ndialing...");
930f3bdf5dSMark Murray 	fflush(stdout);
940f3bdf5dSMark Murray 	tcgetattr(FD, &cntrl);
950f3bdf5dSMark Murray 	cntrl.c_cflag |= HUPCL;
960f3bdf5dSMark Murray 	tcsetattr(FD, TCSANOW, &cntrl);
970f3bdf5dSMark Murray 	echo("#k$\r$\n$D$I$A$L$:$ ");
980f3bdf5dSMark Murray 	for (cp = num; *cp; cp++) {
990f3bdf5dSMark Murray 		delay(1, 10);
1000f3bdf5dSMark Murray 		write(FD, cp, 1);
1010f3bdf5dSMark Murray 	}
1020f3bdf5dSMark Murray 	delay(1, 10);
1030f3bdf5dSMark Murray 	write(FD, "\r", 1);
1040f3bdf5dSMark Murray 	gobble('\n', line);
1050f3bdf5dSMark Murray 	if (gobble('\n', line))
1060f3bdf5dSMark Murray 		connected = gobble('!', line);
1070f3bdf5dSMark Murray 	tcflush(FD, TCIOFLUSH);
1080f3bdf5dSMark Murray #ifdef ACULOG
1090f3bdf5dSMark Murray 	if (timeout) {
1100f3bdf5dSMark Murray 		(void)sprintf(line, "%ld second dial timeout",
1110f3bdf5dSMark Murray 			number(value(DIALTIMEOUT)));
1120f3bdf5dSMark Murray 		logent(value(HOST), num, "ventel", line);
1130f3bdf5dSMark Murray 	}
1140f3bdf5dSMark Murray #endif
1150f3bdf5dSMark Murray 	if (timeout)
1160f3bdf5dSMark Murray 		ven_disconnect();	/* insurance */
1170f3bdf5dSMark Murray 	if (connected || timeout || !boolean(value(VERBOSE)))
1180f3bdf5dSMark Murray 		return (connected);
1190f3bdf5dSMark Murray 	/* call failed, parse response for user */
1200f3bdf5dSMark Murray 	cp = strchr(line, '\r');
1210f3bdf5dSMark Murray 	if (cp)
1220f3bdf5dSMark Murray 		*cp = '\0';
1230f3bdf5dSMark Murray 	for (cp = line; cp = strchr(cp, ' '); cp++)
1240f3bdf5dSMark Murray 		if (cp[1] == ' ')
1250f3bdf5dSMark Murray 			break;
1260f3bdf5dSMark Murray 	if (cp) {
1270f3bdf5dSMark Murray 		while (*cp == ' ')
1280f3bdf5dSMark Murray 			cp++;
1290f3bdf5dSMark Murray 		msg = cp;
1300f3bdf5dSMark Murray 		while (*cp) {
1310f3bdf5dSMark Murray 			if (isupper(*cp))
1320f3bdf5dSMark Murray 				*cp = tolower(*cp);
1330f3bdf5dSMark Murray 			cp++;
1340f3bdf5dSMark Murray 		}
1350f3bdf5dSMark Murray 		printf("%s...", msg);
1360f3bdf5dSMark Murray 	}
1370f3bdf5dSMark Murray 	return (connected);
1380f3bdf5dSMark Murray }
1390f3bdf5dSMark Murray 
1400f3bdf5dSMark Murray void
1410f3bdf5dSMark Murray ven_disconnect()
1420f3bdf5dSMark Murray {
1430f3bdf5dSMark Murray 
1440f3bdf5dSMark Murray 	close(FD);
1450f3bdf5dSMark Murray }
1460f3bdf5dSMark Murray 
1470f3bdf5dSMark Murray void
1480f3bdf5dSMark Murray ven_abort()
1490f3bdf5dSMark Murray {
1500f3bdf5dSMark Murray 
1510f3bdf5dSMark Murray 	write(FD, "\03", 1);
1520f3bdf5dSMark Murray 	close(FD);
1530f3bdf5dSMark Murray }
1540f3bdf5dSMark Murray 
1550f3bdf5dSMark Murray static void
1560f3bdf5dSMark Murray echo(s)
1570f3bdf5dSMark Murray 	char *s;
1580f3bdf5dSMark Murray {
1590f3bdf5dSMark Murray 	char c;
1600f3bdf5dSMark Murray 
1610f3bdf5dSMark Murray 	while (c = *s++) switch (c) {
1620f3bdf5dSMark Murray 
1630f3bdf5dSMark Murray 	case '$':
1640f3bdf5dSMark Murray 		read(FD, &c, 1);
1650f3bdf5dSMark Murray 		s++;
1660f3bdf5dSMark Murray 		break;
1670f3bdf5dSMark Murray 
1680f3bdf5dSMark Murray 	case '#':
1690f3bdf5dSMark Murray 		c = *s++;
1700f3bdf5dSMark Murray 		write(FD, &c, 1);
1710f3bdf5dSMark Murray 		break;
1720f3bdf5dSMark Murray 
1730f3bdf5dSMark Murray 	default:
1740f3bdf5dSMark Murray 		write(FD, &c, 1);
1750f3bdf5dSMark Murray 		read(FD, &c, 1);
1760f3bdf5dSMark Murray 	}
1770f3bdf5dSMark Murray }
1780f3bdf5dSMark Murray 
1790f3bdf5dSMark Murray static void
1800f3bdf5dSMark Murray sigALRM()
1810f3bdf5dSMark Murray {
1820f3bdf5dSMark Murray 	printf("\07timeout waiting for reply\n");
1830f3bdf5dSMark Murray 	timeout = 1;
1840f3bdf5dSMark Murray 	longjmp(timeoutbuf, 1);
1850f3bdf5dSMark Murray }
1860f3bdf5dSMark Murray 
1870f3bdf5dSMark Murray static int
1880f3bdf5dSMark Murray gobble(match, response)
1890f3bdf5dSMark Murray 	char match;
1900f3bdf5dSMark Murray 	char response[];
1910f3bdf5dSMark Murray {
1920f3bdf5dSMark Murray 	char *cp = response;
1930f3bdf5dSMark Murray 	sig_t f;
1940f3bdf5dSMark Murray 	char c;
1950f3bdf5dSMark Murray 
1960f3bdf5dSMark Murray 	f = signal(SIGALRM, sigALRM);
1970f3bdf5dSMark Murray 	timeout = 0;
1980f3bdf5dSMark Murray 	do {
1990f3bdf5dSMark Murray 		if (setjmp(timeoutbuf)) {
2000f3bdf5dSMark Murray 			signal(SIGALRM, f);
2010f3bdf5dSMark Murray 			*cp = '\0';
2020f3bdf5dSMark Murray 			return (0);
2030f3bdf5dSMark Murray 		}
2040f3bdf5dSMark Murray 		alarm(number(value(DIALTIMEOUT)));
2050f3bdf5dSMark Murray 		read(FD, cp, 1);
2060f3bdf5dSMark Murray 		alarm(0);
2070f3bdf5dSMark Murray 		c = (*cp++ &= 0177);
2080f3bdf5dSMark Murray #ifdef notdef
2090f3bdf5dSMark Murray 		if (boolean(value(VERBOSE)))
2100f3bdf5dSMark Murray 			putchar(c);
2110f3bdf5dSMark Murray #endif
2120f3bdf5dSMark Murray 	} while (c != '\n' && c != match);
2130f3bdf5dSMark Murray 	signal(SIGALRM, SIG_DFL);
2140f3bdf5dSMark Murray 	*cp = '\0';
2150f3bdf5dSMark Murray 	return (c == match);
2160f3bdf5dSMark Murray }
2170f3bdf5dSMark Murray 
2180f3bdf5dSMark Murray #define min(a,b)	((a)>(b)?(b):(a))
2190f3bdf5dSMark Murray /*
2200f3bdf5dSMark Murray  * This convoluted piece of code attempts to get
2210f3bdf5dSMark Murray  * the ventel in sync.  If you don't have FIONREAD
2220f3bdf5dSMark Murray  * there are gory ways to simulate this.
2230f3bdf5dSMark Murray  */
2240f3bdf5dSMark Murray static int
2250f3bdf5dSMark Murray vensync(fd)
2260f3bdf5dSMark Murray {
2270f3bdf5dSMark Murray 	int already = 0, nread;
2280f3bdf5dSMark Murray 	char buf[60];
2290f3bdf5dSMark Murray 
2300f3bdf5dSMark Murray 	/*
2310f3bdf5dSMark Murray 	 * Toggle DTR to force anyone off that might have left
2320f3bdf5dSMark Murray 	 * the modem connected, and insure a consistent state
2330f3bdf5dSMark Murray 	 * to start from.
2340f3bdf5dSMark Murray 	 *
2350f3bdf5dSMark Murray 	 * If you don't have the ioctl calls to diddle directly
2360f3bdf5dSMark Murray 	 * with DTR, you can always try setting the baud rate to 0.
2370f3bdf5dSMark Murray 	 */
2380f3bdf5dSMark Murray 	ioctl(FD, TIOCCDTR, 0);
2390f3bdf5dSMark Murray 	sleep(1);
2400f3bdf5dSMark Murray 	ioctl(FD, TIOCSDTR, 0);
2410f3bdf5dSMark Murray 	while (already < MAXRETRY) {
2420f3bdf5dSMark Murray 		/*
2430f3bdf5dSMark Murray 		 * After reseting the modem, send it two \r's to
2440f3bdf5dSMark Murray 		 * autobaud on. Make sure to delay between them
2450f3bdf5dSMark Murray 		 * so the modem can frame the incoming characters.
2460f3bdf5dSMark Murray 		 */
2470f3bdf5dSMark Murray 		write(fd, "\r", 1);
2480f3bdf5dSMark Murray 		delay(1,10);
2490f3bdf5dSMark Murray 		write(fd, "\r", 1);
2500f3bdf5dSMark Murray 		sleep(2);
2510f3bdf5dSMark Murray 		if (ioctl(fd, FIONREAD, (caddr_t)&nread) < 0) {
2520f3bdf5dSMark Murray 			perror("tip: ioctl");
2530f3bdf5dSMark Murray 			continue;
2540f3bdf5dSMark Murray 		}
2550f3bdf5dSMark Murray 		while (nread > 0) {
2560f3bdf5dSMark Murray 			read(fd, buf, min(nread, 60));
2570f3bdf5dSMark Murray 			if ((buf[nread - 1] & 0177) == '$')
2580f3bdf5dSMark Murray 				return (1);
2590f3bdf5dSMark Murray 			nread -= min(nread, 60);
2600f3bdf5dSMark Murray 		}
2610f3bdf5dSMark Murray 		sleep(1);
2620f3bdf5dSMark Murray 		already++;
2630f3bdf5dSMark Murray 	}
2640f3bdf5dSMark Murray 	return (0);
2650f3bdf5dSMark Murray }
2660f3bdf5dSMark Murray 
267