1*19817Sdist /* 2*19817Sdist * Copyright (c) 1983 Regents of the University of California. 3*19817Sdist * All rights reserved. The Berkeley software License Agreement 4*19817Sdist * specifies the terms and conditions for redistribution. 5*19817Sdist */ 6*19817Sdist 718635Smiriam #ifndef lint 8*19817Sdist static char sccsid[] = "@(#)hayes.c 5.1 (Berkeley) 04/30/85"; 9*19817Sdist #endif not lint 1018635Smiriam 1118635Smiriam /* 1218635Smiriam * Routines for calling up on a Hayes Modem 1318635Smiriam * (based on the old VenTel driver). 1418635Smiriam * The modem is expected to be strapped for "echo". 1518635Smiriam * Also, the switches enabling the DTR and CD lines 1618635Smiriam * must be set correctly. 1718635Smiriam * NOTICE: 1818635Smiriam * The easy way to hang up a modem is always simply to 1918635Smiriam * clear the DTR signal. However, if the +++ sequence 2018635Smiriam * (which switches the modem back to local mode) is sent 2118635Smiriam * before modem is hung up, removal of the DTR signal 2218635Smiriam * has no effect (except that it prevents the modem from 2318635Smiriam * recognizing commands). 2418635Smiriam * (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984) 2518635Smiriam */ 2618635Smiriam /* 2718635Smiriam * TODO: 2818635Smiriam * It is probably not a good idea to switch the modem 2918635Smiriam * state between 'verbose' and terse (status messages). 3018635Smiriam * This should be kicked out and we should use verbose 3118635Smiriam * mode only. This would make it consistent with normal 3218635Smiriam * interactive use thru the command 'tip dialer'. 3318635Smiriam */ 3418635Smiriam #include "tip.h" 3518635Smiriam 3618635Smiriam #define min(a,b) ((a < b) ? a : b) 3718635Smiriam 3818635Smiriam static int sigALRM(); 3918635Smiriam static int timeout = 0; 4018635Smiriam static jmp_buf timeoutbuf; 4118635Smiriam static char gobble(); 4218635Smiriam #define DUMBUFLEN 40 4318635Smiriam static char dumbuf[DUMBUFLEN]; 4418635Smiriam 4518635Smiriam #define DIALING 1 4618635Smiriam #define IDLE 2 4718635Smiriam #define CONNECTED 3 4818635Smiriam #define FAILED 4 4918635Smiriam static int state = IDLE; 5018635Smiriam 5118635Smiriam hay_dialer(num, acu) 5218635Smiriam register char *num; 5318635Smiriam char *acu; 5418635Smiriam { 5518635Smiriam register char *cp; 5618635Smiriam register int connected = 0; 5718635Smiriam char dummy; 5818635Smiriam #ifdef ACULOG 5918635Smiriam char line[80]; 6018635Smiriam #endif 6118635Smiriam if (hay_sync() == 0) /* make sure we can talk to the modem */ 6218635Smiriam return(0); 6318635Smiriam if (boolean(value(VERBOSE))) 6418635Smiriam printf("\ndialing..."); 6518635Smiriam fflush(stdout); 6618635Smiriam ioctl(FD, TIOCHPCL, 0); 6718635Smiriam ioctl(FD, TIOCFLUSH, 0); /* get rid of garbage */ 6818635Smiriam write(FD, "ATv0\r", 5); /* tell modem to use short status codes */ 6918635Smiriam gobble("\r"); 7018635Smiriam gobble("\r"); 7118635Smiriam write(FD, "ATTD", 4); /* send dial command */ 7218635Smiriam write(FD, num, strlen(num)); 7318635Smiriam state = DIALING; 7418635Smiriam write(FD, "\r", 1); 7518635Smiriam connected = 0; 7618635Smiriam if (gobble("\r")) { 7718635Smiriam if ((dummy = gobble("01234")) != '1') 7818635Smiriam error_rep(dummy); 7918635Smiriam else 8018635Smiriam connected = 1; 8118635Smiriam } 8218635Smiriam if (connected) 8318635Smiriam state = CONNECTED; 8418635Smiriam else { 8518635Smiriam state = FAILED; 8618635Smiriam return (connected); /* lets get out of here.. */ 8718635Smiriam } 8818635Smiriam ioctl(FD, TIOCFLUSH, 0); 8918635Smiriam #ifdef ACULOG 9018635Smiriam if (timeout) { 9118635Smiriam sprintf(line, "%d second dial timeout", 9218635Smiriam number(value(DIALTIMEOUT))); 9318635Smiriam logent(value(HOST), num, "hayes", line); 9418635Smiriam } 9518635Smiriam #endif 9618635Smiriam if (timeout) 9718635Smiriam hay_disconnect(); /* insurance */ 9818635Smiriam return (connected); 9918635Smiriam } 10018635Smiriam 10118635Smiriam 10218635Smiriam hay_disconnect() 10318635Smiriam { 10418635Smiriam char c; 10518635Smiriam int len, rlen; 10618635Smiriam 10718635Smiriam /* first hang up the modem*/ 10818635Smiriam #ifdef DEBUG 10918635Smiriam printf("\rdisconnecting modem....\n\r"); 11018635Smiriam #endif 11118635Smiriam ioctl(FD, TIOCCDTR, 0); 11218635Smiriam sleep(1); 11318635Smiriam ioctl(FD, TIOCSDTR, 0); 11418635Smiriam goodbye(); 11518635Smiriam } 11618635Smiriam 11718635Smiriam hay_abort() 11818635Smiriam { 11918635Smiriam 12018635Smiriam char c; 12118635Smiriam 12218635Smiriam write(FD, "\r", 1); /* send anything to abort the call */ 12318635Smiriam hay_disconnect(); 12418635Smiriam } 12518635Smiriam 12618635Smiriam static int 12718635Smiriam sigALRM() 12818635Smiriam { 12918635Smiriam 13018635Smiriam printf("\07timeout waiting for reply\n\r"); 13118635Smiriam timeout = 1; 13218635Smiriam longjmp(timeoutbuf, 1); 13318635Smiriam } 13418635Smiriam 13518635Smiriam static char 13618635Smiriam gobble(match) 13718635Smiriam register char *match; 13818635Smiriam { 13918635Smiriam char c; 14018635Smiriam int (*f)(); 14118635Smiriam int i, status = 0; 14218635Smiriam 14318635Smiriam signal(SIGALRM, sigALRM); 14418635Smiriam timeout = 0; 14518635Smiriam #ifdef DEBUG 14618635Smiriam printf("\ngobble: waiting for %s\n", match); 14718635Smiriam #endif 14818635Smiriam do { 14918635Smiriam if (setjmp(timeoutbuf)) { 15018635Smiriam signal(SIGALRM, f); 15118635Smiriam return (0); 15218635Smiriam } 15318635Smiriam alarm(number(value(DIALTIMEOUT))); 15418635Smiriam read(FD, &c, 1); 15518635Smiriam alarm(0); 15618635Smiriam c &= 0177; 15718635Smiriam #ifdef DEBUG 15818635Smiriam printf("%c 0x%x ", c, c); 15918635Smiriam #endif 16018635Smiriam for (i = 0; i < strlen(match); i++) 16118635Smiriam if (c == match[i]) 16218635Smiriam status = c; 16318635Smiriam } while (status == 0); 16418635Smiriam signal(SIGALRM, SIG_DFL); 16518635Smiriam #ifdef DEBUG 16618635Smiriam printf("\n"); 16718635Smiriam #endif 16818635Smiriam return (status); 16918635Smiriam } 17018635Smiriam 17118635Smiriam error_rep(c) 17218635Smiriam register char c; 17318635Smiriam { 17418635Smiriam printf("\n\r"); 17518635Smiriam switch (c) { 17618635Smiriam 17718635Smiriam case '0': 17818635Smiriam printf("OK"); 17918635Smiriam break; 18018635Smiriam 18118635Smiriam case '1': 18218635Smiriam printf("CONNECT"); 18318635Smiriam break; 18418635Smiriam 18518635Smiriam case '2': 18618635Smiriam printf("RING"); 18718635Smiriam break; 18818635Smiriam 18918635Smiriam case '3': 19018635Smiriam printf("NO CARRIER"); 19118635Smiriam break; 19218635Smiriam 19318635Smiriam case '4': 19418635Smiriam printf("ERROR in input"); 19518635Smiriam break; 19618635Smiriam 19718635Smiriam case '5': 19818635Smiriam printf("CONNECT 1200"); 19918635Smiriam break; 20018635Smiriam 20118635Smiriam default: 20218635Smiriam printf("Unknown Modem error: %c (0x%x)", c, c); 20318635Smiriam } 20418635Smiriam printf("\n\r"); 20518635Smiriam return; 20618635Smiriam } 20718635Smiriam 20818635Smiriam /* 20918635Smiriam * set modem back to normal verbose status codes. 21018635Smiriam */ 21118635Smiriam goodbye() 21218635Smiriam { 21318635Smiriam int len, rlen; 21418635Smiriam char c; 21518635Smiriam 21618635Smiriam ioctl(FD, TIOCFLUSH, &len); /* get rid of trash */ 21718635Smiriam if (hay_sync()) { 21818635Smiriam sleep(1); 21918635Smiriam #ifndef DEBUG 22018635Smiriam ioctl(FD, TIOCFLUSH, 0); 22118635Smiriam #endif 22218635Smiriam write(FD, "ATH0\r", 5); /* insurance */ 22318635Smiriam #ifndef DEBUG 22418635Smiriam c = gobble("03"); 22518635Smiriam if (c != '0' && c != '3') { 22618635Smiriam printf("cannot hang up modem\n\r"); 22718635Smiriam printf("please use 'tip dialer' to make sure the line is hung up\n\r"); 22818635Smiriam } 22918635Smiriam #endif 23018635Smiriam sleep(1); 23118635Smiriam ioctl(FD, FIONREAD, &len); 23218635Smiriam #ifdef DEBUG 23318635Smiriam printf("goodbye1: len=%d -- ", len); 23418635Smiriam rlen = read(FD, dumbuf, min(len, DUMBUFLEN)); 23518635Smiriam dumbuf[rlen] = '\0'; 23618635Smiriam printf("read (%d): %s\r\n", rlen, dumbuf); 23718635Smiriam #endif 23818635Smiriam write(FD, "ATv1\r", 5); 23918635Smiriam sleep(1); 24018635Smiriam #ifdef DEBUG 24118635Smiriam ioctl(FD, FIONREAD, &len); 24218635Smiriam printf("goodbye2: len=%d -- ", len); 24318635Smiriam rlen = read(FD, dumbuf, min(len, DUMBUFLEN)); 24418635Smiriam dumbuf[rlen] = '\0'; 24518635Smiriam printf("read (%d): %s\r\n", rlen, dumbuf); 24618635Smiriam #endif 24718635Smiriam } 24818635Smiriam ioctl(FD, TIOCFLUSH, 0); /* clear the input buffer */ 24918635Smiriam ioctl(FD, TIOCCDTR, 0); /* clear DTR (insurance) */ 25018635Smiriam close(FD); 25118635Smiriam } 25218635Smiriam 25318635Smiriam #define MAXRETRY 5 25418635Smiriam 25518635Smiriam hay_sync() 25618635Smiriam { 25718635Smiriam int len, retry = 0; 25818635Smiriam 25918635Smiriam while (retry++ <= MAXRETRY) { 26018635Smiriam write(FD, "AT\r", 3); 26118635Smiriam sleep(1); 26218635Smiriam ioctl(FD, FIONREAD, &len); 26318635Smiriam if (len) { 26418635Smiriam len = read(FD, dumbuf, min(len, DUMBUFLEN)); 26518635Smiriam if (index(dumbuf, '0') || 26618635Smiriam (index(dumbuf, 'O') && index(dumbuf, 'K'))) 26718635Smiriam return(1); 26818635Smiriam #ifdef DEBUG 26918635Smiriam dumbuf[len] = '\0'; 27018635Smiriam printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry); 27118635Smiriam #endif 27218635Smiriam } 27318635Smiriam ioctl(FD, TIOCCDTR, 0); 27418635Smiriam ioctl(FD, TIOCSDTR, 0); 27518635Smiriam } 27618635Smiriam printf("Cannot synchronize with hayes...\n\r"); 27718635Smiriam return(0); 27818635Smiriam } 279