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