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