#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#if defined(REFCLOCK) && defined(CLOCK_FG)
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_calendar.h"
#include "ntp_stdlib.h"
#define DEVICE "/dev/fgclock%d"
#define PRECISION (-10)
#define REFID "GPS"
#define DESCRIPTION "Forum Graphic GPS dating station"
#define LENFG 26
#define SPEED232 B9600
static int fg_init (int);
static int fg_start (int, struct peer *);
static void fg_shutdown (int, struct peer *);
static void fg_poll (int, struct peer *);
static void fg_receive (struct recvbuf *);
struct fgunit {
int pollnum;
int status;
int y2kwarn;
};
static char fginit[] = { 0x10, 0x48, 0x10, 0x0D, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
static char fgdate[] = { 0x10, 0x44, 0x10, 0x0D, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 };
struct refclock refclock_fg = {
fg_start,
fg_shutdown,
fg_poll,
noentry,
noentry,
noentry,
NOFLAGS
};
static int
fg_init(
int fd
)
{
if (write(fd, fginit, LENFG) != LENFG)
return 0;
return (1);
}
static int
fg_start(
int unit,
struct peer *peer
)
{
struct refclockproc *pp;
struct fgunit *up;
int fd;
char device[20];
(void)sprintf(device, DEVICE, unit);
#ifdef DEBUG
if (debug)
printf ("starting FG with device %s\n",device);
#endif
if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
return (0);
if (!(up = (struct fgunit *)
emalloc(sizeof(struct fgunit)))) {
(void) close(fd);
return (0);
}
memset((char *)up, 0, sizeof(struct fgunit));
pp = peer->procptr;
pp->unitptr = (caddr_t)up;
pp->io.clock_recv = fg_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
(void) close(fd);
return (0);
}
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 3);
up->pollnum = 0;
if(!fg_init(pp->io.fd))
refclock_report(peer, CEVNT_FAULT);
return (1);
}
static void
fg_shutdown(
int unit,
struct peer *peer
)
{
struct refclockproc *pp;
struct fgunit *up;
pp = peer->procptr;
up = (struct fgunit *)pp->unitptr;
io_closeclock(&pp->io);
free(up);
}
static void
fg_poll(
int unit,
struct peer *peer
)
{
struct refclockproc *pp;
pp = peer->procptr;
if (write(pp->io.fd, fgdate, LENFG) != LENFG)
refclock_report(peer, CEVNT_FAULT);
else
pp->polls++;
if (peer->burst > 0)
return;
peer->burst = NSTAGE;
record_clock_stats(&peer->srcadr, pp->a_lastcode);
return;
}
static void
fg_receive(
struct recvbuf *rbufp
)
{
struct refclockproc *pp;
struct fgunit *up;
struct peer *peer;
char *bpt;
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
up = (struct fgunit *)pp->unitptr;
if(!up->pollnum)
{
up->pollnum++;
return;
}
if (rbufp->recv_length < (LENFG-2))
{
refclock_report(peer, CEVNT_BADREPLY);
return;
}
bpt = (char *)rbufp->recv_space.X_recv_buffer;
while(*bpt != '')
bpt++;
#define BP2(x) ( bpt[x] & 15 )
#define BP1(x) (( bpt[x] & 240 ) >> 4)
pp->year = BP1(2)*10 + BP2(2);
if(pp->year == 94)
{
refclock_report(peer, CEVNT_BADREPLY);
if(!fg_init(pp->io.fd))
refclock_report(peer, CEVNT_FAULT);
return;
}
if (pp->year < 99)
pp->year += 100;
pp->year += 1900;
pp->day = 100 * BP2(3) + 10 * BP1(4) + BP2(4);
if(up->y2kwarn > 10)
pp->hour = BP1(6)*10 + BP2(6);
else
pp->hour = BP1(5)*10 + BP2(5);
if((up->y2kwarn > 10) && (pp->hour == 10))
{
pp->minute = BP1(7)*10 + BP2(7);
pp->second = BP1(8)*10 + BP2(8);
pp->nsec = (BP1(9)*10 + BP2(9)) * 1000000;
pp->nsec += BP1(10) * 1000;
} else {
pp->hour = BP1(5)*10 + BP2(5);
pp->minute = BP1(6)*10 + BP2(6);
pp->second = BP1(7)*10 + BP2(7);
pp->nsec = (BP1(8)*10 + BP2(8)) * 1000000;
pp->nsec += BP1(9) * 1000;
}
if((pp->hour == 10) && (pp->minute == 10))
{
up->y2kwarn++;
}
sprintf(pp->a_lastcode, "%d %d %d %d %d", pp->year, pp->day, pp->hour, pp->minute, pp->second);
pp->lencode = strlen(pp->a_lastcode);
#ifdef DEBUG
if (debug)
printf ("fg: time is %04d/%03d %02d:%02d:%02d UTC\n",
pp->year, pp->day, pp->hour, pp->minute, pp->second);
#endif
pp->disp = (10e-6);
pp->lastrec = rbufp->recv_time;
if (!refclock_process(pp))
refclock_report(peer, CEVNT_BADTIME);
pp->lastref = pp->lastrec;
refclock_receive(peer);
return;
}
#else
int refclock_fg_bs;
#endif