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