1 /* 2 * Copyright (c) 1983, 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 34 #ifndef lint 35 static char sccsid[] = "@(#)hayes.c 8.1 (Berkeley) 6/6/93"; 36 #endif /* not lint */ 37 38 /* 39 * Routines for calling up on a Hayes Modem 40 * (based on the old VenTel driver). 41 * The modem is expected to be strapped for "echo". 42 * Also, the switches enabling the DTR and CD lines 43 * must be set correctly. 44 * NOTICE: 45 * The easy way to hang up a modem is always simply to 46 * clear the DTR signal. However, if the +++ sequence 47 * (which switches the modem back to local mode) is sent 48 * before modem is hung up, removal of the DTR signal 49 * has no effect (except that it prevents the modem from 50 * recognizing commands). 51 * (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984) 52 */ 53 /* 54 * TODO: 55 * It is probably not a good idea to switch the modem 56 * state between 'verbose' and terse (status messages). 57 * This should be kicked out and we should use verbose 58 * mode only. This would make it consistent with normal 59 * interactive use thru the command 'tip dialer'. 60 */ 61 #include "tipconf.h" 62 #include "tip.h" 63 64 #define min(a,b) ((a < b) ? a : b) 65 66 static void sigALRM(); 67 static int timeout = 0; 68 static jmp_buf timeoutbuf; 69 static char gobble(); 70 #define DUMBUFLEN 40 71 static char dumbuf[DUMBUFLEN]; 72 73 #define DIALING 1 74 #define IDLE 2 75 #define CONNECTED 3 76 #define FAILED 4 77 static int state = IDLE; 78 79 hay_dialer(num, acu) 80 register char *num; 81 char *acu; 82 { 83 register char *cp; 84 register int connected = 0; 85 char dummy; 86 #if ACULOG 87 char line[80]; 88 #endif 89 if (hay_sync() == 0) /* make sure we can talk to the modem */ 90 return(0); 91 if (boolean(value(VERBOSE))) 92 printf("\ndialing..."); 93 fflush(stdout); 94 acu_hupcl (); 95 acu_flush (); 96 write(FD, "ATv0\r", 5); /* tell modem to use short status codes */ 97 gobble("\r"); 98 gobble("\r"); 99 write(FD, "ATTD", 4); /* send dial command */ 100 write(FD, num, strlen(num)); 101 state = DIALING; 102 write(FD, "\r", 1); 103 connected = 0; 104 if (gobble("\r")) { 105 if ((dummy = gobble("01234")) != '1') 106 error_rep(dummy); 107 else 108 connected = 1; 109 } 110 if (connected) 111 state = CONNECTED; 112 else { 113 state = FAILED; 114 return (connected); /* lets get out of here.. */ 115 } 116 ioctl(FD, TIOCFLUSH, 0); 117 #if ACULOG 118 if (timeout) { 119 sprintf(line, "%d second dial timeout", 120 number(value(DIALTIMEOUT))); 121 logent(value(HOST), num, "hayes", line); 122 } 123 #endif 124 if (timeout) 125 hay_disconnect(); /* insurance */ 126 return (connected); 127 } 128 129 130 hay_disconnect() 131 { 132 char c; 133 int len, rlen; 134 135 /* first hang up the modem*/ 136 #ifdef DEBUG 137 printf("\rdisconnecting modem....\n\r"); 138 #endif 139 ioctl(FD, TIOCCDTR, 0); 140 sleep(1); 141 ioctl(FD, TIOCSDTR, 0); 142 goodbye(); 143 } 144 145 hay_abort() 146 { 147 148 char c; 149 150 write(FD, "\r", 1); /* send anything to abort the call */ 151 hay_disconnect(); 152 } 153 154 static void 155 sigALRM() 156 { 157 158 printf("\07timeout waiting for reply\n\r"); 159 timeout = 1; 160 longjmp(timeoutbuf, 1); 161 } 162 163 static char 164 gobble(match) 165 register char *match; 166 { 167 char c; 168 sig_t f; 169 int i, status = 0; 170 171 f = signal(SIGALRM, sigALRM); 172 timeout = 0; 173 #ifdef DEBUG 174 printf("\ngobble: waiting for %s\n", match); 175 #endif 176 do { 177 if (setjmp(timeoutbuf)) { 178 signal(SIGALRM, f); 179 return (0); 180 } 181 alarm(number(value(DIALTIMEOUT))); 182 read(FD, &c, 1); 183 alarm(0); 184 c &= 0177; 185 #ifdef DEBUG 186 printf("%c 0x%x ", c, c); 187 #endif 188 for (i = 0; i < strlen(match); i++) 189 if (c == match[i]) 190 status = c; 191 } while (status == 0); 192 signal(SIGALRM, SIG_DFL); 193 #ifdef DEBUG 194 printf("\n"); 195 #endif 196 return (status); 197 } 198 199 error_rep(c) 200 register char c; 201 { 202 printf("\n\r"); 203 switch (c) { 204 205 case '0': 206 printf("OK"); 207 break; 208 209 case '1': 210 printf("CONNECT"); 211 break; 212 213 case '2': 214 printf("RING"); 215 break; 216 217 case '3': 218 printf("NO CARRIER"); 219 break; 220 221 case '4': 222 printf("ERROR in input"); 223 break; 224 225 case '5': 226 printf("CONNECT 1200"); 227 break; 228 229 default: 230 printf("Unknown Modem error: %c (0x%x)", c, c); 231 } 232 printf("\n\r"); 233 return; 234 } 235 236 /* 237 * set modem back to normal verbose status codes. 238 */ 239 goodbye() 240 { 241 int len, rlen; 242 char c; 243 244 ioctl(FD, TIOCFLUSH, &len); /* get rid of trash */ 245 if (hay_sync()) { 246 sleep(1); 247 #ifndef DEBUG 248 ioctl(FD, TIOCFLUSH, 0); 249 #endif 250 write(FD, "ATH0\r", 5); /* insurance */ 251 #ifndef DEBUG 252 c = gobble("03"); 253 if (c != '0' && c != '3') { 254 printf("cannot hang up modem\n\r"); 255 printf("please use 'tip dialer' to make sure the line is hung up\n\r"); 256 } 257 #endif 258 sleep(1); 259 ioctl(FD, FIONREAD, &len); 260 #ifdef DEBUG 261 printf("goodbye1: len=%d -- ", len); 262 rlen = read(FD, dumbuf, min(len, DUMBUFLEN)); 263 dumbuf[rlen] = '\0'; 264 printf("read (%d): %s\r\n", rlen, dumbuf); 265 #endif 266 write(FD, "ATv1\r", 5); 267 sleep(1); 268 #ifdef DEBUG 269 ioctl(FD, FIONREAD, &len); 270 printf("goodbye2: len=%d -- ", len); 271 rlen = read(FD, dumbuf, min(len, DUMBUFLEN)); 272 dumbuf[rlen] = '\0'; 273 printf("read (%d): %s\r\n", rlen, dumbuf); 274 #endif 275 } 276 ioctl(FD, TIOCFLUSH, 0); /* clear the input buffer */ 277 ioctl(FD, TIOCCDTR, 0); /* clear DTR (insurance) */ 278 close(FD); 279 } 280 281 #define MAXRETRY 5 282 283 hay_sync() 284 { 285 int len, retry = 0; 286 287 while (retry++ <= MAXRETRY) { 288 write(FD, "AT\r", 3); 289 sleep(1); 290 ioctl(FD, FIONREAD, &len); 291 if (len) { 292 len = read(FD, dumbuf, min(len, DUMBUFLEN)); 293 if (index(dumbuf, '0') || 294 (index(dumbuf, 'O') && index(dumbuf, 'K'))) 295 return(1); 296 #ifdef DEBUG 297 dumbuf[len] = '\0'; 298 printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry); 299 #endif 300 } 301 ioctl(FD, TIOCCDTR, 0); 302 ioctl(FD, TIOCSDTR, 0); 303 } 304 printf("Cannot synchronize with hayes...\n\r"); 305 return(0); 306 } 307