From bdab5265fcbf3f472545073a23f8999749a9f2b9 Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Tue, 2 Dec 2014 09:01:21 +0000 Subject: Imported from /home/lorry/working-area/delta_ntp/ntp-dev-4.2.7p482.tar.gz. --- libparse/Makefile.am | 145 +++++ libparse/Makefile.in | 935 +++++++++++++++++++++++++++++++ libparse/README | 96 ++++ libparse/binio.c | 156 ++++++ libparse/clk_computime.c | 219 ++++++++ libparse/clk_dcf7000.c | 214 ++++++++ libparse/clk_hopf6021.c | 283 ++++++++++ libparse/clk_meinberg.c | 776 ++++++++++++++++++++++++++ libparse/clk_rawdcf.c | 658 ++++++++++++++++++++++ libparse/clk_rcc8000.c | 198 +++++++ libparse/clk_schmid.c | 258 +++++++++ libparse/clk_sel240x.c | 178 ++++++ libparse/clk_trimtaip.c | 223 ++++++++ libparse/clk_trimtsip.c | 463 ++++++++++++++++ libparse/clk_varitext.c | 271 +++++++++ libparse/clk_wharton.c | 181 ++++++ libparse/data_mbg.c | 539 ++++++++++++++++++ libparse/gpstolfp.c | 77 +++ libparse/ieee754io.c | 614 +++++++++++++++++++++ libparse/info_trimble.c | 94 ++++ libparse/mfp_mul.c | 207 +++++++ libparse/mkinfo_rcmd.sed | 8 + libparse/mkinfo_scmd.sed | 15 + libparse/parse.c | 945 ++++++++++++++++++++++++++++++++ libparse/parse_conf.c | 182 ++++++ libparse/parsesolaris.c | 1202 ++++++++++++++++++++++++++++++++++++++++ libparse/parsestreams.c | 1367 ++++++++++++++++++++++++++++++++++++++++++++++ libparse/trim_info.c | 70 +++ 28 files changed, 10574 insertions(+) create mode 100644 libparse/Makefile.am create mode 100644 libparse/Makefile.in create mode 100644 libparse/README create mode 100644 libparse/binio.c create mode 100644 libparse/clk_computime.c create mode 100644 libparse/clk_dcf7000.c create mode 100644 libparse/clk_hopf6021.c create mode 100644 libparse/clk_meinberg.c create mode 100644 libparse/clk_rawdcf.c create mode 100644 libparse/clk_rcc8000.c create mode 100644 libparse/clk_schmid.c create mode 100644 libparse/clk_sel240x.c create mode 100644 libparse/clk_trimtaip.c create mode 100644 libparse/clk_trimtsip.c create mode 100644 libparse/clk_varitext.c create mode 100644 libparse/clk_wharton.c create mode 100644 libparse/data_mbg.c create mode 100644 libparse/gpstolfp.c create mode 100644 libparse/ieee754io.c create mode 100644 libparse/info_trimble.c create mode 100644 libparse/mfp_mul.c create mode 100644 libparse/mkinfo_rcmd.sed create mode 100644 libparse/mkinfo_scmd.sed create mode 100644 libparse/parse.c create mode 100644 libparse/parse_conf.c create mode 100644 libparse/parsesolaris.c create mode 100644 libparse/parsestreams.c create mode 100644 libparse/trim_info.c (limited to 'libparse') diff --git a/libparse/Makefile.am b/libparse/Makefile.am new file mode 100644 index 0000000..a92db15 --- /dev/null +++ b/libparse/Makefile.am @@ -0,0 +1,145 @@ +NULL= +BUILT_SOURCES = +CLEANFILES = +noinst_LIBRARIES = @MAKE_LIBPARSE@ @MAKE_LIBPARSE_KERNEL@ +EXTRA_LIBRARIES = libparse.a libparse_kernel.a +EXTRA_PROGRAMS = parsestreams parsesolaris +noinst_PROGRAMS = @MAKE_PARSEKMODULE@ + +K_CFLAGS = -DPARSESTREAM -DNTP_NEED_BOPS + +# info_trimble.c was mistakenly created in the build directory +# previously. It is located in $(srcdir) and any updates must +# end up there. + +libparse_a_SOURCES = parse.c \ + parse_conf.c \ + clk_meinberg.c \ + clk_schmid.c \ + clk_rawdcf.c \ + clk_trimtsip.c \ + clk_dcf7000.c \ + clk_trimtaip.c \ + clk_rcc8000.c \ + clk_hopf6021.c \ + clk_computime.c \ + clk_wharton.c \ + clk_varitext.c \ + clk_sel240x.c \ + data_mbg.c \ + info_trimble.c \ + trim_info.c \ + binio.c \ + ieee754io.c \ + mfp_mul.c \ + gpstolfp.c \ + $(NULL) + +libparse_kernel_a_SOURCES = +libparse_kernel_a_LIBADD = \ + kparse.o \ + kparse_conf.o \ + kclk_computime.o \ + kclk_dcf7000.o \ + kclk_hopf6021.o \ + kclk_meinberg.o \ + kclk_rawdcf.o \ + kclk_rcc8000.o \ + kclk_schmid.o \ + kclk_trimtaip.o \ + kclk_trimtsip.o \ + kclk_varitext.o \ + kclk_wharton.o \ + kclk_sel240x.o \ + kbinio.o \ + kieee754io.o \ + kmfp_mul.o \ + kgpstolfp.o \ + $(NULL) + +AM_CFLAGS = $(CFLAGS_NTP) + +AM_CPPFLAGS = $(NTP_INCS) +AM_CPPFLAGS += -I$(top_srcdir)/kernel +AM_CPPFLAGS += $(CPPFLAGS_NTP) + +EXTRA_DIST = parsesolaris.c parsestreams.c mkinfo_scmd.sed mkinfo_rcmd.sed info_trimble.c + +$(srcdir)/info_trimble.c: $(top_srcdir)/include/trimble.h $(srcdir)/Makefile.am $(srcdir)/mkinfo_scmd.sed $(srcdir)/mkinfo_rcmd.sed + sed -n -f $(srcdir)/mkinfo_scmd.sed $(top_srcdir)/include/trimble.h > info_trimble.new + sed -n -f $(srcdir)/mkinfo_rcmd.sed $(top_srcdir)/include/trimble.h >> info_trimble.new + mv -f info_trimble.new $@ + +kieee754io.o: $(srcdir)/ieee754io.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/ieee754io.c -o $@ + +kmfp_mul.o: $(srcdir)/mfp_mul.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/mfp_mul.c -o $@ + +kgpstolfp.o: $(srcdir)/gpstolfp.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/gpstolfp.c -o $@ + +kbinio.o: $(srcdir)/binio.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/binio.c -o $@ + +kclk_computime.o: $(srcdir)/clk_computime.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_computime.c -o $@ + +kclk_dcf7000.o: $(srcdir)/clk_dcf7000.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_dcf7000.c -o $@ + +kclk_hopf6021.o: $(srcdir)/clk_hopf6021.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_hopf6021.c -o $@ + +kclk_meinberg.o: $(srcdir)/clk_meinberg.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_meinberg.c -o $@ + +kclk_rawdcf.o: $(srcdir)/clk_rawdcf.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_rawdcf.c -o $@ + +kclk_rcc8000.o: $(srcdir)/clk_rcc8000.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_rcc8000.c -o $@ + +kclk_schmid.o: $(srcdir)/clk_schmid.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_schmid.c -o $@ + +kclk_trimtaip.o: $(srcdir)/clk_trimtaip.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_trimtaip.c -o $@ + +kclk_trimtsip.o: $(srcdir)/clk_trimtsip.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_trimtsip.c -o $@ + +kclk_varitext.o: $(srcdir)/clk_varitext.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_varitext.c -o $@ + +kclk_wharton.o: $(srcdir)/clk_wharton.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_wharton.c -o $@ + +kclk_sel240x.o: $(srcdir)/clk_sel240x.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_sel240x.c -o $@ + +kparse.o: $(srcdir)/parse.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/parse.c -o $@ + +kparse_conf.o: $(srcdir)/parse_conf.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/parse_conf.c -o $@ + +parsestreams.loadable_module.o: $(parsestreams_OBJECTS) libparse_kernel.a ../libntp/libntp.a + $(LD) -r -o $@ $(parsestreams_OBJECTS) libparse_kernel.a ../libntp/libntp.a + +parse: $(parsesolaris_OBJECTS) libparse_kernel.a ../libntp/libntp.a + $(LD) -r -o $@ $(parsesolaris_OBJECTS) libparse_kernel.a ../libntp/libntp.a + +parsesolaris.o: sys/systm.h + +sys/systm.h: + -mkdir sys + sed -e '/ffs(.*)/d' < /usr/include/sys/systm.h > sys/systm.h + +## check-libparse is invoked by ntpd/Makefile.am +check-libparse: $(noinst_LIBRARIES) + @: do-nothing action to avoid default SCCS get + +include $(top_srcdir)/sntp/check-libntp.mf +include $(top_srcdir)/depsver.mf +include $(top_srcdir)/includes.mf diff --git a/libparse/Makefile.in b/libparse/Makefile.in new file mode 100644 index 0000000..0344c96 --- /dev/null +++ b/libparse/Makefile.in @@ -0,0 +1,935 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +EXTRA_PROGRAMS = parsestreams$(EXEEXT) parsesolaris$(EXEEXT) +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depsver.mf $(top_srcdir)/includes.mf \ + $(top_srcdir)/sntp/check-libntp.mf +subdir = libparse +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/sntp/libopts/m4/libopts.m4 \ + $(top_srcdir)/sntp/libopts/m4/stdnoreturn.m4 \ + $(top_srcdir)/sntp/libevent/m4/openldap-thread-check.m4 \ + $(top_srcdir)/sntp/libevent/m4/openldap.m4 \ + $(top_srcdir)/sntp/m4/define_dir.m4 \ + $(top_srcdir)/sntp/m4/hms_search_lib.m4 \ + $(top_srcdir)/sntp/m4/libtool.m4 \ + $(top_srcdir)/sntp/m4/ltoptions.m4 \ + $(top_srcdir)/sntp/m4/ltsugar.m4 \ + $(top_srcdir)/sntp/m4/ltversion.m4 \ + $(top_srcdir)/sntp/m4/lt~obsolete.m4 \ + $(top_srcdir)/sntp/m4/ntp_cacheversion.m4 \ + $(top_srcdir)/sntp/m4/ntp_compiler.m4 \ + $(top_srcdir)/sntp/m4/ntp_crosscompile.m4 \ + $(top_srcdir)/sntp/m4/ntp_debug.m4 \ + $(top_srcdir)/sntp/m4/ntp_dir_sep.m4 \ + $(top_srcdir)/sntp/m4/ntp_facilitynames.m4 \ + $(top_srcdir)/sntp/m4/ntp_googletest.m4 \ + $(top_srcdir)/sntp/m4/ntp_ipv6.m4 \ + $(top_srcdir)/sntp/m4/ntp_lib_m.m4 \ + $(top_srcdir)/sntp/m4/ntp_libevent.m4 \ + $(top_srcdir)/sntp/m4/ntp_libntp.m4 \ + $(top_srcdir)/sntp/m4/ntp_lineeditlibs.m4 \ + $(top_srcdir)/sntp/m4/ntp_locinfo.m4 \ + $(top_srcdir)/sntp/m4/ntp_openssl.m4 \ + $(top_srcdir)/sntp/m4/ntp_pkg_config.m4 \ + $(top_srcdir)/sntp/m4/ntp_prog_cc.m4 \ + $(top_srcdir)/sntp/m4/ntp_rlimit.m4 \ + $(top_srcdir)/sntp/m4/ntp_sntp.m4 \ + $(top_srcdir)/sntp/m4/ntp_ver_suffix.m4 \ + $(top_srcdir)/sntp/m4/ntp_vpathhack.m4 \ + $(top_srcdir)/sntp/m4/os_cflags.m4 \ + $(top_srcdir)/sntp/m4/snprintf.m4 \ + $(top_srcdir)/sntp/m4/version.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +AM_V_AR = $(am__v_AR_$(V)) +am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY)) +am__v_AR_0 = @echo " AR " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +libparse_a_AR = $(AR) $(ARFLAGS) +libparse_a_LIBADD = +am__objects_1 = +am_libparse_a_OBJECTS = parse.$(OBJEXT) parse_conf.$(OBJEXT) \ + clk_meinberg.$(OBJEXT) clk_schmid.$(OBJEXT) \ + clk_rawdcf.$(OBJEXT) clk_trimtsip.$(OBJEXT) \ + clk_dcf7000.$(OBJEXT) clk_trimtaip.$(OBJEXT) \ + clk_rcc8000.$(OBJEXT) clk_hopf6021.$(OBJEXT) \ + clk_computime.$(OBJEXT) clk_wharton.$(OBJEXT) \ + clk_varitext.$(OBJEXT) clk_sel240x.$(OBJEXT) \ + data_mbg.$(OBJEXT) info_trimble.$(OBJEXT) trim_info.$(OBJEXT) \ + binio.$(OBJEXT) ieee754io.$(OBJEXT) mfp_mul.$(OBJEXT) \ + gpstolfp.$(OBJEXT) $(am__objects_1) +libparse_a_OBJECTS = $(am_libparse_a_OBJECTS) +libparse_kernel_a_AR = $(AR) $(ARFLAGS) +am__DEPENDENCIES_1 = +libparse_kernel_a_DEPENDENCIES = kparse.o kparse_conf.o \ + kclk_computime.o kclk_dcf7000.o kclk_hopf6021.o \ + kclk_meinberg.o kclk_rawdcf.o kclk_rcc8000.o kclk_schmid.o \ + kclk_trimtaip.o kclk_trimtsip.o kclk_varitext.o kclk_wharton.o \ + kclk_sel240x.o kbinio.o kieee754io.o kmfp_mul.o kgpstolfp.o \ + $(am__DEPENDENCIES_1) +am_libparse_kernel_a_OBJECTS = +libparse_kernel_a_OBJECTS = $(am_libparse_kernel_a_OBJECTS) +PROGRAMS = $(noinst_PROGRAMS) +parsesolaris_SOURCES = parsesolaris.c +parsesolaris_OBJECTS = parsesolaris.$(OBJEXT) +parsesolaris_LDADD = $(LDADD) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +parsestreams_SOURCES = parsestreams.c +parsestreams_OBJECTS = parsestreams.$(OBJEXT) +parsestreams_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/sntp/libevent/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libparse_a_SOURCES) $(libparse_kernel_a_SOURCES) \ + parsesolaris.c parsestreams.c +DIST_SOURCES = $(libparse_a_SOURCES) $(libparse_kernel_a_SOURCES) \ + parsesolaris.c parsestreams.c +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CALC_TICKADJ_DB = @CALC_TICKADJ_DB@ +CALC_TICKADJ_DL = @CALC_TICKADJ_DL@ +CALC_TICKADJ_DS = @CALC_TICKADJ_DS@ +CALC_TICKADJ_MS = @CALC_TICKADJ_MS@ +CALC_TICKADJ_NI = @CALC_TICKADJ_NI@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAGS_NTP = @CFLAGS_NTP@ +CHUTEST = @CHUTEST@ +CONFIG_SHELL = @CONFIG_SHELL@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_NTP = @CPPFLAGS_NTP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DCFD = @DCFD@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EDITLINE_LIBS = @EDITLINE_LIBS@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GTEST_CONFIG = @GTEST_CONFIG@ +GTEST_CPPFLAGS = @GTEST_CPPFLAGS@ +GTEST_CXXFLAGS = @GTEST_CXXFLAGS@ +GTEST_LDFLAGS = @GTEST_LDFLAGS@ +GTEST_LIBS = @GTEST_LIBS@ +HAVE_INLINE = @HAVE_INLINE@ +HAVE_RLIMIT_MEMLOCK = @HAVE_RLIMIT_MEMLOCK@ +HAVE_RLIMIT_STACK = @HAVE_RLIMIT_STACK@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDADD_LIBNTP = @LDADD_LIBNTP@ +LDADD_NLIST = @LDADD_NLIST@ +LDADD_NTP = @LDADD_NTP@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_NTP = @LDFLAGS_NTP@ +LIBISC_PTHREADS_NOTHREADS = @LIBISC_PTHREADS_NOTHREADS@ +LIBM = @LIBM@ +LIBOBJS = @LIBOBJS@ +LIBOPTS_CFLAGS = @LIBOPTS_CFLAGS@ +LIBOPTS_DIR = @LIBOPTS_DIR@ +LIBOPTS_LDADD = @LIBOPTS_LDADD@ +LIBPARSE = @LIBPARSE@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LSCF = @LSCF@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MAKE_ADJTIMED = @MAKE_ADJTIMED@ +MAKE_CHECK_LAYOUT = @MAKE_CHECK_LAYOUT@ +MAKE_CHECK_Y2K = @MAKE_CHECK_Y2K@ +MAKE_LIBNTPSIM = @MAKE_LIBNTPSIM@ +MAKE_LIBPARSE = @MAKE_LIBPARSE@ +MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@ +MAKE_NTPDSIM = @MAKE_NTPDSIM@ +MAKE_NTPSNMPD = @MAKE_NTPSNMPD@ +MAKE_NTPTIME = @MAKE_NTPTIME@ +MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@ +MAKE_TICKADJ = @MAKE_TICKADJ@ +MAKE_TIMETRIM = @MAKE_TIMETRIM@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MANTAGFMT = @MANTAGFMT@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NTPDATE_DB = @NTPDATE_DB@ +NTPDATE_DL = @NTPDATE_DL@ +NTPDATE_DS = @NTPDATE_DS@ +NTPDATE_MS = @NTPDATE_MS@ +NTPDATE_NI = @NTPDATE_NI@ +NTPDC_DB = @NTPDC_DB@ +NTPDC_DL = @NTPDC_DL@ +NTPDC_DS = @NTPDC_DS@ +NTPDC_MS = @NTPDC_MS@ +NTPDC_NI = @NTPDC_NI@ +NTPDSIM_DB = @NTPDSIM_DB@ +NTPDSIM_DL = @NTPDSIM_DL@ +NTPDSIM_DS = @NTPDSIM_DS@ +NTPDSIM_MS = @NTPDSIM_MS@ +NTPDSIM_NI = @NTPDSIM_NI@ +NTPD_DB = @NTPD_DB@ +NTPD_DL = @NTPD_DL@ +NTPD_DS = @NTPD_DS@ +NTPD_MS = @NTPD_MS@ +NTPD_NI = @NTPD_NI@ +NTPQ_DB = @NTPQ_DB@ +NTPQ_DL = @NTPQ_DL@ +NTPQ_DS = @NTPQ_DS@ +NTPQ_MS = @NTPQ_MS@ +NTPQ_NI = @NTPQ_NI@ +NTPSNMPD_DB = @NTPSNMPD_DB@ +NTPSNMPD_DL = @NTPSNMPD_DL@ +NTPSNMPD_DS = @NTPSNMPD_DS@ +NTPSNMPD_MS = @NTPSNMPD_MS@ +NTPSNMPD_NI = @NTPSNMPD_NI@ +NTPSWEEP_DB = @NTPSWEEP_DB@ +NTPSWEEP_DL = @NTPSWEEP_DL@ +NTPSWEEP_DS = @NTPSWEEP_DS@ +NTPSWEEP_MS = @NTPSWEEP_MS@ +NTPSWEEP_NI = @NTPSWEEP_NI@ +NTPTIME_DB = @NTPTIME_DB@ +NTPTIME_DL = @NTPTIME_DL@ +NTPTIME_DS = @NTPTIME_DS@ +NTPTIME_MS = @NTPTIME_MS@ +NTPTIME_NI = @NTPTIME_NI@ +NTPTRACE_DB = @NTPTRACE_DB@ +NTPTRACE_DL = @NTPTRACE_DL@ +NTPTRACE_DS = @NTPTRACE_DS@ +NTPTRACE_MS = @NTPTRACE_MS@ +NTPTRACE_NI = @NTPTRACE_NI@ +NTP_KEYGEN_DB = @NTP_KEYGEN_DB@ +NTP_KEYGEN_DL = @NTP_KEYGEN_DL@ +NTP_KEYGEN_DS = @NTP_KEYGEN_DS@ +NTP_KEYGEN_MS = @NTP_KEYGEN_MS@ +NTP_KEYGEN_NI = @NTP_KEYGEN_NI@ +NTP_KEYSDIR = @NTP_KEYSDIR@ +NTP_WAIT_DB = @NTP_WAIT_DB@ +NTP_WAIT_DL = @NTP_WAIT_DL@ +NTP_WAIT_DS = @NTP_WAIT_DS@ +NTP_WAIT_MS = @NTP_WAIT_MS@ +NTP_WAIT_NI = @NTP_WAIT_NI@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_NET_SNMP_CONFIG = @PATH_NET_SNMP_CONFIG@ +PATH_PERL = @PATH_PERL@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PATH_TEST = @PATH_TEST@ +PERLLIBDIR = @PERLLIBDIR@ +PKG_CONFIG = @PKG_CONFIG@ +POSIX_SHELL = @POSIX_SHELL@ +PROPDELAY = @PROPDELAY@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SNMP_CFLAGS = @SNMP_CFLAGS@ +SNMP_CPPFLAGS = @SNMP_CPPFLAGS@ +SNMP_LIBS = @SNMP_LIBS@ +SNTP = @SNTP@ +SNTP_DB = @SNTP_DB@ +SNTP_DL = @SNTP_DL@ +SNTP_DS = @SNTP_DS@ +SNTP_MS = @SNTP_MS@ +SNTP_NI = @SNTP_NI@ +STDNORETURN_H = @STDNORETURN_H@ +STRIP = @STRIP@ +TESTDCF = @TESTDCF@ +TICKADJ_DB = @TICKADJ_DB@ +TICKADJ_DL = @TICKADJ_DL@ +TICKADJ_DS = @TICKADJ_DS@ +TICKADJ_MS = @TICKADJ_MS@ +TICKADJ_NI = @TICKADJ_NI@ +TIMETRIM_DB = @TIMETRIM_DB@ +TIMETRIM_DL = @TIMETRIM_DL@ +TIMETRIM_DS = @TIMETRIM_DS@ +TIMETRIM_MS = @TIMETRIM_MS@ +TIMETRIM_NI = @TIMETRIM_NI@ +VERSION = @VERSION@ +VER_SUFFIX = @VER_SUFFIX@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +NULL = +BUILT_SOURCES = check-libntp .deps-ver +CLEANFILES = check-libntp .deps-ver +noinst_LIBRARIES = @MAKE_LIBPARSE@ @MAKE_LIBPARSE_KERNEL@ +EXTRA_LIBRARIES = libparse.a libparse_kernel.a +noinst_PROGRAMS = @MAKE_PARSEKMODULE@ +K_CFLAGS = -DPARSESTREAM -DNTP_NEED_BOPS + +# info_trimble.c was mistakenly created in the build directory +# previously. It is located in $(srcdir) and any updates must +# end up there. +libparse_a_SOURCES = parse.c \ + parse_conf.c \ + clk_meinberg.c \ + clk_schmid.c \ + clk_rawdcf.c \ + clk_trimtsip.c \ + clk_dcf7000.c \ + clk_trimtaip.c \ + clk_rcc8000.c \ + clk_hopf6021.c \ + clk_computime.c \ + clk_wharton.c \ + clk_varitext.c \ + clk_sel240x.c \ + data_mbg.c \ + info_trimble.c \ + trim_info.c \ + binio.c \ + ieee754io.c \ + mfp_mul.c \ + gpstolfp.c \ + $(NULL) + +libparse_kernel_a_SOURCES = +libparse_kernel_a_LIBADD = \ + kparse.o \ + kparse_conf.o \ + kclk_computime.o \ + kclk_dcf7000.o \ + kclk_hopf6021.o \ + kclk_meinberg.o \ + kclk_rawdcf.o \ + kclk_rcc8000.o \ + kclk_schmid.o \ + kclk_trimtaip.o \ + kclk_trimtsip.o \ + kclk_varitext.o \ + kclk_wharton.o \ + kclk_sel240x.o \ + kbinio.o \ + kieee754io.o \ + kmfp_mul.o \ + kgpstolfp.o \ + $(NULL) + +AM_CFLAGS = $(CFLAGS_NTP) +AM_CPPFLAGS = $(NTP_INCS) -I$(top_srcdir)/kernel $(CPPFLAGS_NTP) +EXTRA_DIST = parsesolaris.c parsestreams.c mkinfo_scmd.sed mkinfo_rcmd.sed info_trimble.c +NTP_INCS = -I$(top_srcdir)/include -I$(top_srcdir)/lib/isc/include \ + -I$(top_srcdir)/lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/include \ + -I$(top_srcdir)/lib/isc/unix/include +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/sntp/check-libntp.mf $(top_srcdir)/depsver.mf $(top_srcdir)/includes.mf $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libparse/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign libparse/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libparse.a: $(libparse_a_OBJECTS) $(libparse_a_DEPENDENCIES) + $(AM_V_at)-rm -f libparse.a + $(AM_V_AR)$(libparse_a_AR) libparse.a $(libparse_a_OBJECTS) $(libparse_a_LIBADD) + $(AM_V_at)$(RANLIB) libparse.a +libparse_kernel.a: $(libparse_kernel_a_OBJECTS) $(libparse_kernel_a_DEPENDENCIES) + $(AM_V_at)-rm -f libparse_kernel.a + $(AM_V_AR)$(libparse_kernel_a_AR) libparse_kernel.a $(libparse_kernel_a_OBJECTS) $(libparse_kernel_a_LIBADD) + $(AM_V_at)$(RANLIB) libparse_kernel.a + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +parsesolaris$(EXEEXT): $(parsesolaris_OBJECTS) $(parsesolaris_DEPENDENCIES) + @rm -f parsesolaris$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(parsesolaris_OBJECTS) $(parsesolaris_LDADD) $(LIBS) +parsestreams$(EXEEXT): $(parsestreams_OBJECTS) $(parsestreams_DEPENDENCIES) + @rm -f parsestreams$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(parsestreams_OBJECTS) $(parsestreams_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clk_computime.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clk_dcf7000.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clk_hopf6021.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clk_meinberg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clk_rawdcf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clk_rcc8000.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clk_schmid.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clk_sel240x.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clk_trimtaip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clk_trimtsip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clk_varitext.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clk_wharton.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data_mbg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpstolfp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ieee754io.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info_trimble.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mfp_mul.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse_conf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parsesolaris.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parsestreams.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trim_info.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LIBRARIES) $(PROGRAMS) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLIBRARIES clean-noinstPROGRAMS ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +$(srcdir)/info_trimble.c: $(top_srcdir)/include/trimble.h $(srcdir)/Makefile.am $(srcdir)/mkinfo_scmd.sed $(srcdir)/mkinfo_rcmd.sed + sed -n -f $(srcdir)/mkinfo_scmd.sed $(top_srcdir)/include/trimble.h > info_trimble.new + sed -n -f $(srcdir)/mkinfo_rcmd.sed $(top_srcdir)/include/trimble.h >> info_trimble.new + mv -f info_trimble.new $@ + +kieee754io.o: $(srcdir)/ieee754io.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/ieee754io.c -o $@ + +kmfp_mul.o: $(srcdir)/mfp_mul.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/mfp_mul.c -o $@ + +kgpstolfp.o: $(srcdir)/gpstolfp.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/gpstolfp.c -o $@ + +kbinio.o: $(srcdir)/binio.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/binio.c -o $@ + +kclk_computime.o: $(srcdir)/clk_computime.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_computime.c -o $@ + +kclk_dcf7000.o: $(srcdir)/clk_dcf7000.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_dcf7000.c -o $@ + +kclk_hopf6021.o: $(srcdir)/clk_hopf6021.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_hopf6021.c -o $@ + +kclk_meinberg.o: $(srcdir)/clk_meinberg.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_meinberg.c -o $@ + +kclk_rawdcf.o: $(srcdir)/clk_rawdcf.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_rawdcf.c -o $@ + +kclk_rcc8000.o: $(srcdir)/clk_rcc8000.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_rcc8000.c -o $@ + +kclk_schmid.o: $(srcdir)/clk_schmid.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_schmid.c -o $@ + +kclk_trimtaip.o: $(srcdir)/clk_trimtaip.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_trimtaip.c -o $@ + +kclk_trimtsip.o: $(srcdir)/clk_trimtsip.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_trimtsip.c -o $@ + +kclk_varitext.o: $(srcdir)/clk_varitext.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_varitext.c -o $@ + +kclk_wharton.o: $(srcdir)/clk_wharton.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_wharton.c -o $@ + +kclk_sel240x.o: $(srcdir)/clk_sel240x.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_sel240x.c -o $@ + +kparse.o: $(srcdir)/parse.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/parse.c -o $@ + +kparse_conf.o: $(srcdir)/parse_conf.c + $(COMPILE) $(K_CFLAGS) -c $(srcdir)/parse_conf.c -o $@ + +parsestreams.loadable_module.o: $(parsestreams_OBJECTS) libparse_kernel.a ../libntp/libntp.a + $(LD) -r -o $@ $(parsestreams_OBJECTS) libparse_kernel.a ../libntp/libntp.a + +parse: $(parsesolaris_OBJECTS) libparse_kernel.a ../libntp/libntp.a + $(LD) -r -o $@ $(parsesolaris_OBJECTS) libparse_kernel.a ../libntp/libntp.a + +parsesolaris.o: sys/systm.h + +sys/systm.h: + -mkdir sys + sed -e '/ffs(.*)/d' < /usr/include/sys/systm.h > sys/systm.h + +check-libparse: $(noinst_LIBRARIES) + @: do-nothing action to avoid default SCCS get + +check-libntp: ../libntp/libntp.a + @echo stamp > $@ + +../libntp/libntp.a: + cd ../libntp && $(MAKE) $(AM_MAKEFLAGS) libntp.a +$(DEPDIR)/deps-ver: $(top_srcdir)/deps-ver + @[ -f $@ ] || \ + cp $(top_srcdir)/deps-ver $@ + @[ -w $@ ] || \ + chmod ug+w $@ + @cmp $(top_srcdir)/deps-ver $@ > /dev/null || ( \ + $(MAKE) $(AM_MAKEFLAGS) clean && \ + echo -n "Prior $(subdir)/$(DEPDIR) version " && \ + cat $@ && \ + rm -rf $(DEPDIR) && \ + mkdir $(DEPDIR) && \ + case "$(top_builddir)" in \ + .) \ + ./config.status Makefile depfiles \ + ;; \ + *) \ + cd "$(top_builddir)" && \ + ./config.status $(subdir)/Makefile depfiles && \ + cd $(subdir) \ + ;; \ + esac && \ + echo -n "Cleaned $(subdir)/$(DEPDIR) version " && \ + cat $(top_srcdir)/deps-ver \ + ) + cp $(top_srcdir)/deps-ver $@ + +.deps-ver: $(top_srcdir)/deps-ver + @[ ! -d $(DEPDIR) ] || $(MAKE) $(AM_MAKEFLAGS) $(DEPDIR)/deps-ver + @touch $@ + +# +# depsver.mf included in Makefile.am for directories with .deps +# +# When building in the same directory with sources that change over +# time, such as when tracking using bk, the .deps files can become +# stale with respect to moved, deleted, or superceded headers. Most +# commonly, this would exhibit as make reporting a failure to make a +# header file which is no longer in the location given. To address +# this issue, we use a deps-ver file which is updated with each change +# that breaks old .deps files. A copy of deps-ver is made into +# $(DEPDIR) if not already present. If $(DEPDIR)/deps-ver is present +# with different contents than deps-ver, we make clean to ensure all +# .o files built before the incompatible change are rebuilt along with +# their updated .deps files, then remove $(DEPDIR) and recreate it as +# empty stubs. +# +# It is normal when configured with --disable-dependency-tracking for +# the DEPDIR to not have been created. For this reason, we use the +# intermediate target .deps-ver, which invokes make recursively if +# DEPDIR exists. +# +# If you modify depsver.mf, please make the changes to the master +# copy, the one in sntp is copied by the bootstrap script from it. +# +# This comment block follows rather than leads the related code so that +# it stays with it in the generated Makefile.in and Makefile. +# + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libparse/README b/libparse/README new file mode 100644 index 0000000..ac77054 --- /dev/null +++ b/libparse/README @@ -0,0 +1,96 @@ +PARSE reference clock driver: + +This directory contains the files making up the parser for +the parse refclock driver. For reasonably sane clocks this refclock +drivers allows a refclock implementation by just providing a +conversion routine and the appropriate NTP parameters. Refclock +support can run as low a 3k code with the parse refclock driver. + +The modules in here are designed to live in two worlds. In userlevel +as part of the xntp daemon and in kernel land as part of a STREAMS module +or, if someone gets to it, as part of a line discipline. Currently only +SunOS4.x/SunOS5.x STREAMS are supported (volunteers for other vendors like HP?). +This structure means, that refclock_parse can work with or without kernel +support. Kernelsupport increases accuracy tremendingly. The current restriction +of the parse driver is that it only supports SYSV type ttys and that kernel +support is only available for Suns right now. + +Three kernel modules are part of this directory. These work only on +SunOS (SunOS4 and SunOS5). + + SunOS4 (aka Solaris 1.x): + parsestreams.loadable_module.o - standard parse module for SunOS 4 + + Both modules can be loaded via modload . + + SunOS5 (aka Solaris 2.x): + parse - auto loadable streams module + + To install just drop "parse" into /kernel/strmod and + start the daemon (SunOS5 will do the rest). + +The structure of the parse reference clock driver is as follows: + + ntpd - contains NTP implementation and calls a reference clock + 127.127.8.x which is implemented by + refclock_parse.c + - which contains several refclock decriptions. These are + selected by the x part of the refclock address. + The lower two bits specify the device to use. Thus the + value (x % 4) determines the device to open + (/dev/refclock-0 - /dev/refclock-3). + + The kind of clock is selected by the mode parameter. This parameter + selects the clock type which deterimines how I/O is done, + the tty parameters and the NTP parameters. + + refclock_parse operates on an abstract reference clock + that delivers time stamps and stati. Offsets and sychron- + isation information is derived from this data and passed + on to refclock_receive of xntp which uses that data for + syncronisation. + + The abstract reference clock is generated by the parse* + routines. They parse the incoming data stream from the + clock and convert it to the appropriate time stamps. + The data is also mapped int the abstract clock states + POWERUP - clock has no valid phase and time code + information + + NOSYNC - Time code is not confirmed, phase is probably + ok. + SYNC - Time code and phase are correct. + + A clock is trusted for a certain time (type parameter) when + it leaves the SYNC state. This is derived from the + observation that quite a few clocks can still generate good + time code information when losing contact to their + synchronisation source. When the clock does not reagain + synchronisation in that trust period it will be deemed + unsynchronised until it regains synchronisation. The same + will happen if xntp sees the clock unsynchronised at + startup. + + The upper bit of x specifies that all samples delivered + from the clock should be used to discipline the NTP + loopfilter. For clock with accurate once a second time + information this means big improvements for time keeping. + A prerequisite for passing on the time stamps to + the loopfilter is, that the clock is in synchronised state. + + parse.c These are the general routines to parse the incoming data + stream. Usually these routines should not require + modification. + + clk_*.c These files hole the conversion code for the time stamps + and the description how the time code can be parsed and + where the time stamps are to be taken. + If you want to add a new clock type this is the file + you need to write in addition to mention it in + parse_conf.c and setting up the NTP and TTY parameters + in refclock_parse.c. + +Further information can be found in parse/README.parse and the various source +files. + +Frank Kardel diff --git a/libparse/binio.c b/libparse/binio.c new file mode 100644 index 0000000..24aa286 --- /dev/null +++ b/libparse/binio.c @@ -0,0 +1,156 @@ +/* + * /src/NTP/ntp4-dev/libntp/binio.c,v 4.5 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * binio.c,v 4.5 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * $Created: Sun Jul 20 12:55:33 1997 $ + * + * Copyright (c) 1997-2005 by Frank Kardel ntp.org> + * + * 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. + * + */ + +#include +#include "binio.h" + +long +get_lsb_short( + unsigned char **bufpp + ) +{ + long retval; + + retval = *((*bufpp)++); + retval |= *((*bufpp)++) << 8; + + return (retval & 0x8000) ? (~0xFFFF | retval) : retval; +} + +void +put_lsb_short( + unsigned char **bufpp, + long val + ) +{ + *((*bufpp)++) = (unsigned char) (val & 0xFF); + *((*bufpp)++) = (unsigned char) ((val >> 8) & 0xFF); +} + +long +get_lsb_long( + unsigned char **bufpp + ) +{ + long retval; + + retval = *((*bufpp)++); + retval |= *((*bufpp)++) << 8; + retval |= *((*bufpp)++) << 16; + retval |= (u_long)*((*bufpp)++) << 24; + + return retval; +} + +void +put_lsb_long( + unsigned char **bufpp, + long val + ) +{ + *((*bufpp)++) = (unsigned char)(val & 0xFF); + *((*bufpp)++) = (unsigned char)((val >> 8) & 0xFF); + *((*bufpp)++) = (unsigned char)((val >> 16) & 0xFF); + *((*bufpp)++) = (unsigned char)((val >> 24) & 0xFF); +} + +long +get_msb_short( + unsigned char **bufpp + ) +{ + long retval; + + retval = *((*bufpp)++) << 8; + retval |= *((*bufpp)++); + + return (retval & 0x8000) ? (~0xFFFF | retval) : retval; +} + +void +put_msb_short( + unsigned char **bufpp, + long val + ) +{ + *((*bufpp)++) = (unsigned char)((val >> 8) & 0xFF); + *((*bufpp)++) = (unsigned char)( val & 0xFF); +} + +long +get_msb_long( + unsigned char **bufpp + ) +{ + long retval; + + retval = (u_long)*((*bufpp)++) << 24; + retval |= *((*bufpp)++) << 16; + retval |= *((*bufpp)++) << 8; + retval |= *((*bufpp)++); + + return retval; +} + +void +put_msb_long( + unsigned char **bufpp, + long val + ) +{ + *((*bufpp)++) = (unsigned char)((val >> 24) & 0xFF); + *((*bufpp)++) = (unsigned char)((val >> 16) & 0xFF); + *((*bufpp)++) = (unsigned char)((val >> 8 ) & 0xFF); + *((*bufpp)++) = (unsigned char)( val & 0xFF); +} + +/* + * binio.c,v + * Revision 4.2 1999/02/21 12:17:34 kardel + * 4.91f reconcilation + * + * Revision 4.1 1998/06/28 16:47:50 kardel + * added {get,put}_msb_{short,long} functions + * + * Revision 4.0 1998/04/10 19:46:16 kardel + * Start 4.0 release version numbering + * + * Revision 1.1 1998/04/10 19:27:46 kardel + * initial NTP VERSION 4 integration of PARSE with GPS166 binary support + * + * Revision 1.1 1997/10/06 21:05:46 kardel + * new parse structure + * + */ diff --git a/libparse/clk_computime.c b/libparse/clk_computime.c new file mode 100644 index 0000000..1068576 --- /dev/null +++ b/libparse/clk_computime.c @@ -0,0 +1,219 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_COMPUTIME) +/* + * /src/NTP/ntp4-dev/libparse/clk_computime.c,v 4.10 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * clk_computime.c,v 4.10 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * Supports Diem's Computime Radio Clock + * + * Used the Meinberg clock as a template for Diem's Computime Radio Clock + * + * adapted by Alois Camenzind + * + * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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. + * + */ + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" +#include "ntp_stdlib.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include +#else +#include "sys/parsestreams.h" +extern int printf (const char *, ...); +#endif + +/* + * The Computime receiver sends a datagram in the following format every minute + * + * Timestamp T:YY:MM:MD:WD:HH:MM:SSCRLF + * Pos 0123456789012345678901 2 3 + * 0000000000111111111122 2 2 + * Parse T: : : : : : : rn + * + * T Startcharacter "T" specifies start of the timestamp + * YY Year MM Month 1-12 + * MD Day of the month + * WD Day of week + * HH Hour + * MM Minute + * SS Second + * CR Carriage return + * LF Linefeed + * + */ + +static struct format computime_fmt = +{ + { + {8, 2}, {5, 2}, {2, 2}, /* day, month, year */ + {14, 2}, {17, 2}, {20, 2}, /* hour, minute, second */ + {11, 2}, /* dayofweek, */ + }, + (const unsigned char *)"T: : : : : : : \r\n", + 0 +}; + +static u_long cvt_computime (unsigned char *, int, struct format *, clocktime_t *, void *); +static unsigned long inp_computime (parse_t *, unsigned int, timestamp_t *); + +clockformat_t clock_computime = +{ + inp_computime, /* Computime input handling */ + cvt_computime, /* Computime conversion */ + 0, /* no PPS monitoring */ + (void *)&computime_fmt, /* conversion configuration */ + "Diem's Computime Radio Clock", /* Computime Radio Clock */ + 24, /* string buffer */ + 0 /* no private data (complete pakets) */ +}; + +/* + * cvt_computime + * + * convert simple type format + */ +static u_long +cvt_computime( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + + if (!Strok(buffer, format->fixed_string)) { + return CVT_NONE; + } else { + if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, + format->field_offsets[O_DAY].length) || + Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, + format->field_offsets[O_MONTH].length) || + Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, + format->field_offsets[O_YEAR].length) || + Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, + format->field_offsets[O_HOUR].length) || + Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, + format->field_offsets[O_MIN].length) || + Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, + format->field_offsets[O_SEC].length)) { + return CVT_FAIL | CVT_BADFMT; + } else { + + clock_time->flags = 0; + clock_time->utcoffset = 0; /* We have UTC time */ + + return CVT_OK; + } + } +} + +/* + * inp_computime + * + * grep data from input stream + */ +static u_long +inp_computime( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_computime(0x%lx, 0x%x, ...)\n", (long)parseio, ch)); + + switch (ch) + { + case 'T': + parseprintf(DD_PARSE, ("inp_computime: START seen\n")); + + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + return PARSE_INP_SKIP; + + case '\n': + parseprintf(DD_PARSE, ("inp_computime: END seen\n")); + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + default: + return parse_addchar(parseio, ch); + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_COMPUTIME) */ +int clk_computime_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_COMPUTIME) */ + +/* + * clk_computime.c,v + * Revision 4.10 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.9 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.6 1999/11/28 09:13:49 kardel + * RECON_4_0_98F + * + * Revision 4.5 1998/06/14 21:09:34 kardel + * Sun acc cleanup + * + * Revision 4.4 1998/06/13 12:00:38 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:26 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:24 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:51 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:27 kardel + * Start 4.0 release version numbering + * + * from V3 1.8 log info deleted 1998/04/11 kardel + */ diff --git a/libparse/clk_dcf7000.c b/libparse/clk_dcf7000.c new file mode 100644 index 0000000..bfd9a74 --- /dev/null +++ b/libparse/clk_dcf7000.c @@ -0,0 +1,214 @@ +/* + * /src/NTP/ntp4-dev/libparse/clk_dcf7000.c,v 4.10 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * clk_dcf7000.c,v 4.10 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * ELV DCF7000 module + * + * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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 +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_DCF7000) + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include +#else +#include "sys/parsestreams.h" +extern int printf (const char *, ...); +#endif + +static struct format dcf7000_fmt = +{ /* ELV DCF7000 */ + { + { 6, 2}, { 3, 2}, { 0, 2}, + { 12, 2}, { 15, 2}, { 18, 2}, + { 9, 2}, { 21, 2}, + }, + (const unsigned char *)" - - - - - - - \r", + 0 +}; +static u_long cvt_dcf7000 (unsigned char *, int, struct format *, clocktime_t *, void *); +static unsigned long inp_dcf7000 (parse_t *, unsigned int, timestamp_t *); + +clockformat_t clock_dcf7000 = +{ + inp_dcf7000, /* DCF7000 input handling */ + cvt_dcf7000, /* ELV DCF77 conversion */ + 0, /* no direct PPS monitoring */ + (void *)&dcf7000_fmt, /* conversion configuration */ + "ELV DCF7000", /* ELV clock */ + 24, /* string buffer */ + 0 /* no private data (complete pakets) */ +}; + +/* + * cvt_dcf7000 + * + * convert dcf7000 type format + */ +static u_long +cvt_dcf7000( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + if (!Strok(buffer, format->fixed_string)) + { + return CVT_NONE; + } + else + { + if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, + format->field_offsets[O_DAY].length) || + Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, + format->field_offsets[O_MONTH].length) || + Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, + format->field_offsets[O_YEAR].length) || + Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, + format->field_offsets[O_HOUR].length) || + Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, + format->field_offsets[O_MIN].length) || + Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, + format->field_offsets[O_SEC].length)) + { + return CVT_FAIL|CVT_BADFMT; + } + else + { + unsigned char *f = &buffer[format->field_offsets[O_FLAGS].offset]; + long flags; + + clock_time->flags = 0; + clock_time->usecond = 0; + + if (Stoi(f, &flags, format->field_offsets[O_FLAGS].length)) + { + return CVT_FAIL|CVT_BADFMT; + } + else + { + if (flags & 0x1) + clock_time->utcoffset = -2*60*60; + else + clock_time->utcoffset = -1*60*60; + + if (flags & 0x2) + clock_time->flags |= PARSEB_ANNOUNCE; + + if (flags & 0x4) + clock_time->flags |= PARSEB_NOSYNC; + } + return CVT_OK; + } + } +} + +/* + * inp_dcf700 + * + * grep data from input stream + */ +static u_long +inp_dcf7000( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_dcf7000(0x%lx, 0x%x, ...)\n", (long)parseio, ch)); + + switch (ch) + { + case '\r': + parseprintf(DD_PARSE, ("inp_dcf7000: EOL seen\n")); + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + default: + return parse_addchar(parseio, ch); + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_DCF7000) */ +int clk_dcf7000_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_DCF7000) */ + +/* + * History: + * + * clk_dcf7000.c,v + * Revision 4.10 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.9 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.6 1999/11/28 09:13:49 kardel + * RECON_4_0_98F + * + * Revision 4.5 1998/06/14 21:09:34 kardel + * Sun acc cleanup + * + * Revision 4.4 1998/06/13 12:01:59 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:27 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:24 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:51 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:28 kardel + * Start 4.0 release version numbering + * + * from V3 3.18 log info deleted 1998/04/11 kardel + */ diff --git a/libparse/clk_hopf6021.c b/libparse/clk_hopf6021.c new file mode 100644 index 0000000..033d2d2 --- /dev/null +++ b/libparse/clk_hopf6021.c @@ -0,0 +1,283 @@ +/* + * /src/NTP/ntp4-dev/libparse/clk_hopf6021.c,v 4.10 2004/11/14 15:29:41 kardel RELEASE_20050508_A + * + * clk_hopf6021.c,v 4.10 2004/11/14 15:29:41 kardel RELEASE_20050508_A + * + * Radiocode Clocks HOPF Funkuhr 6021 mit serieller Schnittstelle + * base code version from 24th Nov 1995 - history at end + * + * Created by F.Schnekenbuehl from clk_rcc8000.c + * Nortel DASA Network Systems GmbH, Department: ND250 + * A Joint venture of Daimler-Benz Aerospace and Nortel + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_HOPF6021) + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" +#include "ascii.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include +#else +#include "sys/parsestreams.h" +extern int printf (const char *, ...); +#endif + +/* + * hopf Funkuhr 6021 + * used with 9600,8N1, + * UTC ueber serielle Schnittstelle + * Sekundenvorlauf ON + * ETX zum Sekundenvorlauf ON + * Datenstring 6021 + * Ausgabe Uhrzeit und Datum + * Senden mit Steuerzeichen + * Senden sekuendlich + */ + +/* + * Type 6021 Serial Output format + * + * 000000000011111111 / char + * 012345678901234567 \ position + * sABHHMMSSDDMMYYnre Actual + * C4110046231195 Parse + * s enr Check + * + * s = STX (0x02), e = ETX (0x03) + * n = NL (0x0A), r = CR (0x0D) + * + * A B - Status and weekday + * + * A - Status + * + * 8 4 2 1 + * x x x 0 - no announcement + * x x x 1 - Summertime - wintertime - summertime announcement + * x x 0 x - Wintertime + * x x 1 x - Summertime + * 0 0 x x - Time/Date invalid + * 0 1 x x - Internal clock used + * 1 0 x x - Radio clock + * 1 1 x x - Radio clock highprecision + * + * B - 8 4 2 1 + * 0 x x x - MESZ/MEZ + * 1 x x x - UTC + * x 0 0 1 - Monday + * x 0 1 0 - Tuesday + * x 0 1 1 - Wednesday + * x 1 0 0 - Thursday + * x 1 0 1 - Friday + * x 1 1 0 - Saturday + * x 1 1 1 - Sunday + */ + +#define HOPF_DSTWARN 0x01 /* DST switch warning */ +#define HOPF_DST 0x02 /* DST in effect */ + +#define HOPF_MODE 0x0C /* operation mode mask */ +#define HOPF_INVALID 0x00 /* no time code available */ +#define HOPF_INTERNAL 0x04 /* internal clock */ +#define HOPF_RADIO 0x08 /* radio clock */ +#define HOPF_RADIOHP 0x0C /* high precision radio clock */ + +#define HOPF_UTC 0x08 /* time code in UTC */ +#define HOPF_WMASK 0x07 /* mask for weekday code */ + +static struct format hopf6021_fmt = +{ + { + { 9, 2 }, {11, 2}, { 13, 2}, /* Day, Month, Year */ + { 3, 2 }, { 5, 2}, { 7, 2}, /* Hour, Minute, Second */ + { 2, 1 }, { 1, 1}, { 0, 0}, /* Weekday, Flags, Zone */ + /* ... */ + }, + (const unsigned char *)"\002 \n\r\003", + 0 +}; + +#define OFFS(x) format->field_offsets[(x)].offset +#define STOI(x, y) Stoi(&buffer[OFFS(x)], y, format->field_offsets[(x)].length) +#define hexval(x) (('0' <= (x) && (x) <= '9') ? (x) - '0' : \ + ('a' <= (x) && (x) <= 'f') ? (x) - 'a' + 10 : \ + ('A' <= (x) && (x) <= 'F') ? (x) - 'A' + 10 : \ + -1) + +static unsigned long cvt_hopf6021 (unsigned char *, int, struct format *, clocktime_t *, void *); +static unsigned long inp_hopf6021 (parse_t *, unsigned int, timestamp_t *); + +clockformat_t clock_hopf6021 = +{ + inp_hopf6021, /* HOPF 6021 input handling */ + cvt_hopf6021, /* Radiocode clock conversion */ + 0, /* no direct PPS monitoring */ + (void *)&hopf6021_fmt, /* conversion configuration */ + "hopf Funkuhr 6021", /* clock format name */ + 19, /* string buffer */ + 0 /* private data length, no private data */ +}; + +static unsigned long +cvt_hopf6021( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + unsigned char status,weekday; + + if (!Strok(buffer, format->fixed_string)) + { + return CVT_NONE; + } + + if ( STOI(O_DAY, &clock_time->day) || + STOI(O_MONTH, &clock_time->month) || + STOI(O_YEAR, &clock_time->year) || + STOI(O_HOUR, &clock_time->hour) || + STOI(O_MIN, &clock_time->minute) || + STOI(O_SEC, &clock_time->second) + ) + { + return CVT_FAIL|CVT_BADFMT; + } + + clock_time->usecond = 0; + clock_time->utcoffset = 0; + + status = hexval(buffer[OFFS(O_FLAGS)]); + weekday= hexval(buffer[OFFS(O_WDAY)]); + + if ((status == 0xFF) || (weekday == 0xFF)) + { + return CVT_FAIL|CVT_BADFMT; + } + + clock_time->flags = 0; + + if (weekday & HOPF_UTC) + { + clock_time->flags |= PARSEB_UTC; + } + else + { + if (status & HOPF_DST) + { + clock_time->flags |= PARSEB_DST; + clock_time->utcoffset = -2*60*60; /* MET DST */ + } + else + { + clock_time->utcoffset = -1*60*60; /* MET */ + } + } + + clock_time->flags |= (status & HOPF_DSTWARN) ? PARSEB_ANNOUNCE : 0; + + switch (status & HOPF_MODE) + { + case HOPF_INVALID: /* Time/Date invalid */ + clock_time->flags |= PARSEB_POWERUP; + break; + + case HOPF_INTERNAL: /* internal clock */ + clock_time->flags |= PARSEB_NOSYNC; + break; + + case HOPF_RADIO: /* Radio clock */ + case HOPF_RADIOHP: /* Radio clock high precision */ + break; + + default: + return CVT_FAIL|CVT_BADFMT; + } + + return CVT_OK; +} + +/* + * inp_hopf6021 + * + * grep data from input stream + */ +static u_long +inp_hopf6021( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_hopf6021(0x%lx, 0x%x, ...)\n", (long)parseio, ch)); + + switch (ch) + { + case ETX: + parseprintf(DD_PARSE, ("inp_hopf6021: EOL seen\n")); + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + default: + return parse_addchar(parseio, ch); + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */ +int clk_hopf6021_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */ + +/* + * History: + * + * clk_hopf6021.c,v + * Revision 4.10 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.7 1999/11/28 09:13:49 kardel + * RECON_4_0_98F + * + * Revision 4.6 1998/11/15 20:27:57 kardel + * Release 4.0.73e13 reconcilation + * + * Revision 4.5 1998/06/14 21:09:35 kardel + * Sun acc cleanup + * + * Revision 4.4 1998/06/13 12:02:38 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:27 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:25 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:52 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:29 kardel + * Start 4.0 release version numbering + * + * from V3 3.6 log info deleted 1998/04/11 kardel + */ diff --git a/libparse/clk_meinberg.c b/libparse/clk_meinberg.c new file mode 100644 index 0000000..bc0ac0e --- /dev/null +++ b/libparse/clk_meinberg.c @@ -0,0 +1,776 @@ +/* + * /src/NTP/REPOSITORY/ntp4-dev/libparse/clk_meinberg.c,v 4.12.2.1 2005/09/25 10:22:35 kardel RELEASE_20050925_A + * + * clk_meinberg.c,v 4.12.2.1 2005/09/25 10:22:35 kardel RELEASE_20050925_A + * + * Meinberg clock support + * + * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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 +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_MEINBERG) + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "ntp_machine.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include +#else +#include "sys/parsestreams.h" +#endif + +#include "ntp_stdlib.h" + +#include "ntp_stdlib.h" + +#include "mbg_gps166.h" +#include "binio.h" +#include "ascii.h" + +/* + * The Meinberg receiver every second sends a datagram of the following form + * (Standard Format) + * + * D:
..;T:;U:::; + * pos: 0 00 00 0 00 0 11 111 1 111 12 2 22 2 22 2 2 2 3 3 3 + * 1 23 45 6 78 9 01 234 5 678 90 1 23 4 56 7 8 9 0 1 2 + * = '\002' ASCII start of text + * = '\003' ASCII end of text + *
,, = day, month, year(2 digits!!) + * = day of week (sunday= 0) + * ,, = hour, minute, second + * = '#' if never synced since powerup for DCF C51 + * = '#' if not PZF sychronisation available for PZF 535/509 + * = ' ' if ok + * = '*' if time comes from internal quartz + * = ' ' if completely synched + * = 'S' if daylight saving time is active + * = 'U' if time is represented in UTC + * = ' ' if no special condition exists + * = '!' during the hour preceeding an daylight saving time + * start/end change + * = 'A' leap second insert warning + * = ' ' if no special condition exists + * + * Extended data format (PZFUERL for PZF type clocks) + * + *
..; ; ::; + * pos: 0 00 0 00 0 00 11 1 11 11 1 11 2 22 22 2 2 2 2 2 3 3 3 + * 1 23 4 56 7 89 01 2 34 56 7 89 0 12 34 5 6 7 8 9 0 1 2 + * = '\002' ASCII start of text + * = '\003' ASCII end of text + *
,, = day, month, year(2 digits!!) + * = day of week (sunday= 0) + * ,, = hour, minute, second + * = 'U' UTC time display + * = '#' if never synced since powerup else ' ' for DCF C51 + * '#' if not PZF sychronisation available else ' ' for PZF 535/509 + * = '*' if time comes from internal quartz else ' ' + * = 'S' if daylight saving time is active else ' ' + * = '!' during the hour preceeding an daylight saving time + * start/end change + * = 'A' LEAP second announcement + * = 'R' alternate antenna + * + * Meinberg GPS166 receiver + * + * You must get the Uni-Erlangen firmware for the GPS receiver support + * to work to full satisfaction ! + * + *
..; ; ::; <+/-><00:00>; ; + * + * 000000000111111111122222222223333333333444444444455555555556666666 + * 123456789012345678901234567890123456789012345678901234567890123456 + * \x0209.07.93; 5; 08:48:26; +00:00; #*S!A L; 49.5736N 11.0280E 373m\x03 + * + * + * = '\002' ASCII start of text + * = '\003' ASCII end of text + *
,, = day, month, year(2 digits!!) + * = day of week (sunday= 0) + * ,, = hour, minute, second + * <+/->,<00:00> = offset to UTC + * = '#' if never synced since powerup else ' ' + * = '*' if position is not confirmed else ' ' + * = 'S' if daylight saving time is active else ' ' + * = '!' during the hour preceeding an daylight saving time + * start/end change + * = 'A' LEAP second announcement + * = 'R' alternate antenna (reminiscent of PZF535) usually ' ' + * = 'L' on 23:59:60 + * + * Binary messages have a lead in for a fixed header of SOH + */ + +/*--------------------------------------------------------------*/ +/* Name: csum() */ +/* */ +/* Purpose: Compute a checksum about a number of bytes */ +/* */ +/* Input: uchar *p address of the first byte */ +/* short n the number of bytes */ +/* */ +/* Output: -- */ +/* */ +/* Ret val: the checksum */ +/*+-------------------------------------------------------------*/ + +unsigned long +mbg_csum( + unsigned char *p, + unsigned int n + ) +{ + unsigned long sum = 0; + short i; + + for ( i = 0; i < n; i++ ) + sum += *p++; + + return( sum ); +} /* csum */ + +void +get_mbg_header( + unsigned char **bufpp, + GPS_MSG_HDR *headerp + ) +{ + headerp->gps_cmd = get_lsb_short(bufpp); + headerp->gps_len = get_lsb_short(bufpp); + headerp->gps_data_csum = get_lsb_short(bufpp); + headerp->gps_hdr_csum = get_lsb_short(bufpp); +} + +static struct format meinberg_fmt[] = +{ + { + { + { 3, 2}, { 6, 2}, { 9, 2}, + { 18, 2}, { 21, 2}, { 24, 2}, + { 14, 1}, { 27, 4}, { 29, 1}, + }, + (const unsigned char *)"\2D: . . ;T: ;U: . . ; \3", + 0 + }, + { /* special extended FAU Erlangen extended format */ + { + { 1, 2}, { 4, 2}, { 7, 2}, + { 14, 2}, { 17, 2}, { 20, 2}, + { 11, 1}, { 25, 4}, { 27, 1}, + }, + (const unsigned char *)"\2 . . ; ; : : ; \3", + MBG_EXTENDED + }, + { /* special extended FAU Erlangen GPS format */ + { + { 1, 2}, { 4, 2}, { 7, 2}, + { 14, 2}, { 17, 2}, { 20, 2}, + { 11, 1}, { 32, 7}, { 35, 1}, + { 25, 2}, { 28, 2}, { 24, 1} + }, + (const unsigned char *)"\2 . . ; ; : : ; : ; ; . . ", + 0 + } +}; + +static u_long cvt_meinberg (unsigned char *, int, struct format *, clocktime_t *, void *); +static u_long cvt_mgps (unsigned char *, int, struct format *, clocktime_t *, void *); +static u_long mbg_input (parse_t *, unsigned int, timestamp_t *); +static u_long gps_input (parse_t *, unsigned int, timestamp_t *); + +struct msg_buf +{ + unsigned short len; /* len to fill */ + unsigned short phase; /* current input phase */ +}; + +#define MBG_NONE 0 /* no data input */ +#define MBG_HEADER 1 /* receiving header */ +#define MBG_DATA 2 /* receiving data */ +#define MBG_STRING 3 /* receiving standard data message */ + +clockformat_t clock_meinberg[] = +{ + { + mbg_input, /* normal input handling */ + cvt_meinberg, /* Meinberg conversion */ + pps_one, /* easy PPS monitoring */ + 0, /* conversion configuration */ + "Meinberg Standard", /* Meinberg simple format - beware */ + 32, /* string buffer */ + 0 /* no private data (complete pakets) */ + }, + { + mbg_input, /* normal input handling */ + cvt_meinberg, /* Meinberg conversion */ + pps_one, /* easy PPS monitoring */ + 0, /* conversion configuration */ + "Meinberg Extended", /* Meinberg enhanced format */ + 32, /* string buffer */ + 0 /* no private data (complete pakets) */ + }, + { + gps_input, /* no input handling */ + cvt_mgps, /* Meinberg GPS166 conversion */ + pps_one, /* easy PPS monitoring */ + (void *)&meinberg_fmt[2], /* conversion configuration */ + "Meinberg GPS Extended", /* Meinberg FAU GPS format */ + 512, /* string buffer */ + sizeof(struct msg_buf) /* no private data (complete pakets) */ + } +}; + +/* + * cvt_meinberg + * + * convert simple type format + */ +static u_long +cvt_meinberg( + unsigned char *buffer, + int size, + struct format *unused, + clocktime_t *clock_time, + void *local + ) +{ + struct format *format; + + /* + * select automagically correct data format + */ + if (Strok(buffer, meinberg_fmt[0].fixed_string)) + { + format = &meinberg_fmt[0]; + } + else + { + if (Strok(buffer, meinberg_fmt[1].fixed_string)) + { + format = &meinberg_fmt[1]; + } + else + { + return CVT_FAIL|CVT_BADFMT; + } + } + + /* + * collect data + */ + if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, + format->field_offsets[O_DAY].length) || + Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, + format->field_offsets[O_MONTH].length) || + Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, + format->field_offsets[O_YEAR].length) || + Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, + format->field_offsets[O_HOUR].length) || + Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, + format->field_offsets[O_MIN].length) || + Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, + format->field_offsets[O_SEC].length)) + { + return CVT_FAIL|CVT_BADFMT; + } + else + { + unsigned char *f = &buffer[format->field_offsets[O_FLAGS].offset]; + + clock_time->usecond = 0; + clock_time->flags = PARSEB_S_LEAP; + + if (clock_time->second == 60) + clock_time->flags |= PARSEB_LEAPSECOND; + + /* + * in the extended timecode format we have also the + * indication that the timecode is in UTC + * for compatibilty reasons we start at the USUAL + * offset (POWERUP flag) and know that the UTC indication + * is the character before the powerup flag + */ + if ((format->flags & MBG_EXTENDED) && (f[-1] == 'U')) + { + /* + * timecode is in UTC + */ + clock_time->utcoffset = 0; /* UTC */ + clock_time->flags |= PARSEB_UTC; + } + else + { + /* + * only calculate UTC offset if MET/MED is in time code + * or we have the old time code format, where we do not + * know whether it is UTC time or MET/MED + * pray that nobody switches to UTC in the *old* standard time code + * ROMS !!!! The new ROMS have 'U' at the ZONE field - good. + */ + switch (buffer[format->field_offsets[O_ZONE].offset]) + { + case ' ': + clock_time->utcoffset = -1*60*60; /* MET */ + break; + + case 'S': + clock_time->utcoffset = -2*60*60; /* MED */ + break; + + case 'U': + /* + * timecode is in UTC + */ + clock_time->utcoffset = 0; /* UTC */ + clock_time->flags |= PARSEB_UTC; + break; + + default: + return CVT_FAIL|CVT_BADFMT; + } + } + + /* + * gather status flags + */ + if (buffer[format->field_offsets[O_ZONE].offset] == 'S') + clock_time->flags |= PARSEB_DST; + + if (f[0] == '#') + clock_time->flags |= PARSEB_POWERUP; + + if (f[1] == '*') + clock_time->flags |= PARSEB_NOSYNC; + + if (f[3] == '!') + clock_time->flags |= PARSEB_ANNOUNCE; + + /* + * oncoming leap second + * 'a' code not confirmed - earth is not + * expected to speed up + */ + if (f[3] == 'A') + clock_time->flags |= PARSEB_LEAPADD; + + if (f[3] == 'a') + clock_time->flags |= PARSEB_LEAPDEL; + + + if (format->flags & MBG_EXTENDED) + { + clock_time->flags |= PARSEB_S_ANTENNA; + + /* + * DCF77 does not encode the direction - + * so we take the current default - + * earth slowing down + */ + clock_time->flags &= ~PARSEB_LEAPDEL; + + if (f[4] == 'A') + clock_time->flags |= PARSEB_LEAPADD; + + if (f[5] == 'R') + clock_time->flags |= PARSEB_ALTERNATE; + } + return CVT_OK; + } +} + + +/* + * mbg_input + * + * grep data from input stream + */ +static u_long +mbg_input( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("mbg_input(0x%lx, 0x%x, ...)\n", (long)parseio, ch)); + + switch (ch) + { + case STX: + parseprintf(DD_PARSE, ("mbg_input: STX seen\n")); + + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + return PARSE_INP_SKIP; + + case ETX: + parseprintf(DD_PARSE, ("mbg_input: ETX seen\n")); + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + default: + return parse_addchar(parseio, ch); + } +} + + +/* + * cvt_mgps + * + * convert Meinberg GPS format + */ +static u_long +cvt_mgps( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + if (!Strok(buffer, format->fixed_string)) + { + return cvt_meinberg(buffer, size, format, clock_time, local); + } + else + { + if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, + format->field_offsets[O_DAY].length) || + Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, + format->field_offsets[O_MONTH].length) || + Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, + format->field_offsets[O_YEAR].length) || + Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, + format->field_offsets[O_HOUR].length) || + Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, + format->field_offsets[O_MIN].length) || + Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, + format->field_offsets[O_SEC].length)) + { + return CVT_FAIL|CVT_BADFMT; + } + else + { + long h; + unsigned char *f = &buffer[format->field_offsets[O_FLAGS].offset]; + + clock_time->flags = PARSEB_S_LEAP|PARSEB_S_POSITION; + + clock_time->usecond = 0; + + /* + * calculate UTC offset + */ + if (Stoi(&buffer[format->field_offsets[O_UTCHOFFSET].offset], &h, + format->field_offsets[O_UTCHOFFSET].length)) + { + return CVT_FAIL|CVT_BADFMT; + } + else + { + if (Stoi(&buffer[format->field_offsets[O_UTCMOFFSET].offset], &clock_time->utcoffset, + format->field_offsets[O_UTCMOFFSET].length)) + { + return CVT_FAIL|CVT_BADFMT; + } + + clock_time->utcoffset += TIMES60(h); + clock_time->utcoffset = TIMES60(clock_time->utcoffset); + + if (buffer[format->field_offsets[O_UTCSOFFSET].offset] != '-') + { + clock_time->utcoffset = -clock_time->utcoffset; + } + } + + /* + * gather status flags + */ + if (buffer[format->field_offsets[O_ZONE].offset] == 'S') + clock_time->flags |= PARSEB_DST; + + if (clock_time->utcoffset == 0) + clock_time->flags |= PARSEB_UTC; + + /* + * no sv's seen - no time & position + */ + if (f[0] == '#') + clock_time->flags |= PARSEB_POWERUP; + + /* + * at least one sv seen - time (for last position) + */ + if (f[1] == '*') + clock_time->flags |= PARSEB_NOSYNC; + else + if (!(clock_time->flags & PARSEB_POWERUP)) + clock_time->flags |= PARSEB_POSITION; + + /* + * oncoming zone switch + */ + if (f[3] == '!') + clock_time->flags |= PARSEB_ANNOUNCE; + + /* + * oncoming leap second + * 'a' code not confirmed - earth is not + * expected to speed up + */ + if (f[4] == 'A') + clock_time->flags |= PARSEB_LEAPADD; + + if (f[4] == 'a') + clock_time->flags |= PARSEB_LEAPDEL; + + /* + * f[5] == ' ' + */ + + /* + * this is the leap second + */ + if ((f[6] == 'L') || (clock_time->second == 60)) + clock_time->flags |= PARSEB_LEAPSECOND; + + return CVT_OK; + } + } +} + +/* + * gps_input + * + * grep binary data from input stream + */ +static u_long +gps_input( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + CSUM calc_csum; /* used to compare the incoming csums */ + GPS_MSG_HDR header; + struct msg_buf *msg_buf; + + msg_buf = (struct msg_buf *)parseio->parse_pdata; + + parseprintf(DD_PARSE, ("gps_input(0x%lx, 0x%x, ...)\n", (long)parseio, ch)); + + if (!msg_buf) + return PARSE_INP_SKIP; + + if ( msg_buf->phase == MBG_NONE ) + { /* not receiving yet */ + switch (ch) + { + case SOH: + parseprintf(DD_PARSE, ("gps_input: SOH seen\n")); + + msg_buf->len = sizeof( header ); /* prepare to receive msg header */ + msg_buf->phase = MBG_HEADER; /* receiving header */ + break; + + case STX: + parseprintf(DD_PARSE, ("gps_input: STX seen\n")); + + msg_buf->len = 0; + msg_buf->phase = MBG_STRING; /* prepare to receive ASCII ETX delimited message */ + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + break; + + default: + return PARSE_INP_SKIP; /* keep searching */ + } + + parseio->parse_dtime.parse_msglen = 1; /* reset buffer pointer */ + parseio->parse_dtime.parse_msg[0] = ch; /* fill in first character */ + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + return PARSE_INP_SKIP; + } + + /* SOH/STX has already been received */ + + /* save incoming character in both buffers if needbe */ + if ((msg_buf->phase == MBG_STRING) && + (parseio->parse_index < parseio->parse_dsize)) + parseio->parse_data[parseio->parse_index++] = ch; + + parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch; + + if (parseio->parse_dtime.parse_msglen > sizeof(parseio->parse_dtime.parse_msg)) + { + msg_buf->phase = MBG_NONE; /* buffer overflow - discard */ + parseio->parse_data[parseio->parse_index] = '\0'; + memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1)); + parseio->parse_ldsize = parseio->parse_index; + return PARSE_INP_DATA; + } + + switch (msg_buf->phase) + { + case MBG_HEADER: + case MBG_DATA: + msg_buf->len--; + + if ( msg_buf->len ) /* transfer not complete */ + return PARSE_INP_SKIP; + + parseprintf(DD_PARSE, ("gps_input: %s complete\n", (msg_buf->phase == MBG_DATA) ? "data" : "header")); + + break; + + case MBG_STRING: + if ((ch == ETX) || (parseio->parse_index >= parseio->parse_dsize)) + { + msg_buf->phase = MBG_NONE; + parseprintf(DD_PARSE, ("gps_input: string complete\n")); + parseio->parse_data[parseio->parse_index] = '\0'; + memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1)); + parseio->parse_ldsize = parseio->parse_index; + parseio->parse_index = 0; + return PARSE_INP_TIME; + } + else + { + return PARSE_INP_SKIP; + } + } + + /* cnt == 0, so the header or the whole message is complete */ + + if ( msg_buf->phase == MBG_HEADER ) + { /* header complete now */ + unsigned char *datap = parseio->parse_dtime.parse_msg + 1; + + get_mbg_header(&datap, &header); + + parseprintf(DD_PARSE, ("gps_input: header: cmd 0x%x, len %d, dcsum 0x%x, hcsum 0x%x\n", + (int)header.gps_cmd, (int)header.gps_len, (int)header.gps_data_csum, + (int)header.gps_hdr_csum)); + + + calc_csum = mbg_csum( (unsigned char *) parseio->parse_dtime.parse_msg + 1, (unsigned short)6 ); + + if ( calc_csum != header.gps_hdr_csum ) + { + parseprintf(DD_PARSE, ("gps_input: header checksum mismatch expected 0x%x, got 0x%x\n", + (int)calc_csum, (int)mbg_csum( (unsigned char *) parseio->parse_dtime.parse_msg, (unsigned short)6 ))); + + msg_buf->phase = MBG_NONE; /* back to hunting mode */ + return PARSE_INP_DATA; /* invalid header checksum received - pass up for detection */ + } + + if ((header.gps_len == 0) || /* no data to wait for */ + (header.gps_len >= (sizeof (parseio->parse_dtime.parse_msg) - sizeof(header) - 1))) /* blows anything we have space for */ + { + msg_buf->phase = MBG_NONE; /* back to hunting mode */ + return (header.gps_len == 0) ? PARSE_INP_DATA : PARSE_INP_SKIP; /* message complete/throwaway */ + } + + parseprintf(DD_PARSE, ("gps_input: expecting %d bytes of data message\n", (int)header.gps_len)); + + msg_buf->len = header.gps_len;/* save number of bytes to wait for */ + msg_buf->phase = MBG_DATA; /* flag header already complete */ + return PARSE_INP_SKIP; + } + + parseprintf(DD_PARSE, ("gps_input: message data complete\n")); + + /* Header and data have been received. The header checksum has been */ + /* checked */ + + msg_buf->phase = MBG_NONE; /* back to hunting mode */ + return PARSE_INP_DATA; /* message complete, must be evaluated */ +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_MEINBERG) */ +int clk_meinberg_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_MEINBERG) */ + +/* + * History: + * + * clk_meinberg.c,v + * Revision 4.12.2.1 2005/09/25 10:22:35 kardel + * cleanup buffer bounds + * + * Revision 4.12 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.11 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.8 1999/11/28 09:13:50 kardel + * RECON_4_0_98F + * + * Revision 4.7 1999/02/21 11:09:14 kardel + * cleanup + * + * Revision 4.6 1998/06/14 21:09:36 kardel + * Sun acc cleanup + * + * Revision 4.5 1998/06/13 15:18:54 kardel + * fix mem*() to b*() function macro emulation + * + * Revision 4.4 1998/06/13 12:03:23 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:28 kardel + * fix prototypes + * + * Revision 4.2 1998/05/24 16:14:42 kardel + * support current Meinberg standard data formats + * + * Revision 4.1 1998/05/24 09:39:52 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:29 kardel + * Start 4.0 release version numbering + * + * from V3 3.23 - log info deleted 1998/04/11 kardel + * + */ diff --git a/libparse/clk_rawdcf.c b/libparse/clk_rawdcf.c new file mode 100644 index 0000000..98848be --- /dev/null +++ b/libparse/clk_rawdcf.c @@ -0,0 +1,658 @@ +/* + * /src/NTP/REPOSITORY/ntp4-dev/libparse/clk_rawdcf.c,v 4.18 2006/06/22 18:40:01 kardel RELEASE_20060622_A + * + * clk_rawdcf.c,v 4.18 2006/06/22 18:40:01 kardel RELEASE_20060622_A + * + * Raw DCF77 pulse clock support + * + * Copyright (c) 1995-2006 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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 +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_RAWDCF) + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" +#ifdef PARSESTREAM +# include +#endif + +#ifndef PARSEKERNEL +# include "ntp_stdlib.h" +#endif + +/* + * DCF77 raw time code + * + * From "Zur Zeit", Physikalisch-Technische Bundesanstalt (PTB), Braunschweig + * und Berlin, Maerz 1989 + * + * Timecode transmission: + * AM: + * time marks are send every second except for the second before the + * next minute mark + * time marks consist of a reduction of transmitter power to 25% + * of the nominal level + * the falling edge is the time indication (on time) + * time marks of a 100ms duration constitute a logical 0 + * time marks of a 200ms duration constitute a logical 1 + * FM: + * see the spec. (basically a (non-)inverted psuedo random phase shift) + * + * Encoding: + * Second Contents + * 0 - 10 AM: free, FM: 0 + * 11 - 14 free + * 15 R - alternate antenna + * 16 A1 - expect zone change (1 hour before) + * 17 - 18 Z1,Z2 - time zone + * 0 0 illegal + * 0 1 MEZ (MET) + * 1 0 MESZ (MED, MET DST) + * 1 1 illegal + * 19 A2 - expect leap insertion/deletion (1 hour before) + * 20 S - start of time code (1) + * 21 - 24 M1 - BCD (lsb first) Minutes + * 25 - 27 M10 - BCD (lsb first) 10 Minutes + * 28 P1 - Minute Parity (even) + * 29 - 32 H1 - BCD (lsb first) Hours + * 33 - 34 H10 - BCD (lsb first) 10 Hours + * 35 P2 - Hour Parity (even) + * 36 - 39 D1 - BCD (lsb first) Days + * 40 - 41 D10 - BCD (lsb first) 10 Days + * 42 - 44 DW - BCD (lsb first) day of week (1: Monday -> 7: Sunday) + * 45 - 49 MO - BCD (lsb first) Month + * 50 MO0 - 10 Months + * 51 - 53 Y1 - BCD (lsb first) Years + * 54 - 57 Y10 - BCD (lsb first) 10 Years + * 58 P3 - Date Parity (even) + * 59 - usually missing (minute indication), except for leap insertion + */ + +static u_long pps_rawdcf (parse_t *, int, timestamp_t *); +static u_long cvt_rawdcf (unsigned char *, int, struct format *, clocktime_t *, void *); +static u_long inp_rawdcf (parse_t *, unsigned int, timestamp_t *); + +typedef struct last_tcode { + time_t tcode; /* last converted time code */ +} last_tcode_t; + +#define BUFFER_MAX 61 + +clockformat_t clock_rawdcf = +{ + inp_rawdcf, /* DCF77 input handling */ + cvt_rawdcf, /* raw dcf input conversion */ + pps_rawdcf, /* examining PPS information */ + 0, /* no private configuration data */ + "RAW DCF77 Timecode", /* direct decoding / time synthesis */ + + BUFFER_MAX, /* bit buffer */ + sizeof(last_tcode_t) +}; + +static struct dcfparam +{ + unsigned char *onebits; + unsigned char *zerobits; +} dcfparameter = +{ + (unsigned char *)"###############RADMLS1248124P124812P1248121241248112481248P??", /* 'ONE' representation */ + (unsigned char *)"--------------------s-------p------p----------------------p__" /* 'ZERO' representation */ +}; + +static struct rawdcfcode +{ + char offset; /* start bit */ +} rawdcfcode[] = +{ + { 0 }, { 15 }, { 16 }, { 17 }, { 19 }, { 20 }, { 21 }, { 25 }, { 28 }, { 29 }, + { 33 }, { 35 }, { 36 }, { 40 }, { 42 }, { 45 }, { 49 }, { 50 }, { 54 }, { 58 }, { 59 } +}; + +#define DCF_M 0 +#define DCF_R 1 +#define DCF_A1 2 +#define DCF_Z 3 +#define DCF_A2 4 +#define DCF_S 5 +#define DCF_M1 6 +#define DCF_M10 7 +#define DCF_P1 8 +#define DCF_H1 9 +#define DCF_H10 10 +#define DCF_P2 11 +#define DCF_D1 12 +#define DCF_D10 13 +#define DCF_DW 14 +#define DCF_MO 15 +#define DCF_MO0 16 +#define DCF_Y1 17 +#define DCF_Y10 18 +#define DCF_P3 19 + +static struct partab +{ + char offset; /* start bit of parity field */ +} partab[] = +{ + { 21 }, { 29 }, { 36 }, { 59 } +}; + +#define DCF_P_P1 0 +#define DCF_P_P2 1 +#define DCF_P_P3 2 + +#define DCF_Z_MET 0x2 +#define DCF_Z_MED 0x1 + +static u_long +ext_bf( + unsigned char *buf, + int idx, + unsigned char *zero + ) +{ + u_long sum = 0; + int i, first; + + first = rawdcfcode[idx].offset; + + for (i = rawdcfcode[idx+1].offset - 1; i >= first; i--) + { + sum <<= 1; + sum |= (buf[i] != zero[i]); + } + return sum; +} + +static unsigned +pcheck( + unsigned char *buf, + int idx, + unsigned char *zero + ) +{ + int i,last; + unsigned psum = 1; + + last = partab[idx+1].offset; + + for (i = partab[idx].offset; i < last; i++) + psum ^= (buf[i] != zero[i]); + + return psum; +} + +static u_long +convert_rawdcf( + unsigned char *buffer, + int size, + struct dcfparam *dcfprm, + clocktime_t *clock_time + ) +{ + unsigned char *s = buffer; + unsigned char *b = dcfprm->onebits; + unsigned char *c = dcfprm->zerobits; + int i; + + parseprintf(DD_RAWDCF,("parse: convert_rawdcf: \"%s\"\n", buffer)); + + if (size < 57) + { +#ifndef PARSEKERNEL + msyslog(LOG_ERR, "parse: convert_rawdcf: INCOMPLETE DATA - time code only has %d bits", size); +#endif + return CVT_NONE; + } + + for (i = 0; i < size; i++) + { + if ((*s != *b) && (*s != *c)) + { + /* + * we only have two types of bytes (ones and zeros) + */ +#ifndef PARSEKERNEL + msyslog(LOG_ERR, "parse: convert_rawdcf: BAD DATA - no conversion"); +#endif + return CVT_NONE; + } + if (*b) b++; + if (*c) c++; + s++; + } + + /* + * check Start and Parity bits + */ + if ((ext_bf(buffer, DCF_S, dcfprm->zerobits) == 1) && + pcheck(buffer, DCF_P_P1, dcfprm->zerobits) && + pcheck(buffer, DCF_P_P2, dcfprm->zerobits) && + pcheck(buffer, DCF_P_P3, dcfprm->zerobits)) + { + /* + * buffer OK + */ + parseprintf(DD_RAWDCF,("parse: convert_rawdcf: parity check passed\n")); + + clock_time->flags = PARSEB_S_ANTENNA|PARSEB_S_LEAP; + clock_time->utctime= 0; + clock_time->usecond= 0; + clock_time->second = 0; + clock_time->minute = ext_bf(buffer, DCF_M10, dcfprm->zerobits); + clock_time->minute = TIMES10(clock_time->minute) + ext_bf(buffer, DCF_M1, dcfprm->zerobits); + clock_time->hour = ext_bf(buffer, DCF_H10, dcfprm->zerobits); + clock_time->hour = TIMES10(clock_time->hour) + ext_bf(buffer, DCF_H1, dcfprm->zerobits); + clock_time->day = ext_bf(buffer, DCF_D10, dcfprm->zerobits); + clock_time->day = TIMES10(clock_time->day) + ext_bf(buffer, DCF_D1, dcfprm->zerobits); + clock_time->month = ext_bf(buffer, DCF_MO0, dcfprm->zerobits); + clock_time->month = TIMES10(clock_time->month) + ext_bf(buffer, DCF_MO, dcfprm->zerobits); + clock_time->year = ext_bf(buffer, DCF_Y10, dcfprm->zerobits); + clock_time->year = TIMES10(clock_time->year) + ext_bf(buffer, DCF_Y1, dcfprm->zerobits); + + switch (ext_bf(buffer, DCF_Z, dcfprm->zerobits)) + { + case DCF_Z_MET: + clock_time->utcoffset = -1*60*60; + break; + + case DCF_Z_MED: + clock_time->flags |= PARSEB_DST; + clock_time->utcoffset = -2*60*60; + break; + + default: + parseprintf(DD_RAWDCF,("parse: convert_rawdcf: BAD TIME ZONE\n")); + return CVT_FAIL|CVT_BADFMT; + } + + if (ext_bf(buffer, DCF_A1, dcfprm->zerobits)) + clock_time->flags |= PARSEB_ANNOUNCE; + + if (ext_bf(buffer, DCF_A2, dcfprm->zerobits)) + clock_time->flags |= PARSEB_LEAPADD; /* default: DCF77 data format deficiency */ + + if (ext_bf(buffer, DCF_R, dcfprm->zerobits)) + clock_time->flags |= PARSEB_ALTERNATE; + + parseprintf(DD_RAWDCF,("parse: convert_rawdcf: TIME CODE OK: %d:%d, %d.%d.%d, flags 0x%lx\n", + (int)clock_time->hour, (int)clock_time->minute, (int)clock_time->day, (int)clock_time->month,(int) clock_time->year, + (u_long)clock_time->flags)); + return CVT_OK; + } + else + { + /* + * bad format - not for us + */ +#ifndef PARSEKERNEL + msyslog(LOG_ERR, "parse: convert_rawdcf: parity check FAILED for \"%s\"", buffer); +#endif + return CVT_FAIL|CVT_BADFMT; + } +} + +/* + * raw dcf input routine - needs to fix up 50 baud + * characters for 1/0 decision + */ +static u_long +cvt_rawdcf( + unsigned char *buffer, + int size, + struct format *param, + clocktime_t *clock_time, + void *local + ) +{ + last_tcode_t *t = (last_tcode_t *)local; + unsigned char *s = (unsigned char *)buffer; + unsigned char *e = s + size; + unsigned char *b = dcfparameter.onebits; + unsigned char *c = dcfparameter.zerobits; + u_long rtc = CVT_NONE; + unsigned int i, lowmax, highmax, cutoff, span; +#define BITS 9 + unsigned char histbuf[BITS]; + /* + * the input buffer contains characters with runs of consecutive + * bits set. These set bits are an indication of the DCF77 pulse + * length. We assume that we receive the pulse at 50 Baud. Thus + * a 100ms pulse would generate a 4 bit train (20ms per bit and + * start bit) + * a 200ms pulse would create all zeroes (and probably a frame error) + */ + + for (i = 0; i < BITS; i++) + { + histbuf[i] = 0; + } + + cutoff = 0; + lowmax = 0; + + while (s < e) + { + unsigned int ch = *s ^ 0xFF; + /* + * these lines are left as an excercise to the reader 8-) + */ + if (!((ch+1) & ch) || !*s) + { + + for (i = 0; ch; i++) + { + ch >>= 1; + } + + *s = i; + histbuf[i]++; + cutoff += i; + lowmax++; + } + else + { + parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: character check for 0x%x@%d FAILED\n", *s, (int)(s - (unsigned char *)buffer))); + *s = (unsigned char)~0; + rtc = CVT_FAIL|CVT_BADFMT; + } + s++; + } + + if (lowmax) + { + cutoff /= lowmax; + } + else + { + cutoff = 4; /* doesn't really matter - it'll fail anyway, but gives error output */ + } + + parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: average bit count: %d\n", cutoff)); + + lowmax = 0; + highmax = 0; + + parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: histogram:")); + for (i = 0; i <= cutoff; i++) + { + lowmax+=histbuf[i] * i; + highmax += histbuf[i]; + parseprintf(DD_RAWDCF,(" %d", histbuf[i])); + } + parseprintf(DD_RAWDCF, (" ")); + + lowmax += highmax / 2; + + if (highmax) + { + lowmax /= highmax; + } + else + { + lowmax = 0; + } + + highmax = 0; + cutoff = 0; + + for (; i < BITS; i++) + { + highmax+=histbuf[i] * i; + cutoff +=histbuf[i]; + parseprintf(DD_RAWDCF,(" %d", histbuf[i])); + } + parseprintf(DD_RAWDCF,("\n")); + + if (cutoff) + { + highmax /= cutoff; + } + else + { + highmax = BITS-1; + } + + span = cutoff = lowmax; + for (i = lowmax; i <= highmax; i++) + { + if (histbuf[cutoff] > histbuf[i]) + { + cutoff = i; + span = i; + } + else + if (histbuf[cutoff] == histbuf[i]) + { + span = i; + } + } + + cutoff = (cutoff + span) / 2; + + parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: lower maximum %d, higher maximum %d, cutoff %d\n", lowmax, highmax, cutoff)); + + s = (unsigned char *)buffer; + while (s < e) + { + if (*s == (unsigned char)~0) + { + *s = '?'; + } + else + { + *s = (*s >= cutoff) ? *b : *c; + } + s++; + if (*b) b++; + if (*c) c++; + } + + if (rtc == CVT_NONE) + { + rtc = convert_rawdcf(buffer, size, &dcfparameter, clock_time); + if (rtc == CVT_OK) + { + time_t newtime; + + newtime = parse_to_unixtime(clock_time, &rtc); + if ((rtc == CVT_OK) && t) + { + if ((newtime - t->tcode) == 60) /* guard against multi bit errors */ + { + clock_time->utctime = newtime; + } + else + { + rtc = CVT_FAIL|CVT_BADTIME; + } + t->tcode = newtime; + } + } + } + + return rtc; +} + +/* + * pps_rawdcf + * + * currently a very stupid version - should be extended to decode + * also ones and zeros (which is easy) + */ +/*ARGSUSED*/ +static u_long +pps_rawdcf( + parse_t *parseio, + int status, + timestamp_t *ptime + ) +{ + if (!status) /* negative edge for simpler wiring (Rx->DCD) */ + { + parseio->parse_dtime.parse_ptime = *ptime; + parseio->parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS; + } + + return CVT_NONE; +} + +static u_long +snt_rawdcf( + parse_t *parseio, + timestamp_t *ptime + ) +{ + if ((parseio->parse_dtime.parse_status & CVT_MASK) == CVT_OK) + { + parseio->parse_dtime.parse_stime = *ptime; + +#ifdef PARSEKERNEL + parseio->parse_dtime.parse_time.tv.tv_sec++; +#else + parseio->parse_dtime.parse_time.fp.l_ui++; +#endif + + parseprintf(DD_RAWDCF,("parse: snt_rawdcf: time stamp synthesized offset %d seconds\n", parseio->parse_index - 1)); + + return updatetimeinfo(parseio, parseio->parse_lstate); + } + return CVT_NONE; +} + +/* + * inp_rawdcf + * + * grab DCF77 data from input stream + */ +static u_long +inp_rawdcf( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + static struct timeval timeout = { 1, 500000 }; /* 1.5 secongs denote second #60 */ + + parseprintf(DD_PARSE, ("inp_rawdcf(0x%lx, 0x%x, ...)\n", (long)parseio, ch)); + + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + + if (parse_timedout(parseio, tstamp, &timeout)) + { + parseprintf(DD_PARSE, ("inp_rawdcf: time out seen\n")); + + (void) parse_end(parseio); + (void) parse_addchar(parseio, ch); + return PARSE_INP_TIME; + } + else + { + unsigned int rtc; + + rtc = parse_addchar(parseio, ch); + if (rtc == PARSE_INP_SKIP) + { + if (snt_rawdcf(parseio, tstamp) == CVT_OK) + return PARSE_INP_SYNTH; + } + return rtc; + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_RAWDCF) */ +int clk_rawdcf_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_RAWDCF) */ + +/* + * History: + * + * clk_rawdcf.c,v + * Revision 4.18 2006/06/22 18:40:01 kardel + * clean up signedness (gcc 4) + * + * Revision 4.17 2006/01/22 16:01:55 kardel + * update version information + * + * Revision 4.16 2006/01/22 15:51:22 kardel + * generate reasonable timecode output on invalid input + * + * Revision 4.15 2005/08/06 19:17:06 kardel + * clean log output + * + * Revision 4.14 2005/08/06 17:39:40 kardel + * cleanup size handling wrt/ to buffer boundaries + * + * Revision 4.13 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.12 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.9 1999/12/06 13:42:23 kardel + * transfer correctly converted time codes always into tcode + * + * Revision 4.8 1999/11/28 09:13:50 kardel + * RECON_4_0_98F + * + * Revision 4.7 1999/04/01 20:07:20 kardel + * added checking for minutie increment of timestamps in clk_rawdcf.c + * + * Revision 4.6 1998/06/14 21:09:37 kardel + * Sun acc cleanup + * + * Revision 4.5 1998/06/13 12:04:16 kardel + * fix SYSV clock name clash + * + * Revision 4.4 1998/06/12 15:22:28 kardel + * fix prototypes + * + * Revision 4.3 1998/06/06 18:33:36 kardel + * simplified condidional compile expression + * + * Revision 4.2 1998/05/24 11:04:18 kardel + * triggering PPS on negative edge for simpler wiring (Rx->DCD) + * + * Revision 4.1 1998/05/24 09:39:53 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:30 kardel + * Start 4.0 release version numbering + * + * from V3 3.24 log info deleted 1998/04/11 kardel + * + */ diff --git a/libparse/clk_rcc8000.c b/libparse/clk_rcc8000.c new file mode 100644 index 0000000..6dca166 --- /dev/null +++ b/libparse/clk_rcc8000.c @@ -0,0 +1,198 @@ +/* + * /src/NTP/ntp4-dev/libparse/clk_rcc8000.c,v 4.9 2004/11/14 15:29:41 kardel RELEASE_20050508_A + * + * clk_rcc8000.c,v 4.9 2004/11/14 15:29:41 kardel RELEASE_20050508_A + * + * Radiocode Clocks Ltd RCC 8000 Intelligent Off-Air Master Clock support + * + * Created by R.E.Broughton from clk_trimtaip.c + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#if HAVE_CONFIG_H +# include +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_RCC8000) + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include +#else +#include "sys/parsestreams.h" +extern int printf (const char *, ...); +#endif + +/* Type II Serial Output format + * + * 0000000000111111111122222222223 / char + * 0123456789012345678901234567890 \ posn + * HH:MM:SS.XYZ DD/MM/YY DDD W Prn Actual + * 33 44 55 666 00 11 22 7 Parse + * : : . / / rn Check + * "15:50:36.534 30/09/94 273 5 A\x0d\x0a" + * + * DDD - Day of year number + * W - Day of week number (Sunday is 0) + * P is the Status. See comment below for details. + */ + +#define O_USEC O_WDAY +static struct format rcc8000_fmt = +{ { { 13, 2 }, {16, 2}, { 19, 2}, /* Day, Month, Year */ + { 0, 2 }, { 3, 2}, { 6, 2}, /* Hour, Minute, Second */ + { 9, 3 }, {28, 1}, { 0, 0}, /* uSec, Status (Valid,Reject,BST,Leapyear) */ }, + (const unsigned char *)" : : . / / \r\n", + /*"15:50:36.534 30/09/94 273 5 A\x0d\x0a" */ + 0 +}; + +static unsigned long cvt_rcc8000 (unsigned char *, int, struct format *, clocktime_t *, void *); +static unsigned long inp_rcc8000 (parse_t *, unsigned int, timestamp_t *); + +clockformat_t clock_rcc8000 = +{ + inp_rcc8000, /* no input handling */ + cvt_rcc8000, /* Radiocode clock conversion */ + 0, /* no direct PPS monitoring */ + (void *)&rcc8000_fmt, /* conversion configuration */ + "Radiocode RCC8000", + 31, /* string buffer */ + 0 /* no private data */ +}; + +static unsigned long +cvt_rcc8000( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + if (!Strok(buffer, format->fixed_string)) return CVT_NONE; +#define OFFS(x) format->field_offsets[(x)].offset +#define STOI(x, y) Stoi(&buffer[OFFS(x)], y, format->field_offsets[(x)].length) + if ( STOI(O_DAY, &clock_time->day) || + STOI(O_MONTH, &clock_time->month) || + STOI(O_YEAR, &clock_time->year) || + STOI(O_HOUR, &clock_time->hour) || + STOI(O_MIN, &clock_time->minute) || + STOI(O_SEC, &clock_time->second) || + STOI(O_USEC, &clock_time->usecond) + ) return CVT_FAIL|CVT_BADFMT; + clock_time->usecond *= 1000; + + clock_time->utcoffset = 0; + +#define RCCP buffer[28] + /* + * buffer[28] is the ASCII representation of a hex character ( 0 through F ) + * The four bits correspond to: + * 8 - Valid Time + * 4 - Reject Code + * 2 - British Summer Time (receiver set to emit GMT all year.) + * 1 - Leap year + */ +#define RCC8000_VALID 0x8 +#define RCC8000_REJECT 0x4 +#define RCC8000_BST 0x2 +#define RCC8000_LEAPY 0x1 + + clock_time->flags = 0; + + if ( (RCCP >= '0' && RCCP <= '9') || (RCCP >= 'A' && RCCP <= 'F') ) + { + register int flag; + + flag = (RCCP >= '0' && RCCP <= '9' ) ? RCCP - '0' : RCCP - 'A' + 10; + + if (!(flag & RCC8000_VALID)) + clock_time->flags |= PARSEB_POWERUP; + + clock_time->flags |= PARSEB_UTC; /* British special - guess why 8-) */ + + /* other flags not used */ + } + return CVT_OK; +} +/* + * inp_rcc8000 + * + * grep data from input stream + */ +static u_long +inp_rcc8000( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_rcc8000(0x%lx, 0x%x, ...)\n", (long)parseio, ch)); + + switch (ch) + { + case '\n': + parseprintf(DD_PARSE, ("inp_rcc8000: EOL seen\n")); + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + + default: + if (parseio->parse_index == 0) /* take sample at start of message */ + { + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + } + return parse_addchar(parseio, ch); + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_RCC8000) */ +int clk_rcc8000_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_RCC8000) */ + +/* + * History: + * + * clk_rcc8000.c,v + * Revision 4.9 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.6 1999/11/28 09:13:51 kardel + * RECON_4_0_98F + * + * Revision 4.5 1998/06/14 21:09:38 kardel + * Sun acc cleanup + * + * Revision 4.4 1998/06/13 12:05:02 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:29 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:25 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:53 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:30 kardel + * Start 4.0 release version numbering + * + * from V3 3.5 log info deleted 1998/04/11 kardel + */ diff --git a/libparse/clk_schmid.c b/libparse/clk_schmid.c new file mode 100644 index 0000000..045f0fc --- /dev/null +++ b/libparse/clk_schmid.c @@ -0,0 +1,258 @@ +/* + * /src/NTP/ntp4-dev/libparse/clk_schmid.c,v 4.9 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * clk_schmid.c,v 4.9 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * Schmid clock support + * based on information and testing from Adam W. Feigin et. al (Swisstime iis.ethz.ch) + * + * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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. + * + */ + +#if HAVE_CONFIG_H +# include +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SCHMID) + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include +#else +#include "sys/parsestreams.h" +extern int printf (const char *, ...); +#endif + +/* + * Description courtesy of Adam W. Feigin et. al (Swisstime iis.ethz.ch) + * + * The command to Schmid's DCF77 clock is a single byte; each bit + * allows the user to select some part of the time string, as follows (the + * output for the lsb is sent first). + * + * Bit 0: time in MEZ, 4 bytes *binary, not BCD*; hh.mm.ss.tenths + * Bit 1: date 3 bytes *binary, not BCD: dd.mm.yy + * Bit 2: week day, 1 byte (unused here) + * Bit 3: time zone, 1 byte, 0=MET, 1=MEST. (unused here) + * Bit 4: clock status, 1 byte, 0=time invalid, + * 1=time from crystal backup, + * 3=time from DCF77 + * Bit 5: transmitter status, 1 byte, + * bit 0: backup antenna + * bit 1: time zone change within 1h + * bit 3,2: TZ 01=MEST, 10=MET + * bit 4: leap second will be + * added within one hour + * bits 5-7: Zero + * Bit 6: time in backup mode, units of 5 minutes (unused here) + * + */ +#define WS_TIME 0x01 +#define WS_SIGNAL 0x02 + +#define WS_ALTERNATE 0x01 +#define WS_ANNOUNCE 0x02 +#define WS_TZ 0x0c +#define WS_MET 0x08 +#define WS_MEST 0x04 +#define WS_LEAP 0x10 + +static u_long cvt_schmid (unsigned char *, int, struct format *, clocktime_t *, void *); +static unsigned long inp_schmid (parse_t *, unsigned int, timestamp_t *); + +clockformat_t clock_schmid = +{ + inp_schmid, /* no input handling */ + cvt_schmid, /* Schmid conversion */ + 0, /* not direct PPS monitoring */ + 0, /* conversion configuration */ + "Schmid", /* Schmid receiver */ + 12, /* binary data buffer */ + 0, /* no private data (complete messages) */ +}; + + +static u_long +cvt_schmid( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + if ((size != 11) || (buffer[10] != (unsigned char)'\375')) + { + return CVT_NONE; + } + else + { + if (buffer[0] > 23 || buffer[1] > 59 || buffer[2] > 59 || buffer[3] > 9) /* Time */ + { + return CVT_FAIL|CVT_BADTIME; + } + else + if (buffer[4] < 1 || buffer[4] > 31 || buffer[5] < 1 || buffer[5] > 12 + || buffer[6] > 99) + { + return CVT_FAIL|CVT_BADDATE; + } + else + { + clock_time->hour = buffer[0]; + clock_time->minute = buffer[1]; + clock_time->second = buffer[2]; + clock_time->usecond = buffer[3] * 100000; + clock_time->day = buffer[4]; + clock_time->month = buffer[5]; + clock_time->year = buffer[6]; + + clock_time->flags = 0; + + switch (buffer[8] & WS_TZ) + { + case WS_MET: + clock_time->utcoffset = -1*60*60; + break; + + case WS_MEST: + clock_time->utcoffset = -2*60*60; + clock_time->flags |= PARSEB_DST; + break; + + default: + return CVT_FAIL|CVT_BADFMT; + } + + if (!(buffer[7] & WS_TIME)) + { + clock_time->flags |= PARSEB_POWERUP; + } + + if (!(buffer[7] & WS_SIGNAL)) + { + clock_time->flags |= PARSEB_NOSYNC; + } + + if (buffer[7] & WS_SIGNAL) + { + if (buffer[8] & WS_ALTERNATE) + { + clock_time->flags |= PARSEB_ALTERNATE; + } + + if (buffer[8] & WS_ANNOUNCE) + { + clock_time->flags |= PARSEB_ANNOUNCE; + } + + if (buffer[8] & WS_LEAP) + { + clock_time->flags |= PARSEB_LEAPADD; /* default: DCF77 data format deficiency */ + } + } + + clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_ANTENNA; + + return CVT_OK; + } + } +} + +/* + * inp_schmid + * + * grep data from input stream + */ +static u_long +inp_schmid( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_schmid(0x%lx, 0x%x, ...)\n", (long)parseio, ch)); + + switch (ch) + { + case 0xFD: /* */ + parseprintf(DD_PARSE, ("mbg_input: ETX seen\n")); + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + default: + return parse_addchar(parseio, ch); + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SCHMID) */ +int clk_schmid_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SCHMID) */ + +/* + * History: + * + * clk_schmid.c,v + * Revision 4.9 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.8 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.5 1999/11/28 09:13:51 kardel + * RECON_4_0_98F + * + * Revision 4.4 1998/06/13 12:06:03 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:29 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:26 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:53 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:31 kardel + * Start 4.0 release version numbering + * + * from V3 3.22 log info deleted 1998/04/11 kardel + */ diff --git a/libparse/clk_sel240x.c b/libparse/clk_sel240x.c new file mode 100644 index 0000000..a09d347 --- /dev/null +++ b/libparse/clk_sel240x.c @@ -0,0 +1,178 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2009,2012 - +// Schweitzer Engineering Laboratories, Inc. +////////////////////////////////////////////////////////////////////////////// + +// Need to have _XOPEN_SOURCE defined for time.h to give the +// correct strptime signature. As per feature_test_macros(7), +// define this before including any header files. + +// #ifndef _XOPEN_SOURCE +// #define _XOPEN_SOURCE +// #endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SEL240X) + +#include "ntp_syslog.h" +#include "ntp_types.h" +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" +#include "ntp_machine.h" +#include "ntp_stdlib.h" + +#include "parse.h" + +#ifndef PARSESTREAM +# include +#else +# include "sys/parsestreams.h" +#endif + +#include + +////////////////////////////////////////////////////////////////////////////// +// The B8 output has the following format B8 = '\x01YYYY:ddd:hh:mm:ssq\r\n' +// where q = ' ' locked +// '.' <1 us +// '*' <10 us +// '#' <100 us +// '?' >100 us +// +// Based on this we need to recored the stime when we receive the +// character and end it when we see the \n. +// +// The q or quality character indicates satellite lock and sync. For the +// purposes of NTP we are going to call it valid when we receive anything but +// a '?'. But we are only going to call it synced when we receive a ' ' +////////////////////////////////////////////////////////////////////////////// + +static unsigned long inp_sel240x( parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp); +static unsigned long cvt_sel240x( unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local ); + +// Parse clock format structure describing the message above +static struct format sel240x_fmt = +{ { { 6, 3 }, + { 0, 0 }, + { 1, 4 }, + { 10, 2 }, + { 13, 2 }, + { 16, 2 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 } + }, + (const unsigned char *)"\x01 : : : : \x0d\x0a", + 0 +}; + +// Structure desctibing the parser +clockformat_t clock_sel240x = +{ + inp_sel240x, + cvt_sel240x, + pps_one, + (void*)&sel240x_fmt, + "SEL B8", + 25, + 0 +}; + +////////////////////////////////////////////////////////////////////////////// +static unsigned long +inp_sel240x( parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned long rc; + + parseprintf( DD_PARSE, + ("inp_sel240x(0x%lx, 0x%x, ...)\n",(long)parseio, ch)); + + switch( ch ) + { + case '\x01': + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + parseio->parse_dtime.parse_stime = *tstamp; + rc = PARSE_INP_SKIP; + break; + case '\n': + if( (rc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP ) + { + rc = parse_end( parseio ); + } + break; + default: + rc = parse_addchar( parseio, ch ); + } + + return rc; +} + +////////////////////////////////////////////////////////////////////////////// +static unsigned long +cvt_sel240x( unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + unsigned long rc = CVT_NONE; + + if( Strok(buffer, format->fixed_string) ) + { + struct tm ptime; + buffer++; + buffer = (unsigned char *) strptime( + (const char *)buffer, "%Y:%j:%H:%M:%S", &ptime ); + if( *(buffer+1) != '\x0d' ) + { + rc = CVT_FAIL | CVT_BADFMT; + } + else + { + clock_time->day = ptime.tm_mday; + clock_time->month = ptime.tm_mon + 1; + clock_time->year = ptime.tm_year + 1900; + clock_time->hour = ptime.tm_hour; + clock_time->minute = ptime.tm_min; + clock_time->second = ptime.tm_sec; + clock_time->usecond = 0; + clock_time->utcoffset = 0; + clock_time->flags = PARSEB_UTC; + + if( *buffer == '?' ) + { + clock_time->flags |= PARSEB_POWERUP; + } + else if( *buffer != ' ' ) + { + clock_time->flags |= PARSEB_NOSYNC; + } + + rc = CVT_OK; + } + } + + return rc; +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */ +int clk_sel240x_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SEL240X) */ diff --git a/libparse/clk_trimtaip.c b/libparse/clk_trimtaip.c new file mode 100644 index 0000000..322d0fa --- /dev/null +++ b/libparse/clk_trimtaip.c @@ -0,0 +1,223 @@ +/* + * /src/NTP/ntp4-dev/libparse/clk_trimtaip.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * clk_trimtaip.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * Trimble SV6 clock support - several collected codepieces + * + * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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 +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_TRIMTAIP) + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include +#else +#include "sys/parsestreams.h" +extern int printf (const char *, ...); +#endif + +/* 0000000000111111111122222222223333333 / char + * 0123456789012345678901234567890123456 \ posn + * >RTMhhmmssdddDDMMYYYYoodnnvrrrrr;*xx< Actual + * ----33445566600112222BB7__-_____--99- Parse + * >RTM 1 ;* <", Check + */ + +#define hexval(x) (('0' <= (x) && (x) <= '9') ? (x) - '0' : \ + ('a' <= (x) && (x) <= 'f') ? (x) - 'a' + 10 : \ + ('A' <= (x) && (x) <= 'F') ? (x) - 'A' + 10 : \ + -1) +#define O_USEC O_WDAY +#define O_GPSFIX O_FLAGS +#define O_CHKSUM O_UTCHOFFSET + static struct format trimsv6_fmt = +{ { { 13, 2 }, {15, 2}, { 17, 4}, /* Day, Month, Year */ + { 4, 2 }, { 6, 2}, { 8, 2}, /* Hour, Minute, Second */ + { 10, 3 }, {23, 1}, { 0, 0}, /* uSec, FIXes (WeekDAY, FLAGS, ZONE) */ + { 34, 2 }, { 0, 0}, { 21, 2}, /* cksum, -, utcS (UTC[HMS]OFFSET) */ +}, + (const unsigned char *)">RTM 1 ;* <", + 0 +}; + +static unsigned long cvt_trimtaip (unsigned char *, int, struct format *, clocktime_t *, void *); +static unsigned long inp_trimtaip (parse_t *, unsigned int, timestamp_t *); + +clockformat_t clock_trimtaip = +{ + inp_trimtaip, /* no input handling */ + cvt_trimtaip, /* Trimble conversion */ + pps_one, /* easy PPS monitoring */ + (void *)&trimsv6_fmt, /* conversion configuration */ + "Trimble TAIP", + 37, /* string buffer */ + 0 /* no private data */ +}; + +static unsigned long +cvt_trimtaip( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + long gpsfix; + u_char calc_csum = 0; + long recv_csum; + int i; + + if (!Strok(buffer, format->fixed_string)) return CVT_NONE; +#define OFFS(x) format->field_offsets[(x)].offset +#define STOI(x, y) \ + Stoi(&buffer[OFFS(x)], y, \ + format->field_offsets[(x)].length) + if ( STOI(O_DAY, &clock_time->day) || + STOI(O_MONTH, &clock_time->month) || + STOI(O_YEAR, &clock_time->year) || + STOI(O_HOUR, &clock_time->hour) || + STOI(O_MIN, &clock_time->minute) || + STOI(O_SEC, &clock_time->second) || + STOI(O_USEC, &clock_time->usecond)|| + STOI(O_GPSFIX, &gpsfix) + ) return CVT_FAIL|CVT_BADFMT; + + clock_time->usecond *= 1000; + /* Check that the checksum is right */ + for (i=OFFS(O_CHKSUM)-1; i >= 0; i--) calc_csum ^= buffer[i]; + recv_csum = (hexval(buffer[OFFS(O_CHKSUM)]) << 4) | + hexval(buffer[OFFS(O_CHKSUM)+1]); + if (recv_csum < 0) return CVT_FAIL|CVT_BADTIME; + if (((u_char) recv_csum) != calc_csum) return CVT_FAIL|CVT_BADTIME; + + clock_time->utcoffset = 0; + + /* What should flags be set to ? */ + clock_time->flags = PARSEB_UTC; + + /* if the current GPS fix is 9 (unknown), reject */ + if (0 > gpsfix || gpsfix > 9) clock_time->flags |= PARSEB_POWERUP; + + return CVT_OK; +} + +/* + * inp_trimtaip + * + * grep data from input stream + */ +static u_long +inp_trimtaip( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_trimtaip(0x%lx, 0x%x, ...)\n", (long)parseio, ch)); + + switch (ch) + { + case '>': + parseprintf(DD_PARSE, ("inp_trimptaip: START seen\n")); + + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + return PARSE_INP_SKIP; + + case '<': + parseprintf(DD_PARSE, ("inp_trimtaip: END seen\n")); + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + + default: + return parse_addchar(parseio, ch); + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_TRIMTAIP) */ +int clk_trimtaip_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_TRIMTAIP) */ + +/* + * History: + * + * clk_trimtaip.c,v + * Revision 4.11 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.10 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.7 1999/11/28 09:13:51 kardel + * RECON_4_0_98F + * + * Revision 4.6 1998/08/16 18:46:27 kardel + * (clock_trimtaip =): changed format name + * + * Revision 4.5 1998/06/14 21:09:38 kardel + * Sun acc cleanup + * + * Revision 4.4 1998/06/13 12:06:57 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:29 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:26 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:54 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:31 kardel + * Start 4.0 release version numbering + * + * from V3 1.4 log info deleted 1998/04/11 kardel + */ + diff --git a/libparse/clk_trimtsip.c b/libparse/clk_trimtsip.c new file mode 100644 index 0000000..743e39c --- /dev/null +++ b/libparse/clk_trimtsip.c @@ -0,0 +1,463 @@ +/* + * /src/NTP/REPOSITORY/ntp4-dev/libparse/clk_trimtsip.c,v 4.19 2009/11/01 10:47:49 kardel RELEASE_20091101_A + * + * clk_trimtsip.c,v 4.19 2009/11/01 10:47:49 kardel RELEASE_20091101_A + * + * Trimble TSIP support + * Thanks to Sven Dietrich for providing test hardware + * + * Copyright (c) 1995-2009 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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 +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_TRIMTSIP) + +#include "ntp_syslog.h" +#include "ntp_types.h" +#include "ntp_fp.h" +#include "timevalops.h" +#include "ntp_calendar.h" +#include "ntp_machine.h" +#include "ntp_stdlib.h" + +#include "parse.h" + +#ifndef PARSESTREAM +# include +#else +# include "sys/parsestreams.h" +#endif + +#include "ascii.h" +#include "binio.h" +#include "ieee754io.h" +#include "trimble.h" + +/* + * Trimble low level TSIP parser / time converter + * + * The receiver uses a serial message protocol called Trimble Standard + * Interface Protocol (it can support others but this driver only supports + * TSIP). Messages in this protocol have the following form: + * + * ... ... + * + * Any bytes within the portion of value 10 hex () are doubled + * on transmission and compressed back to one on reception. Otherwise + * the values of data bytes can be anything. The serial interface is RS-422 + * asynchronous using 9600 baud, 8 data bits with odd party (**note** 9 bits + * in total!), and 1 stop bit. The protocol supports byte, integer, single, + * and double datatypes. Integers are two bytes, sent most significant first. + * Singles are IEEE754 single precision floating point numbers (4 byte) sent + * sign & exponent first. Doubles are IEEE754 double precision floating point + * numbers (8 byte) sent sign & exponent first. + * The receiver supports a large set of messages, only a very small subset of + * which is used here. + * + * From this module the following are recognised: + * + * ID Description + * + * 41 GPS Time + * 46 Receiver health + * 4F UTC correction data (used to get leap second warnings) + * + * All others are accepted but ignored for time conversion - they are passed up to higher layers. + * + */ + +static offsets_t trim_offsets = { 0, 1, 2, 3, 4, 5, 6, 7 }; + +struct trimble +{ + u_char t_in_pkt; /* first DLE received */ + u_char t_dle; /* subsequent DLE received */ + u_short t_week; /* GPS week */ + u_short t_weekleap; /* GPS week of next/last week */ + u_short t_dayleap; /* day in week */ + u_short t_gpsutc; /* GPS - UTC offset */ + u_short t_gpsutcleap; /* offset at next/last leap */ + u_char t_operable; /* receiver feels OK */ + u_char t_mode; /* actual operating mode */ + u_char t_leap; /* possible leap warning */ + u_char t_utcknown; /* utc offset known */ +}; + +#define STATUS_BAD 0 /* BAD or UNINITIALIZED receiver status */ +#define STATUS_UNSAFE 1 /* not enough receivers for full precision */ +#define STATUS_SYNC 2 /* enough information for good operation */ + +static unsigned long inp_tsip (parse_t *, unsigned int, timestamp_t *); +static unsigned long cvt_trimtsip (unsigned char *, int, struct format *, clocktime_t *, void *); + +struct clockformat clock_trimtsip = +{ + inp_tsip, /* Trimble TSIP input handler */ + cvt_trimtsip, /* Trimble TSIP conversion */ + pps_one, /* easy PPS monitoring */ + 0, /* no configuration data */ + "Trimble TSIP", + 400, /* input buffer */ + sizeof(struct trimble) /* private data */ +}; + +#define ADDSECOND 0x01 +#define DELSECOND 0x02 + +static unsigned long +inp_tsip( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + struct trimble *t = (struct trimble *)parseio->parse_pdata; + + if (!t) + return PARSE_INP_SKIP; /* local data not allocated - sigh! */ + + if (!t->t_in_pkt && ch != DLE) { + /* wait for start of packet */ + return PARSE_INP_SKIP; + } + + if ((parseio->parse_index >= (parseio->parse_dsize - 2)) || + (parseio->parse_dtime.parse_msglen >= (sizeof(parseio->parse_dtime.parse_msg) - 2))) + { /* OVERFLOW - DROP! */ + t->t_in_pkt = t->t_dle = 0; + parseio->parse_index = 0; + parseio->parse_dtime.parse_msglen = 0; + return PARSE_INP_SKIP; + } + + switch (ch) { + case DLE: + if (!t->t_in_pkt) { + t->t_dle = 0; + t->t_in_pkt = 1; + parseio->parse_index = 0; + parseio->parse_data[parseio->parse_index++] = ch; + parseio->parse_dtime.parse_msglen = 0; + parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch; + parseio->parse_dtime.parse_stime = *tstamp; /* pick up time stamp at packet start */ + } else if (t->t_dle) { + /* Double DLE -> insert a DLE */ + t->t_dle = 0; + parseio->parse_data[parseio->parse_index++] = DLE; + parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = DLE; + } else + t->t_dle = 1; + break; + + case ETX: + if (t->t_dle) { + /* DLE,ETX -> end of packet */ + parseio->parse_data[parseio->parse_index++] = DLE; + parseio->parse_data[parseio->parse_index] = ch; + parseio->parse_ldsize = parseio->parse_index+1; + memcpy(parseio->parse_ldata, parseio->parse_data, parseio->parse_ldsize); + parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = DLE; + parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch; + t->t_in_pkt = t->t_dle = 0; + return PARSE_INP_TIME|PARSE_INP_DATA; + } + /*FALLTHROUGH*/ + + default: /* collect data */ + t->t_dle = 0; + parseio->parse_data[parseio->parse_index++] = ch; + parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch; + } + + return PARSE_INP_SKIP; +} + +static int +getshort( + unsigned char *p + ) +{ + return get_msb_short(&p); +} + +/* + * cvt_trimtsip + * + * convert TSIP type format + */ +static unsigned long +cvt_trimtsip( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + register struct trimble *t = (struct trimble *)local; /* get local data space */ +#define mb(_X_) (buffer[2+(_X_)]) /* shortcut for buffer access */ + register u_char cmd; + + clock_time->flags = 0; + + if (!t) { + return CVT_NONE; /* local data not allocated - sigh! */ + } + + if ((size < 4) || + (buffer[0] != DLE) || + (buffer[size-1] != ETX) || + (buffer[size-2] != DLE)) + { + printf("TRIMBLE BAD packet, size %d:\n", size); + return CVT_NONE; + } + else + { + unsigned char *bp; + cmd = buffer[1]; + + switch(cmd) + { + case CMD_RCURTIME: + { /* GPS time */ + l_fp secs; + int week = getshort((unsigned char *)&mb(4)); + l_fp utcoffset; + l_fp gpstime; + + bp = &mb(0); + if (fetch_ieee754(&bp, IEEE_SINGLE, &secs, trim_offsets) != IEEE_OK) + return CVT_FAIL|CVT_BADFMT; + + if ((secs.l_i <= 0) || + (t->t_utcknown == 0)) + { + clock_time->flags = PARSEB_POWERUP; + return CVT_OK; + } + if (week < 990) { + week += 1024; + } + + /* time OK */ + + /* fetch UTC offset */ + bp = &mb(6); + if (fetch_ieee754(&bp, IEEE_SINGLE, &utcoffset, trim_offsets) != IEEE_OK) + return CVT_FAIL|CVT_BADFMT; + + L_SUB(&secs, &utcoffset); /* adjust GPS time to UTC time */ + + gpstolfp((unsigned short)week, (unsigned short)0, + secs.l_ui, &gpstime); + + gpstime.l_uf = secs.l_uf; + + clock_time->utctime = gpstime.l_ui - JAN_1970; + + TSFTOTVU(gpstime.l_uf, clock_time->usecond); + + if (t->t_leap == ADDSECOND) + clock_time->flags |= PARSEB_LEAPADD; + + if (t->t_leap == DELSECOND) + clock_time->flags |= PARSEB_LEAPDEL; + + switch (t->t_operable) + { + case STATUS_SYNC: + clock_time->flags &= ~(PARSEB_POWERUP|PARSEB_NOSYNC); + break; + + case STATUS_UNSAFE: + clock_time->flags |= PARSEB_NOSYNC; + break; + + case STATUS_BAD: + clock_time->flags |= PARSEB_NOSYNC|PARSEB_POWERUP; + break; + } + + if (t->t_mode == 0) + clock_time->flags |= PARSEB_POSITION; + + clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_POSITION; + + return CVT_OK; + + } /* case 0x41 */ + + case CMD_RRECVHEALTH: + { + /* TRIMBLE health */ + u_char status = mb(0); + + switch (status) + { + case 0x00: /* position fixes */ + t->t_operable = STATUS_SYNC; + break; + + case 0x09: /* 1 satellite */ + case 0x0A: /* 2 satellites */ + case 0x0B: /* 3 satellites */ + t->t_operable = STATUS_UNSAFE; + break; + + default: + t->t_operable = STATUS_BAD; + break; + } + t->t_mode = status; + } + break; + + case CMD_RUTCPARAM: + { + l_fp t0t; + unsigned char *lbp; + + /* UTC correction data - derive a leap warning */ + int tls = t->t_gpsutc = getshort((unsigned char *)&mb(12)); /* current leap correction (GPS-UTC) */ + int tlsf = t->t_gpsutcleap = getshort((unsigned char *)&mb(24)); /* new leap correction */ + + t->t_weekleap = getshort((unsigned char *)&mb(20)); /* week no of leap correction */ + if (t->t_weekleap < 990) + t->t_weekleap += 1024; + + t->t_dayleap = getshort((unsigned char *)&mb(22)); /* day in week of leap correction */ + t->t_week = getshort((unsigned char *)&mb(18)); /* current week no */ + if (t->t_week < 990) + t->t_week += 1024; + + lbp = (unsigned char *)&mb(14); /* last update time */ + if (fetch_ieee754(&lbp, IEEE_SINGLE, &t0t, trim_offsets) != IEEE_OK) + return CVT_FAIL|CVT_BADFMT; + + t->t_utcknown = t0t.l_ui != 0; + + if ((t->t_utcknown) && /* got UTC information */ + (tlsf != tls) && /* something will change */ + ((t->t_weekleap - t->t_week) < 5)) /* and close in the future */ + { + /* generate a leap warning */ + if (tlsf > tls) + t->t_leap = ADDSECOND; + else + t->t_leap = DELSECOND; + } + else + { + t->t_leap = 0; + } + } + break; + + default: + /* it's validly formed, but we don't care about it! */ + break; + } + } + return CVT_SKIP; +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_TRIMTSIP && !PARSESTREAM) */ +int clk_trimtsip_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_TRIMTSIP && !PARSESTREAM) */ + +/* + * History: + * + * clk_trimtsip.c,v + * Revision 4.19 2009/11/01 10:47:49 kardel + * de-P() + * + * Revision 4.18 2009/11/01 08:46:46 kardel + * clarify case FALLTHROUGH + * + * Revision 4.17 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.16 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.13 1999/11/28 09:13:51 kardel + * RECON_4_0_98F + * + * Revision 4.12 1999/02/28 13:00:08 kardel + * *** empty log message *** + * + * Revision 4.11 1999/02/28 11:47:54 kardel + * (struct trimble): new member t_utcknown + * (cvt_trimtsip): fixed status monitoring, bad receiver states are + * now recognized + * + * Revision 4.10 1999/02/27 15:57:15 kardel + * use mmemcpy instead of bcopy + * + * Revision 4.9 1999/02/21 12:17:42 kardel + * 4.91f reconcilation + * + * Revision 4.8 1998/11/15 20:27:58 kardel + * Release 4.0.73e13 reconcilation + * + * Revision 4.7 1998/08/16 18:49:20 kardel + * (cvt_trimtsip): initial kernel capable version (no more floats) + * (clock_trimtsip =): new format name + * + * Revision 4.6 1998/08/09 22:26:05 kardel + * Trimble TSIP support + * + * Revision 4.5 1998/08/02 10:37:05 kardel + * working TSIP parser + * + * Revision 4.4 1998/06/28 16:50:40 kardel + * (getflt): fixed ENDIAN issue + * (getdbl): fixed ENDIAN issue + * (getint): use get_msb_short() + * (cvt_trimtsip): use gpstolfp() for conversion + * + * Revision 4.3 1998/06/13 12:07:31 kardel + * fix SYSV clock name clash + * + * Revision 4.2 1998/06/12 15:22:30 kardel + * fix prototypes + * + * Revision 4.1 1998/05/24 09:39:54 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:32 kardel + * Start 4.0 release version numbering + * + * from V3 1.8 loginfo deleted 1998/04/11 kardel + */ diff --git a/libparse/clk_varitext.c b/libparse/clk_varitext.c new file mode 100644 index 0000000..295ce0a --- /dev/null +++ b/libparse/clk_varitext.c @@ -0,0 +1,271 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_VARITEXT) +/* + * /src/NTP/ntp4-dev/libparse/clk_varitext.c,v 1.5 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * clk_varitext.c,v 1.5 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * Varitext code variant by A.McConnell 1997/01/19 + * + * Supports Varitext's Radio Clock + * + * Used the Meinberg/Computime clock as a template for Varitext Radio Clock + * + * Codebase: + * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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. + * + */ + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" + +#ifndef PARSESTREAM +# include "ntp_stdlib.h" +# include +#else +# include "sys/parsestreams.h" +extern int printf (const char *, ...); +#endif + +static const u_char VT_INITIALISED = 0x01; +static const u_char VT_SYNCHRONISED = 0x02; +static const u_char VT_ALARM_STATE = 0x04; +static const u_char VT_BST = 0x08; +static const u_char VT_SEASON_CHANGE = 0x10; +static const u_char VT_LAST_TELEGRAM_OK = 0x20; + +/* + * The Varitext receiver sends a datagram in the following format every minute + * + * Timestamp T:YY:MM:MD:WD:HH:MM:SSCRLFSTXXX + * Pos 0123456789012345678901 2 3 4567 + * 0000000000111111111122 2 2 2222 + * Parse T: : : : : : : \r\n + * + * T Startcharacter "T" specifies start of the timestamp + * YY Year MM Month 1-12 + * MD Day of the month + * WD Day of week + * HH Hour + * MM Minute + * SS Second + * CR Carriage return + * LF Linefeed + * ST Status character + * Bit 0 - Set= Initialised; Reset=Time Invalid (DO NOT USE) + * Bit 1 - Set= Synchronised; Reset= Unsynchronised + * Bit 2 - Set= Alarm state; Reset= No alarm + * Bit 3 - Set= BST; Reset= GMT + * Bit 4 - Set= Seasonal change in approx hour; Reset= No seasonal change expected + * Bit 5 - Set= Last MSF telegram was OK; Reset= Last telegram was in error; + * Bit 6 - Always set + * Bit 7 - Unused + * XXX Checksum calculated using Fletcher's method (ignored for now). + */ + +static struct format varitext_fmt = +{ + { + {8, 2}, {5, 2}, {2, 2}, /* day, month, year */ + {14, 2}, {17, 2}, {20, 2}, /* hour, minute, second */ + {11, 2}, {24, 1} /* dayofweek, status */ + }, + (const unsigned char*)"T: : : : : : : \r\n ", + 0 +}; + +static u_long cvt_varitext (unsigned char *, int, struct format *, clocktime_t *, void *); +static u_long inp_varitext (parse_t *, unsigned int, timestamp_t *); + +struct varitext { + unsigned char start_found; + unsigned char end_found; + unsigned char end_count; + unsigned char previous_ch; + timestamp_t tstamp; +}; + +clockformat_t clock_varitext = +{ + inp_varitext, /* Because of the strange format we need to parse it ourselves */ + cvt_varitext, /* Varitext conversion */ + 0, /* no PPS monitoring */ + (void *)&varitext_fmt, /* conversion configuration */ + "Varitext Radio Clock", /* Varitext Radio Clock */ + 30, /* string buffer */ + sizeof(struct varitext), /* Private data size required to hold current parse state */ +}; + +/* + * cvt_varitext + * + * convert simple type format + */ +static u_long +cvt_varitext( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + + if (!Strok(buffer, format->fixed_string)) { + return CVT_NONE; + } else { + if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, + format->field_offsets[O_DAY].length) || + Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, + format->field_offsets[O_MONTH].length) || + Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, + format->field_offsets[O_YEAR].length) || + Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, + format->field_offsets[O_HOUR].length) || + Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, + format->field_offsets[O_MIN].length) || + Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, + format->field_offsets[O_SEC].length)) { + return CVT_FAIL | CVT_BADFMT; + } else { + u_char *f = (u_char*) &buffer[format->field_offsets[O_FLAGS].offset]; + + clock_time->flags = 0; + clock_time->utcoffset = 0; + + if (((*f) & VT_BST)) /* BST flag is set so set to indicate daylight saving time is active and utc offset */ + { + clock_time->utcoffset = -1*60*60; + clock_time->flags |= PARSEB_DST; + } + /* + if (!((*f) & VT_INITIALISED)) Clock not initialised + clock_time->flags |= PARSEB_POWERUP; + + if (!((*f) & VT_SYNCHRONISED)) Clock not synchronised + clock_time->flags |= PARSEB_NOSYNC; + + if (((*f) & VT_SEASON_CHANGE)) Seasonal change expected in the next hour + clock_time->flags |= PARSEB_ANNOUNCE; + */ + return CVT_OK; + } + } +} + +static u_long +inp_varitext( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + struct varitext *t = (struct varitext *)parseio->parse_pdata; + int rtc; + + parseprintf(DD_PARSE, ("inp_varitext(0x%lx, 0x%x, ...)\n", (long)parseio, ch)); + + if (!t) + return PARSE_INP_SKIP; /* local data not allocated - sigh! */ + + if (ch == 'T') + t->tstamp = *tstamp; + + if ((t->previous_ch == 'T') && (ch == ':')) + { + parseprintf(DD_PARSE, ("inp_varitext: START seen\n")); + + parseio->parse_data[0] = 'T'; + parseio->parse_index=1; + parseio->parse_dtime.parse_stime = t->tstamp; /* Time stamp at packet start */ + t->start_found = 1; + t->end_found = 0; + t->end_count = 0; + } + + if (t->start_found) + { + if ((rtc = parse_addchar(parseio, ch)) != PARSE_INP_SKIP) + { + parseprintf(DD_PARSE, ("inp_varitext: ABORTED due to too many characters\n")); + + memset(t, 0, sizeof(struct varitext)); + return rtc; + } + + if (t->end_found) + { + if (++(t->end_count) == 4) /* Finally found the end of the message */ + { + parseprintf(DD_PARSE, ("inp_varitext: END seen\n")); + + memset(t, 0, sizeof(struct varitext)); + if ((rtc = parse_addchar(parseio, 0)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + } + } + + if ((t->previous_ch == '\r') && (ch == '\n')) + { + t->end_found = 1; + } + + } + + t->previous_ch = ch; + + return PARSE_INP_SKIP; +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_VARITEXT) */ +int clk_varitext_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_VARITEXT) */ + +/* + * History: + * + * clk_varitext.c,v + * Revision 1.5 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 1.4 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * + * Revision 1.0 1997/06/02 13:16:30 McConnell + * File created + * + */ diff --git a/libparse/clk_wharton.c b/libparse/clk_wharton.c new file mode 100644 index 0000000..55ab43a --- /dev/null +++ b/libparse/clk_wharton.c @@ -0,0 +1,181 @@ +/* + * /src/NTP/ntp4-dev/libparse/clk_wharton.c,v 4.2 2004/11/14 15:29:41 kardel RELEASE_20050508_A + * + * clk_wharton.c,v 4.2 2004/11/14 15:29:41 kardel RELEASE_20050508_A + * + * From Philippe De Muyter , 1999 + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_WHARTON_400A) +/* + * Support for WHARTON 400A Series clock + 404.2 serial interface. + * + * Copyright (C) 1999, 2000 by Philippe De Muyter + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#include "ntp_fp.h" +#include "ascii.h" +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include +#else +#include "sys/parsestreams.h" +extern void printf (const char *, ...); +#endif + +/* + * In private e-mail alastair@wharton.co.uk said : + * "If you are going to use the 400A and 404.2 system [for ntp] I recommend + * that you set the 400A to output the message every second. The start of + * transmission of the first byte of the message is synchronised to the + * second edge." + * The WHARTON 400A Series is able to send date/time serial messages + * in 7 output formats. We use format 1 here because it is the shortest. + * For use with this driver, the WHARTON 400A Series clock must be set-up + * as follows : + * Programmable Selected + * Option No Option + * BST or CET display 3 9 or 11 + * No external controller 7 0 + * Serial Output Format 1 9 1 + * Baud rate 9600 bps 10 96 + * Bit length 8 bits 11 8 + * Parity even 12 E + * + * WHARTON 400A Series output format 1 is as follows : + * + * Timestamp STXssmmhhDDMMYYSETX + * Pos 0 12345678901234 + * 0 00000000011111 + * + * STX start transmission (ASCII 0x02) + * ETX end transmission (ASCII 0x03) + * ss Second expressed in reversed decimal (units then tens) + * mm Minute expressed in reversed decimal + * hh Hour expressed in reversed decimal + * DD Day of month expressed in reversed decimal + * MM Month expressed in reversed decimal (January is 1) + * YY Year (without century) expressed in reversed decimal + * S Status byte : 0x30 + + * bit 0 0 = MSF source 1 = DCF source + * bit 1 0 = Winter time 1 = Summer time + * bit 2 0 = not synchronised 1 = synchronised + * bit 3 0 = no early warning 1 = early warning + * + */ + +/* + * cvt_wharton_400a + * + * convert simple type format + */ +static u_long +cvt_wharton_400a( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + int i; + + /* The given `size' includes a terminating null-character. */ + if (size != 15 || buffer[0] != STX || buffer[14] != ETX + || buffer[13] < '0' || buffer[13] > ('0' + 0xf)) + return CVT_NONE; + for (i = 1; i < 13; i += 1) + if (buffer[i] < '0' || buffer[i] > '9') + return CVT_NONE; + clock_time->second = (buffer[2] - '0') * 10 + buffer[1] - '0'; + clock_time->minute = (buffer[4] - '0') * 10 + buffer[3] - '0'; + clock_time->hour = (buffer[6] - '0') * 10 + buffer[5] - '0'; + clock_time->day = (buffer[8] - '0') * 10 + buffer[7] - '0'; + clock_time->month = (buffer[10] - '0') * 10 + buffer[9] - '0'; + clock_time->year = (buffer[12] - '0') * 10 + buffer[11] - '0'; + clock_time->usecond = 0; + if (buffer[13] & 0x1) /* We have CET time */ + clock_time->utcoffset = -1*60*60; + else /* We have BST time */ + clock_time->utcoffset = 0; + if (buffer[13] & 0x2) { + clock_time->flags |= PARSEB_DST; + clock_time->utcoffset += -1*60*60; + } + if (!(buffer[13] & 0x4)) + clock_time->flags |= PARSEB_NOSYNC; + if (buffer[13] & 0x8) + clock_time->flags |= PARSEB_ANNOUNCE; + + return CVT_OK; +} + +/* + * inp_wharton_400a + * + * grep data from input stream + */ +static u_long +inp_wharton_400a( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_wharton_400a(0x%lx, 0x%x, ...)\n", (long)parseio, ch)); + + switch (ch) + { + case STX: + parseprintf(DD_PARSE, ("inp_wharton_400a: STX seen\n")); + + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + return PARSE_INP_SKIP; + + case ETX: + parseprintf(DD_PARSE, ("inp_wharton_400a: ETX seen\n")); + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + default: + return parse_addchar(parseio, ch); + } +} + +clockformat_t clock_wharton_400a = +{ + inp_wharton_400a, /* input handling function */ + cvt_wharton_400a, /* conversion function */ + 0, /* no PPS monitoring */ + 0, /* conversion configuration */ + "WHARTON 400A Series clock Output Format 1", /* String format name */ + 15, /* string buffer */ + 0 /* no private data (complete pakets) */ +}; + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_WHARTON_400A) */ +int clk_wharton_400a_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_WHARTON_400A) */ + +/* + * clk_wharton.c,v + * Revision 4.1 1999/02/28 15:27:24 kardel + * wharton clock integration + * + */ diff --git a/libparse/data_mbg.c b/libparse/data_mbg.c new file mode 100644 index 0000000..97bef35 --- /dev/null +++ b/libparse/data_mbg.c @@ -0,0 +1,539 @@ +/* + * /src/NTP/REPOSITORY/ntp4-dev/libparse/data_mbg.c,v 4.8 2006/06/22 18:40:01 kardel RELEASE_20060622_A + * + * data_mbg.c,v 4.8 2006/06/22 18:40:01 kardel RELEASE_20060622_A + * + * $Created: Sun Jul 20 12:08:14 1997 $ + * + * Copyright (c) 1997-2005 by Frank Kardel ntp.org> + * + * 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. + * + */ + +#include +#ifdef PARSESTREAM +#define NEED_BOPS +#include "ntp_string.h" +#else +#include +#endif +#include "ntp_types.h" +#include "ntp_stdlib.h" +#include "ntp_fp.h" +#include "mbg_gps166.h" +#include "binio.h" +#include "ieee754io.h" + +static void get_mbg_tzname (unsigned char **, char *); +static void mbg_time_status_str (char **, unsigned int, int); + +#if 0 /* no actual floats on Meinberg binary interface */ +static offsets_t mbg_float = { 1, 0, 3, 2, 0, 0, 0, 0 }; /* byte order for meinberg floats */ +#endif +static offsets_t mbg_double = { 1, 0, 3, 2, 5, 4, 7, 6 }; /* byte order for meinberg doubles */ +static int32 rad2deg_i = 57; +static u_int32 rad2deg_f = 0x4BB834C7; /* 57.2957795131 == 180/PI */ + +void +put_mbg_header( + unsigned char **bufpp, + GPS_MSG_HDR *headerp + ) +{ + put_lsb_short(bufpp, headerp->gps_cmd); + put_lsb_short(bufpp, headerp->gps_len); + put_lsb_short(bufpp, headerp->gps_data_csum); + put_lsb_short(bufpp, headerp->gps_hdr_csum); +} + +void +get_mbg_sw_rev( + unsigned char **bufpp, + SW_REV *sw_revp + ) +{ + sw_revp->code = get_lsb_short(bufpp); + memcpy(sw_revp->name, *bufpp, sizeof(sw_revp->name)); + *bufpp += sizeof(sw_revp->name); +} + +void +get_mbg_ascii_msg( + unsigned char **bufpp, + ASCII_MSG *ascii_msgp + ) +{ + ascii_msgp->csum = get_lsb_short(bufpp); + ascii_msgp->valid = get_lsb_short(bufpp); + memcpy(ascii_msgp->s, *bufpp, sizeof(ascii_msgp->s)); + *bufpp += sizeof(ascii_msgp->s); +} + +void +get_mbg_svno( + unsigned char **bufpp, + SVNO *svnop + ) +{ + *svnop = get_lsb_short(bufpp); +} + +void +get_mbg_health( + unsigned char **bufpp, + HEALTH *healthp + ) +{ + *healthp = get_lsb_short(bufpp); +} + +void +get_mbg_cfg( + unsigned char **bufpp, + CFG *cfgp + ) +{ + *cfgp = get_lsb_short(bufpp); +} + +void +get_mbg_tgps( + unsigned char **bufpp, + T_GPS *tgpsp + ) +{ + tgpsp->wn = get_lsb_short(bufpp); + tgpsp->sec = get_lsb_long(bufpp); + tgpsp->tick = get_lsb_long(bufpp); +} + +void +get_mbg_tm( + unsigned char **buffpp, + TM *tmp + ) +{ + tmp->year = get_lsb_short(buffpp); + tmp->month = *(*buffpp)++; + tmp->mday = *(*buffpp)++; + tmp->yday = get_lsb_short(buffpp); + tmp->wday = *(*buffpp)++; + tmp->hour = *(*buffpp)++; + tmp->minute = *(*buffpp)++; + tmp->second = *(*buffpp)++; + tmp->frac = get_lsb_long(buffpp); + tmp->offs_from_utc = get_lsb_long(buffpp); + tmp->status= get_lsb_short(buffpp); +} + +void +get_mbg_ttm( + unsigned char **buffpp, + TTM *ttmp + ) +{ + ttmp->channel = get_lsb_short(buffpp); + get_mbg_tgps(buffpp, &ttmp->t); + get_mbg_tm(buffpp, &ttmp->tm); +} + +void +get_mbg_synth( + unsigned char **buffpp, + SYNTH *synthp + ) +{ + synthp->freq = get_lsb_short(buffpp); + synthp->range = get_lsb_short(buffpp); + synthp->phase = get_lsb_short(buffpp); +} + +static void +get_mbg_tzname( + unsigned char **buffpp, + char *tznamep + ) +{ + strlcpy(tznamep, (char *)*buffpp, sizeof(TZ_NAME)); + *buffpp += sizeof(TZ_NAME); +} + +void +get_mbg_tzdl( + unsigned char **buffpp, + TZDL *tzdlp + ) +{ + tzdlp->offs = get_lsb_long(buffpp); + tzdlp->offs_dl = get_lsb_long(buffpp); + get_mbg_tm(buffpp, &tzdlp->tm_on); + get_mbg_tm(buffpp, &tzdlp->tm_off); + get_mbg_tzname(buffpp, (char *)tzdlp->name[0]); + get_mbg_tzname(buffpp, (char *)tzdlp->name[1]); +} + +void +get_mbg_antinfo( + unsigned char **buffpp, + ANT_INFO *antinfop + ) +{ + antinfop->status = get_lsb_short(buffpp); + get_mbg_tm(buffpp, &antinfop->tm_disconn); + get_mbg_tm(buffpp, &antinfop->tm_reconn); + antinfop->delta_t = get_lsb_long(buffpp); +} + +static void +mbg_time_status_str( + char **buffpp, + unsigned int status, + int size + ) +{ + static struct state + { + int flag; /* bit flag */ + const char *string; /* bit name */ + } states[] = + { + { TM_UTC, "UTC CORR" }, + { TM_LOCAL, "LOCAL TIME" }, + { TM_DL_ANN, "DST WARN" }, + { TM_DL_ENB, "DST" }, + { TM_LS_ANN, "LEAP WARN" }, + { TM_LS_ENB, "LEAP SEC" }, + { 0, "" } + }; + + if (status) + { + char *start, *p; + struct state *s; + + start = p = *buffpp; + + for (s = states; s->flag; s++) + { + if (s->flag & status) + { + if (p != *buffpp) + { + strlcpy(p, ", ", size - (p - start)); + p += 2; + } + strlcpy(p, s->string, size - (p - start)); + p += strlen(p); + } + } + *buffpp = p; + } +} + +void +mbg_tm_str( + char **buffpp, + TM *tmp, + int size + ) +{ + char *s = *buffpp; + + snprintf(*buffpp, size, "%04d-%02d-%02d %02d:%02d:%02d.%07ld (%c%02d%02d) ", + tmp->year, tmp->month, tmp->mday, + tmp->hour, tmp->minute, tmp->second, tmp->frac, + (tmp->offs_from_utc < 0) ? '-' : '+', + abs(tmp->offs_from_utc) / 3600, + (abs(tmp->offs_from_utc) / 60) % 60); + *buffpp += strlen(*buffpp); + + mbg_time_status_str(buffpp, tmp->status, size - (*buffpp - s)); +} + +void +mbg_tgps_str( + char **buffpp, + T_GPS *tgpsp, + int size + ) +{ + snprintf(*buffpp, size, "week %d + %ld days + %ld.%07ld sec", + tgpsp->wn, tgpsp->sec / 86400, + tgpsp->sec % 86400, tgpsp->tick); + *buffpp += strlen(*buffpp); +} + +void +get_mbg_cfgh( + unsigned char **buffpp, + CFGH *cfghp + ) +{ + int i; + + cfghp->csum = get_lsb_short(buffpp); + cfghp->valid = get_lsb_short(buffpp); + get_mbg_tgps(buffpp, &cfghp->tot_51); + get_mbg_tgps(buffpp, &cfghp->tot_63); + get_mbg_tgps(buffpp, &cfghp->t0a); + + for (i = MIN_SVNO; i <= MAX_SVNO; i++) + { + get_mbg_cfg(buffpp, &cfghp->cfg[i]); + } + + for (i = MIN_SVNO; i <= MAX_SVNO; i++) + { + get_mbg_health(buffpp, &cfghp->health[i]); + } +} + +void +get_mbg_utc( + unsigned char **buffpp, + UTC *utcp + ) +{ + utcp->csum = get_lsb_short(buffpp); + utcp->valid = get_lsb_short(buffpp); + + get_mbg_tgps(buffpp, &utcp->t0t); + + if (fetch_ieee754(buffpp, IEEE_DOUBLE, &utcp->A0, mbg_double) != IEEE_OK) + { + L_CLR(&utcp->A0); + } + + if (fetch_ieee754(buffpp, IEEE_DOUBLE, &utcp->A1, mbg_double) != IEEE_OK) + { + L_CLR(&utcp->A1); + } + + utcp->WNlsf = get_lsb_short(buffpp); + utcp->DNt = get_lsb_short(buffpp); + utcp->delta_tls = *(*buffpp)++; + utcp->delta_tlsf = *(*buffpp)++; +} + +void +get_mbg_lla( + unsigned char **buffpp, + LLA lla + ) +{ + int i; + + for (i = LAT; i <= ALT; i++) + { + if (fetch_ieee754(buffpp, IEEE_DOUBLE, &lla[i], mbg_double) != IEEE_OK) + { + L_CLR(&lla[i]); + } + else + if (i != ALT) + { /* convert to degrees (* 180/PI) */ + mfp_mul(&lla[i].l_i, &lla[i].l_uf, lla[i].l_i, lla[i].l_uf, rad2deg_i, rad2deg_f); + } + } +} + +void +get_mbg_xyz( + unsigned char **buffpp, + XYZ xyz + ) +{ + int i; + + for (i = XP; i <= ZP; i++) + { + if (fetch_ieee754(buffpp, IEEE_DOUBLE, &xyz[i], mbg_double) != IEEE_OK) + { + L_CLR(&xyz[i]); + } + } +} + +static void +get_mbg_comparam( + unsigned char **buffpp, + COM_PARM *comparamp + ) +{ + int i; + + comparamp->baud_rate = get_lsb_long(buffpp); + for (i = 0; i < sizeof(comparamp->framing); i++) + { + comparamp->framing[i] = *(*buffpp)++; + } + comparamp->handshake = get_lsb_short(buffpp); +} + +void +get_mbg_portparam( + unsigned char **buffpp, + PORT_PARM *portparamp + ) +{ + int i; + + for (i = 0; i < N_COM; i++) + { + get_mbg_comparam(buffpp, &portparamp->com[i]); + } + for (i = 0; i < N_COM; i++) + { + portparamp->mode[i] = *(*buffpp)++; + } +} + +#define FETCH_DOUBLE(src, addr) \ + if (fetch_ieee754(src, IEEE_DOUBLE, addr, mbg_double) != IEEE_OK) \ + { \ + L_CLR(addr); \ + } + +void +get_mbg_eph( + unsigned char ** buffpp, + EPH *ephp + ) +{ + ephp->csum = get_lsb_short(buffpp); + ephp->valid = get_lsb_short(buffpp); + + ephp->health = get_lsb_short(buffpp); + ephp->IODC = get_lsb_short(buffpp); + ephp->IODE2 = get_lsb_short(buffpp); + ephp->IODE3 = get_lsb_short(buffpp); + + get_mbg_tgps(buffpp, &ephp->tt); + get_mbg_tgps(buffpp, &ephp->t0c); + get_mbg_tgps(buffpp, &ephp->t0e); + + FETCH_DOUBLE(buffpp, &ephp->sqrt_A); + FETCH_DOUBLE(buffpp, &ephp->e); + FETCH_DOUBLE(buffpp, &ephp->M0); + FETCH_DOUBLE(buffpp, &ephp->omega); + FETCH_DOUBLE(buffpp, &ephp->OMEGA0); + FETCH_DOUBLE(buffpp, &ephp->OMEGADOT); + FETCH_DOUBLE(buffpp, &ephp->deltan); + FETCH_DOUBLE(buffpp, &ephp->i0); + FETCH_DOUBLE(buffpp, &ephp->idot); + FETCH_DOUBLE(buffpp, &ephp->crc); + FETCH_DOUBLE(buffpp, &ephp->crs); + FETCH_DOUBLE(buffpp, &ephp->cuc); + FETCH_DOUBLE(buffpp, &ephp->cus); + FETCH_DOUBLE(buffpp, &ephp->cic); + FETCH_DOUBLE(buffpp, &ephp->cis); + + FETCH_DOUBLE(buffpp, &ephp->af0); + FETCH_DOUBLE(buffpp, &ephp->af1); + FETCH_DOUBLE(buffpp, &ephp->af2); + FETCH_DOUBLE(buffpp, &ephp->tgd); + + ephp->URA = get_lsb_short(buffpp); + + ephp->L2code = *(*buffpp)++; + ephp->L2flag = *(*buffpp)++; +} + +void +get_mbg_alm( + unsigned char **buffpp, + ALM *almp + ) +{ + almp->csum = get_lsb_short(buffpp); + almp->valid = get_lsb_short(buffpp); + + almp->health = get_lsb_short(buffpp); + get_mbg_tgps(buffpp, &almp->t0a); + + + FETCH_DOUBLE(buffpp, &almp->sqrt_A); + FETCH_DOUBLE(buffpp, &almp->e); + + FETCH_DOUBLE(buffpp, &almp->M0); + FETCH_DOUBLE(buffpp, &almp->omega); + FETCH_DOUBLE(buffpp, &almp->OMEGA0); + FETCH_DOUBLE(buffpp, &almp->OMEGADOT); + FETCH_DOUBLE(buffpp, &almp->deltai); + FETCH_DOUBLE(buffpp, &almp->af0); + FETCH_DOUBLE(buffpp, &almp->af1); +} + +void +get_mbg_iono( + unsigned char **buffpp, + IONO *ionop + ) +{ + ionop->csum = get_lsb_short(buffpp); + ionop->valid = get_lsb_short(buffpp); + + FETCH_DOUBLE(buffpp, &ionop->alpha_0); + FETCH_DOUBLE(buffpp, &ionop->alpha_1); + FETCH_DOUBLE(buffpp, &ionop->alpha_2); + FETCH_DOUBLE(buffpp, &ionop->alpha_3); + + FETCH_DOUBLE(buffpp, &ionop->beta_0); + FETCH_DOUBLE(buffpp, &ionop->beta_1); + FETCH_DOUBLE(buffpp, &ionop->beta_2); + FETCH_DOUBLE(buffpp, &ionop->beta_3); +} + +/* + * data_mbg.c,v + * Revision 4.8 2006/06/22 18:40:01 kardel + * clean up signedness (gcc 4) + * + * Revision 4.7 2005/10/07 22:11:10 kardel + * bounded buffer implementation + * + * Revision 4.6.2.1 2005/09/25 10:23:06 kardel + * support bounded buffers + * + * Revision 4.6 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.5 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.3 1999/02/21 12:17:42 kardel + * 4.91f reconcilation + * + * Revision 4.2 1998/06/14 21:09:39 kardel + * Sun acc cleanup + * + * Revision 4.1 1998/05/24 08:02:06 kardel + * trimmed version log + * + * Revision 4.0 1998/04/10 19:45:33 kardel + * Start 4.0 release version numbering + */ + diff --git a/libparse/gpstolfp.c b/libparse/gpstolfp.c new file mode 100644 index 0000000..5354dd3 --- /dev/null +++ b/libparse/gpstolfp.c @@ -0,0 +1,77 @@ +/* + * /src/NTP/ntp4-dev/libntp/gpstolfp.c,v 4.8 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * gpstolfp.c,v 4.8 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * $Created: Sun Jun 28 16:30:38 1998 $ + * + * Copyright (c) 1998-2005 by Frank Kardel ntp.org> + * + * 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. + * + */ +#include +#include "ntp_fp.h" + +#define GPSORIGIN 2524953600UL /* NTP origin - GPS origin in seconds */ +#define SECSPERWEEK (unsigned)(604800) /* seconds per week - GPS tells us about weeks */ +#define GPSWRAP 990 /* assume week count less than this in the previous epoch */ + +void +gpstolfp( + int weeks, + int days, + unsigned long seconds, + l_fp * lfp + ) +{ + if (weeks < GPSWRAP) + { + weeks += 1024; + } + + lfp->l_ui = weeks * SECSPERWEEK + days * 86400 + seconds + GPSORIGIN; /* convert to NTP time */ + lfp->l_uf = 0; +} + +/* + * History: + * + * gpstolfp.c,v + * Revision 4.8 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.7 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.3 1999/02/28 11:42:44 kardel + * (GPSWRAP): update GPS rollover to 990 weeks + * + * Revision 4.2 1998/07/11 10:05:25 kardel + * Release 4.0.73d reconcilation + * + * Revision 4.1 1998/06/28 16:47:15 kardel + * added gpstolfp() function + */ diff --git a/libparse/ieee754io.c b/libparse/ieee754io.c new file mode 100644 index 0000000..61bc853 --- /dev/null +++ b/libparse/ieee754io.c @@ -0,0 +1,614 @@ +/* + * /src/NTP/ntp4-dev/libntp/ieee754io.c,v 4.12 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * ieee754io.c,v 4.12 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * $Created: Sun Jul 13 09:12:02 1997 $ + * + * Copyright (c) 1997-2005 by Frank Kardel ntp.org> + * + * 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 + +#include +#include "l_stdlib.h" +#include "ntp_stdlib.h" +#include "ntp_fp.h" +#include "ieee754io.h" + +static unsigned char get_byte (unsigned char *, offsets_t, int *); +#ifdef __not_yet__ +static void put_byte (unsigned char *, offsets_t, int *, unsigned char); +#endif + +#ifdef LIBDEBUG + +#include "lib_strbuf.h" + +static char * +fmt_blong( + unsigned long val, + int cnt + ) +{ + char *buf, *s; + int i = cnt; + + val <<= 32 - cnt; + LIB_GETBUF(buf); + s = buf; + + while (i--) + { + if (val & 0x80000000) + { + *s++ = '1'; + } + else + { + *s++ = '0'; + } + val <<= 1; + } + *s = '\0'; + return buf; +} + +static char * +fmt_flt( + unsigned int sign, + unsigned long mh, + unsigned long ml, + unsigned long ch + ) +{ + char *buf; + + LIB_GETBUF(buf); + snprintf(buf, LIB_BUFLENGTH, "%c %s %s %s", sign ? '-' : '+', + fmt_blong(ch, 11), + fmt_blong(mh, 20), + fmt_blong(ml, 32)); + + return buf; +} + +static char * +fmt_hex( + unsigned char *bufp, + int length + ) +{ + char * buf; + char hex[4]; + int i; + + LIB_GETBUF(buf); + buf[0] = '\0'; + for (i = 0; i < length; i++) { + snprintf(hex, sizeof(hex), "%02x", bufp[i]); + strlcat(buf, hex, LIB_BUFLENGTH); + } + + return buf; +} + +#endif + +static unsigned char +get_byte( + unsigned char *bufp, + offsets_t offset, + int *fieldindex + ) +{ + unsigned char val; + + val = *(bufp + offset[*fieldindex]); +#ifdef LIBDEBUG + if (debug > 4) + printf("fetchieee754: getbyte(0x%08x, %d) = 0x%02x\n", (unsigned int)(bufp)+offset[*fieldindex], *fieldindex, val); +#endif + (*fieldindex)++; + return val; +} + +#ifdef __not_yet__ +static void +put_byte( + unsigned char *bufp, + offsets_t offsets, + int *fieldindex, + unsigned char val + ) +{ + *(bufp + offsets[*fieldindex]) = val; + (*fieldindex)++; +} +#endif + +/* + * make conversions to and from external IEEE754 formats and internal + * NTP FP format. + */ +int +fetch_ieee754( + unsigned char **buffpp, + int size, + l_fp *lfpp, + offsets_t offsets + ) +{ + unsigned char *bufp = *buffpp; + unsigned int sign; + unsigned int bias; + unsigned int maxexp; + int mbits; + u_long mantissa_low; + u_long mantissa_high; + u_long characteristic; + long exponent; +#ifdef LIBDEBUG + int length; +#endif + unsigned char val; + int fieldindex = 0; + + switch (size) + { + case IEEE_DOUBLE: +#ifdef LIBDEBUG + length = 8; +#endif + mbits = 52; + bias = 1023; + maxexp = 2047; + break; + + case IEEE_SINGLE: +#ifdef LIBDEBUG + length = 4; +#endif + mbits = 23; + bias = 127; + maxexp = 255; + break; + + default: + return IEEE_BADCALL; + } + + val = get_byte(bufp, offsets, &fieldindex); /* fetch sign byte & first part of characteristic */ + + sign = (val & 0x80) != 0; + characteristic = (val & 0x7F); + + val = get_byte(bufp, offsets, &fieldindex); /* fetch rest of characteristic and start of mantissa */ + + switch (size) + { + case IEEE_SINGLE: + characteristic <<= 1; + characteristic |= (val & 0x80) != 0; /* grab last characteristic bit */ + + mantissa_high = 0; + + mantissa_low = (val &0x7F) << 16; + mantissa_low |= (u_long)get_byte(bufp, offsets, &fieldindex) << 8; + mantissa_low |= get_byte(bufp, offsets, &fieldindex); + break; + + case IEEE_DOUBLE: + characteristic <<= 4; + characteristic |= (val & 0xF0) >> 4; /* grab lower characteristic bits */ + + mantissa_high = (val & 0x0F) << 16; + mantissa_high |= (u_long)get_byte(bufp, offsets, &fieldindex) << 8; + mantissa_high |= get_byte(bufp, offsets, &fieldindex); + + mantissa_low = (u_long)get_byte(bufp, offsets, &fieldindex) << 24; + mantissa_low |= (u_long)get_byte(bufp, offsets, &fieldindex) << 16; + mantissa_low |= (u_long)get_byte(bufp, offsets, &fieldindex) << 8; + mantissa_low |= get_byte(bufp, offsets, &fieldindex); + break; + + default: + return IEEE_BADCALL; + } +#ifdef LIBDEBUG + if (debug > 4) + { + double d; + float f; + + if (size == IEEE_SINGLE) + { + int i; + + for (i = 0; i < length; i++) + { + *((unsigned char *)(&f)+i) = *(*buffpp + offsets[i]); + } + d = f; + } + else + { + int i; + + for (i = 0; i < length; i++) + { + *((unsigned char *)(&d)+i) = *(*buffpp + offsets[i]); + } + } + + printf("fetchieee754: FP: %s -> %s -> %e(=%s)\n", fmt_hex(*buffpp, length), + fmt_flt(sign, mantissa_high, mantissa_low, characteristic), + d, fmt_hex((unsigned char *)&d, length)); + } +#endif + + *buffpp += fieldindex; + + /* + * detect funny numbers + */ + if (characteristic == maxexp) + { + /* + * NaN or Infinity + */ + if (mantissa_low || mantissa_high) + { + /* + * NaN + */ + return IEEE_NAN; + } + else + { + /* + * +Inf or -Inf + */ + return sign ? IEEE_NEGINFINITY : IEEE_POSINFINITY; + } + } + else + { + /* + * collect real numbers + */ + + L_CLR(lfpp); + + /* + * check for overflows + */ + exponent = characteristic - bias; + + if (exponent > 31) /* sorry - hardcoded */ + { + /* + * overflow only in respect to NTP-FP representation + */ + return sign ? IEEE_NEGOVERFLOW : IEEE_POSOVERFLOW; + } + else + { + int frac_offset; /* where the fraction starts */ + + frac_offset = mbits - exponent; + + if (characteristic == 0) + { + /* + * de-normalized or tiny number - fits only as 0 + */ + return IEEE_OK; + } + else + { + /* + * adjust for implied 1 + */ + if (mbits > 31) + mantissa_high |= 1 << (mbits - 32); + else + mantissa_low |= 1 << mbits; + + /* + * take mantissa apart - if only all machine would support + * 64 bit operations 8-( + */ + if (frac_offset > mbits) + { + lfpp->l_ui = 0; /* only fractional number */ + frac_offset -= mbits + 1; /* will now contain right shift count - 1*/ + if (mbits > 31) + { + lfpp->l_uf = mantissa_high << (63 - mbits); + lfpp->l_uf |= mantissa_low >> (mbits - 33); + lfpp->l_uf >>= frac_offset; + } + else + { + lfpp->l_uf = mantissa_low >> frac_offset; + } + } + else + { + if (frac_offset > 32) + { + /* + * must split in high word + */ + lfpp->l_ui = mantissa_high >> (frac_offset - 32); + lfpp->l_uf = (mantissa_high & ((1 << (frac_offset - 32)) - 1)) << (64 - frac_offset); + lfpp->l_uf |= mantissa_low >> (frac_offset - 32); + } + else + { + /* + * must split in low word + */ + lfpp->l_ui = mantissa_high << (32 - frac_offset); + lfpp->l_ui |= (mantissa_low >> frac_offset) & ((1 << (32 - frac_offset)) - 1); + lfpp->l_uf = (mantissa_low & ((1 << frac_offset) - 1)) << (32 - frac_offset); + } + } + + /* + * adjust for sign + */ + if (sign) + { + L_NEG(lfpp); + } + + return IEEE_OK; + } + } + } +} + +int +put_ieee754( + unsigned char **bufpp, + int size, + l_fp *lfpp, + offsets_t offsets + ) +{ + l_fp outlfp; +#ifdef LIBDEBUG + unsigned int sign; + unsigned int bias; +#endif +/*unsigned int maxexp;*/ + int mbits; + int msb; + u_long mantissa_low = 0; + u_long mantissa_high = 0; +#ifdef LIBDEBUG + u_long characteristic = 0; + long exponent; +#endif +/*int length;*/ + unsigned long mask; + + outlfp = *lfpp; + + switch (size) + { + case IEEE_DOUBLE: + /*length = 8;*/ + mbits = 52; +#ifdef LIBDEBUG + bias = 1023; +#endif + /*maxexp = 2047;*/ + break; + + case IEEE_SINGLE: + /*length = 4;*/ + mbits = 23; +#ifdef LIBDEBUG + bias = 127; +#endif + /*maxexp = 255;*/ + break; + + default: + return IEEE_BADCALL; + } + + /* + * find sign + */ + if (L_ISNEG(&outlfp)) + { + L_NEG(&outlfp); +#ifdef LIBDEBUG + sign = 1; +#endif + } + else + { +#ifdef LIBDEBUG + sign = 0; +#endif + } + + if (L_ISZERO(&outlfp)) + { +#ifdef LIBDEBUG + exponent = mantissa_high = mantissa_low = 0; /* true zero */ +#endif + } + else + { + /* + * find number of significant integer bits + */ + mask = 0x80000000; + if (outlfp.l_ui) + { + msb = 63; + while (mask && ((outlfp.l_ui & mask) == 0)) + { + mask >>= 1; + msb--; + } + } + else + { + msb = 31; + while (mask && ((outlfp.l_uf & mask) == 0)) + { + mask >>= 1; + msb--; + } + } + + switch (size) + { + case IEEE_SINGLE: + mantissa_high = 0; + if (msb >= 32) + { + mantissa_low = (outlfp.l_ui & ((1 << (msb - 32)) - 1)) << (mbits - (msb - 32)); + mantissa_low |= outlfp.l_uf >> (mbits - (msb - 32)); + } + else + { + mantissa_low = (outlfp.l_uf << (mbits - msb)) & ((1 << mbits) - 1); + } + break; + + case IEEE_DOUBLE: + if (msb >= 32) + { + mantissa_high = (outlfp.l_ui << (mbits - msb)) & ((1 << (mbits - 32)) - 1); + mantissa_high |= outlfp.l_uf >> (32 - (mbits - msb)); + mantissa_low = (outlfp.l_ui & ((1 << (msb - mbits)) - 1)) << (32 - (msb - mbits)); + mantissa_low |= outlfp.l_uf >> (msb - mbits); + } + else + { + mantissa_high = outlfp.l_uf << (mbits - 32 - msb); + mantissa_low = outlfp.l_uf << (mbits - 32); + } + } + +#ifdef LIBDEBUG + exponent = msb - 32; + characteristic = exponent + bias; + + if (debug > 4) + printf("FP: %s\n", fmt_flt(sign, mantissa_high, mantissa_low, characteristic)); +#endif + } + return IEEE_OK; +} + + +#if defined(DEBUG) && defined(LIBDEBUG) +int main( + int argc, + char **argv + ) +{ + static offsets_t native_off = { 0, 1, 2, 3, 4, 5, 6, 7 }; + double f = 1.0; + double *f_p = &f; + l_fp fp; + + if (argc == 2) + { + if (sscanf(argv[1], "%lf", &f) != 1) + { + printf("cannot convert %s to a float\n", argv[1]); + return 1; + } + } + + printf("double: %s %s\n", fmt_blong(*(unsigned long *)&f, 32), fmt_blong(*(unsigned long *)((char *)(&f)+4), 32)); + printf("fetch from %f = %d\n", f, fetch_ieee754((void *)&f_p, IEEE_DOUBLE, &fp, native_off)); + printf("fp [%s %s] = %s\n", fmt_blong(fp.l_ui, 32), fmt_blong(fp.l_uf, 32), mfptoa(fp.l_ui, fp.l_uf, 15)); + f_p = &f; + put_ieee754((void *)&f_p, IEEE_DOUBLE, &fp, native_off); + + return 0; +} + +#endif +/* + * History: + * + * ieee754io.c,v + * Revision 4.12 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.11 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.8 1999/02/21 12:17:36 kardel + * 4.91f reconcilation + * + * Revision 4.7 1999/02/21 11:26:03 kardel + * renamed index to fieldindex to avoid index() name clash + * + * Revision 4.6 1998/11/15 20:27:52 kardel + * Release 4.0.73e13 reconcilation + * + * Revision 4.5 1998/08/16 19:01:51 kardel + * debug information only compile for LIBDEBUG case + * + * Revision 4.4 1998/08/09 09:39:28 kardel + * Release 4.0.73e2 reconcilation + * + * Revision 4.3 1998/06/13 11:56:19 kardel + * disabled putbute() for the time being + * + * Revision 4.2 1998/06/12 15:16:58 kardel + * ansi2knr compatibility + * + * Revision 4.1 1998/05/24 07:59:56 kardel + * conditional debug support + * + * Revision 4.0 1998/04/10 19:46:29 kardel + * Start 4.0 release version numbering + * + * Revision 1.1 1998/04/10 19:27:46 kardel + * initial NTP VERSION 4 integration of PARSE with GPS166 binary support + * + * Revision 1.1 1997/10/06 21:05:45 kardel + * new parse structure + * + */ diff --git a/libparse/info_trimble.c b/libparse/info_trimble.c new file mode 100644 index 0000000..6456e0f --- /dev/null +++ b/libparse/info_trimble.c @@ -0,0 +1,94 @@ +/* + * Automatically generated - do not modify + */ + +#include +#include "ntp_types.h" +#include "ntpd.h" +#include "trimble.h" + +cmd_info_t trimble_scmds[] = { + { CMD_CCLROSC, "CMD_CCLROSC", "clear oscillator offset (0x1D)", "", 0 }, + { CMD_CCLRRST, "CMD_CCLRRST", "clear battery backup and RESET (0x1E)", "", 0 }, + { CMD_CVERSION, "CMD_CVERSION", "return software version (0x1F)", "", 0 }, + { CMD_CALMANAC, "CMD_CALMANAC", "almanac (0x20)", "", 0 }, + { CMD_CCURTIME, "CMD_CCURTIME", "current time (0x21)", "", 0 }, + { CMD_CMODESEL, "CMD_CMODESEL", "mode select (2-d, 3-D, auto) (0x22)", "", 0 }, + { CMD_CINITPOS, "CMD_CINITPOS", "initial position (0x23)", "", 0 }, + { CMD_CRECVPOS, "CMD_CRECVPOS", "receiver position fix mode (0x24)", "", 0 }, + { CMD_CRESET, "CMD_CRESET", "soft reset & selftest (0x25)", "", 0 }, + { CMD_CRECVHEALTH, "CMD_CRECVHEALTH", "receiver health (0x26)", "", 0 }, + { CMD_CSIGNALLV, "CMD_CSIGNALLV", "signal levels (0x27)", "", 0 }, + { CMD_CMESSAGE, "CMD_CMESSAGE", "GPS system message (0x28)", "", 0 }, + { CMD_CALMAHEALTH, "CMD_CALMAHEALTH", "almanac healt page (0x29)", "", 0 }, + { CMD_C2DALTITUDE, "CMD_C2DALTITUDE", "altitude for 2-D mode (0x2A)", "", 0 }, + { CMD_CINITPOSLLA, "CMD_CINITPOSLLA", "initial position LLA (0x2B)", "", 0 }, + { CMD_COPERPARAM, "CMD_COPERPARAM", "operating parameters (0x2C)", "", 0 }, + { CMD_COSCOFFSET, "CMD_COSCOFFSET", "oscillator offset (0x2D)", "", 0 }, + { CMD_CSETGPSTIME, "CMD_CSETGPSTIME", "set GPS time (0x2E)", "", 0 }, + { CMD_CUTCPARAM, "CMD_CUTCPARAM", "UTC parameters (0x2F)", "", 0 }, + { CMD_CACCPOSXYZ, "CMD_CACCPOSXYZ", "accurate initial position (XYZ/ECEF) (0x31)", "", 0 }, + { CMD_CACCPOS, "CMD_CACCPOS", "accurate initial position (0x32)", "", 0 }, + { CMD_CANALOGDIG, "CMD_CANALOGDIG", "analog to digital (0x33)", "", 0 }, + { CMD_CSAT1SAT, "CMD_CSAT1SAT", "satellite for 1-Sat mode (0x34)", "", 0 }, + { CMD_CIOOPTIONS, "CMD_CIOOPTIONS", "I/O options (0x35)", "", 0 }, + { CMD_CVELOCAID, "CMD_CVELOCAID", "velocity aiding of acquisition (0x36)", "", 0 }, + { CMD_CSTATLSTPOS, "CMD_CSTATLSTPOS", "status and values of last pos. and vel. (0x37)", "", 0 }, + { CMD_CLOADSSATDT, "CMD_CLOADSSATDT", "load satellite system data (0x38)", "", 0 }, + { CMD_CSATDISABLE, "CMD_CSATDISABLE", "satellite disable (0x39)", "", 0 }, + { CMD_CLASTRAW, "CMD_CLASTRAW", "last raw measurement (0x3A)", "", 0 }, + { CMD_CSTATSATEPH, "CMD_CSTATSATEPH", "satellite ephemeris status (0x3B)", "", 0 }, + { CMD_CSTATTRACK, "CMD_CSTATTRACK", "tracking status (0x3C)", "", 0 }, + { CMD_CCHANADGPS, "CMD_CCHANADGPS", "configure channel A for differential GPS (0x3D)", "", 0 }, + { CMD_CADDITFIX, "CMD_CADDITFIX", "additional fix data (0x3E)", "", 0 }, + { CMD_CDGPSFIXMD, "CMD_CDGPSFIXMD", "set/request differential GPS position fix mode (0x62)", "", 0 }, + { CMD_CDGPSCORR, "CMD_CDGPSCORR", "differential correction status (0x65)", "", 0 }, + { CMD_CPOSFILT, "CMD_CPOSFILT", "position filter parameters (0x71)", "", 0 }, + { CMD_CHEIGHTFILT, "CMD_CHEIGHTFILT", "height filter control (0x73)", "", 0 }, + { CMD_CHIGH8CNT, "CMD_CHIGH8CNT", "high-8 (best 4) / high-6 (overdetermined) control (0x75)", "", 0 }, + { CMD_CMAXDGPSCOR, "CMD_CMAXDGPSCOR", "maximum rate of DGPS corrections (0x77)", "", 0 }, + { CMD_CSUPER, "CMD_CSUPER", "super paket (0x8E)", "", 0 }, + { 0xFF, "", "" } +}; + + +cmd_info_t trimble_rcmds[] = { + { CMD_RDATAA, "CMD_RDATAA", "data channel A configuration (0x3D)", "trimble_channelA", RO }, + { CMD_RALMANAC, "CMD_RALMANAC", "almanac data for sat (0x40)", "gps_almanac", RO }, + { CMD_RCURTIME, "CMD_RCURTIME", "GPS time (0x41)", "gps_time", RO }, + { CMD_RSPOSXYZ, "CMD_RSPOSXYZ", "single precision XYZ position (0x42)", "gps_position(XYZ)", RO|DEF }, + { CMD_RVELOXYZ, "CMD_RVELOXYZ", "velocity fix (XYZ ECEF) (0x43)", "gps_velocity(XYZ)", RO|DEF }, + { CMD_RBEST4, "CMD_RBEST4", "best 4 satellite selection (0x44)", "trimble_best4", RO|DEF }, + { CMD_RVERSION, "CMD_RVERSION", "software version (0x45)", "trimble_version", RO|DEF }, + { CMD_RRECVHEALTH, "CMD_RRECVHEALTH", "receiver health (0x46)", "trimble_receiver_health", RO|DEF }, + { CMD_RSIGNALLV, "CMD_RSIGNALLV", "signal levels of all satellites (0x47)", "trimble_signal_levels", RO }, + { CMD_RMESSAGE, "CMD_RMESSAGE", "GPS system message (0x48)", "gps-message", RO|DEF }, + { CMD_RALMAHEALTH, "CMD_RALMAHEALTH", "almanac health page for all satellites (0x49)", "gps_almanac_health", RO }, + { CMD_RSLLAPOS, "CMD_RSLLAPOS", "single LLA position (0x4A)", "gps_position(LLA)", RO|DEF }, + { CMD_RMACHSTAT, "CMD_RMACHSTAT", "machine code / status (0x4B)", "trimble_status", RO|DEF }, + { CMD_ROPERPARAM, "CMD_ROPERPARAM", "operating parameters (0x4C)", "trimble_opparam", RO }, + { CMD_ROSCOFFSET, "CMD_ROSCOFFSET", "oscillator offset (0x4D)", "trimble_oscoffset", RO }, + { CMD_RSETGPSTIME, "CMD_RSETGPSTIME", "response to set GPS time (0x4E)", "trimble_setgpstime", RO }, + { CMD_RUTCPARAM, "CMD_RUTCPARAM", "UTC parameters (0x4F)", "gps_utc_correction", RO|DEF }, + { CMD_RANALOGDIG, "CMD_RANALOGDIG", "analog to digital (0x53)", "trimble_analogdigital", RO }, + { CMD_RSAT1BIAS, "CMD_RSAT1BIAS", "one-satellite bias & bias rate (0x54)", "trimble_sat1bias", RO }, + { CMD_RIOOPTIONS, "CMD_RIOOPTIONS", "I/O options (0x55)", "trimble_iooptions", RO }, + { CMD_RSTATLSTFIX, "CMD_RSTATLSTFIX", "status and values of last pos. and vel. (0x57)", "trimble_status_lastpos", RO }, + { CMD_RLOADSSATDT, "CMD_RLOADSSATDT", "response to load satellite system data (0x58)", "trimble_loaddata", RO }, + { CMD_RSATDISABLE, "CMD_RSATDISABLE", "satellite disable (0x59)", "trimble_satdisble", RO }, + { CMD_RLASTRAW, "CMD_RLASTRAW", "last raw measurement (0x5A)", "trimble_lastraw", RO }, + { CMD_RSTATSATEPH, "CMD_RSTATSATEPH", "satellite ephemeris status (0x5B)", "trimble_ephstatus", RO }, + { CMD_RSTATTRACK, "CMD_RSTATTRACK", "tracking status (0x5C)", "trimble_tracking_status", RO|DEF }, + { CMD_RADDITFIX, "CMD_RADDITFIX", "additional fix data (0x5E)", "trimble_addfix", RO }, + { CMD_RALLINVIEW, "CMD_RALLINVIEW", "all in view satellite selection (0x6D)", "trimble_satview", RO|DEF }, + { CMD_RPOSFILT, "CMD_RPOSFILT", "position filter parameters (0x72)", "trimble_posfilt", RO }, + { CMD_RHEIGHTFILT, "CMD_RHEIGHTFILT", "height filter control (0x74)", "trimble_heightfilt", RO }, + { CMD_RHIGH8CNT, "CMD_RHIGH8CNT", "high-8 (best 4) / high-6 (overdetermined) control (0x76)", "trimble_high8control", RO }, + { CMD_RMAXAGE, "CMD_RMAXAGE", "DC MaxAge (0x78)", "trimble_dgpsmaxage", RO }, + { CMD_RDGPSFIX, "CMD_RDGPSFIX", "differential position fix mode (0x82)", "trimble_dgpsfixmode", RO }, + { CMD_RDOUBLEXYZ, "CMD_RDOUBLEXYZ", "double precision XYZ (0x83)", "gps_position_ext(XYZ)", RO|DEF }, + { CMD_RDOUBLELLA, "CMD_RDOUBLELLA", "double precision LLA (0x84)", "gps_position_ext(LLA)", RO|DEF }, + { CMD_RDGPSSTAT, "CMD_RDGPSSTAT", "differential correction status (0x85)", "trimble_dgpsstatus", RO }, + { CMD_RSUPER, "CMD_RSUPER", "super paket (0x8F)", "", 0 }, + { 0xFF, "", "" } +}; diff --git a/libparse/mfp_mul.c b/libparse/mfp_mul.c new file mode 100644 index 0000000..43c1e39 --- /dev/null +++ b/libparse/mfp_mul.c @@ -0,0 +1,207 @@ +/* + * /src/NTP/ntp4-dev/libparse/mfp_mul.c,v 4.9 2005/07/17 20:34:40 kardel RELEASE_20050717_A + * + * mfp_mul.c,v 4.9 2005/07/17 20:34:40 kardel RELEASE_20050717_A + * + * $Created: Sat Aug 16 20:35:08 1997 $ + * + * Copyright (c) 1997-2005 by Frank Kardel ntp.org> + * + * 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. + * + */ +#include +#include +#include "ntp_stdlib.h" +#include "ntp_types.h" +#include "ntp_fp.h" + +#define LOW_MASK (u_int32)((1<<(FRACTION_PREC/2))-1) +#define HIGH_MASK (u_int32)(LOW_MASK << (FRACTION_PREC/2)) + +/* + * for those who worry about overflows (possibly triggered by static analysis tools): + * + * Largest value of a 2^n bit number is 2^n-1. + * Thus the result is: (2^n-1)*(2^n-1) = 2^2n - 2^n - 2^n + 1 < 2^2n + * Here overflow can not happen for 2 reasons: + * 1) the code actually multiplies the absolute values of two signed + * 64bit quantities.thus effectively multiplying 2 63bit quantities. + * 2) Carry propagation is from low to high, building principle is + * addition, so no storage for the 2^2n term from above is needed. + */ + +void +mfp_mul( + int32 *o_i, + u_int32 *o_f, + int32 a_i, + u_int32 a_f, + int32 b_i, + u_int32 b_f + ) +{ + int32 i, j; + u_int32 f; + u_long a[4]; /* operand a */ + u_long b[4]; /* operand b */ + u_long c[5]; /* result c - 5 items for performance - see below */ + u_long carry; + + int neg = 0; + + if (a_i < 0) /* examine sign situation */ + { + neg = 1; + M_NEG(a_i, a_f); + } + + if (b_i < 0) /* examine sign situation */ + { + neg = !neg; + M_NEG(b_i, b_f); + } + + a[0] = a_f & LOW_MASK; /* prepare a operand */ + a[1] = (a_f & HIGH_MASK) >> (FRACTION_PREC/2); + a[2] = a_i & LOW_MASK; + a[3] = (a_i & HIGH_MASK) >> (FRACTION_PREC/2); + + b[0] = b_f & LOW_MASK; /* prepare b operand */ + b[1] = (b_f & HIGH_MASK) >> (FRACTION_PREC/2); + b[2] = b_i & LOW_MASK; + b[3] = (b_i & HIGH_MASK) >> (FRACTION_PREC/2); + + c[0] = c[1] = c[2] = c[3] = c[4] = 0; + + for (i = 0; i < 4; i++) /* we do assume 32 * 32 = 64 bit multiplication */ + for (j = 0; j < 4; j++) + { + u_long result_low, result_high; + int low_index = (i+j)/2; /* formal [0..3] - index for low long word */ + int mid_index = 1+low_index; /* formal [1..4]! - index for high long word + will generate unecessary add of 0 to c[4] + but save 15 'if (result_high) expressions' */ + int high_index = 1+mid_index; /* formal [2..5]! - index for high word overflow + - only assigned on overflow (limits range to 2..3) */ + + result_low = (u_long)a[i] * (u_long)b[j]; /* partial product */ + + if ((i+j) & 1) /* splits across two result registers */ + { + result_high = result_low >> (FRACTION_PREC/2); + result_low <<= FRACTION_PREC/2; + carry = (unsigned)1<<(FRACTION_PREC/2); + } + else + { /* stays in a result register - except for overflows */ + result_high = 0; + carry = 1; + } + + if (((c[low_index] >> 1) + (result_low >> 1) + ((c[low_index] & result_low & carry) != 0)) & + (u_int32)((unsigned)1<<(FRACTION_PREC - 1))) { + result_high++; /* propagate overflows */ + } + + c[low_index] += result_low; /* add up partial products */ + + if (((c[mid_index] >> 1) + (result_high >> 1) + ((c[mid_index] & result_high & 1) != 0)) & + (u_int32)((unsigned)1<<(FRACTION_PREC - 1))) { + c[high_index]++; /* propagate overflows of high word sum */ + } + + c[mid_index] += result_high; /* will add a 0 to c[4] once but saves 15 if conditions */ + } + +#ifdef DEBUG + if (debug > 6) + printf("mfp_mul: 0x%04lx%04lx%04lx%04lx * 0x%04lx%04lx%04lx%04lx = 0x%08lx%08lx%08lx%08lx\n", + a[3], a[2], a[1], a[0], b[3], b[2], b[1], b[0], c[3], c[2], c[1], c[0]); +#endif + + if (c[3]) /* overflow */ + { + i = ((unsigned)1 << (FRACTION_PREC-1)) - 1; + f = ~(unsigned)0; + } + else + { /* take produkt - discarding extra precision */ + i = c[2]; + f = c[1]; + } + + if (neg) /* recover sign */ + { + M_NEG(i, f); + } + + *o_i = i; + *o_f = f; + +#ifdef DEBUG + if (debug > 6) + printf("mfp_mul: %s * %s => %s\n", + mfptoa((u_long)a_i, a_f, 6), + mfptoa((u_long)b_i, b_f, 6), + mfptoa((u_long)i, f, 6)); +#endif +} + +/* + * History: + * + * mfp_mul.c,v + * Revision 4.9 2005/07/17 20:34:40 kardel + * correct carry propagation implementation + * + * Revision 4.8 2005/07/12 16:17:26 kardel + * add explanation why we do not write into c[4] + * + * Revision 4.7 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.6 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.3 1999/02/21 12:17:37 kardel + * 4.91f reconcilation + * + * Revision 4.2 1998/12/20 23:45:28 kardel + * fix types and warnings + * + * Revision 4.1 1998/05/24 07:59:57 kardel + * conditional debug support + * + * Revision 4.0 1998/04/10 19:46:38 kardel + * Start 4.0 release version numbering + * + * Revision 1.1 1998/04/10 19:27:47 kardel + * initial NTP VERSION 4 integration of PARSE with GPS166 binary support + * + * Revision 1.1 1997/10/06 21:05:46 kardel + * new parse structure + * + */ diff --git a/libparse/mkinfo_rcmd.sed b/libparse/mkinfo_rcmd.sed new file mode 100644 index 0000000..5238d5c --- /dev/null +++ b/libparse/mkinfo_rcmd.sed @@ -0,0 +1,8 @@ +1i\ +\ +\ +cmd_info_t trimble_rcmds[] = { +s!^#define[ \ ][ \ ]*\(CMD_R[^ \ ]*\)[ \ ][ \ ]*\([^ \ ]*\)[ \ ][ \ ]*/\*[ \ ][ \ ]*\(.*\)[ \ ]*:\([^:]*\):\([^:]*\)[ \ ][ \ ]*\*/!\ { \1, "\1", "\3 (\2)", "\4", \5 },!p +$a\ +\ { 0xFF, "", "" }\ +}; diff --git a/libparse/mkinfo_scmd.sed b/libparse/mkinfo_scmd.sed new file mode 100644 index 0000000..9c17f39 --- /dev/null +++ b/libparse/mkinfo_scmd.sed @@ -0,0 +1,15 @@ +1i\ +/*\ +\ * Automatically generated - do not modify\ +\ */\ +\ +#include \ +#include "ntp_types.h"\ +#include "ntpd.h"\ +#include "trimble.h"\ +\ +cmd_info_t trimble_scmds[] = { +s!^#define[ ][ ]*\(CMD_C[^ ]*\)[ ][ ]*\([^ ]*\)[ ][ ]*/\*[ ][ ]*\(.*\)[ ][ ]*\*/! { \1, "\1", "\3 (\2)", "", 0 },!p +$a\ +\ { 0xFF, "", "" }\ +}; diff --git a/libparse/parse.c b/libparse/parse.c new file mode 100644 index 0000000..85e5299 --- /dev/null +++ b/libparse/parse.c @@ -0,0 +1,945 @@ +/* + * /src/NTP/ntp4-dev/libparse/parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A + * + * parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A + * + * Parser module for reference clock + * + * PARSEKERNEL define switches between two personalities of the module + * if PARSEKERNEL is defined this module can be used + * as kernel module. In this case the time stamps will be + * a struct timeval. + * when PARSEKERNEL is not defined NTP time stamps will be used. + * + * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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 +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) + +#if !(defined(lint) || defined(__GNUC__)) +static char rcsid[] = "parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A"; +#endif + +#include "ntp_fp.h" +#include "timevalops.h" +#include "ntp_calendar.h" +#include "ntp_stdlib.h" +#include "ntp_machine.h" +#include "ntp.h" /* (get Y2KFixes definitions) Y2KFixes */ + +#include "parse.h" + +#ifndef PARSESTREAM +# include +#else +# include "sys/parsestreams.h" +#endif + +extern clockformat_t *clockformats[]; +extern unsigned short nformats; + +static u_long timepacket (parse_t *); + +/* + * strings support usually not in kernel - duplicated, but what the heck + */ +static int +Strlen( + register const char *s + ) +{ + register int c; + + c = 0; + if (s) + { + while (*s++) + { + c++; + } + } + return c; +} + +static int +Strcmp( + register const char *s, + register const char *t + ) +{ + register int c = 0; + + if (!s || !t || (s == t)) + { + return 0; + } + + while (!(c = *s++ - *t++) && *s && *t) + /* empty loop */; + + return c; +} + +int +parse_timedout( + parse_t *parseio, + timestamp_t *tstamp, + struct timeval *del + ) +{ + struct timeval delta; + +#ifdef PARSEKERNEL + delta.tv_sec = tstamp->tv.tv_sec - parseio->parse_lastchar.tv.tv_sec; + delta.tv_usec = tstamp->tv.tv_usec - parseio->parse_lastchar.tv.tv_usec; + if (delta.tv_usec < 0) + { + delta.tv_sec -= 1; + delta.tv_usec += 1000000; + } +#else + l_fp delt; + + delt = tstamp->fp; + L_SUB(&delt, &parseio->parse_lastchar.fp); + TSTOTV(&delt, &delta); +#endif + + if (timercmp(&delta, del, >)) + { + parseprintf(DD_PARSE, ("parse: timedout: TRUE\n")); + return 1; + } + else + { + parseprintf(DD_PARSE, ("parse: timedout: FALSE\n")); + return 0; + } +} + +/*ARGSUSED*/ +int +parse_ioinit( + register parse_t *parseio + ) +{ + parseprintf(DD_PARSE, ("parse_iostart\n")); + + parseio->parse_plen = 0; + parseio->parse_pdata = (void *)0; + + parseio->parse_data = 0; + parseio->parse_ldata = 0; + parseio->parse_dsize = 0; + + parseio->parse_badformat = 0; + parseio->parse_ioflags = PARSE_IO_CS7; /* usual unix default */ + parseio->parse_index = 0; + parseio->parse_ldsize = 0; + + return 1; +} + +/*ARGSUSED*/ +void +parse_ioend( + register parse_t *parseio + ) +{ + parseprintf(DD_PARSE, ("parse_ioend\n")); + + if (parseio->parse_pdata) + FREE(parseio->parse_pdata, parseio->parse_plen); + + if (parseio->parse_data) + FREE(parseio->parse_data, (unsigned)(parseio->parse_dsize * 2 + 2)); +} + +unsigned int +parse_restart( + parse_t *parseio, + unsigned int ch + ) +{ + unsigned int updated = PARSE_INP_SKIP; + + /* + * re-start packet - timeout - overflow - start symbol + */ + + if (parseio->parse_index) + { + /* + * filled buffer - thus not end character found + * do processing now + */ + parseio->parse_data[parseio->parse_index] = '\0'; + memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1)); + parseio->parse_ldsize = parseio->parse_index; + updated = PARSE_INP_TIME; + } + + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + parseprintf(DD_PARSE, ("parse: parse_restart: buffer start (updated = %x)\n", updated)); + return updated; +} + +unsigned int +parse_addchar( + parse_t *parseio, + unsigned int ch + ) +{ + /* + * add to buffer + */ + if (parseio->parse_index < parseio->parse_dsize) + { + /* + * collect into buffer + */ + parseprintf(DD_PARSE, ("parse: parse_addchar: buffer[%d] = 0x%x\n", parseio->parse_index, ch)); + parseio->parse_data[parseio->parse_index++] = (char)ch; + return PARSE_INP_SKIP; + } + else + /* + * buffer overflow - attempt to make the best of it + */ + return parse_restart(parseio, ch); +} + +unsigned int +parse_end( + parse_t *parseio + ) +{ + /* + * message complete processing + */ + parseio->parse_data[parseio->parse_index] = '\0'; + memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1)); + parseio->parse_ldsize = parseio->parse_index; + parseio->parse_index = 0; + parseprintf(DD_PARSE, ("parse: parse_end: buffer end\n")); + return PARSE_INP_TIME; +} + +/*ARGSUSED*/ +int +parse_ioread( + register parse_t *parseio, + register unsigned int ch, + register timestamp_t *tstamp + ) +{ + register unsigned updated = CVT_NONE; + /* + * within STREAMS CSx (x < 8) chars still have the upper bits set + * so we normalize the characters by masking unecessary bits off. + */ + switch (parseio->parse_ioflags & PARSE_IO_CSIZE) + { + case PARSE_IO_CS5: + ch &= 0x1F; + break; + + case PARSE_IO_CS6: + ch &= 0x3F; + break; + + case PARSE_IO_CS7: + ch &= 0x7F; + break; + + case PARSE_IO_CS8: + ch &= 0xFF; + break; + } + + parseprintf(DD_PARSE, ("parse_ioread(0x%lx, char=0x%x, ..., ...)\n", (unsigned long)parseio, ch & 0xFF)); + + if (!clockformats[parseio->parse_lformat]->convert) + { + parseprintf(DD_PARSE, ("parse_ioread: input dropped.\n")); + return CVT_NONE; + } + + if (clockformats[parseio->parse_lformat]->input) + { + unsigned long input_status; + + input_status = clockformats[parseio->parse_lformat]->input(parseio, ch, tstamp); + + if (input_status & PARSE_INP_SYNTH) + { + updated = CVT_OK; + } + + if (input_status & PARSE_INP_TIME) /* time sample is available */ + { + updated = timepacket(parseio); + } + + if (input_status & PARSE_INP_DATA) /* got additional data */ + { + updated |= CVT_ADDITIONAL; + } + } + + + /* + * remember last character time + */ + parseio->parse_lastchar = *tstamp; + +#ifdef DEBUG + if ((updated & CVT_MASK) != CVT_NONE) + { + parseprintf(DD_PARSE, ("parse_ioread: time sample accumulated (status=0x%x)\n", updated)); + } +#endif + + parseio->parse_dtime.parse_status = updated; + + return (((updated & CVT_MASK) != CVT_NONE) || + ((updated & CVT_ADDITIONAL) != 0)); +} + +/* + * parse_iopps + * + * take status line indication and derive synchronisation information + * from it. + * It can also be used to decode a serial serial data format (such as the + * ONE, ZERO, MINUTE sync data stream from DCF77) + */ +/*ARGSUSED*/ +int +parse_iopps( + register parse_t *parseio, + register int status, + register timestamp_t *ptime + ) +{ + register unsigned updated = CVT_NONE; + + /* + * PPS pulse information will only be delivered to ONE clock format + * this is either the last successful conversion module with a ppssync + * routine, or a fixed format with a ppssync routine + */ + parseprintf(DD_PARSE, ("parse_iopps: STATUS %s\n", (status == SYNC_ONE) ? "ONE" : "ZERO")); + + if (clockformats[parseio->parse_lformat]->syncpps) + { + updated = clockformats[parseio->parse_lformat]->syncpps(parseio, status == SYNC_ONE, ptime); + parseprintf(DD_PARSE, ("parse_iopps: updated = 0x%x\n", updated)); + } + + return (updated & CVT_MASK) != CVT_NONE; +} + +/* + * parse_iodone + * + * clean up internal status for new round + */ +/*ARGSUSED*/ +void +parse_iodone( + register parse_t *parseio + ) +{ + /* + * we need to clean up certain flags for the next round + */ + parseprintf(DD_PARSE, ("parse_iodone: DONE\n")); + parseio->parse_dtime.parse_state = 0; /* no problems with ISRs */ +} + +/*---------- conversion implementation --------------------*/ + +/* + * convert a struct clock to UTC since Jan, 1st 1970 0:00 (the UNIX EPOCH) + */ +#define days_per_year(x) ((x) % 4 ? 365 : ((x % 400) ? ((x % 100) ? 366 : 365) : 366)) + +time_t +parse_to_unixtime( + register clocktime_t *clock_time, + register u_long *cvtrtc + ) +{ +#define SETRTC(_X_) { if (cvtrtc) *cvtrtc = (_X_); } + static int days_of_month[] = + { + 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + register int i; + time_t t; + + if (clock_time->utctime) + return clock_time->utctime; /* if the conversion routine gets it right away - why not */ + + if ( clock_time->year < YEAR_PIVOT ) /* Y2KFixes [ */ + clock_time->year += 100; /* convert 20xx%100 to 20xx-1900 */ + if ( clock_time->year < YEAR_BREAK ) /* expand to full four-digits */ + clock_time->year += 1900; + + if (clock_time->year < 1970 ) /* Y2KFixes ] */ + { + SETRTC(CVT_FAIL|CVT_BADDATE); + return -1; + } + + /* + * sorry, slow section here - but it's not time critical anyway + */ + t = julian0(clock_time->year) - julian0(1970); /* Y2kFixes */ + /* month */ + if (clock_time->month <= 0 || clock_time->month > 12) + { + SETRTC(CVT_FAIL|CVT_BADDATE); + return -1; /* bad month */ + } + +#if 0 /* Y2KFixes */ + /* adjust leap year */ + if (clock_time->month < 3 && days_per_year(clock_time->year) == 366) + t--; +#else /* Y2KFixes [ */ + if ( clock_time->month >= 3 && isleap_4(clock_time->year) ) + t++; /* add one more if within leap year */ +#endif /* Y2KFixes ] */ + + for (i = 1; i < clock_time->month; i++) + { + t += days_of_month[i]; + } + /* day */ + if (clock_time->day < 1 || ((clock_time->month == 2 && days_per_year(clock_time->year) == 366) ? + clock_time->day > 29 : clock_time->day > days_of_month[clock_time->month])) + { + SETRTC(CVT_FAIL|CVT_BADDATE); + return -1; /* bad day */ + } + + t += clock_time->day - 1; + /* hour */ + if (clock_time->hour < 0 || clock_time->hour >= 24) + { + SETRTC(CVT_FAIL|CVT_BADTIME); + return -1; /* bad hour */ + } + + t = TIMES24(t) + clock_time->hour; + + /* min */ + if (clock_time->minute < 0 || clock_time->minute > 59) + { + SETRTC(CVT_FAIL|CVT_BADTIME); + return -1; /* bad min */ + } + + t = TIMES60(t) + clock_time->minute; + /* sec */ + + if (clock_time->second < 0 || clock_time->second > 60) /* allow for LEAPs */ + { + SETRTC(CVT_FAIL|CVT_BADTIME); + return -1; /* bad sec */ + } + + t = TIMES60(t) + clock_time->second; + + t += clock_time->utcoffset; /* warp to UTC */ + + /* done */ + + clock_time->utctime = t; /* documentray only */ + + return t; +} + +/*--------------- format conversion -----------------------------------*/ + +int +Stoi( + const unsigned char *s, + long *zp, + int cnt + ) +{ + char unsigned const *b = s; + int f,z,v; + char unsigned c; + + f=z=v=0; + + while(*s == ' ') + s++; + + if (*s == '-') + { + s++; + v = 1; + } + else + if (*s == '+') + s++; + + for(;;) + { + c = *s++; + if (c == '\0' || c < '0' || c > '9' || (cnt && ((s-b) > cnt))) + { + if (f == 0) + { + return(-1); + } + if (v) + z = -z; + *zp = z; + return(0); + } + z = (z << 3) + (z << 1) + ( c - '0' ); + f=1; + } +} + +int +Strok( + const unsigned char *s, + const unsigned char *m + ) +{ + if (!s || !m) + return 0; + + while(*s && *m) + { + if ((*m == ' ') ? 1 : (*s == *m)) + { + s++; + m++; + } + else + { + return 0; + } + } + return !*m; +} + +u_long +updatetimeinfo( + register parse_t *parseio, + register u_long flags + ) +{ +#ifdef PARSEKERNEL + { + int s = splhigh(); +#endif + + parseio->parse_lstate = parseio->parse_dtime.parse_state | flags | PARSEB_TIMECODE; + + parseio->parse_dtime.parse_state = parseio->parse_lstate; + +#ifdef PARSEKERNEL + (void)splx((unsigned int)s); + } +#endif + + +#ifdef PARSEKERNEL + parseprintf(DD_PARSE, ("updatetimeinfo status=0x%x, time=%x\n", parseio->parse_dtime.parse_state, + parseio->parse_dtime.parse_time.tv.tv_sec)); +#else + parseprintf(DD_PARSE, ("updatetimeinfo status=0x%lx, time=%x\n", (long)parseio->parse_dtime.parse_state, + parseio->parse_dtime.parse_time.fp.l_ui)); +#endif + + return CVT_OK; /* everything fine and dandy... */ +} + + +/* + * syn_simple + * + * handle a sync time stamp + */ +/*ARGSUSED*/ +void +syn_simple( + register parse_t *parseio, + register timestamp_t *ts, + register struct format *format, + register u_long why + ) +{ + parseio->parse_dtime.parse_stime = *ts; +} + +/* + * pps_simple + * + * handle a pps time stamp + */ +/*ARGSUSED*/ +u_long +pps_simple( + register parse_t *parseio, + register int status, + register timestamp_t *ptime + ) +{ + parseio->parse_dtime.parse_ptime = *ptime; + parseio->parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS; + + return CVT_NONE; +} + +/* + * pps_one + * + * handle a pps time stamp in ONE edge + */ +/*ARGSUSED*/ +u_long +pps_one( + register parse_t *parseio, + register int status, + register timestamp_t *ptime + ) +{ + if (status) + return pps_simple(parseio, status, ptime); + + return CVT_NONE; +} + +/* + * pps_zero + * + * handle a pps time stamp in ZERO edge + */ +/*ARGSUSED*/ +u_long +pps_zero( + register parse_t *parseio, + register int status, + register timestamp_t *ptime + ) +{ + if (!status) + return pps_simple(parseio, status, ptime); + + return CVT_NONE; +} + +/* + * timepacket + * + * process a data packet + */ +static u_long +timepacket( + register parse_t *parseio + ) +{ + register unsigned short format; + register time_t t; + u_long cvtrtc; /* current conversion result */ + clocktime_t clock_time; + + memset((char *)&clock_time, 0, sizeof clock_time); + format = parseio->parse_lformat; + + if (format == (unsigned short)~0) + return CVT_NONE; + + switch ((cvtrtc = clockformats[format]->convert ? + clockformats[format]->convert((unsigned char *)parseio->parse_ldata, parseio->parse_ldsize, (struct format *)(clockformats[format]->data), &clock_time, parseio->parse_pdata) : + CVT_NONE) & CVT_MASK) + { + case CVT_FAIL: + parseio->parse_badformat++; + break; + + case CVT_NONE: + /* + * too bad - pretend bad format + */ + parseio->parse_badformat++; + break; + + case CVT_OK: + break; + + case CVT_SKIP: + return CVT_NONE; + + default: + /* shouldn't happen */ +#ifndef PARSEKERNEL + msyslog(LOG_WARNING, "parse: INTERNAL error: bad return code of convert routine \"%s\"", clockformats[format]->name); +#endif + return CVT_FAIL|cvtrtc; + } + + if ((t = parse_to_unixtime(&clock_time, &cvtrtc)) == -1) + { + return CVT_FAIL|cvtrtc; + } + + /* + * time stamp + */ +#ifdef PARSEKERNEL + parseio->parse_dtime.parse_time.tv.tv_sec = t; + parseio->parse_dtime.parse_time.tv.tv_usec = clock_time.usecond; +#else + parseio->parse_dtime.parse_time.fp.l_ui = t + JAN_1970; + TVUTOTSF(clock_time.usecond, parseio->parse_dtime.parse_time.fp.l_uf); +#endif + + parseio->parse_dtime.parse_format = format; + + return updatetimeinfo(parseio, clock_time.flags); +} + +/*ARGSUSED*/ +int +parse_timecode( + parsectl_t *dct, + parse_t *parse + ) +{ + dct->parsegettc.parse_state = parse->parse_lstate; + dct->parsegettc.parse_format = parse->parse_lformat; + /* + * move out current bad packet count + * user program is expected to sum these up + * this is not a problem, as "parse" module are + * exclusive open only + */ + dct->parsegettc.parse_badformat = parse->parse_badformat; + parse->parse_badformat = 0; + + if (parse->parse_ldsize <= PARSE_TCMAX) + { + dct->parsegettc.parse_count = parse->parse_ldsize; + memcpy(dct->parsegettc.parse_buffer, parse->parse_ldata, dct->parsegettc.parse_count); + return 1; + } + else + { + return 0; + } +} + + +/*ARGSUSED*/ +int +parse_setfmt( + parsectl_t *dct, + parse_t *parse + ) +{ + if (dct->parseformat.parse_count <= PARSE_TCMAX) + { + if (dct->parseformat.parse_count) + { + register unsigned short i; + + for (i = 0; i < nformats; i++) + { + if (!Strcmp(dct->parseformat.parse_buffer, clockformats[i]->name)) + { + if (parse->parse_pdata) + FREE(parse->parse_pdata, parse->parse_plen); + parse->parse_pdata = 0; + + parse->parse_plen = clockformats[i]->plen; + + if (parse->parse_plen) + { + parse->parse_pdata = MALLOC(parse->parse_plen); + if (!parse->parse_pdata) + { + parseprintf(DD_PARSE, ("set format failed: malloc for private data area failed\n")); + return 0; + } + memset((char *)parse->parse_pdata, 0, parse->parse_plen); + } + + if (parse->parse_data) + FREE(parse->parse_data, (unsigned)(parse->parse_dsize * 2 + 2)); + parse->parse_ldata = parse->parse_data = 0; + + parse->parse_dsize = clockformats[i]->length; + + if (parse->parse_dsize) + { + parse->parse_data = (char*)MALLOC((unsigned)(parse->parse_dsize * 2 + 2)); + if (!parse->parse_data) + { + if (parse->parse_pdata) + FREE(parse->parse_pdata, parse->parse_plen); + parse->parse_pdata = 0; + + parseprintf(DD_PARSE, ("init failed: malloc for data area failed\n")); + return 0; + } + } + + + /* + * leave room for '\0' + */ + parse->parse_ldata = parse->parse_data + parse->parse_dsize + 1; + + parse->parse_lformat = i; + + return 1; + } + } + } + } + return 0; +} + +/*ARGSUSED*/ +int +parse_getfmt( + parsectl_t *dct, + parse_t *parse + ) +{ + if (dct->parseformat.parse_format < nformats && + Strlen(clockformats[dct->parseformat.parse_format]->name) <= PARSE_TCMAX) + { + dct->parseformat.parse_count = Strlen(clockformats[dct->parseformat.parse_format]->name)+1; + memcpy(dct->parseformat.parse_buffer, clockformats[dct->parseformat.parse_format]->name, dct->parseformat.parse_count); + return 1; + } + else + { + return 0; + } +} + +/*ARGSUSED*/ +int +parse_setcs( + parsectl_t *dct, + parse_t *parse + ) +{ + parse->parse_ioflags &= ~PARSE_IO_CSIZE; + parse->parse_ioflags |= dct->parsesetcs.parse_cs & PARSE_IO_CSIZE; + return 1; +} + +#else /* not (REFCLOCK && CLOCK_PARSE) */ +int parse_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE) */ + +/* + * History: + * + * parse.c,v + * Revision 4.20 2005/08/06 17:39:40 kardel + * cleanup size handling wrt/ to buffer boundaries + * + * Revision 4.19 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.18 2004/11/14 16:11:05 kardel + * update Id tags + * + * Revision 4.17 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.14 1999/11/28 09:13:52 kardel + * RECON_4_0_98F + * + * Revision 4.13 1999/02/28 11:50:20 kardel + * (timepacket): removed unecessary code + * + * Revision 4.12 1999/02/21 12:17:44 kardel + * 4.91f reconcilation + * + * Revision 4.11 1999/02/21 11:09:47 kardel + * unified debug output + * + * Revision 4.10 1998/12/20 23:45:30 kardel + * fix types and warnings + * + * Revision 4.9 1998/08/09 22:26:06 kardel + * Trimble TSIP support + * + * Revision 4.8 1998/06/14 21:09:39 kardel + * Sun acc cleanup + * + * Revision 4.7 1998/06/13 15:19:13 kardel + * fix mem*() to b*() function macro emulation + * + * Revision 4.6 1998/06/13 13:24:13 kardel + * printf fmt + * + * Revision 4.5 1998/06/13 13:01:10 kardel + * printf fmt + * + * Revision 4.4 1998/06/13 12:12:10 kardel + * bcopy/memcpy cleanup + * fix SVSV name clash + * + * Revision 4.3 1998/06/12 15:22:30 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:27 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:55 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:36 kardel + * Start 4.0 release version numbering + * + * from V3 3.46 log info deleted 1998/04/11 kardel + */ diff --git a/libparse/parse_conf.c b/libparse/parse_conf.c new file mode 100644 index 0000000..b7234dd --- /dev/null +++ b/libparse/parse_conf.c @@ -0,0 +1,182 @@ +/* + * /src/NTP/ntp4-dev/libparse/parse_conf.c,v 4.9 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * parse_conf.c,v 4.9 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * Parser configuration module for reference clocks + * + * STREAM define switches between two personalities of the module + * if STREAM is defined this module can be used with dcf77sync.c as + * a STREAMS kernel module. In this case the time stamps will be + * a struct timeval. + * when STREAM is not defined NTP time stamps will be used. + * + * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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 +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" + +#ifdef CLOCK_SCHMID +extern clockformat_t clock_schmid; +#endif + +#ifdef CLOCK_DCF7000 +extern clockformat_t clock_dcf7000; +#endif + +#ifdef CLOCK_MEINBERG +extern clockformat_t clock_meinberg[]; +#endif + +#ifdef CLOCK_RAWDCF +extern clockformat_t clock_rawdcf; +#endif + +#ifdef CLOCK_TRIMTAIP +extern clockformat_t clock_trimtaip; +#endif + +#ifdef CLOCK_TRIMTSIP +extern clockformat_t clock_trimtsip; +#endif + +#ifdef CLOCK_RCC8000 +extern clockformat_t clock_rcc8000; +#endif + +#ifdef CLOCK_HOPF6021 +extern clockformat_t clock_hopf6021; +#endif + +#ifdef CLOCK_COMPUTIME +extern clockformat_t clock_computime; +#endif + +#ifdef CLOCK_WHARTON_400A +extern clockformat_t clock_wharton_400a; +#endif + +#ifdef CLOCK_VARITEXT +extern clockformat_t clock_varitext; +#endif + +#ifdef CLOCK_SEL240X +extern clockformat_t clock_sel240x; +#endif + +/* + * format definitions + */ +clockformat_t *clockformats[] = +{ +#ifdef CLOCK_MEINBERG + &clock_meinberg[0], + &clock_meinberg[1], + &clock_meinberg[2], +#endif +#ifdef CLOCK_DCF7000 + &clock_dcf7000, +#endif +#ifdef CLOCK_SCHMID + &clock_schmid, +#endif +#ifdef CLOCK_RAWDCF + &clock_rawdcf, +#endif +#ifdef CLOCK_TRIMTAIP + &clock_trimtaip, +#endif +#ifdef CLOCK_TRIMTSIP + &clock_trimtsip, +#endif +#ifdef CLOCK_RCC8000 + &clock_rcc8000, +#endif +#ifdef CLOCK_HOPF6021 + &clock_hopf6021, +#endif +#ifdef CLOCK_COMPUTIME + &clock_computime, +#endif +#ifdef CLOCK_WHARTON_400A + &clock_wharton_400a, +#endif +#ifdef CLOCK_VARITEXT + &clock_varitext, +#endif +#ifdef CLOCK_SEL240X + &clock_sel240x, +#endif + 0}; + +unsigned short nformats = sizeof(clockformats) / sizeof(clockformats[0]) - 1; + +#else /* not (REFCLOCK && CLOCK_PARSE) */ +int parse_conf_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE) */ + +/* + * History: + * + * parse_conf.c,v + * Revision 4.9 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.8 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.5 1999/11/28 09:13:53 kardel + * RECON_4_0_98F + * + * Revision 4.4 1999/02/28 15:27:25 kardel + * wharton clock integration + * + * Revision 4.3 1998/08/16 18:52:15 kardel + * (clockformats): Trimble TSIP driver now also + * available for kernel operation + * + * Revision 4.2 1998/06/12 09:13:48 kardel + * conditional compile macros fixed + * + * Revision 4.1 1998/05/24 09:40:49 kardel + * adjustments of log messages + * + * + * from V3 3.24 log info deleted 1998/04/11 kardel + */ diff --git a/libparse/parsesolaris.c b/libparse/parsesolaris.c new file mode 100644 index 0000000..d3756af --- /dev/null +++ b/libparse/parsesolaris.c @@ -0,0 +1,1202 @@ +/* + * /src/NTP/ntp4-dev/libparse/parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * STREAMS module for reference clocks + * + * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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. + * + */ + +#define _KERNEL /* it is a _KERNEL module */ + +#ifndef lint +static char rcsid[] = "parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __GNUC__ /* makes it compile on Solaris 2.6 - acc doesn't like it -- GREAT! */ +#include +#endif + +#include "ntp_fp.h" +#include "parse.h" +#include + +/*--------------- loadable driver section -----------------------------*/ + +static struct streamtab parseinfo; + +static struct fmodsw fmod_templ = +{ + "parse", /* module name */ + &parseinfo, /* module information */ + D_NEW|D_MP|D_MTQPAIR, /* exclusive for q pair */ + /* lock ptr */ +}; + +extern struct mod_ops mod_strmodops; + +static struct modlstrmod modlstrmod = +{ + &mod_strmodops, /* a STREAMS module */ + "PARSE - NTP reference", /* name this baby - keep room for revision number */ + &fmod_templ +}; + +static struct modlinkage modlinkage = +{ + MODREV_1, + { + &modlstrmod, + NULL + } +}; + +/* + * module management routines + */ +/*ARGSUSED*/ +int +_init( + void + ) +{ + static char revision[] = "4.6"; + char *s, *S; + char *t; + +#ifndef lint + t = rcsid; +#endif + + /* + * copy RCS revision into Drv_name + * + * are we forcing RCS here to do things it was not built for ? + */ + s = revision; + if (*s == '$') + { + /* + * skip "$Revision: " + * if present. - not necessary on a -kv co (cvs export) + */ + while (*s && (*s != ' ')) + { + s++; + } + if (*s == ' ') s++; + } + + t = modlstrmod.strmod_linkinfo; + while (*t && (*t != ' ')) + { + t++; + } + if (*t == ' ') t++; + + S = s; + while (*S && (((*S >= '0') && (*S <= '9')) || (*S == '.'))) + { + S++; + } + + if (*s && *t && (S > s)) + { + if (strlen(t) >= (S - s)) + { + strlcpy(t, s, (unsigned)(S - s)); + } + } + return (mod_install(&modlinkage)); +} + +/*ARGSUSED*/ +int +_info( + struct modinfo *modinfop + ) +{ + return (mod_info(&modlinkage, modinfop)); +} + +/*ARGSUSED*/ +int +_fini( + void + ) +{ + if (mod_remove(&modlinkage) != DDI_SUCCESS) + { + return EBUSY; + } + else + return DDI_SUCCESS; +} + +/*--------------- stream module definition ----------------------------*/ + +static int parseopen (queue_t *, dev_t *, int, int, cred_t *); +static int parseclose (queue_t *, int); +static int parsewput (queue_t *, mblk_t *); +static int parserput (queue_t *, mblk_t *); +static int parsersvc (queue_t *); + +static struct module_info driverinfo = +{ + 0, /* module ID number */ + fmod_templ.f_name, /* module name - why repeated here ? compat ?*/ + 0, /* minimum accepted packet size */ + INFPSZ, /* maximum accepted packet size */ + 1, /* high water mark - flow control */ + 0 /* low water mark - flow control */ +}; + +static struct qinit rinit = /* read queue definition */ +{ + parserput, /* put procedure */ + parsersvc, /* service procedure */ + parseopen, /* open procedure */ + parseclose, /* close procedure */ + NULL, /* admin procedure - NOT USED FOR NOW */ + &driverinfo, /* information structure */ + NULL /* statistics */ +}; + +static struct qinit winit = /* write queue definition */ +{ + parsewput, /* put procedure */ + NULL, /* service procedure */ + NULL, /* open procedure */ + NULL, /* close procedure */ + NULL, /* admin procedure - NOT USED FOR NOW */ + &driverinfo, /* information structure */ + NULL /* statistics */ +}; + +static struct streamtab parseinfo = /* stream info element for parse driver */ +{ + &rinit, /* read queue */ + &winit, /* write queue */ + NULL, /* read mux */ + NULL /* write mux */ +}; + +/*--------------- driver data structures ----------------------------*/ + +/* + * we usually have an inverted signal - but you + * can change this to suit your needs + */ +int cd_invert = 1; /* invert status of CD line - PPS support via CD input */ + +#ifdef PARSEDEBUG +int parsedebug = ~0; +#else +int parsedebug = 0; +#endif + +/*--------------- module implementation -----------------------------*/ + +#define TIMEVAL_USADD(_X_, _US_) do {\ + (_X_)->tv_usec += (_US_);\ + if ((_X_)->tv_usec >= 1000000)\ + {\ + (_X_)->tv_sec++;\ + (_X_)->tv_usec -= 1000000;\ + }\ + } while (0) + +static int init_linemon (queue_t *); +static void close_linemon (queue_t *, queue_t *); + +#define M_PARSE 0x0001 +#define M_NOPARSE 0x0002 + +void +ntp_memset( + char *a, + int x, + int c + ) +{ + while (c-- > 0) + *a++ = x; +} + +static void +pprintf( + int lev, + char *form, + ... + ) +{ + va_list ap; + + va_start(ap, form); + + if (lev & parsedebug) + vcmn_err(CE_CONT, form, ap); + + va_end(ap); +} + +static int +setup_stream( + queue_t *q, + int mode + ) +{ + register mblk_t *mp; + + pprintf(DD_OPEN,"parse: SETUP_STREAM - setting up stream for q=%x\n", q); + + mp = allocb(sizeof(struct stroptions), BPRI_MED); + if (mp) + { + struct stroptions *str = (void *)mp->b_wptr; + + str->so_flags = SO_READOPT|SO_HIWAT|SO_LOWAT|SO_ISNTTY; + str->so_readopt = (mode == M_PARSE) ? RMSGD : RNORM; + str->so_hiwat = (mode == M_PARSE) ? sizeof(parsetime_t) : 256; + str->so_lowat = 0; + mp->b_datap->db_type = M_SETOPTS; + mp->b_wptr += sizeof(struct stroptions); + if (!q) + panic("NULL q - strange"); + putnext(q, mp); + return putctl1(WR(q)->q_next, M_CTL, (mode == M_PARSE) ? MC_SERVICEIMM : + MC_SERVICEDEF); + } + else + { + pprintf(DD_OPEN, "parse: setup_stream - FAILED - no MEMORY for allocb\n"); + return 0; + } +} + +/*ARGSUSED*/ +static int +parseopen( + queue_t *q, + dev_t *dev, + int flag, + int sflag, + cred_t *credp + ) +{ + register parsestream_t *parse; + static int notice = 0; + + pprintf(DD_OPEN, "parse: OPEN - q=%x\n", q); + + if (sflag != MODOPEN) + { /* open only for modules */ + pprintf(DD_OPEN, "parse: OPEN - FAILED - not MODOPEN\n"); + return EIO; + } + + if (q->q_ptr != (caddr_t)NULL) + { + pprintf(DD_OPEN, "parse: OPEN - FAILED - EXCLUSIVE ONLY\n"); + return EBUSY; + } + + q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t), KM_SLEEP); + if (q->q_ptr == (caddr_t)0) + { + return ENOMEM; + } + + pprintf(DD_OPEN, "parse: OPEN - parse area q=%x, q->q_ptr=%x\n", q, q->q_ptr); + WR(q)->q_ptr = q->q_ptr; + pprintf(DD_OPEN, "parse: OPEN - WQ parse area q=%x, q->q_ptr=%x\n", WR(q), WR(q)->q_ptr); + + parse = (parsestream_t *) q->q_ptr; + bzero((caddr_t)parse, sizeof(*parse)); + parse->parse_queue = q; + parse->parse_status = PARSE_ENABLE; + parse->parse_ppsclockev.tv.tv_sec = 0; + parse->parse_ppsclockev.tv.tv_usec = 0; + parse->parse_ppsclockev.serial = 0; + + qprocson(q); + + pprintf(DD_OPEN, "parse: OPEN - initializing io subsystem q=%x\n", q); + + if (!parse_ioinit(&parse->parse_io)) + { + /* + * ok guys - beat it + */ + qprocsoff(q); + + kmem_free((caddr_t)parse, sizeof(parsestream_t)); + + return EIO; + } + + pprintf(DD_OPEN, "parse: OPEN - initializing stream q=%x\n", q); + + if (setup_stream(q, M_PARSE)) + { + (void) init_linemon(q); /* hook up PPS ISR routines if possible */ + pprintf(DD_OPEN, "parse: OPEN - SUCCEEDED\n"); + + /* + * I know that you know the delete key, but you didn't write this + * code, did you ? - So, keep the message in here. + */ + if (!notice) + { + cmn_err(CE_CONT, "?%s: Copyright (c) 1993-2005, Frank Kardel\n", modlstrmod.strmod_linkinfo); + notice = 1; + } + + return 0; + } + else + { + qprocsoff(q); + + kmem_free((caddr_t)parse, sizeof(parsestream_t)); + + return EIO; + } +} + +/*ARGSUSED*/ +static int +parseclose( + queue_t *q, + int flags + ) +{ + register parsestream_t *parse = (parsestream_t *)q->q_ptr; + register unsigned long s; + + pprintf(DD_CLOSE, "parse: CLOSE\n"); + + qprocsoff(q); + + s = splhigh(); + + if (parse->parse_dqueue) + close_linemon(parse->parse_dqueue, q); + parse->parse_dqueue = (queue_t *)0; + + (void) splx(s); + + parse_ioend(&parse->parse_io); + + kmem_free((caddr_t)parse, sizeof(parsestream_t)); + + q->q_ptr = (caddr_t)NULL; + WR(q)->q_ptr = (caddr_t)NULL; + + return 0; +} + +/* + * move unrecognized stuff upward + */ +static int +parsersvc( + queue_t *q + ) +{ + mblk_t *mp; + + while ((mp = getq(q))) + { + if (canputnext(q) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + pprintf(DD_RSVC, "parse: RSVC - putnext\n"); + } + else + { + putbq(q, mp); + pprintf(DD_RSVC, "parse: RSVC - flow control wait\n"); + break; + } + } + return 0; +} + +/* + * do ioctls and + * send stuff down - dont care about + * flow control + */ +static int +parsewput( + queue_t *q, + mblk_t *mp + ) +{ + register int ok = 1; + register mblk_t *datap; + register struct iocblk *iocp; + parsestream_t *parse = (parsestream_t *)q->q_ptr; + + pprintf(DD_WPUT, "parse: parsewput\n"); + + switch (mp->b_datap->db_type) + { + default: + putnext(q, mp); + break; + + case M_IOCTL: + iocp = (void *)mp->b_rptr; + switch (iocp->ioc_cmd) + { + default: + pprintf(DD_WPUT, "parse: parsewput - forward M_IOCTL\n"); + putnext(q, mp); + break; + + case CIOGETEV: + /* + * taken from Craig Leres ppsclock module (and modified) + */ + datap = allocb(sizeof(struct ppsclockev), BPRI_MED); + if (datap == NULL || mp->b_cont) + { + mp->b_datap->db_type = M_IOCNAK; + iocp->ioc_error = (datap == NULL) ? ENOMEM : EINVAL; + if (datap != NULL) + freeb(datap); + qreply(q, mp); + break; + } + + mp->b_cont = datap; + /* (void *) quiets cast alignment warning */ + *(struct ppsclockev *)(void *)datap->b_wptr = parse->parse_ppsclockev; + datap->b_wptr += + sizeof(struct ppsclockev) / sizeof(*datap->b_wptr); + mp->b_datap->db_type = M_IOCACK; + iocp->ioc_count = sizeof(struct ppsclockev); + qreply(q, mp); + break; + + case PARSEIOC_ENABLE: + case PARSEIOC_DISABLE: + { + parse->parse_status = (parse->parse_status & (unsigned)~PARSE_ENABLE) | + (iocp->ioc_cmd == PARSEIOC_ENABLE) ? + PARSE_ENABLE : 0; + if (!setup_stream(RD(q), (parse->parse_status & PARSE_ENABLE) ? + M_PARSE : M_NOPARSE)) + { + mp->b_datap->db_type = M_IOCNAK; + } + else + { + mp->b_datap->db_type = M_IOCACK; + } + qreply(q, mp); + break; + } + + case PARSEIOC_TIMECODE: + case PARSEIOC_SETFMT: + case PARSEIOC_GETFMT: + case PARSEIOC_SETCS: + if (iocp->ioc_count == sizeof(parsectl_t)) + { + parsectl_t *dct = (void *)mp->b_cont->b_rptr; + + switch (iocp->ioc_cmd) + { + case PARSEIOC_TIMECODE: + pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_TIMECODE\n"); + ok = parse_timecode(dct, &parse->parse_io); + break; + + case PARSEIOC_SETFMT: + pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_SETFMT\n"); + ok = parse_setfmt(dct, &parse->parse_io); + break; + + case PARSEIOC_GETFMT: + pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_GETFMT\n"); + ok = parse_getfmt(dct, &parse->parse_io); + break; + + case PARSEIOC_SETCS: + pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_SETCS\n"); + ok = parse_setcs(dct, &parse->parse_io); + break; + } + mp->b_datap->db_type = ok ? M_IOCACK : M_IOCNAK; + } + else + { + mp->b_datap->db_type = M_IOCNAK; + } + pprintf(DD_WPUT, "parse: parsewput qreply - %s\n", (mp->b_datap->db_type == M_IOCNAK) ? "M_IOCNAK" : "M_IOCACK"); + qreply(q, mp); + break; + } + } + return 0; +} + +/* + * read characters from streams buffers + */ +static unsigned long +rdchar( + mblk_t **mp + ) +{ + while (*mp != (mblk_t *)NULL) + { + if ((*mp)->b_wptr - (*mp)->b_rptr) + { + return (unsigned long)(*(unsigned char *)((*mp)->b_rptr++)); + } + else + { + register mblk_t *mmp = *mp; + + *mp = (*mp)->b_cont; + freeb(mmp); + } + } + return (unsigned long)~0; +} + +/* + * convert incoming data + */ +static int +parserput( + queue_t *q, + mblk_t *imp + ) +{ + register unsigned char type; + mblk_t *mp = imp; + + switch (type = mp->b_datap->db_type) + { + default: + /* + * anything we don't know will be put on queue + * the service routine will move it to the next one + */ + pprintf(DD_RPUT, "parse: parserput - forward type 0x%x\n", type); + + if (canputnext(q) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + } + else + putq(q, mp); + break; + + case M_BREAK: + case M_DATA: + { + register parsestream_t * parse = (parsestream_t *)q->q_ptr; + register mblk_t *nmp; + register unsigned long ch; + timestamp_t c_time; + timespec_t hres_time; + + /* + * get time on packet delivery + */ + gethrestime(&hres_time); + c_time.tv.tv_sec = hres_time.tv_sec; + c_time.tv.tv_usec = hres_time.tv_nsec / 1000; + + if (!(parse->parse_status & PARSE_ENABLE)) + { + pprintf(DD_RPUT, "parse: parserput - parser disabled - forward type 0x%x\n", type); + if (canputnext(q) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + } + else + putq(q, mp); + } + else + { + pprintf(DD_RPUT, "parse: parserput - M_%s\n", (type == M_DATA) ? "DATA" : "BREAK"); + if (type == M_DATA) + { + /* + * parse packet looking for start an end characters + */ + while (mp != (mblk_t *)NULL) + { + ch = rdchar(&mp); + if (ch != ~0 && parse_ioread(&parse->parse_io, (unsigned int)ch, &c_time)) + { + /* + * up up and away (hopefully ...) + * don't press it if resources are tight or nobody wants it + */ + nmp = (mblk_t *)NULL; + if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) + { + bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); + nmp->b_wptr += sizeof(parsetime_t); + putnext(parse->parse_queue, nmp); + } + else + if (nmp) freemsg(nmp); + parse_iodone(&parse->parse_io); + } + } + } + else + { + if (parse_ioread(&parse->parse_io, (unsigned int)0, &c_time)) + { + /* + * up up and away (hopefully ...) + * don't press it if resources are tight or nobody wants it + */ + nmp = (mblk_t *)NULL; + if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) + { + bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); + nmp->b_wptr += sizeof(parsetime_t); + putnext(parse->parse_queue, nmp); + } + else + if (nmp) freemsg(nmp); + parse_iodone(&parse->parse_io); + } + freemsg(mp); + } + break; + } + } + + /* + * CD PPS support for non direct ISR hack + */ + case M_HANGUP: + case M_UNHANGUP: + { + register parsestream_t * parse = (parsestream_t *)q->q_ptr; + timestamp_t c_time; + timespec_t hres_time; + register mblk_t *nmp; + register int status = cd_invert ^ (type == M_UNHANGUP); + + gethrestime(&hres_time); + c_time.tv.tv_sec = hres_time.tv_sec; + c_time.tv.tv_usec = hres_time.tv_nsec / 1000; + + pprintf(DD_RPUT, "parse: parserput - M_%sHANGUP\n", (type == M_HANGUP) ? "" : "UN"); + + if ((parse->parse_status & PARSE_ENABLE) && + parse_iopps(&parse->parse_io, status ? SYNC_ONE : SYNC_ZERO, &c_time)) + { + nmp = (mblk_t *)NULL; + if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) + { + bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); + nmp->b_wptr += sizeof(parsetime_t); + putnext(parse->parse_queue, nmp); + } + else + if (nmp) freemsg(nmp); + parse_iodone(&parse->parse_io); + freemsg(mp); + } + else + if (canputnext(q) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + } + else + putq(q, mp); + + if (status) + { + parse->parse_ppsclockev.tv = c_time.tv; + ++(parse->parse_ppsclockev.serial); + } + } + } + return 0; +} + +static int init_zs_linemon (queue_t *, queue_t *); /* handle line monitor for "zs" driver */ +static void close_zs_linemon (queue_t *, queue_t *); + +/*-------------------- CD isr status monitor ---------------*/ + +static int +init_linemon( + queue_t *q + ) +{ + register queue_t *dq; + + dq = WR(q); + /* + * we ARE doing very bad things down here (basically stealing ISR + * hooks) + * + * so we chase down the STREAMS stack searching for the driver + * and if this is a known driver we insert our ISR routine for + * status changes in to the ExternalStatus handling hook + */ + while (dq->q_next) + { + dq = dq->q_next; /* skip down to driver */ + } + + /* + * find appropriate driver dependent routine + */ + if (dq->q_qinfo && dq->q_qinfo->qi_minfo) + { + register char *dname = dq->q_qinfo->qi_minfo->mi_idname; + + pprintf(DD_INSTALL, "init_linemon: driver is \"%s\"\n", dname); + +#ifdef sun + if (dname && !strcmp(dname, "zs")) + { + return init_zs_linemon(dq, q); + } + else +#endif + { + pprintf(DD_INSTALL, "init_linemon: driver \"%s\" not suitable for CD monitoring\n", dname); + return 0; + } + } + pprintf(DD_INSTALL, "init_linemon: cannot find driver\n"); + return 0; +} + +static void +close_linemon( + queue_t *q, + queue_t *my_q + ) +{ + /* + * find appropriate driver dependent routine + */ + if (q->q_qinfo && q->q_qinfo->qi_minfo) + { + register char *dname = q->q_qinfo->qi_minfo->mi_idname; + +#ifdef sun + if (dname && !strcmp(dname, "zs")) + { + close_zs_linemon(q, my_q); + return; + } + pprintf(DD_INSTALL, "close_linemon: cannot find driver close routine for \"%s\"\n", dname); +#endif + } + pprintf(DD_INSTALL, "close_linemon: cannot find driver name\n"); +} + +#ifdef sun +#include +#include +#include +#include + +static void zs_xsisr (struct zscom *); /* zs external status interupt handler */ + +/* + * there should be some docs telling how to get to + * sz:zs_usec_delay and zs:initzsops() + */ +#define zs_usec_delay 5 + +struct savedzsops +{ + struct zsops zsops; + struct zsops *oldzsops; +}; + +static struct zsops *emergencyzs; + +static int +init_zs_linemon( + queue_t *q, + queue_t *my_q + ) +{ + register struct zscom *zs; + register struct savedzsops *szs; + register parsestream_t *parsestream = (parsestream_t *)my_q->q_ptr; + /* + * we expect the zsaline pointer in the q_data pointer + * from there on we insert our on EXTERNAL/STATUS ISR routine + * into the interrupt path, before the standard handler + */ + zs = ((struct asyncline *)q->q_ptr)->za_common; + if (!zs) + { + /* + * well - not found on startup - just say no (shouldn't happen though) + */ + return 0; + } + else + { + /* + * we do a direct replacement, in case others fiddle also + * if somebody else grabs our hook and we disconnect + * we are in DEEP trouble - panic is likely to be next, sorry + */ + szs = (struct savedzsops *) kmem_alloc(sizeof(struct savedzsops), KM_SLEEP); + + if (szs == (struct savedzsops *)0) + { + pprintf(DD_INSTALL, "init_zs_linemon: CD monitor NOT installed - no memory\n"); + + return 0; + } + else + { + parsestream->parse_data = (void *)szs; + + mutex_enter(zs->zs_excl); + + parsestream->parse_dqueue = q; /* remember driver */ + + szs->zsops = *zs->zs_ops; + szs->zsops.zsop_xsint = (void (*) (struct zscom *))zs_xsisr; /* place our bastard */ + szs->oldzsops = zs->zs_ops; + emergencyzs = zs->zs_ops; + + zs->zs_ops = &szs->zsops; /* hook it up */ + /* + * XXX: this is usually done via zsopinit() + * - have yet to find a way to call that routine + */ + zs->zs_xsint = (void (*) (struct zscom *))zs_xsisr; + + mutex_exit(zs->zs_excl); + + pprintf(DD_INSTALL, "init_zs_linemon: CD monitor installed\n"); + + return 1; + } + } +} + +/* + * unregister our ISR routine - must call under splhigh() (or + * whatever block ZS status interrupts) + */ +static void +close_zs_linemon( + queue_t *q, + queue_t *my_q + ) +{ + register struct zscom *zs; + register parsestream_t *parsestream = (parsestream_t *)my_q->q_ptr; + + zs = ((struct asyncline *)q->q_ptr)->za_common; + if (!zs) + { + /* + * well - not found on startup - just say no (shouldn't happen though) + */ + return; + } + else + { + register struct savedzsops *szs = (struct savedzsops *)parsestream->parse_data; + + mutex_enter(zs->zs_excl); + + zs->zs_ops = szs->oldzsops; /* reset to previous handler functions */ + /* + * XXX: revert xsint (usually done via zsopinit() - have still to find + * a way to call that bugger + */ + zs->zs_xsint = zs->zs_ops->zsop_xsint; + + mutex_exit(zs->zs_excl); + + kmem_free((caddr_t)szs, sizeof (struct savedzsops)); + + pprintf(DD_INSTALL, "close_zs_linemon: CD monitor deleted\n"); + return; + } +} + +#define ZSRR0_IGNORE (ZSRR0_CD|ZSRR0_SYNC|ZSRR0_CTS) + +#define MAXDEPTH 50 /* maximum allowed stream crawl */ + +/* + * take external status interrupt (only CD interests us) + */ +static void +zs_xsisr( + struct zscom *zs + ) +{ + register struct asyncline *za = (void *)zs->zs_priv; + register queue_t *q; + register unsigned char zsstatus; + register int loopcheck; + register unsigned char cdstate; + register const char *dname = "-UNKNOWN-"; + timespec_t hres_time; + + /* + * pick up current state + */ + zsstatus = SCC_READ0(); + + if (za->za_rr0 ^ (cdstate = zsstatus & ZSRR0_CD)) + { + timestamp_t cdevent; + register int status; + + /* + * time stamp + */ + gethrestime(&hres_time); + cdevent.tv.tv_sec = hres_time.tv_sec; + cdevent.tv.tv_usec = hres_time.tv_nsec / 1000; + + q = za->za_ttycommon.t_readq; + + /* + * logical state + */ + status = cd_invert ? cdstate == 0 : cdstate != 0; + + /* + * ok - now the hard part - find ourself + */ + loopcheck = MAXDEPTH; + + while (q) + { + if (q->q_qinfo && q->q_qinfo->qi_minfo) + { + dname = q->q_qinfo->qi_minfo->mi_idname; + + if (!strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) + { + /* + * back home - phew (hopping along stream queues might + * prove dangerous to your health) + */ + + if ((((parsestream_t *)q->q_ptr)->parse_status & PARSE_ENABLE) && + parse_iopps(&((parsestream_t *)q->q_ptr)->parse_io, status ? SYNC_ONE : SYNC_ZERO, &cdevent)) + { + /* + * XXX - currently we do not pass up the message, as + * we should. + * for a correct behaviour wee need to block out + * processing until parse_iodone has been posted via + * a softcall-ed routine which does the message pass-up + * right now PPS information relies on input being + * received + */ + parse_iodone(&((parsestream_t *)q->q_ptr)->parse_io); + } + + if (status) + { + ((parsestream_t *)q->q_ptr)->parse_ppsclockev.tv = cdevent.tv; + ++(((parsestream_t *)q->q_ptr)->parse_ppsclockev.serial); + } + + pprintf(DD_ISR, "zs_xsisr: CD event %s has been posted for \"%s\"\n", status ? "ONE" : "ZERO", dname); + break; + } + } + + q = q->q_next; + + if (!loopcheck--) + { + panic("zs_xsisr: STREAMS Queue corrupted - CD event"); + } + } + + if (cdstate) /* fake CARRIER status - XXX currently not coordinated */ + za->za_flags |= ZAS_CARR_ON; + else + za->za_flags &= ~ZAS_CARR_ON; + + /* + * only pretend that CD and ignored transistion (SYNC,CTS) + * have been handled + */ + za->za_rr0 = (za->za_rr0 & ~ZSRR0_IGNORE) | (zsstatus & ZSRR0_IGNORE); + + if (((za->za_rr0 ^ zsstatus) & ~ZSRR0_IGNORE) == 0) + { + /* + * all done - kill status indication and return + */ + SCC_WRITE0(ZSWR0_RESET_STATUS); /* might kill other conditions here */ + return; + } + } + + pprintf(DD_ISR, "zs_xsisr: non CD event 0x%x for \"%s\"\n", + (za->za_rr0 ^ zsstatus) & ~ZSRR0_CD,dname); + /* + * we are now gathered here to process some unusual external status + * interrupts. + * any CD events have also been handled and shouldn't be processed + * by the original routine (unless we have a VERY busy port pin) + * some initializations are done here, which could have been done before for + * both code paths but have been avioded for minimum path length to + * the uniq_time routine + */ + dname = (char *) 0; + q = za->za_ttycommon.t_readq; + + loopcheck = MAXDEPTH; + + /* + * the real thing for everything else ... + */ + while (q) + { + if (q->q_qinfo && q->q_qinfo->qi_minfo) + { + dname = q->q_qinfo->qi_minfo->mi_idname; + if (!strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) + { + register void (*zsisr) (struct zscom *); + + /* + * back home - phew (hopping along stream queues might + * prove dangerous to your health) + */ + if ((zsisr = ((struct savedzsops *)((parsestream_t *)q->q_ptr)->parse_data)->oldzsops->zsop_xsint)) + zsisr(zs); + else + panic("zs_xsisr: unable to locate original ISR"); + + pprintf(DD_ISR, "zs_xsisr: non CD event was processed for \"%s\"\n", dname); + /* + * now back to our program ... + */ + return; + } + } + + q = q->q_next; + + if (!loopcheck--) + { + panic("zs_xsisr: STREAMS Queue corrupted - non CD event"); + } + } + + /* + * last resort - shouldn't even come here as it indicates + * corrupted TTY structures + */ + printf("zs_zsisr: looking for \"%s\" - found \"%s\" - taking EMERGENCY path\n", parseinfo.st_rdinit->qi_minfo->mi_idname, dname ? dname : "-NIL-"); + + if (emergencyzs && emergencyzs->zsop_xsint) + emergencyzs->zsop_xsint(zs); + else + panic("zs_xsisr: no emergency ISR handler"); +} +#endif /* sun */ + +/* + * History: + * + * parsesolaris.c,v + * Revision 4.11 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.10 2004/11/14 16:06:08 kardel + * update Id tags + * + * Revision 4.9 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.6 1998/11/15 21:56:08 kardel + * ntp_memset not necessary + * + * Revision 4.5 1998/11/15 21:23:37 kardel + * ntp_memset() replicated in Sun kernel files + * + * Revision 4.4 1998/06/14 21:09:40 kardel + * Sun acc cleanup + * + * Revision 4.3 1998/06/13 12:14:59 kardel + * more prototypes + * fix name clashes + * allow for ansi2knr + * + * Revision 4.2 1998/06/12 15:23:08 kardel + * fix prototypes + * adjust for ansi2knr + * + * Revision 4.1 1998/05/24 09:38:46 kardel + * streams initiated iopps calls (M_xHANGUP) are now consistent with the + * respective calls from zs_xsisr() + * simulation of CARRIER status to avoid unecessary M_xHANGUP messages + * + * Revision 4.0 1998/04/10 19:45:38 kardel + * Start 4.0 release version numbering + * + * from V3 3.28 log info deleted 1998/04/11 kardel + */ diff --git a/libparse/parsestreams.c b/libparse/parsestreams.c new file mode 100644 index 0000000..3fb4cc3 --- /dev/null +++ b/libparse/parsestreams.c @@ -0,0 +1,1367 @@ +/* + * /src/NTP/ntp4-dev/libparse/parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * STREAMS module for reference clocks + * (SunOS4.x) + * + * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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. + * + */ + +#define KERNEL /* MUST */ +#define VDDRV /* SHOULD */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef lint +static char rcsid[] = "parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A"; +#endif + +#ifndef KERNEL +#include "Bletch: MUST COMPILE WITH KERNEL DEFINE" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef VDDRV +#include +#endif + +#include "ntp_stdlib.h" +#include "ntp_fp.h" +/* + * just make checking compilers more silent + */ +extern int printf (const char *, ...); +extern int putctl1 (queue_t *, int, int); +extern int canput (queue_t *); +extern void putbq (queue_t *, mblk_t *); +extern void freeb (mblk_t *); +extern void qreply (queue_t *, mblk_t *); +extern void freemsg (mblk_t *); +extern void panic (const char *, ...); +extern void usec_delay (int); + +#include "parse.h" +#include "sys/parsestreams.h" + +/* + * use microtime instead of uniqtime if advised to + */ +#ifdef MICROTIME +#define uniqtime microtime +#endif + +#ifdef VDDRV +static unsigned int parsebusy = 0; + +/*--------------- loadable driver section -----------------------------*/ + +extern struct streamtab parseinfo; + + +#ifdef PPS_SYNC +static char mnam[] = "PARSEPPS "; /* name this baby - keep room for revision number */ +#else +static char mnam[] = "PARSE "; /* name this baby - keep room for revision number */ +#endif +struct vdldrv parsesync_vd = +{ + VDMAGIC_PSEUDO, /* nothing like a real driver - a STREAMS module */ + mnam, +}; + +/* + * strings support usually not in kernel + */ +static int +Strlen( + register const char *s + ) +{ + register int c; + + c = 0; + if (s) + { + while (*s++) + { + c++; + } + } + return c; +} + +static void +Strncpy( + register char *t, + register char *s, + register int c + ) +{ + if (s && t) + { + while ((c-- > 0) && (*t++ = *s++)) + ; + } +} + +static int +Strcmp( + register const char *s, + register const char *t + ) +{ + register int c = 0; + + if (!s || !t || (s == t)) + { + return 0; + } + + while (!(c = *s++ - *t++) && *s && *t) + /* empty loop */; + + return c; +} + +static int +Strncmp( + register char *s, + register char *t, + register int n + ) +{ + register int c = 0; + + if (!s || !t || (s == t)) + { + return 0; + } + + while (n-- && !(c = *s++ - *t++) && *s && *t) + /* empty loop */; + + return c; +} + +void +ntp_memset( + char *a, + int x, + int c + ) +{ + while (c-- > 0) + *a++ = x; +} + +/* + * driver init routine + * since no mechanism gets us into and out of the fmodsw, we have to + * do it ourselves + */ +/*ARGSUSED*/ +int +xxxinit( + unsigned int fc, + struct vddrv *vdp, + addr_t vdin, + struct vdstat *vds + ) +{ + extern struct fmodsw fmodsw[]; + extern int fmodcnt; + + struct fmodsw *fm = fmodsw; + struct fmodsw *fmend = &fmodsw[fmodcnt]; + struct fmodsw *ifm = (struct fmodsw *)0; + char *mname = parseinfo.st_rdinit->qi_minfo->mi_idname; + + switch (fc) + { + case VDLOAD: + vdp->vdd_vdtab = (struct vdlinkage *)&parsesync_vd; + /* + * now, jog along fmodsw scanning for an empty slot + * and deposit our name there + */ + while (fm <= fmend) + { + if (!Strncmp(fm->f_name, mname, FMNAMESZ)) + { + printf("vddrinit[%s]: STREAMS module already loaded.\n", mname); + return(EBUSY); + } + else + if ((ifm == (struct fmodsw *)0) && + (fm->f_name[0] == '\0') && + (fm->f_str == (struct streamtab *)0)) + { + /* + * got one - so move in + */ + ifm = fm; + break; + } + fm++; + } + + if (ifm == (struct fmodsw *)0) + { + printf("vddrinit[%s]: no slot free for STREAMS module\n", mname); + return (ENOSPC); + } + else + { + static char revision[] = "4.7"; + char *s, *S, *t; + + s = rcsid; /* NOOP - keep compilers happy */ + + Strncpy(ifm->f_name, mname, FMNAMESZ); + ifm->f_name[FMNAMESZ] = '\0'; + ifm->f_str = &parseinfo; + /* + * copy RCS revision into Drv_name + * + * are we forcing RCS here to do things it was not built for ? + */ + s = revision; + if (*s == '$') + { + /* + * skip "$Revision: " + * if present. - not necessary on a -kv co (cvs export) + */ + while (*s && (*s != ' ')) + { + s++; + } + if (*s == ' ') s++; + } + + t = parsesync_vd.Drv_name; + while (*t && (*t != ' ')) + { + t++; + } + if (*t == ' ') t++; + + S = s; + while (*S && (((*S >= '0') && (*S <= '9')) || (*S == '.'))) + { + S++; + } + + if (*s && *t && (S > s)) + { + if (Strlen(t) >= (S - s)) + { + (void) Strncpy(t, s, S - s); + } + } + return (0); + } + break; + + case VDUNLOAD: + if (parsebusy > 0) + { + printf("vddrinit[%s]: STREAMS module has still %d instances active.\n", mname, parsebusy); + return (EBUSY); + } + else + { + while (fm <= fmend) + { + if (!Strncmp(fm->f_name, mname, FMNAMESZ)) + { + /* + * got it - kill entry + */ + fm->f_name[0] = '\0'; + fm->f_str = (struct streamtab *)0; + fm++; + + break; + } + fm++; + } + if (fm > fmend) + { + printf("vddrinit[%s]: cannot find entry for STREAMS module\n", mname); + return (ENXIO); + } + else + return (0); + } + + + case VDSTAT: + return (0); + + default: + return (EIO); + + } + return EIO; +} + +#endif + +/*--------------- stream module definition ----------------------------*/ + +static int parseopen (queue_t *, dev_t, int, int); +static int parseclose (queue_t *, int); +static int parsewput (queue_t *, mblk_t *); +static int parserput (queue_t *, mblk_t *); +static int parsersvc (queue_t *); + +static char mn[] = "parse"; + +static struct module_info driverinfo = +{ + 0, /* module ID number */ + mn, /* module name */ + 0, /* minimum accepted packet size */ + INFPSZ, /* maximum accepted packet size */ + 1, /* high water mark - flow control */ + 0 /* low water mark - flow control */ +}; + +static struct qinit rinit = /* read queue definition */ +{ + parserput, /* put procedure */ + parsersvc, /* service procedure */ + parseopen, /* open procedure */ + parseclose, /* close procedure */ + NULL, /* admin procedure - NOT USED FOR NOW */ + &driverinfo, /* information structure */ + NULL /* statistics */ +}; + +static struct qinit winit = /* write queue definition */ +{ + parsewput, /* put procedure */ + NULL, /* service procedure */ + NULL, /* open procedure */ + NULL, /* close procedure */ + NULL, /* admin procedure - NOT USED FOR NOW */ + &driverinfo, /* information structure */ + NULL /* statistics */ +}; + +struct streamtab parseinfo = /* stream info element for dpr driver */ +{ + &rinit, /* read queue */ + &winit, /* write queue */ + NULL, /* read mux */ + NULL, /* write mux */ + NULL /* module auto push */ +}; + +/*--------------- driver data structures ----------------------------*/ + +/* + * we usually have an inverted signal - but you + * can change this to suit your needs + */ +int cd_invert = 1; /* invert status of CD line - PPS support via CD input */ + +int parsedebug = ~0; + +extern void uniqtime (struct timeval *); + +/*--------------- module implementation -----------------------------*/ + +#define TIMEVAL_USADD(_X_, _US_) {\ + (_X_)->tv_usec += (_US_);\ + if ((_X_)->tv_usec >= 1000000)\ + {\ + (_X_)->tv_sec++;\ + (_X_)->tv_usec -= 1000000;\ + }\ + } while (0) + +static int init_linemon (queue_t *); +static void close_linemon (queue_t *, queue_t *); + +#define M_PARSE 0x0001 +#define M_NOPARSE 0x0002 + +static int +setup_stream( + queue_t *q, + int mode + ) +{ + mblk_t *mp; + + mp = allocb(sizeof(struct stroptions), BPRI_MED); + if (mp) + { + struct stroptions *str = (struct stroptions *)(void *)mp->b_rptr; + + str->so_flags = SO_READOPT|SO_HIWAT|SO_LOWAT; + str->so_readopt = (mode == M_PARSE) ? RMSGD : RNORM; + str->so_hiwat = (mode == M_PARSE) ? sizeof(parsetime_t) : 256; + str->so_lowat = 0; + mp->b_datap->db_type = M_SETOPTS; + mp->b_wptr += sizeof(struct stroptions); + putnext(q, mp); + return putctl1(WR(q)->q_next, M_CTL, (mode == M_PARSE) ? MC_SERVICEIMM : + MC_SERVICEDEF); + } + else + { + parseprintf(DD_OPEN,("parse: setup_stream - FAILED - no MEMORY for allocb\n")); + return 0; + } +} + +/*ARGSUSED*/ +static int +parseopen( + queue_t *q, + dev_t dev, + int flag, + int sflag + ) +{ + register parsestream_t *parse; + static int notice = 0; + + parseprintf(DD_OPEN,("parse: OPEN\n")); + + if (sflag != MODOPEN) + { /* open only for modules */ + parseprintf(DD_OPEN,("parse: OPEN - FAILED - not MODOPEN\n")); + return OPENFAIL; + } + + if (q->q_ptr != (caddr_t)NULL) + { + u.u_error = EBUSY; + parseprintf(DD_OPEN,("parse: OPEN - FAILED - EXCLUSIVE ONLY\n")); + return OPENFAIL; + } + +#ifdef VDDRV + parsebusy++; +#endif + + q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t)); + if (q->q_ptr == (caddr_t)0) + { + parseprintf(DD_OPEN,("parse: OPEN - FAILED - no memory\n")); +#ifdef VDDRV + parsebusy--; +#endif + return OPENFAIL; + } + WR(q)->q_ptr = q->q_ptr; + + parse = (parsestream_t *)(void *)q->q_ptr; + bzero((caddr_t)parse, sizeof(*parse)); + parse->parse_queue = q; + parse->parse_status = PARSE_ENABLE; + parse->parse_ppsclockev.tv.tv_sec = 0; + parse->parse_ppsclockev.tv.tv_usec = 0; + parse->parse_ppsclockev.serial = 0; + + if (!parse_ioinit(&parse->parse_io)) + { + /* + * ok guys - beat it + */ + kmem_free((caddr_t)parse, sizeof(parsestream_t)); +#ifdef VDDRV + parsebusy--; +#endif + return OPENFAIL; + } + + if (setup_stream(q, M_PARSE)) + { + (void) init_linemon(q); /* hook up PPS ISR routines if possible */ + + parseprintf(DD_OPEN,("parse: OPEN - SUCCEEDED\n")); + + /* + * I know that you know the delete key, but you didn't write this + * code, did you ? - So, keep the message in here. + */ + if (!notice) + { +#ifdef VDDRV + printf("%s: Copyright (C) 1991-2005, Frank Kardel\n", parsesync_vd.Drv_name); +#else + printf("%s: Copyright (C) 1991-2005, Frank Kardel\n", "parsestreams.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A"); +#endif + notice = 1; + } + + return MODOPEN; + } + else + { + kmem_free((caddr_t)parse, sizeof(parsestream_t)); + +#ifdef VDDRV + parsebusy--; +#endif + return OPENFAIL; + } +} + +/*ARGSUSED*/ +static int +parseclose( + queue_t *q, + int flags + ) +{ + register parsestream_t *parse = (parsestream_t *)(void *)q->q_ptr; + register unsigned long s; + + parseprintf(DD_CLOSE,("parse: CLOSE\n")); + + s = splhigh(); + + if (parse->parse_dqueue) + close_linemon(parse->parse_dqueue, q); + parse->parse_dqueue = (queue_t *)0; + + (void) splx(s); + + parse_ioend(&parse->parse_io); + + kmem_free((caddr_t)parse, sizeof(parsestream_t)); + + q->q_ptr = (caddr_t)NULL; + WR(q)->q_ptr = (caddr_t)NULL; + +#ifdef VDDRV + parsebusy--; +#endif + return 0; +} + +/* + * move unrecognized stuff upward + */ +static int +parsersvc( + queue_t *q + ) +{ + mblk_t *mp; + + while ((mp = getq(q))) + { + if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + parseprintf(DD_RSVC,("parse: RSVC - putnext\n")); + } + else + { + putbq(q, mp); + parseprintf(DD_RSVC,("parse: RSVC - flow control wait\n")); + break; + } + } + return 0; +} + +/* + * do ioctls and + * send stuff down - dont care about + * flow control + */ +static int +parsewput( + queue_t *q, + register mblk_t *mp + ) +{ + register int ok = 1; + register mblk_t *datap; + register struct iocblk *iocp; + parsestream_t *parse = (parsestream_t *)(void *)q->q_ptr; + + parseprintf(DD_WPUT,("parse: parsewput\n")); + + switch (mp->b_datap->db_type) + { + default: + putnext(q, mp); + break; + + case M_IOCTL: + iocp = (struct iocblk *)(void *)mp->b_rptr; + switch (iocp->ioc_cmd) + { + default: + parseprintf(DD_WPUT,("parse: parsewput - forward M_IOCTL\n")); + putnext(q, mp); + break; + + case CIOGETEV: + /* + * taken from Craig Leres ppsclock module (and modified) + */ + datap = allocb(sizeof(struct ppsclockev), BPRI_MED); + if (datap == NULL || mp->b_cont) + { + mp->b_datap->db_type = M_IOCNAK; + iocp->ioc_error = (datap == NULL) ? ENOMEM : EINVAL; + if (datap != NULL) + freeb(datap); + qreply(q, mp); + break; + } + + mp->b_cont = datap; + *(struct ppsclockev *)(void *)datap->b_wptr = parse->parse_ppsclockev; + datap->b_wptr += + sizeof(struct ppsclockev) / sizeof(*datap->b_wptr); + mp->b_datap->db_type = M_IOCACK; + iocp->ioc_count = sizeof(struct ppsclockev); + qreply(q, mp); + break; + + case PARSEIOC_ENABLE: + case PARSEIOC_DISABLE: + { + parse->parse_status = (parse->parse_status & (unsigned)~PARSE_ENABLE) | + (iocp->ioc_cmd == PARSEIOC_ENABLE) ? + PARSE_ENABLE : 0; + if (!setup_stream(RD(q), (parse->parse_status & PARSE_ENABLE) ? + M_PARSE : M_NOPARSE)) + { + mp->b_datap->db_type = M_IOCNAK; + } + else + { + mp->b_datap->db_type = M_IOCACK; + } + qreply(q, mp); + break; + } + + case PARSEIOC_TIMECODE: + case PARSEIOC_SETFMT: + case PARSEIOC_GETFMT: + case PARSEIOC_SETCS: + if (iocp->ioc_count == sizeof(parsectl_t)) + { + parsectl_t *dct = (parsectl_t *)(void *)mp->b_cont->b_rptr; + + switch (iocp->ioc_cmd) + { + case PARSEIOC_TIMECODE: + parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_TIMECODE\n")); + ok = parse_timecode(dct, &parse->parse_io); + break; + + case PARSEIOC_SETFMT: + parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_SETFMT\n")); + ok = parse_setfmt(dct, &parse->parse_io); + break; + + case PARSEIOC_GETFMT: + parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_GETFMT\n")); + ok = parse_getfmt(dct, &parse->parse_io); + break; + + case PARSEIOC_SETCS: + parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_SETCS\n")); + ok = parse_setcs(dct, &parse->parse_io); + break; + } + mp->b_datap->db_type = ok ? M_IOCACK : M_IOCNAK; + } + else + { + mp->b_datap->db_type = M_IOCNAK; + } + parseprintf(DD_WPUT,("parse: parsewput qreply - %s\n", (mp->b_datap->db_type == M_IOCNAK) ? "M_IOCNAK" : "M_IOCACK")); + qreply(q, mp); + break; + } + } + return 0; +} + +/* + * read characters from streams buffers + */ +static unsigned long +rdchar( + register mblk_t **mp + ) +{ + while (*mp != (mblk_t *)NULL) + { + if ((*mp)->b_wptr - (*mp)->b_rptr) + { + return (unsigned long)(*(unsigned char *)((*mp)->b_rptr++)); + } + else + { + register mblk_t *mmp = *mp; + + *mp = (*mp)->b_cont; + freeb(mmp); + } + } + return (unsigned)~0; +} + +/* + * convert incoming data + */ +static int +parserput( + queue_t *q, + mblk_t *mp + ) +{ + unsigned char type; + + switch (type = mp->b_datap->db_type) + { + default: + /* + * anything we don't know will be put on queue + * the service routine will move it to the next one + */ + parseprintf(DD_RPUT,("parse: parserput - forward type 0x%x\n", type)); + if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + } + else + putq(q, mp); + break; + + case M_BREAK: + case M_DATA: + { + register parsestream_t * parse = (parsestream_t *)(void *)q->q_ptr; + register mblk_t *nmp; + register unsigned long ch; + timestamp_t ctime; + + /* + * get time on packet delivery + */ + uniqtime(&ctime.tv); + + if (!(parse->parse_status & PARSE_ENABLE)) + { + parseprintf(DD_RPUT,("parse: parserput - parser disabled - forward type 0x%x\n", type)); + if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + } + else + putq(q, mp); + } + else + { + parseprintf(DD_RPUT,("parse: parserput - M_%s\n", (type == M_DATA) ? "DATA" : "BREAK")); + + if (type == M_DATA) + { + /* + * parse packet looking for start an end characters + */ + while (mp != (mblk_t *)NULL) + { + ch = rdchar(&mp); + if (ch != ~0 && parse_ioread(&parse->parse_io, (unsigned int)ch, &ctime)) + { + /* + * up up and away (hopefully ...) + * don't press it if resources are tight or nobody wants it + */ + nmp = (mblk_t *)NULL; + if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) + { + bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); + nmp->b_wptr += sizeof(parsetime_t); + putnext(parse->parse_queue, nmp); + } + else + if (nmp) freemsg(nmp); + parse_iodone(&parse->parse_io); + } + } + } + else + { + if (parse_ioread(&parse->parse_io, (unsigned int)0, &ctime)) + { + /* + * up up and away (hopefully ...) + * don't press it if resources are tight or nobody wants it + */ + nmp = (mblk_t *)NULL; + if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) + { + bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); + nmp->b_wptr += sizeof(parsetime_t); + putnext(parse->parse_queue, nmp); + } + else + if (nmp) freemsg(nmp); + parse_iodone(&parse->parse_io); + } + freemsg(mp); + } + break; + } + } + + /* + * CD PPS support for non direct ISR hack + */ + case M_HANGUP: + case M_UNHANGUP: + { + register parsestream_t * parse = (parsestream_t *)(void *)q->q_ptr; + timestamp_t ctime; + register mblk_t *nmp; + register int status = cd_invert ^ (type == M_UNHANGUP); + + uniqtime(&ctime.tv); + + parseprintf(DD_RPUT,("parse: parserput - M_%sHANGUP\n", (type == M_HANGUP) ? "" : "UN")); + + if ((parse->parse_status & PARSE_ENABLE) && + parse_iopps(&parse->parse_io, (int)(status ? SYNC_ONE : SYNC_ZERO), &ctime)) + { + nmp = (mblk_t *)NULL; + if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) + { + bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); + nmp->b_wptr += sizeof(parsetime_t); + putnext(parse->parse_queue, nmp); + } + else + if (nmp) freemsg(nmp); + parse_iodone(&parse->parse_io); + freemsg(mp); + } + else + if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + } + else + putq(q, mp); + + if (status) + { + parse->parse_ppsclockev.tv = ctime.tv; + ++(parse->parse_ppsclockev.serial); + } + } + } + return 0; +} + +static int init_zs_linemon (queue_t *, queue_t *); /* handle line monitor for "zs" driver */ +static void close_zs_linemon (queue_t *, queue_t *); + +/*-------------------- CD isr status monitor ---------------*/ + +static int +init_linemon( + register queue_t *q + ) +{ + register queue_t *dq; + + dq = WR(q); + /* + * we ARE doing very bad things down here (basically stealing ISR + * hooks) + * + * so we chase down the STREAMS stack searching for the driver + * and if this is a known driver we insert our ISR routine for + * status changes in to the ExternalStatus handling hook + */ + while (dq->q_next) + { + dq = dq->q_next; /* skip down to driver */ + } + + /* + * find appropriate driver dependent routine + */ + if (dq->q_qinfo && dq->q_qinfo->qi_minfo) + { + register char *dname = dq->q_qinfo->qi_minfo->mi_idname; + + parseprintf(DD_INSTALL, ("init_linemon: driver is \"%s\"\n", dname)); + +#ifdef sun + if (dname && !Strcmp(dname, "zs")) + { + return init_zs_linemon(dq, q); + } + else +#endif + { + parseprintf(DD_INSTALL, ("init_linemon: driver \"%s\" not suitable for CD monitoring\n", dname)); + return 0; + } + } + parseprintf(DD_INSTALL, ("init_linemon: cannot find driver\n")); + return 0; +} + +static void +close_linemon( + register queue_t *q, + register queue_t *my_q + ) +{ + /* + * find appropriate driver dependent routine + */ + if (q->q_qinfo && q->q_qinfo->qi_minfo) + { + register char *dname = q->q_qinfo->qi_minfo->mi_idname; + +#ifdef sun + if (dname && !Strcmp(dname, "zs")) + { + close_zs_linemon(q, my_q); + return; + } + parseprintf(DD_INSTALL, ("close_linemon: cannot find driver close routine for \"%s\"\n", dname)); +#endif + } + parseprintf(DD_INSTALL, ("close_linemon: cannot find driver name\n")); +} + +#ifdef sun + +#include +#include +#include + +static unsigned long cdmask = ZSRR0_CD; + +struct savedzsops +{ + struct zsops zsops; + struct zsops *oldzsops; +}; + +struct zsops *emergencyzs; +extern void zsopinit (struct zscom *, struct zsops *); +static int zs_xsisr (struct zscom *); /* zs external status interupt handler */ + +static int +init_zs_linemon( + register queue_t *q, + register queue_t *my_q + ) +{ + register struct zscom *zs; + register struct savedzsops *szs; + register parsestream_t *parsestream = (parsestream_t *)(void *)my_q->q_ptr; + /* + * we expect the zsaline pointer in the q_data pointer + * from there on we insert our on EXTERNAL/STATUS ISR routine + * into the interrupt path, before the standard handler + */ + zs = ((struct zsaline *)(void *)q->q_ptr)->za_common; + if (!zs) + { + /* + * well - not found on startup - just say no (shouldn't happen though) + */ + return 0; + } + else + { + unsigned long s; + + /* + * we do a direct replacement, in case others fiddle also + * if somebody else grabs our hook and we disconnect + * we are in DEEP trouble - panic is likely to be next, sorry + */ + szs = (struct savedzsops *)(void *)kmem_alloc(sizeof(struct savedzsops)); + + if (szs == (struct savedzsops *)0) + { + parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor NOT installed - no memory\n")); + + return 0; + } + else + { + parsestream->parse_data = (void *)szs; + + s = splhigh(); + + parsestream->parse_dqueue = q; /* remember driver */ + + szs->zsops = *zs->zs_ops; + szs->zsops.zsop_xsint = zs_xsisr; /* place our bastard */ + szs->oldzsops = zs->zs_ops; + emergencyzs = zs->zs_ops; + + zsopinit(zs, &szs->zsops); /* hook it up */ + + (void) splx(s); + + parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor installed\n")); + + return 1; + } + } +} + +/* + * unregister our ISR routine - must call under splhigh() + */ +static void +close_zs_linemon( + register queue_t *q, + register queue_t *my_q + ) +{ + register struct zscom *zs; + register parsestream_t *parsestream = (parsestream_t *)(void *)my_q->q_ptr; + + zs = ((struct zsaline *)(void *)q->q_ptr)->za_common; + if (!zs) + { + /* + * well - not found on startup - just say no (shouldn't happen though) + */ + return; + } + else + { + register struct savedzsops *szs = (struct savedzsops *)parsestream->parse_data; + + zsopinit(zs, szs->oldzsops); /* reset to previous handler functions */ + + kmem_free((caddr_t)szs, sizeof (struct savedzsops)); + + parseprintf(DD_INSTALL, ("close_zs_linemon: CD monitor deleted\n")); + return; + } +} + +#define MAXDEPTH 50 /* maximum allowed stream crawl */ + +#ifdef PPS_SYNC +extern void hardpps (struct timeval *, long); +#ifdef PPS_NEW +extern struct timeval timestamp; +#else +extern struct timeval pps_time; +#endif +#endif + +/* + * take external status interrupt (only CD interests us) + */ +static int +zs_xsisr( + struct zscom *zs + ) +{ + register struct zsaline *za = (struct zsaline *)(void *)zs->zs_priv; + register struct zscc_device *zsaddr = zs->zs_addr; + register queue_t *q; + register unsigned char zsstatus; + register int loopcheck; + register char *dname; +#ifdef PPS_SYNC + register unsigned int s; + register long usec; +#endif + + /* + * pick up current state + */ + zsstatus = zsaddr->zscc_control; + + if ((za->za_rr0 ^ zsstatus) & (cdmask)) + { + timestamp_t cdevent; + register int status; + + za->za_rr0 = (za->za_rr0 & ~(cdmask)) | (zsstatus & (cdmask)); + +#ifdef PPS_SYNC + s = splclock(); +#ifdef PPS_NEW + usec = timestamp.tv_usec; +#else + usec = pps_time.tv_usec; +#endif +#endif + /* + * time stamp + */ + uniqtime(&cdevent.tv); + +#ifdef PPS_SYNC + (void)splx(s); +#endif + + /* + * logical state + */ + status = cd_invert ? (zsstatus & cdmask) == 0 : (zsstatus & cdmask) != 0; + +#ifdef PPS_SYNC + if (status) + { + usec = cdevent.tv.tv_usec - usec; + if (usec < 0) + usec += 1000000; + + hardpps(&cdevent.tv, usec); + } +#endif + + q = za->za_ttycommon.t_readq; + + /* + * ok - now the hard part - find ourself + */ + loopcheck = MAXDEPTH; + + while (q) + { + if (q->q_qinfo && q->q_qinfo->qi_minfo) + { + dname = q->q_qinfo->qi_minfo->mi_idname; + + if (!Strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) + { + /* + * back home - phew (hopping along stream queues might + * prove dangerous to your health) + */ + + if ((((parsestream_t *)(void *)q->q_ptr)->parse_status & PARSE_ENABLE) && + parse_iopps(&((parsestream_t *)(void *)q->q_ptr)->parse_io, (int)(status ? SYNC_ONE : SYNC_ZERO), &cdevent)) + { + /* + * XXX - currently we do not pass up the message, as + * we should. + * for a correct behaviour wee need to block out + * processing until parse_iodone has been posted via + * a softcall-ed routine which does the message pass-up + * right now PPS information relies on input being + * received + */ + parse_iodone(&((parsestream_t *)(void *)q->q_ptr)->parse_io); + } + + if (status) + { + ((parsestream_t *)(void *)q->q_ptr)->parse_ppsclockev.tv = cdevent.tv; + ++(((parsestream_t *)(void *)q->q_ptr)->parse_ppsclockev.serial); + } + + parseprintf(DD_ISR, ("zs_xsisr: CD event %s has been posted for \"%s\"\n", status ? "ONE" : "ZERO", dname)); + break; + } + } + + q = q->q_next; + + if (!loopcheck--) + { + panic("zs_xsisr: STREAMS Queue corrupted - CD event"); + } + } + + /* + * only pretend that CD has been handled + */ + ZSDELAY(2); + + if (!((za->za_rr0 ^ zsstatus) & ~(cdmask))) + { + /* + * all done - kill status indication and return + */ + zsaddr->zscc_control = ZSWR0_RESET_STATUS; /* might kill other conditions here */ + return 0; + } + } + + if (zsstatus & cdmask) /* fake CARRIER status */ + za->za_flags |= ZAS_CARR_ON; + else + za->za_flags &= ~ZAS_CARR_ON; + + /* + * we are now gathered here to process some unusual external status + * interrupts. + * any CD events have also been handled and shouldn't be processed + * by the original routine (unless we have a VERY busy port pin) + * some initializations are done here, which could have been done before for + * both code paths but have been avoided for minimum path length to + * the uniq_time routine + */ + dname = (char *) 0; + q = za->za_ttycommon.t_readq; + + loopcheck = MAXDEPTH; + + /* + * the real thing for everything else ... + */ + while (q) + { + if (q->q_qinfo && q->q_qinfo->qi_minfo) + { + dname = q->q_qinfo->qi_minfo->mi_idname; + if (!Strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) + { + register int (*zsisr) (struct zscom *); + + /* + * back home - phew (hopping along stream queues might + * prove dangerous to your health) + */ + if ((zsisr = ((struct savedzsops *)((parsestream_t *)(void *)q->q_ptr)->parse_data)->oldzsops->zsop_xsint)) + return zsisr(zs); + else + panic("zs_xsisr: unable to locate original ISR"); + + parseprintf(DD_ISR, ("zs_xsisr: non CD event was processed for \"%s\"\n", dname)); + /* + * now back to our program ... + */ + return 0; + } + } + + q = q->q_next; + + if (!loopcheck--) + { + panic("zs_xsisr: STREAMS Queue corrupted - non CD event"); + } + } + + /* + * last resort - shouldn't even come here as it indicates + * corrupted TTY structures + */ + printf("zs_zsisr: looking for \"%s\" - found \"%s\" - taking EMERGENCY path\n", parseinfo.st_rdinit->qi_minfo->mi_idname, dname ? dname : "-NIL-"); + + if (emergencyzs && emergencyzs->zsop_xsint) + emergencyzs->zsop_xsint(zs); + else + panic("zs_xsisr: no emergency ISR handler"); + return 0; +} +#endif /* sun */ + +/* + * History: + * + * parsestreams.c,v + * Revision 4.11 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.10 2004/11/14 16:06:08 kardel + * update Id tags + * + * Revision 4.9 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.7 1999/11/28 09:13:53 kardel + * RECON_4_0_98F + * + * Revision 4.6 1998/12/20 23:45:31 kardel + * fix types and warnings + * + * Revision 4.5 1998/11/15 21:23:38 kardel + * ntp_memset() replicated in Sun kernel files + * + * Revision 4.4 1998/06/13 12:15:59 kardel + * superfluous variable removed + * + * Revision 4.3 1998/06/12 15:23:08 kardel + * fix prototypes + * adjust for ansi2knr + * + * Revision 4.2 1998/05/24 18:16:22 kardel + * moved copy of shadow status to the beginning + * + * Revision 4.1 1998/05/24 09:38:47 kardel + * streams initiated iopps calls (M_xHANGUP) are now consistent with the + * respective calls from zs_xsisr() + * simulation of CARRIER status to avoid unecessary M_xHANGUP messages + * + * Revision 4.0 1998/04/10 19:45:38 kardel + * Start 4.0 release version numbering + * + * from V3 3.37 log info deleted 1998/04/11 kardel + */ diff --git a/libparse/trim_info.c b/libparse/trim_info.c new file mode 100644 index 0000000..619e238 --- /dev/null +++ b/libparse/trim_info.c @@ -0,0 +1,70 @@ +/* + * /src/NTP/ntp4-dev/libparse/trim_info.c,v 4.5 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * trim_info.c,v 4.5 2005/04/16 17:32:10 kardel RELEASE_20050508_A + * + * $Created: Sun Aug 2 20:20:34 1998 $ + * + * Copyright (c) 1995-2005 by Frank Kardel ntp.org> + * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, 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. + * + */ +#include +#include "ntp_types.h" +#include "trimble.h" + +cmd_info_t * +trimble_convert( + unsigned int cmd, + cmd_info_t *tbl + ) +{ + int i; + + for (i = 0; tbl[i].cmd != 0xFF; i++) + { + if (tbl[i].cmd == cmd) + return &tbl[i]; + } + return 0; +} + +/* + * trim_info.c,v + * Revision 4.5 2005/04/16 17:32:10 kardel + * update copyright + * + * Revision 4.4 2004/11/14 15:29:41 kardel + * support PPSAPI, upgrade Copyright to Berkeley style + * + * Revision 4.2 1998/12/20 23:45:31 kardel + * fix types and warnings + * + * Revision 4.1 1998/08/09 22:27:48 kardel + * Trimble TSIP support + * + */ -- cgit v1.2.1