refclock_hopfser.c [plain text]
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#if defined(SYS_WINNT)
#undef close
#define close closesocket
#endif
#if defined(REFCLOCK) && (defined(CLOCK_HOPF_SERIAL))
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_control.h"
#include "ntp_refclock.h"
#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
#if defined HAVE_SYS_MODEM_H
# include <sys/modem.h>
# define TIOCMSET MCSETA
# define TIOCMGET MCGETA
# define TIOCM_RTS MRTS
#endif
#ifdef HAVE_TERMIOS_H
# ifdef TERMIOS_NEEDS__SVID3
# define _SVID3
# endif
# include <termios.h>
# ifdef TERMIOS_NEEDS__SVID3
# undef _SVID3
# endif
#endif
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#define DESCRIPTION "hopf Elektronik serial clock"
#define PRECISION (-10)
#define REFID "hopf\0"
#define DEVICE "/dev/hopfclock%d"
#define SPEED232 B9600
#define STX 0x02
#define ETX 0x03
#define CR 0x0c
#define LF 0x0a
#define REC_QUEUE_EMPTY 0
#define REC_QUEUE_FULL 1
#define HOPF_OPMODE 0x0C
#define HOPF_INVALID 0x00
#define HOPF_INTERNAL 0x04
#define HOPF_RADIO 0x08
#define HOPF_RADIOHP 0x0C
struct hopfclock_unit {
l_fp laststamp;
short unit;
u_long polled;
char leap_status;
int rpt_next;
};
static int hopfserial_start P((int, struct peer *));
static void hopfserial_shutdown P((int, struct peer *));
static void hopfserial_receive P((struct recvbuf *));
static void hopfserial_poll P((int, struct peer *));
struct refclock refclock_hopfser = {
hopfserial_start,
hopfserial_shutdown,
hopfserial_poll,
noentry,
noentry,
noentry,
NOFLAGS
};
static int
hopfserial_start (
int unit,
struct peer *peer
)
{
register struct hopfclock_unit *up;
struct refclockproc *pp;
int fd;
char gpsdev[20];
#ifdef SYS_WINNT
(void) sprintf(gpsdev, "COM%d:", unit);
#else
(void) sprintf(gpsdev, DEVICE, unit);
#endif
fd = refclock_open(gpsdev, SPEED232, LDISC_CLK);
if (fd <= 0) {
#ifdef DEBUG
printf("hopfSerialClock(%d) start: open %s failed\n", unit, gpsdev);
#endif
return 0;
}
msyslog(LOG_NOTICE, "hopfSerialClock(%d) fd: %d dev: %s", unit, fd,
gpsdev);
up = (struct hopfclock_unit *) emalloc(sizeof(struct hopfclock_unit));
if (!(up)) {
msyslog(LOG_ERR, "hopfSerialClock(%d) emalloc: %m",unit);
#ifdef DEBUG
printf("hopfSerialClock(%d) emalloc\n",unit);
#endif
(void) close(fd);
return (0);
}
memset((char *)up, 0, sizeof(struct hopfclock_unit));
pp = peer->procptr;
pp->unitptr = (caddr_t)up;
pp->io.clock_recv = hopfserial_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
#ifdef DEBUG
printf("hopfSerialClock(%d) io_addclock\n",unit);
#endif
(void) close(fd);
free(up);
return (0);
}
pp->clockdesc = DESCRIPTION;
peer->precision = PRECISION;
peer->burst = NSTAGE;
memcpy((char *)&pp->refid, REFID, 4);
up->leap_status = 0;
up->unit = (short) unit;
return (1);
}
static void
hopfserial_shutdown (
int unit,
struct peer *peer
)
{
register struct hopfclock_unit *up;
struct refclockproc *pp;
pp = peer->procptr;
up = (struct hopfclock_unit *)pp->unitptr;
io_closeclock(&pp->io);
free(up);
}
static void
hopfserial_receive (
struct recvbuf *rbufp
)
{
struct hopfclock_unit *up;
struct refclockproc *pp;
struct peer *peer;
int synch;
int DoW;
int day, month;
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
up = (struct hopfclock_unit *)pp->unitptr;
if (up->rpt_next == 0 )
return;
up->rpt_next = 0;
pp->lencode = (u_short)refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
if (pp->lencode == 0)
return;
sscanf(pp->a_lastcode,
#if 1
"%1x%1x%2d%2d%2d%2d%2d%2d",
#else
"%*c%1x%1x%2d%2d%2d%2d%2d%2d",
#endif
&synch,
&DoW,
&pp->hour,
&pp->minute,
&pp->second,
&day,
&month,
&pp->year);
if((pp->hour < 0) || (pp->hour > 23) ||
(pp->minute < 0) || (pp->minute > 59) ||
(pp->second < 0) || (pp->second > 60) ||
(day < 1) || (day > 31) ||
(month < 1) || (month > 12) ||
(pp->year < 0) || (pp->year > 99)) {
refclock_report(peer, CEVNT_BADREPLY);
return;
}
pp->day = ymd2yd(pp->year,month,day);
pp->leap=0;
if(pp->year < YEAR_PIVOT) { pp->year += 100; }
pp->year += 1900;
#if 0
wsprintf(pp->a_lastcode,
"STATUS: %1X%1X, DATE: %02d.%02d.%04d TIME: %02d:%02d:%02d",
synch,
DoW,
day,
month,
pp->year,
pp->hour,
pp->minute,
pp->second);
pp->lencode = strlen(pp->a_lastcode);
if ((synch && 0xc) == 0 ){
refclock_report(peer, CEVNT_BADTIME);
pp->leap = LEAP_NOTINSYNC;
return;
}
#endif
if ((synch & HOPF_OPMODE) == HOPF_INVALID ){
refclock_report(peer, CEVNT_BADTIME);
pp->leap = LEAP_NOTINSYNC;
return;
}
if ((synch & HOPF_OPMODE) == HOPF_INTERNAL){
if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
refclock_report(peer, CEVNT_BADTIME);
pp->leap = LEAP_NOTINSYNC;
return;
}
}
if (!refclock_process(pp)) {
refclock_report(peer, CEVNT_BADTIME);
return;
}
pp->lastref = pp->lastrec;
refclock_receive(peer);
#if 0
msyslog(LOG_ERR, " D:%x D:%d D:%d",synch,pp->minute,pp->second);
#endif
record_clock_stats(&peer->srcadr, pp->a_lastcode);
return;
}
static void
hopfserial_poll (
int unit,
struct peer *peer
)
{
register struct hopfclock_unit *up;
struct refclockproc *pp;
pp = peer->procptr;
up = (struct hopfclock_unit *)pp->unitptr;
pp->polls++;
up->rpt_next = 1;
#if 0
record_clock_stats(&peer->srcadr, pp->a_lastcode);
#endif
return;
}
#else
int refclock_hopfser_bs;
#endif