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