refclock_dumbclock.c [plain text]
#define GET_LOCALTIME
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#if defined(REFCLOCK) && defined(CLOCK_DUMBCLOCK)
#include <stdio.h>
#include <ctype.h>
#include <sys/time.h>
#include <time.h>
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_calendar.h"
#include "ntp_stdlib.h"
#define DEVICE "/dev/dumbclock%d"
#define SPEED232 B9600
#define PRECISION (-13)
#define REFID "dumbclock"
#define DESCRIPTION "Dumb clock"
#define INSANE_SECONDS 3600
struct dumbclock_unit {
u_char tcswitch;
l_fp laststamp;
u_char lasthour;
u_char linect;
struct tm ymd;
};
static int dumbclock_start P((int, struct peer *));
static void dumbclock_shutdown P((int, struct peer *));
static void dumbclock_receive P((struct recvbuf *));
#if 0
static void dumbclock_poll P((int, struct peer *));
#endif
struct refclock refclock_dumbclock = {
dumbclock_start,
dumbclock_shutdown,
noentry,
noentry,
noentry,
noentry,
NOFLAGS
};
static int
dumbclock_start(
int unit,
struct peer *peer
)
{
register struct dumbclock_unit *up;
struct refclockproc *pp;
int fd;
char device[20];
struct tm *tm_time_p;
time_t now;
(void)sprintf(device, DEVICE, unit);
#ifdef DEBUG
if (debug)
printf ("starting Dumbclock with device %s\n",device);
#endif
if (!(fd = refclock_open(device, SPEED232, 0)))
return (0);
if (!(up = (struct dumbclock_unit *)
emalloc(sizeof(struct dumbclock_unit)))) {
(void) close(fd);
return (0);
}
memset((char *)up, 0, sizeof(struct dumbclock_unit));
pp = peer->procptr;
pp->unitptr = (caddr_t)up;
pp->io.clock_recv = dumbclock_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
(void) close(fd);
free(up);
return (0);
}
time(&now);
#ifdef GET_LOCALTIME
tm_time_p = localtime(&now);
#else
tm_time_p = gmtime(&now);
#endif
if (tm_time_p)
{
up->ymd = *tm_time_p;
}
else
{
return 0;
}
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 4);
return (1);
}
static void
dumbclock_shutdown(
int unit,
struct peer *peer
)
{
register struct dumbclock_unit *up;
struct refclockproc *pp;
pp = peer->procptr;
up = (struct dumbclock_unit *)pp->unitptr;
io_closeclock(&pp->io);
free(up);
}
static void
dumbclock_receive(
struct recvbuf *rbufp
)
{
struct dumbclock_unit *up;
struct refclockproc *pp;
struct peer *peer;
l_fp trtmp;
int hours;
int minutes;
int seconds;
int temp;
int got_good;
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
up = (struct dumbclock_unit *)pp->unitptr;
temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
if (temp == 0) {
if (up->tcswitch == 0) {
up->tcswitch = 1;
up->laststamp = trtmp;
} else
up->tcswitch = 0;
return;
}
pp->lencode = temp;
pp->lastrec = up->laststamp;
up->laststamp = trtmp;
up->tcswitch = 1;
#ifdef DEBUG
if (debug)
printf("dumbclock: timecode %d %s\n",
pp->lencode, pp->a_lastcode);
#endif
pp->msec = 0;
got_good=0;
if (sscanf(pp->a_lastcode,"%02d:%02d:%02d",
&hours,&minutes,&seconds) == 3)
{
struct tm *gmtp;
struct tm *lt_p;
time_t asserted_time;
struct tm asserted_tm;
int adjyear;
int adjmon;
int reality_delta;
time_t now;
asserted_tm.tm_year = up->ymd.tm_year;
asserted_tm.tm_mon = up->ymd.tm_mon;
asserted_tm.tm_mday = up->ymd.tm_mday;
asserted_tm.tm_hour = hours;
asserted_tm.tm_min = minutes;
asserted_tm.tm_sec = seconds;
asserted_tm.tm_isdst = -1;
#ifdef GET_LOCALTIME
asserted_time = mktime (&asserted_tm);
time(&now);
#else
#include "GMT unsupported for dumbclock!"
#endif
reality_delta = asserted_time - now;
if (reality_delta > INSANE_SECONDS)
{
asserted_time -= SECSPERDAY;
}
else if (-reality_delta > INSANE_SECONDS)
{
asserted_time += SECSPERDAY;
}
lt_p = localtime(&asserted_time);
if (lt_p)
{
up->ymd = *lt_p;
}
else
{
refclock_report (peer, CEVNT_FAULT);
return;
}
if ((gmtp = gmtime (&asserted_time)) == NULL)
{
refclock_report (peer, CEVNT_FAULT);
return;
}
adjyear = gmtp->tm_year+1900;
adjmon = gmtp->tm_mon+1;
pp->day = ymd2yd (adjyear, adjmon, gmtp->tm_mday);
pp->hour = gmtp->tm_hour;
pp->minute = gmtp->tm_min;
pp->second = gmtp->tm_sec;
#ifdef DEBUG
if (debug)
printf ("time is %04d/%02d/%02d %02d:%02d:%02d UTC\n",
adjyear,adjmon,gmtp->tm_mday,pp->hour,pp->minute,
pp->second);
#endif
got_good=1;
}
if (!got_good)
{
if (up->linect > 0)
up->linect--;
else
refclock_report(peer, CEVNT_BADREPLY);
return;
}
if (!refclock_process(pp)) {
refclock_report(peer, CEVNT_BADTIME);
peer->burst = 0;
return;
}
if (peer->burst > 0)
return;
record_clock_stats(&peer->srcadr, pp->a_lastcode);
refclock_receive(peer);
up->lasthour = pp->hour;
}
#if 0
static void
dumbclock_poll(
int unit,
struct peer *peer
)
{
register struct dumbclock_unit *up;
struct refclockproc *pp;
char pollchar;
#if 0
pp = peer->procptr;
up = (struct dumbclock_unit *)pp->unitptr;
if (peer->burst == 0 && peer->reach == 0)
refclock_report(peer, CEVNT_TIMEOUT);
if (up->linect > 0)
pollchar = 'R';
else
pollchar = 'T';
if (write(pp->io.fd, &pollchar, 1) != 1)
refclock_report(peer, CEVNT_FAULT);
else
pp->polls++;
#endif
}
#endif
#else
int refclock_dumbclock_bs;
#endif