📄 refclock_parse.c
字号:
/* * /src/NTP/REPOSITORY/ntp4-dev/ntpd/refclock_parse.c,v 4.64 2005/11/09 20:44:47 kardel RELEASE_20051109_A * * refclock_parse.c,v 4.64 2005/11/09 20:44:47 kardel RELEASE_20051109_A * * generic reference clock driver for several DCF/GPS/MSF/... receivers * * optionally make use of a STREAMS module for input processing where * available and configured. Currently the STREAMS module * is only available for Suns running SunOS 4.x and SunOS5.x * * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org> * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universit鋞 Erlangen-N黵nberg, Germany * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#ifdef HAVE_CONFIG_H# include "config.h"#endif#if defined(REFCLOCK) && defined(CLOCK_PARSE)/* * This driver currently provides the support for * - Meinberg receiver DCF77 PZF 535 (TCXO version) (DCF) * - Meinberg receiver DCF77 PZF 535 (OCXO version) (DCF) * - Meinberg receiver DCF77 PZF 509 (DCF) * - Meinberg receiver DCF77 AM receivers (e.g. C51) (DCF) * - IGEL CLOCK (DCF) * - ELV DCF7000 (DCF) * - Schmid clock (DCF) * - Conrad DCF77 receiver module (DCF) * - FAU DCF77 NTP receiver (TimeBrick) (DCF) * - WHARTON 400A Series clock (DCF) * * - Meinberg GPS166/GPS167 (GPS) * - Trimble (TSIP and TAIP protocol) (GPS) * * - RCC8000 MSF Receiver (MSF) * - VARITEXT clock (MSF) *//* * Meinberg receivers are usually connected via a * 9600 baud serial line * * The Meinberg GPS receivers also have a special NTP time stamp * format. The firmware release is Uni-Erlangen. * * Meinberg generic receiver setup: * output time code every second * Baud rate 9600 7E2S * * Meinberg GPS16x setup: * output time code every second * Baudrate 19200 8N1 * * This software supports the standard data formats used * in Meinberg receivers. * * Special software versions are only sensible for the * GPS 16x family of receivers. * * Meinberg can be reached via: http://www.meinberg.de/ */#include "ntpd.h"#include "ntp_refclock.h"#include "ntp_unixtime.h" /* includes <sys/time.h> */#include "ntp_control.h"#include "ntp_string.h"#include <stdio.h>#include <ctype.h>#ifndef TM_IN_SYS_TIME# include <time.h>#endif#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#if !defined(STREAM) && !defined(HAVE_SYSV_TTYS) && !defined(HAVE_BSD_TTYS) && !defined(HAVE_TERMIOS)# include "Bletch: Define one of {STREAM,HAVE_SYSV_TTYS,HAVE_TERMIOS}"#endif#ifdef STREAM# include <sys/stream.h># include <sys/stropts.h>#endif#ifdef HAVE_TERMIOS# define TTY_GETATTR(_FD_, _ARG_) tcgetattr((_FD_), (_ARG_))# define TTY_SETATTR(_FD_, _ARG_) tcsetattr((_FD_), TCSANOW, (_ARG_))# undef HAVE_SYSV_TTYS#endif#ifdef HAVE_SYSV_TTYS# define TTY_GETATTR(_FD_, _ARG_) ioctl((_FD_), TCGETA, (_ARG_))# define TTY_SETATTR(_FD_, _ARG_) ioctl((_FD_), TCSETAW, (_ARG_))#endif#ifdef HAVE_BSD_TTYS/* #error CURRENTLY NO BSD TTY SUPPORT */# include "Bletch: BSD TTY not currently supported"#endif#ifdef HAVE_SYS_IOCTL_H# include <sys/ioctl.h>#endif#ifdef HAVE_PPSAPI# include "ppsapi_timepps.h"#endif#ifdef PPS# ifdef HAVE_SYS_PPSCLOCK_H# include <sys/ppsclock.h># endif# ifdef HAVE_TIO_SERIAL_STUFF# include <linux/serial.h># endif#endif#define BUFFER_SIZE(_BUF, _PTR) ((_BUF) + sizeof(_BUF) - (_PTR))#define BUFFER_SIZES(_BUF, _PTR, _SZ) ((_BUF) + (_SZ) - (_PTR))/* * document type of PPS interfacing - copy of ifdef mechanism in local_input() */#undef PPS_METHOD #ifdef HAVE_PPSAPI#define PPS_METHOD "PPS API"#else#ifdef TIOCDCDTIMESTAMP#define PPS_METHOD "TIOCDCDTIMESTAMP"#else /* TIOCDCDTIMESTAMP */#if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV))#ifdef HAVE_CIOGETEV#define PPS_METHOD "CIOGETEV"#endif#ifdef HAVE_TIOCGPPSEV#define PPS_METHOD "TIOCGPPSEV"#endif#endif#endif /* TIOCDCDTIMESTAMP */#endif /* HAVE_PPSAPI */#include "ntp_io.h"#include "ntp_stdlib.h"#include "parse.h"#include "mbg_gps166.h"#include "trimble.h"#include "binio.h"#include "ascii.h"#include "ieee754io.h"static char rcsid[] = "refclock_parse.c,v 4.64 2005/11/09 20:44:47 kardel RELEASE_20051109_A";/**=========================================================================== ** external interface to ntp mechanism **/static int parse_start P((int, struct peer *));static void parse_shutdown P((int, struct peer *));static void parse_poll P((int, struct peer *));static void parse_control P((int, struct refclockstat *, struct refclockstat *, struct peer *));struct refclock refclock_parse = { parse_start, parse_shutdown, parse_poll, parse_control, noentry, noentry, NOFLAGS};/* * Definitions */#define MAXUNITS 4 /* maximum number of "PARSE" units permitted */#define PARSEDEVICE "/dev/refclock-%d" /* device to open %d is unit number */#undef ABS#define ABS(_X_) (((_X_) < 0) ? -(_X_) : (_X_))#define PARSE_HARDPPS_DISABLE 0#define PARSE_HARDPPS_ENABLE 1/**=========================================================================== ** function vector for dynamically binding io handling mechanism **/struct parseunit; /* to keep inquiring minds happy */typedef struct bind{ const char *bd_description; /* name of type of binding */ int (*bd_init) P((struct parseunit *)); /* initialize */ void (*bd_end) P((struct parseunit *)); /* end */ int (*bd_setcs) P((struct parseunit *, parsectl_t *)); /* set character size */ int (*bd_disable) P((struct parseunit *)); /* disable */ int (*bd_enable) P((struct parseunit *)); /* enable */ int (*bd_getfmt) P((struct parseunit *, parsectl_t *)); /* get format */ int (*bd_setfmt) P((struct parseunit *, parsectl_t *)); /* setfmt */ int (*bd_timecode) P((struct parseunit *, parsectl_t *)); /* get time code */ void (*bd_receive) P((struct recvbuf *)); /* receive operation */ int (*bd_io_input) P((struct recvbuf *)); /* input operation */} bind_t;#define PARSE_END(_X_) (*(_X_)->binding->bd_end)(_X_)#define PARSE_SETCS(_X_, _CS_) (*(_X_)->binding->bd_setcs)(_X_, _CS_)#define PARSE_ENABLE(_X_) (*(_X_)->binding->bd_enable)(_X_)#define PARSE_DISABLE(_X_) (*(_X_)->binding->bd_disable)(_X_)#define PARSE_GETFMT(_X_, _DCT_) (*(_X_)->binding->bd_getfmt)(_X_, _DCT_)#define PARSE_SETFMT(_X_, _DCT_) (*(_X_)->binding->bd_setfmt)(_X_, _DCT_)#define PARSE_GETTIMECODE(_X_, _DCT_) (*(_X_)->binding->bd_timecode)(_X_, _DCT_)/* * io modes */#define PARSE_F_PPSPPS 0x0001 /* use loopfilter PPS code (CIOGETEV) */#define PARSE_F_PPSONSECOND 0x0002 /* PPS pulses are on second *//**=========================================================================== ** error message regression handling ** ** there are quite a few errors that can occur in rapid succession such as ** noisy input data or no data at all. in order to reduce the amount of ** syslog messages in such case, we are using a backoff algorithm. We limit ** the number of error messages of a certain class to 1 per time unit. if a ** configurable number of messages is displayed that way, we move on to the ** next time unit / count for that class. a count of messages that have been ** suppressed is held and displayed whenever a corresponding message is ** displayed. the time units for a message class will also be displayed. ** whenever an error condition clears we reset the error message state, ** thus we would still generate much output on pathological conditions ** where the system oscillates between OK and NOT OK states. coping ** with that condition is currently considered too complicated. **/#define ERR_ALL (unsigned)~0 /* "all" errors */#define ERR_BADDATA (unsigned)0 /* unusable input data/conversion errors */#define ERR_NODATA (unsigned)1 /* no input data */#define ERR_BADIO (unsigned)2 /* read/write/select errors */#define ERR_BADSTATUS (unsigned)3 /* unsync states */#define ERR_BADEVENT (unsigned)4 /* non nominal events */#define ERR_INTERNAL (unsigned)5 /* internal error */#define ERR_CNT (unsigned)(ERR_INTERNAL+1)#define ERR(_X_) if (list_err(parse, (_X_)))struct errorregression{ u_long err_count; /* number of repititions per class */ u_long err_delay; /* minimum delay between messages */};static struct errorregressionerr_baddata[] = /* error messages for bad input data */{ { 1, 0 }, /* output first message immediately */ { 5, 60 }, /* output next five messages in 60 second intervals */ { 3, 3600 }, /* output next 3 messages in hour intervals */ { 0, 12*3600 } /* repeat messages only every 12 hours */};static struct errorregressionerr_nodata[] = /* error messages for missing input data */{ { 1, 0 }, /* output first message immediately */ { 5, 60 }, /* output next five messages in 60 second intervals */ { 3, 3600 }, /* output next 3 messages in hour intervals */ { 0, 12*3600 } /* repeat messages only every 12 hours */};static struct errorregressionerr_badstatus[] = /* unsynchronized state messages */{ { 1, 0 }, /* output first message immediately */ { 5, 60 }, /* output next five messages in 60 second intervals */ { 3, 3600 }, /* output next 3 messages in hour intervals */ { 0, 12*3600 } /* repeat messages only every 12 hours */};static struct errorregressionerr_badio[] = /* io failures (bad reads, selects, ...) */{ { 1, 0 }, /* output first message immediately */ { 5, 60 }, /* output next five messages in 60 second intervals */ { 5, 3600 }, /* output next 3 messages in hour intervals */ { 0, 12*3600 } /* repeat messages only every 12 hours */};static struct errorregressionerr_badevent[] = /* non nominal events */{ { 20, 0 }, /* output first message immediately */ { 6, 60 }, /* output next five messages in 60 second intervals */ { 5, 3600 }, /* output next 3 messages in hour intervals */ { 0, 12*3600 } /* repeat messages only every 12 hours */};static struct errorregressionerr_internal[] = /* really bad things - basically coding/OS errors */{ { 0, 0 }, /* output all messages immediately */};static struct errorregression *err_tbl[] ={ err_baddata, err_nodata, err_badio, err_badstatus, err_badevent, err_internal};struct errorinfo{ u_long err_started; /* begin time (ntp) of error condition */ u_long err_last; /* last time (ntp) error occurred */ u_long err_cnt; /* number of error repititions */ u_long err_suppressed; /* number of suppressed messages */ struct errorregression *err_stage; /* current error stage */};/**=========================================================================== ** refclock instance data **/struct parseunit{ /* * NTP management */ struct peer *peer; /* backlink to peer structure - refclock inactive if 0 */ struct refclockproc *generic; /* backlink to refclockproc structure */ /* * PARSE io */ bind_t *binding; /* io handling binding */ /* * parse state */ parse_t parseio; /* io handling structure (user level parsing) */ /* * type specific parameters */ struct parse_clockinfo *parse_type; /* link to clock description */ /* * clock state handling/reporting */ u_char flags; /* flags (leap_control) */ u_long lastchange; /* time (ntp) when last state change accured */ u_long statetime[CEVNT_MAX+1]; /* accumulated time of clock states */ u_long pollneeddata; /* current_time(!=0) for receive sample expected in PPS mode */ u_short lastformat; /* last format used */ u_long lastsync; /* time (ntp) when clock was last seen fully synchronized */ u_long maxunsync; /* max time in seconds a receiver is trusted after loosing synchronisation */ double ppsphaseadjust; /* phase adjustment of PPS time stamp */ u_long lastmissed; /* time (ntp) when poll didn't get data (powerup heuristic) */ u_long ppsserial; /* magic cookie for ppsclock serials (avoids stale ppsclock data) */#ifdef HAVE_PPSAPI pps_handle_t ppshandle; /* store PPSAPI handle */ pps_params_t ppsparams; /* current PPS parameters */ int hardppsstate; /* current hard pps state */#endif parsetime_t timedata; /* last (parse module) data */ void *localdata; /* optional local, receiver-specific data */ unsigned long localstate; /* private local state */ struct errorinfo errors[ERR_CNT]; /* error state table for suppressing excessive error messages */ struct ctl_var *kv; /* additional pseudo variables */ u_long laststatistic; /* time when staticstics where output */};/**=========================================================================== ** Clockinfo section all parameter for specific clock types ** includes NTP parameters, TTY parameters and IO handling parameters **/static void poll_dpoll P((struct parseunit *));static void poll_poll P((struct peer *));static int poll_init P((struct parseunit *));typedef struct poll_info{ u_long rate; /* poll rate - once every "rate" seconds - 0 off */ const char *string; /* string to send for polling */ u_long count; /* number of characters in string */} poll_info_t;#define NO_CL_FLAGS 0#define NO_POLL 0#define NO_INIT 0#define NO_END 0#define NO_EVENT 0#define NO_LCLDATA 0#define NO_MESSAGE 0#define NO_PPSDELAY 0#define DCF_ID "DCF" /* generic DCF */#define DCF_A_ID "DCFa" /* AM demodulation */#define DCF_P_ID "DCFp" /* psuedo random phase shift */#define GPS_ID "GPS" /* GPS receiver */#define NOCLOCK_ROOTDELAY 0.0#define NOCLOCK_BASEDELAY 0.0#define NOCLOCK_DESCRIPTION 0#define NOCLOCK_MAXUNSYNC 0#define NOCLOCK_CFLAG 0#define NOCLOCK_IFLAG 0#define NOCLOCK_OFLAG 0#define NOCLOCK_LFLAG 0#define NOCLOCK_ID "TILT"#define NOCLOCK_POLL NO_POLL#define NOCLOCK_INIT NO_INIT#define NOCLOCK_END NO_END#define NOCLOCK_DATA NO_LCLDATA#define NOCLOCK_FORMAT ""#define NOCLOCK_TYPE CTL_SST_TS_UNSPEC#define NOCLOCK_SAMPLES 0#define NOCLOCK_KEEP 0 #define DCF_TYPE CTL_SST_TS_LF#define GPS_TYPE CTL_SST_TS_UHF/* * receiver specific constants */#define MBG_SPEED (B9600)#define MBG_CFLAG (CS7|PARENB|CREAD|CLOCAL|HUPCL|CSTOPB)#define MBG_IFLAG (IGNBRK|IGNPAR|ISTRIP)#define MBG_OFLAG 0#define MBG_LFLAG 0#define MBG_FLAGS PARSE_F_PPSONSECOND/* * Meinberg DCF77 receivers */#define DCFUA31_ROOTDELAY 0.0 /* 0 */#define DCFUA31_BASEDELAY 0.010 /* 10.7421875ms: 10 ms (+/- 3 ms) */#define DCFUA31_DESCRIPTION "Meinberg DCF77 C51 or compatible"#define DCFUA31_MAXUNSYNC 60*30 /* only trust clock for 1/2 hour */#define DCFUA31_SPEED MBG_SPEED#define DCFUA31_CFLAG MBG_CFLAG#define DCFUA31_IFLAG MBG_IFLAG#define DCFUA31_OFLAG MBG_OFLAG#define DCFUA31_LFLAG MBG_LFLAG#define DCFUA31_SAMPLES 5#define DCFUA31_KEEP 3#define DCFUA31_FORMAT "Meinberg Standard"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -