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