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