Annotation of embedaddon/ntp/ntpd/refclock_hopfser.c, revision 1.1
1.1 ! misho 1: /*
! 2: *
! 3: * refclock_hopfser.c
! 4: * - clock driver for hopf serial boards (GPS or DCF77)
! 5: *
! 6: * Date: 30.03.2000 Revision: 01.10
! 7: *
! 8: * latest source and further information can be found at:
! 9: * http://www.ATLSoft.de/ntp
! 10: *
! 11: */
! 12:
! 13: #ifdef HAVE_CONFIG_H
! 14: # include "config.h"
! 15: #endif
! 16:
! 17: #if defined(REFCLOCK) && (defined(CLOCK_HOPF_SERIAL))
! 18:
! 19: #include "ntpd.h"
! 20: #include "ntp_io.h"
! 21: #include "ntp_control.h"
! 22: #include "ntp_refclock.h"
! 23: #include "ntp_unixtime.h"
! 24: #include "ntp_stdlib.h"
! 25:
! 26: #if defined HAVE_SYS_MODEM_H
! 27: # include <sys/modem.h>
! 28: # ifndef __QNXNTO__
! 29: # define TIOCMSET MCSETA
! 30: # define TIOCMGET MCGETA
! 31: # define TIOCM_RTS MRTS
! 32: # endif
! 33: #endif
! 34:
! 35: #ifdef HAVE_TERMIOS_H
! 36: # ifdef TERMIOS_NEEDS__SVID3
! 37: # define _SVID3
! 38: # endif
! 39: # include <termios.h>
! 40: # ifdef TERMIOS_NEEDS__SVID3
! 41: # undef _SVID3
! 42: # endif
! 43: #endif
! 44:
! 45: #ifdef HAVE_SYS_IOCTL_H
! 46: # include <sys/ioctl.h>
! 47: #endif
! 48:
! 49: #ifdef SYS_WINNT
! 50: extern int async_write(int, const void *, unsigned int);
! 51: #undef write
! 52: #define write(fd, data, octets) async_write(fd, data, octets)
! 53: #endif
! 54:
! 55: /*
! 56: * clock definitions
! 57: */
! 58: #define DESCRIPTION "hopf Elektronik serial clock" /* Long name */
! 59: #define PRECISION (-10) /* precision assumed (about 1 ms) */
! 60: #define REFID "hopf\0" /* reference ID */
! 61: /*
! 62: * I/O definitions
! 63: */
! 64: #define DEVICE "/dev/hopfclock%d" /* device name and unit */
! 65: #define SPEED232 B9600 /* uart speed (9600 baud) */
! 66:
! 67:
! 68: #define STX 0x02
! 69: #define ETX 0x03
! 70: #define CR 0x0c
! 71: #define LF 0x0a
! 72:
! 73: /* parse states */
! 74: #define REC_QUEUE_EMPTY 0
! 75: #define REC_QUEUE_FULL 1
! 76:
! 77: #define HOPF_OPMODE 0x0C /* operation mode mask */
! 78: #define HOPF_INVALID 0x00 /* no time code available */
! 79: #define HOPF_INTERNAL 0x04 /* internal clock */
! 80: #define HOPF_RADIO 0x08 /* radio clock */
! 81: #define HOPF_RADIOHP 0x0C /* high precision radio clock */
! 82:
! 83: /*
! 84: * hopfclock unit control structure.
! 85: */
! 86: struct hopfclock_unit {
! 87: l_fp laststamp; /* last receive timestamp */
! 88: short unit; /* NTP refclock unit number */
! 89: u_long polled; /* flag to detect noreplies */
! 90: char leap_status; /* leap second flag */
! 91: int rpt_next;
! 92: };
! 93:
! 94: /*
! 95: * Function prototypes
! 96: */
! 97:
! 98: static int hopfserial_start (int, struct peer *);
! 99: static void hopfserial_shutdown (int, struct peer *);
! 100: static void hopfserial_receive (struct recvbuf *);
! 101: static void hopfserial_poll (int, struct peer *);
! 102: /* static void hopfserial_io (struct recvbuf *); */
! 103: /*
! 104: * Transfer vector
! 105: */
! 106: struct refclock refclock_hopfser = {
! 107: hopfserial_start, /* start up driver */
! 108: hopfserial_shutdown, /* shut down driver */
! 109: hopfserial_poll, /* transmit poll message */
! 110: noentry, /* not used */
! 111: noentry, /* initialize driver (not used) */
! 112: noentry, /* not used */
! 113: NOFLAGS /* not used */
! 114: };
! 115:
! 116: /*
! 117: * hopfserial_start - open the devices and initialize data for processing
! 118: */
! 119: static int
! 120: hopfserial_start (
! 121: int unit,
! 122: struct peer *peer
! 123: )
! 124: {
! 125: register struct hopfclock_unit *up;
! 126: struct refclockproc *pp;
! 127: int fd;
! 128: char gpsdev[20];
! 129:
! 130: snprintf(gpsdev, sizeof(gpsdev), DEVICE, unit);
! 131:
! 132: /* LDISC_STD, LDISC_RAW
! 133: * Open serial port. Use CLK line discipline, if available.
! 134: */
! 135: fd = refclock_open(gpsdev, SPEED232, LDISC_CLK);
! 136: if (fd <= 0) {
! 137: #ifdef DEBUG
! 138: printf("hopfSerialClock(%d) start: open %s failed\n", unit, gpsdev);
! 139: #endif
! 140: return 0;
! 141: }
! 142:
! 143: msyslog(LOG_NOTICE, "hopfSerialClock(%d) fd: %d dev: %s", unit, fd,
! 144: gpsdev);
! 145:
! 146: /*
! 147: * Allocate and initialize unit structure
! 148: */
! 149: up = emalloc(sizeof(*up));
! 150: memset(up, 0, sizeof(*up));
! 151: pp = peer->procptr;
! 152: pp->unitptr = (caddr_t)up;
! 153: pp->io.clock_recv = hopfserial_receive;
! 154: pp->io.srcclock = (caddr_t)peer;
! 155: pp->io.datalen = 0;
! 156: pp->io.fd = fd;
! 157: if (!io_addclock(&pp->io)) {
! 158: #ifdef DEBUG
! 159: printf("hopfSerialClock(%d) io_addclock\n", unit);
! 160: #endif
! 161: close(fd);
! 162: pp->io.fd = -1;
! 163: free(up);
! 164: pp->unitptr = NULL;
! 165: return (0);
! 166: }
! 167:
! 168: /*
! 169: * Initialize miscellaneous variables
! 170: */
! 171: pp->clockdesc = DESCRIPTION;
! 172: peer->precision = PRECISION;
! 173: peer->burst = NSTAGE;
! 174: memcpy((char *)&pp->refid, REFID, 4);
! 175:
! 176: up->leap_status = 0;
! 177: up->unit = (short) unit;
! 178:
! 179: return (1);
! 180: }
! 181:
! 182:
! 183: /*
! 184: * hopfserial_shutdown - shut down the clock
! 185: */
! 186: static void
! 187: hopfserial_shutdown (
! 188: int unit,
! 189: struct peer *peer
! 190: )
! 191: {
! 192: register struct hopfclock_unit *up;
! 193: struct refclockproc *pp;
! 194:
! 195: pp = peer->procptr;
! 196: up = (struct hopfclock_unit *)pp->unitptr;
! 197:
! 198: if (-1 != pp->io.fd)
! 199: io_closeclock(&pp->io);
! 200: if (NULL != up)
! 201: free(up);
! 202: }
! 203:
! 204:
! 205:
! 206: /*
! 207: * hopfserial_receive - receive data from the serial interface
! 208: */
! 209:
! 210: static void
! 211: hopfserial_receive (
! 212: struct recvbuf *rbufp
! 213: )
! 214: {
! 215: struct hopfclock_unit *up;
! 216: struct refclockproc *pp;
! 217: struct peer *peer;
! 218:
! 219: int synch; /* synchhronization indicator */
! 220: int DoW; /* Dow */
! 221:
! 222: int day, month; /* ddd conversion */
! 223:
! 224: /*
! 225: * Initialize pointers and read the timecode and timestamp.
! 226: */
! 227: peer = (struct peer *)rbufp->recv_srcclock;
! 228: pp = peer->procptr;
! 229: up = (struct hopfclock_unit *)pp->unitptr;
! 230:
! 231: if (up->rpt_next == 0 )
! 232: return;
! 233:
! 234:
! 235: up->rpt_next = 0; /* wait until next poll interval occur */
! 236:
! 237: pp->lencode = (u_short)refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
! 238:
! 239: if (pp->lencode == 0)
! 240: return;
! 241:
! 242: sscanf(pp->a_lastcode,
! 243: #if 1
! 244: "%1x%1x%2d%2d%2d%2d%2d%2d", /* ...cr,lf */
! 245: #else
! 246: "%*c%1x%1x%2d%2d%2d%2d%2d%2d", /* stx...cr,lf,etx */
! 247: #endif
! 248: &synch,
! 249: &DoW,
! 250: &pp->hour,
! 251: &pp->minute,
! 252: &pp->second,
! 253: &day,
! 254: &month,
! 255: &pp->year);
! 256:
! 257:
! 258: /*
! 259: Validate received values at least enough to prevent internal
! 260: array-bounds problems, etc.
! 261: */
! 262: if((pp->hour < 0) || (pp->hour > 23) ||
! 263: (pp->minute < 0) || (pp->minute > 59) ||
! 264: (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ ||
! 265: (day < 1) || (day > 31) ||
! 266: (month < 1) || (month > 12) ||
! 267: (pp->year < 0) || (pp->year > 99)) {
! 268: /* Data out of range. */
! 269: refclock_report(peer, CEVNT_BADREPLY);
! 270: return;
! 271: }
! 272: /*
! 273: some preparations
! 274: */
! 275: pp->day = ymd2yd(pp->year,month,day);
! 276: pp->leap=0;
! 277:
! 278: /* Year-2000 check! */
! 279: /* wrap 2-digit date into 4-digit */
! 280:
! 281: if(pp->year < YEAR_PIVOT) { pp->year += 100; } /* < 98 */
! 282: pp->year += 1900;
! 283:
! 284: /* preparation for timecode ntpq rl command ! */
! 285:
! 286: #if 0
! 287: snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
! 288: "STATUS: %1X%1X, DATE: %02d.%02d.%04d TIME: %02d:%02d:%02d",
! 289: synch,
! 290: DoW,
! 291: day,
! 292: month,
! 293: pp->year,
! 294: pp->hour,
! 295: pp->minute,
! 296: pp->second);
! 297:
! 298: pp->lencode = strlen(pp->a_lastcode);
! 299: if ((synch && 0xc) == 0 ){ /* time ok? */
! 300: refclock_report(peer, CEVNT_BADTIME);
! 301: pp->leap = LEAP_NOTINSYNC;
! 302: return;
! 303: }
! 304: #endif
! 305: /*
! 306: * If clock has no valid status then report error and exit
! 307: */
! 308: if ((synch & HOPF_OPMODE) == HOPF_INVALID ){ /* time ok? */
! 309: refclock_report(peer, CEVNT_BADTIME);
! 310: pp->leap = LEAP_NOTINSYNC;
! 311: return;
! 312: }
! 313:
! 314: /*
! 315: * Test if time is running on internal quarz
! 316: * if CLK_FLAG1 is set, sychronize even if no radio operation
! 317: */
! 318:
! 319: if ((synch & HOPF_OPMODE) == HOPF_INTERNAL){
! 320: if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
! 321: refclock_report(peer, CEVNT_BADTIME);
! 322: pp->leap = LEAP_NOTINSYNC;
! 323: return;
! 324: }
! 325: }
! 326:
! 327:
! 328: if (!refclock_process(pp)) {
! 329: refclock_report(peer, CEVNT_BADTIME);
! 330: return;
! 331: }
! 332: pp->lastref = pp->lastrec;
! 333: refclock_receive(peer);
! 334:
! 335: #if 0
! 336: msyslog(LOG_ERR, " D:%x D:%d D:%d",synch,pp->minute,pp->second);
! 337: #endif
! 338:
! 339: record_clock_stats(&peer->srcadr, pp->a_lastcode);
! 340:
! 341: return;
! 342: }
! 343:
! 344:
! 345: /*
! 346: * hopfserial_poll - called by the transmit procedure
! 347: *
! 348: */
! 349: static void
! 350: hopfserial_poll (
! 351: int unit,
! 352: struct peer *peer
! 353: )
! 354: {
! 355: register struct hopfclock_unit *up;
! 356: struct refclockproc *pp;
! 357: pp = peer->procptr;
! 358:
! 359: up = (struct hopfclock_unit *)pp->unitptr;
! 360:
! 361: pp->polls++;
! 362: up->rpt_next = 1;
! 363:
! 364: #if 0
! 365: record_clock_stats(&peer->srcadr, pp->a_lastcode);
! 366: #endif
! 367:
! 368: return;
! 369: }
! 370:
! 371: #else
! 372: int refclock_hopfser_bs;
! 373: #endif /* REFCLOCK */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>