Commit | Line | Data |
---|---|---|
051b1e55 DF |
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 | ||
e316be98 | 7 | #ifndef lint |
051b1e55 DF |
8 | static char sccsid[] = "@(#)hayes.c 5.1 (Berkeley) %G%"; |
9 | #endif not lint | |
e316be98 MAN |
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 | char dummy; | |
58 | #ifdef ACULOG | |
59 | char line[80]; | |
60 | #endif | |
61 | if (hay_sync() == 0) /* make sure we can talk to the modem */ | |
62 | return(0); | |
63 | if (boolean(value(VERBOSE))) | |
64 | printf("\ndialing..."); | |
65 | fflush(stdout); | |
66 | ioctl(FD, TIOCHPCL, 0); | |
67 | ioctl(FD, TIOCFLUSH, 0); /* get rid of garbage */ | |
68 | write(FD, "ATv0\r", 5); /* tell modem to use short status codes */ | |
69 | gobble("\r"); | |
70 | gobble("\r"); | |
71 | write(FD, "ATTD", 4); /* send dial command */ | |
72 | write(FD, num, strlen(num)); | |
73 | state = DIALING; | |
74 | write(FD, "\r", 1); | |
75 | connected = 0; | |
76 | if (gobble("\r")) { | |
77 | if ((dummy = gobble("01234")) != '1') | |
78 | error_rep(dummy); | |
79 | else | |
80 | connected = 1; | |
81 | } | |
82 | if (connected) | |
83 | state = CONNECTED; | |
84 | else { | |
85 | state = FAILED; | |
86 | return (connected); /* lets get out of here.. */ | |
87 | } | |
88 | ioctl(FD, TIOCFLUSH, 0); | |
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 | 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 | char c; | |
215 | ||
216 | ioctl(FD, TIOCFLUSH, &len); /* get rid of trash */ | |
217 | if (hay_sync()) { | |
218 | sleep(1); | |
219 | #ifndef DEBUG | |
220 | ioctl(FD, TIOCFLUSH, 0); | |
221 | #endif | |
222 | write(FD, "ATH0\r", 5); /* insurance */ | |
223 | #ifndef DEBUG | |
224 | c = gobble("03"); | |
225 | if (c != '0' && c != '3') { | |
226 | printf("cannot hang up modem\n\r"); | |
227 | printf("please use 'tip dialer' to make sure the line is hung up\n\r"); | |
228 | } | |
229 | #endif | |
230 | sleep(1); | |
231 | ioctl(FD, FIONREAD, &len); | |
232 | #ifdef DEBUG | |
233 | printf("goodbye1: len=%d -- ", len); | |
234 | rlen = read(FD, dumbuf, min(len, DUMBUFLEN)); | |
235 | dumbuf[rlen] = '\0'; | |
236 | printf("read (%d): %s\r\n", rlen, dumbuf); | |
237 | #endif | |
238 | write(FD, "ATv1\r", 5); | |
239 | sleep(1); | |
240 | #ifdef DEBUG | |
241 | ioctl(FD, FIONREAD, &len); | |
242 | printf("goodbye2: len=%d -- ", len); | |
243 | rlen = read(FD, dumbuf, min(len, DUMBUFLEN)); | |
244 | dumbuf[rlen] = '\0'; | |
245 | printf("read (%d): %s\r\n", rlen, dumbuf); | |
246 | #endif | |
247 | } | |
248 | ioctl(FD, TIOCFLUSH, 0); /* clear the input buffer */ | |
249 | ioctl(FD, TIOCCDTR, 0); /* clear DTR (insurance) */ | |
250 | close(FD); | |
251 | } | |
252 | ||
253 | #define MAXRETRY 5 | |
254 | ||
255 | hay_sync() | |
256 | { | |
257 | int len, retry = 0; | |
258 | ||
259 | while (retry++ <= MAXRETRY) { | |
260 | write(FD, "AT\r", 3); | |
261 | sleep(1); | |
262 | ioctl(FD, FIONREAD, &len); | |
263 | if (len) { | |
264 | len = read(FD, dumbuf, min(len, DUMBUFLEN)); | |
265 | if (index(dumbuf, '0') || | |
266 | (index(dumbuf, 'O') && index(dumbuf, 'K'))) | |
267 | return(1); | |
268 | #ifdef DEBUG | |
269 | dumbuf[len] = '\0'; | |
270 | printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry); | |
271 | #endif | |
272 | } | |
273 | ioctl(FD, TIOCCDTR, 0); | |
274 | ioctl(FD, TIOCSDTR, 0); | |
275 | } | |
276 | printf("Cannot synchronize with hayes...\n\r"); | |
277 | return(0); | |
278 | } |