154359Sroberto/* 254359Sroberto * refclock_leitch - clock driver for the Leitch CSD-5300 Master Clock 354359Sroberto */ 482498Sroberto 554359Sroberto#ifdef HAVE_CONFIG_H 682498Sroberto# include <config.h> 754359Sroberto#endif 854359Sroberto 9290001Sglebius#include "ntp_types.h" 10290001Sglebius 1154359Sroberto#if defined(REFCLOCK) && defined(CLOCK_LEITCH) 1254359Sroberto 13290001Sglebius#include <stdio.h> 14290001Sglebius#include <ctype.h> 15290001Sglebius 1654359Sroberto#include "ntpd.h" 1754359Sroberto#include "ntp_io.h" 1854359Sroberto#include "ntp_refclock.h" 19290001Sglebius#include "timevalops.h" 2054359Sroberto#include "ntp_stdlib.h" 2154359Sroberto 2254359Sroberto 2354359Sroberto/* 2454359Sroberto * Driver for Leitch CSD-5300 Master Clock System 2554359Sroberto * 2654359Sroberto * COMMANDS: 2754359Sroberto * DATE: D <CR> 2854359Sroberto * TIME: T <CR> 2954359Sroberto * STATUS: S <CR> 3054359Sroberto * LOOP: L <CR> 3154359Sroberto * 3254359Sroberto * FORMAT: 3354359Sroberto * DATE: YYMMDD<CR> 3454359Sroberto * TIME: <CR>/HHMMSS <CR>/HHMMSS <CR>/HHMMSS <CR>/ 3554359Sroberto * second bondaried on the stop bit of the <CR> 3654359Sroberto * second boundaries at '/' above. 3754359Sroberto * STATUS: G (good), D (diag fail), T (time not provided) or 3854359Sroberto * P (last phone update failed) 3954359Sroberto */ 40290001Sglebius#define PRECISION (-20) /* 1x10-8 */ 4154359Sroberto#define MAXUNITS 1 /* max number of LEITCH units */ 4254359Sroberto#define LEITCHREFID "ATOM" /* reference id */ 4354359Sroberto#define LEITCH_DESCRIPTION "Leitch: CSD 5300 Master Clock System Driver" 4454359Sroberto#define LEITCH232 "/dev/leitch%d" /* name of radio device */ 4554359Sroberto#define SPEED232 B300 /* uart speed (300 baud) */ 46182007Sroberto#ifdef DEBUG 4754359Sroberto#define leitch_send(A,M) \ 4854359Srobertoif (debug) fprintf(stderr,"write leitch %s\n",M); \ 4954359Srobertoif ((write(A->leitchio.fd,M,sizeof(M)) < 0)) {\ 50182007Sroberto if (debug) \ 51182007Sroberto fprintf(stderr, "leitch_send: unit %d send failed\n", A->unit); \ 52182007Sroberto else \ 53182007Sroberto msyslog(LOG_ERR, "leitch_send: unit %d send failed %m",A->unit);} 54182007Sroberto#else 55182007Sroberto#define leitch_send(A,M) \ 56182007Srobertoif ((write(A->leitchio.fd,M,sizeof(M)) < 0)) {\ 57182007Sroberto msyslog(LOG_ERR, "leitch_send: unit %d send failed %m",A->unit);} 58182007Sroberto#endif 59182007Sroberto 6054359Sroberto#define STATE_IDLE 0 6154359Sroberto#define STATE_DATE 1 6254359Sroberto#define STATE_TIME1 2 6354359Sroberto#define STATE_TIME2 3 6454359Sroberto#define STATE_TIME3 4 6554359Sroberto 6654359Sroberto/* 6754359Sroberto * LEITCH unit control structure 6854359Sroberto */ 6954359Srobertostruct leitchunit { 7054359Sroberto struct peer *peer; 7154359Sroberto struct refclockio leitchio; 7254359Sroberto u_char unit; 7354359Sroberto short year; 7454359Sroberto short yearday; 7554359Sroberto short month; 7654359Sroberto short day; 7754359Sroberto short hour; 7854359Sroberto short second; 7954359Sroberto short minute; 8054359Sroberto short state; 8154359Sroberto u_short fudge1; 8254359Sroberto l_fp reftime1; 8354359Sroberto l_fp reftime2; 8454359Sroberto l_fp reftime3; 8554359Sroberto l_fp codetime1; 8654359Sroberto l_fp codetime2; 8754359Sroberto l_fp codetime3; 8854359Sroberto u_long yearstart; 8954359Sroberto}; 9054359Sroberto 9154359Sroberto/* 9254359Sroberto * Function prototypes 9354359Sroberto */ 94290001Sglebiusstatic void leitch_init (void); 95290001Sglebiusstatic int leitch_start (int, struct peer *); 96290001Sglebiusstatic void leitch_shutdown (int, struct peer *); 97290001Sglebiusstatic void leitch_poll (int, struct peer *); 98290001Sglebiusstatic void leitch_control (int, const struct refclockstat *, struct refclockstat *, struct peer *); 9954359Sroberto#define leitch_buginfo noentry 100290001Sglebiusstatic void leitch_receive (struct recvbuf *); 101290001Sglebiusstatic void leitch_process (struct leitchunit *); 10254359Sroberto#if 0 103290001Sglebiusstatic void leitch_timeout (struct peer *); 10454359Sroberto#endif 105290001Sglebiusstatic int leitch_get_date (struct recvbuf *, struct leitchunit *); 106290001Sglebiusstatic int leitch_get_time (struct recvbuf *, struct leitchunit *, int); 107290001Sglebiusstatic int days_per_year (int); 10854359Sroberto 10954359Srobertostatic struct leitchunit leitchunits[MAXUNITS]; 11054359Srobertostatic u_char unitinuse[MAXUNITS]; 11154359Srobertostatic u_char stratumtouse[MAXUNITS]; 11254359Srobertostatic u_int32 refid[MAXUNITS]; 11354359Sroberto 11454359Srobertostatic char days_in_month [] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 11554359Sroberto 11654359Sroberto/* 11754359Sroberto * Transfer vector 11854359Sroberto */ 11954359Srobertostruct refclock refclock_leitch = { 12054359Sroberto leitch_start, leitch_shutdown, leitch_poll, 12154359Sroberto leitch_control, leitch_init, leitch_buginfo, NOFLAGS 12254359Sroberto}; 12354359Sroberto 12454359Sroberto/* 12554359Sroberto * leitch_init - initialize internal leitch driver data 12654359Sroberto */ 12754359Srobertostatic void 12854359Srobertoleitch_init(void) 12954359Sroberto{ 13054359Sroberto int i; 13154359Sroberto 13254359Sroberto memset((char*)leitchunits, 0, sizeof(leitchunits)); 13354359Sroberto memset((char*)unitinuse, 0, sizeof(unitinuse)); 13454359Sroberto for (i = 0; i < MAXUNITS; i++) 13554359Sroberto memcpy((char *)&refid[i], LEITCHREFID, 4); 13654359Sroberto} 13754359Sroberto 13854359Sroberto/* 13954359Sroberto * leitch_shutdown - shut down a LEITCH clock 14054359Sroberto */ 14154359Srobertostatic void 14254359Srobertoleitch_shutdown( 14354359Sroberto int unit, 14454359Sroberto struct peer *peer 14554359Sroberto ) 14654359Sroberto{ 147290001Sglebius struct leitchunit *leitch; 148290001Sglebius 149290001Sglebius if (unit >= MAXUNITS) { 150290001Sglebius return; 151290001Sglebius } 152290001Sglebius leitch = &leitchunits[unit]; 153290001Sglebius if (-1 != leitch->leitchio.fd) 154290001Sglebius io_closeclock(&leitch->leitchio); 15554359Sroberto#ifdef DEBUG 15654359Sroberto if (debug) 157290001Sglebius fprintf(stderr, "leitch_shutdown()\n"); 15854359Sroberto#endif 15954359Sroberto} 16054359Sroberto 16154359Sroberto/* 16254359Sroberto * leitch_poll - called by the transmit procedure 16354359Sroberto */ 16454359Srobertostatic void 16554359Srobertoleitch_poll( 16654359Sroberto int unit, 16754359Sroberto struct peer *peer 16854359Sroberto ) 16954359Sroberto{ 17054359Sroberto struct leitchunit *leitch; 17154359Sroberto 17254359Sroberto /* start the state machine rolling */ 17354359Sroberto 17454359Sroberto#ifdef DEBUG 17554359Sroberto if (debug) 17654359Sroberto fprintf(stderr, "leitch_poll()\n"); 17754359Sroberto#endif 178182007Sroberto if (unit >= MAXUNITS) { 17954359Sroberto /* XXXX syslog it */ 18054359Sroberto return; 18154359Sroberto } 18254359Sroberto 18354359Sroberto leitch = &leitchunits[unit]; 18454359Sroberto 18554359Sroberto if (leitch->state != STATE_IDLE) { 18654359Sroberto /* reset and wait for next poll */ 18754359Sroberto /* XXXX syslog it */ 18854359Sroberto leitch->state = STATE_IDLE; 18954359Sroberto } else { 19054359Sroberto leitch_send(leitch,"D\r"); 19154359Sroberto leitch->state = STATE_DATE; 19254359Sroberto } 19354359Sroberto} 19454359Sroberto 19554359Srobertostatic void 19654359Srobertoleitch_control( 19754359Sroberto int unit, 198290001Sglebius const struct refclockstat *in, 19954359Sroberto struct refclockstat *out, 20054359Sroberto struct peer *passed_peer 20154359Sroberto ) 20254359Sroberto{ 20354359Sroberto if (unit >= MAXUNITS) { 20454359Sroberto msyslog(LOG_ERR, 20554359Sroberto "leitch_control: unit %d invalid", unit); 20654359Sroberto return; 20754359Sroberto } 20854359Sroberto 20954359Sroberto if (in) { 21054359Sroberto if (in->haveflags & CLK_HAVEVAL1) 21154359Sroberto stratumtouse[unit] = (u_char)(in->fudgeval1); 21254359Sroberto if (in->haveflags & CLK_HAVEVAL2) 21354359Sroberto refid[unit] = in->fudgeval2; 21454359Sroberto if (unitinuse[unit]) { 21554359Sroberto struct peer *peer; 21654359Sroberto 21754359Sroberto peer = (&leitchunits[unit])->peer; 21854359Sroberto peer->stratum = stratumtouse[unit]; 21954359Sroberto peer->refid = refid[unit]; 22054359Sroberto } 22154359Sroberto } 22254359Sroberto 22354359Sroberto if (out) { 22454359Sroberto memset((char *)out, 0, sizeof (struct refclockstat)); 22554359Sroberto out->type = REFCLK_ATOM_LEITCH; 22654359Sroberto out->haveflags = CLK_HAVEVAL1 | CLK_HAVEVAL2; 22754359Sroberto out->fudgeval1 = (int32)stratumtouse[unit]; 22854359Sroberto out->fudgeval2 = refid[unit]; 22954359Sroberto out->p_lastcode = ""; 23054359Sroberto out->clockdesc = LEITCH_DESCRIPTION; 23154359Sroberto } 23254359Sroberto} 23354359Sroberto 23454359Sroberto/* 23554359Sroberto * leitch_start - open the LEITCH devices and initialize data for processing 23654359Sroberto */ 23754359Srobertostatic int 23854359Srobertoleitch_start( 23954359Sroberto int unit, 24054359Sroberto struct peer *peer 24154359Sroberto ) 24254359Sroberto{ 24354359Sroberto struct leitchunit *leitch; 24454359Sroberto int fd232; 24554359Sroberto char leitchdev[20]; 24654359Sroberto 24754359Sroberto /* 24854359Sroberto * Check configuration info. 24954359Sroberto */ 25054359Sroberto if (unit >= MAXUNITS) { 25154359Sroberto msyslog(LOG_ERR, "leitch_start: unit %d invalid", unit); 25254359Sroberto return (0); 25354359Sroberto } 25454359Sroberto 25554359Sroberto if (unitinuse[unit]) { 25654359Sroberto msyslog(LOG_ERR, "leitch_start: unit %d in use", unit); 25754359Sroberto return (0); 25854359Sroberto } 25954359Sroberto 26054359Sroberto /* 26154359Sroberto * Open serial port. 26254359Sroberto */ 263290001Sglebius snprintf(leitchdev, sizeof(leitchdev), LEITCH232, unit); 26454359Sroberto fd232 = open(leitchdev, O_RDWR, 0777); 26554359Sroberto if (fd232 == -1) { 26654359Sroberto msyslog(LOG_ERR, 26754359Sroberto "leitch_start: open of %s: %m", leitchdev); 26854359Sroberto return (0); 26954359Sroberto } 27054359Sroberto 27154359Sroberto leitch = &leitchunits[unit]; 272290001Sglebius memset(leitch, 0, sizeof(*leitch)); 27354359Sroberto 27454359Sroberto#if defined(HAVE_SYSV_TTYS) 27554359Sroberto /* 27654359Sroberto * System V serial line parameters (termio interface) 27754359Sroberto * 27854359Sroberto */ 27954359Sroberto { struct termio ttyb; 28054359Sroberto if (ioctl(fd232, TCGETA, &ttyb) < 0) { 28154359Sroberto msyslog(LOG_ERR, 28254359Sroberto "leitch_start: ioctl(%s, TCGETA): %m", leitchdev); 28354359Sroberto goto screwed; 28454359Sroberto } 28554359Sroberto ttyb.c_iflag = IGNBRK|IGNPAR|ICRNL; 28654359Sroberto ttyb.c_oflag = 0; 28754359Sroberto ttyb.c_cflag = SPEED232|CS8|CLOCAL|CREAD; 28854359Sroberto ttyb.c_lflag = ICANON; 28954359Sroberto ttyb.c_cc[VERASE] = ttyb.c_cc[VKILL] = '\0'; 29054359Sroberto if (ioctl(fd232, TCSETA, &ttyb) < 0) { 29154359Sroberto msyslog(LOG_ERR, 29254359Sroberto "leitch_start: ioctl(%s, TCSETA): %m", leitchdev); 29354359Sroberto goto screwed; 29454359Sroberto } 29554359Sroberto } 29654359Sroberto#endif /* HAVE_SYSV_TTYS */ 29754359Sroberto#if defined(HAVE_TERMIOS) 29854359Sroberto /* 29954359Sroberto * POSIX serial line parameters (termios interface) 30054359Sroberto */ 30154359Sroberto { struct termios ttyb, *ttyp; 30254359Sroberto 30354359Sroberto ttyp = &ttyb; 30454359Sroberto if (tcgetattr(fd232, ttyp) < 0) { 30554359Sroberto msyslog(LOG_ERR, 30654359Sroberto "leitch_start: tcgetattr(%s): %m", leitchdev); 30754359Sroberto goto screwed; 30854359Sroberto } 30954359Sroberto ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL; 31054359Sroberto ttyp->c_oflag = 0; 31154359Sroberto ttyp->c_cflag = SPEED232|CS8|CLOCAL|CREAD; 31254359Sroberto ttyp->c_lflag = ICANON; 31354359Sroberto ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0'; 31454359Sroberto if (tcsetattr(fd232, TCSANOW, ttyp) < 0) { 31554359Sroberto msyslog(LOG_ERR, 31654359Sroberto "leitch_start: tcsetattr(%s): %m", leitchdev); 31754359Sroberto goto screwed; 31854359Sroberto } 31954359Sroberto if (tcflush(fd232, TCIOFLUSH) < 0) { 32054359Sroberto msyslog(LOG_ERR, 32154359Sroberto "leitch_start: tcflush(%s): %m", leitchdev); 32254359Sroberto goto screwed; 32354359Sroberto } 32454359Sroberto } 32554359Sroberto#endif /* HAVE_TERMIOS */ 32654359Sroberto#if defined(HAVE_BSD_TTYS) 32754359Sroberto /* 32854359Sroberto * 4.3bsd serial line parameters (sgttyb interface) 32954359Sroberto */ 330290001Sglebius { 331290001Sglebius struct sgttyb ttyb; 33254359Sroberto 33354359Sroberto if (ioctl(fd232, TIOCGETP, &ttyb) < 0) { 33454359Sroberto msyslog(LOG_ERR, 33554359Sroberto "leitch_start: ioctl(%s, TIOCGETP): %m", leitchdev); 33654359Sroberto goto screwed; 33754359Sroberto } 33854359Sroberto ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232; 33954359Sroberto ttyb.sg_erase = ttyb.sg_kill = '\0'; 34054359Sroberto ttyb.sg_flags = EVENP|ODDP|CRMOD; 34154359Sroberto if (ioctl(fd232, TIOCSETP, &ttyb) < 0) { 34254359Sroberto msyslog(LOG_ERR, 34354359Sroberto "leitch_start: ioctl(%s, TIOCSETP): %m", leitchdev); 34454359Sroberto goto screwed; 34554359Sroberto } 34654359Sroberto } 34754359Sroberto#endif /* HAVE_BSD_TTYS */ 34854359Sroberto 34954359Sroberto /* 35054359Sroberto * Set up the structures 35154359Sroberto */ 35254359Sroberto leitch->peer = peer; 35354359Sroberto leitch->unit = unit; 35454359Sroberto leitch->state = STATE_IDLE; 35554359Sroberto leitch->fudge1 = 15; /* 15ms */ 35654359Sroberto 35754359Sroberto leitch->leitchio.clock_recv = leitch_receive; 358290001Sglebius leitch->leitchio.srcclock = peer; 35954359Sroberto leitch->leitchio.datalen = 0; 36054359Sroberto leitch->leitchio.fd = fd232; 36154359Sroberto if (!io_addclock(&leitch->leitchio)) { 362290001Sglebius leitch->leitchio.fd = -1; 36354359Sroberto goto screwed; 36454359Sroberto } 36554359Sroberto 36654359Sroberto /* 36754359Sroberto * All done. Initialize a few random peer variables, then 36854359Sroberto * return success. 36954359Sroberto */ 370290001Sglebius peer->precision = PRECISION; 37154359Sroberto peer->stratum = stratumtouse[unit]; 37254359Sroberto peer->refid = refid[unit]; 37354359Sroberto unitinuse[unit] = 1; 37454359Sroberto return(1); 37554359Sroberto 37654359Sroberto /* 37754359Sroberto * Something broke; abandon ship. 37854359Sroberto */ 37954359Sroberto screwed: 38054359Sroberto close(fd232); 38154359Sroberto return(0); 38254359Sroberto} 38354359Sroberto 38454359Sroberto/* 38554359Sroberto * leitch_receive - receive data from the serial interface on a leitch 38654359Sroberto * clock 38754359Sroberto */ 38854359Srobertostatic void 38954359Srobertoleitch_receive( 39054359Sroberto struct recvbuf *rbufp 39154359Sroberto ) 39254359Sroberto{ 393290001Sglebius struct leitchunit *leitch = rbufp->recv_peer->procptr->unitptr; 39454359Sroberto 39554359Sroberto#ifdef DEBUG 39654359Sroberto if (debug) 39754359Sroberto fprintf(stderr, "leitch_recieve(%*.*s)\n", 39854359Sroberto rbufp->recv_length, rbufp->recv_length, 39954359Sroberto rbufp->recv_buffer); 40054359Sroberto#endif 40154359Sroberto if (rbufp->recv_length != 7) 40254359Sroberto return; /* The date is return with a trailing newline, 40354359Sroberto discard it. */ 40454359Sroberto 40554359Sroberto switch (leitch->state) { 40654359Sroberto case STATE_IDLE: /* unexpected, discard and resync */ 40754359Sroberto return; 40854359Sroberto case STATE_DATE: 40954359Sroberto if (!leitch_get_date(rbufp,leitch)) { 41054359Sroberto leitch->state = STATE_IDLE; 41154359Sroberto break; 41254359Sroberto } 41354359Sroberto leitch_send(leitch,"T\r"); 41454359Sroberto#ifdef DEBUG 41554359Sroberto if (debug) 41654359Sroberto fprintf(stderr, "%u\n",leitch->yearday); 41754359Sroberto#endif 41854359Sroberto leitch->state = STATE_TIME1; 41954359Sroberto break; 42054359Sroberto case STATE_TIME1: 42154359Sroberto if (!leitch_get_time(rbufp,leitch,1)) { 42254359Sroberto } 42354359Sroberto if (!clocktime(leitch->yearday,leitch->hour,leitch->minute, 42454359Sroberto leitch->second, 1, rbufp->recv_time.l_ui, 42554359Sroberto &leitch->yearstart, &leitch->reftime1.l_ui)) { 42654359Sroberto leitch->state = STATE_IDLE; 42754359Sroberto break; 42854359Sroberto } 429132451Sroberto leitch->reftime1.l_uf = 0; 43054359Sroberto#ifdef DEBUG 43154359Sroberto if (debug) 43254359Sroberto fprintf(stderr, "%lu\n", (u_long)leitch->reftime1.l_ui); 43354359Sroberto#endif 43454359Sroberto MSUTOTSF(leitch->fudge1, leitch->reftime1.l_uf); 43554359Sroberto leitch->codetime1 = rbufp->recv_time; 43654359Sroberto leitch->state = STATE_TIME2; 43754359Sroberto break; 43854359Sroberto case STATE_TIME2: 43954359Sroberto if (!leitch_get_time(rbufp,leitch,2)) { 44054359Sroberto } 44154359Sroberto if (!clocktime(leitch->yearday,leitch->hour,leitch->minute, 44254359Sroberto leitch->second, 1, rbufp->recv_time.l_ui, 44354359Sroberto &leitch->yearstart, &leitch->reftime2.l_ui)) { 44454359Sroberto leitch->state = STATE_IDLE; 44554359Sroberto break; 44654359Sroberto } 44754359Sroberto#ifdef DEBUG 44854359Sroberto if (debug) 44954359Sroberto fprintf(stderr, "%lu\n", (u_long)leitch->reftime2.l_ui); 45054359Sroberto#endif 45154359Sroberto MSUTOTSF(leitch->fudge1, leitch->reftime2.l_uf); 45254359Sroberto leitch->codetime2 = rbufp->recv_time; 45354359Sroberto leitch->state = STATE_TIME3; 45454359Sroberto break; 45554359Sroberto case STATE_TIME3: 45654359Sroberto if (!leitch_get_time(rbufp,leitch,3)) { 45754359Sroberto } 45854359Sroberto if (!clocktime(leitch->yearday,leitch->hour,leitch->minute, 45954359Sroberto leitch->second, GMT, rbufp->recv_time.l_ui, 46054359Sroberto &leitch->yearstart, &leitch->reftime3.l_ui)) { 46154359Sroberto leitch->state = STATE_IDLE; 46254359Sroberto break; 46354359Sroberto } 46454359Sroberto#ifdef DEBUG 46554359Sroberto if (debug) 46654359Sroberto fprintf(stderr, "%lu\n", (u_long)leitch->reftime3.l_ui); 46754359Sroberto#endif 46854359Sroberto MSUTOTSF(leitch->fudge1, leitch->reftime3.l_uf); 46954359Sroberto leitch->codetime3 = rbufp->recv_time; 47054359Sroberto leitch_process(leitch); 47154359Sroberto leitch->state = STATE_IDLE; 47254359Sroberto break; 47354359Sroberto default: 47454359Sroberto msyslog(LOG_ERR, 47554359Sroberto "leitech_receive: invalid state %d unit %d", 47654359Sroberto leitch->state, leitch->unit); 47754359Sroberto } 47854359Sroberto} 47954359Sroberto 48054359Sroberto/* 48154359Sroberto * leitch_process - process a pile of samples from the clock 48254359Sroberto * 48354359Sroberto * This routine uses a three-stage median filter to calculate offset and 48454359Sroberto * dispersion. reduce jitter. The dispersion is calculated as the span 48554359Sroberto * of the filter (max - min), unless the quality character (format 2) is 48654359Sroberto * non-blank, in which case the dispersion is calculated on the basis of 48754359Sroberto * the inherent tolerance of the internal radio oscillator, which is 48854359Sroberto * +-2e-5 according to the radio specifications. 48954359Sroberto */ 49054359Srobertostatic void 49154359Srobertoleitch_process( 49254359Sroberto struct leitchunit *leitch 49354359Sroberto ) 49454359Sroberto{ 49554359Sroberto l_fp off; 49654359Sroberto l_fp tmp_fp; 49754359Sroberto /*double doffset;*/ 49854359Sroberto 49954359Sroberto off = leitch->reftime1; 50054359Sroberto L_SUB(&off,&leitch->codetime1); 50154359Sroberto tmp_fp = leitch->reftime2; 50254359Sroberto L_SUB(&tmp_fp,&leitch->codetime2); 50354359Sroberto if (L_ISGEQ(&off,&tmp_fp)) 50454359Sroberto off = tmp_fp; 50554359Sroberto tmp_fp = leitch->reftime3; 50654359Sroberto L_SUB(&tmp_fp,&leitch->codetime3); 50754359Sroberto 50854359Sroberto if (L_ISGEQ(&off,&tmp_fp)) 50954359Sroberto off = tmp_fp; 51054359Sroberto /*LFPTOD(&off, doffset);*/ 51154359Sroberto refclock_receive(leitch->peer); 51254359Sroberto} 51354359Sroberto 51454359Sroberto/* 51554359Sroberto * days_per_year 51654359Sroberto */ 51754359Srobertostatic int 51854359Srobertodays_per_year( 51954359Sroberto int year 52054359Sroberto ) 52154359Sroberto{ 52254359Sroberto if (year%4) { /* not a potential leap year */ 52354359Sroberto return (365); 52454359Sroberto } else { 52554359Sroberto if (year % 100) { /* is a leap year */ 52654359Sroberto return (366); 52754359Sroberto } else { 52854359Sroberto if (year % 400) { 52954359Sroberto return (365); 53054359Sroberto } else { 53154359Sroberto return (366); 53254359Sroberto } 53354359Sroberto } 53454359Sroberto } 53554359Sroberto} 53654359Sroberto 53754359Srobertostatic int 53854359Srobertoleitch_get_date( 53954359Sroberto struct recvbuf *rbufp, 54054359Sroberto struct leitchunit *leitch 54154359Sroberto ) 54254359Sroberto{ 54354359Sroberto int i; 54454359Sroberto 54554359Sroberto if (rbufp->recv_length < 6) 54654359Sroberto return(0); 54754359Sroberto#undef BAD /* confict: defined as (-1) in AIX sys/param.h */ 54854359Sroberto#define BAD(A) (rbufp->recv_buffer[A] < '0') || (rbufp->recv_buffer[A] > '9') 54954359Sroberto if (BAD(0)||BAD(1)||BAD(2)||BAD(3)||BAD(4)||BAD(5)) 55054359Sroberto return(0); 55154359Sroberto#define ATOB(A) ((rbufp->recv_buffer[A])-'0') 55254359Sroberto leitch->year = ATOB(0)*10 + ATOB(1); 55354359Sroberto leitch->month = ATOB(2)*10 + ATOB(3); 55454359Sroberto leitch->day = ATOB(4)*10 + ATOB(5); 55554359Sroberto 55654359Sroberto /* sanity checks */ 55754359Sroberto if (leitch->month > 12) 55854359Sroberto return(0); 55954359Sroberto if (leitch->day > days_in_month[leitch->month-1]) 56054359Sroberto return(0); 56154359Sroberto 56254359Sroberto /* calculate yearday */ 56354359Sroberto i = 0; 56454359Sroberto leitch->yearday = leitch->day; 56554359Sroberto 56654359Sroberto while ( i < (leitch->month-1) ) 56754359Sroberto leitch->yearday += days_in_month[i++]; 56854359Sroberto 56954359Sroberto if ((days_per_year((leitch->year>90?1900:2000)+leitch->year)==365) && 57054359Sroberto leitch->month > 2) 57154359Sroberto leitch->yearday--; 57254359Sroberto 57354359Sroberto return(1); 57454359Sroberto} 57554359Sroberto 57654359Sroberto/* 57754359Sroberto * leitch_get_time 57854359Sroberto */ 57954359Srobertostatic int 58054359Srobertoleitch_get_time( 58154359Sroberto struct recvbuf *rbufp, 58254359Sroberto struct leitchunit *leitch, 58354359Sroberto int which 58454359Sroberto ) 58554359Sroberto{ 58654359Sroberto if (BAD(0)||BAD(1)||BAD(2)||BAD(3)||BAD(4)||BAD(5)) 58754359Sroberto return(0); 58854359Sroberto leitch->hour = ATOB(0)*10 +ATOB(1); 58954359Sroberto leitch->minute = ATOB(2)*10 +ATOB(3); 59054359Sroberto leitch->second = ATOB(4)*10 +ATOB(5); 59154359Sroberto 59254359Sroberto if ((leitch->hour > 23) || (leitch->minute > 60) || 59354359Sroberto (leitch->second > 60)) 59454359Sroberto return(0); 59554359Sroberto return(1); 59654359Sroberto} 59754359Sroberto 59854359Sroberto#else 599290001SglebiusNONEMPTY_TRANSLATION_UNIT 60054359Sroberto#endif /* REFCLOCK */ 601