#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#if defined(REFCLOCK) && defined(CLOCK_ZYFER)
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
#include "ntp_unixtime.h"
#include <stdio.h>
#include <ctype.h>
#ifdef HAVE_SYS_TERMIOS_H
# include <sys/termios.h>
#endif
#ifdef HAVE_SYS_PPSCLOCK_H
# include <sys/ppsclock.h>
#endif
#define DEVICE "/dev/zyfer%d"
#define SPEED232 B9600
#define PRECISION (-20)
#define REFID "GPS\0"
#define DESCRIPTION "Zyfer GPStarplus"
#define LENZYFER 29
struct zyferunit {
u_char Rcvbuf[LENZYFER + 1];
u_char polled;
int pollcnt;
l_fp tstamp;
int Rcvptr;
};
static int zyfer_start P((int, struct peer *));
static void zyfer_shutdown P((int, struct peer *));
static void zyfer_receive P((struct recvbuf *));
static void zyfer_poll P((int, struct peer *));
struct refclock refclock_zyfer = {
zyfer_start,
zyfer_shutdown,
zyfer_poll,
noentry,
noentry,
noentry,
NOFLAGS
};
static int
zyfer_start(
int unit,
struct peer *peer
)
{
register struct zyferunit *up;
struct refclockproc *pp;
int fd;
char device[20];
(void)sprintf(device, DEVICE, unit);
if ( !(fd = refclock_open(device, SPEED232, LDISC_RAW)) )
return (0);
msyslog(LOG_NOTICE, "zyfer(%d) fd: %d dev <%s>", unit, fd, device);
if (!(up = (struct zyferunit *)
emalloc(sizeof(struct zyferunit)))) {
(void) close(fd);
return (0);
}
memset((char *)up, 0, sizeof(struct zyferunit));
pp = peer->procptr;
pp->io.clock_recv = zyfer_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);
}
pp->unitptr = (caddr_t)up;
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 4);
up->pollcnt = 2;
up->polled = 0;
return (1);
}
static void
zyfer_shutdown(
int unit,
struct peer *peer
)
{
register struct zyferunit *up;
struct refclockproc *pp;
pp = peer->procptr;
up = (struct zyferunit *)pp->unitptr;
io_closeclock(&pp->io);
free(up);
}
static void
zyfer_receive(
struct recvbuf *rbufp
)
{
register struct zyferunit *up;
struct refclockproc *pp;
struct peer *peer;
int tmode;
int tfom;
int omode;
u_char *p;
#ifdef PPS
struct ppsclockev ppsev;
int request;
#ifdef HAVE_CIOGETEV
request = CIOGETEV;
#endif
#ifdef HAVE_TIOCGPPSEV
request = TIOCGPPSEV;
#endif
#endif
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
up = (struct zyferunit *)pp->unitptr;
p = (u_char *) &rbufp->recv_space;
if (pp->lencode >= LENZYFER)
pp->lencode = 0;
if (!pp->lencode) {
if (*p == '!')
pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode,
BMAX, &pp->lastrec);
else
return;
} else {
memcpy(pp->a_lastcode + pp->lencode, p, rbufp->recv_length);
pp->lencode += rbufp->recv_length;
pp->a_lastcode[pp->lencode] = '\0';
}
if (pp->lencode < LENZYFER)
return;
record_clock_stats(&peer->srcadr, pp->a_lastcode);
if (pp->lencode != LENZYFER) {
refclock_report(peer, CEVNT_BADTIME);
return;
}
if (sscanf(pp->a_lastcode, "!TIME,%4d,%3d,%2d,%2d,%2d,%d,%d,%d",
&pp->year, &pp->day, &pp->hour, &pp->minute, &pp->second,
&tmode, &tfom, &omode) != 8) {
refclock_report(peer, CEVNT_BADREPLY);
return;
}
if (tmode != 2) {
refclock_report(peer, CEVNT_BADTIME);
return;
}
if (omode != 1) {
pp->leap = LEAP_NOTINSYNC;
return;
}
#ifdef PPS
if(ioctl(fdpps,request,(caddr_t) &ppsev) >=0) {
ppsev.tv.tv_sec += (u_int32) JAN_1970;
TVTOTS(&ppsev.tv,&up->tstamp);
}
pp->lastrec = up->tstamp;
#endif
if (!refclock_process(pp)) {
refclock_report(peer, CEVNT_BADTIME);
return;
}
up->pollcnt = 2;
if (up->polled) {
up->polled = 0;
refclock_receive(peer);
}
}
static void
zyfer_poll(
int unit,
struct peer *peer
)
{
register struct zyferunit *up;
struct refclockproc *pp;
pp = peer->procptr;
up = (struct zyferunit *)pp->unitptr;
if (!up->pollcnt)
refclock_report(peer, CEVNT_TIMEOUT);
else
up->pollcnt--;
pp->polls++;
up->polled = 1;
}
#else
int refclock_zyfer_bs;
#endif