1 | /* |
---|
2 | * refclock_acts - clock driver for the NIST/PTB Automated Computer Time |
---|
3 | * Service aka Amalgamated Containerized Trash Service (ACTS) |
---|
4 | */ |
---|
5 | |
---|
6 | #ifdef HAVE_CONFIG_H |
---|
7 | #include <config.h> |
---|
8 | #endif |
---|
9 | |
---|
10 | #if defined(REFCLOCK) && (defined(ACTS) || defined(PTBACTS)) |
---|
11 | |
---|
12 | #include <stdio.h> |
---|
13 | #include <ctype.h> |
---|
14 | #include <sys/time.h> |
---|
15 | #ifdef HAVE_SYS_IOCTL_H |
---|
16 | # include <sys/ioctl.h> |
---|
17 | #endif /* HAVE_SYS_IOCTL_H */ |
---|
18 | |
---|
19 | #include "ntpd.h" |
---|
20 | #include "ntp_io.h" |
---|
21 | #include "ntp_unixtime.h" |
---|
22 | #include "ntp_refclock.h" |
---|
23 | #include "ntp_stdlib.h" |
---|
24 | #include "ntp_control.h" |
---|
25 | |
---|
26 | /* MUST BE AFTER LAST #include <config.h> !!! */ |
---|
27 | |
---|
28 | #if defined(ACTS) && defined(PTBACTS) |
---|
29 | # if defined(KEEPPTBACTS) |
---|
30 | # undef ACTS |
---|
31 | # else /* not KEEPPTBACTS */ |
---|
32 | # undef PTBACTS |
---|
33 | # endif /* not KEEPPTBACTS */ |
---|
34 | #endif /* ACTS && PTBACTS */ |
---|
35 | |
---|
36 | /* |
---|
37 | * This driver supports the NIST Automated Computer Time Service (ACTS). |
---|
38 | * It periodically dials a prespecified telephone number, receives the |
---|
39 | * NIST timecode data and calculates the local clock correction. It is |
---|
40 | * designed primarily for use as a backup when neither a radio clock nor |
---|
41 | * connectivity to Internet time servers is available. For the best |
---|
42 | * accuracy, the individual telephone line/modem delay needs to be |
---|
43 | * calibrated using outside sources. |
---|
44 | * |
---|
45 | * The ACTS is located at NIST Boulder, CO, telephone 303 494 4774. A |
---|
46 | * toll call from a residence telephone in Newark, DE, costs between 14 |
---|
47 | * and 27 cents, depending on time of day, and from a campus telephone |
---|
48 | * between 3 and 4 cents, although it is not clear what carrier and time |
---|
49 | * of day discounts apply in this case. The modem dial string will |
---|
50 | * differ depending on local telephone configuration, etc., and is |
---|
51 | * specified by the phone command in the configuration file. The |
---|
52 | * argument to this command is an AT command for a Hayes compatible |
---|
53 | * modem. |
---|
54 | * |
---|
55 | * The accuracy produced by this driver should be in the range of a |
---|
56 | * millisecond or two, but may need correction due to the delay |
---|
57 | * characteristics of the individual modem involved. For undetermined |
---|
58 | * reasons, some modems work with the ACTS echo-delay measurement scheme |
---|
59 | * and some don't. This driver tries to do the best it can with what it |
---|
60 | * gets. Initial experiments with a Practical Peripherals 9600SA modem |
---|
61 | * here in Delaware suggest an accuracy of a millisecond or two can be |
---|
62 | * achieved without the scheme by using a fudge time1 value of 65.0 ms. |
---|
63 | * In either case, the dispersion for a single call involving ten |
---|
64 | * samples is about 1.3 ms. |
---|
65 | * |
---|
66 | * The driver can operate in either of three modes, as determined by |
---|
67 | * the mode parameter in the server configuration command. In mode 0 |
---|
68 | * (automatic) the driver operates continuously at intervals depending |
---|
69 | * on the prediction error, as measured by the driver, usually in the |
---|
70 | * order of several hours. In mode 1 (backup) the driver is enabled in |
---|
71 | * automatic mode only when no other source of synchronization is |
---|
72 | * available and when more than MAXOUTAGE (3600 s) have elapsed since |
---|
73 | * last synchronized by other sources. In mode 2 (manual) the driver |
---|
74 | * operates only when enabled using a fudge flags switch, as described |
---|
75 | * below. |
---|
76 | * |
---|
77 | * For reliable call management, this driver requires a 1200-bps modem |
---|
78 | * with a Hayes-compatible command set and control over the modem data |
---|
79 | * terminal ready (DTR) control line. Present restrictions require the |
---|
80 | * use of a POSIX-compatible programming interface, although other |
---|
81 | * interfaces may work as well. The modem setup string is hard-coded in |
---|
82 | * the driver and may require changes for nonstandard modems or special |
---|
83 | * circumstances. |
---|
84 | * |
---|
85 | * Further information can be found in the README.refclock file in the |
---|
86 | * xntp3 distribution. |
---|
87 | * |
---|
88 | * Fudge Factors |
---|
89 | * |
---|
90 | * Ordinarily, the propagation time correction is computed automatically |
---|
91 | * by ACTS and the driver. When this is not possible or erratic due to |
---|
92 | * individual modem characteristics, the fudge flag2 switch should be |
---|
93 | * set to disable the ACTS echo-delay scheme. In any case, the fudge |
---|
94 | * time1 parameter can be used to adjust the propagation delay as |
---|
95 | * required. |
---|
96 | * |
---|
97 | * The ACTS call interval is determined in one of three ways. In manual |
---|
98 | * mode a call is initiated by setting fudge flag1 using xntpdc, either |
---|
99 | * manually or via a cron job. In AUTO mode this flag is set by the peer |
---|
100 | * timer, which is controlled by the sys_poll variable in response to |
---|
101 | * measured errors. In backup mode the driver is ordinarily asleep, but |
---|
102 | * awakes (in auto mode) if all other synchronization sources are lost. |
---|
103 | * In either auto or backup modes, the call interval increases as long |
---|
104 | * as the measured errors do not exceed the value of the fudge time2 |
---|
105 | * parameter. |
---|
106 | * |
---|
107 | * When the fudge flag1 is set, the ACTS calling program is activated. |
---|
108 | * This program dials each number listed in the phones command of the |
---|
109 | * configuration file in turn. If a call attempt fails, the next number |
---|
110 | * in the list is dialed. The fudge flag1 and counter are reset and the |
---|
111 | * calling program terminated if (a) a valid clock update has been |
---|
112 | * determined, (b) no more numbers remain in the list, (c) a device |
---|
113 | * fault or timeout occurs or (d) fudge flag1 is reset manually using |
---|
114 | * xntpdc. |
---|
115 | * |
---|
116 | * In automatic and backup modes, the driver determines the call |
---|
117 | * interval using a procedure depending on the measured prediction |
---|
118 | * error and the fudge time2 parameter. If the error exceeds time2 for a |
---|
119 | * number of times depending on the current interval, the interval is |
---|
120 | * decreased, but not less than about 1000 s. If the error is less than |
---|
121 | * time2 for some number of times, the interval is increased, but not |
---|
122 | * more than about 18 h. With the default value of zero for fudge time2, |
---|
123 | * the interval will increase from 1000 s to the 4000-8000-s range, in |
---|
124 | * which the expected accuracy should be in the 1-2-ms range. Setting |
---|
125 | * fudge time2 to a large value, like 0.1 s, may result in errors of |
---|
126 | * that order, but increase the call interval to the maximum. The exact |
---|
127 | * value for each configuration will depend on the modem and operating |
---|
128 | * system involved, so some experimentation may be necessary. |
---|
129 | */ |
---|
130 | |
---|
131 | /* |
---|
132 | * DESCRIPTION OF THE AUTOMATED COMPUTER TELEPHONE SERVICE (ACTS) |
---|
133 | * (reformatted from ACTS on-line computer help information) |
---|
134 | * |
---|
135 | * The following is transmitted (at 1200 baud) following completion of |
---|
136 | * the telephone connection. |
---|
137 | * |
---|
138 | * National Institute of Standards and Technology |
---|
139 | * Telephone Time Service, Generator 3B |
---|
140 | * Enter question mark "?" for HELP |
---|
141 | * D L D |
---|
142 | * MJD YR MO DA H M S ST S UT1 msADV <OTM> |
---|
143 | * 47999 90-04-18 21:39:15 50 0 +.1 045.0 UTC(NIST) * |
---|
144 | * 47999 90-04-18 21:39:16 50 0 +.1 045.0 UTC(NIST) * |
---|
145 | * 47999 90-04-18 21:39:17 50 0 +.1 045.0 UTC(NIST) * |
---|
146 | * 47999 90-04-18 21:39:18 50 0 +.1 045.0 UTC(NIST) * |
---|
147 | * 47999 90-04-18 21:39:19 50 0 +.1 037.6 UTC(NIST) # |
---|
148 | * 47999 90-04-18 21:39:20 50 0 +.1 037.6 UTC(NIST) # |
---|
149 | * etc..etc...etc....... |
---|
150 | * |
---|
151 | * UTC = Universal Time Coordinated, the official world time referred to |
---|
152 | * the zero meridian. |
---|
153 | * |
---|
154 | * DST Daylight savings time characters, valid for the continental |
---|
155 | * U.S., are set as follows: |
---|
156 | * |
---|
157 | * 00 We are on standard time (ST). |
---|
158 | * 01-49 Now on DST, go to ST when your local time is 2:00 am and |
---|
159 | * the count is 01. The count is decremented daily at 00 |
---|
160 | * (UTC). |
---|
161 | * 50 We are on DST. |
---|
162 | * 51-99 Now on ST, go to DST when your local time is 2:00 am and |
---|
163 | * the count is 51. The count is decremented daily at 00 |
---|
164 | * (UTC). |
---|
165 | * |
---|
166 | * The two DST characters provide up to 48 days advance notice of a |
---|
167 | * change in time. The count remains at 00 or 50 at other times. |
---|
168 | * |
---|
169 | * LS Leap second flag is set to "1" to indicate that a leap second is |
---|
170 | * to be added as 23:59:60 (UTC) on the last day of the current UTC |
---|
171 | * month. The LS flag will be reset to "0" starting with 23:59:60 |
---|
172 | * (UTC). The flag will remain on for the entire month before the |
---|
173 | * second is added. Leap seconds are added as needed at the end of |
---|
174 | * any month. Usually June and/or December are chosen. |
---|
175 | * |
---|
176 | * The leap second flag will be set to a "2" to indicate that a |
---|
177 | * leap second is to be deleted at 23:59:58--00:00:00 on the last |
---|
178 | * day of the current month. (This latter provision is included per |
---|
179 | * international recommendation, however it is not likely to be |
---|
180 | * required in the near future.) |
---|
181 | * |
---|
182 | * DUT1 Approximate difference between earth rotation time (UT1) and |
---|
183 | * UTC, in steps of 0.1 second: DUT1 = UT1 - UTC. |
---|
184 | * |
---|
185 | * MJD Modified Julian Date, often used to tag certain scientific data. |
---|
186 | * |
---|
187 | * The full time format is sent at 1200 baud, 8 bit, 1 stop, no parity. |
---|
188 | * The format at 300 Baud is also 8 bit, 1 stop, no parity. At 300 Baud |
---|
189 | * the MJD and DUT1 values are deleted and the time is transmitted only |
---|
190 | * on even seconds. |
---|
191 | * |
---|
192 | * Maximum on line time will be 56 seconds. If all lines are busy at any |
---|
193 | * time, the oldest call will be terminated if it has been on line more |
---|
194 | * than 28 seconds, otherwise, the call that first reaches 28 seconds |
---|
195 | * will be terminated. |
---|
196 | * |
---|
197 | * Current time is valid at the "on-time" marker (OTM), either "*" or |
---|
198 | * "#". The nominal on-time marker (*) will be transmitted 45 ms early |
---|
199 | * to account for the 8 ms required to send 1 character at 1200 Baud, |
---|
200 | * plus an additional 7 ms for delay from NIST to the user, and |
---|
201 | * approximately 30 ms "scrambler" delay inherent in 1200 Baud modems. |
---|
202 | * If the caller echoes all characters, NIST will measure the round trip |
---|
203 | * delay and advance the on-time marker so that the midpoint of the stop |
---|
204 | * bit arrives at the user on time. The amount of msADV will reflect the |
---|
205 | * actual required advance in milliseconds and the OTM will be a "#". |
---|
206 | * |
---|
207 | * (The NIST system requires 4 or 5 consecutive delay measurements which |
---|
208 | * are consistent before switching from "*" to "#". If the user has a |
---|
209 | * 1200 Baud modem with the same internal delay as that used by NIST, |
---|
210 | * then the "#" OTM should arrive at the user within +-2 ms of the |
---|
211 | * correct time. |
---|
212 | * |
---|
213 | * However, NIST has studied different brands of 1200 Baud modems and |
---|
214 | * found internal delays from 24 ms to 40 ms and offsets of the "#" OTM |
---|
215 | * of +-10 ms. For many computer users, +-10 ms accuracy should be more |
---|
216 | * than adequate since many computer internal clocks can only be set |
---|
217 | * with granularity of 20 to 50 ms. In any case, the repeatability of |
---|
218 | * the offset for the "#" OTM should be within +-2 ms, if the dial-up |
---|
219 | * path is reciprocal and the user doesn't change the brand or model of |
---|
220 | * modem used. |
---|
221 | * |
---|
222 | * This should be true even if the dial-up path on one day is a land- |
---|
223 | * line of less than 40 ms (one way) and on the next day is a satellite |
---|
224 | * link of 260 to 300 ms. In the rare event that the path is one way by |
---|
225 | * satellite and the other way by land line with a round trip |
---|
226 | * measurement in the range of 90 to 260 ms, the OTM will remain a "*" |
---|
227 | * indicating 45 ms advance. |
---|
228 | * |
---|
229 | * For user comments write: |
---|
230 | * NIST-ACTS |
---|
231 | * Time and Frequency Division |
---|
232 | * Mail Stop 847 |
---|
233 | * 325 Broadway |
---|
234 | * Boulder, CO 80303 |
---|
235 | * |
---|
236 | * Software for setting (PC)DOS compatable machines is available on a |
---|
237 | * 360-kbyte diskette for $35.00 from: NIST Office of Standard Reference |
---|
238 | * Materials B311-Chemistry Bldg, NIST, Gaithersburg, MD, 20899, (301) |
---|
239 | * 975-6776 |
---|
240 | * |
---|
241 | * PTB timecode service (+49 531 512038) |
---|
242 | * The Physikalisch-Technische Bundesanstalt (Germany) |
---|
243 | * also supports a modem time service |
---|
244 | * as the data formats are very similar this driver can also be compiled for |
---|
245 | * utilizing the PTB time code service. |
---|
246 | * |
---|
247 | * Data format |
---|
248 | * 0000000000111111111122222222223333333333444444444455555555556666666666777777777 7 |
---|
249 | * 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9 |
---|
250 | * 1995-01-23 20:58:51 MEZ 10402303260219950123195849740+40000500 * |
---|
251 | * A B C D EF G H IJ K L M N O P Q R S T U V W XY Z<CR><LF> |
---|
252 | * |
---|
253 | * A year |
---|
254 | * B month |
---|
255 | * C day |
---|
256 | * D hour |
---|
257 | * E : normally |
---|
258 | * A for DST to ST switch first hour |
---|
259 | * B for DST to ST switch second hour if not marked in H |
---|
260 | * F minute |
---|
261 | * G second |
---|
262 | * H timezone |
---|
263 | * I day of week |
---|
264 | * J week of year |
---|
265 | * K day of year |
---|
266 | * L month for next ST/DST changes |
---|
267 | * M day |
---|
268 | * N hour |
---|
269 | * O UTC year |
---|
270 | * P UTC month |
---|
271 | * Q UTC day |
---|
272 | * R UTC hour |
---|
273 | * S UTC minute |
---|
274 | * T modified julian day (MJD) |
---|
275 | * U DUT1 |
---|
276 | * V direction and month if leap second |
---|
277 | * W signal delay (assumed/measured) |
---|
278 | * X sequence number for additional text line in Y |
---|
279 | * Y additional text |
---|
280 | * Z on time marker (* - assumed delay / # measured delay) |
---|
281 | * <CR>!<LF> ! is second change ! |
---|
282 | * |
---|
283 | * This format is also used by the National Physical Laboratory (NPL)'s |
---|
284 | * TRUETIME service in the UK. In this case the timezone field is |
---|
285 | * UTC+0 or UTC+1 for standard and daylight saving time. The phone |
---|
286 | * number for this service (a premium rate number) is 0891 516 333. |
---|
287 | * It is not clear whether the echo check is implemented. |
---|
288 | * |
---|
289 | * For more detail, see http://www.npl.co.uk/npl/cetm/taf/truetime.html. |
---|
290 | */ |
---|
291 | |
---|
292 | /* |
---|
293 | * Interface definitions |
---|
294 | */ |
---|
295 | #define SPEED232 B1200 /* uart speed (1200 cowardly baud) */ |
---|
296 | #define PRECISION (-10) /* precision assumed (about 1 ms) */ |
---|
297 | #ifdef ACTS |
---|
298 | # define REFID "ACTS" /* reference ID */ |
---|
299 | # define DESCRIPTION "NIST Automated Computer Time Service" /* WRU */ |
---|
300 | # define LENCODE 50 /* length of valid timecode string */ |
---|
301 | # define DEVICE "/dev/acts%d" /* device name and unit */ |
---|
302 | # define REF_ENTRY refclock_acts |
---|
303 | #else /* not ACTS */ |
---|
304 | # define REFID "TPTB" /* reference ID */ |
---|
305 | # define DESCRIPTION "PTB Automated Computer Time Service" |
---|
306 | # define LENCODE 78 /* length of valid timecode string */ |
---|
307 | # define DEVICE "/dev/ptb%d" /* device name and unit */ |
---|
308 | # define REF_ENTRY refclock_ptb |
---|
309 | #endif /* not ACTS */ |
---|
310 | #define MODE_AUTO 0 /* automatic mode */ |
---|
311 | #define MODE_BACKUP 1 /* backup mode */ |
---|
312 | #define MODE_MANUAL 2 /* manual mode */ |
---|
313 | |
---|
314 | #define NSAMPLES 3 /* stages of median filter */ |
---|
315 | #define MSGCNT 10 /* we need this many ACTS messages */ |
---|
316 | #define SMAX 80 /* max token string length */ |
---|
317 | #define ACTS_MINPOLL 10 /* log2 min poll interval (1024 s) */ |
---|
318 | #define ACTS_MAXPOLL 14 /* log2 max poll interval (16384 s) */ |
---|
319 | #define MAXOUTAGE 3600 /* max before ACTS kicks in (s) */ |
---|
320 | |
---|
321 | /* |
---|
322 | * Modem control strings. These may have to be changed for some modems. |
---|
323 | * |
---|
324 | * AT command prefix |
---|
325 | * B1 initiate call negotiation using Bell 212A |
---|
326 | * &C1 enable carrier detect |
---|
327 | * &D2 hang up and return to command mode on DTR transition |
---|
328 | * E0 modem command echo disabled |
---|
329 | * l1 set modem speaker volume to low level |
---|
330 | * M1 speaker enabled untill carrier detect |
---|
331 | * Q0 return result codes |
---|
332 | * V1 return result codes as English words |
---|
333 | */ |
---|
334 | #define MODEM_SETUP "ATB1&C1&D2E0L1M1Q0V1" /* modem setup */ |
---|
335 | #define MODEM_HANGUP "ATH" /* modem disconnect */ |
---|
336 | |
---|
337 | /* |
---|
338 | * Timeouts |
---|
339 | */ |
---|
340 | #define IDLE 60 /* idle timeout (s) */ |
---|
341 | #define WAIT 2 /* wait timeout (s) */ |
---|
342 | #define ANSWER 30 /* answer timeout (s) */ |
---|
343 | #define CONNECT 10 /* connect timeout (s) */ |
---|
344 | #define TIMECODE 15 /* timecode timeout (s) */ |
---|
345 | |
---|
346 | /* |
---|
347 | * Imported from ntp_timer module |
---|
348 | */ |
---|
349 | extern u_long current_time; /* current time (s) */ |
---|
350 | extern u_long last_time; /* last clock update time (s) */ |
---|
351 | extern struct event timerqueue[]; /* inner space */ |
---|
352 | |
---|
353 | /* |
---|
354 | * Imported from ntpd module |
---|
355 | */ |
---|
356 | extern int debug; /* global debug flag */ |
---|
357 | |
---|
358 | /* |
---|
359 | * Imported from ntp_config module |
---|
360 | */ |
---|
361 | extern char sys_phone[][MAXDIAL]; /* modem dial strings */ |
---|
362 | |
---|
363 | /* |
---|
364 | * Imported from ntp_proto module |
---|
365 | */ |
---|
366 | extern struct peer *sys_peer; /* who is running the show */ |
---|
367 | extern u_char sys_poll; /* log2 of system poll interval */ |
---|
368 | extern struct peer *sys_peer; /* system peer structure pointer */ |
---|
369 | |
---|
370 | /* |
---|
371 | * Tables to compute the ddd of year form icky dd/mm timecode. Viva la |
---|
372 | * leap. |
---|
373 | */ |
---|
374 | static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
---|
375 | static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
---|
376 | |
---|
377 | /* |
---|
378 | * Unit control structure |
---|
379 | */ |
---|
380 | struct actsunit { |
---|
381 | struct event timer; /* timeout timer */ |
---|
382 | int pollcnt; /* poll message counter */ |
---|
383 | |
---|
384 | int state; /* the first one was Delaware */ |
---|
385 | int run; /* call program run switch */ |
---|
386 | int msgcnt; /* count of ACTS messages received */ |
---|
387 | long redial; /* interval to next automatic call */ |
---|
388 | double msADV; /* millisecond advance of last message */ |
---|
389 | }; |
---|
390 | |
---|
391 | /* |
---|
392 | * Function prototypes |
---|
393 | */ |
---|
394 | static int acts_start P((int, struct peer *)); |
---|
395 | static void acts_shutdown P((int, struct peer *)); |
---|
396 | static void acts_receive P((struct recvbuf *)); |
---|
397 | static void acts_poll P((int, struct peer *)); |
---|
398 | static void acts_timeout P((struct peer *)); |
---|
399 | static void acts_disc P((struct peer *)); |
---|
400 | static int acts_write P((struct peer *, char *)); |
---|
401 | |
---|
402 | /* |
---|
403 | * Transfer vector (conditional structure name) |
---|
404 | */ |
---|
405 | struct refclock REF_ENTRY = { |
---|
406 | acts_start, /* start up driver */ |
---|
407 | acts_shutdown, /* shut down driver */ |
---|
408 | acts_poll, /* transmit poll message */ |
---|
409 | noentry, /* not used (old acts_control) */ |
---|
410 | noentry, /* not used (old acts_init) */ |
---|
411 | noentry, /* not used (old acts_buginfo) */ |
---|
412 | NOFLAGS /* not used */ |
---|
413 | }; |
---|
414 | |
---|
415 | |
---|
416 | /* |
---|
417 | * acts_start - open the devices and initialize data for processing |
---|
418 | */ |
---|
419 | static int |
---|
420 | acts_start(unit, peer) |
---|
421 | int unit; |
---|
422 | struct peer *peer; |
---|
423 | { |
---|
424 | register struct actsunit *up; |
---|
425 | struct refclockproc *pp; |
---|
426 | int fd; |
---|
427 | char device[20]; |
---|
428 | int dtr = TIOCM_DTR; |
---|
429 | |
---|
430 | /* |
---|
431 | * Open serial port. Use ACTS line discipline, if available. It |
---|
432 | * pumps a timestamp into the data stream at every on-time |
---|
433 | * character '*' found. Note: the port must have modem control |
---|
434 | * or deep pockets for the phone bill. HP-UX 9.03 users should |
---|
435 | * have very deep pockets. |
---|
436 | */ |
---|
437 | (void)sprintf(device, DEVICE, unit); |
---|
438 | if (!(fd = refclock_open(device, SPEED232, LDISC_ACTS))) |
---|
439 | return (0); |
---|
440 | if (ioctl(fd, TIOCMBIS, (char *)&dtr) < 0) { |
---|
441 | msyslog(LOG_ERR, "clock %s ACTS no modem control", |
---|
442 | ntoa(&peer->srcadr)); |
---|
443 | return (0); |
---|
444 | } |
---|
445 | |
---|
446 | /* |
---|
447 | * Allocate and initialize unit structure |
---|
448 | */ |
---|
449 | if (!(up = (struct actsunit *) |
---|
450 | emalloc(sizeof(struct actsunit)))) { |
---|
451 | (void) close(fd); |
---|
452 | return (0); |
---|
453 | } |
---|
454 | memset((char *)up, 0, sizeof(struct actsunit)); |
---|
455 | pp = peer->procptr; |
---|
456 | pp->io.clock_recv = acts_receive; |
---|
457 | pp->io.srcclock = (caddr_t)peer; |
---|
458 | pp->io.datalen = 0; |
---|
459 | pp->io.fd = fd; |
---|
460 | if (!io_addclock(&pp->io)) { |
---|
461 | (void) close(fd); |
---|
462 | free(up); |
---|
463 | return (0); |
---|
464 | } |
---|
465 | pp->unitptr = (caddr_t)up; |
---|
466 | |
---|
467 | /* |
---|
468 | * Initialize miscellaneous variables |
---|
469 | */ |
---|
470 | peer->precision = PRECISION; |
---|
471 | pp->clockdesc = DESCRIPTION; |
---|
472 | memcpy((char *)&pp->refid, REFID, 4); |
---|
473 | peer->minpoll = ACTS_MINPOLL; |
---|
474 | peer->maxpoll = ACTS_MAXPOLL; |
---|
475 | peer->sstclktype = CTL_SST_TS_TELEPHONE; |
---|
476 | |
---|
477 | /* |
---|
478 | * Initialize modem and kill DTR. We skedaddle if this comes |
---|
479 | * bum. |
---|
480 | */ |
---|
481 | if (!acts_write(peer, MODEM_SETUP)) { |
---|
482 | (void) close(fd); |
---|
483 | free(up); |
---|
484 | return (0); |
---|
485 | } |
---|
486 | |
---|
487 | /* |
---|
488 | * Set up the driver timeout |
---|
489 | */ |
---|
490 | up->timer.peer = (struct peer *)peer; |
---|
491 | up->timer.event_handler = acts_timeout; |
---|
492 | up->timer.event_time = current_time + WAIT; |
---|
493 | TIMER_INSERT(timerqueue, &up->timer); |
---|
494 | return (1); |
---|
495 | } |
---|
496 | |
---|
497 | |
---|
498 | /* |
---|
499 | * acts_shutdown - shut down the clock |
---|
500 | */ |
---|
501 | static void |
---|
502 | acts_shutdown(unit, peer) |
---|
503 | int unit; |
---|
504 | struct peer *peer; |
---|
505 | { |
---|
506 | register struct actsunit *up; |
---|
507 | struct refclockproc *pp; |
---|
508 | |
---|
509 | pp = peer->procptr; |
---|
510 | up = (struct actsunit *)pp->unitptr; |
---|
511 | TIMER_DEQUEUE(&up->timer); |
---|
512 | io_closeclock(&pp->io); |
---|
513 | free(up); |
---|
514 | } |
---|
515 | |
---|
516 | |
---|
517 | /* |
---|
518 | * acts_receive - receive data from the serial interface |
---|
519 | */ |
---|
520 | static void |
---|
521 | acts_receive(rbufp) |
---|
522 | struct recvbuf *rbufp; |
---|
523 | { |
---|
524 | register struct actsunit *up; |
---|
525 | struct refclockproc *pp; |
---|
526 | struct peer *peer; |
---|
527 | char str[SMAX]; |
---|
528 | int i; |
---|
529 | l_fp tstmp; |
---|
530 | u_fp disp; |
---|
531 | char hangup = '%'; /* ACTS hangup */ |
---|
532 | int day; /* day of the month */ |
---|
533 | int month; /* month of the year */ |
---|
534 | u_long mjd; /* Modified Julian Day */ |
---|
535 | double dut1; /* DUT adjustment */ |
---|
536 | double msADV; /* ACTS transmit advance (ms) */ |
---|
537 | char flag; /* calibration flag */ |
---|
538 | #ifndef PTBACTS |
---|
539 | char utc[10]; /* this is NIST and you're not */ |
---|
540 | u_int dst; /* daylight/standard time indicator */ |
---|
541 | u_int leap; /* leap-second indicator */ |
---|
542 | #else |
---|
543 | char leapdir; /* leap direction */ |
---|
544 | u_int leapmonth; /* month of leap */ |
---|
545 | #endif |
---|
546 | /* |
---|
547 | * Initialize pointers and read the timecode and timestamp. If |
---|
548 | * the OK modem status code, leave it where folks can find it. |
---|
549 | */ |
---|
550 | peer = (struct peer *)rbufp->recv_srcclock; |
---|
551 | pp = peer->procptr; |
---|
552 | up = (struct actsunit *)pp->unitptr; |
---|
553 | pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, |
---|
554 | &pp->lastrec); |
---|
555 | if (pp->lencode == 0) { |
---|
556 | if (strcmp(pp->a_lastcode, "OK") == 0) |
---|
557 | pp->lencode = 2; |
---|
558 | return; |
---|
559 | } |
---|
560 | #ifdef DEBUG |
---|
561 | if (debug) |
---|
562 | printf("acts: state %d timecode %d %*s\n", up->state, |
---|
563 | pp->lencode, pp->lencode, pp->a_lastcode); |
---|
564 | #endif |
---|
565 | |
---|
566 | switch (up->state) { |
---|
567 | |
---|
568 | case 0: |
---|
569 | |
---|
570 | /* |
---|
571 | * State 0. We are not expecting anything. Probably |
---|
572 | * modem disconnect noise. Go back to sleep. |
---|
573 | */ |
---|
574 | return; |
---|
575 | |
---|
576 | case 1: |
---|
577 | |
---|
578 | /* |
---|
579 | * State 1. We are waiting for the call to be answered. |
---|
580 | * All we care about here is CONNECT as the first token |
---|
581 | * in the string. If the modem signals BUSY, ERROR, NO |
---|
582 | * ANSWER, NO CARRIER or NO DIALTONE, we immediately |
---|
583 | * hang up the phone. If CONNECT doesn't happen after |
---|
584 | * ANSWER seconds, hang up the phone. If everything is |
---|
585 | * okay, start the connect timeout and slide into state |
---|
586 | * 2. |
---|
587 | */ |
---|
588 | if( strcmp(sys_phone[0],"DIRECT") != 0 ) { |
---|
589 | if (pp) { |
---|
590 | if (pp->a_lastcode[0]) { |
---|
591 | (void)strncpy(str, strtok(pp->a_lastcode, " "), SMAX); |
---|
592 | } else { |
---|
593 | msyslog(LOG_ERR, "clock %s ACTS: pp->a_lastcode was NIL", |
---|
594 | ntoa(&peer->srcadr)); |
---|
595 | *str = '\0'; |
---|
596 | } |
---|
597 | } else { |
---|
598 | /* pp was NIL */ |
---|
599 | msyslog(LOG_ERR, "clock %s ACTS: pp was NIL", |
---|
600 | ntoa(&peer->srcadr)); |
---|
601 | *str = '\0'; |
---|
602 | } |
---|
603 | if (strcmp(str, "BUSY") == 0 || strcmp(str, "ERROR") == |
---|
604 | 0 || strcmp(str, "NO") == 0) { |
---|
605 | TIMER_DEQUEUE(&up->timer); |
---|
606 | NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */ |
---|
607 | msyslog(LOG_NOTICE, |
---|
608 | "clock %s ACTS modem status %s", |
---|
609 | ntoa(&peer->srcadr), pp->a_lastcode); |
---|
610 | acts_disc(peer); |
---|
611 | } else if (strcmp(str, "CONNECT") == 0) { |
---|
612 | TIMER_DEQUEUE(&up->timer); |
---|
613 | up->timer.event_time = current_time + CONNECT; |
---|
614 | TIMER_INSERT(timerqueue, &up->timer); |
---|
615 | up->msgcnt = 0; |
---|
616 | up->state++; |
---|
617 | } |
---|
618 | } else { |
---|
619 | (void) strncpy(str,"CONNECT",7); |
---|
620 | TIMER_DEQUEUE(&up->timer); |
---|
621 | up->timer.event_time = current_time + CONNECT; |
---|
622 | TIMER_INSERT(timerqueue, &up->timer); |
---|
623 | up->msgcnt = 0; |
---|
624 | up->state++; |
---|
625 | } |
---|
626 | return; |
---|
627 | |
---|
628 | case 2: |
---|
629 | |
---|
630 | /* |
---|
631 | * State 2. The call has been answered and we are |
---|
632 | * waiting for the first ACTS message. If this doesn't |
---|
633 | * happen within the timecode timeout, hang up the |
---|
634 | * phone. We probably got a wrong number or ACTS is |
---|
635 | * down. |
---|
636 | */ |
---|
637 | TIMER_DEQUEUE(&up->timer); |
---|
638 | up->timer.event_time = current_time + TIMECODE; |
---|
639 | TIMER_INSERT(timerqueue, &up->timer); |
---|
640 | up->state++; |
---|
641 | } |
---|
642 | |
---|
643 | /* |
---|
644 | * Real yucky things here. Ignore everything except timecode |
---|
645 | * messages, as determined by the message length. We told the |
---|
646 | * terminal routines to end the line with '*' and the line |
---|
647 | * discipline to strike a timestamp on that character. However, |
---|
648 | * when the ACTS echo-delay scheme works, the '*' eventually |
---|
649 | * becomes a '#'. In this case the message is ended by the <CR> |
---|
650 | * that comes about 200 ms after the '#' and the '#' cannot be |
---|
651 | * echoed at the proper time. But, this may not be a lose, since |
---|
652 | * we already have good data from prior messages and only need |
---|
653 | * the millisecond advance calculated by ACTS. So, if the |
---|
654 | * message is long enough and has an on-time character at the |
---|
655 | * right place, we consider the message (but not neccesarily the |
---|
656 | * timestmap) to be valid. |
---|
657 | */ |
---|
658 | if (pp->lencode != LENCODE) |
---|
659 | return; |
---|
660 | |
---|
661 | #ifndef PTBACTS |
---|
662 | /* |
---|
663 | * We apparently have a valid timecode message, so dismember it |
---|
664 | * with sscan(). This routine does a good job in spotting syntax |
---|
665 | * errors without becoming overly pedantic. |
---|
666 | * |
---|
667 | * D L D |
---|
668 | * MJD YR MO DA H M S ST S UT1 msADV OTM |
---|
669 | * 47222 88-03-02 21:39:15 83 0 +.3 045.0 UTC(NBS) * |
---|
670 | */ |
---|
671 | if (sscanf(pp->a_lastcode, |
---|
672 | "%5ld %2d-%2d-%2d %2d:%2d:%2d %2d %1d %3lf %5lf %s %c", |
---|
673 | &mjd, &pp->year, &month, &day, &pp->hour, &pp->minute, |
---|
674 | &pp->second, &dst, &leap, &dut1, &msADV, utc, &flag) != 13) { |
---|
675 | refclock_report(peer, CEVNT_BADREPLY); |
---|
676 | return; |
---|
677 | } |
---|
678 | #else |
---|
679 | /* |
---|
680 | * Data format |
---|
681 | * 0000000000111111111122222222223333333333444444444455555555556666666666777777777 7 |
---|
682 | * 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9 |
---|
683 | * 1995-01-23 20:58:51 MEZ 10402303260219950123195849740+40000500 * |
---|
684 | */ |
---|
685 | if (sscanf(pp->a_lastcode, |
---|
686 | "%*4d-%*2d-%*2d %*2d:%*2d:%2d %*5c%*12c%4d%2d%2d%2d%2d%5ld%2lf%c%2d%3lf%*15c%c", |
---|
687 | &pp->second, &pp->year, &month, &day, &pp->hour, &pp->minute, &mjd, &dut1, &leapdir, &leapmonth, &msADV, &flag) != 12) { |
---|
688 | refclock_report(peer, CEVNT_BADREPLY); |
---|
689 | return; |
---|
690 | } |
---|
691 | #endif |
---|
692 | /* |
---|
693 | * Some modems can't be trusted (the Practical Peripherals |
---|
694 | * 9600SA comes to mind) and, even if they manage to unstick |
---|
695 | * ACTS, the millisecond advance is wrong, so we use CLK_FLAG2 |
---|
696 | * to disable echoes, if neccessary. |
---|
697 | */ |
---|
698 | if ((flag == '*' || flag == '#') && !(pp->sloppyclockflag & |
---|
699 | CLK_FLAG2)) |
---|
700 | (void)write(pp->io.fd, &flag, 1); |
---|
701 | |
---|
702 | /* |
---|
703 | * Yes, I know this code incorrectly thinks that 2000 is a leap |
---|
704 | * year. The ACTS timecode format croaks then anyway. Life is |
---|
705 | * short. Would only the timecode mavens resist the urge to |
---|
706 | * express months of the year and days of the month in favor of |
---|
707 | * days of the year. |
---|
708 | */ |
---|
709 | if (month < 1 || month > 12 || day < 1) { |
---|
710 | refclock_report(peer, CEVNT_BADTIME); |
---|
711 | return; |
---|
712 | } |
---|
713 | if (pp->year % 4) { |
---|
714 | if (day > day1tab[month - 1]) { |
---|
715 | refclock_report(peer, CEVNT_BADTIME); |
---|
716 | return; |
---|
717 | } |
---|
718 | for (i = 0; i < month - 1; i++) |
---|
719 | day += day1tab[i]; |
---|
720 | } else { |
---|
721 | if (day > day2tab[month - 1]) { |
---|
722 | refclock_report(peer, CEVNT_BADTIME); |
---|
723 | return; |
---|
724 | } |
---|
725 | for (i = 0; i < month - 1; i++) |
---|
726 | day += day2tab[i]; |
---|
727 | } |
---|
728 | pp->day = day; |
---|
729 | |
---|
730 | #ifndef PTBACTS |
---|
731 | if (leap == 1) |
---|
732 | pp->leap = LEAP_ADDSECOND; |
---|
733 | else if (pp->leap == 2) |
---|
734 | pp->leap = LEAP_DELSECOND; |
---|
735 | else |
---|
736 | pp->leap = 0; |
---|
737 | #else |
---|
738 | if (leapmonth == month) { |
---|
739 | if (leapdir == '+') |
---|
740 | pp->leap = LEAP_ADDSECOND; |
---|
741 | else if (leapdir == '-') |
---|
742 | pp->leap = LEAP_DELSECOND; |
---|
743 | } |
---|
744 | else |
---|
745 | pp->leap = 0; |
---|
746 | #endif |
---|
747 | pp->lasttime = current_time; |
---|
748 | |
---|
749 | /* |
---|
750 | * Colossal hack here. We process each sample in a trimmed-mean |
---|
751 | * filter and determine the reference clock offset and |
---|
752 | * dispersion. The fudge time1 value is added to each sample as |
---|
753 | * received. If we collect MSGCNT samples before the '#' on-time |
---|
754 | * character, we use the results of the filter as is. If the '#' |
---|
755 | * is found before that, the adjusted msADV is used to correct |
---|
756 | * the propagation delay. |
---|
757 | */ |
---|
758 | up->msgcnt++; |
---|
759 | if (flag == '#') { |
---|
760 | L_CLR(&tstmp); |
---|
761 | TVUTOTSF((long)((msADV - up->msADV) * 1000.), |
---|
762 | tstmp.l_uf); |
---|
763 | L_ADD(&pp->offset, &tstmp); |
---|
764 | } else { |
---|
765 | up->msADV = msADV; |
---|
766 | if (!refclock_process(pp, up->msgcnt, up->msgcnt - |
---|
767 | up->msgcnt / 3)) { |
---|
768 | refclock_report(peer, CEVNT_BADTIME); |
---|
769 | return; |
---|
770 | } else if (up->msgcnt < MSGCNT) |
---|
771 | return; |
---|
772 | } |
---|
773 | |
---|
774 | /* |
---|
775 | * We have a filtered sample offset ready for peer processing. |
---|
776 | * We use lastrec as both the reference time and receive time in |
---|
777 | * order to avoid being cute, like setting the reference time |
---|
778 | * later than the receive time, which may cause a paranoid |
---|
779 | * protocol module to chuck out the data. Finaly, we unhook the |
---|
780 | * timeout, arm for the next call, fold the tent and go home. |
---|
781 | * The little dance with the '%' character is an undocumented |
---|
782 | * ACTS feature that hangs up the phone real quick without |
---|
783 | * waiting for carrier loss or long-space disconnect, but we do |
---|
784 | * these clumsy things anyway. |
---|
785 | */ |
---|
786 | disp = LFPTOFP(&pp->fudgetime2); |
---|
787 | record_clock_stats(&peer->srcadr, pp->a_lastcode); |
---|
788 | refclock_receive(peer, &pp->offset, 0, pp->dispersion + |
---|
789 | (u_fp)disp, &pp->lastrec, &pp->lastrec, pp->leap); |
---|
790 | pp->sloppyclockflag &= ~CLK_FLAG1; |
---|
791 | up->pollcnt = 0; |
---|
792 | TIMER_DEQUEUE(&up->timer); |
---|
793 | (void)write(pp->io.fd, &hangup, 1); |
---|
794 | up->state = 0; |
---|
795 | acts_disc(peer); |
---|
796 | } |
---|
797 | |
---|
798 | |
---|
799 | /* |
---|
800 | * acts_poll - called by the transmit routine |
---|
801 | */ |
---|
802 | static void |
---|
803 | acts_poll(unit, peer) |
---|
804 | int unit; |
---|
805 | struct peer *peer; |
---|
806 | { |
---|
807 | register struct actsunit *up; |
---|
808 | struct refclockproc *pp; |
---|
809 | |
---|
810 | /* |
---|
811 | * If the driver is running, we set the enable flag (fudge |
---|
812 | * flag1), which causes the driver timeout routine to initiate a |
---|
813 | * call to ACTS. If not, the enable flag can be set using |
---|
814 | * xntpdc. If this is the sustem peer, then follow the system |
---|
815 | * poll interval. |
---|
816 | */ |
---|
817 | pp = peer->procptr; |
---|
818 | up = (struct actsunit *)pp->unitptr; |
---|
819 | if (up->run) { |
---|
820 | pp->sloppyclockflag |= CLK_FLAG1; |
---|
821 | if (peer == sys_peer) |
---|
822 | peer->hpoll = sys_poll; |
---|
823 | else |
---|
824 | peer->hpoll = peer->minpoll; |
---|
825 | } |
---|
826 | } |
---|
827 | |
---|
828 | |
---|
829 | /* |
---|
830 | * acts_timeout - called by the timer interrupt |
---|
831 | */ |
---|
832 | static void |
---|
833 | acts_timeout(peer) |
---|
834 | struct peer *peer; |
---|
835 | { |
---|
836 | register struct actsunit *up; |
---|
837 | struct refclockproc *pp; |
---|
838 | int dtr = TIOCM_DTR; |
---|
839 | |
---|
840 | /* |
---|
841 | * If a timeout occurs in other than state 0, the call has |
---|
842 | * failed. If in state 0, we just see if there is other work to |
---|
843 | * do. |
---|
844 | */ |
---|
845 | pp = peer->procptr; |
---|
846 | up = (struct actsunit *)pp->unitptr; |
---|
847 | if (up->state) { |
---|
848 | acts_disc(peer); |
---|
849 | return; |
---|
850 | } |
---|
851 | switch (peer->ttl) { |
---|
852 | |
---|
853 | /* |
---|
854 | * In manual mode the ACTS calling program is activated |
---|
855 | * by the xntpdc program using the enable flag (fudge |
---|
856 | * flag1), either manually or by a cron job. |
---|
857 | */ |
---|
858 | case MODE_MANUAL: |
---|
859 | up->run = 0; |
---|
860 | break; |
---|
861 | |
---|
862 | /* |
---|
863 | * In automatic mode the ACTS calling program runs |
---|
864 | * continuously at intervals determined by the sys_poll |
---|
865 | * variable. |
---|
866 | */ |
---|
867 | case MODE_AUTO: |
---|
868 | if (!up->run) |
---|
869 | pp->sloppyclockflag |= CLK_FLAG1; |
---|
870 | up->run = 1; |
---|
871 | break; |
---|
872 | |
---|
873 | /* |
---|
874 | * In backup mode the ACTS calling program is disabled, |
---|
875 | * unless no system peer has been selected for MAXOUTAGE |
---|
876 | * (3600 s). Once enabled, it runs until some other NTP |
---|
877 | * peer shows up. |
---|
878 | */ |
---|
879 | case MODE_BACKUP: |
---|
880 | if (!up->run && sys_peer == 0) { |
---|
881 | if (current_time - last_time > MAXOUTAGE) { |
---|
882 | up->run = 1; |
---|
883 | peer->hpoll = peer->minpoll; |
---|
884 | NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */ |
---|
885 | msyslog(LOG_NOTICE, |
---|
886 | "clock %s ACTS backup started ", |
---|
887 | ntoa(&peer->srcadr)); |
---|
888 | } |
---|
889 | } else if (up->run && sys_peer->sstclktype != CTL_SST_TS_TELEPHONE) { |
---|
890 | peer->hpoll = peer->minpoll; |
---|
891 | up->run = 0; |
---|
892 | NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */ |
---|
893 | msyslog(LOG_NOTICE, |
---|
894 | "clock %s ACTS backup stopped", |
---|
895 | ntoa(&peer->srcadr)); |
---|
896 | } |
---|
897 | break; |
---|
898 | |
---|
899 | default: |
---|
900 | msyslog(LOG_ERR, |
---|
901 | "clock %s ACTS invalid mode", ntoa(&peer->srcadr)); |
---|
902 | |
---|
903 | } |
---|
904 | |
---|
905 | /* |
---|
906 | * The fudge flag1 is used as an enable/disable; if set either |
---|
907 | * by the code or via xntpdc, the ACTS calling program is |
---|
908 | * started; if reset, the phones stop ringing. |
---|
909 | */ |
---|
910 | if (!(pp->sloppyclockflag & CLK_FLAG1)) { |
---|
911 | up->pollcnt = 0; |
---|
912 | up->timer.event_time = current_time + IDLE; |
---|
913 | TIMER_INSERT(timerqueue, &up->timer); |
---|
914 | return; |
---|
915 | } |
---|
916 | |
---|
917 | /* |
---|
918 | * Initiate a call to the ACTS service. If we wind up here in |
---|
919 | * other than state 0, a successful call could not be completed |
---|
920 | * within minpoll seconds. We advance to the next modem dial |
---|
921 | * string. If none are left, we log a notice and clear the |
---|
922 | * enable flag. For future enhancement: call the site RP and |
---|
923 | * leave an obscene message in his voicemail. |
---|
924 | */ |
---|
925 | if (sys_phone[up->pollcnt][0] == '\0') { |
---|
926 | refclock_report(peer, CEVNT_TIMEOUT); |
---|
927 | NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */ |
---|
928 | msyslog(LOG_NOTICE, |
---|
929 | "clock %s ACTS calling program terminated", |
---|
930 | ntoa(&peer->srcadr)); |
---|
931 | pp->sloppyclockflag &= ~CLK_FLAG1; |
---|
932 | #ifdef DEBUG |
---|
933 | if (debug) |
---|
934 | printf("acts: calling program terminated\n"); |
---|
935 | #endif |
---|
936 | up->pollcnt = 0; |
---|
937 | up->timer.event_time = current_time + IDLE; |
---|
938 | TIMER_INSERT(timerqueue, &up->timer); |
---|
939 | return; |
---|
940 | } |
---|
941 | |
---|
942 | /* |
---|
943 | * Raise DTR, call ACTS and start the answer timeout. We think |
---|
944 | * it strange if the OK status has not been received from the |
---|
945 | * modem, but plow ahead anyway. |
---|
946 | */ |
---|
947 | if (strcmp(pp->a_lastcode, "OK") != 0) |
---|
948 | NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */ |
---|
949 | msyslog(LOG_NOTICE, "clock %s ACTS no modem status", |
---|
950 | ntoa(&peer->srcadr)); |
---|
951 | (void)ioctl(pp->io.fd, TIOCMBIS, (char *)&dtr); |
---|
952 | (void)acts_write(peer, sys_phone[up->pollcnt]); |
---|
953 | NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */ |
---|
954 | msyslog(LOG_NOTICE, "clock %s ACTS calling %s\n", |
---|
955 | ntoa(&peer->srcadr), sys_phone[up->pollcnt]); |
---|
956 | up->state = 1; |
---|
957 | up->pollcnt++; |
---|
958 | pp->polls++; |
---|
959 | up->timer.event_time = current_time + ANSWER; |
---|
960 | TIMER_INSERT(timerqueue, &up->timer); |
---|
961 | } |
---|
962 | |
---|
963 | |
---|
964 | /* |
---|
965 | * acts_disc - disconnect the call and wait for the ruckus to cool |
---|
966 | */ |
---|
967 | static void |
---|
968 | acts_disc(peer) |
---|
969 | struct peer *peer; |
---|
970 | { |
---|
971 | register struct actsunit *up; |
---|
972 | struct refclockproc *pp; |
---|
973 | int dtr = TIOCM_DTR; |
---|
974 | |
---|
975 | /* |
---|
976 | * We should never get here other than in state 0, unless a call |
---|
977 | * has timed out. We drop DTR, which will reliably get the modem |
---|
978 | * off the air, even while ACTS is hammering away full tilt. |
---|
979 | */ |
---|
980 | pp = peer->procptr; |
---|
981 | up = (struct actsunit *)pp->unitptr; |
---|
982 | (void)ioctl(pp->io.fd, TIOCMBIC, (char *)&dtr); |
---|
983 | if (up->state > 0) { |
---|
984 | NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */ |
---|
985 | msyslog(LOG_NOTICE, "clock %s ACTS call failed %d", |
---|
986 | ntoa(&peer->srcadr), up->state); |
---|
987 | #ifdef DEBUG |
---|
988 | if (debug) |
---|
989 | printf("acts: call failed %d\n", up->state); |
---|
990 | #endif |
---|
991 | up->state = 0; |
---|
992 | } |
---|
993 | up->timer.event_time = current_time + WAIT; |
---|
994 | TIMER_INSERT(timerqueue, &up->timer); |
---|
995 | } |
---|
996 | |
---|
997 | |
---|
998 | /* |
---|
999 | * acts_write - write a message to the serial port |
---|
1000 | */ |
---|
1001 | static int |
---|
1002 | acts_write(peer, str) |
---|
1003 | struct peer *peer; |
---|
1004 | char *str; |
---|
1005 | { |
---|
1006 | register struct actsunit *up; |
---|
1007 | struct refclockproc *pp; |
---|
1008 | int len; |
---|
1009 | int code; |
---|
1010 | char cr = '\r'; |
---|
1011 | |
---|
1012 | /* |
---|
1013 | * Not much to do here, other than send the message, handle |
---|
1014 | * debug and report faults. |
---|
1015 | */ |
---|
1016 | pp = peer->procptr; |
---|
1017 | up = (struct actsunit *)pp->unitptr; |
---|
1018 | len = strlen(str); |
---|
1019 | #ifdef DEBUG |
---|
1020 | if (debug) |
---|
1021 | printf("acts: state %d send %d %s\n", up->state, len, |
---|
1022 | str); |
---|
1023 | #endif |
---|
1024 | code = write(pp->io.fd, str, len) == len; |
---|
1025 | code &= write(pp->io.fd, &cr, 1) == 1; |
---|
1026 | if (!code) |
---|
1027 | refclock_report(peer, CEVNT_FAULT); |
---|
1028 | return (code); |
---|
1029 | } |
---|
1030 | |
---|
1031 | #else /* not (REFCLOCK && (ACTS || PTBACTS)) */ |
---|
1032 | int refclock_acts_bs; |
---|
1033 | #endif /* not (REFCLOCK && (ACTS || PTBACTS)) */ |
---|