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