1/* 2 * refclock_acts - clock driver for the NIST/USNO/PTB/NPL Computer Time 3 * Services 4 */ 5#ifdef HAVE_CONFIG_H 6#include <config.h> 7#endif 8 9#if defined(REFCLOCK) && (defined(CLOCK_ACTS) || defined(CLOCK_PTBACTS)) 10 11#include "ntpd.h" 12#include "ntp_io.h" 13#include "ntp_unixtime.h" 14#include "ntp_refclock.h" 15#include "ntp_stdlib.h" 16#include "ntp_control.h" 17 18#include <stdio.h> 19#include <ctype.h> 20#ifdef HAVE_SYS_IOCTL_H 21# include <sys/ioctl.h> 22#endif /* HAVE_SYS_IOCTL_H */ 23 24/* 25 * This driver supports the US (NIST, USNO) and European (PTB, NPL, 26 * etc.) modem time services, as well as Spectracom GPS and WWVB 27 * receivers connected via a modem. The driver periodically dials a 28 * number from a telephone list, receives the timecode data and 29 * calculates the local clock correction. It is designed primarily for 30 * use as backup when neither a radio clock nor connectivity to Internet 31 * time servers is available. 32 * 33 * This driver requires a modem with a Hayes-compatible command set and 34 * control over the modem data terminal ready (DTR) control line. The 35 * modem setup string is hard-coded in the driver and may require 36 * changes for nonstandard modems or special circumstances. For reasons 37 * unrelated to this driver, the data set ready (DSR) control line 38 * should not be set when this driver is first started. 39 * 40 * The calling program is initiated by setting fudge flag1, either 41 * manually or automatically. When flag1 is set, the calling program 42 * dials the first number in the phone command of the configuration 43 * file. If that call fails, the calling program dials the second number 44 * and so on. The number is specified by the Hayes ATDT prefix followed 45 * by the number itself, including the prefix and long-distance digits 46 * and delay code, if necessary. The flag1 is reset and the calling 47 * program terminated if (a) a valid clock update has been determined, 48 * (b) no more numbers remain in the list, (c) a device fault or timeout 49 * occurs or (d) fudge flag1 is reset manually. 50 * 51 * The driver is transparent to each of the modem time services and 52 * Spectracom radios. It selects the parsing algorithm depending on the 53 * message length. There is some hazard should the message be corrupted. 54 * However, the data format is checked carefully and only if all checks 55 * succeed is the message accepted. Corrupted lines are discarded 56 * without complaint. 57 * 58 * Fudge controls 59 * 60 * flag1 force a call in manual mode 61 * flag2 enable port locking (not verified) 62 * flag3 no modem; port is directly connected to device 63 * flag4 not used 64 * 65 * time1 offset adjustment (s) 66 * 67 * Ordinarily, the serial port is connected to a modem; however, it can 68 * be connected directly to a device or another computer for testing and 69 * calibration. In this case set fudge flag3 and the driver will send a 70 * single character 'T' at each poll event. In principle, fudge flag2 71 * enables port locking, allowing the modem to be shared when not in use 72 * by this driver. At least on Solaris with the current NTP I/O 73 * routines, this results only in lots of ugly error messages. 74 */ 75/* 76 * National Institute of Science and Technology (NIST) 77 * 78 * Phone: (303) 494-4774 (Boulder, CO); (808) 335-4721 (Hawaii) 79 * 80 * Data Format 81 * 82 * National Institute of Standards and Technology 83 * Telephone Time Service, Generator 3B 84 * Enter question mark "?" for HELP 85 * D L D 86 * MJD YR MO DA H M S ST S UT1 msADV <OTM> 87 * 47999 90-04-18 21:39:15 50 0 +.1 045.0 UTC(NIST) *<CR><LF> 88 * ... 89 * 90 * MJD, DST, DUT1 and UTC are not used by this driver. The "*" or "#" is 91 * the on-time markers echoed by the driver and used by NIST to measure 92 * and correct for the propagation delay. 93 * 94 * US Naval Observatory (USNO) 95 * 96 * Phone: (202) 762-1594 (Washington, DC); (719) 567-6742 (Boulder, CO) 97 * 98 * Data Format (two lines, repeating at one-second intervals) 99 * 100 * jjjjj nnn hhmmss UTC<CR><LF> 101 * *<CR><LF> 102 * 103 * jjjjj modified Julian day number (not used) 104 * nnn day of year 105 * hhmmss second of day 106 * * on-time marker for previous timecode 107 * ... 108 * 109 * USNO does not correct for the propagation delay. A fudge time1 of 110 * about .06 s is advisable. 111 * 112 * European Services (PTB, NPL, etc.) 113 * 114 * PTB: +49 531 512038 (Germany) 115 * NPL: 0906 851 6333 (UK only) 116 * 117 * Data format (see the documentation for phone numbers and formats.) 118 * 119 * 1995-01-23 20:58:51 MEZ 10402303260219950123195849740+40000500<CR><LF> 120 * 121 * Spectracom GPS and WWVB Receivers 122 * 123 * If a modem is connected to a Spectracom receiver, this driver will 124 * call it up and retrieve the time in one of two formats. As this 125 * driver does not send anything, the radio will have to either be 126 * configured in continuous mode or be polled by another local driver. 127 */ 128/* 129 * Interface definitions 130 */ 131#define DEVICE "/dev/acts%d" /* device name and unit */ 132#define SPEED232 B9600 /* uart speed (9600 baud) */ 133#define PRECISION (-10) /* precision assumed (about 1 ms) */ 134#define LOCKFILE "/var/spool/locks/LCK..cua%d" 135#define DESCRIPTION "Automated Computer Time Service" /* WRU */ 136#define REFID "NONE" /* default reference ID */ 137#define MSGCNT 20 /* max message count */ 138#define SMAX 256 /* max clockstats line length */ 139#define MAXPHONE 10 /* max number of phone numbers */ 140 141/* 142 * Calling program modes 143 */ 144#define MODE_AUTO 0 /* automatic mode */ 145#define MODE_BACKUP 1 /* backup mode */ 146#define MODE_MANUAL 2 /* manual mode */ 147 148/* 149 * Service identifiers. 150 */ 151#define REFACTS "NIST" /* NIST reference ID */ 152#define LENACTS 50 /* NIST format */ 153#define REFUSNO "USNO" /* USNO reference ID */ 154#define LENUSNO 20 /* USNO */ 155#define REFPTB "PTB\0" /* PTB/NPL reference ID */ 156#define LENPTB 78 /* PTB/NPL format */ 157#define REFWWVB "WWVB" /* WWVB reference ID */ 158#define LENWWVB0 22 /* WWVB format 0 */ 159#define LENWWVB2 24 /* WWVB format 2 */ 160#define LF 0x0a /* ASCII LF */ 161 162/* 163 * Modem setup strings. These may have to be changed for some modems. 164 * 165 * AT command prefix 166 * B1 US answer tone 167 * &C0 disable carrier detect 168 * &D2 hang up and return to command mode on DTR transition 169 * E0 modem command echo disabled 170 * l1 set modem speaker volume to low level 171 * M1 speaker enabled until carrier detect 172 * Q0 return result codes 173 * V1 return result codes as English words 174 */ 175#define MODEM_SETUP "ATB1&C0&D2E0L1M1Q0V1\r" /* modem setup */ 176#define MODEM_HANGUP "ATH\r" /* modem disconnect */ 177 178/* 179 * Timeouts (all in seconds) 180 */ 181#define SETUP 3 /* setup timeout */ 182#define DTR 1 /* DTR timeout */ 183#define ANSWER 60 /* answer timeout */ 184#define CONNECT 20 /* first valid message timeout */ 185#define TIMECODE 30 /* all valid messages timeout */ 186 187/* 188 * State machine codes 189 */ 190#define S_IDLE 0 /* wait for poll */ 191#define S_OK 1 /* wait for modem setup */ 192#define S_DTR 2 /* wait for modem DTR */ 193#define S_CONNECT 3 /* wait for answer*/ 194#define S_FIRST 4 /* wait for first valid message */ 195#define S_MSG 5 /* wait for all messages */ 196#define S_CLOSE 6 /* wait after sending disconnect */ 197 198/* 199 * Unit control structure 200 */ 201struct actsunit { 202 int unit; /* unit number */ 203 int state; /* the first one was Delaware */ 204 int timer; /* timeout counter */ 205 int retry; /* retry index */ 206 int msgcnt; /* count of messages received */ 207 l_fp tstamp; /* on-time timestamp */ 208 char *bufptr; /* buffer pointer */ 209}; 210 211/* 212 * Function prototypes 213 */ 214static int acts_start (int, struct peer *); 215static void acts_shutdown (int, struct peer *); 216static void acts_receive (struct recvbuf *); 217static void acts_message (struct peer *); 218static void acts_timecode (struct peer *, char *); 219static void acts_poll (int, struct peer *); 220static void acts_timeout (struct peer *); 221static void acts_disc (struct peer *); 222static void acts_timer (int, struct peer *); 223 224/* 225 * Transfer vector (conditional structure name) 226 */ 227struct refclock refclock_acts = { 228 acts_start, /* start up driver */ 229 acts_shutdown, /* shut down driver */ 230 acts_poll, /* transmit poll message */ 231 noentry, /* not used */ 232 noentry, /* not used */ 233 noentry, /* not used */ 234 acts_timer /* housekeeping timer */ 235}; 236 237/* 238 * Initialize data for processing 239 */ 240static int 241acts_start ( 242 int unit, 243 struct peer *peer 244 ) 245{ 246 struct actsunit *up; 247 struct refclockproc *pp; 248 249 /* 250 * Allocate and initialize unit structure 251 */ 252 up = emalloc(sizeof(struct actsunit)); 253 memset(up, 0, sizeof(struct actsunit)); 254 up->unit = unit; 255 pp = peer->procptr; 256 pp->unitptr = (caddr_t)up; 257 pp->io.clock_recv = acts_receive; 258 pp->io.srcclock = (caddr_t)peer; 259 pp->io.datalen = 0; 260 261 /* 262 * Initialize miscellaneous variables 263 */ 264 peer->precision = PRECISION; 265 pp->clockdesc = DESCRIPTION; 266 memcpy((char *)&pp->refid, REFID, 4); 267 peer->sstclktype = CTL_SST_TS_TELEPHONE; 268 up->bufptr = pp->a_lastcode; 269 return (1); 270} 271 272 273/* 274 * acts_shutdown - shut down the clock 275 */ 276static void 277acts_shutdown ( 278 int unit, 279 struct peer *peer 280 ) 281{ 282 struct actsunit *up; 283 struct refclockproc *pp; 284 285 /* 286 * Warning: do this only when a call is not in progress. 287 */ 288 pp = peer->procptr; 289 up = (struct actsunit *)pp->unitptr; 290 free(up); 291} 292 293 294/* 295 * acts_receive - receive data from the serial interface 296 */ 297static void 298acts_receive ( 299 struct recvbuf *rbufp 300 ) 301{ 302 struct actsunit *up; 303 struct refclockproc *pp; 304 struct peer *peer; 305 char tbuf[BMAX]; 306 char *tptr; 307 308 /* 309 * Initialize pointers and read the timecode and timestamp. Note 310 * we are in raw mode and victim of whatever the terminal 311 * interface kicks up; so, we have to reassemble messages from 312 * arbitrary fragments. Capture the timecode at the beginning of 313 * the message and at the '*' and '#' on-time characters. 314 */ 315 peer = (struct peer *)rbufp->recv_srcclock; 316 pp = peer->procptr; 317 up = (struct actsunit *)pp->unitptr; 318 pp->lencode = refclock_gtraw(rbufp, tbuf, BMAX - (up->bufptr - 319 pp->a_lastcode), &pp->lastrec); 320 for (tptr = tbuf; *tptr != '\0'; tptr++) { 321 if (*tptr == LF) { 322 if (up->bufptr == pp->a_lastcode) { 323 up->tstamp = pp->lastrec; 324 continue; 325 326 } else { 327 *up->bufptr = '\0'; 328 acts_message(peer); 329 up->bufptr = pp->a_lastcode; 330 } 331 } else if (!iscntrl(*tptr)) { 332 *up->bufptr++ = *tptr; 333 if (*tptr == '*' || *tptr == '#') { 334 up->tstamp = pp->lastrec; 335 write(pp->io.fd, tptr, 1); 336 } 337 } 338 } 339} 340 341 342/* 343 * acts_message - process message 344 */ 345void 346acts_message( 347 struct peer *peer 348 ) 349{ 350 struct actsunit *up; 351 struct refclockproc *pp; 352 int dtr = TIOCM_DTR; 353 char tbuf[SMAX]; 354#ifdef DEBUG 355 u_int modem; 356#endif 357 358 /* 359 * What to do depends on the state and the first token in the 360 * message. */ 361 pp = peer->procptr; 362 up = (struct actsunit *)pp->unitptr; 363#ifdef DEBUG 364 ioctl(pp->io.fd, TIOCMGET, (char *)&modem); 365 snprintf(tbuf, sizeof(tbuf), "acts: %04x (%d %d) %d %s", modem, 366 up->state, up->timer, strlen(pp->a_lastcode), 367 pp->a_lastcode); 368 if (debug) 369 printf("%s\n", tbuf); 370#endif 371 372 /* 373 * Extract the first token in the line. A NO token sends the 374 * message to the clockstats. 375 */ 376 strncpy(tbuf, pp->a_lastcode, SMAX); 377 strtok(tbuf, " "); 378 if (strcmp(tbuf, "NO") == 0) { 379 report_event(PEVNT_CLOCK, peer, pp->a_lastcode); 380 return; 381 } 382 switch(up->state) { 383 384 /* 385 * We are waiting for the OK response to the modem setup 386 * command. When this happens, raise DTR and dial the number 387 * followed by \r. 388 */ 389 case S_OK: 390 if (strcmp(tbuf, "OK") != 0) { 391 msyslog(LOG_ERR, "acts: setup error %s", 392 pp->a_lastcode); 393 acts_disc(peer); 394 return; 395 } 396 ioctl(pp->io.fd, TIOCMBIS, (char *)&dtr); 397 up->state = S_DTR; 398 up->timer = DTR; 399 return; 400 401 /* 402 * We are waiting for the call to be answered. All we care about 403 * here is token CONNECT. Send the message to the clockstats. 404 */ 405 case S_CONNECT: 406 report_event(PEVNT_CLOCK, peer, pp->a_lastcode); 407 if (strcmp(tbuf, "CONNECT") != 0) { 408 acts_disc(peer); 409 return; 410 } 411 up->state = S_FIRST; 412 up->timer = CONNECT; 413 return; 414 415 /* 416 * We are waiting for a timecode. Pass it to the parser. 417 */ 418 case S_FIRST: 419 case S_MSG: 420 acts_timecode(peer, pp->a_lastcode); 421 break; 422 } 423} 424 425/* 426 * acts_timecode - identify the service and parse the timecode message 427 */ 428void 429acts_timecode( 430 struct peer *peer, /* peer structure pointer */ 431 char *str /* timecode string */ 432 ) 433{ 434 struct actsunit *up; 435 struct refclockproc *pp; 436 int day; /* day of the month */ 437 int month; /* month of the year */ 438 u_long mjd; /* Modified Julian Day */ 439 double dut1; /* DUT adjustment */ 440 441 u_int dst; /* ACTS daylight/standard time */ 442 u_int leap; /* ACTS leap indicator */ 443 double msADV; /* ACTS transmit advance (ms) */ 444 char utc[10]; /* ACTS timescale */ 445 char flag; /* ACTS on-time character (* or #) */ 446 447 char synchar; /* WWVB synchronized indicator */ 448 char qualchar; /* WWVB quality indicator */ 449 char leapchar; /* WWVB leap indicator */ 450 char dstchar; /* WWVB daylight/savings indicator */ 451 int tz; /* WWVB timezone */ 452 453 u_int leapmonth; /* PTB/NPL month of leap */ 454 char leapdir; /* PTB/NPL leap direction */ 455 456 /* 457 * The parser selects the modem format based on the message 458 * length. Since the data are checked carefully, occasional 459 * errors due noise are forgivable. 460 */ 461 pp = peer->procptr; 462 up = (struct actsunit *)pp->unitptr; 463 pp->nsec = 0; 464 switch(strlen(str)) { 465 466 /* 467 * For USNO format on-time character '*', which is on a line by 468 * itself. Be sure a timecode has been received. 469 */ 470 case 1: 471 if (*str == '*' && up->msgcnt > 0) 472 break; 473 474 return; 475 476 /* 477 * ACTS format: "jjjjj yy-mm-dd hh:mm:ss ds l uuu aaaaa 478 * UTC(NIST) *" 479 */ 480 case LENACTS: 481 if (sscanf(str, 482 "%5ld %2d-%2d-%2d %2d:%2d:%2d %2d %1d %3lf %5lf %9s %c", 483 &mjd, &pp->year, &month, &day, &pp->hour, 484 &pp->minute, &pp->second, &dst, &leap, &dut1, 485 &msADV, utc, &flag) != 13) { 486 refclock_report(peer, CEVNT_BADREPLY); 487 return; 488 } 489 490 /* 491 * Wait until ACTS has calculated the roundtrip delay. 492 * We don't need to do anything, as ACTS adjusts the 493 * on-time epoch. 494 */ 495 if (flag != '#') 496 return; 497 498 pp->day = ymd2yd(pp->year, month, day); 499 pp->leap = LEAP_NOWARNING; 500 if (leap == 1) 501 pp->leap = LEAP_ADDSECOND; 502 else if (pp->leap == 2) 503 pp->leap = LEAP_DELSECOND; 504 memcpy(&pp->refid, REFACTS, 4); 505 if (up->msgcnt == 0) 506 record_clock_stats(&peer->srcadr, str); 507 up->msgcnt++; 508 break; 509 510 /* 511 * USNO format: "jjjjj nnn hhmmss UTC" 512 */ 513 case LENUSNO: 514 if (sscanf(str, "%5ld %3d %2d%2d%2d %3s", 515 &mjd, &pp->day, &pp->hour, &pp->minute, 516 &pp->second, utc) != 6) { 517 refclock_report(peer, CEVNT_BADREPLY); 518 return; 519 } 520 521 /* 522 * Wait for the on-time character, which follows in a 523 * separate message. There is no provision for leap 524 * warning. 525 */ 526 pp->leap = LEAP_NOWARNING; 527 memcpy(&pp->refid, REFUSNO, 4); 528 if (up->msgcnt == 0) 529 record_clock_stats(&peer->srcadr, str); 530 up->msgcnt++; 531 return; 532 533 /* 534 * PTB/NPL format: "yyyy-mm-dd hh:mm:ss MEZ" 535 */ 536 case LENPTB: 537 if (sscanf(str, 538 "%*4d-%*2d-%*2d %*2d:%*2d:%2d %*5c%*12c%4d%2d%2d%2d%2d%5ld%2lf%c%2d%3lf%*15c%c", 539 &pp->second, &pp->year, &month, &day, &pp->hour, 540 &pp->minute, &mjd, &dut1, &leapdir, &leapmonth, 541 &msADV, &flag) != 12) { 542 refclock_report(peer, CEVNT_BADREPLY); 543 return; 544 } 545 pp->leap = LEAP_NOWARNING; 546 if (leapmonth == month) { 547 if (leapdir == '+') 548 pp->leap = LEAP_ADDSECOND; 549 else if (leapdir == '-') 550 pp->leap = LEAP_DELSECOND; 551 } 552 pp->day = ymd2yd(pp->year, month, day); 553 memcpy(&pp->refid, REFPTB, 4); 554 if (up->msgcnt == 0) 555 record_clock_stats(&peer->srcadr, str); 556 up->msgcnt++; 557 break; 558 559 560 /* 561 * WWVB format 0: "I ddd hh:mm:ss DTZ=nn" 562 */ 563 case LENWWVB0: 564 if (sscanf(str, "%c %3d %2d:%2d:%2d %cTZ=%2d", 565 &synchar, &pp->day, &pp->hour, &pp->minute, 566 &pp->second, &dstchar, &tz) != 7) { 567 refclock_report(peer, CEVNT_BADREPLY); 568 return; 569 } 570 pp->leap = LEAP_NOWARNING; 571 if (synchar != ' ') 572 pp->leap = LEAP_NOTINSYNC; 573 memcpy(&pp->refid, REFWWVB, 4); 574 if (up->msgcnt == 0) 575 record_clock_stats(&peer->srcadr, str); 576 up->msgcnt++; 577 break; 578 579 /* 580 * WWVB format 2: "IQyy ddd hh:mm:ss.mmm LD" 581 */ 582 case LENWWVB2: 583 if (sscanf(str, "%c%c%2d %3d %2d:%2d:%2d.%3ld%c%c%c", 584 &synchar, &qualchar, &pp->year, &pp->day, 585 &pp->hour, &pp->minute, &pp->second, &pp->nsec, 586 &dstchar, &leapchar, &dstchar) != 11) { 587 refclock_report(peer, CEVNT_BADREPLY); 588 return; 589 } 590 pp->nsec *= 1000000; 591 pp->leap = LEAP_NOWARNING; 592 if (synchar != ' ') 593 pp->leap = LEAP_NOTINSYNC; 594 else if (leapchar == 'L') 595 pp->leap = LEAP_ADDSECOND; 596 memcpy(&pp->refid, REFWWVB, 4); 597 if (up->msgcnt == 0) 598 record_clock_stats(&peer->srcadr, str); 599 up->msgcnt++; 600 break; 601 602 /* 603 * None of the above. Just forget about it and wait for the next 604 * message or timeout. 605 */ 606 default: 607 return; 608 } 609 610 /* 611 * We have a valid timecode. The fudge time1 value is added to 612 * each sample by the main line routines. Note that in current 613 * telephone networks the propatation time can be different for 614 * each call and can reach 200 ms for some calls. 615 */ 616 peer->refid = pp->refid; 617 pp->lastrec = up->tstamp; 618 if (!refclock_process(pp)) { 619 refclock_report(peer, CEVNT_BADTIME); 620 return; 621 } 622 pp->lastref = pp->lastrec; 623 if (up->state != S_MSG) { 624 up->state = S_MSG; 625 up->timer = TIMECODE; 626 } 627} 628 629 630/* 631 * acts_poll - called by the transmit routine 632 */ 633static void 634acts_poll ( 635 int unit, 636 struct peer *peer 637 ) 638{ 639 struct actsunit *up; 640 struct refclockproc *pp; 641 642 /* 643 * This routine is called at every system poll. All it does is 644 * set flag1 under certain conditions. The real work is done by 645 * the timeout routine and state machine. 646 */ 647 pp = peer->procptr; 648 up = (struct actsunit *)pp->unitptr; 649 switch (peer->ttl) { 650 651 /* 652 * In manual mode the calling program is activated by the ntpdc 653 * program using the enable flag (fudge flag1), either manually 654 * or by a cron job. 655 */ 656 case MODE_MANUAL: 657 /* fall through */ 658 break; 659 660 /* 661 * In automatic mode the calling program runs continuously at 662 * intervals determined by the poll event or specified timeout. 663 */ 664 case MODE_AUTO: 665 pp->sloppyclockflag |= CLK_FLAG1; 666 break; 667 668 /* 669 * In backup mode the calling program runs continuously as long 670 * as either no peers are available or this peer is selected. 671 */ 672 case MODE_BACKUP: 673 if (sys_peer == NULL || sys_peer == peer) 674 pp->sloppyclockflag |= CLK_FLAG1; 675 break; 676 } 677} 678 679 680/* 681 * acts_timer - called at one-second intervals 682 */ 683static void 684acts_timer( 685 int unit, 686 struct peer *peer 687 ) 688{ 689 struct actsunit *up; 690 struct refclockproc *pp; 691 692 /* 693 * This routine implments a timeout which runs for a programmed 694 * interval. The counter is initialized by the state machine and 695 * counts down to zero. Upon reaching zero, the state machine is 696 * called. If flag1 is set while in S_IDLE state, force a 697 * timeout. 698 */ 699 pp = peer->procptr; 700 up = (struct actsunit *)pp->unitptr; 701 if (pp->sloppyclockflag & CLK_FLAG1 && up->state == S_IDLE) { 702 acts_timeout(peer); 703 return; 704 } 705 if (up->timer == 0) 706 return; 707 708 up->timer--; 709 if (up->timer == 0) 710 acts_timeout(peer); 711} 712 713 714/* 715 * acts_timeout - called on timeout 716 */ 717static void 718acts_timeout( 719 struct peer *peer 720 ) 721{ 722 struct actsunit *up; 723 struct refclockproc *pp; 724 int fd; 725 char device[20]; 726 char lockfile[128], pidbuf[8]; 727 char tbuf[SMAX]; 728 729 /* 730 * The state machine is driven by messages from the modem, when 731 * first stated and at timeout. 732 */ 733 pp = peer->procptr; 734 up = (struct actsunit *)pp->unitptr; 735 pp->sloppyclockflag &= ~CLK_FLAG1; 736 if (sys_phone[up->retry] == NULL && !(pp->sloppyclockflag & 737 CLK_FLAG3)) { 738 msyslog(LOG_ERR, "acts: no phones"); 739 return; 740 } 741 switch(up->state) { 742 743 /* 744 * System poll event. Lock the modem port and open the device. 745 */ 746 case S_IDLE: 747 748 /* 749 * Lock the modem port. If busy, retry later. Note: if 750 * something fails between here and the close, the lock 751 * file may not be removed. 752 */ 753 if (pp->sloppyclockflag & CLK_FLAG2) { 754 snprintf(lockfile, sizeof(lockfile), LOCKFILE, 755 up->unit); 756 fd = open(lockfile, O_WRONLY | O_CREAT | O_EXCL, 757 0644); 758 if (fd < 0) { 759 msyslog(LOG_ERR, "acts: port busy"); 760 return; 761 } 762 snprintf(pidbuf, sizeof(pidbuf), "%d\n", 763 (u_int)getpid()); 764 write(fd, pidbuf, strlen(pidbuf)); 765 close(fd); 766 } 767 768 /* 769 * Open the device in raw mode and link the I/O. 770 */ 771 if (!pp->io.fd) { 772 snprintf(device, sizeof(device), DEVICE, 773 up->unit); 774 fd = refclock_open(device, SPEED232, 775 LDISC_ACTS | LDISC_RAW | LDISC_REMOTE); 776 if (fd == 0) { 777 msyslog(LOG_ERR, 778 "acts: open fails"); 779 return; 780 } 781 pp->io.fd = fd; 782 if (!io_addclock(&pp->io)) { 783 msyslog(LOG_ERR, 784 "acts: addclock fails"); 785 close(fd); 786 pp->io.fd = 0; 787 return; 788 } 789 } 790 791 /* 792 * If the port is directly connected to the device, skip 793 * the modem business and send 'T' for Spectrabum. 794 */ 795 if (pp->sloppyclockflag & CLK_FLAG3) { 796 if (write(pp->io.fd, "T", 1) < 0) { 797 msyslog(LOG_ERR, "acts: write %m"); 798 return; 799 } 800 up->state = S_FIRST; 801 up->timer = CONNECT; 802 return; 803 } 804 805 /* 806 * Initialize the modem. This works with Hayes commands. 807 */ 808#ifdef DEBUG 809 if (debug) 810 printf("acts: setup %s\n", MODEM_SETUP); 811#endif 812 if (write(pp->io.fd, MODEM_SETUP, strlen(MODEM_SETUP)) < 813 0) { 814 msyslog(LOG_ERR, "acts: write %m"); 815 return; 816 } 817 up->state = S_OK; 818 up->timer = SETUP; 819 return; 820 821 /* 822 * In OK state the modem did not respond to setup. 823 */ 824 case S_OK: 825 msyslog(LOG_ERR, "acts: no modem"); 826 break; 827 828 /* 829 * In DTR state we are waiting for the modem to settle down 830 * before hammering it with a dial command. 831 */ 832 case S_DTR: 833 snprintf(tbuf, sizeof(tbuf), "DIAL #%d %s", up->retry, 834 sys_phone[up->retry]); 835 report_event(PEVNT_CLOCK, peer, tbuf); 836#ifdef DEBUG 837 if (debug) 838 printf("%s\n", tbuf); 839#endif 840 write(pp->io.fd, sys_phone[up->retry], 841 strlen(sys_phone[up->retry])); 842 write(pp->io.fd, "\r", 1); 843 up->state = S_CONNECT; 844 up->timer = ANSWER; 845 return; 846 847 /* 848 * In CONNECT state the call did not complete. 849 */ 850 case S_CONNECT: 851 msyslog(LOG_ERR, "acts: no answer"); 852 break; 853 854 /* 855 * In FIRST state no messages were received. 856 */ 857 case S_FIRST: 858 msyslog(LOG_ERR, "acts: no messages"); 859 break; 860 861 /* 862 * In CLOSE state hangup is complete. Close the doors and 863 * windows and get some air. 864 */ 865 case S_CLOSE: 866 867 /* 868 * Close the device and unlock a shared modem. 869 */ 870 if (pp->io.fd) { 871 io_closeclock(&pp->io); 872 close(pp->io.fd); 873 if (pp->sloppyclockflag & CLK_FLAG2) { 874 snprintf(lockfile, sizeof(lockfile), 875 LOCKFILE, up->unit); 876 unlink(lockfile); 877 } 878 pp->io.fd = 0; 879 } 880 881 /* 882 * If messages were received, fold the tent and wait for 883 * the next poll. If no messages and there are more 884 * numbers to dial, retry after a short wait. 885 */ 886 up->bufptr = pp->a_lastcode; 887 up->timer = 0; 888 up->state = S_IDLE; 889 if ( up->msgcnt == 0) { 890 up->retry++; 891 if (sys_phone[up->retry] == NULL) 892 up->retry = 0; 893 else 894 up->timer = SETUP; 895 } else { 896 up->retry = 0; 897 } 898 up->msgcnt = 0; 899 return; 900 } 901 acts_disc(peer); 902} 903 904 905/* 906 * acts_disc - disconnect the call and clean the place up. 907 */ 908static void 909acts_disc ( 910 struct peer *peer 911 ) 912{ 913 struct actsunit *up; 914 struct refclockproc *pp; 915 int dtr = TIOCM_DTR; 916 917 /* 918 * We get here if the call terminated successfully or if an 919 * error occured. If the median filter has something in it, 920 * feed the data to the clock filter. If a modem port, drop DTR 921 * to force command mode and send modem hangup. 922 */ 923 pp = peer->procptr; 924 up = (struct actsunit *)pp->unitptr; 925 if (up->msgcnt > 0) 926 refclock_receive(peer); 927 if (!(pp->sloppyclockflag & CLK_FLAG3)) { 928 ioctl(pp->io.fd, TIOCMBIC, (char *)&dtr); 929 write(pp->io.fd, MODEM_HANGUP, strlen(MODEM_HANGUP)); 930 } 931 up->timer = SETUP; 932 up->state = S_CLOSE; 933} 934#else 935int refclock_acts_bs; 936#endif /* REFCLOCK */ 937