diff options
author | Martin Burnicki <martin.burnicki@meinberg.de> | 2017-07-26 12:00:00 +0200 |
---|---|---|
committer | Martin Burnicki <martin.burnicki@meinberg.de> | 2017-07-26 12:00:00 +0200 |
commit | bd8c46abdb579b8c7871b9ff22a2555c2211e110 (patch) | |
tree | 501778613366a983fd1d039e9dc08ce52d3b79bd | |
parent | 9fd30c3e28e55927b786f742fee14b3a03c8cd32 (diff) | |
download | mbgtools-nbsd-bd8c46abdb579b8c7871b9ff22a2555c2211e110.tar.gz mbgtools-nbsd-bd8c46abdb579b8c7871b9ff22a2555c2211e110.zip |
Update files from mbgtools-nbsd-dev-2017-07-26.tar.gzmbgtools-nbsd-dev-2017-07-26
109 files changed, 57423 insertions, 14790 deletions
diff --git a/src/external/bsd/meinberg/Makefile b/src/external/bsd/meinberg/Makefile new file mode 100755 index 0000000..346d99a --- /dev/null +++ b/src/external/bsd/meinberg/Makefile @@ -0,0 +1,6 @@ +# $NetBSD: Makefile,v 1.2 2010/08/28 15:42:46 kardel Exp $ + +SUBDIR+= mbgclock +SUBDIR+= dist + +.include <bsd.subdir.mk> diff --git a/src/external/bsd/meinberg/Makefile.inc b/src/external/bsd/meinberg/Makefile.inc new file mode 100755 index 0000000..f169b5c --- /dev/null +++ b/src/external/bsd/meinberg/Makefile.inc @@ -0,0 +1,30 @@ +# $NetBSD: Makefile.inc,v 1.5 2010/12/04 23:08:32 christos Exp $ + +.if !defined(MEINBERG_MAKEFILE_INC) +MEINBERG_MAKEFILE_INC=yes + +USE_FORT?= yes # network client/server + +# WARNS?= 5 + +.include <bsd.own.mk> + +IDIST= ${NETBSDSRCDIR}/external/bsd/meinberg/dist +MBG_LIB_COMMON= ${IDIST}/mbglib/common +MBG_LIB_BSD= ${IDIST}/mbglib/bsd + +CPPFLAGS+=-I${MBG_LIB_COMMON} -I${MBG_LIB_BSD} + +.if defined(DEBUG) +CPPFLAGS+=-DDEBUG=${DEBUG} +.endif + +.if defined(MBG_DEBUG) +CPPFLAGS+=-DMBG_DEBUG=${MBG_DEBUG} +.endif + +.if exists(${.CURDIR}/../../Makefile.inc) +.include "${.CURDIR}/../../Makefile.inc" +.endif + +.endif diff --git a/src/external/bsd/meinberg/dist/Makefile b/src/external/bsd/meinberg/dist/Makefile index de11e0e..e1a79f8 100755 --- a/src/external/bsd/meinberg/dist/Makefile +++ b/src/external/bsd/meinberg/dist/Makefile @@ -1,13 +1,16 @@ ######################################################################### # -# $Id: Makefile 1.1.1.2 2011/07/08 12:10:09 martin TRASH $ +# $Id: Makefile 1.1.1.4 2017/07/26 14:31:06 martin TEST $ # # Description: # Makefile for mbgtools which recurses into the subdirectories. # # ----------------------------------------------------------------------- # $Log: Makefile $ +# Revision 1.1.1.4 2017/07/26 14:31:06 martin +# Removed trailing spaces. +# Revision 1.1.1.3 2011/11/24 13:59:58 martin # Revision 1.1.1.2 2011/07/08 12:10:09 martin # Revision 1.1.1.1 2011/03/29 13:54:39 martin # Revision 1.1.1.6.1.1 2011/03/28 09:36:56 martin @@ -120,6 +123,7 @@ chk_subdir = $(shell test -f $(strip $(1))/Makefile && echo "$(1)" ) SUBDIRS += $(call chk_subdir, "mbgfasttstamp" ) SUBDIRS += $(call chk_subdir, "mbgsvcd" ) SUBDIRS += $(call chk_subdir, "mbgxhrtime" ) + SUBDIRS += $(call chk_subdir, "test/mbgtestcalrec" ) SUBDIRS += $(call chk_subdir, "test/mbgtestio" ) SUBDIRS += $(call chk_subdir, "test/mbgtestmmio" ) SUBDIRS += $(call chk_subdir, "test/mbgtestxhrt" ) @@ -157,11 +161,12 @@ SUBDIRS += mbggpscap SUBDIRS += mbghrtime SUBDIRS += mbgfasttstamp # SUBDIRS += mbgxhrtime ## not yet tested -SUBDIRS += test/mbgtestio -SUBDIRS += test/mbgtestmmio -SUBDIRS += test/mbgtestxhrt -SUBDIRS += test/mbgchksystime -# SUBDIRS += mbgclock +SUBDIRS += test/mbgtestcalrec +# SUBDIRS += test/mbgtestio +# SUBDIRS += test/mbgtestmmio +# SUBDIRS += test/mbgtestxhrt +# SUBDIRS += test/mbgchksystime +## SUBDIRS += mbgclock #out of tree in this project .PHONY: all clean distclean install uninstall all clean distclean install uninstall: @@ -298,8 +303,8 @@ VPATH = $(BASEDIR)/mbglib/common:$(BASEDIR)/mbglib/bsd # Check whether thread affinity is supported by the installed pthread library. # Newer versions of glibc/pthread (at least glibc 2.5) supports this natively. # Older versions of glibc/pthread (e.g. glibc 2.3) may not support this natively - # but may provide a NPTL (New Posix Thread Library) library located under separate - # include and lib paths. We try to detect NPTL and add those paths to the search + # but may provide a NPTL (New Posix Thread Library) library located under separate + # include and lib paths. We try to detect NPTL and add those paths to the search # paths only if USE_NTPL has been defined e.g. on the make command line. # Check whether pthread_getaffinity is supported by the standard pthread.h diff --git a/src/external/bsd/meinberg/dist/README b/src/external/bsd/meinberg/dist/README index 4167efb..e6c42d4 100755 --- a/src/external/bsd/meinberg/dist/README +++ b/src/external/bsd/meinberg/dist/README @@ -1,4 +1,4 @@ -$Id: README 1.1 2011/03/29 13:35:05 martin TRASH $ +$Id: README 1.1 2011/03/29 13:35:05 martin TEST $ This is the README file for mbgtools-fbsd-dev-2011-02-04 -------------------------------------------------------- diff --git a/src/external/bsd/meinberg/dist/mbgctrl/Makefile b/src/external/bsd/meinberg/dist/mbgctrl/Makefile index 01e3abf..367960d 100755 --- a/src/external/bsd/meinberg/dist/mbgctrl/Makefile +++ b/src/external/bsd/meinberg/dist/mbgctrl/Makefile @@ -1,19 +1,16 @@ ######################################################################### # -# $Id: Makefile 1.7.1.2.1.2 2011/04/20 09:34:06 martin TRASH $ +# $Id: Makefile 1.8 2017/07/05 18:51:21 martin REL_M $ # # Description: # Makefile for mbgctrl. # # ----------------------------------------------------------------------- # $Log: Makefile $ -# Revision 1.7.1.2.1.2 2011/04/20 09:34:06 martin -# Added module lan_util. -# Revision 1.7.1.2.1.1 2010/09/20 12:06:15 stefan -# Updated for use with latest base Makefile. -# Revision 1.7.1.2 2010/08/30 09:05:22 martin -# Revision 1.7.1.1 2010/08/30 08:20:54 martin +# Revision 1.8 2017/07/05 18:51:21 martin +# Updated list of object files and use top level +# Makefile properly. # Revision 1.7 2009/07/24 10:31:16 martin # Moved declarations to a common file which is now included. # Revision 1.6 2008/12/22 11:54:31 martin @@ -39,11 +36,14 @@ MBGDEVIO_SIMPLE = 0 OBJS = $(TARGET).o OBJS += mbgdevio.o +OBJS += mbgutil.o +OBJS += timeutil.o +OBJS += str_util.o OBJS += toolutil.o +OBJS += mbgerror.o +OBJS += cfg_hlp.o +OBJS += deviohlp.o OBJS += gpsutils.o -OBJS += pcpsutil.o -OBJS += parmgps.o -OBJS += parmpcps.o OBJS += lan_util.o BASEDIR := .. diff --git a/src/external/bsd/meinberg/dist/mbgctrl/mbgctrl.c b/src/external/bsd/meinberg/dist/mbgctrl/mbgctrl.c index 18e8644..ea9e250 100755 --- a/src/external/bsd/meinberg/dist/mbgctrl/mbgctrl.c +++ b/src/external/bsd/meinberg/dist/mbgctrl/mbgctrl.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgctrl.c 1.22.1.7.1.24 2011/07/19 15:49:42 martin TRASH $ + * $Id: mbgctrl.c 1.23 2017/07/05 19:10:07 martin REL_M $ * * Description: * Main file for mbgctrl program which sends commands and @@ -9,53 +9,18 @@ * * ----------------------------------------------------------------------- * $Log: mbgctrl.c $ - * Revision 1.22.1.7.1.24 2011/07/19 15:49:42 martin - * Warn if trying to handle serial port cfg but no serial port is supported. - * Revision 1.22.1.7.1.23 2011/07/19 13:08:08 martin - * Revision 1.22.1.7.1.22 2011/07/08 11:20:15 martin - * More PTP stuff ... - * Revision 1.22.1.7.1.21 2011/07/08 09:04:46 martin - * More PTP stuff ... - * Revision 1.22.1.7.1.20 2011/07/07 15:08:57 martin - * Started simulation of PTP configuration. - * Revision 1.22.1.7.1.19 2011/07/06 09:48:01 martin - * Revision 1.22.1.7.1.18 2011/07/05 15:35:53 martin - * Modified version handling. - * Revision 1.22.1.7.1.17 2011/07/05 14:35:17 martin + * Revision 1.23 2017/07/05 19:10:07 martin * New way to maintain version information. - * Revision 1.22.1.7.1.16 2011/06/27 13:03:19 martin - * Use O_RDWR flag when opening a device. - * Revision 1.22.1.7.1.15 2011/05/04 14:53:18 martin - * Fixed compiler warning. - * Revision 1.22.1.7.1.14 2011/05/03 15:43:12 martin - * Revision 1.22.1.7.1.13 2011/04/21 11:09:42 martin - * Revision 1.22.1.7.1.12 2011/04/21 10:16:03 martin - * Revision 1.22.1.7.1.11 2011/04/21 08:49:09 martin - * Revision 1.22.1.7.1.10 2011/04/21 08:40:19 martin - * Revision 1.22.1.7.1.9 2011/04/21 07:51:05 martin - * Revision 1.22.1.7.1.8 2011/04/20 16:07:41 martin - * Revision 1.22.1.7.1.7 2011/04/20 14:49:31 martin - * Revision 1.22.1.7.1.6 2011/04/20 14:43:00 martin - * Revision 1.22.1.7.1.5 2011/04/20 14:13:36 martin - * Revision 1.22.1.7.1.4 2011/04/20 13:32:52 martin - * Revision 1.22.1.7.1.3 2011/04/20 11:34:28 martin - * Revision 1.22.1.7.1.2 2011/04/20 11:32:36 martin - * Revision 1.22.1.7.1.1 2011/04/19 15:31:31 martin - * Started modifications for PTP unicast master cfg. - * Revision 1.22.1.7 2011/04/19 10:02:37 martin - * Syntax fix. - * Revision 1.22.1.6 2011/04/19 09:57:00 martin - * Untabbified and removed trailing spaces. - * Revision 1.22.1.5 2011/03/21 08:32:18 martin - * Fixed compiler warning. - * Revision 1.22.1.4 2011/03/03 10:01:00 daniel - * Support configuring PTP roles. - * Revision 1.22.1.3 2011/02/18 13:35:59 daniel - * Revision 1.22.1.2 2011/02/18 13:35:11 daniel - * Revision 1.22.1.1 2011/02/18 11:27:29 daniel - * Preliminary support for configuring PTP parameters incl. Unicast + * Support build under Windows. * Bugfix: accept parameter keyword only when substring is found at the * start of the parameter string. + * Support configuring PTP parameters incl. unicast + * Warn if trying to handle serial port cfg but no serial port is supported. + * Basic support for programmable pulse outputs, including pulse shift feature. + * Yet incomplete support for synthesizer output. + * Use more functions from common library modules. + * Use codes and inline functions from mbgerror.h. + * Proper return codes and exit codes. * Revision 1.22 2009/09/29 14:58:18 martin * Unified and simplified parameter evaluation. * Updated version number to 3.4.0. @@ -126,15 +91,17 @@ // include Meinberg headers #include <mbgdevio.h> +#include <deviohlp.h> #include <pcpsmktm.h> #include <pcpsutil.h> -#include <parmpcps.h> -#include <parmgps.h> +#include <cfg_hlp.h> #include <myutil.h> #include <gpsutils.h> #include <cnv_wday.h> #include <toolutil.h> +#include <ptp_util.h> #include <lan_util.h> +#include <str_util.h> // include system headers #include <stdio.h> @@ -148,14 +115,17 @@ #define MBG_FIRST_COPYRIGHT_YEAR 2001 #define MBG_LAST_COPYRIGHT_YEAR 0 // use default -static const char *pname = "mbgctrl"; +#define RC_USAGE 1 -#define SIM_PTP_CFG ( 0 && DEBUG ) //##+++ +static const char *pname = "mbgctrl"; static char *dev_name; static int err_unicast_nsupp; -static const char str_unknown[] = "(unknown)"; + +static const char str_spc_not[] = " not"; +static const char str_spc_not_supp[] = " (not supported)"; +static const char str_spc_wildcard[] = " (wildcard)"; static TZDL tzdl_utc = DEFAULT_TZDL_UTC; static TZDL tzdl_cet_cest = DEFAULT_TZDL_CET_CEST_EN; @@ -167,158 +137,115 @@ static const char tz_info_cet_cest[] = TZ_INFO_CET_CEST_EN; static const char tz_info_eet_eest[] = TZ_INFO_EET_EEST_EN; static const char *mode_names[N_STR_MODE] = DEFAULT_ENG_MODE_NAMES; -static const char *time_scale_name[N_MBG_TIME_SCALE] = MBG_TIME_SCALE_STRS; + +static const char *time_scale_names[N_MBG_TIME_SCALE] = MBG_TIME_SCALE_STRS; #define _get_time_scale_name( _i ) \ - ( ( (_i) < N_MBG_TIME_SCALE ) ? time_scale_name[_i] : str_unknown ) + ( ( (_i) < N_MBG_TIME_SCALE ) ? time_scale_names[_i] : str_unknown ) + +static const char * const pout_mode_names_eng[N_POUT_MODES] = DEFAULT_ENG_POUT_NAMES; + +#define _get_pout_mode_name( _i ) \ + ( ( (_i) < N_POUT_MODES ) ? pout_mode_names_eng[_i] : str_unknown ) static const char no_gps_cmd[] = "does not support GPS commands"; static const char no_tzdl[] = "does not support configurable time zone"; static const char no_tz[] = "does not support time zones"; +static const char no_synth[] = "has no synthesizer output"; static const char no_event_time[] = "does not support event times"; static const char no_enable_flags[] = "does not support enable flags"; static const char no_time_scale[] = "does not support a configurable time scale"; -static const char no_lan_intf[] = "does not provide a LAN interface"; +static const char no_lan_intf[] = "has no LAN interface"; static const char no_ptp[] = "does not provide PTP"; static const char no_cab_len[] = "does not support antenna signal delay compensation"; -#define N_SUPP_UNICAST_MASTER 1 - - -#define DEFAULT_MC_SYNC_INTV_MIN -6 // [log2 s] -#define DEFAULT_MC_SYNC_INTV_MAX 6 // [log2 s] - -#define DEFAULT_MC_ANN_INTV_MIN -6 // [log2 s] -#define DEFAULT_MC_ANN_INTV_MAX 6 // [log2 s] - -#define DEFAULT_MC_DELAY_REQ_INTV_MIN -6 // [log2 s] -#define DEFAULT_MC_DELAY_REQ_INTV_MAX 6 // [log2 s] - - -#define DEFAULT_UC_SYNC_INTV_MIN -6 // [log2 s] -#define DEFAULT_UC_SYNC_INTV_MAX 6 // [log2 s] - -#define DEFAULT_UC_ANN_INTV_MIN -6 // [log2 s] -#define DEFAULT_UC_ANN_INTV_MAX 6 // [log2 s] - -#define DEFAULT_UC_DELAY_REQ_INTV_MIN -6 // [log2 s] -#define DEFAULT_UC_DELAY_REQ_INTV_MAX 6 // [log2 s] +/** + * @brief A type used to pass print control flags to functions + * + * @see ::CTRL_FLAG_MASKS + */ +typedef int CTRL_FLAGS; -#define DEFAULT_MC_SYNC_INTV 0 // [log2 s] -#define DEFAULT_MC_ANN_INTV 1 // [log2 s] -#define DEFAULT_MC_DELAY_REQ_INTV 3 // [log2 s] -#define DEFAULT_UC_SYNC_INTV 0 // [log2 s] -#define DEFAULT_UC_ANN_INTV 1 // [log2 s] -#define DEFAULT_UC_DELAY_REQ_INTV 3 // [log2 s] -#define DEFAULT_UC_MSG_DURATION 300 // [s] +/** + * @brief flag masks used with ::CTRL_FLAGS + * + * @see ::CTRL_FLAGS + */ +enum CTRL_FLAG_MASKS +{ + CTRL_PRINT_ALL = 0x01, + CTRL_PRINT_NEWLINES = 0x02, + CTRL_PRINT_IDX = 0x04, + CTRL_PRINT_ERR = 0x08, + CTRL_PRINT_PLUS = 0x10, + CTRL_NOT_SUPP = 0x20 +}; +struct OPT_HANDLER_SPEC_S; -#define DEFAULT_PTP_CFG_SETTINGS \ -{ \ - PTP_NW_PROT_BIT_UDP_IPV4, /* nw_prot */ \ - 0, /* profile */ \ - 0, /* domain_number */ \ - PTP_DELAY_MECH_BIT_E2E, /* delay_mech */ \ - PTP_ROLE_MULTICAST_SLAVE, /* ptp_role */ \ - 128, /* priority_1 */ \ - 128, /* priority_2 */ \ - 52, /* dflt_clk_class_unsync_cold */ \ - 7, /* dflt_clk_class_unsync_warm */ \ - 6, /* dflt_clk_class_sync_cold */ \ - 6, /* dflt_clk_class_sync_warm */ \ - 0, /* reserved_1 */ \ - 0, /* reserved_2 */ \ - DEFAULT_MC_SYNC_INTV, /* sync_intv [log2 s]*/ \ - DEFAULT_MC_ANN_INTV, /* ann_intv [log2 s] */ \ - DEFAULT_MC_DELAY_REQ_INTV, /* delay_req_intv [log2 s] */ \ - 0, /* upper_bound, not used */ \ - 0, /* lower_bound, not used */ \ - 0, /* reserved_3 */ \ - 0 /* flags */ \ -} +typedef int HELP_FNC( MBG_DEV_HANDLE, const PCPS_DEV *, const struct OPT_HANDLER_SPEC_S *, CTRL_FLAGS ); +typedef int SET_FNC( MBG_DEV_HANDLE, const char *, int ); +typedef int SHOW_FNC( MBG_DEV_HANDLE, const struct OPT_HANDLER_SPEC_S *, const PCPS_DEV *, const char * ); -//##++++++++++ -#define DEFAULT_PTP_SLAVE_SUPP_FLAGS 0 -#define DEFAULT_PTP_SLAVE_SUPP_NW_PROT 0 -#define DEFAULT_PTP_SLAVE_SUPP_PROFILES 0 -#define DEFAULT_PTP_SLAVE_SUPP_DELAY_MECH 0 - -#define DEFAULT_PTP_CFG_INFO_SLAVE \ -{ \ - DEFAULT_PTP_CFG_SETTINGS, /* ptp_cfg_settings */ \ - 2, /* ptp_proto_version */ \ - 0, /* reserved_1 */ \ - 0, /* reserved_2 */ \ - DEFAULT_MC_SYNC_INTV_MIN, /* sync_intv_min */ \ - DEFAULT_MC_SYNC_INTV_MAX, /* sync_intv_max */ \ - DEFAULT_MC_ANN_INTV_MIN, /* ann_intv_min */ \ - DEFAULT_MC_ANN_INTV_MIN, /* ann_intv_max */ \ - DEFAULT_MC_DELAY_REQ_INTV_MIN, /* delay_req_intv_min */ \ - DEFAULT_MC_DELAY_REQ_INTV_MIN, /* delay_req_intv_max */ \ - DEFAULT_PTP_SLAVE_SUPP_FLAGS, /* supp_flags */ \ - DEFAULT_PTP_SLAVE_SUPP_NW_PROT, /* supp_nw_prot */ \ - DEFAULT_PTP_SLAVE_SUPP_PROFILES, /* supp_profiles */ \ - DEFAULT_PTP_SLAVE_SUPP_DELAY_MECH /* supp_delay_mech */ \ -} +typedef struct OPT_HANDLER_SPEC_S +{ + const char *cmd_name; + MBG_CHK_SUPP_FNC *chk_supp_fnc; + HELP_FNC *help_fnc; + SET_FNC *set_fnc; + SHOW_FNC *show_fnc; + const char *cmd_info; + const char *not_supp_msg; + uint32_t flags; ///< see ::OPT_FLAG_MASKS -#define DEFAULT_PTP_UC_MASTER_CFG_LIMITS \ -{ \ - 1, /* n_supp_master */ \ - -6, /* sync_intv_min */ \ - 6, /* sync_intv_max */ \ - -6, /* ann_intv_min */ \ - 6, /* ann_intv_max */ \ - -6, /* delay_req_intv_min */ \ - 6, /* delay_req_intv_max */ \ - 0, /* reserved_0 */ \ - 0, /* supp_flags */ \ - 0 /* reserved_1 */ \ -} +} OPT_HANDLER_SPEC; -#define DEFAULT_PTP_UC_MASTER_SETTINGS \ -{ \ - "0.0.0.0", /* gm_host */ \ - PTP_CLOCK_ID_WILDCARD, /* gm_clock_id */ \ - PTP_PORT_ID_WILDCARD, /* gm_port_id */ \ - DEFAULT_UC_SYNC_INTV, /* sync_intv [log2 s] */ \ - DEFAULT_UC_ANN_INTV, /* ann_intv [log2 s] */ \ - DEFAULT_UC_DELAY_REQ_INTV, /* delay_req_intv [log2 s] */ \ - 0, /* fix_offset, [ns] */ \ - DEFAULT_UC_MSG_DURATION, /* message_duration [s] */ \ - 0, /* reserved_1 */ \ - 0 /* flags */ \ -} +enum OPT_FLAG_BITS +{ + OPT_SUPP_CMD_IDX_BIT, ///< e.g. COM0=, COM1=, etc. vs. TZ= + N_OPT_FLAG_BITS +}; +enum OPT_FLAG_MASKS +{ + OPT_SUPP_CMD_IDX = ( 1UL << OPT_SUPP_CMD_IDX_BIT ) ///< see ::OPT_SUPP_CMD_IDX_BIT +}; -#define DEFAULT_PTP_UC_MASTER_INFO \ -{ \ - DEFAULT_PTP_UC_MASTER_SETTINGS, /* settings */ \ - 0, /* reserved */ \ - 0 /* flags */ \ -} +OPT_HANDLER_SPEC ohs_pout = +{ + "POUT", // cmd_name + NULL, // chk_supp_fnc + NULL, // help_fnc + NULL, // set_fnc + NULL, // show_fnc + NULL, // cmd_info + NULL, // not_supp_msg + OPT_SUPP_CMD_IDX // flags +}; -#if SIM_PTP_CFG - static PTP_CFG_INFO sim_ptp_cfg_info = DEFAULT_PTP_CFG_INFO_SLAVE; - static PTP_UC_MASTER_CFG_LIMITS sim_ptp_uc_master_cfg_limits = DEFAULT_PTP_UC_MASTER_CFG_LIMITS; - static PTP_UC_MASTER_INFO sim_ptp_uc_master_info[N_SUPP_UNICAST_MASTER] = { DEFAULT_PTP_UC_MASTER_INFO }; -#endif +typedef struct +{ + int indent_1; + int indent_2; + int indent_3; + int comm_col_x; +} INDENTS; +const INDENTS usage_indents = { 2, 4, 6, 30 }; +const INDENTS usage_indents_detailed = { 4, 6, 8, 30 }; +const INDENTS show_indents = { 2, 4, 0, 0 }; -typedef struct -{ - PTP_CFG_INFO ptp_cfg_info; - PTP_UC_MASTER_CFG_LIMITS ptp_uc_master_cfg_limits; - ALL_PTP_UC_MASTER_INFO all_ptp_uc_master_info; -} ALL_PTP_CFG_INFO; +#define SHOW_INDENT_1 " " +#define SHOW_INDENT_2 " " @@ -372,6 +299,9 @@ static const char *nw_prot_short[] = PTP_NW_PROT_STRS_SHORT; static const char *ptp_roles[] = PTP_ROLE_STRS; static const char *ptp_roles_short[] = PTP_ROLE_STRS_SHORT; +static const PTP_CLOCK_ID clock_id_wildcard = PTP_CLOCK_ID_WILDCARD; + +//##+++++++++++++++++++ // If unicast is not supported for a PTP device then the device is definitely // a multicast slave, in which case index 0 returns the correct role name. #define _ptp_role_name( _i ) \ @@ -381,6 +311,194 @@ static const char *ptp_roles_short[] = PTP_ROLE_STRS_SHORT; ( ( (_i) < N_PTP_ROLES ) ? ptp_roles_short[_i] : str_unknown ) +static const char pout_name_mode[] = "MODE"; +static const char pout_name_len[] = "LEN"; +static const char pout_name_inv[] = "INV"; +static const char pout_name_ois[] = "OIS"; +static const char pout_name_shift[] = "SHIFT"; + + + + + +static /*HDR*/ +__attribute__( ( format( printf, 4, 5 ) ) ) +int usage_line( const INDENTS *p_ind, const OPT_HANDLER_SPEC *p_opt, + const char *cmd_parm, const char *cmd_comment_fmt, ... ) +{ + int n = 0; + + // print left margin, if not 0 + if ( p_ind->indent_1 ) + n += printf( "%*s", p_ind->indent_1, str_empty ); + + // print command name + if ( p_opt ) + n += printf( "%s", p_opt->cmd_name ); + + // print the command parameters, if specified + if ( cmd_parm ) + { + if ( p_opt && ( p_opt->flags & OPT_SUPP_CMD_IDX ) ) + n+= printf( "%s", "<n>" ); + + n += printf( "=%s", cmd_parm ); + } + + // print command comment which can be a format string + // expecting additional parameters + if ( cmd_comment_fmt ) + { + va_list arg_list; + + // indent the comment string + if ( p_ind->indent_2 ) + { + int w = p_ind->indent_2 - n; + + while ( w < 0 ) + w += 8; + + n += printf( "%*s", w, str_empty ); + } + + va_start( arg_list, cmd_comment_fmt ); + n += vprintf( cmd_comment_fmt, arg_list ); + va_end( arg_list ); + } + + n += printf( "\n" ); + + return n; + +} // usage_line + + + +static /*HDR*/ +int print_indent( int i ) +{ + int n = printf( "%*s", i, str_empty ); + + return n; + +} // print_indent + + + +static /*HDR*/ +__attribute__( ( format( printf, 2, 3 ) ) ) +int usage_note( int indent, const char *fmt, ... ) +{ + // print left margin, if not 0 + int n = print_indent( indent ); + + if ( fmt ) + { + va_list arg_list; + + va_start( arg_list, fmt ); + n += vprintf( fmt, arg_list ); + n += printf( "\n" ); + va_end( arg_list ); + } + + return n; + +} // usage_note + + + +typedef const char *(STR_FNC)( int idx ); + + +static /*HDR*/ +void print_bit_mask_list( const char *info_1, const char *info_2, uint32_t supp_mask, + int n_known, const char * const names[], STR_FNC *s_fnc, + int inst_idx, CTRL_FLAGS ctrl_flags, const INDENTS *p_ind ) +{ + const char *str_s_fnc = s_fnc ? s_fnc( inst_idx ) : str_empty; + + print_indent( p_ind->indent_2 ); + + if ( ctrl_flags & CTRL_PRINT_ALL ) + { + supp_mask = ( 1UL << n_known ) - 1; + + if ( supp_mask ) + printf( "Known %s%s: ", info_1, str_s_fnc ); + else + printf( "No %s%s known.", info_1, str_s_fnc ); + } + else + { + if ( supp_mask ) + { + printf( "%s", info_1 ); + + if ( info_2 ) + printf( " %s", info_2 ); + + #if defined( DEBUG ) + printf( " (%04lX)", (ulong) supp_mask ); + #endif + + printf( ":" ); + } + else + { + printf( "No %s.", info_1 ); + + if ( info_2 ) + printf( " %s", info_2 ); + + printf( "." ); + } + } + + + if ( supp_mask ) + { + int n_printed = 0; + int i; + const char *str_sep = ( ctrl_flags & CTRL_PRINT_PLUS ) ? "+" : ", "; + + for ( i = 0; i < n_known; i++ ) + { + const char *cp; + + if ( ( supp_mask & ( 1UL << i ) ) == 0 ) + continue; + + if ( names ) + cp = names[i]; + else + if ( s_fnc ) + cp = s_fnc( i ); + else + cp = str_empty; + + if ( ctrl_flags & ( CTRL_PRINT_NEWLINES | CTRL_PRINT_IDX ) ) + { + printf( "\n" ); + print_indent( p_ind->indent_3 ); + + if ( ctrl_flags & CTRL_PRINT_IDX ) + printf( "%i: ", i ); + + printf( "%s", cp ); + } + else + printf( "%s%s", n_printed ? str_sep : str_empty, cp ); + + n_printed++; + } + } + + printf( "\n" ); + +} // print_bit_mask_list + static /*HDR*/ @@ -397,7 +515,7 @@ int set_tz_code( MBG_DEV_HANDLE dh, PCPS_TZCODE tzcode, const char *s ) { int rc = mbg_set_tzcode( dh, &tzcode ); - if ( mbg_ioctl_err( rc, "mbg_set_tzcode" ) ) + if ( mbg_cond_err_msg( rc, "mbg_set_tzcode" ) ) return rc; printf( "The clock's time zone setting has been set to %s.\n", s ); @@ -413,7 +531,7 @@ int set_gps_tzdl( MBG_DEV_HANDLE dh, const TZDL *tzdl, const char *info ) { int rc = mbg_set_gps_tzdl( dh, tzdl ); - if ( mbg_ioctl_err( rc, "set_gps_tzdl" ) ) + if ( mbg_cond_err_msg( rc, "set_gps_tzdl" ) ) return rc; if ( info ) @@ -454,7 +572,7 @@ int set_timezone( MBG_DEV_HANDLE dh, const char *tz_name, const PCPS_DEV *p_dev else { printf( "** Unknown timezone name %s\n", tz_name ); - rc = 1; + rc = RC_USAGE; } if ( tz_info ) @@ -480,7 +598,7 @@ int show_tzdl_offs( MBG_DEV_HANDLE dh, const char *info ) TZDL tzdl; int rc = mbg_get_gps_tzdl( dh, &tzdl ); - if ( mbg_ioctl_err( rc, "mbg_get_gps_tzdl" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_gps_tzdl" ) ) return rc; printf( "%s timezone offset: UTC%+lis", info, (long) tzdl.offs ); @@ -513,6 +631,60 @@ int set_tzdl_offs( MBG_DEV_HANDLE dh, const char *s ) static /*HDR*/ +int show_synth( MBG_DEV_HANDLE dh, const char *info ) +{ + SYNTH synth; + int rc = mbg_get_synth( dh, &synth ); + + if ( mbg_cond_err_msg( rc, "mbg_get_synth" ) ) + return rc; + + printf( "%s synthesizer settings: freq %i.%iE%i Hz, phase %+i.%i deg", info, + synth.freq / 10, synth.freq % 10, synth.range, + synth.phase / 10, abs( synth.phase ) % 10 ); + +/* + int16_t freq; ///< four digits used; scale: 0.1 Hz; e.g. 1234 -> 123.4 Hz + int16_t range; ///< scale factor for freq; 0..::MAX_SYNTH_RANGE + int16_t phase; ///< -::MAX_SYNTH_PHASE..+::MAX_SYNTH_PHASE; >0 -> pulses later +*/ + return MBG_SUCCESS; + +} // show_synth + + + +static /*HDR*/ +int set_synth( MBG_DEV_HANDLE dh, const char *s ) +{ + SYNTH synth = { 0 }; + char *cp; + + long freq = strtol( s, &cp, 10 ) * 10; + + if ( *cp == '.' ) + { + long frac = strtol( ++cp, NULL, 10 ); + if ( frac < 0 || frac > 9 ) + goto fail; + + freq += frac; + } + + synth.freq = (int16_t) freq; + synth.range = 0; + synth.phase = 0; + + return mbg_set_synth( dh, &synth ); + +fail: + return MBG_ERR_INV_PARM; + +} // set_synth + + + +static /*HDR*/ int show_lan_intf( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info ) { IP4_SETTINGS ip4_settings; @@ -520,7 +692,7 @@ int show_lan_intf( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info ) int rc = mbg_get_ip4_settings( dh, &ip4_settings ); - if ( mbg_ioctl_err( rc, "mbg_get_ip4_settings" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_ip4_settings" ) ) return rc; printf( "On-board LAN interface settings:" ); @@ -551,66 +723,24 @@ int show_lan_intf( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info ) static /*HDR*/ -int mbg_get_all_ptp_cfg_info( MBG_DEV_HANDLE dh, ALL_PTP_CFG_INFO *p ) +const char *intv_str( int i ) { - int rc = MBG_SUCCESS; + static char s[20]; - memset( p, 0, sizeof( *p ) ); - -#if SIM_PTP_CFG - p->ptp_cfg_info = sim_ptp_cfg_info; -#else - rc = mbg_get_ptp_cfg_info( dh, &p->ptp_cfg_info ); -#endif - - if ( mbg_ioctl_err( rc, "mbg_get_ptp_cfg_info" ) ) - goto ret; - - - if ( p->ptp_cfg_info.supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) - { - #if SIM_PTP_CFG - p->ptp_uc_master_cfg_limits = sim_ptp_uc_master_cfg_limits; - #else - rc = mbg_get_ptp_uc_master_cfg_limits( dh, &p->ptp_uc_master_cfg_limits ); - #endif - - if ( mbg_ioctl_err( rc, "mbg_get_ptp_uc_master_cfg_limits" ) ) - goto ret; - - - if ( p->ptp_uc_master_cfg_limits.n_supp_master > MAX_PARM_PTP_UC_MASTER ) - { - printf( "The number of PTP unicast masters supported by this device (%i)\n" - "exceeds the number of unicast masters supporterd by this driver (%i)\n", - p->ptp_uc_master_cfg_limits.n_supp_master, MAX_PARM_PTP_UC_MASTER ); - rc = MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP; - goto ret; - } + int abs_i = abs( i ); + ulong ul; + // Currently the valid range is [-7:+7] + if ( abs_i > 7 ) + return str_empty; - #if SIM_PTP_CFG - { - int i; + ul = 1UL << abs_i; - for ( i = 0; i < p->ptp_uc_master_cfg_limits.n_supp_master; i++ ) - { - PTP_UC_MASTER_INFO_IDX *pi = &p->all_ptp_uc_master_info[i]; - pi->idx = i; - pi->info = sim_ptp_uc_master_info[i]; - } - } - #else - rc = mbg_get_all_ptp_uc_master_info( dh, p->all_ptp_uc_master_info, &p->ptp_uc_master_cfg_limits ); - #endif - if ( mbg_ioctl_err( rc, "mbg_get_all_ptp_uc_master_info" ) ) - goto ret; - } + snprintf_safe( s, sizeof( s ), " (%s%lu s)", ( i < 0 ) ? "1/" : str_empty, ul ); -ret: - return rc; + return s; -} // mbg_get_all_ptp_cfg_info +} // intv_str @@ -618,28 +748,34 @@ static /*HDR*/ int show_ptp_cfg( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info ) { ALL_PTP_CFG_INFO all_ptp_cfg_info; + PTP_CFG_INFO *pi = &all_ptp_cfg_info.ptp_cfg_info; + PTP_CFG_SETTINGS *ps = &pi->settings; char ws[256]; int unicast_supported; int idx; int rc = mbg_get_all_ptp_cfg_info( dh, &all_ptp_cfg_info ); - if ( rc < 0 ) + if ( mbg_cond_err_msg( rc, "mbg_get_all_ptp_cfg_info" ) ) return rc; - unicast_supported = ( all_ptp_cfg_info.ptp_cfg_info.supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) != 0; + unicast_supported = ( pi->supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) != 0; printf( "\nPTP configuration:\n"); - idx = all_ptp_cfg_info.ptp_cfg_info.settings.ptp_role; + idx = ps->ptp_role; printf( " PTP Role : %s (%s)\n", _ptp_role_name_short( idx ), _ptp_role_name( idx ) ); - idx = all_ptp_cfg_info.ptp_cfg_info.settings.nw_prot; + idx = ps->nw_prot; printf( " Network Protocol: %s (%s)\n", nw_prot_short[idx], nw_prot[idx] ); - printf( " Delay Mechanism : %s\n", delay_mech[all_ptp_cfg_info.ptp_cfg_info.settings.delay_mech] ); - printf( " Domain Number : %d\n", all_ptp_cfg_info.ptp_cfg_info.settings.domain_number ); - printf( " V1 HW Compat. : %d\n", ( all_ptp_cfg_info.ptp_cfg_info.settings.flags & PTP_CFG_MSK_V1_HW_COMPAT ) ? 1 : 0 ); + printf( " Delay Mechanism : %s\n", delay_mech[ps->delay_mech] ); + printf( " Domain Number : %d\n", ps->domain_number ); + printf( " V1 HW Compat. : %d\n", ( ps->flags & PTP_CFG_MSK_V1_HW_COMPAT ) ? 1 : 0 ); + + printf( " Sync Msg Intv. : % i%s\n", ps->sync_intv, intv_str( ps->sync_intv) ); + printf( " Ann. Msg Intv. : % i%s\n", ps->ann_intv, intv_str( ps->ann_intv ) ); + printf( " Dly. Req. Intv. : % i%s\n", ps->delay_req_intv, intv_str( ps->delay_req_intv ) ); if ( unicast_supported ) { @@ -648,27 +784,33 @@ int show_ptp_cfg( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info ) for ( i = 0; i < p_uc_limits->n_supp_master; i++ ) { - PTP_UC_MASTER_SETTINGS *p = &all_ptp_cfg_info.all_ptp_uc_master_info[i].info.settings; + PTP_UC_MASTER_SETTINGS *p = &all_ptp_cfg_info.all_ptp_uc_master_info_idx[i].info.settings; - printf( "\nPTP unicast master" ); + printf( "\nConfigured PTP unicast master" ); if ( p_uc_limits->n_supp_master > 1 ) printf( " %i", i ); + if ( ps->ptp_role == PTP_ROLE_MULTICAST_SLAVE ) + printf( " (not used for this role)" ); + printf( ":\n"); printf( " GM Host: %s\n", p->gm_host ); snprint_octets( ws, sizeof( ws ), p->gm_clock_id.b, sizeof( p->gm_clock_id.b ), MAC_SEP_CHAR, NULL ); - printf( " GM Clock ID: %s\n", ws ); + printf( " GM Clock ID: %s%s\n", ws, + ( memcmp( &p->gm_clock_id, &clock_id_wildcard, sizeof( p->gm_clock_id ) ) == 0 ) ? + str_spc_wildcard : str_empty ); - printf( " GM Port ID: %d\n\n", p->gm_port_id ); - printf( " Sync Msg Interval [2^x s]: %i\n", p->sync_intv ); - printf( " Ann. Msg Interval [2^x s]: %i\n", p->ann_intv ); - printf( " DelReq Msg Interval [2^x s]: %i\n", p->delay_req_intv ); - printf( " Message Duration: %i s\n", p->message_duration ); - } + printf( " GM Port ID: %d%s\n", p->gm_port_id, + ( p->gm_port_id == PTP_PORT_ID_WILDCARD ) ? str_spc_wildcard : str_empty ); + printf( " Sync Msg Intv. : % i%s\n", p->sync_intv, intv_str( p->sync_intv ) ); + printf( " Ann. Msg Intv. : % i%s\n", p->ann_intv, intv_str( p->ann_intv ) ); + printf( " Dly. Req. Intv. : % i%s\n", p->delay_req_intv, intv_str( p->delay_req_intv ) ); + printf( " Message Duration: %i s\n", p->message_duration ); + } } return MBG_SUCCESS; @@ -726,9 +868,9 @@ static /*HDR*/ * @param p A pointer to a (char *) which is set to the beginning * of the value part of a parameter string * - * @return <0 Syntax error, i.e. missing colon - * 0 No error. If parameter has been found then *p set - * to the parameter value, else to NULL. + * @return ::MBG_SUCCESS on success. If parameter has been found then + * @p *p is set to the parameter value, else to NULL. + * ::MBG_ERR_PARM_FMT if syntax error, i.e. missing colon. */ int chk_parm_name( const char *arg, const char *id, char **p ) { @@ -739,7 +881,7 @@ int chk_parm_name( const char *arg, const char *id, char **p ) cp += strlen( id ); if ( *cp != ':' ) - return -1; + return MBG_ERR_PARM_FMT; cp++; } @@ -747,7 +889,7 @@ int chk_parm_name( const char *arg, const char *id, char **p ) if ( p ) *p = cp; // may be NULL - return 0; + return MBG_SUCCESS; } // chk_parm_name @@ -821,8 +963,8 @@ int chk_int16_parm( const char *arg, const char *id, int16_t *p, int16_t range_m char *cp; int idx = chk_parm_name( arg, id, &cp ); - if ( idx < 0 ) // parameter error - return -1; + if ( mbg_rc_is_error( idx ) ) // parameter error + return idx; if ( cp ) // parameter found { @@ -835,7 +977,7 @@ int chk_int16_parm( const char *arg, const char *id, int16_t *p, int16_t range_m if ( ( tmp < range_min ) || ( tmp > range_max ) ) { printf( "error: %s %i out of range (%i..%i)\n", info, tmp, range_min, range_max ); - return -1; + return MBG_ERR_RANGE; } *p = tmp; @@ -852,7 +994,7 @@ int chk_int16_parm( const char *arg, const char *id, int16_t *p, int16_t range_m static /*HDR*/ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) { - ALL_PTP_CFG_INFO all_ptp_cfg_info; + ALL_PTP_CFG_INFO all_ptp_cfg_info = { { { 0 } } }; ALL_PTP_CFG_INFO prv_all_ptp_cfg_info; PTP_CFG_INFO *p_info; PTP_CFG_SETTINGS *p_settings; @@ -866,8 +1008,7 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) int idx; int unicast_supported; int uc_master_idx = 0; - int16_t tmp_int16; - + const char *err_info = NULL; int rc = mbg_get_all_ptp_cfg_info( dh, &all_ptp_cfg_info ); if ( rc < 0 ) @@ -884,8 +1025,8 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) unicast_supported = ( p_info->supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) != 0; p_uc_limits = &all_ptp_cfg_info.ptp_uc_master_cfg_limits; - // The pointers below need to be updated wnenever uc_master_idx is changed - p_uc_info = &all_ptp_cfg_info.all_ptp_uc_master_info[uc_master_idx].info; + // The pointers below need to be updated whenever uc_master_idx is changed + p_uc_info = &all_ptp_cfg_info.all_ptp_uc_master_info_idx[uc_master_idx].info; p_uc_settings = &p_uc_info->settings; @@ -896,8 +1037,10 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) p_settings->nw_prot = idx; else if ( idx < -1 ) + { + err_info = ptp_name_net; goto fail; - + } // Delay Mechanism idx = chk_tbl_parm( arg, ptp_name_del, delay_mech, N_PTP_DELAY_MECH, p_info->supp_delay_mech, "delay mechanism" ); @@ -906,19 +1049,25 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) p_settings->delay_mech = idx; else if ( idx < -1 ) + { + err_info = ptp_name_del; goto fail; + } // Domain Number idx = chk_parm_name( arg, ptp_name_dom, &cp ); - if ( idx < 0 ) // parameter error + if ( mbg_rc_is_error( idx ) ) // parameter error + { + err_info = ptp_name_dom; goto fail; + } if ( cp ) // parameter found { idx = atoi( cp ); - //##+++++ must check range!! + // TODO Must check range!! p_settings->domain_number = idx; } @@ -926,8 +1075,11 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) // V1 Hardware compatibility flag idx = chk_parm_name( arg, ptp_name_v1, &cp ); - if ( idx < 0 ) // parameter error + if ( mbg_rc_is_error( idx ) ) // parameter error + { + err_info = ptp_name_v1; goto fail; + } if ( cp ) // parameter found { @@ -953,7 +1105,7 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) //---- unicast stuff ---- // PTP role - supp_mask = _get_supp_ptp_role_idx_msk( p_info->supp_flags ); + supp_mask = get_supp_ptp_role_mask( p_info->supp_flags ); idx = chk_tbl_parm( arg, ptp_name_role, ptp_roles_short, N_PTP_ROLES, supp_mask, "PTP role" ); if ( idx >= 0 ) // valid parameter found @@ -965,14 +1117,20 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) } else if ( idx < -1 ) // parameter error + { + err_info = ptp_name_role; goto fail; + } // GM Host idx = chk_parm_name( arg, ptp_name_gmip, &cp ); - if ( idx < 0 ) // parameter error + if ( mbg_rc_is_error( idx ) ) // parameter error + { + err_info = ptp_name_gmip; goto fail; + } if ( cp ) // parameter found { @@ -982,7 +1140,7 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) { // currently IP addresses are accepted only, so check for // a valid IPv4 address - if ( str_to_ip4_addr( &ip4addr, cp ) ) + if ( str_to_ip4_addr( &ip4addr, cp ) > 0 ) { snprint_ip4_addr( ws, sizeof( ws ), &ip4addr, NULL ); printf( " GM IP Address: %s\n", ws ); @@ -991,7 +1149,10 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) strcpy( p_uc_settings->gm_host, ws ); } else + { + err_info = ptp_name_gmip; goto fail; + } } } @@ -999,8 +1160,11 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) // GM Clock ID idx = chk_parm_name( arg, ptp_name_gmid, &cp ); - if ( idx < 0 ) // parameter error + if ( mbg_rc_is_error( idx ) ) // parameter error + { + err_info = ptp_name_gmid; goto fail; + } if ( cp ) // parameter found { @@ -1009,21 +1173,27 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) else { PTP_CLOCK_ID gm_clock_id; - idx = str_to_octets( gm_clock_id.b, sizeof( gm_clock_id.b ), cp ); + + // Check if specified GM ID is wildcard. + if ( *cp == '*' ) // TODO check if next char is separator + { + gm_clock_id = clock_id_wildcard; + idx = sizeof( gm_clock_id ); + } + else + idx = str_to_octets( gm_clock_id.b, sizeof( gm_clock_id.b ), cp ); if ( idx != sizeof( gm_clock_id ) ) { printf( "Syntax error in specified GM clock ID\n" ); goto fail; } - else - { - p_uc_settings->gm_clock_id = gm_clock_id; - snprint_octets( ws, sizeof( ws ), p_uc_settings->gm_clock_id.b, - sizeof( p_uc_settings->gm_clock_id.b ), MAC_SEP_CHAR, NULL ); - printf( " setting GM Clock ID: %s\n", ws ); - } + p_uc_settings->gm_clock_id = gm_clock_id; + + snprint_octets( ws, sizeof( ws ), p_uc_settings->gm_clock_id.b, + sizeof( p_uc_settings->gm_clock_id.b ), MAC_SEP_CHAR, NULL ); + printf( " setting GM Clock ID: %s\n", ws ); } } @@ -1031,8 +1201,11 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) // GM Target Port ID idx = chk_parm_name( arg, ptp_name_pid, &cp ); - if ( idx < 0 ) // parameter error + if ( mbg_rc_is_error( idx ) ) // parameter error + { + err_info = ptp_name_pid; goto fail; + } if ( cp ) // parameter found { @@ -1040,95 +1213,87 @@ int set_ptp_cfg( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) err_unicast_nsupp = 1; else { - p_uc_settings->gm_port_id = strtoul( cp, NULL, 0 ); - printf( " setting GM port id: %d\n", p_uc_settings->gm_port_id ); + // Check if specified Port ID is wildcard. + if ( *cp == '*' ) // TODO check if next char is separator + p_uc_settings->gm_port_id = PTP_PORT_ID_WILDCARD; + else + p_uc_settings->gm_port_id = (PTP_PORT_ID) strtoul( cp, NULL, 0 ); + + printf( " setting GM port id: %d%s\n", p_uc_settings->gm_port_id, + ( p_uc_settings->gm_port_id == PTP_PORT_ID_WILDCARD ) ? str_spc_wildcard : str_empty ); } } // Sync Message Rate - idx = chk_int16_parm( arg, ptp_name_smi, &p_uc_settings->sync_intv, + idx = chk_int16_parm( arg, ptp_name_smi, + ( p_settings->ptp_role == PTP_ROLE_MULTICAST_SLAVE ) ? + &p_settings->sync_intv : &p_uc_settings->sync_intv, p_uc_limits->sync_intv_min, p_uc_limits->sync_intv_max, - unicast_supported, "sync intv." ); + 1, "sync intv." ); if ( idx < 0 ) + { + err_info = ptp_name_smi; goto fail; + } // Announce Message Rate - idx = chk_int16_parm( arg, ptp_name_ami, &p_uc_settings->ann_intv, + idx = chk_int16_parm( arg, ptp_name_ami, + ( p_settings->ptp_role == PTP_ROLE_MULTICAST_SLAVE ) ? + &p_settings->ann_intv : &p_uc_settings->ann_intv, p_uc_limits->ann_intv_min, p_uc_limits->ann_intv_max, - unicast_supported, "ann. intv." ); + 1, "ann. intv." ); if ( idx < 0 ) + { + err_info = ptp_name_ami; goto fail; + } - // Delay Message Rate - idx = chk_int16_parm( arg, ptp_name_dri, &p_uc_settings->delay_req_intv, + // Delay Request Interval Rate + idx = chk_int16_parm( arg, ptp_name_dri, + ( p_settings->ptp_role == PTP_ROLE_MULTICAST_SLAVE ) ? + &p_settings->delay_req_intv : &p_uc_settings->delay_req_intv, p_uc_limits->delay_req_intv_min, p_uc_limits->delay_req_intv_max, - unicast_supported, "delay req. intv." ); + 1, "delay req. intv." ); if ( idx < 0 ) + { + err_info = ptp_name_dri; goto fail; + } + // Message Duration - tmp_int16 = p_uc_settings->message_duration; - idx = chk_int16_parm( arg, ptp_name_dur, &tmp_int16, + idx = chk_int16_parm( arg, ptp_name_dur, (int16_t *) &p_uc_settings->message_duration, PTP_UC_MSG_DURATION_MIN, PTP_UC_MSG_DURATION_MAX, unicast_supported, "msg. duration" ); if ( idx < 0 ) + { + err_info = ptp_name_dur; goto fail; - - p_uc_settings->message_duration = tmp_int16; - -#if 0 //##++++++++++++ - - cp = strstr( arg, ptp_name_dur ); - - if ( cp != NULL ) - { - l = strlen( ptp_name_dur ); - - if ( *(cp+l) != ':' ) - goto fail; // parameter syntax error: name not followed by colon - - l++; - - ptp_unicast_settings.message_duration = atoi( cp+l ); - printf( " setting message duration: %i seconds\n", ptp_unicast_settings.message_duration ); - } -#endif - - -#if SIM_PTP_CFG - sim_ptp_cfg_info.settings = *p_settings; - rc = 0; -#else - rc = mbg_set_ptp_cfg_settings( dh, p_settings ); -#endif - - if ( mbg_ioctl_err( rc, "mbg_set_ptp_cfg_settings" ) ) - return rc; + } -#if 0 //##+++++++++ - if ( unicast_supported ) + if ( memcmp( &all_ptp_cfg_info, &prv_all_ptp_cfg_info, sizeof( all_ptp_cfg_info ) ) != 0 ) { - #if SIM_PTP_CFG - #error test - rc = MBG_SUCCESS; - #else - rc = mbg_set_ptp_unicast_cfg_settings( dh, &ptp_unicast_settings ); - #endif - if ( mbg_ioctl_err( rc, "mbg_set_ptp_unicast_cfg_settings" ) ) + rc = mbg_save_all_ptp_cfg_info( dh, &all_ptp_cfg_info ); + + if ( mbg_cond_err_msg( rc, "mbg_save_all_ptp_cfg_info" ) ) return rc; } -#endif return MBG_SUCCESS; fail: - printf( "Syntax error in argument!\n" ); + printf( "Invalid parameter in argument" ); + + if ( err_info ) + printf( " %s", err_info ); + + printf( "!\n" ); return MBG_ERR_CFG; @@ -1181,7 +1346,7 @@ int set_lan_intf( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) int rc = mbg_get_ip4_settings( dh, &prv_ip4_settings ); - if ( mbg_ioctl_err( rc, "mbg_get_ip4_settings" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_ip4_settings" ) ) return rc; if ( strcmp( arg, "DHCP" ) == 0 ) @@ -1262,7 +1427,7 @@ done: // now check static configuration save: rc = mbg_set_ip4_settings( dh, &ip4_settings ); - if ( mbg_ioctl_err( rc, "mbg_set_ip4_settings" ) ) + if ( mbg_cond_err_msg( rc, "mbg_set_ip4_settings" ) ) return rc; return MBG_SUCCESS; @@ -1312,7 +1477,7 @@ int set_gps_pos( MBG_DEV_HANDLE dh, const char *gp ) rc = mbg_set_gps_pos_lla ( dh, new_pos_lla ); - if ( mbg_ioctl_err( rc, "mbg_set_gps_pos_lla" ) ) + if ( mbg_cond_err_msg( rc, "mbg_set_gps_pos_lla" ) ) return rc; printf( "The clock's receiver position has been set to lat=%+.4f, lon=%+.4f, alt=%.0fm\n", @@ -1353,7 +1518,7 @@ int set_date_time( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, { rc = mbg_get_time( dh, &u.t ); - if ( mbg_ioctl_err( rc, "mbg_get_time" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_time" ) ) return rc; } @@ -1439,7 +1604,7 @@ int set_date_time( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, rc = mbg_set_gps_time( dh, &ttm ); - if ( mbg_ioctl_err( rc, "mbg_set_gps_time" ) ) + if ( mbg_cond_err_msg( rc, "mbg_set_gps_time" ) ) return rc; } else // is not a GPS card @@ -1475,7 +1640,7 @@ int set_date_time( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, rc = mbg_set_time( dh, &u.stime ); - if ( mbg_ioctl_err( rc, "mbg_set_time" ) ) + if ( mbg_cond_err_msg( rc, "mbg_set_time" ) ) return rc; } @@ -1488,26 +1653,34 @@ int set_date_time( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, static /*HDR*/ -void check_setup_receiver_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, - RECEIVER_INFO *p_ri ) +int check_setup_receiver_info( MBG_DEV_HANDLE dh, RECEIVER_INFO *p_ri ) { + int rc = MBG_SUCCESS; + // Set up the RECEIVER_INFO structure only if this has not been done // before. Check the ticks_per_sec field to see if the structure // has already been set up or not. - if ( p_ri->ticks_per_sec == 0 ) - mbg_setup_receiver_info( dh, p_dev, p_ri ); + if ( p_ri->ticks_per_sec == 0 && p_ri->model_code == 0 ) + { + rc = mbg_setup_receiver_info( dh, NULL, p_ri ); + mbg_cond_err_msg( rc, "mbg_setup_receiver_info" ); + } + + return rc; } // check_setup_receiver_info static /*HDR*/ +// returns a negative error code on failure, or the number of supported COM ports on success int check_get_receiver_port_cfg( MBG_DEV_HANDLE dh, RECEIVER_PORT_CFG *p_rpcfg, const PCPS_DEV *p_dev, RECEIVER_INFO *p_ri ) { - int rc = MBG_SUCCESS; + int rc = check_setup_receiver_info( dh, p_ri ); - check_setup_receiver_info( dh, p_dev, p_ri ); + if ( mbg_rc_is_error( rc ) ) + goto out; // Set up the RECEIVER_PORT_CFG structure only if this has not been done // before. Check whether the number of ports is > 0 and the first port's @@ -1516,10 +1689,13 @@ int check_get_receiver_port_cfg( MBG_DEV_HANDLE dh, RECEIVER_PORT_CFG *p_rpcfg, ( p_rpcfg->pii[0].port_info.port_settings.parm.baud_rate == 0 ) ) { rc = mbg_get_serial_settings( dh, p_dev, p_rpcfg, p_ri ); - - mbg_ioctl_err( rc, "mbg_get_serial_settings" ); + mbg_cond_err_msg( rc, "mbg_get_serial_settings" ); } + if ( mbg_rc_is_success( rc ) ) + rc = p_ri->n_com_ports; + +out: return rc; } // check_get_receiver_port_cfg @@ -1638,7 +1814,7 @@ int save_serial_settings( MBG_DEV_HANDLE dh, unsigned int port_num, const char * // load current settings and supported settings rc = mbg_get_serial_settings( dh, p_dev, &rpcfg, p_ri ); - if ( mbg_ioctl_err( rc, "mbg_get_serial_settings" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_serial_settings" ) ) return rc; @@ -1676,7 +1852,7 @@ int save_serial_settings( MBG_DEV_HANDLE dh, unsigned int port_num, const char * ul = strtoul( cp, &p_tail, 10 ); if ( p_tail != cp ) - p_ps->str_type = ul; + p_ps->str_type = (uint8_t) ul; // TODO check range ? cp = p_tail; @@ -1689,7 +1865,7 @@ int save_serial_settings( MBG_DEV_HANDLE dh, unsigned int port_num, const char * ul = strtoul( cp, &p_tail, 10 ); if ( p_tail != cp ) - p_ps->mode = ul; + p_ps->mode = (uint8_t) ul; // TODO check range ? done_parm_str: @@ -1706,7 +1882,7 @@ done_parm_str: // save new parameters rc = mbg_save_serial_settings( dh, p_dev, &rpcfg, port_num ); - if ( mbg_ioctl_err( rc, "mbg_save_serial_settings" ) ) + if ( mbg_cond_err_msg( rc, "mbg_save_serial_settings" ) ) return rc; @@ -1725,6 +1901,479 @@ invalid: static /*HDR*/ +// returns a negative error code on failure, or the number of supported programmable pulse outputs on success +int check_get_pout_cfg( MBG_DEV_HANDLE dh, ALL_POUT_INFO_IDX api, RECEIVER_INFO *p_ri ) +{ + int rc = check_setup_receiver_info( dh, p_ri ); + + // Set up the ALL_POUT_INFO_IDX structure only if this has not been done + // before. Check whether the number of ports is > 0 and the first port's + // baud rate is still 0 to see if the structure has already been set up. + if ( ( p_ri->n_prg_out > 0 ) && + ( api[0].pout_info.supp_modes == 0 ) ) + { + rc = mbg_get_gps_all_pout_info( dh, api, p_ri ); + mbg_cond_err_msg( rc, "mbg_get_gps_all_pout_info" ); + } + + if ( mbg_rc_is_success( rc ) ) + rc = p_ri->n_prg_out; + + return rc; + +} // check_get_pout_cfg + + + +static /*HDR*/ +int help_pout_arg( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, + const OPT_HANDLER_SPEC *p_opt, CTRL_FLAGS ctrl_flags ) +{ + const INDENTS *p_ind = &usage_indents; + const INDENTS *p_ind_detailed = &usage_indents_detailed; + int rc = MBG_SUCCESS; + int i; + + usage_line( p_ind, p_opt, NULL, "Show settings of the programmable output(s)" ); + usage_line( p_ind, p_opt, "MODE:<m>[,LEN:<l>][,INV:<i>][,OIS:<o>][,SHIFT:<s>]", "Configure programmable output <n>" ); // ### TODO + + printf( "\n" + " where:\n" ); + + printf( " MODE:<m> Specifies the programmable output mode with index <m>, see mbgctrl -?.\n" + " Please note that subsequent parameters may only be appropriate for specific modes.\n\n" ); + + printf( " LEN:<l> Specifies the pulse lenght for modes that support this.\n" + " <l> is an integer value in 10 ms units, i.e. <l> = 20 yields 200 ms.\n\n" ); + + printf( " INV:<i> \"Inverted\" flag specifying if the output level is to be inverted,\n" + " if the output supports this.\n" + " Values for <i>: 1 invert output level, 0 don't invert.\n\n" ); + + printf( " OIS:<o> \"Only If Sync\" flag specifying if the output is to be enabled ONLY\n" + " while the device is synchronized, if the output supports this.\n" + " Values for <o>: 1 enable this feature, 0 disable this feature\n" + " NOTE: This overrides the Enable Flags settings (parameter \"EF\").\n" + " The output is enabled ONLY when the device state changes to \"synchronized\"\n" + " after power-up, and is disabled again when the device enters holdover mode,\n" + " i.e. the reference signal is lost.\n\n" ); + + printf( " SHIFT:<s> Specifies a phase shift of the output slope, if the output supports this.\n" + " <s> is an integer value, in nanoseconds.\n" + " The maximum range is %+li to %+li ns,\n" + " corresponding to %+li to %+li ms.\n" + " The effective resolution depends on the resolution of the device's internal clock,\n" + " which may be e.g. 10 or 20 ns, depending on the device type. See mbgctrl -?.\n\n", + (long) DEFAULT_POUT_PULSE_SHIFT_MIN, (long) DEFAULT_POUT_PULSE_SHIFT_MAX, + (long) DEFAULT_POUT_PULSE_SHIFT_MIN / 1000L, (long) DEFAULT_POUT_PULSE_SHIFT_MAX / 1000L ); + + + if ( dh != MBG_INVALID_DEV_HANDLE ) + { + RECEIVER_INFO ri = { 0 }; + ALL_POUT_INFO_IDX api = { { 0 } }; + int n_pout; + + rc = check_get_pout_cfg( dh, api, &ri ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + n_pout = rc; + + for ( i = 0; i < n_pout; i++ ) + { + const POUT_INFO *pi = &api[i].pout_info; + + printf( "%*s", p_ind->indent_2, str_empty ); + printf( "Programmable output %i:\n", i ); + + print_bit_mask_list( "Supported modes", NULL, pi->supp_modes, + N_POUT_MODES, pout_mode_names_eng, NULL, 0, + ctrl_flags | CTRL_PRINT_IDX, p_ind_detailed ); + + // ### TODO evaluate more properties + usage_note( p_ind_detailed->indent_2, "Output level can%s be inverted.", + ( pi->flags & POUT_NOT_INVERTIBLE ) ? str_spc_not : str_empty ); + + if ( pi->flags & POUT_FIXED_PULSE_LEN ) + usage_note( p_ind_detailed->indent_2, "Pulse length is fixed and can't be changed." ); + + if ( pi->flags & POUT_SUPP_PULSE_SHIFT ) + usage_note( p_ind_detailed->indent_2, "Output supports pulse shift with resolution %u ns.", + pi->pulse_shift_res ); + + printf( "\n" ); + } + } + else + { +#if 0 // ### TODO + print_bit_mask_list( "modes", str_supp_by_dev, tsi.supp_scales, + N_MBG_TIME_SCALE, time_scale_names, NULL, ctrl_flags | CTRL_PRINT_IDX ); +#endif + } + +out: + return rc; + +} // help_pout_arg + + + +static /*HDR*/ +int eval_pout( MBG_DEV_HANDLE dh, const char *s, int inst_num ) +{ + RECEIVER_INFO ri = { 0 }; + ALL_POUT_INFO_IDX api = { { 0 } }; + ALL_POUT_INFO_IDX prv_api; + POUT_INFO *p_pi = &api[inst_num].pout_info; // ### TODO check inst_num range? + POUT_SETTINGS *p_ps = &p_pi->pout_settings; + const char *err_info = NULL; + char *cp; + int n_pout; + int idx; + int i; + int rc = check_get_pout_cfg( dh, api, &ri ); + + if ( mbg_cond_err_msg( rc, "check_get_pout_cfg" ) ) + return rc; + + n_pout = rc; // Contains now the number of programmable pulse outputs + + // save current settings + memcpy( prv_api, api, sizeof( prv_api ) ); + + // Mode + idx = chk_parm_name( s, pout_name_mode, &cp ); + + if ( mbg_rc_is_error( idx ) ) // parameter error + { + err_info = pout_name_mode; + goto fail; + } + + if ( cp ) // parameter found + { + idx = atoi( cp ); + + if ( idx < 0 || idx >= N_POUT_MODES ) + { + printf( "Programmable output mode %i out of range (0..%i)\n", idx, N_POUT_MODES - 1 ); + goto fail; + } + + if ( !_is_supported( idx, p_pi->supp_modes ) ) + { + printf( "Programmable output mode %i (%s) not supported for output %i\n", + idx, _get_pout_mode_name( idx ), inst_num ); + goto fail; + } + + p_ps->mode = idx; + printf( "Programmable output mode for output %i changed to %s (%i)\n", + inst_num, _get_pout_mode_name( p_ps->mode ), p_ps->mode ); + } + + + // Pulse len + idx = chk_parm_name( s, pout_name_len, &cp ); + + if ( mbg_rc_is_error( idx ) ) // parameter error + { + err_info = pout_name_len; + goto fail; + } + + if ( cp ) // parameter found + { + idx = atoi( cp ); + + if ( !_is_supported( p_ps->mode, POUT_MODES_MODE_PARAM_AS_PULSE_LEN ) ) + { + printf( "Pulse length parameter not supported for mode \"%s\"\n", + _get_pout_mode_name( p_ps->mode ) ); + goto fail; + } + + if ( idx < 0 || idx >= MAX_POUT_PULSE_LEN ) + { + printf( "Pulse length %i out of range (1..%i)\n", idx, MAX_POUT_PULSE_LEN ); + goto fail; + } + + if ( p_pi->flags & POUT_FIXED_PULSE_LEN ) + { + if ( idx != p_ps->mode_param ) + printf( "Warning. pulse length %i (%i ms) is fix and can't be changed!\n", + p_ps->mode_param, p_ps->mode_param * 10 ); + } + else + { + p_ps->mode_param = idx; + printf( "Pulse length for programmable output %i changed to %i (%i ms)\n", + inst_num, p_ps->mode_param, p_ps->mode_param * 10 ); + } + } + + + // "Inverted" flag + idx = chk_parm_name( s, pout_name_inv, &cp ); + + if ( mbg_rc_is_error( idx ) ) // parameter error + { + err_info = pout_name_inv; + goto fail; + } + + if ( cp ) // parameter found + { + idx = atoi( cp ); + + if ( idx < 0 || idx > 1 ) + { + printf( "Invalid flag value %i for parameter %s, must be 0 or 1\n", idx, pout_name_inv ); + goto fail; + } + + if ( p_pi->flags & POUT_NOT_INVERTIBLE ) + { + if ( idx ) + { + printf( "Warning: Output level can't be inverted for output %i\n", inst_num ); + goto fail; + } + } + + if ( idx ) + p_ps->flags |= POUT_INVERTED; + else + p_ps->flags &= ~POUT_INVERTED; + + printf( "Output level for output %i%s inverted\n", + inst_num, idx ? str_empty : str_spc_not ); + } + + + // "Only If Sync" flag + idx = chk_parm_name( s, pout_name_ois, &cp ); + + if ( mbg_rc_is_error( idx ) ) // parameter error + { + err_info = pout_name_ois; + goto fail; + } + + if ( cp ) // parameter found + { + idx = atoi( cp ); + + if ( idx < 0 || idx > 1 ) + { + printf( "Invalid flag value %i for parameter %s, must be 0 or 1\n", idx, pout_name_ois ); + goto fail; + } + + if ( !( p_pi->flags & POUT_SUPP_IF_SYNC_ONLY ) ) + { + if ( idx ) + { + printf( "Warning: \"Only if sync\" flag not supported for output %i\n", inst_num ); + goto fail; + } + } + + if ( idx ) + p_ps->flags |= POUT_IF_SYNC_ONLY; + else + p_ps->flags &= ~POUT_IF_SYNC_ONLY; + + printf( "\"Only if sync\" flag%s set for output %i\n", + idx ? str_empty : str_spc_not, inst_num ); + } + + + // "Pulse Shift" parameter + idx = chk_parm_name( s, pout_name_shift, &cp ); + + if ( mbg_rc_is_error( idx ) ) // parameter error + { + err_info = pout_name_shift; + goto fail; + } + + if ( cp ) // parameter found + { + long pulse_shift = atol( cp ); + + if ( !( p_pi->flags & POUT_SUPP_PULSE_SHIFT ) ) + { + printf( "Warning: pulse shift not supported for output %i\n", inst_num ); + goto fail; + } + + if ( !_is_supported( p_ps->mode, POUT_MODES_DATA_PULSE_SHIFT ) ) + { + printf( "Pulse shift not supported for mode \"%s\"\n", + _get_pout_mode_name( p_ps->mode ) ); + goto fail; + } + + + if ( ( pulse_shift < DEFAULT_POUT_PULSE_SHIFT_MIN ) || + ( pulse_shift > DEFAULT_POUT_PULSE_SHIFT_MAX ) ) + { + printf( "Pulse shift %li ns out of range (%+li..%+li ns)\n", pulse_shift, + (long) DEFAULT_POUT_PULSE_SHIFT_MIN, (long) DEFAULT_POUT_PULSE_SHIFT_MAX ); + goto fail; + } + + if ( p_pi->pulse_shift_res ) + { + long rem = pulse_shift % p_pi->pulse_shift_res; + long l = pulse_shift - rem; + + #if 0 && defined( DEBUG ) + printf( "DEBUG: s %li, rem %li, l %li\n", pulse_shift, rem, l ); + #endif + + if ( l != pulse_shift ) + { + printf( "Warning: pulse shift %+li ns not appropriate for resolution %u ns, truncating to %li ns.\n", + pulse_shift, p_pi->pulse_shift_res, l ); + pulse_shift = l; + } + } + + p_ps->pout_data.pulse_shift = pulse_shift; + + printf( "Pulse shift for programmable output %i changed to %li ns\n", + inst_num, (long) p_ps->pout_data.pulse_shift ); + } + + + for ( i = 0; i < n_pout; i++ ) + { + POUT_SETTINGS *p_ps = &api[i].pout_info.pout_settings; + + if ( memcmp( p_ps, &prv_api[i].pout_info.pout_settings, sizeof( *p_ps ) ) ) + { + // settings for this output have changed + rc = mbg_set_gps_pout_settings( dh, p_ps, i ); + + if ( mbg_rc_is_error( rc ) ) + return rc; + } + } + + return MBG_SUCCESS; + +fail: + printf( "Invalid parameter in argument" ); + + if ( err_info ) + printf( " %s", err_info ); + + printf( "!\n" ); + + return MBG_ERR_CFG; + +} // eval_pout + + + +static /*HDR*/ +int show_pout( MBG_DEV_HANDLE dh, const OPT_HANDLER_SPEC *p_opt, const PCPS_DEV *p_devx, const char *cmd_info ) +{ + const INDENTS *p_ind = &show_indents; + RECEIVER_INFO ri = { 0 }; + ALL_POUT_INFO_IDX api = { { 0 } }; + int i; + int n_pout; + int rc = check_get_pout_cfg( dh, api, &ri ); + + if ( mbg_cond_err_msg( rc, "check_get_pout_cfg" ) ) + return rc; + + n_pout = rc; // Contains now the number of programmable pulse outputs + + print_indent( p_ind->indent_1 ); + printf( "%s:", cmd_info ); + + if ( n_pout ) + { + for ( i = 0; i < n_pout; i++ ) + { + const POUT_INFO *pi = &api[i].pout_info; + const POUT_SETTINGS *ps = &pi->pout_settings; + + // TODO: Actually the code below only shows the current mode, + // and whether the output signal is inverted, or not. + // Full featured code should also display additional parameters + // depending the selected mode. + + printf( "\n" ); + print_indent( p_ind->indent_2 ); + printf( "Output %i: ", i ); + printf( "%s", _get_pout_mode_name( ps->mode ) ); + + // Print pulse len, if supported by the mode + if ( _is_supported( ps->mode, POUT_MODES_MODE_PARAM_AS_PULSE_LEN ) ) + { + // pulse len is 10 ms units, so multiply by 10 to get ms + printf( ", len %u ms", (unsigned int) ps->mode_param * 10 ); + + if ( pi->flags & POUT_FIXED_PULSE_LEN ) + printf( " (fix)" ); + } + + // ### FIXME check more mode_param usage, times etc. + + // If outputs can be inverted then this doesn't depend on the current mode + if ( !( pi->flags & POUT_NOT_INVERTIBLE ) ) + printf( ", %sinverted", ( ps->flags & POUT_INVERTED ) ? str_empty : str_not_spc ); + + + + if ( _is_supported( ps->mode, POUT_MODES_SUPP_IF_SYNC_ONLY ) ) + { + char ws[80]; + const char *cp = NULL; + + if ( _is_supported( ps->mode, POUT_MODES_TIMEOUT ) && + ( ( pi->flags & POUT_SUPP_IF_SYNC_ONLY ) == 0 ) && + ( ps->timeout != 0 ) ) + { + snprintf_safe( ws, sizeof( ws ), "after timeout %i min ", ps->timeout ); + cp = ws; + } + + if ( pi->flags & POUT_SUPP_IF_SYNC_ONLY ) + printf( ", %sdisabled %sif sync. lost", + ( ps->flags & POUT_IF_SYNC_ONLY ) ? str_empty : str_not_spc, + cp ? cp : str_empty ); + } + + + + + if ( pi->flags & POUT_SUPP_PULSE_SHIFT ) + if ( _is_supported( ps->mode, POUT_MODES_DATA_PULSE_SHIFT ) ) + printf( ", shift %li ns, res. %li ns", (long) ps->pout_data.pulse_shift, (long) pi->pulse_shift_res ); + } + } + else + printf( str_spc_not_supp ); + + printf( "\n" ); + + return MBG_SUCCESS; + +} // show_pout + + + +static /*HDR*/ void printf_ef( uint16_t flag, const char *info ) { printf( "%s:%u", info, ( flag == EF_OFF ) ? 0 : 1 ); @@ -1741,7 +2390,7 @@ int show_enable_flags( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *inf rc = mbg_get_gps_enable_flags( dh, &ef ); - if ( mbg_ioctl_err( rc, "mbg_get_gps_enable_flags" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_gps_enable_flags" ) ) return rc; printf( "%s enable flags: ", info ); @@ -1809,7 +2458,7 @@ int set_enable_flags( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev rc = mbg_get_gps_enable_flags( dh, &ef ); - if ( mbg_ioctl_err( rc, "mbg_get_gps_enable_flags" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_gps_enable_flags" ) ) return rc; // Scan input parameters @@ -1842,7 +2491,7 @@ int set_enable_flags( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev save: rc = mbg_set_gps_enable_flags( dh, &ef ); - if ( mbg_ioctl_err( rc, "mbg_set_gps_enable_flags" ) ) + if ( mbg_cond_err_msg( rc, "mbg_set_gps_enable_flags" ) ) return rc; return MBG_SUCCESS; @@ -1856,7 +2505,7 @@ int send_gps_cmd( MBG_DEV_HANDLE dh, ushort cmd ) { int rc = mbg_set_gps_cmd( dh, &cmd ); - if ( mbg_ioctl_err( rc, "mbg_set_gps_cmd" ) ) + if ( mbg_cond_err_msg( rc, "mbg_set_gps_cmd" ) ) return rc; printf( "NOTE: the command code %u has been sent to the GPS clock.\n", cmd ); @@ -1873,7 +2522,7 @@ int show_ant_cable_len( MBG_DEV_HANDLE dh, const char *info ) ANT_CABLE_LEN len; int rc = mbg_get_gps_ant_cable_len( dh, &len ); - if ( mbg_ioctl_err( rc, "mbg_get_gps_ant_cable_len" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_gps_ant_cable_len" ) ) return rc; printf( "%s antenna cable length: %u meter(s)", info, len ); @@ -1887,10 +2536,10 @@ int show_ant_cable_len( MBG_DEV_HANDLE dh, const char *info ) static /*HDR*/ int set_ant_cable_len( MBG_DEV_HANDLE dh, const char *s ) { - ANT_CABLE_LEN len = atol( s ); + ANT_CABLE_LEN len = (ANT_CABLE_LEN) atol( s ); // TODO check range ? int rc = mbg_set_gps_ant_cable_len( dh, &len ); - if ( mbg_ioctl_err( rc, "mbg_set_gps_ant_cable_len" ) ) + if ( mbg_cond_err_msg( rc, "mbg_set_gps_ant_cable_len" ) ) return rc; return MBG_SUCCESS; @@ -1909,15 +2558,15 @@ int set_event_time( MBG_DEV_HANDLE dh, const char *s ) // set event at current system time + number of seconds event_time = time( NULL ) + strtol( s, NULL, 10 ); - event_ts.sec = event_time; // Unix UTC seconds + event_ts.sec = (uint32_t) event_time; // Unix UTC seconds // TODO: check range / conversion event_ts.frac = 0; // fraction of second, 0xFFFFFFFF == 0.99.. sec rc = mbg_set_event_time( dh, &event_ts ); - if ( mbg_ioctl_err( rc, "mbg_set_event_time" ) ) + if ( mbg_cond_err_msg( rc, "mbg_set_event_time" ) ) return rc; - mbg_snprint_hr_tstamp( ws, sizeof( ws ), &event_ts ); + mbg_snprint_hr_tstamp( ws, sizeof( ws ), &event_ts, 0, 0 ); // raw timestamp? printf( "Event time set to UTC %s\n", ws ); return MBG_SUCCESS; @@ -1931,12 +2580,18 @@ int get_n_time_scale( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_INFO *p_tsci ) { MBG_TIME_SCALE_INFO tsci = { { 0 } }; int rc; - int i; - rc = mbg_dev_has_time_scale( dh, &i ); + rc = mbg_chk_dev_has_time_scale( dh ); - if ( ( rc != MBG_SUCCESS ) || ( i == 0 ) ) - goto done; // failed or not supported + if ( mbg_rc_is_error( rc ) ) + { + if ( rc == MBG_ERR_NOT_SUPP_BY_DEV ) + printf( "This device does not support a configurable time scale.\n" ); + else + mbg_cond_err_msg( rc, "mbg_chk_dev_has_time_scale" ); + + goto done; + } rc = mbg_get_time_scale_info( dh, &tsci ); @@ -1961,7 +2616,7 @@ int show_time_scale( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *info rc = mbg_get_time_scale_info( dh, &tsci ); - if ( mbg_ioctl_err( rc, "mbg_get_time_scale_info" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_time_scale_info" ) ) return rc; printf( "%s time scale index: %u (%s)", info, tsci.settings.scale, @@ -1983,7 +2638,7 @@ int set_time_scale( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) rc = mbg_get_time_scale_info( dh, &tsci ); - if ( mbg_ioctl_err( rc, "mbg_get_time_scale_info" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_time_scale_info" ) ) return rc; @@ -2005,7 +2660,7 @@ int set_time_scale( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) rc = mbg_set_time_scale_settings( dh, &tsci.settings ); - if ( mbg_ioctl_err( rc, "mbg_set_time_scale_settings" ) ) + if ( mbg_cond_err_msg( rc, "mbg_set_time_scale_settings" ) ) return rc; return MBG_SUCCESS; @@ -2015,17 +2670,14 @@ int set_time_scale( MBG_DEV_HANDLE dh, const char *arg, const PCPS_DEV *p_dev ) static /*HDR*/ -void usage( MBG_DEV_HANDLE dh, PCPS_DEV *p_dev, RECEIVER_INFO *p_ri, +void usage( MBG_DEV_HANDLE dh, PCPS_DEV *p_dev, RECEIVER_INFO *p_ri, RECEIVER_PORT_CFG *p_rpcfg ) { int i; int n_time_scale; if ( p_dev ) - { - check_setup_receiver_info( dh, p_dev, p_ri ); check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri ); - } printf( "Usage: %s cmd [dev]\n" "\n" @@ -2121,6 +2773,10 @@ void usage( MBG_DEV_HANDLE dh, PCPS_DEV *p_dev, RECEIVER_INFO *p_ri, printf( "\n" ); + help_pout_arg( dh, p_dev, &ohs_pout, 0 ); + + printf( "\n" ); + printf( " EF show clock's enable flags\n" " EF=SERIAL:0,PULSES:1,SYNTH:0 modify clock's enable flags\n" "\n" @@ -2132,7 +2788,7 @@ void usage( MBG_DEV_HANDLE dh, PCPS_DEV *p_dev, RECEIVER_INFO *p_ri, " 0: only after the card has synchronized to its incoming signal\n" " 1: immediately after power-up\n" "\n" - " Please note enable flags may not be supported by any device\n" + " Please note that not every device supports enable flags.\n" "\n" ); @@ -2149,7 +2805,7 @@ void usage( MBG_DEV_HANDLE dh, PCPS_DEV *p_dev, RECEIVER_INFO *p_ri, " If no broadcast address is specified then the default broadcast address\n" " is computed from the IP address and the network mask.\n" "\n" - " Please note a LAN interface may not be provided by any board type.\n" + " Please note that not every device provides a LAN interface.\n" " Also, the IP values above are examples only. The real values to be used\n" " depend on the settings of the network to which the card is attached.\n" "\n" @@ -2171,17 +2827,17 @@ void usage( MBG_DEV_HANDLE dh, PCPS_DEV *p_dev, RECEIVER_INFO *p_ri, printf( " If the PTP device supports unicast slave mode then the following parameters\n" " can be specified to configure a unicast master to be queried:\n" - " PTP=ROLE:<rl>[,GMIP:<ip>][,GMID:<id>][,PID:<po>][,SMI:<sr>][,AMI:<ar>][,DMI:<dr>][,DUR:<du>] set PTP unicast parameters\n" + " PTP=ROLE:<rl>[,GMIP:<ip>][,GMID:<id>][,PID:<po>][,SMI:<sr>][,AMI:<ar>][,DRI:<dr>][,DUR:<du>] set PTP unicast parameters\n" "\n" " where, e.g.:\n" " ROLE:MCS specifies \"Multicast Slave\" PTP role\n" " ROLE:UCS specifies \"Unicast Slave\" PTP role\n" " GMIP:192.168.1.115 specifies the IP address of the grandmaster\n" - " GMID:FF:FF:FF:FF:FF:FF:FF:FF specifies the Clock ID of the grandmaster, or '*' as wildcard for all FF\n" - " PID:1 specifies the target port ID of the grandmaster port to be used, or '*' for wildcard\n" - " SMI:0 specifies the Sync message interval requested from the grandmaster in 2^x seconds [-6..6]\n" - " AMI:1 specifies the Announce message interval requested from the grandmaster in 2^x seconds [-6..6]\n" - " DMI:1 specifies the DelayRequest message interval requested from the grandmaster in 2^x seconds [-6..6]\n" + " GMID:FF:FF:FF:FF:FF:FF:FF:FF specifies the Clock ID of the grandmaster, or '*' as wildcard for all 'FF'\n" + " PID:1 specifies the target Port ID of the grandmaster port to be used, or '*' for wildcard\n" + " SMI:0 specifies the Sync Message Interval requested from the grandmaster in 2^x seconds [-6..6]\n" + " AMI:1 specifies the Announce Message Interval requested from the grandmaster in 2^x seconds [-6..6]\n" + " DRI:1 specifies the Delay Request Interval requested from the grandmaster in 2^x seconds [-6..6]\n" " DUR:300 specifies the duration in seconds how long the master shall send messages to the slave until a timeout or renewal occurs\n" "\n" ); @@ -2219,27 +2875,27 @@ const char *str_parm_p( const char *s, const char *keyword ) static /*HDR*/ -int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, +int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, RECEIVER_INFO *p_ri, RECEIVER_PORT_CFG *p_rpcfg ) { const char *sdate = NULL; const char *stime = NULL; const char *cp; int i; - int rc = 0; + int rc = MBG_SUCCESS; int error_occurred = 0; must_print_usage = 0; for ( i = 1; i < argc; i++ ) { - if ( rc < 0 ) + if ( mbg_rc_is_error( rc ) ) error_occurred = 1; - if ( rc > 0 ) + if ( rc == RC_USAGE ) must_print_usage = 1; - rc = 0; + rc = MBG_SUCCESS; if ( ( strcmp( argv[i], "-?" ) == 0 ) || ( strcmp( argv[i], "-h" ) == 0 ) || @@ -2312,11 +2968,16 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p { if ( p_dev ) { - check_setup_receiver_info( dh, p_dev, p_ri ); - if ( p_ri->n_com_ports ) + int rc = check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri ); + + if ( mbg_rc_is_error( rc ) ) { - check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri ); + // ### TODO print another error? + continue; + } + if ( p_ri->n_com_ports ) + { if ( *cp != 0 ) { printf( "** Invalid parameter: %s\n", argv[i] ); @@ -2343,8 +3004,13 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p char *p_tail; ulong port_num; - check_setup_receiver_info( dh, p_dev, p_ri ); - check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri ); + rc = check_get_receiver_port_cfg( dh, p_rpcfg, p_dev, p_ri ); + + if ( mbg_rc_is_error( rc ) ) + { + // ### TODO print another error? + continue; + } port_num = strtoul( cp, &p_tail, 10 ); @@ -2359,7 +3025,7 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p if ( port_num >= (ulong) p_ri->n_com_ports ) { - printf( "** COM port number %lu exceeds maximum %u\n", + printf( "** COM port number %lu exceeds maximum %u\n", port_num, p_ri->n_com_ports ); must_print_usage = 1; continue; @@ -2378,6 +3044,58 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p } + cp = str_parm_p( argv[i], "POUT" ); + + if ( cp ) + { + if ( p_dev ) + { + ulong n_pout; + ulong pout_num; + char *p_tail; + + check_setup_receiver_info( dh, p_ri ); + n_pout = p_ri->n_prg_out; + + if ( n_pout == 0 ) + { + printf( "Programmable outputs not supported!\n" ); + continue; + } + + pout_num = strtoul( cp, &p_tail, 10 ); + + if ( p_tail == cp ) // no POUT number specified + { + show_pout( dh, &ohs_pout, p_dev, "Current programmable outputs settings" ); + continue; + } + + cp = p_tail; + + if ( pout_num >= n_pout ) + { + printf( "** Programmable output number %lu exceeds maximum %lu\n", + pout_num, n_pout ); + must_print_usage = 1; + continue; + } + + if ( *cp != '=' ) + { + printf( "** Invalid programmable output specification: %s\n", argv[i] ); + must_print_usage = 1; + continue; + } + + rc = eval_pout( dh, ++cp, (unsigned) pout_num ); + printf( "\n" ); + show_pout( dh, &ohs_pout, p_dev, "Current programmable outputs settings" ); + } + continue; + } + + cp = str_parm_p( argv[i], "EF" ); if ( cp ) @@ -2396,7 +3114,7 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p { rc = set_enable_flags( dh, ++cp, p_dev ); - if ( rc < 0 ) + if ( mbg_rc_is_error( rc ) ) { printf( "*** Warning: invalid enable flag parameter syntax\n" ); must_print_usage = 1; @@ -2430,7 +3148,7 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p { rc = set_time_scale( dh, ++cp, p_dev ); - if ( rc < 0 ) + if ( mbg_rc_is_error( rc ) ) { must_print_usage = 1; continue; @@ -2463,7 +3181,7 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p { rc = set_tzdl_offs( dh, ++cp ); - if ( rc < 0 ) + if ( mbg_rc_is_error( rc ) ) { must_print_usage = 1; continue; @@ -2478,6 +3196,39 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p } + cp = str_parm_p( argv[i], "SYNTH" ); + + if ( cp ) + { + if ( p_dev ) + { + char *info = "Current"; + + if ( !_pcps_has_synth( p_dev ) ) + { + err_msg( p_dev, no_synth ); + continue; + } + + if ( *cp == '=' ) + { + rc = set_synth( dh, ++cp ); + + if ( mbg_rc_is_error( rc ) ) + { + must_print_usage = 1; + continue; + } + + info = "New"; + } + + show_synth( dh, info ); + } + continue; + } + + cp = str_parm_p( argv[i], "LAN" ); if ( cp ) @@ -2496,7 +3247,7 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p { rc = set_lan_intf( dh, ++cp, p_dev ); - if ( rc < 0 ) + if ( mbg_rc_is_error( rc ) ) { must_print_usage = 1; continue; @@ -2529,11 +3280,8 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p { rc = set_ptp_cfg( dh, ++cp, p_dev ); - if ( rc < 0 ) - { - must_print_usage = 1; + if ( mbg_rc_is_error( rc ) ) continue; - } info = "New"; } @@ -2561,7 +3309,7 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p { rc = set_ant_cable_len( dh, ++cp ); - if ( rc < 0 ) + if ( mbg_rc_is_error( rc ) ) { must_print_usage = 1; continue; @@ -2587,9 +3335,9 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p if ( *cp == '=' ) rc = set_event_time( dh, ++cp ); else - rc = -1; + rc = MBG_ERR_PARM_FMT; - if ( rc < 0 ) + if ( mbg_rc_is_error( rc ) ) printf( "*** Warning: invalid event time parameter\n" ); } else @@ -2613,13 +3361,18 @@ int check_cmd_line( int argc, char *argv[], MBG_DEV_HANDLE dh, const PCPS_DEV *p if ( p_dev ) if ( sdate || stime ) + { rc = set_date_time( dh, p_dev, sdate, stime ); + if ( mbg_rc_is_error( rc ) ) + error_occurred = 1; + } + if ( error_occurred ) - return -1; + return MBG_ERR_GENERIC; if ( must_print_usage ) - return 1; + return RC_USAGE; return MBG_SUCCESS; @@ -2634,6 +3387,7 @@ int main( int argc, char *argv[] ) PCPS_DEV dev = { { 0 } }; PCPS_DEV *pdev = NULL; MBG_DEV_HANDLE dh = MBG_INVALID_DEV_HANDLE; + MBG_DEV_FN tmp_dev_fn; int rc; mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); @@ -2646,34 +3400,22 @@ int main( int argc, char *argv[] ) // pass a device handle, so commands are not evaluated. check_cmd_line( argc, argv, dh, NULL, &ri, &rpcfg ); - if ( dev_name ) - dh = open( dev_name, O_RDWR ); // open specific device - else - dh = mbg_open_device( 0 ); // open first device found + rc = mbg_open_device_by_param( &dh, dev_name, 0, 0, + tmp_dev_fn, sizeof( tmp_dev_fn ), 0 ); - if ( dh == MBG_INVALID_DEV_HANDLE ) - { - //##++++++++++++++++++++++ - if ( dev_name ) - fprintf( stderr, "%s: ", dev_name ); - - perror( "Unable to open device" ); + if ( mbg_rc_is_error( rc ) ) goto fail; - } + // get information about the device - rc = mbg_get_show_dev_info( dh, dev_name, &dev ); + rc = mbg_get_show_dev_info( dh, NULL, &dev ); - if ( rc < 0 ) + if ( mbg_rc_is_error( rc ) ) goto fail; pdev = &dev; - #if SIM_PTP_CFG - pdev->cfg.features |= PCPS_HAS_PTP; - #endif - rc = check_cmd_line( argc, argv, dh, pdev, &ri, &rpcfg ); if ( rc < 0 ) @@ -2686,13 +3428,13 @@ int main( int argc, char *argv[] ) mbg_close_device( &dh ); - return 0; + return MBG_EXIT_CODE_SUCCESS; show_usage: usage( dh, pdev, &ri, &rpcfg ); - return 1; + return MBG_EXIT_CODE_USAGE; fail: - return 2; + return MBG_EXIT_CODE_FAIL; } diff --git a/src/external/bsd/meinberg/dist/mbgfasttstamp/Makefile b/src/external/bsd/meinberg/dist/mbgfasttstamp/Makefile index 92cfa46..4eb3b9c 100755 --- a/src/external/bsd/meinberg/dist/mbgfasttstamp/Makefile +++ b/src/external/bsd/meinberg/dist/mbgfasttstamp/Makefile @@ -1,15 +1,16 @@ ######################################################################### # -# $Id: Makefile 1.2.1.2 2010/08/30 09:05:23 martin TEST $ +# $Id: Makefile 1.3 2017/07/05 18:50:00 martin REL_M $ # # Description: # Makefile for mbgfasttstamp. # # ----------------------------------------------------------------------- # $Log: Makefile $ -# Revision 1.2.1.2 2010/08/30 09:05:23 martin -# Revision 1.2.1.1 2010/08/30 08:21:01 martin +# Revision 1.3 2017/07/05 18:50:00 martin +# Updated list of object files and use top level +# Makefile properly. # Revision 1.2 2009/07/24 10:31:16 martin # Moved declarations to a common file which is now included. # Revision 1.1 2008/12/22 11:45:01 martin @@ -18,11 +19,15 @@ ######################################################################### TARGET = mbgfasttstamp -INST_DIR = /usr/local/bin +INST_TO_BIN = 1 OBJS = $(TARGET).o OBJS += mbgdevio.o +OBJS += timeutil.o +OBJS += str_util.o +OBJS += cfg_hlp.o OBJS += toolutil.o +OBJS += mbgerror.o OBJS += gpsutils.o BASEDIR := .. diff --git a/src/external/bsd/meinberg/dist/mbgfasttstamp/mbgfasttstamp.c b/src/external/bsd/meinberg/dist/mbgfasttstamp/mbgfasttstamp.c index f9eefc2..ea5e5a3 100755 --- a/src/external/bsd/meinberg/dist/mbgfasttstamp/mbgfasttstamp.c +++ b/src/external/bsd/meinberg/dist/mbgfasttstamp/mbgfasttstamp.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgfasttstamp.c 1.6.1.3.1.3 2011/07/05 15:35:54 martin TRASH martin $ + * $Id: mbgfasttstamp.c 1.7 2017/07/05 18:55:22 martin REL_M $ * * Description: * Main file for mbgfasttstamp program which demonstrates how to access @@ -9,16 +9,16 @@ * * ----------------------------------------------------------------------- * $Log: mbgfasttstamp.c $ - * Revision 1.6.1.3.1.3 2011/07/05 15:35:54 martin - * Modified version handling. - * Revision 1.6.1.3.1.2 2011/07/05 14:35:17 martin + * Revision 1.7 2017/07/05 18:55:22 martin * New way to maintain version information. - * Revision 1.6.1.3.1.1 2011/05/13 18:52:12 martin - * Started to support signal handler to catch CTRL-C. - * Revision 1.6.1.3 2011/01/28 12:04:07 martin - * Revision 1.6.1.2 2011/01/28 11:51:13 martin - * Revision 1.6.1.1 2011/01/28 11:17:00 martin + * Support build under Windows. * Abort if MM access not supported on the target OS. + * Support signal handler to catch CTRL-C. + * Added options to sleep between calls. + * Parameters -u and -s imply -c. + * Use more functions from common library modules. + * Use codes and inline functions from mbgerror.h. + * Proper return codes and exit codes. * Revision 1.6 2010/05/21 12:54:33 martin * Print warning if no cycles supported on the target platform * and thus latencies can not be computed. @@ -43,13 +43,11 @@ // include Meinberg headers #include <mbgdevio.h> -#include <pcpsutil.h> #include <toolutil.h> // common utility functions // include system headers #include <stdio.h> #include <stdlib.h> -#include <unistd.h> #define MBG_MICRO_VERSION 0 @@ -64,20 +62,8 @@ static const char *pname = "mbgfasttstamp"; static int loops; static int burst_read; static int read_raw; -static int exit_requested; - - - -static /*HDR*/ -void sighandler( int sig ) -{ - #if defined( DEBUG ) - printf( "Caught signal %i, exiting.\n", sig ); - #endif - - exit_requested = 1; - -} // sighandler +static long sleep_secs; +static long sleep_usecs; @@ -98,10 +84,10 @@ int show_fast_hr_timestamp( MBG_DEV_HANDLE dh ) int rc = read_raw ? mbg_get_fast_hr_timestamp( dh, &ts ) : mbg_get_fast_hr_timestamp_comp( dh, &ts, &hns_latency ); - if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp..." ) ) - goto fail; + if ( mbg_cond_err_msg( rc, "mbg_get_fast_hr_timestamp..." ) ) + return rc; - mbg_print_hr_timestamp( &ts, hns_latency, NULL, read_raw ); + mbg_print_hr_timestamp( &ts, hns_latency, NULL, read_raw, 1 ); // raw timestamp? if ( this_loops > 0 ) this_loops--; @@ -109,13 +95,16 @@ int show_fast_hr_timestamp( MBG_DEV_HANDLE dh ) if ( this_loops == 0 ) break; + if ( sleep_secs ) + sleep( sleep_secs ); + else + if ( sleep_usecs ) + usleep( sleep_usecs ); + // if this_loops is < 0 then loop forever } - return 0; - -fail: - return -1; + return MBG_SUCCESS; } // show_fast_hr_timestamp @@ -145,8 +134,8 @@ int show_fast_hr_timestamp_burst( MBG_DEV_HANDLE dh ) { int rc = mbg_get_fast_hr_timestamp( dh, &ts[i] ); - if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp" ) ) - goto fail; + if ( mbg_cond_err_msg( rc, "mbg_get_fast_hr_timestamp" ) ) + return rc; } } else @@ -154,21 +143,17 @@ int show_fast_hr_timestamp_burst( MBG_DEV_HANDLE dh ) { int rc = mbg_get_fast_hr_timestamp_comp( dh, &ts[i], &hns_latency[i] ); - if ( mbg_ioctl_err( rc, "mbg_get_fast_hr_timestamp_comp" ) ) - goto fail; + if ( mbg_cond_err_msg( rc, "mbg_get_fast_hr_timestamp_comp" ) ) + return rc; } for ( i = 0; i < this_loops; i++ ) { PCPS_TIME_STAMP *p_prv_ts = i ? &ts[i - 1] : NULL; - mbg_print_hr_timestamp( &ts[i], hns_latency[i], p_prv_ts, read_raw ); + mbg_print_hr_timestamp( &ts[i], hns_latency[i], p_prv_ts, read_raw, 0 ); // raw timestamp? } - return 0; - - -fail: - return -1; + return MBG_SUCCESS; } // show_fast_hr_timestamp_burst @@ -177,16 +162,13 @@ fail: static /*HDR*/ int do_mbgfasttstamp( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) { - int supported = 0; - int rc = mbg_dev_has_fast_hr_timestamp( dh, &supported ); - - if ( mbg_ioctl_err( rc, "mbg_has_fast_hr_timestamp" ) ) - goto done; + int rc = mbg_chk_dev_has_fast_hr_timestamp( dh ); - if ( !supported ) + if ( mbg_rc_is_error( rc ) ) { - printf( "This device does not support fast (memory mapped) time stamps.\n" ); - goto done; + mbg_cond_err_msg_info( rc, "mbg_chk_dev_has_fast_hr_timestamp", + "support fast (memory mapped) time stamps" ); + return rc; } if ( burst_read ) @@ -194,13 +176,12 @@ int do_mbgfasttstamp( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) else show_fast_hr_timestamp( dh ); -done: - mbg_close_device( &dh ); - - return rc; + return MBG_SUCCESS; } // do_mbgfasttstamp +static MBG_DEV_HANDLER_FNC do_mbgfasttstamp; + static /*HDR*/ @@ -217,6 +198,8 @@ void usage( void ) mbg_print_opt_info( "-n num", "run num loops" ); mbg_print_opt_info( "-b", "burst read" ); mbg_print_opt_info( "-r", "read raw time stamps, no cycles" ); + mbg_print_opt_info( "-s num", "sleep num seconds between calls (implies -c)" ); + mbg_print_opt_info( "-u num", "sleep num microseconds between calls (implies -c)" ); mbg_print_device_options(); puts( "" ); @@ -232,7 +215,7 @@ int main( int argc, char *argv[] ) mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); // check command line parameters - while ( ( c = getopt( argc, argv, "bcn:rh?" ) ) != -1 ) + while ( ( c = getopt( argc, argv, "bcn:rs:u:h?" ) ) != -1 ) { switch ( c ) { @@ -252,6 +235,16 @@ int main( int argc, char *argv[] ) read_raw = 1; break; + case 's': + sleep_secs = atoi( optarg ); + loops = -1; + break; + + case 'u': + sleep_usecs = atoi( optarg ); + loops = -1; + break; + case 'h': case '?': default: @@ -262,7 +255,7 @@ int main( int argc, char *argv[] ) if ( must_print_usage ) { usage(); - return 1; + return MBG_EXIT_CODE_USAGE; } #if !MBG_TGT_SUPP_MEM_ACC @@ -270,7 +263,7 @@ int main( int argc, char *argv[] ) return 1; #endif - #if !defined( MBG_PC_CYCLES_SUPPORTED ) + #if !MBG_PC_CYCLES_SUPPORTED printf( "** Warning: No cycles support to compute real latencies on this platform!\n" ); if ( !read_raw ) @@ -282,12 +275,8 @@ int main( int argc, char *argv[] ) printf( "\n" ); #endif - // The function below checks which devices have been specified - // on the command, and for each device - // - tries to open the device - // - shows basic device info - // - calls the function passed as last parameter - rc = mbg_check_devices( argc, argv, optind, do_mbgfasttstamp ); + // Handle each of the specified devices. + rc = mbg_handle_devices( argc, argv, optind, do_mbgfasttstamp, 0 ); - return abs( rc ); + return mbg_rc_is_success( rc ) ? MBG_EXIT_CODE_SUCCESS : MBG_EXIT_CODE_FAIL; } diff --git a/src/external/bsd/meinberg/dist/mbggpscap/Makefile b/src/external/bsd/meinberg/dist/mbggpscap/Makefile index 6564761..7f511e3 100755 --- a/src/external/bsd/meinberg/dist/mbggpscap/Makefile +++ b/src/external/bsd/meinberg/dist/mbggpscap/Makefile @@ -1,15 +1,16 @@ ######################################################################### # -# $Id: Makefile 1.7.1.2 2010/08/30 09:05:23 martin TEST $ +# $Id: Makefile 1.8 2017/07/05 18:50:00 martin REL_M $ # # Description: # Makefile for mbggpscap. # # ----------------------------------------------------------------------- # $Log: Makefile $ -# Revision 1.7.1.2 2010/08/30 09:05:23 martin -# Revision 1.7.1.1 2010/08/30 08:21:32 martin +# Revision 1.8 2017/07/05 18:50:00 martin +# Updated list of object files and use top level +# Makefile properly. # Revision 1.7 2009/07/24 10:31:16 martin # Moved declarations to a common file which is now included. # Revision 1.6 2008/12/22 11:56:58 martin @@ -28,12 +29,16 @@ ######################################################################### TARGET = mbggpscap -INST_DIR = /usr/local/bin +INST_TO_BIN = 1 OBJS = $(TARGET).o OBJS += mbgdevio.o -OBJS += gpsutils.o +OBJS += timeutil.o +OBJS += str_util.o OBJS += toolutil.o +OBJS += mbgerror.o +OBJS += cfg_hlp.o +OBJS += gpsutils.o BASEDIR := .. include $(BASEDIR)/Makefile diff --git a/src/external/bsd/meinberg/dist/mbggpscap/mbggpscap.c b/src/external/bsd/meinberg/dist/mbggpscap/mbggpscap.c index a440f87..80c591e 100755 --- a/src/external/bsd/meinberg/dist/mbggpscap/mbggpscap.c +++ b/src/external/bsd/meinberg/dist/mbggpscap/mbggpscap.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbggpscap.c 1.10.1.4 2011/07/05 15:35:54 martin TRASH martin $ + * $Id: mbggpscap.c 1.11 2017/07/05 18:59:14 martin REL_M $ * * Description: * Main file for mbggpscap program which demonstrates how to access @@ -13,15 +13,21 @@ * * ----------------------------------------------------------------------- * $Log: mbggpscap.c $ - * Revision 1.10.1.4 2011/07/05 15:35:54 martin - * Modified version handling. - * Revision 1.10.1.3 2011/07/05 14:35:18 martin + * Revision 1.11 2017/07/05 18:59:14 martin * New way to maintain version information. - * Revision 1.10.1.2 2010/11/12 12:27:17 martin + * Support build under Windows. + * Improved code execution paths. * Improved reading capture events arriving at a high rate. * Support validation of capture signals arriving at a constant rate. - * Revision 1.10.1.1 2010/03/10 16:42:33 martin - * Improved code execution paths. + * Fixed a bug when displaying the capture event status. TTM and + * PCPS_HR_TIME are using different sets of status flags. + * New option -r which displays raw timestamps and raw status. + * New option -o which forces usage of old API. + * New command line option to clear buffer. + * Account for PCPS_HRT_BIN_FRAC_SCALE renamed to MBG_FRAC32_UNITS_PER_SEC. + * Use more functions from common library modules. + * Use codes and inline functions from mbgerror.h. + * Proper return codes and exit codes. * Revision 1.10 2009/09/29 15:02:15 martin * Updated version number to 3.4.0. * Revision 1.9 2009/07/24 09:50:08 martin @@ -53,13 +59,11 @@ // include Meinberg headers #include <mbgdevio.h> -#include <pcpsutil.h> #include <toolutil.h> // common utility functions // include system headers #include <stdio.h> #include <stdlib.h> -#include <unistd.h> #include <time.h> @@ -76,27 +80,17 @@ static const char *pname = "mbggpscap"; static int continuous; static double nom_cap_intv; // nominal capture interval to check [s] static double max_cap_jitter; // max allowed jitter [s] +static int raw; +static int force_old_api; +static int clear_buffer; static int has_been_called; static int must_check_intv; +static int query_only; static ulong err_cnt; static PCPS_HR_TIME prv_ucap; -static /*HDR*/ -void show_ucap_status( ulong status ) -{ - // status bit definitions can be found in pcpsdefs.h. - - if ( status & PCPS_UCAP_OVERRUN ) // capture events have occurred too fast - printf( " << CAP OVR" ); - - if ( status & PCPS_UCAP_BUFFER_FULL ) // capture buffer has been full, events lost - printf( " << BUF OVR" ); - -} // show_ucap_status - - static /*HDR*/ void show_ucap_event( const PCPS_HR_TIME *ucap ) @@ -104,16 +98,17 @@ void show_ucap_event( const PCPS_HR_TIME *ucap ) char ws[80]; // Print converted date and time to a string: - mbg_snprint_hr_time( ws, sizeof( ws ), ucap ); + mbg_snprint_hr_time( ws, sizeof( ws ), ucap, raw ); // Print the time stamp, ucap->signal contains the channel number: printf( "New capture: CH%i: %s", ucap->signal, ws ); if ( must_check_intv && has_been_called ) { + int jitter_exceeded; double abs_delta; double d = ucap->tstamp.sec - prv_ucap.tstamp.sec; - d += ( (double) ucap->tstamp.frac - prv_ucap.tstamp.frac ) / PCPS_HRT_BIN_FRAC_SCALE; + d += ( (double) ucap->tstamp.frac - prv_ucap.tstamp.frac ) / MBG_FRAC32_UNITS_PER_SEC; printf( " %+.6f", d ); @@ -122,14 +117,28 @@ void show_ucap_event( const PCPS_HR_TIME *ucap ) if ( abs_delta < 0.0 ) abs_delta = -abs_delta; + jitter_exceeded = 0; + if ( abs_delta > max_cap_jitter ) + { + jitter_exceeded = 1; err_cnt++; + } if ( err_cnt ) - printf( " ** %lu", err_cnt ); + printf( " %lu%s", err_cnt, jitter_exceeded ? " <<" : "" ); } - show_ucap_status( ucap->status ); + // status bit definitions can be found in pcpsdefs.h. + + if ( raw ) + printf( ", st: 0x%04X", ucap->status ); + + if ( ucap->status & PCPS_UCAP_OVERRUN ) // capture events have occurred too fast + printf( " << CAP OVR" ); + + if ( ucap->status & PCPS_UCAP_BUFFER_FULL ) // capture buffer has been full, events lost + printf( " << BUF OVR" ); prv_ucap = *ucap; has_been_called = 1; @@ -158,7 +167,8 @@ void show_gps_ucap( const TTM *ucap ) (ulong) ucap->tm.frac ); - show_ucap_status( ucap->tm.status ); + if ( raw ) + printf( ", st: 0x%04lX", (ulong) ucap->tm.status ); printf( "\n" ); @@ -176,7 +186,7 @@ void check_serial_mode( MBG_DEV_HANDLE dh ) // read the clock's current port settings int rc = mbg_get_gps_port_parm( dh, &port_parm ); - if ( mbg_ioctl_err( rc, "mbg_get_gps_port_parm" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_gps_port_parm" ) ) return; @@ -198,7 +208,10 @@ void check_serial_mode( MBG_DEV_HANDLE dh ) rc = mbg_set_gps_port_parm( dh, &port_parm ); - if ( mbg_ioctl_err( rc, "mbg_set_gps_port_parm" ) ) + // ### TODO FIXME The call above requires root permissions, so + // print a more appropriate message if the call failed. + + if ( mbg_cond_err_msg( rc, "mbg_set_gps_port_parm" ) ) return; printf( "NOTE: the clock's serial port mode has been changed.\n" ); @@ -211,11 +224,13 @@ static /*HDR*/ int do_mbggpscap( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) { int rc; + int this_clear_buffer = clear_buffer; must_check_intv = continuous && ( nom_cap_intv != 0 ); has_been_called = 0; err_cnt = 0; + if ( !_pcps_has_ucap( p_dev ) && !_pcps_is_gps( p_dev ) ) { printf( "This device type does not provide time capture inputs.\n" ); @@ -233,7 +248,7 @@ int do_mbggpscap( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) // The new API calls are supported by all supported by all newer boards which // provide user capture inputs, and also for older boards with a firmware update. - if ( _pcps_has_ucap( p_dev ) ) // check if the new API is supported + if ( !force_old_api && _pcps_has_ucap( p_dev ) ) // check if the new API is supported { // The new API provides the following functions: // mbg_clr_ucap_buff() clear the on-board FIFO buffer @@ -259,9 +274,16 @@ int do_mbggpscap( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) ucap_entries.used, ucap_entries.max ); } + if ( this_clear_buffer ) + { + printf( "Clearing on-board FIFO buffer\n" ); + mbg_clr_ucap_buff( dh ); + this_clear_buffer = 0; + } + // If the program is not to run continuously and no // capture events are available then we're through. - if ( !continuous && ucap_entries.used == 0 ) + if ( query_only || ( !continuous && ucap_entries.used == 0 ) ) return 0; @@ -270,6 +292,10 @@ int do_mbggpscap( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) "Reading capture events:\n" ); + if ( must_check_intv ) + if ( max_cap_jitter == 0.0 ) + max_cap_jitter = 0.1e-6; + // Now read out all events from the FIFO and wait // for new events if the FIFO is empty. for (;;) @@ -278,7 +304,7 @@ int do_mbggpscap( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) rc = mbg_get_ucap_event( dh, &ucap_event ); - if ( mbg_ioctl_err( rc, "mbg_get_ucap_event" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_ucap_event" ) ) break; // an error has occurred // If a user capture event has been read then it @@ -296,7 +322,7 @@ int do_mbggpscap( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) } else // use the old API { - printf( "Checking for capture events:\n" ); + printf( "Checking for capture events using the old API:\n" ); for (;;) { @@ -304,7 +330,7 @@ int do_mbggpscap( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) rc = mbg_get_gps_ucap( dh, &ucap_ttm ); - if ( mbg_ioctl_err( rc, "mbg_get_gps_ucap" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_gps_ucap" ) ) break; // an error has occurred @@ -330,6 +356,8 @@ int do_mbggpscap( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) } // do_mbggpscap +static MBG_DEV_HANDLER_FNC do_mbggpscap; + static /*HDR*/ @@ -341,8 +369,12 @@ void usage( void ) ); mbg_print_help_options(); mbg_print_opt_info( "-c", "run continuously" ); + mbg_print_opt_info( "-C", "clear capture buffer" ); mbg_print_opt_info( "-i val", "check interval between captures events [s]" ); mbg_print_opt_info( "-j val", "max allowed jitter of capture interval [s]" ); + mbg_print_opt_info( "-q", "query FIFO buffer status only" ); + mbg_print_opt_info( "-r", "show raw (hex) timestamp and status)" ); + mbg_print_opt_info( "-o", "force usage of old API (for testing only)" ); mbg_print_device_options(); puts( "" ); @@ -358,7 +390,7 @@ int main( int argc, char *argv[] ) mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); // check command line parameters - while ( ( c = getopt( argc, argv, "ci:j:h?" ) ) != -1 ) + while ( ( c = getopt( argc, argv, "cCi:j:qroh?" ) ) != -1 ) { switch ( c ) { @@ -366,6 +398,10 @@ int main( int argc, char *argv[] ) continuous = 1; break; + case 'C': + clear_buffer = 1; + break; + case 'i': nom_cap_intv = atof( optarg ); break; @@ -374,6 +410,18 @@ int main( int argc, char *argv[] ) max_cap_jitter = atof( optarg ); break; + case 'q': + query_only = 1; + break; + + case 'r': + raw = 1; + break; + + case 'o': + force_old_api = 1; + break; + case 'h': case '?': default: @@ -384,15 +432,17 @@ int main( int argc, char *argv[] ) if ( must_print_usage ) { usage(); - return 1; + return MBG_EXIT_CODE_USAGE; + } + + if ( nom_cap_intv != 0.0 ) + { + printf( "Nominal capture interval: %f s\n", nom_cap_intv ); + printf( "Maximum allowed capture jitter: %f s\n", max_cap_jitter ); } - // The function below checks which devices have been specified - // on the command, and for each device - // - tries to open the device - // - shows basic device info - // - calls the function passed as last parameter - rc = mbg_check_devices( argc, argv, optind, do_mbggpscap ); + // Handle each of the specified devices. + rc = mbg_handle_devices( argc, argv, optind, do_mbggpscap, 0 ); - return abs( rc ); + return mbg_rc_is_success( rc ) ? MBG_EXIT_CODE_SUCCESS : MBG_EXIT_CODE_FAIL; } diff --git a/src/external/bsd/meinberg/dist/mbghrtime/Makefile b/src/external/bsd/meinberg/dist/mbghrtime/Makefile index e332204..48e5a14 100755 --- a/src/external/bsd/meinberg/dist/mbghrtime/Makefile +++ b/src/external/bsd/meinberg/dist/mbghrtime/Makefile @@ -1,15 +1,16 @@ ######################################################################### # -# $Id: Makefile 1.7.1.2 2010/08/30 09:05:23 martin TEST $ +# $Id: Makefile 1.8 2017/07/05 18:50:00 martin REL_M $ # # Description: # Makefile for mbghrtime. # # ----------------------------------------------------------------------- # $Log: Makefile $ -# Revision 1.7.1.2 2010/08/30 09:05:23 martin -# Revision 1.7.1.1 2010/08/30 08:21:39 martin +# Revision 1.8 2017/07/05 18:50:00 martin +# Updated list of object files and use top level +# Makefile properly. # Revision 1.7 2009/07/24 10:31:16 martin # Moved declarations to a common file which is now included. # Revision 1.6 2008/12/22 11:56:59 martin @@ -28,11 +29,15 @@ ######################################################################### TARGET = mbghrtime -INST_DIR = /usr/local/bin +INST_TO_BIN = 1 OBJS = $(TARGET).o OBJS += mbgdevio.o +OBJS += timeutil.o +OBJS += str_util.o OBJS += toolutil.o +OBJS += mbgerror.o +OBJS += cfg_hlp.o OBJS += gpsutils.o BASEDIR := .. diff --git a/src/external/bsd/meinberg/dist/mbghrtime/mbghrtime.c b/src/external/bsd/meinberg/dist/mbghrtime/mbghrtime.c index c209612..2b0f4cd 100755 --- a/src/external/bsd/meinberg/dist/mbghrtime/mbghrtime.c +++ b/src/external/bsd/meinberg/dist/mbghrtime/mbghrtime.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbghrtime.c 1.11.1.6 2011/07/05 15:35:54 martin TRASH martin $ + * $Id: mbghrtime.c 1.12 2017/07/05 19:02:13 martin REL_M $ * * Description: * Main file for mbghrtime program which demonstrates how to access @@ -10,15 +10,15 @@ * * ----------------------------------------------------------------------- * $Log: mbghrtime.c $ - * Revision 1.11.1.6 2011/07/05 15:35:54 martin - * Modified version handling. - * Revision 1.11.1.5 2011/07/05 14:35:18 martin + * Revision 1.12 2017/07/05 19:02:13 martin * New way to maintain version information. - * Revision 1.11.1.4 2011/01/28 12:04:08 martin - * Revision 1.11.1.3 2011/01/28 11:52:51 martin - * Revision 1.11.1.2 2011/01/28 11:51:13 martin - * Revision 1.11.1.1 2011/01/28 11:17:33 martin - * Starrted to support raw and burst. + * Support build under Windows. + * Support raw and burst mode. + * New options -s, -u, -v. + * Parameters -u and -s imply -c. + * Use more functions from common library modules. + * Use codes and inline functions from mbgerror.h. + * Proper return codes and exit codes. * Revision 1.11 2010/05/21 12:54:33 martin * Print warning if no cycles supported on the target platform * and thus latencies can not be computed. @@ -53,15 +53,12 @@ // include Meinberg headers #include <mbgdevio.h> -#include <pcpsutil.h> #include <toolutil.h> // common utility functions // include system headers #include <time.h> #include <stdio.h> #include <stdlib.h> -#include <unistd.h> -#include <sys/time.h> // gettimeofday() @@ -77,6 +74,9 @@ static const char *pname = "mbghrtime"; static int loops; static int burst_read; static int read_raw; +static long sleep_secs; +static long sleep_usecs; +static int verbose; @@ -99,10 +99,10 @@ int show_hr_timestamp( MBG_DEV_HANDLE dh ) int rc = read_raw ? mbg_get_hr_time( dh, &ht ) : mbg_get_hr_time_comp( dh, &ht, &hns_latency ); - if ( mbg_ioctl_err( rc, "mbg_get_hr_time_..." ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_hr_time_..." ) ) goto fail; - mbg_print_hr_timestamp( &ht.tstamp, hns_latency, p, read_raw ); + mbg_print_hr_time( &ht, hns_latency, p, read_raw, verbose, verbose ); prv_ht = ht; p = &prv_ht.tstamp; @@ -113,6 +113,12 @@ int show_hr_timestamp( MBG_DEV_HANDLE dh ) if ( this_loops == 0 ) break; + if ( sleep_secs ) + sleep( sleep_secs ); + else + if ( sleep_usecs ) + usleep( sleep_usecs ); + // if this_loops is < 0 then loop forever } @@ -149,7 +155,7 @@ int show_hr_timestamp_burst( MBG_DEV_HANDLE dh ) { int rc = mbg_get_hr_time( dh, &ht[i] ); - if ( mbg_ioctl_err( rc, "mbg_get_hr_time" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_hr_time" ) ) goto fail; } } @@ -158,14 +164,14 @@ int show_hr_timestamp_burst( MBG_DEV_HANDLE dh ) { int rc = mbg_get_hr_time_comp( dh, &ht[i], &hns_latency[i] ); - if ( mbg_ioctl_err( rc, "mbg_get_hr_time_comp" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_hr_time_comp" ) ) goto fail; } for ( i = 0; i < this_loops; i++ ) { PCPS_HR_TIME *p_prv_ht = i ? &ht[i - 1] : NULL; - mbg_print_hr_timestamp( &ht[i].tstamp, hns_latency[i], &p_prv_ht->tstamp, read_raw ); + mbg_print_hr_time( &ht[i], hns_latency[i], &p_prv_ht->tstamp, read_raw, verbose, verbose ); } return 0; @@ -181,15 +187,15 @@ fail: static /*HDR*/ int do_mbghrtime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) { - int supported = 0; - int rc = mbg_dev_has_hr_time( dh, &supported ); - - if ( mbg_ioctl_err( rc, "mbg_dev_has_hr_time" ) ) - goto done; + int rc = mbg_chk_dev_has_hr_time( dh ); - if ( !supported ) + if ( mbg_rc_is_error( rc ) ) { - printf( "High resolution time not supported by this device.\n" ); + if ( rc == MBG_ERR_NOT_SUPP_BY_DEV ) // ### TODO not_supp + printf( "High resolution time not supported by this device.\n" ); + else + mbg_cond_err_msg( rc, "mbg_chk_dev_has_hr_time" ); + goto done; } @@ -199,12 +205,12 @@ int do_mbghrtime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) show_hr_timestamp( dh ); done: - mbg_close_device( &dh ); - return rc; } // do_mbghrtime +static MBG_DEV_HANDLER_FNC do_mbghrtime; + static /*HDR*/ @@ -220,6 +226,9 @@ void usage( void ) mbg_print_opt_info( "-n num", "run num loops" ); mbg_print_opt_info( "-b", "burst read" ); mbg_print_opt_info( "-r", "read raw time stamps, no cycles" ); + mbg_print_opt_info( "-s num", "sleep num seconds between calls (implies -c)" ); + mbg_print_opt_info( "-u num", "sleep num microseconds between calls (implies -c)" ); + mbg_print_opt_info( "-v", "increase verbosity" ); mbg_print_device_options(); puts( "" ); @@ -235,7 +244,7 @@ int main( int argc, char *argv[] ) mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); // check command line parameters - while ( ( c = getopt( argc, argv, "bcn:rh?" ) ) != -1 ) + while ( ( c = getopt( argc, argv, "bcn:rs:u:vh?" ) ) != -1 ) { switch ( c ) { @@ -255,6 +264,20 @@ int main( int argc, char *argv[] ) read_raw = 1; break; + case 's': + sleep_secs = atoi( optarg ); + loops = -1; + break; + + case 'u': + sleep_usecs = atoi( optarg ); + loops = -1; + break; + + case 'v': + verbose++; + break; + case 'h': case '?': default: @@ -265,11 +288,11 @@ int main( int argc, char *argv[] ) if ( must_print_usage ) { usage(); - return 1; + return MBG_EXIT_CODE_USAGE; } - #if !defined( MBG_PC_CYCLES_SUPPORTED ) + #if !MBG_PC_CYCLES_SUPPORTED printf( "** Warning: No cycles support to compute real latencies on this platform!\n" ); if ( !read_raw ) @@ -282,12 +305,8 @@ int main( int argc, char *argv[] ) #endif - // The function below checks which devices have been specified - // on the command, and for each device - // - tries to open the device - // - shows basic device info - // - calls the function passed as last parameter - rc = mbg_check_devices( argc, argv, optind, do_mbghrtime ); + // Handle each of the specified devices. + rc = mbg_handle_devices( argc, argv, optind, do_mbghrtime, 0 ); - return abs( rc ); + return mbg_rc_is_success( rc ) ? MBG_EXIT_CODE_SUCCESS : MBG_EXIT_CODE_FAIL; } diff --git a/src/external/bsd/meinberg/dist/mbgirigcfg/Makefile b/src/external/bsd/meinberg/dist/mbgirigcfg/Makefile index fbeb4b5..9639209 100755 --- a/src/external/bsd/meinberg/dist/mbgirigcfg/Makefile +++ b/src/external/bsd/meinberg/dist/mbgirigcfg/Makefile @@ -1,15 +1,16 @@ ######################################################################### # -# $Id: Makefile 1.5.1.2 2010/08/30 09:05:23 martin TEST $ +# $Id: Makefile 1.6 2017/07/05 18:50:01 martin REL_M $ # # Description: # Makefile for mbgirigcfg. # # ----------------------------------------------------------------------- # $Log: Makefile $ -# Revision 1.5.1.2 2010/08/30 09:05:23 martin -# Revision 1.5.1.1 2010/08/30 08:21:45 martin +# Revision 1.6 2017/07/05 18:50:01 martin +# Updated list of object files and use top level +# Makefile properly. # Revision 1.5 2009/07/24 10:31:17 martin # Moved declarations to a common file which is now included. # Revision 1.4 2008/12/22 11:56:59 martin @@ -24,11 +25,16 @@ ######################################################################### TARGET = mbgirigcfg -INST_DIR = /usr/local/sbin +INST_TO_SBIN = 1 OBJS = $(TARGET).o OBJS += mbgdevio.o +OBJS += mbgutil.o +OBJS += timeutil.o +OBJS += str_util.o OBJS += toolutil.o +OBJS += mbgerror.o +OBJS += cfg_hlp.o OBJS += gpsutils.o BASEDIR := .. diff --git a/src/external/bsd/meinberg/dist/mbgirigcfg/mbgirigcfg.c b/src/external/bsd/meinberg/dist/mbgirigcfg/mbgirigcfg.c index b55e3f9..c3a89c8 100755 --- a/src/external/bsd/meinberg/dist/mbgirigcfg/mbgirigcfg.c +++ b/src/external/bsd/meinberg/dist/mbgirigcfg/mbgirigcfg.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgirigcfg.c 1.10.1.12 2011/07/19 12:59:06 martin TRASH $ + * $Id: mbgirigcfg.c 1.11 2017/07/05 19:05:27 martin REL_M $ * * Description: * Main file for the mbgirigcfg program which can be used to configure @@ -10,26 +10,19 @@ * * ----------------------------------------------------------------------- * $Log: mbgirigcfg.c $ - * Revision 1.10.1.12 2011/07/19 12:59:06 martin - * Revision 1.10.1.11 2011/07/07 15:08:35 martin - * Removed obsolete code. - * Revision 1.10.1.10 2011/07/06 14:53:50 martin - * Revision 1.10.1.9 2011/07/05 15:35:54 martin - * Modified version handling. - * Revision 1.10.1.8 2011/07/05 14:35:18 martin + * Revision 1.11 2017/07/05 19:05:27 martin * New way to maintain version information. - * Revision 1.10.1.7 2011/07/05 12:24:58 martin - * Revision 1.10.1.6 2011/07/04 10:30:29 martin + * Support build under Windows. + * New parameter -i to let incoming TFOM flag be ignored. + * Accept parameter -? to print usage. * Use getopt() for option processing. * Support multiple devices. - * Revision 1.10.1.5 2011/07/01 13:49:47 martin - * bug fixes. - * Revision 1.10.1.4 2011/02/02 12:28:44 martin - * Revision 1.10.1.3 2010/08/30 08:22:24 martin - * Revision 1.10.1.2 2010/08/19 13:57:42 martin - * Revision 1.10.1.1 2010/08/19 11:26:12 martin - * Accept parameter -? to print usage. - * New parameter -i to let incoming TFOM flag be ignored. + * New parameter -X which set ref offs to 'unconfigured'. + * Support specification of minutes for ref offset. + * Use safe string functions. + * Use more functions from common library modules. + * Use codes and inline functions from mbgerror.h. + * Proper return codes and exit codes. * Revision 1.10 2009/09/29 15:02:15 martin * Updated version number to 3.4.0. * Revision 1.9 2009/07/24 09:50:08 martin @@ -62,9 +55,9 @@ // include Meinberg headers #include <mbgdevio.h> +#include <mbgutil.h> #include <mbgtime.h> #include <pcpsmktm.h> -#include <pcpsutil.h> #include <pcpslstr.h> #include <myutil.h> #include <toolutil.h> @@ -74,7 +67,6 @@ #include <stdlib.h> #include <string.h> #include <time.h> -#include <unistd.h> #define MBG_MICRO_VERSION 0 @@ -116,7 +108,28 @@ static const char *icode_rx_descr[N_ICODE_RX] = DEFAULT_ICODE_RX_DESCRIPTIONS_EN static const char *icode_tx_names[N_ICODE_TX] = DEFAULT_ICODE_TX_NAMES; static const char *icode_tx_descr[N_ICODE_TX] = DEFAULT_ICODE_TX_DESCRIPTIONS_ENG; -static int max_ref_offs_h = MBG_REF_OFFS_MAX / MINS_PER_HOUR; +static char str_ref_offs_min[16]; // need to be snprint_hours_mins'ed with -MBG_REF_OFFS_MAX +static char str_ref_offs_max[16]; // need to be snprint_hours_mins'ed with +MBG_REF_OFFS_MAX + + + +static /*HDR*/ +size_t snprint_hours_mins( char *s, size_t max_len, long num_minutes ) +{ + ldiv_t ldt = ldiv( labs( num_minutes ), MINS_PER_HOUR ); + + size_t n = mbg_snprintf( s, max_len, "%c%li", + ( num_minutes < 0 ) ? '-' : '+', ldt.quot ); + + if ( ldt.rem ) + n += mbg_snprintf( &s[n], max_len - n, ":%02li", ldt.rem ); + + n += mbg_snprintf( &s[n], max_len - n, "h" ); + + return n; + +} // snprint_hours_mins + static /*HDR*/ @@ -126,20 +139,11 @@ int get_cfg( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev ) int rc_tx = MBG_SUCCESS; if ( _pcps_is_irig_rx( pdev ) ) - { - rc_rx = mbg_get_irig_rx_info( dh, &irig_rx_info ); - - if ( rc_rx == MBG_SUCCESS && _pcps_has_ref_offs( pdev ) ) - rc_rx = mbg_get_ref_offs( dh, &ref_offs ); - - if ( rc_rx == MBG_SUCCESS && _pcps_has_opt_flags( pdev ) ) - rc_rx = mbg_get_opt_info( dh, &opt_info ); - } + rc_rx = mbg_get_all_irig_rx_info( dh, pdev, &irig_rx_info, + &ref_offs, &opt_info ); if ( _pcps_has_irig_tx( pdev ) ) - { rc_tx = mbg_get_irig_tx_info( dh, &irig_tx_info ); - } if ( rc_rx != MBG_SUCCESS ) @@ -164,20 +168,10 @@ int save_cfg( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev ) int rc_tx = MBG_SUCCESS; if ( _pcps_is_irig_rx( pdev ) ) - { - rc_rx = mbg_set_irig_rx_settings( dh, &irig_rx_info.settings ); - - if ( rc_rx == MBG_SUCCESS && _pcps_has_ref_offs( pdev ) ) - rc_rx = mbg_set_ref_offs( dh, &ref_offs ); - - if ( rc_rx == MBG_SUCCESS && _pcps_has_opt_flags( pdev ) ) - rc_rx = mbg_set_opt_settings( dh, &opt_info.settings ); - } - + rc_rx = mbg_save_all_irig_rx_settings( dh, pdev, &irig_rx_info.settings, + &ref_offs, &opt_info.settings ); if ( rc_rx == MBG_SUCCESS && _pcps_has_irig_tx( pdev ) ) - { rc_tx = mbg_set_irig_tx_settings( dh, &irig_tx_info.settings ); - } if ( rc_rx != MBG_SUCCESS ) printf( "** Error writing IRIG RX configuration.\n" ); @@ -186,7 +180,7 @@ int save_cfg( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev ) printf( "** Error writing IRIG TX configuration.\n" ); if ( rc_rx != MBG_SUCCESS || rc_tx != MBG_SUCCESS ) - return -1; + return -1; //##++ return MBG_SUCCESS; @@ -198,7 +192,8 @@ static /*HDR*/ void print_cfg_rx( const char *info, const char *msg ) { int idx = irig_rx_info.settings.icode; - int ref_offs_h = ref_offs / MINS_PER_HOUR; + char ws[16]; + const char *cp = NULL; printf( "%s %s configuration:\n", info, msg ); @@ -213,10 +208,20 @@ void print_cfg_rx( const char *info, const char *msg ) printf( " " DEFAULT_STR_IRIG_OFFS_EN ": " ); - if ( abs( ref_offs_h ) > max_ref_offs_h ) - printf( "** not configured **\n" ); + if ( labs( ref_offs ) > MBG_REF_OFFS_MAX ) + cp = "** not configured **"; else - printf( "%+i h\n", ref_offs_h ); + { + snprint_hours_mins( ws, sizeof( ws ), ref_offs ); + cp = ws; + } + + printf( "%s", cp ); + + if ( ( 1UL << idx ) & MSK_ICODE_RX_HAS_TZI ) + printf( " (ignored with code %s)", icode_rx_names[idx] ); + + printf( "\n" ); if ( opt_info.supp_flags & MBG_OPT_FLAG_STR_UTC ) printf( " " DEFAULT_STR_IRIG_TIMESTR_UTC_EN ": %s\n", @@ -284,27 +289,69 @@ void set_new_icode_rx( char *s ) static /*HDR*/ void set_new_ref_offs( char *s ) { - int new_ref_offs_h; + long new_ref_offs; + char *cp = s; + int is_negative = 0; + + // expected format: [-]hh[:mm] + + // In case of e.g. "-0:30" conversion of the first part "-0" would yield + // 0 and thus the sign would get lost, so we check the sign explicitly. + if ( *cp == '-' ) + is_negative = 1; + + new_ref_offs = strtol( cp, &cp, 10 ); + + if ( cp == s ) // no number found at beginning + goto invalid; - new_ref_offs_h = atoi( s ); + new_ref_offs *= MINS_PER_HOUR; - if ( abs( new_ref_offs_h ) > max_ref_offs_h ) + if ( *cp++ == ':' ) // offset minutes seem to follow { - printf( "** New IRIG time offset %ih exceeds range (%+ih..%+ih).\n", - new_ref_offs_h, -max_ref_offs_h, max_ref_offs_h ); - cfg_err_rx = 1; + long tmp = strtol( cp, &cp, 10 ); + + // the value behind the colon should always be positive + if ( tmp < 0 || tmp >= MINS_PER_HOUR ) + goto invalid; + + // apply the minutes offset according to the sign + new_ref_offs += is_negative ? -tmp : tmp; } - else + + if ( labs( new_ref_offs ) > MBG_REF_OFFS_MAX ) { - ref_offs = new_ref_offs_h * MINS_PER_HOUR; - changed_cfg_rx = 1; + char ws[16]; + snprint_hours_mins( ws, sizeof( ws ), new_ref_offs ); + printf( "** New IRIG time offset %s exceeds range (%s..%s).\n", + ws, str_ref_offs_min, str_ref_offs_max ); + goto invalid; } + ref_offs = (MBG_REF_OFFS) new_ref_offs; + changed_cfg_rx = 1; + + return; + + +invalid: + cfg_err_rx = 1; + } // set_new_ref_offs static /*HDR*/ +void set_ref_offs_not_cfgd( void ) +{ + ref_offs = MBG_REF_OFFS_NOT_CFGD; + changed_cfg_rx = 1; + +} // set_ref_offs_not_cfgd + + + +static /*HDR*/ void set_new_str_utc( char *s ) { int this_cfg_err; @@ -461,7 +508,7 @@ void check_cmd_line( int argc, char *argv[], const PCPS_DEV *pdev ) // force checking all parameters since this may be called several times optind = 1; - while ( ( c = getopt( argc, argv, "h?" "r:o:u:i:" "t:l:s:" ) ) != -1 ) + while ( ( c = getopt( argc, argv, "h?" "r:o:u:i:X" "t:l:s:" ) ) != -1 ) { switch ( c ) { @@ -493,6 +540,11 @@ void check_cmd_line( int argc, char *argv[], const PCPS_DEV *pdev ) set_new_tfom_flag( optarg, &irig_rx_info.settings, &changed_cfg_rx, &cfg_err_rx ); break; + case 'X': // set UTC ref_offs to "not configured" + if ( chk_dev_rx( pdev ) ) + set_ref_offs_not_cfgd(); + break; + // IRIG output options @@ -553,10 +605,20 @@ void usage( void ) printf( "\n" ); printf( - " -o offs specifies the IRIG input time offset from UTC, in hours,\n" - " where \"offs\" can be a value in the range %+i..%+i\n" + " -o offs specifies the IRIG input time offset from UTC, in hours and optional minute,\n" + " where \"offs\" can be a value in the range %s .. %s.\n" + " When the device is shipped this parameter is set to \"not configured\"\n" + " to prevent the receiver from synchronizing to an IRIG input signal with\n" + " unknown UTC offset immediately after installation, which could cause\n" + " the system time to be set wrong by the time synchronization software.\n" "\n", - -max_ref_offs_h, max_ref_offs_h + str_ref_offs_min, str_ref_offs_max + ); + + printf( + " -X set the IRIG input time offset from UTC to \"not configured\".\n" + " See also the -o option.\n" + "\n" ); printf( @@ -576,6 +638,7 @@ void usage( void ) "\n" ); + printf( "Options supported by IRIG transmitters:\n" "\n" @@ -634,13 +697,17 @@ int do_mbgirigcfg( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) { printf( "** This device does not provide an IRIG input or output.\n" ); must_print_help_info = 1; - return rc; + goto done; } check_cmd_line( glb_argc, glb_argv, p_dev ); if ( cfg_err_rx || cfg_err_tx ) + { + printf( "** Invalid configuration options specified.\n" ); must_print_help_info = 1; + goto done; + } if ( changed_cfg_rx || changed_cfg_tx ) { @@ -653,7 +720,7 @@ int do_mbgirigcfg( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) rc = save_cfg( dh, p_dev ); - if ( mbg_ioctl_err( rc, "save IRIG configuration" ) ) + if ( mbg_cond_err_msg( rc, "save IRIG configuration" ) ) goto done; } else @@ -672,6 +739,8 @@ done: } // do_mbgirigcfg +static MBG_DEV_HANDLER_FNC do_mbgirigcfg; + int main( int argc, char *argv[] ) @@ -680,28 +749,28 @@ int main( int argc, char *argv[] ) mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); + snprint_hours_mins( str_ref_offs_min, sizeof( str_ref_offs_min ), -MBG_REF_OFFS_MAX ); + snprint_hours_mins( str_ref_offs_max, sizeof( str_ref_offs_max ), MBG_REF_OFFS_MAX ); + check_cmd_line( argc, argv, NULL ); if ( must_print_usage ) { usage(); - return 1; + return MBG_EXIT_CODE_USAGE; } + // We work with copies of the arguments here since the arguments + // are evaluated once more for each device. glb_argc = argc; glb_argv = argv; - - // The function below checks which devices have been specified - // on the command, and for each device - // - tries to open the device - // - shows basic device info - // - calls the function passed as last parameter - rc = mbg_check_devices( glb_argc, glb_argv, optind, do_mbgirigcfg ); + // Handle each of the specified devices. + rc = mbg_handle_devices( glb_argc, glb_argv, optind, do_mbgirigcfg, 0 ); if ( must_print_help_info ) printf( "For help type \"%s -h\"\n\n", pname ); - return abs( rc ); + return mbg_rc_is_success( rc ) ? MBG_EXIT_CODE_SUCCESS : MBG_EXIT_CODE_FAIL; } diff --git a/src/external/bsd/meinberg/dist/mbglib/bsd/mbg_bsd.h b/src/external/bsd/meinberg/dist/mbglib/bsd/mbg_bsd.h deleted file mode 100755 index 9efef59..0000000 --- a/src/external/bsd/meinberg/dist/mbglib/bsd/mbg_bsd.h +++ /dev/null @@ -1,49 +0,0 @@ - -/************************************************************************** - * - * $Id: mbg_bsd.h 1.1.1.1 2011/02/04 14:44:33 martin TEST $ - * - * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany - * - * Description: - * OS dependend definitions/redefinitions for *BSD. - * - * ----------------------------------------------------------------------- - * $Log: mbg_bsd.h $ - * Revision 1.1.1.1 2011/02/04 14:44:33 martin - * Revision 1.1 2011/01/26 16:09:33 martin - * Initial revision. - * - **************************************************************************/ - -#ifndef _MBG_BSD_H -#define _MBG_BSD_H - - -/* Other headers to be included */ - -#include <sys/types.h> -#include <sys/bus.h> -#include <machine/bus.h> - - -#ifdef _MBG_BSD - #define _ext -#else - #define _ext extern -#endif - - -/* Start of header body */ - -// definitions for clock() support in kernel drivers -// extern unsigned long volatile jiffies; //##++ this is just a workaround to build without errors -// #define clock() jiffies - - -/* End of header body */ - -#undef _ext - -#endif /* _MBG_BSD_H */ - diff --git a/src/external/bsd/meinberg/dist/mbglib/bsd/pci_bsd.h b/src/external/bsd/meinberg/dist/mbglib/bsd/pci_bsd.h index f032234..7ac79e9 100755 --- a/src/external/bsd/meinberg/dist/mbglib/bsd/pci_bsd.h +++ b/src/external/bsd/meinberg/dist/mbglib/bsd/pci_bsd.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pci_bsd.h 1.1 2011/01/26 16:09:33 martin TEST $ + * $Id: pci_bsd.h 1.2 2012/11/07 10:23:46 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,6 +11,8 @@ * * ----------------------------------------------------------------------- * $Log: pci_bsd.h $ + * Revision 1.2 2012/11/07 10:23:46 martin + * Cleanup. * Revision 1.1 2011/01/26 16:09:33 martin * Initial revision. * @@ -24,9 +26,6 @@ #include <pcidefs.h> -#include <mbg_bsd.h> -//##++ #include <linux/pci.h> - #ifdef _PCI_BSD #define _ext @@ -37,12 +36,6 @@ /* Start of header body */ -//##++ update comment -// The pcibios_..() calls use below are not supported by -// recent 2.6.x kernels. However, those kernels should use -// the PNP PCI interface anyway, whereas the functions below -// are only used by non-PNP environments. - #define _mbg_pci_find_bios( _p1, _p2, _p3 ) \ ( pcibios_present() ? PCI_SUCCESS : PCI_NO_SUCCESS ) diff --git a/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.c b/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.c index a1b14d1..1f81e6f 100755 --- a/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.c +++ b/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: rsrc_bsd.c 1.1.1.1 2011/02/07 15:28:32 martin TEST $ + * $Id: rsrc_bsd.c 1.2 2017/07/06 09:05:19 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,8 +10,9 @@ * * ----------------------------------------------------------------------- * $Log: rsrc_bsd.c $ - * Revision 1.1.1.1 2011/02/07 15:28:32 martin - * Removed obsolete code; more cleanup required. + * Revision 1.2 2017/07/06 09:05:19 martin + * Removed obsolete code. + * Cleanup. * Revision 1.1 2011/01/26 16:09:33 martin * Initial revision. * @@ -22,48 +23,16 @@ #undef _RSRC_BSD -// extern const char *pcps_driver_name; - - -#if 1 //##++ ||defined( KERNEL_VERSION ) && ( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 0 ) ) - - // check_region(), request_region(), and release_region() used in 2.2.x and - // maybe early 2.4.x kernels have been replaced by more versatile functions. - // Additionally, there have been defined some macros with the names - // of the old functions, but calling the new functions. Those macros are still - // supported by early 2.6.x kernels, but may not be supported anymore in the future. - // So if those macros don't exist then only the old functions can be used and we - // use some macros with the new names and call the old functions. - - #if !defined( request_region ) - #define __check_region( _rsrc, _start, _n ) \ - check_region( (_start), (_n) ) - - #define __request_region( _rsrc, _start, _n, _name ) \ - request_region( (_start), (_n), (_name) ) - - #define __release_region( _rsrc, _start, _n ) \ - release_region( (_start), (_n) ) - #endif - -#endif - - /*HDR*/ int rsrc_alloc_ports( ushort port, ushort n, ushort decode_width ) { -#if 0 //##++ - int rc = __check_region( &ioport_resource, port, n ); - - if ( rc < 0 ) - return( rc ); + // Nothing to do; just avoid "unused variable" warnings + (void) port; + (void) n; + (void) decode_width; - - __request_region( &ioport_resource, port, n, pcps_driver_name ); -#endif - - return 0; + return 0; // success } // rsrc_alloc_ports @@ -72,11 +41,10 @@ int rsrc_alloc_ports( ushort port, ushort n, ushort decode_width ) /*HDR*/ void rsrc_dealloc_ports( ushort port, ushort n ) { -#if 0 //##++ - __release_region( &ioport_resource, port, n ); -#endif + // Nothing to do; just avoid "unused variable" warnings + (void) port; + (void) n; } // rsrc_dealloc_ports - diff --git a/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.h b/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.h index ba1af48..80ea291 100755 --- a/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.h +++ b/src/external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: rsrc_bsd.h 1.1 2011/01/26 16:09:34 martin TEST $ + * $Id: rsrc_bsd.h 1.2 2012/11/07 10:24:10 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,8 @@ * * ----------------------------------------------------------------------- * $Log: rsrc_bsd.h $ + * Revision 1.2 2012/11/07 10:24:10 martin + * Removed obsolete include. * Revision 1.1 2011/01/26 16:09:34 martin * Initial revision. * @@ -21,7 +23,6 @@ /* Other headers to be included */ -#include <mbg_bsd.h> #include <rsrc.h> #include <words.h> diff --git a/src/external/bsd/meinberg/dist/mbglib/common/amccdefs.h b/src/external/bsd/meinberg/dist/mbglib/common/amccdefs.h index 1d68cbe..3aeba78 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/amccdefs.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/amccdefs.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: amccdefs.h 1.2 2007/06/06 10:16:53 martin REL_M $ + * $Id: amccdefs.h 1.3 2017/05/10 15:21:33 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,8 @@ * * ----------------------------------------------------------------------- * $Log: amccdefs.h $ + * Revision 1.3 2017/05/10 15:21:33 martin + * Tiny cleanup. * Revision 1.2 2007/06/06 10:16:53 martin * Moved some IRQ bit masks here. * Revision 1.1 2000/07/20 09:19:39Z MARTIN @@ -33,6 +35,10 @@ /* Start of header body */ +#ifdef __cplusplus +extern "C" { +#endif + // The following operation registers are implemented // in the S5933. The registers can be accessed via port @@ -88,12 +94,6 @@ #undef _ext -/* function prototypes: */ - -#ifdef __cplusplus -extern "C" { -#endif - /* ----- function prototypes begin ----- */ /* This section was generated automatically */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/cfg_hlp.c b/src/external/bsd/meinberg/dist/mbglib/common/cfg_hlp.c new file mode 100755 index 0000000..4a9c674 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/cfg_hlp.c @@ -0,0 +1,1518 @@ + +/************************************************************************** + * + * $Id: cfg_hlp.c 1.2 2017/07/05 12:17:38 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Meinberg device configuration helper functions. + * + * ----------------------------------------------------------------------- + * $Log: cfg_hlp.c $ + * Revision 1.2 2017/07/05 12:17:38 martin + * Support functions for TLV, IMS, GPIO, and + * mbg_snprint_revision() provided by philipp. + * Support functions for network configuration, + * NTP configuration, ALL_UCAP stuff, SNMP and + * MONITORING, as well as ALL_PTP_V2_COMMON_DATASETS + * and ALL_PTP_V1_COMMON_DATASETS provided by thomas-b. + * Support functions for xmulti_ref and IO PORT stuff + * provided by philipp and thomas-b. + * More common GNSS support. + * New functions alloc_dev_hw_id() and chk_free_dev_hw_id(). + * Tried portable printing of int64_t types. + * Account for frac_sec_from_bin() obsoleted by + * bin_frac_32_to_dec_frac(). + * Revision 1.1 2014/04/25 09:14:49 martin + * Initial revision. + * + **************************************************************************/ + +#define _CFG_HLP + #include <cfg_hlp.h> +#undef _CFG_HLP + +#include <mbgerror.h> +#include <timeutil.h> +#include <str_util.h> +#include <myutil.h> +#include <mbgtime.h> + +#if defined( _PRELIMINARY_CODE ) + #include <mbgmktm.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + + + +/*HDR*/ +/** + * @brief Check if a software revision name should be displayed + * + * The software revision name is usually empty, except if the + * firmware is a customized version, in which case the field + * contains an identifier string. + * + * There are some standard firmware versions where this string + * is not empty but padded with spaces, etc., so we try to + * clean this up and display the string properly, if appropriate. + * + * @param[in,out] p The ::SW_REV name to check + * @param[in] verbose The app's verbosity level + * + * @return != 0 if SW name should be displayed + */ +int chk_sw_rev_name( SW_REV *p, int verbose ) +{ + if ( verbose > 1 ) // more than just verbose + return 1; // just return raw string + + trim_whitespace( p->name ); + + // Some firmware versions have "CC_STANDARD" in their standard version, + // which doesn't provide any valuable information. + // We discard this by default. + if ( strstr( p->name, "CC_STANDARD" ) ) + p->name[0] = 0; + + if ( verbose ) + return 1; // calling app should display string, even if empty + + // calling app should display string only if not empty + return strlen( p->name ) != 0; + +} // chk_sw_rev_name + + + +/*HDR*/ +int get_str_idx( const char *search, + const char *str_table[], + int n_entries ) +{ + int i; + + for ( i = 0; i < n_entries; i++ ) + if ( strcmp( search, str_table[i] ) == 0 ) + return i; + + return -1; + +} // get_str_idx + + + +/*HDR*/ +int get_baud_rate_idx( BAUD_RATE baud_rate ) +{ + int i; + + for ( i = 0; i < N_MBG_BAUD_RATES; i++ ) + if ( baud_rate == mbg_baud_rate[i] ) + return i; + + return -1; + +} // get_baud_rate_idx + + + +/*HDR*/ +int get_framing_idx( const char *framing ) +{ + return get_str_idx( framing, mbg_framing_str, N_MBG_FRAMINGS ); + +} // get_framing_idx + + + +/*HDR*/ +void port_settings_from_port_parm_mode( + PORT_SETTINGS *p_ps, + uint8_t pp_mode, + int str_type_cap + ) +{ + if ( pp_mode >= STR_UCAP ) + { + p_ps->str_type = str_type_cap; + p_ps->mode = ( pp_mode == STR_UCAP ) ? STR_AUTO : STR_ON_REQ; + } + else + { + p_ps->str_type = 0; + p_ps->mode = pp_mode; + } + +} // port_settings_from_port_parm_mode + + + +/*HDR*/ +void port_parm_mode_from_port_settings( + uint8_t *pp_mode, + const PORT_SETTINGS *p_ps, + int str_type_cap + ) +{ + if ( p_ps->str_type == str_type_cap ) + *pp_mode = ( p_ps->mode == STR_ON_REQ ) ? STR_UCAP_REQ : STR_UCAP; + else + *pp_mode = p_ps->mode; + +} // port_parm_mode_from_port_settings + + + +/*HDR*/ +void port_settings_from_port_parm( + PORT_SETTINGS *p_ps, + int port_num, + const PORT_PARM *p_pp, + int cap_str_idx +) +{ + p_ps->parm = p_pp->com[port_num]; + + port_settings_from_port_parm_mode( p_ps, p_pp->mode[port_num], + cap_str_idx ); + +} // port_info_from_port_parm + + + +/*HDR*/ +void port_parm_from_port_settings( + PORT_PARM *p_pp, + int port_num, + const PORT_SETTINGS *p_ps, + int cap_str_idx +) +{ + p_pp->com[port_num] = p_ps->parm; + + port_parm_mode_from_port_settings( &p_pp->mode[port_num], + p_ps, cap_str_idx ); + +} // port_parm_from_port_settings + + + +/*HDR*/ +uint32_t check_valid_port_info( const PORT_INFO *p_pi, + const STR_TYPE_INFO_IDX str_type_info_idx[], + int n_str_type ) +{ + const PORT_SETTINGS *p_ps = &p_pi->port_settings; + int idx; + uint32_t flags = 0; + + + if ( p_pi->supp_baud_rates & ~_mask( N_MBG_BAUD_RATES ) ) + flags |= MBG_PS_MSK_BAUD_RATE_OVR_SW; // dev. supports more baud rates than driver + + idx = get_baud_rate_idx( p_ps->parm.baud_rate ); + + if ( !_inrange( idx, 0, N_MBG_BAUD_RATES ) || + !_is_supported( idx, p_pi->supp_baud_rates ) ) + flags |= MBG_PS_MSK_BAUD_RATE; + + + if ( p_pi->supp_framings & ~_mask( N_MBG_FRAMINGS ) ) + flags |= MBG_PS_MSK_FRAMING_OVR_SW; // dev. supports more framings than driver + + idx = get_framing_idx( p_ps->parm.framing ); + + if ( !_inrange( idx, 0, N_MBG_FRAMINGS ) || + !_is_supported( idx, p_pi->supp_framings ) ) + flags |= MBG_PS_MSK_FRAMING; + + + if ( p_ps->parm.handshake >= N_COM_HS ) + flags |= MBG_PS_MSK_HS_OVR_SW; // handshake index exceeds max. + + if ( p_ps->parm.handshake != HS_NONE ) // currently no device supports any handshake + flags |= MBG_PS_MSK_HS; // handshake mode not supp. by dev. + + + if ( p_pi->supp_str_types & ~_mask( n_str_type ) ) + flags |= MBG_PS_MSK_STR_TYPE_OVR_SW; // firmware error: more string types supported than reported + + idx = p_ps->str_type; + + if ( idx >= n_str_type ) + flags |= MBG_PS_MSK_STR_TYPE_OVR_DEV; // string type index exceeds max. + else + { + if ( !_is_supported( idx, p_pi->supp_str_types ) ) + flags |= MBG_PS_MSK_STR_TYPE; // string type not supported by this port + else + { + // Use the str_type index to get the supported output mode mask + // from the string type info table. This is required to check + // whether the selected mode is supported by the selected + // string type. + ulong supp_modes = str_type_info_idx[idx].str_type_info.supp_modes; + + if ( supp_modes & ~_mask( N_STR_MODE ) ) + flags |= MBG_PS_MSK_STR_MODE_OVR_SW; // dev. supports more string modes than driver + + idx = p_ps->mode; + + if ( idx >= N_STR_MODE ) // mode is always >= 0 + flags |= MBG_PS_MSK_STR_MODE_OVR_SW; // string mode index exceeds max. + else + if ( !_is_supported( idx, supp_modes ) ) + flags |= MBG_PS_MSK_STR_MODE; // string mode not supp. by this string type and port + } + } + + + if ( p_ps->flags != 0 ) /* currently always 0 */ + flags |= MBG_PS_MSK_FLAGS_OVR_SW | MBG_PS_MSK_FLAGS; + + + return flags; + +} // check_valid_port_info + + + +/*HDR*/ +int valid_port_info( const PORT_INFO *p_pi, + const STR_TYPE_INFO_IDX str_type_info_idx[], + int n_str_type ) +{ + return check_valid_port_info( p_pi, str_type_info_idx, n_str_type ) == 0; + +} // valid_port_info + + + +/*HDR*/ +int setup_port_info_from_port_settings( PORT_INFO_IDX pii[], const PORT_PARM *p_pp, + const RECEIVER_INFO *p_ri ) +{ + int i; + + for ( i = 0; i < p_ri->n_com_ports; i++ ) + { + PORT_INFO_IDX *p_pii = &pii[i]; + PORT_INFO *p_pi = &p_pii->port_info; + + p_pii->idx = i; + port_settings_from_port_parm( &p_pi->port_settings, i, p_pp, 1 ); + + p_pi->supp_baud_rates = DEFAULT_GPS_BAUD_RATES_C166; + p_pi->supp_framings = DEFAULT_GPS_FRAMINGS_C166; + p_pi->supp_str_types = DEFAULT_SUPP_STR_TYPES_GPS; + } + + return MBG_SUCCESS; + +} // setup_port_info_from_port_settings + + + +/*HDR*/ +int setup_default_str_type_info_idx( STR_TYPE_INFO_IDX stii[], const RECEIVER_INFO *p_ri ) +{ + int i; + + for ( i = 0; i < p_ri->n_str_type; i++ ) + { + STR_TYPE_INFO_IDX *stip = &stii[i]; + stip->idx = i; + stip->str_type_info = default_str_type_info[i]; + } + + return MBG_SUCCESS; + +} // setup_default_str_type_info_idx + + + +/*HDR*/ +int chk_set_n_gnss_supp( ALL_GNSS_INFO *p_agi ) +{ + p_agi->n_gnss_supp = num_bits_set( p_agi->gnss_mode_info.supp_gnss_types ); + + if ( p_agi->n_gnss_supp > N_GNSS_TYPES ) + return MBG_ERR_N_GNSS_EXCEEDS_SUPP; + + return MBG_SUCCESS; + +} // chk_set_n_gnss_supp + + + +/*HDR*/ +/** + * @brief + * + * ### Setup GNSS info from stat_info so we can use the same printing routine + */ +void setup_gps_only_sat_info_idx_from_statinfo( ALL_GNSS_INFO *p_agi ) +{ + STAT_INFO *p_si = &p_agi->stat_info; + GNSS_SAT_INFO_IDX *p_gsii = &p_agi->gnss_sat_info_idx[GNSS_TYPE_GPS]; + GNSS_SAT_INFO *p_gsi = &p_gsii->gnss_sat_info; + + memset( p_gsii, 0, sizeof( *p_gsii ) ); + p_gsii->idx = GNSS_TYPE_GPS; + + p_gsi->gnss_type = GNSS_TYPE_GPS; + p_gsi->svs_in_view = p_si->svs_in_view; + p_gsi->good_svs = p_si->good_svs; + +} // setup_gps_only_sat_info_idx_from_statinfo + + + +/*HDR*/ +/** + * @brief + * + * Setup GNSS info from stat_info so we can use the same printing routine + */ +int setup_gps_only_gnss_info_from_statinfo( ALL_GNSS_INFO *p_agi ) +{ + MBG_GNSS_MODE_INFO *p_gmi = &p_agi->gnss_mode_info; + + memset( p_gmi, 0, sizeof( *p_gmi ) ); + + p_gmi->supp_gnss_types = MBG_GNSS_TYPE_MSK_GPS; + p_gmi->settings.gnss_set = p_gmi->supp_gnss_types; + + memset( p_agi->gnss_sat_info_idx, 0, sizeof( p_agi->gnss_sat_info_idx ) ); + + setup_gps_only_sat_info_idx_from_statinfo( p_agi ); + + return chk_set_n_gnss_supp( p_agi ); + +} // setup_gps_only_gnss_info_from_statinfo + + + +/*HDR*/ +void chk_free_dev_hw_id( DEVICE_INFO *p ) +{ + if ( p->hw_id ) + { + free( p->hw_id ); + p->hw_id = NULL; + } + +} // chk_free_dev_hw_id + + + +/*HDR*/ +int alloc_dev_hw_id( DEVICE_INFO *p, size_t len ) +{ + if ( p->hw_id ) + return MBG_ERR_ALREADY_ALLOC; + + + p->hw_id = (char *) malloc( len ); + + if ( p->hw_id == NULL ) + return MBG_ERR_NO_MEM; + + return MBG_SUCCESS; + +} // alloc_dev_hw_id + + + +/*HDR*/ +const char *get_fw_id_from_hw_id( const char *hw_id ) +{ + int i; + + for ( i = 0; i < N_SUPP_DEV_TOTAL; i++ ) + { + DEVICE_INFO *p = &device_list[i]; + + if ( strlen( p->fw_id ) && p->hw_id ) //### TODO check if this still works as expected + { + if ( strcmp( hw_id, p->hw_id ) == 0 ) + { + if ( strlen( p->fw_id ) > 0 ) + return p->fw_id; + + #if defined( DEBUG ) + fprintf( stderr, "Length of fw_id is 0 in %s for device %i (%s)\n", + __func__, i, p->hw_id ); + #endif + } + } + } + + return NULL; + +} // get_fw_id_from_hw_id + + + +/*HDR*/ +const char *get_hw_id_from_fw_id( const char *fw_id ) +{ + int i; + + for ( i = 0; i < N_SUPP_DEV_TOTAL; i++ ) + { + DEVICE_INFO *p = &device_list[i]; + + if ( strlen( p->fw_id ) && p->hw_id ) //### TODO check if this still works as expected + { + if ( strcmp( fw_id, p->fw_id ) == 0 ) + { + if ( strlen( p->hw_id ) > 0 ) + return p->hw_id; + + #if defined( DEBUG ) + fprintf( stderr, "Length of hw_id is 0 in %s for device %i (%s)\n", + __func__, i, p->fw_id ); + #endif + } + } + } + + return NULL; + +} // get_hw_id_from_fw_id + + + +/*HDR*/ +/** + * @brief Returns the currently used ::MBG_IO_PORT_TYPE_INFO_IDX for the appropriate ::MBG_IO_PORT_INFO_IDX + * + * @param[in] all_io_port_info Pointer to the ::ALL_IO_PORT_INFO, containing the current configuration + * @param[in] io_port_info_idx Pointer to the ::MBG_IO_PORT_INFO_IDX, for which the ::MBG_IO_PORT_TYPE_INFO_IDX shall be found + * + * @return Pointer to the ::MBG_IO_PORT_TYPE_INFO_IDX found, or NULL + */ +MBG_IO_PORT_TYPE_INFO_IDX *get_io_port_type_info_idx( ALL_IO_PORT_INFO *all_io_port_info, MBG_IO_PORT_INFO_IDX *io_port_info_idx ) +{ + uint8_t i; + + if ( !all_io_port_info || !io_port_info_idx ) + return NULL; + + for ( i = 0; i < io_port_info_idx->info.num_types; ++i ) + { + MBG_IO_PORT_TYPE_INFO_IDX *ptii = &all_io_port_info->pt_infos[io_port_info_idx->idx][i]; + MBG_IO_PORT_TYPE_INFO *pti = &ptii->info; + + if ( pti->port_type == io_port_info_idx->info.settings.port_type ) + { + if ( pti->port_type == MBG_IO_PORT_TYPE_GPIO ) + { + if ( pti->data.gpio_limits.type == io_port_info_idx->info.settings.data.gpio_settings.type ) + return ptii; + } + else + return ptii; + } + } + + return NULL; + +} // get_io_port_type_info_idx + + + +/*HDR*/ +/** + * @brief Initializes a ::MBG_TLV_ANNOUNCE structure + * + * @param[out] tlv Pointer to a ::MBG_TLV_ANNOUNCE structure + * @param[in] uid Unique sender ID used as identifier with all + * subsequent messages related to this transaction. + * @param[in] tlv_feat_type One of the ::MBG_TLV_FEAT_TYPES + * @param[in] total_bytes Total number of bytes of all upcoming TLVs + */ +void mbg_tlv_announce_init( MBG_TLV_ANNOUNCE *tlv, MBG_TLV_UID uid, + MBG_TLV_TYPE tlv_feat_type, uint32_t total_bytes ) +{ + memset( tlv, 0, sizeof( *tlv ) ); + tlv->data.uid = uid; + tlv->data.type = tlv_feat_type; + tlv->data.total_bytes = total_bytes; + tlv->data.reserved_1 = 0; + tlv->reserved_1 = 0; + tlv->reserved_2 = 0; + +} // mbg_tlv_announce_init + + + +/*HDR*/ +/** + * @brief Initializes a ::MBG_TLV + * + * @param[out] tlv Pointer to a valid ::MBG_TLV structure + * @param[in] uid Unique sender ID used as identifier for each further + * TLV message related to this type. + * @param[in] tlv_type Type identifier, see ::MBG_TLV_TYPES + * @param[in] total_bytes Total number of bytes belonging to this + * TLV transaction (which is very likely split into several TLVs) + */ +void mbg_tlv_init( MBG_TLV *tlv, MBG_TLV_UID uid, + MBG_TLV_TYPE tlv_type, uint32_t total_bytes ) +{ + memset( tlv, 0, sizeof( *tlv ) ); + tlv->hdr.uid = uid; + tlv->hdr.tlv_type = tlv_type; + tlv->hdr.cur_bytes = 0; + tlv->hdr.trans_bytes = 0; + tlv->hdr.total_bytes = total_bytes; + tlv->hdr.reserved_1 = 0; + tlv->hdr.reserved_2 = 0; + tlv->hdr.reserved_3 = 0; + +} // mbg_tlv_init + + + +/*HDR*/ +/** + * @brief Initializes ::MBG_TLV_RCV_STATE structure + * + * @param[in,out] state Pointer to ::MBG_TLV_RCV_STATE structure + * @param[in] uid Unique sender ID used as identifier for each further + * TLV message related to this type. + * @param[in] total_bytes Total number of bytes belonging to this + * TLV transaction (which is very likely split into several TLVS) + */ +void mbg_tlv_rcv_state_init( MBG_TLV_RCV_STATE *state, MBG_TLV_UID uid, uint32_t total_bytes ) +{ + state->data.uid = uid; + state->data.type = 0; + state->data.total_bytes = total_bytes; + state->data.reserved_1 = 0; + state->read_bytes = 0; + state->reserved_1 = 0; + +} // mbg_tlv_state_init + + + +/*HDR*/ +int mbg_snprint_revision( char *buf, size_t buflen, + const char *prefix, const char *suffix, + uint32_t rev) +{ + size_t bytes = 0; + uint32_t major, minor, patch; + + if ( prefix ) + bytes += snprintf_safe( &buf[bytes], buflen, "%s", prefix ); + + _mbg_decode_revision( rev, major, minor, patch ); + bytes += snprintf_safe( &buf[bytes], buflen - bytes, "%u.%u.%u", + major, minor, patch); + + if ( suffix ) + bytes += snprintf_safe( &buf[bytes], buflen - bytes, "%s", suffix ); + + return _int_from_size_t( bytes ); + +} // mbg_snprint_revision + + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_xbp_supp_nodes( const ALL_XBP_INFO *info ) +{ + if ( info ) + { + if ( ( info->limits.features & XBP_FEAT_MASK_NODES ) == XBP_FEAT_MASK_NODES ) + return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + } + + return MBG_ERR_INV_PARM; + +} // chk_dev_xbp_supp_nodes + + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_net_cfg_supp_stage_2( const ALL_NET_CFG_INFO *info ) +{ + if ( info->glb_cfg_info.feat_flags & MBG_NET_GLB_SUPP_STAGE_2_MASK ) + return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_net_cfg_supp_stage_2 + + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_ntp_supp_client( const ALL_NTP_CFG_INFO *info ) +{ + if ( ( ( info->glb_info.supp_ntp_roles & NTP_MSK_ROLE_CLIENT ) == NTP_MSK_ROLE_CLIENT ) || + ( ( info->glb_info.supp_ntp_roles & NTP_MSK_ROLE_CLIENT_SERVER ) == NTP_MSK_ROLE_CLIENT_SERVER ) ) + return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_ntp_supp_client + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_ntp_supp_server( const ALL_NTP_CFG_INFO *info ) +{ + if ( ( ( info->glb_info.supp_ntp_roles & NTP_MSK_ROLE_SERVER ) == NTP_MSK_ROLE_SERVER ) || + ( ( info->glb_info.supp_ntp_roles & NTP_MSK_ROLE_CLIENT_SERVER ) == NTP_MSK_ROLE_CLIENT_SERVER ) ) + return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_ntp_supp_server + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_xmulti_ref_supp_mrf_none( const ALL_XMULTI_REF_INFO *info ) +{ + if ( ( info->instances.flags & XMRIF_MSK_MRF_NONE_SUPP ) == XMRIF_MSK_MRF_NONE_SUPP ) + return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_xmulti_ref_supp_mrf_none + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_xmulti_ref_supp_ext_src_info( const ALL_XMULTI_REF_INFO *info ) +{ + if ( ( info->instances.flags & XMRIF_MSK_EXT_SRC_INFO_SUPP ) == XMRIF_MSK_EXT_SRC_INFO_SUPP ) + return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_xmulti_ref_supp_ext_src_info + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_xmulti_ref_supp_holdover_status( const ALL_XMULTI_REF_INFO *info ) +{ + if ( ( info->instances.flags & XMRIF_MSK_HOLDOVER_STATUS_SUPP ) == XMRIF_MSK_HOLDOVER_STATUS_SUPP ) + return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_xmulti_ref_supp_holdover_status + + +/*HDR*/ +/* + * Type is NOT an index of ::XMULTI_REF_INSTANCES::n_xmr_settings, + * but of ::MULTI_REF_TYPES. + * Depends on chk_dev_supp_xmulti_ref_ext_src_info. + * @see chk_dev_supp_xmulti_ref_ext_src_info + */ +_NO_MBG_API_ATTR int _MBG_API chk_dev_xmulti_ref_supp_ext_source_stats( const ALL_XMULTI_REF_INFO *info, int type ) +{ + if ( + ( type < N_MULTI_REF ) && + (( info->ext_src_infos[type].info.feat_flags & XMR_EXT_SRC_FEAT_FLAG_MSK_STATS ) == XMR_EXT_SRC_FEAT_FLAG_MSK_STATS ) + ) return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_xmulti_ref_supp_ext_source_stats + + +/*HDR*/ +/* + * Type is NOT an index of ::XMULTI_REF_INSTANCES::n_xmr_settings, + * but of ::MULTI_REF_TYPES. + * Depends on chk_dev_supp_xmulti_ref_ext_src_info. + * @see chk_dev_supp_xmulti_ref_ext_src_info + */ +_NO_MBG_API_ATTR int _MBG_API chk_dev_xmulti_ref_supp_ext_source_metrics( const ALL_XMULTI_REF_INFO *info, int type ) +{ + if ( + ( type < N_MULTI_REF ) && + (( info->ext_src_infos[type].info.feat_flags & XMR_EXT_SRC_FEAT_FLAG_MSK_METRICS ) == XMR_EXT_SRC_FEAT_FLAG_MSK_METRICS ) + ) return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_xmulti_ref_supp_ext_source_metrics + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_ims_has_fdm( const ALL_IMS_INFO *info ) +{ + if ( ( info->state.flags & MBG_IMS_STATE_FLAG_MSK_HAS_FDM ) == MBG_IMS_STATE_FLAG_MSK_HAS_FDM ) + return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_ims_has_fdm + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_ims_is_volt_out_enabled( const ALL_IMS_STATE *ims_state, unsigned idx ) +{ + const MBG_IMS_SENSOR_STATE *sstate = &ims_state->sensor_state_idx[idx].state; + + if ( + ( sstate->type == MBG_IMS_SENSOR_VOLTAGE ) && + ( ( sstate->flags & MBG_IMS_SENSOR_VOLTAGE_OUT_ENB ) == MBG_IMS_SENSOR_VOLTAGE_OUT_ENB ) + ) return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_ims_is_volt_out_enabled + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_ims_is_volt_out_overload( const ALL_IMS_STATE *ims_state, unsigned idx ) +{ + const MBG_IMS_SENSOR_STATE *sstate = &ims_state->sensor_state_idx[idx].state; + + if ( + ( sstate->type == MBG_IMS_SENSOR_VOLTAGE ) && + ( ( sstate->flags & MBG_IMS_SENSOR_VOLTAGE_OUT_OVR ) == MBG_IMS_SENSOR_VOLTAGE_OUT_OVR ) + ) return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_ims_is_volt_out_overload + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_ims_is_pll_locked( const ALL_IMS_STATE *ims_state, unsigned idx ) +{ + const MBG_IMS_SENSOR_STATE *sstate = &ims_state->sensor_state_idx[idx].state; + + if ( + ( sstate->type == MBG_IMS_SENSOR_PLL ) && + ( ( sstate->flags & MBG_IMS_SENSOR_PLL_LOCKED ) == MBG_IMS_SENSOR_PLL_LOCKED ) + ) return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_ims_is_pll_locked + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_gpio_supp_ass_idx( const ALL_GPIO_INFO *gpio_info, unsigned idx ) +{ + const MBG_GPIO_LIMITS *limits = &gpio_info->infos[idx].info.limits; + + if ( ( limits->supp_flags & MSK_MBG_GPIO_DEPENDS_ON_ASS_IO_IDX ) == MSK_MBG_GPIO_DEPENDS_ON_ASS_IO_IDX ) + return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_gpio_supp_ass_idx + + +/*HDR*/ +_NO_MBG_API_ATTR int _MBG_API chk_dev_gpio_dep_on_ass_idx( const ALL_GPIO_INFO *gpio_info, unsigned idx ) +{ + const MBG_GPIO_SETTINGS *settings = &gpio_info->infos[idx].info.settings; + + if ( ( settings->flags & MSK_MBG_GPIO_DEPENDS_ON_ASS_IO_IDX ) == MSK_MBG_GPIO_DEPENDS_ON_ASS_IO_IDX ) + return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_gpio_dep_on_ass_idx + + +/*HDR*/ +/** + * @brief Checks whether GPIO supports status function + * + * @param[out] info Pointer to a ::ALL_GPIO_INFO structure to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_dev_has_gpio + * @see ::mbg_chk_dev_has_gpio + * @see ::free_all_gpio_info + */ +_NO_MBG_API_ATTR int _MBG_API chk_dev_gpio_has_status( const ALL_GPIO_INFO *info ) +{ + if ( ( info->cfg_limits.flags & MBG_GPIO_CFG_LIMIT_FLAG_MASK_STATUS_SUPP ) == MBG_GPIO_CFG_LIMIT_FLAG_MASK_STATUS_SUPP ) + return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_dev_gpio_has_status + + + +/*HDR*/ +/** + * @brief Frees ::ALL_XBP_INFO structure + * + * @param[in] p Pointer to the ::ALL_XBP_INFO structure, which will be freed + * + * @see ::mbgextio_get_all_xbp_info + */ +void free_all_xbp_info ( ALL_XBP_INFO *p ) +{ + if ( p ) + { + if ( p->node_limits ) + free( p->node_limits ); + + if ( p->node_infos ) + free( p->node_infos ); + + free( p ); + } + +} // free_all_xbp_info + + + +/*HDR*/ +/** + * @brief Frees ::ALL_NET_CFG_INFO structure + * + * @param[in] p Pointer to the ::ALL_NET_CFG_INFO structure, which will be freed + * + * @see ::mbgextio_get_all_net_cfg_info + */ +void free_all_net_cfg_info ( ALL_NET_CFG_INFO *p ) +{ + if ( p ) + { + if ( p->link_infos ) + free( p->link_infos ); + + if ( p->addr_infos ) + free( p->addr_infos ); + + if ( p->dns_srvrs ) + free( p->dns_srvrs ); + + if ( p->dns_srch_doms ) + free( p->dns_srch_doms ); + + if ( p->route_infos ) + free( p->route_infos ); + + free( p ); + } + +} // free_all_net_cfg_info + + + +/*HDR*/ +/** + * @brief Frees ::ALL_NET_STATUS_INFO structure + * + * @param[in] p Pointer to the ::ALL_NET_STATUS_INFO structure, which will be freed + * + * @see ::mbgextio_get_all_net_status_info + */ +void free_all_net_status_info ( ALL_NET_STATUS_INFO *p ) +{ + if ( p ) + { + if ( p->link_infos ) + free( p->link_infos ); + + if ( p->addr_infos ) + free( p->addr_infos ); + + if ( p->dns_srvrs ) + free( p->dns_srvrs ); + + if ( p->dns_srch_doms ) + free( p->dns_srch_doms ); + + if ( p->route_infos ) + free( p->route_infos ); + + free( p ); + } + +} // free_all_net_status_info + + + +/*HDR*/ +/** + * @brief Frees ::ALL_SNMP_INFO structure + * + * @param[in] p Pointer to the ::ALL_SNMP_INFO structure, which will be freed + * + */ +void free_all_snmp_info ( ALL_SNMP_INFO *p ) +{ + if ( p ) + { + if ( p->v12_infos ) + free( p->v12_infos ); + + if ( p->v12_trap_infos ) + free( p->v12_trap_infos ); + + if ( p->v3_infos ) + free( p->v3_infos ); + + if ( p->v3_trap_infos ) + free( p->v3_trap_infos ); + + free( p ); + } + +} // free_all_snmp_info + + + +/*HDR*/ +/** + * @brief Frees ::ALL_MONITORING_INFO structure + * + * @param[in] p Pointer to the ::ALL_MONITORING_INFO structure, which will be freed + * + */ +void free_all_monitoring_info ( ALL_MONITORING_INFO *p ) +{ + if ( p ) + { + if ( p->all_snmp_info ) + free_all_snmp_info( p->all_snmp_info ); + + if ( p->event_infos ) + free( p->event_infos ); + + free ( p ); + } +} + + +/*HDR*/ +/** + * @brief Frees ::ALL_MONITORING_STATUS structure + * + * @param[in] p Pointer to the ::ALL_MONITORING_STATUS structure, which will be freed + * + */ +void free_all_monitoring_status ( ALL_MONITORING_STATUS *p ) +{ + if ( p ) + { + if ( p->event_stati ) + free( p->event_stati ); + + free ( p ); + } +} + + + +/*HDR*/ +/** + * @brief Frees ::ALL_XMULTI_REF_INFO structure + * + * @param[in] p Pointer to the ::ALL_XMULTI_REF_INFO structure, which will be freed + * + * @see ::mbgextio_get_all_xmulti_ref_info + * @see ::mbg_get_all_xmulti_ref_info + */ +void free_all_xmulti_ref_info( ALL_XMULTI_REF_INFO *p ) +{ + if ( p ) + { + if ( p->infos ) + free( p->infos ); + + if ( p->ext_src_infos ) + free( p->ext_src_infos ); + + free ( p ); + } + +} // free_all_xmulti_ref_info + + + +/*HDR*/ +/** + * @brief Frees ::ALL_XMULTI_REF_STATUS structure + * + * @param[in] p Pointer to the ::ALL_XMULTI_REF_STATUS structure, which will be freed + * + * @see ::mbgextio_get_all_xmulti_ref_status + * @see ::mbg_get_all_xmulti_ref_status + */ +void free_all_xmulti_ref_status( ALL_XMULTI_REF_STATUS *p ) +{ + if ( p ) + { + if ( p->status ) + free( p->status ); + + if ( p->holdover_status ) + free( p->holdover_status ); + + if ( p->stats_idx ) + free( p->stats_idx ); + + if ( p->metrics_idx ) + free( p->metrics_idx ); + + free( p ); + } + +} // free_all_xmulti_ref_status + + + +/*HDR*/ +/** + * @brief Frees ::ALL_PTP_V1_COMMON_DATASETS structure allocated by ::mbgextio_get_all_ptp_v1_common_datasets + * + * @param[in] p Pointer to the ::ALL_PTP_V1_COMMON_DATASETS structure, which will be freed + * + * @see ::mbgextio_get_all_ptp_v1_common_datasets + */ +void free_all_ptp_v1_common_datasets( ALL_PTP_V1_COMMON_DATASETS *p ) +{ + if ( p ) + { + if ( p->port_datasets ) + free( p->port_datasets ); + + free( p ); + } + +} // free_all_ptp_v1_common_datasets + + + +/*HDR*/ +/** + * @brief Frees ::ALL_PTP_V2_COMMON_DATASETS structure allocated by ::mbgextio_get_all_ptp_v2_common_datasets + * + * @param[in] p Pointer to the ::ALL_PTP_V2_COMMON_DATASETS structure, which will be freed + * + * @see ::mbgextio_get_all_ptp_v2_common_datasets + */ +void free_all_ptp_v2_common_datasets( ALL_PTP_V2_COMMON_DATASETS *p ) +{ + if ( p ) + { + if ( p->port_datasets ) + free( p->port_datasets ); + + free( p ); + } + +} // free_all_ptp_v2_common_datasets + + + +/*HDR*/ +/** + * @brief Frees ::ALL_NTP_CFG_INFO structure + * + * @param[in] p Pointer to the ::ALL_NTP_CFG_INFO structure, which will be freed + * + * @see ::mbgextio_get_all_ntp_cfg_info + */ +void free_all_ntp_cfg_info( ALL_NTP_CFG_INFO *p ) +{ + if ( p ) + { + if ( p->symm_key_limits ) + free( p->symm_key_limits ); + + if ( p->symm_key_info_idx ) + free( p->symm_key_info_idx ); + + if ( p->trusted_key_info_idx ) + free( p->trusted_key_info_idx ); + + if ( p->clnt_info ) + free( p->clnt_info ); + + if ( p->peer_settings_idx ) + free( p->peer_settings_idx ); + + if ( p->srv_info ) + free( p->srv_info ); + + if ( p->refclk_info_idx ) + free( p->refclk_info_idx ); + + if ( p->misc_limits ) + free( p->misc_limits ); + + if ( p->orphan_mode_info ) + free( p->orphan_mode_info ); + + free( p ); + } + +} // free_all_ntp_cfg_info + + + +/*HDR*/ +/** + * @brief Frees ::ALL_NTP_STATUS structure + * + * @param[in] p Pointer to the ::ALL_NTP_STATUS structure, which will be freed + * + * @see ::mbgextio_get_all_ntp_status + */ +void free_all_ntp_status( ALL_NTP_STATUS *p ) +{ + if ( p ) + { + if ( p->refclk_states ) + free( p->refclk_states ); + + if ( p->peer_states ) + free( p->peer_states ); + + free( p ); + } + +} // free_all_ntp_status + + + +/*HDR*/ +/** + * @brief Frees memory allocated by ::mbgextio_get_all_ims_info + * + * @param[in] p Pointer to the ::ALL_IMS_INFO structure, which will be freed + * + * @see ::mbgextio_dev_has_ims + * @see ::mbgextio_get_all_ims_info + * @see ::mbgextio_get_all_ims_state + */ +void free_all_ims_info( ALL_IMS_INFO *p ) +{ + if ( p ) + { + if ( p->fdm_info ) + free( p->fdm_info ); + + if ( p->fdm_limits ) + free( p->fdm_limits ); + + if ( p->fdm_outinfo_idx ) + free( p->fdm_outinfo_idx ); + + free( p ); + } + +} // free_all_ims_info + + + +/*HDR*/ +/** + * @brief Frees memory allocated by ::mbgextio_get_all_ims_state + * + * @param[in] p Pointer to the ::ALL_IMS_STATE structure, which will be freed + * + * @see ::mbgextio_dev_has_ims + * @see ::mbgextio_get_all_ims_info + * @see ::mbgextio_get_all_ims_state + */ +void free_all_ims_state( ALL_IMS_STATE *p ) +{ + if ( p ) + { + if ( p->sensor_state_idx ) + free( p->sensor_state_idx ); + + if ( p->fdm_state ) + free( p->fdm_state ); + + if ( p->fdm_output_state_idx ) + free( p->fdm_output_state_idx ); + + free( p ); + } + +} // free_all_ims_state + + + +/*HDR*/ +/** + * @brief Frees memory allocated by ::mbgextio_get_all_gpio_info + * + * @param[in] p Pointer to the ::ALL_GPIO_INFO structure, which will be freed + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_dev_has_gpio + * @see ::mbgextio_get_all_gpio_info + */ +void free_all_gpio_info( ALL_GPIO_INFO *p ) +{ + if ( p ) + { + if ( p->infos ) + free( p->infos ); + + free( p ); + } + +} // free_all_gpio_info + + + +/*HDR*/ +/** + * @brief Frees memory allocated by ::mbgextio_get_all_io_port_info + * + * @param[in] p Pointer to the ::ALL_IO_PORT_INFO structure, which will be freed + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_dev_has_io_ports + * @see ::mbgextio_get_all_io_port_info + * @see ::mbgextio_get_all_io_port_status + * @see ::free_all_io_port_status + */ +void free_all_io_port_info( ALL_IO_PORT_INFO *p ) +{ + uint8_t i; + + if ( p ) + { + if ( p->pt_infos ) + { + for ( i = 0; i < p->limits.num_ports; ++i ) + { + if ( p->pt_infos[i] ) + free( p->pt_infos[i] ); + } + + free ( p->pt_infos ); + } + + if ( p->p_infos ) + free( p->p_infos ); + + free( p ); + } + +} // free_all_io_port_info + + + +/*HDR*/ +/** + * @brief Frees memory allocated by ::mbgextio_get_all_io_port_status + * + * @param[in] p Pointer to the ::ALL_IO_PORT_STATUS structure, which will be freed + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_dev_has_io_ports + * @see ::mbgextio_get_all_io_port_info + * @see ::mbgextio_get_all_io_port_status + * @see ::free_all_io_port_info + */ +void free_all_io_port_status( ALL_IO_PORT_STATUS *p ) +{ + if ( p ) + { + if ( p->status ) + free ( p->status ); + + free( p ); + } + +} // free_all_io_port_status + + + +/*HDR*/ +/** + * @brief Frees memory allocated by ::mbgextio_get_all_gpio_state + * + * @param[in] p Pointer to the ::ALL_GPIO_STATE structure, which will be freed + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_dev_has_gpio + * @see ::mbgextio_get_all_gpio_state + */ +void free_all_gpio_state( ALL_GPIO_STATE *p ) +{ + if ( p ) + { + if ( p->states ) + free( p->states ); + + free( p ); + } + +} // free_all_gpio_state + + + +/*HDR*/ +/** + * Allocates memory for a new ::UCAP_ENTRY structure + * + * @return The new allocated ::UCAP_ENTRY or NULL if the calloc call was not successful + */ +UCAP_ENTRY* calloc_ucap_entry( void ) +{ + UCAP_ENTRY *entry = (UCAP_ENTRY *) calloc( 1, sizeof( *entry ) ); + if ( entry ) + { + mbg_klist_init(&entry->head); + } + return entry; + +} // calloc_ucap_entry + + +/*HDR*/ +/** + * @brief Frees memory allocated by ::mbgextio_get_all_ucap_info + * + * @param[in] p Pointer to the ::ALL_UCAP_INFO structure, which will be freed + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_dev_has_ucap + * @see ::mbg_chk_dev_has_ucap + * @see ::mbgextio_get_all_ucap_info + * @see ::mbg_get_all_ucap_info + */ +void free_all_ucap_info( ALL_UCAP_INFO *p ) +{ + if ( p ) + { + UCAP_ENTRY *entry; + + while ( !mbg_klist_is_empty( &p->list ) ) + { + entry = mbg_klist_first_entry( &p->list, UCAP_ENTRY, head ); + mbg_klist_delete_item( &entry->head ); + free( entry ); + } + + free( p ); + } + +} // free_all_ucap_info + + +/*HDR*/ +/** + * @brief Frees ::ALL_UCAP_NET_INFO structure + * + * @param[in] p Pointer to the ::ALL_UCAP_NET_INFO structure, which will be freed + * + * @see ::mbgextio_get_all_ucap_net_info + */ +void free_all_ucap_net_info( ALL_UCAP_NET_INFO *p ) +{ + if ( p ) + { + if ( p->recv_infos ) + free( p->recv_infos ); + + free( p ); + } + +} // free_all_ucap_net_info + + + +/*HDR*/ +/** + * @brief Set up a ::NTP_TSTAMP structure from a hex string with a time in seconds and binary fractions + * + * @param[in] s A string with a time in seconds since NTP epoch 1900-01-01, + * with binary fractions separated by decimal point, + * e.g. 'dc763e43.73bd5a8f' as printed by the ntpq utility + * @param[out] p Address of a ::NTP_TSTAMP structure to be set up + * + * @see ::str_ntp_hex_to_nano_time_64 + */ +void str_ntp_hex_to_ntp_tstamp( const char *s, NTP_TSTAMP *p ) +{ + char *cp = NULL; + + p->seconds = strtoul( s, &cp, 16 ); + + if ( *cp == '.' ) // fractions may follow + { + cp++; // skip '.' + + p->fractions = strtoul( cp, NULL, 16 ); + } + else + p->fractions = 0; + +} // str_ntp_hex_to_ntp_tstamp + + + +#if !defined( MBG_TGT_MISSING_64_BIT_TYPES ) + +/*HDR*/ +/** + * @brief Convert a ::NTP_TSTAMP structure to a ::NANO_TIME_64 structure + * + * @param[in] p_nts The ::NTP_TSTAMP structure to be converted + * @param[out] p_nt64 The ::NANO_TIME_64 structure to be filled up + */ +void ntp_tstamp_to_nanotime_64( const NTP_TSTAMP *p_nts, NANO_TIME_64 *p_nt64 ) +{ + p_nt64->secs = p_nts->seconds - NTP_SEC_BIAS; + p_nt64->nano_secs = bin_frac_32_to_dec_frac( p_nts->fractions, NSECS_PER_SEC ); + +} // ntp_tstamp_to_nanotime_64 + + + +/*HDR*/ +/** + * @brief Set up a ::NANO_TIME_64 structure from a hex string with a time in seconds and binary fractions + * + * @param[in] s A string with a time in seconds since epoch 1900-01-01, + * with binary fractions separated by decimal point, + * e.g. 'dc763e43.73bd5a8f' as printed by the ntpq utility + * @param[out] p Address of a ::NANO_TIME_64 structure to be set up + * + * @see ::str_ntp_hex_to_ntp_tstamp + */ +void str_ntp_hex_to_nano_time_64( const char *s, NANO_TIME_64 *p ) +{ + NTP_TSTAMP nts = { 0 }; + + str_ntp_hex_to_ntp_tstamp( s, &nts ); + ntp_tstamp_to_nanotime_64( &nts, p ); + +} // str_ntp_hex_to_nano_time_64 + +#endif // !defined( MBG_TGT_MISSING_64_BIT_TYPES ) + + diff --git a/src/external/bsd/meinberg/dist/mbglib/common/cfg_hlp.h b/src/external/bsd/meinberg/dist/mbglib/common/cfg_hlp.h new file mode 100755 index 0000000..44ddbe9 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/cfg_hlp.h @@ -0,0 +1,1217 @@ + +/************************************************************************** + * + * $Id: cfg_hlp.h 1.4.2.1 2017/07/26 14:26:01 martin TEST $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for configuration programs. + * + * WARNING: Changing the constants defined here affects the size of + * the related structures and arrays, and thus would break compatibility + * if used in DLLs / shared object libraries. + * + * Care must be taken that the number of objects supported by + * any particular device (which can be only determined at runtime) + * does not exceed the max. number of objects specified here + * for the configuration programs. + * + * ----------------------------------------------------------------------- + * $Log: cfg_hlp.h $ + * Revision 1.4.2.1 2017/07/26 14:26:01 martin + * Fixed build for NetBSD. + * Revision 1.4 2017/07/05 13:22:00 martin + * Definitions for TLV, IMS, and GPIO provided by philipp. + * Definitions for ALL_XPB_INFO, ALL_NET_CFG_INFO, + * ALL_PTP_V2_COMMON_DATASETS, ALL_PTP_V1_COMMON_DATASETS, + * ALL_UCAP and associated stuff provided by thomas-b. + * Definitions for xmulti_ref and IO PORT, SNMP and MONITORING, + * and associated stuff provided by philipp and thomas-b. + * New definitions COMP_SIG_MODES and PCPS_TIME_EXT_FLAGS. + * New inline functions device_id_is_serial() and + * device_id_is_lan(). + * Moved inline function num_bits_set() and a lot of + * global configuration variables here. + * Older defines N_SUPP_DEV, PCPS_MAX_DDEVS, and MBG_MAX_DEVICES + * have been obsoleted by new defines N_SUPP_DEV_BUS, N_SUPP_DEV_EXT, + * and N_SUPP_DEV_TOTAL. + * Updated function prototypes. + * Revision 1.3 2013/09/25 10:02:15 martin + * Added ALL_PTP_CFG_INFO, ALL_GNSS_SAT_INFO_IDX and + * related definitions. + * Added doxygen comments. + * Revision 1.2 2012/10/02 18:16:26 martin + * Modified some typedefs to be more compliant with the underlying types. + * Revision 1.1 2011/09/21 15:59:59 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _CFG_HLP_H +#define _CFG_HLP_H + + +/* Other headers to be included */ + +#include <gpsdefs.h> +#include <mbgklist.h> + +#if !defined( MBG_TGT_KERNEL ) + #include <stdlib.h> + #include <string.h> +#endif + +#if defined( _PRELIMINARY_CODE ) + #if defined( MBG_TGT_POSIX ) + #include <sys/stat.h> + #include <time.h> + #endif // MBG_TGT_POSIX + + #if defined( MBG_TGT_LINUX ) + #include <sys/sysinfo.h> + #endif // MBG_TGT_LINUX + +#endif // _PRELIMINARY_CODE + +#ifdef _CFG_HLP + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + + +#if 1 // ### TODO cleanup + +#define N_SUPP_DEV_BUS 16 +#define N_SUPP_DEV_EXT 1 + +#define N_SUPP_DEV_TOTAL ( N_SUPP_DEV_BUS + N_SUPP_DEV_EXT ) + +typedef struct _DEVICE_INFO +{ + char *hw_id; + char fw_id[100]; + +} DEVICE_INFO; + +_ext DEVICE_INFO device_list[N_SUPP_DEV_TOTAL]; + +#endif + + + +/// @brief The max number of serial ports supported by configuration programs +#define MAX_PARM_PORT 10 + +/// @brief The max number of serial string types supported by configuration programs +#define MAX_PARM_STR_TYPE 20 + +/// @brief The max number of programmable pulse outputs supported by configuration programs +#define MAX_PARM_POUT 10 + +/// @brief The max number of GNSS settings supported by configuration programs +#define MAX_PARM_GNSS_SAT N_GNSS_TYPES + +/// @brief The max number of PTP unicast masters supported by configuration programs +#define MAX_PARM_PTP_UC_MASTER 3 + +/// @brief The max number of external NTP server associations to be handled by configuration programs +#define MAX_PARM_EXT_NTP_SRVR 20 + +/// @brief The max number of GPIO ports supported by configuration programs +#define MAX_PARM_GPIO 10 + +/// @brief The max number of XMR sources supported by configuration programs +#define MAX_PARM_XMR 10 + +/// @brief The max number of external NTP servers supported by configuration programs +#define MAX_EXT_NTP_SERVERS 20 + +/// @brief The max. number of time monitoring modules supported by configuration programs +/// Each module may support a different number of targets to be monitored. +/// @see ### TODO +#define MAX_MBG_TIME_MON_MODULES 10 + +/// @brief The max. number of time monitoring targets supported by configuration programs +/// This is the sum of all targets from all monitoring modules. +/// @see ### TODO +#define MAX_MBG_TIME_MON_TARGETS 100 + + + +/// @brief An array of configuration settings for all serial ports +typedef PORT_INFO_IDX ALL_PORT_INFO_IDX[MAX_PARM_PORT]; + +/// @brief An array of configuration settings for all serial string types +typedef STR_TYPE_INFO_IDX ALL_STR_TYPE_INFO_IDX[MAX_PARM_STR_TYPE]; + +/** + * @brief All configuration parameters for all serial ports + * + * Used to collect all configuration parameters of a clock's serial ports + * that can be handled by a configuration program. + * + * @see ::RECEIVER_INFO::n_com_ports + * @see ::RECEIVER_INFO::n_str_type + */ +typedef struct +{ + ALL_PORT_INFO_IDX pii; ///< all serial port configuration settings + ALL_STR_TYPE_INFO_IDX stii; ///< all supported serial string types + PORT_PARM tmp_pp; ///< used internally only, for compatibility + +} RECEIVER_PORT_CFG; + + + +/** + * @brief All XBP information of a XBP supporting device + * + * This structure represents a list of connected devices + * + * @see ::GPS_HAS_XBP + */ +typedef struct +{ + XBP_LIMITS limits; + XBP_NODE_LIMITS* node_limits; + XBP_NODE_INFO_IDX* node_infos; +} ALL_XBP_INFO; + + + +/** + * @brief An array of configuration settings for all programmable pulse outputs + * + * Used to collect all configuration parameters of a clock's programmable pulse outputs + * that can be handled by a configuration program. + * + * @see ::RECEIVER_INFO::n_prg_out + */ +typedef POUT_INFO_IDX ALL_POUT_INFO_IDX[MAX_PARM_POUT]; + + + +/** + * @brief All network configuration parameters + * + * Used to collect all configuration parameters for networking + * + * @see ::GPS_HAS_NET_CFG + * @see ::GPS_HAS_LAN_IP4 + */ +typedef struct +{ + MBG_NET_GLB_CFG_INFO glb_cfg_info; + MBG_NET_INTF_LINK_INFO_IDX *link_infos; + MBG_NET_INTF_ADDR_INFO_IDX *addr_infos; + MBG_IP_ADDR_IDX *dns_srvrs; + MBG_NET_NAME_IDX *dns_srch_doms; + MBG_NET_INTF_ROUTE_INFO_IDX *route_infos; +} ALL_NET_CFG_INFO; + +typedef ALL_NET_CFG_INFO ALL_NET_STATUS_INFO; + + + +/** + * @brief All SNMP configuration information + * + * Used to collect all configuration parameters for monitoring via SNMP + * Can be used, if ::MBG_MONITORING_TYPE_MSK_SNMP is set in ::MBG_MONITORING_LIMITS::supp_types + * + * @see ::MBG_XFEATURE_MONITORING + */ +typedef struct +{ + MBG_SNMP_GLB_INFO glb_info; + MBG_SNMP_V12_INFO_IDX *v12_infos; + MBG_SNMP_V12_TRAP_INFO_IDX *v12_trap_infos; + MBG_SNMP_V3_INFO_IDX *v3_infos; + MBG_SNMP_V3_TRAP_INFO_IDX *v3_trap_infos; + +} ALL_SNMP_INFO; + + +/** + * @brief All monitoring information + * + * Used to collect all configuration parameters for monitoring of a device + * Depending on the ::MBG_MONITORING_LIMITS::supp_types, + * the approriate configurations can be found in the sub structures + * + * @see ::MBG_XFEATURE_MONITORING + */ +typedef struct +{ + MBG_EVENT_INFO_IDX info; + void *priv_data; + +} MBG_EVENT_INFO_IDX_DATA; + +typedef struct +{ + MBG_MONITORING_LIMITS limits; + ALL_SNMP_INFO *all_snmp_info; + MBG_EVENT_INFO_IDX_DATA *event_infos; + +} ALL_MONITORING_INFO; + + + +typedef struct +{ + MBG_EVENT_STATUS_IDX status; + void *priv_data; + +} MBG_EVENT_STATUS_IDX_DATA; + + + +/** + * @brief All monitoring status + * + * Used to collect all status information for monitoring a device. + * Depending on the ::MBG_MONITORING_LIMITS::supp_num_events, + * the appropriate event status for each event can be found + * in ::ALL_MONITORING_STATUS::event_stati. + */ +typedef struct +{ + MBG_MONITORING_STATUS status; + MBG_EVENT_STATUS_IDX_DATA *event_stati; + +} ALL_MONITORING_STATUS; + + + +/// @brief Configuration settings for all unicast master specifications +typedef PTP_UC_MASTER_INFO_IDX ALL_PTP_UC_MASTER_INFO_IDX[MAX_PARM_PTP_UC_MASTER]; + +/** + * @brief All PTP configuration parameters + * + * Used to collect all configuration parameters for a PTP daemon + * that can be handled by a configuration program. + * + * @see ::GPS_HAS_PTP + * @see ::PTP_UC_MASTER_CFG_LIMITS::n_supp_master + */ +typedef struct +{ + PTP_CFG_INFO ptp_cfg_info; + PTP_UC_MASTER_CFG_LIMITS ptp_uc_master_cfg_limits; + ALL_PTP_UC_MASTER_INFO_IDX all_ptp_uc_master_info_idx; + +} ALL_PTP_CFG_INFO; + + + +/** + * @brief All PTPv1 common datasets for a PTP device + * + * Contains one of each common datasets plus one port dataset + * for each port of a device. The number of port datasets is defined + * in the ::MBG_PTP_V1_DEFAULT_DATASET::number_ports field of the + * ::ALL_PTP_V1_COMMON_DATASETS::default_dataset member. + * + * @see ::MBG_PTP_V1_DEFAULT_DATASET + * @see ::MBG_PTP_V1_CURRENT_DATASET + * @see ::MBG_PTP_V1_PARENT_DATASET + * @see ::MBG_PTP_V1_TIME_PROPERTIES_DATASET + * @see ::MBG_PTP_V1_PORT_DATASET_IDX + */ +typedef struct +{ + MBG_PTP_V1_DEFAULT_DATASET default_dataset; + MBG_PTP_V1_CURRENT_DATASET current_dataset; + MBG_PTP_V1_PARENT_DATASET parent_dataset; + MBG_PTP_V1_TIME_PROPERTIES_DATASET time_properties_dataset; + MBG_PTP_V1_PORT_DATASET_IDX *port_datasets; + +} ALL_PTP_V1_COMMON_DATASETS; + + + +/** + * @brief All PTPv2 common datasets for a PTP device + * + * Contains one of each common datasets plus one port dataset + * for each port of a device. The number of port datasets is defined + * in the ::MBG_PTP_V1_DEFAULT_DATASET::number_ports field of the + * ::ALL_PTP_V1_COMMON_DATASETS::default_dataset member. + * + * @see ::MBG_PTP_V2_DEFAULT_DATASET + * @see ::MBG_PTP_V2_CURRENT_DATASET + * @see ::MBG_PTP_V2_PARENT_DATASET + * @see ::MBG_PTP_V2_TIME_PROPERTIES_DATASET + * @see ::MBG_PTP_V2_PORT_DATASET_IDX + */ +typedef struct +{ + MBG_PTP_V2_DEFAULT_DATASET default_dataset; + MBG_PTP_V2_CURRENT_DATASET current_dataset; + MBG_PTP_V2_PARENT_DATASET parent_dataset; + MBG_PTP_V2_TIME_PROPERTIES_DATASET time_properties_dataset; + MBG_PTP_V2_PORT_DATASET_IDX *port_datasets; + +} ALL_PTP_V2_COMMON_DATASETS; + + + +/** + * @brief An array of configuration settings for all programmable pulse outputs + * + * Used to collect all configuration parameters of a clock's programmable pulse outputs + * that can be handled by a configuration program. + */ +typedef GNSS_SAT_INFO_IDX ALL_GNSS_SAT_INFO_IDX[MAX_PARM_GNSS_SAT]; + + + +/** + * @brief Summary information on all supported GNSS systems + * + * Used to collect all configuration parameters even for devices + * that can receive the signals from multiple satellite systems. + */ +typedef struct +{ + STAT_INFO stat_info; + int n_gnss_supp; + MBG_GNSS_MODE_INFO gnss_mode_info; + ALL_GNSS_SAT_INFO_IDX gnss_sat_info_idx; + +} ALL_GNSS_INFO; + + + +/// @brief Configuration settings for all NTP server associations +typedef NTP_PEER_SETTINGS ALL_NTP_PEER_SETTINGS[MAX_EXT_NTP_SERVERS]; + +/** + * @brief All NTP configuration parameters + * + * Used to collect all configuration parameters for an NTP daemon + * that can be handled by a configuration program. + * + * @see ::GPS_HAS_NTP + */ +typedef struct +{ + ALL_NTP_PEER_SETTINGS all_ntp_peer_settings; + +} NTP_CLIENT_CFG_PEER_SETTINGS; + + +typedef struct +{ + NTP_GLB_INFO glb_info; + NTP_SYMM_KEY_LIMITS *symm_key_limits; + NTP_SYMM_KEY_INFO_IDX *symm_key_info_idx; + NTP_TRUSTED_KEY_INFO_IDX *trusted_key_info_idx; + + NTP_CLNT_MODE_INFO *clnt_info; + NTP_PEER_SETTINGS_IDX *peer_settings_idx; + + NTP_SRV_MODE_INFO *srv_info; + NTP_REFCLK_CFG_INFO_IDX *refclk_info_idx; + NTP_MISC_LIMITS *misc_limits; + NTP_MISC_ORPHAN_MODE_INFO *orphan_mode_info; + +} ALL_NTP_CFG_INFO; + + +typedef struct +{ + NTP_SYS_STATE sys_state; + NTP_REFCLK_STATE_IDX *refclk_states; + NTP_PEER_STATE_IDX *peer_states; +} ALL_NTP_STATUS; + + + +/// @brief Configuration settings for all GPIO ports +typedef MBG_GPIO_INFO_IDX ALL_GPIO_INFO_IDX[MAX_PARM_GPIO]; + +/// @brief Status information on all GPIO ports +typedef MBG_GPIO_STATUS_IDX ALL_GPIO_STATUS_IDX[MAX_PARM_GPIO]; + + + + +/// @brief Status of all XMR inputs +typedef XMULTI_REF_STATUS_IDX ALL_XMULTI_REF_STATUS_IDX[MAX_PARM_XMR]; + +/// @brief Configuration settings for all XMR inputs +typedef XMULTI_REF_INFO_IDX ALL_XMULTI_REF_INFO_IDX[MAX_PARM_XMR]; + + + +typedef struct +{ + XMULTI_REF_INSTANCES instances; + XMULTI_REF_INFO_IDX *infos; + XMR_EXT_SRC_INFO_IDX *ext_src_infos; +} ALL_XMULTI_REF_INFO; + + +typedef struct +{ + XMULTI_REF_STATUS_IDX *status; + XMR_HOLDOVER_STATUS *holdover_status; + XMR_STATS_IDX *stats_idx; + XMR_METRICS_IDX *metrics_idx; + /* ALL_XMULTI_REF_STATUS related flag if at least one ref type supports stats */ + unsigned char has_stats; + /* ALL_XMULTI_REF_STATUS related flag if at least one ref type supports metrics */ + unsigned char has_metrics; +} ALL_XMULTI_REF_STATUS; + + + +typedef struct +{ + MBG_IMS_STATE state; + MBG_IMS_FDM_INFO *fdm_info; + MBG_IMS_FDM_LIMITS *fdm_limits; + MBG_IMS_FDM_OUTPUT_INFO_IDX *fdm_outinfo_idx; +} ALL_IMS_INFO; + + +typedef struct +{ + MBG_IMS_SENSOR_STATE_IDX *sensor_state_idx; + MBG_IMS_FDM_STATE *fdm_state; + MBG_IMS_FDM_OUTPUT_STATE_IDX *fdm_output_state_idx; +} ALL_IMS_STATE; + + + +typedef struct +{ + MBG_GPIO_CFG_LIMITS cfg_limits; + MBG_GPIO_INFO_IDX *infos; +} ALL_GPIO_INFO; + + +typedef struct +{ + MBG_GPIO_STATUS_IDX *states; +} ALL_GPIO_STATE; + + +typedef struct +{ + MBG_IO_PORT_LIMITS limits; + MBG_IO_PORT_INFO_IDX *p_infos; + MBG_IO_PORT_TYPE_INFO_IDX **pt_infos; +} ALL_IO_PORT_INFO; + + +typedef struct +{ + MBG_IO_PORT_STATUS_IDX *status; +} ALL_IO_PORT_STATUS; + + +#ifndef MAX_UCAP_ENTRIES +/* + * According to Andre's GPS firmware this is the maximum + * number of user captures that are preserved. + */ +#define MAX_UCAP_ENTRIES 585 +#endif + +typedef struct +{ + struct mbg_klist_head head; + TTM ttm; +} UCAP_ENTRY; + +typedef struct +{ + uint32_t num_ucaps; /// User capture counter, see ::MAX_UCAP_ENTRIES + struct mbg_klist_head list; +} ALL_UCAP_INFO; + +// User Captures via Network configuration, see ::MBG_XFEATURE_UCAP_NET +typedef struct +{ + MBG_UCAP_NET_GLB_INFO glb_info; + MBG_UCAP_NET_RECV_INFO_IDX *recv_infos; +} ALL_UCAP_NET_INFO; + + + +/** + * @brief A mode specifying how to interpret a ::PCPS_SIG_VAL + * + * Used with ::PCPS_TIME_EXT::comp_sig_mode. Depending on this mode + * a signal value can be interpreted e.g. as signal strength (with + * long wave or IRIG time code receivers), or as indicator whether an + * antenna is connected (satellite receivers), or a network link is + * available (PTP slaves) or not, and an appropriate status message + * can be displayed. + * + * @see @ref PCPS_SIG_VAL_DEFS + */ +enum COMP_SIG_MODES +{ + COMP_SIG_MODE_NONE, ///< signal value not used + COMP_SIG_MODE_SIGNAL, ///< input signal strength + COMP_SIG_MODE_ANT_CONN, ///< antenna connection state + COMP_SIG_MODE_PORT_LINK, ///< port link state + N_CONN_SIG_MODES +}; + + +/** + * @brief Flag bits indicating if some extended status is available + * + * @see ::PCPS_TIME_EXT_FLAGS + */ +enum PCPS_TIME_EXT_FLAG_BITS +{ + PCPS_TIME_EXT_FLAG_BIT_UTC_VALID, ///< ::PCPS_TIME_EXT::utc_offs field is valid + N_PCPS_TIME_EXT_FLAG_BITS +}; + + +/** + * @brief Flag masks used with ::PCPS_TIME_EXT::flags + * + * @see ::PCPS_TIME_EXT_FLAG_BITS + */ +enum PCPS_TIME_EXT_FLAGS +{ + PCPS_TIME_EXT_FLAG_UTC_VALID = ( 1UL << PCPS_TIME_EXT_FLAG_BIT_UTC_VALID ) ///< see ::PCPS_TIME_EXT_FLAG_BIT_UTC_VALID +}; + + + +_ext BAUD_RATE mbg_baud_rate[N_MBG_BAUD_RATES] +#ifdef _DO_INIT + = MBG_BAUD_RATES +#endif +; + +_ext const char *mbg_baud_str[N_MBG_BAUD_RATES] +#ifdef _DO_INIT + = MBG_BAUD_STRS +#endif +; + +_ext const char *mbg_framing_str[N_MBG_FRAMINGS] +#ifdef _DO_INIT + = MBG_FRAMING_STRS +#endif +; + +_ext const char *str_unknown +#ifdef _DO_INIT + = "unknown" +#endif +; + + +_ext const char *str_undefined +#ifdef _DO_INIT + = "(undefined)" +#endif +; + + +_ext const char *str_not_spc +#ifdef _DO_INIT + = "not " +#endif +; + + + +//### TODO +#define DEFAULT_MAX_STR_TYPE 2 // DEFAULT_N_STR_TYPE_GPS ? + +_ext STR_TYPE_INFO default_str_type_info[DEFAULT_MAX_STR_TYPE] +#ifdef _DO_INIT + = { + { DEFAULT_STR_MODES, "Default Time String", "Time", 0 }, + { DEFAULT_STR_MODES_UCAP, "Capture String", "Cap", 0 } + } +#endif +; + + + +_ext const char *mbg_gpio_type_names[N_MBG_GPIO_TYPES] +#ifdef _DO_INIT + = DEFAULT_GPIO_TYPES_SHORT_STRS +#endif +; + +#define _get_gpio_type_name( _i ) \ + ( ( (_i) < N_MBG_GPIO_TYPES ) ? mbg_gpio_type_names[_i] : str_unknown ) + + + +_ext const char *mbg_gpio_port_state_names[N_MBG_GPIO_PORT_STATES] +#ifdef _DO_INIT + = DEFAULT_GPIO_PORT_STATE_NAMES +#endif +; + +#define _get_gpio_port_state_name( _i ) \ + ( ( (_i) < N_MBG_GPIO_PORT_STATES ) ? mbg_gpio_port_state_names[_i] : str_unknown ) + + + +_ext const char *mbg_gpio_signal_shape_names[N_MBG_GPIO_SIGNAL_SHAPES] +#ifdef _DO_INIT + = DEFAULT_GPIO_SIGNAL_SHAPE_NAMES +#endif +; + +#define _get_gpio_signal_shape_name( _i ) \ + ( ( (_i) < N_MBG_GPIO_SIGNAL_SHAPES ) ? mbg_gpio_signal_shape_names[_i] : str_unknown ) + + + +_ext const char *mbg_gpio_fixed_freq_strs[N_MBG_GPIO_FIXED_FREQ] +#ifdef _DO_INIT + = MBG_GPIO_FIXED_FREQ_STRS +#endif +; + +#define _get_gpio_fixed_freq_str( _i ) \ + ( ( (_i) < N_MBG_GPIO_FIXED_FREQ ) ? mbg_gpio_fixed_freq_strs[_i] : str_unknown ) + + + +_ext const char *xmr_holdover_status_mode_names[N_XMR_HOLDOVER_STATUS_MODES] +#ifdef _DO_INIT + = XMR_HOLDOVER_STATUS_MODE_NAMES +#endif +; + +#define _get_xmr_holdover_status_mode_name( _i ) \ + ( ( (_i) < N_XMR_HOLDOVER_STATUS_MODES ) ? xmr_holdover_status_mode_names[_i] : str_unknown ) + + + +/** + * @brief Count the number of bits which are not 0 + * + * @param[in] val Value to be tested + * + * @return The number of non-zero bits in val + */ +static __mbg_inline +int num_bits_set( long val ) +{ + int bits_set = 0; + size_t i; + + for ( i = 0; i < ( 8 * sizeof( val ) ); i++ ) + { + if ( val & 1 ) + bits_set++; + + val >>= 1; + } + + return bits_set; + +} // num_bits_set + + + +/** + * @brief Check if a device ID refers to a serial port + * + * @param[in] dev_id A string with the device name or port name + * + * @see ::DEFAULT_SERIAL_DEVICE_NAME + * + * @return true if the device id contains the name of a serial port, else false + */ +static __mbg_inline +bool device_id_is_serial( const char *dev_id ) +{ + #if defined( MBG_TGT_WIN32 ) + //##++++ There may be also serial ports under Windows + // which don't have "COM" in their name. + return strstr( dev_id, "COM" ) != NULL; + #elif defined( MBG_TGT_LINUX ) + return strstr( dev_id, "/dev/ttyS" ) != NULL // standard serial device + || strstr( dev_id, "/dev/ttyUSB" ) != NULL; // serial-to-USB adapter + #elif defined( MBG_TGT_FREEBSD ) + return strstr( dev_id, "/dev/ttyu" ) != NULL // dial-in device (standard), FreeBSD 10 and newer + || strstr( dev_id, "/dev/cuau" ) != NULL // dial out device, FreeBSD 10 and newer + || strstr( dev_id, "/dev/ttyd" ) != NULL // dial-in device (standard), before FreeBSD 10 + || strstr( dev_id, "/dev/cuad" ) != NULL; // dial-out device, before FreeBSD 10 + #elif defined( MBG_TGT_NETBSD ) + // TODO This is just an ugly hack which identifies + // some traditional device names as serial ports. + // There are quite a few other possible names. + // See "man 4 com" and "man 4 tty". + return strstr( dev_id, "/dev/tty0" ) != NULL // traditional dial-in devices + || strstr( dev_id, "/dev/dty0" ) != NULL; // traditional dial-out devices + #elif defined( MBG_TGT_QNX_NTO ) + return strstr( dev_id, "/dev/ser" ) != NULL; + #elif defined( MBG_TGT_DOS ) + return strstr( dev_id, "COM" ) != NULL; + #else + #error device_id_is_serial() needs to be implemented for this platform + #endif + +} // device_id_is_serial + + + +/** + * @brief Check if a device ID refers to a LAN connection + * + * @param[in] dev_id A string with the device ID + * + * @return true if the device id specifies a LAN connection, else false + */ +static __mbg_inline +bool device_id_is_lan( const char *dev_id ) +{ + return strstr( dev_id, "LAN" ) != NULL; + +} // device_id_is_lan + + + +#if defined( _PRELIMINARY_CODE ) + +static __mbg_inline +MBG_TLV_UID mbg_tlv_create_id( void ) +{ +#if defined( MBG_TGT_LINUX ) ///### FIXME for FreeBSD and Windows + struct sysinfo info; + + // Linux specific, implement Windows equivalent + sysinfo( &info ); + return ( (MBG_TLV_UID) ( ( time( NULL ) >> 16 ) | ( info.uptime << 16 ) ) ); +#else + return 0; +#endif +} // mbg_tlv_create_id + +#endif // defined( _PRELIMINARY_CODE ) + + + +#if !defined( MBG_TGT_KERNEL ) + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + /** + * @brief Check if a software revision name should be displayed + * + * The software revision name is usually empty, except if the + * firmware is a customized version, in which case the field + * contains an identifier string. + * + * There are some standard firmware versions where this string + * is not empty but padded with spaces, etc., so we try to + * clean this up and display the string properly, if appropriate. + * + * @param[in,out] p The ::SW_REV name to check + * @param[in] verbose The app's verbosity level + * + * @return != 0 if SW name should be displayed + */ + int chk_sw_rev_name( SW_REV *p, int verbose ) ; + + int get_str_idx( const char *search, const char *str_table[], int n_entries ) ; + int get_baud_rate_idx( BAUD_RATE baud_rate ) ; + int get_framing_idx( const char *framing ) ; + void port_settings_from_port_parm_mode( PORT_SETTINGS *p_ps, uint8_t pp_mode, int str_type_cap ) ; + void port_parm_mode_from_port_settings( uint8_t *pp_mode, const PORT_SETTINGS *p_ps, int str_type_cap ) ; + void port_settings_from_port_parm( PORT_SETTINGS *p_ps, int port_num, const PORT_PARM *p_pp, int cap_str_idx ) ; + void port_parm_from_port_settings( PORT_PARM *p_pp, int port_num, const PORT_SETTINGS *p_ps, int cap_str_idx ) ; + uint32_t check_valid_port_info( const PORT_INFO *p_pi, const STR_TYPE_INFO_IDX str_type_info_idx[], int n_str_type ) ; + int valid_port_info( const PORT_INFO *p_pi, const STR_TYPE_INFO_IDX str_type_info_idx[], int n_str_type ) ; + int setup_port_info_from_port_settings( PORT_INFO_IDX pii[], const PORT_PARM *p_pp, const RECEIVER_INFO *p_ri ) ; + int setup_default_str_type_info_idx( STR_TYPE_INFO_IDX stii[], const RECEIVER_INFO *p_ri ) ; + int chk_set_n_gnss_supp( ALL_GNSS_INFO *p_agi ) ; + /** + * @brief + * + * ### Setup GNSS info from stat_info so we can use the same printing routine + */ + void setup_gps_only_sat_info_idx_from_statinfo( ALL_GNSS_INFO *p_agi ) ; + + /** + * @brief + * + * Setup GNSS info from stat_info so we can use the same printing routine + */ + int setup_gps_only_gnss_info_from_statinfo( ALL_GNSS_INFO *p_agi ) ; + + void chk_free_dev_hw_id( DEVICE_INFO *p ) ; + int alloc_dev_hw_id( DEVICE_INFO *p, size_t len ) ; + const char *get_fw_id_from_hw_id( const char *hw_id ) ; + const char *get_hw_id_from_fw_id( const char *fw_id ) ; + /** + * @brief Returns the currently used ::MBG_IO_PORT_TYPE_INFO_IDX for the appropriate ::MBG_IO_PORT_INFO_IDX + * + * @param[in] all_io_port_info Pointer to the ::ALL_IO_PORT_INFO, containing the current configuration + * @param[in] io_port_info_idx Pointer to the ::MBG_IO_PORT_INFO_IDX, for which the ::MBG_IO_PORT_TYPE_INFO_IDX shall be found + * + * @return Pointer to the ::MBG_IO_PORT_TYPE_INFO_IDX found, or NULL + */ + MBG_IO_PORT_TYPE_INFO_IDX *get_io_port_type_info_idx( ALL_IO_PORT_INFO *all_io_port_info, MBG_IO_PORT_INFO_IDX *io_port_info_idx ) ; + + /** + * @brief Initializes a ::MBG_TLV_ANNOUNCE structure + * + * @param[out] tlv Pointer to a ::MBG_TLV_ANNOUNCE structure + * @param[in] uid Unique sender ID used as identifier with all + * subsequent messages related to this transaction. + * @param[in] tlv_feat_type One of the ::MBG_TLV_FEAT_TYPES + * @param[in] total_bytes Total number of bytes of all upcoming TLVs + */ + void mbg_tlv_announce_init( MBG_TLV_ANNOUNCE *tlv, MBG_TLV_UID uid, MBG_TLV_TYPE tlv_feat_type, uint32_t total_bytes ) ; + + /** + * @brief Initializes a ::MBG_TLV + * + * @param[out] tlv Pointer to a valid ::MBG_TLV structure + * @param[in] uid Unique sender ID used as identifier for each further + * TLV message related to this type. + * @param[in] tlv_type Type identifier, see ::MBG_TLV_TYPES + * @param[in] total_bytes Total number of bytes belonging to this + * TLV transaction (which is very likely split into several TLVs) + */ + void mbg_tlv_init( MBG_TLV *tlv, MBG_TLV_UID uid, MBG_TLV_TYPE tlv_type, uint32_t total_bytes ) ; + + /** + * @brief Initializes ::MBG_TLV_RCV_STATE structure + * + * @param[in,out] state Pointer to ::MBG_TLV_RCV_STATE structure + * @param[in] uid Unique sender ID used as identifier for each further + * TLV message related to this type. + * @param[in] total_bytes Total number of bytes belonging to this + * TLV transaction (which is very likely split into several TLVS) + */ + void mbg_tlv_rcv_state_init( MBG_TLV_RCV_STATE *state, MBG_TLV_UID uid, uint32_t total_bytes ) ; + + int mbg_snprint_revision( char *buf, size_t buflen, const char *prefix, const char *suffix, uint32_t rev) ; + _NO_MBG_API_ATTR int _MBG_API chk_dev_xbp_supp_nodes( const ALL_XBP_INFO *info ) ; + _NO_MBG_API_ATTR int _MBG_API chk_dev_net_cfg_supp_stage_2( const ALL_NET_CFG_INFO *info ) ; + _NO_MBG_API_ATTR int _MBG_API chk_dev_ntp_supp_client( const ALL_NTP_CFG_INFO *info ) ; + _NO_MBG_API_ATTR int _MBG_API chk_dev_ntp_supp_server( const ALL_NTP_CFG_INFO *info ) ; + _NO_MBG_API_ATTR int _MBG_API chk_dev_xmulti_ref_supp_mrf_none( const ALL_XMULTI_REF_INFO *info ) ; + _NO_MBG_API_ATTR int _MBG_API chk_dev_xmulti_ref_supp_ext_src_info( const ALL_XMULTI_REF_INFO *info ) ; + _NO_MBG_API_ATTR int _MBG_API chk_dev_xmulti_ref_supp_holdover_status( const ALL_XMULTI_REF_INFO *info ) ; + /* + * Type is NOT an index of ::XMULTI_REF_INSTANCES::n_xmr_settings, + * but of ::MULTI_REF_TYPES. + * Depends on chk_dev_supp_xmulti_ref_ext_src_info. + * @see chk_dev_supp_xmulti_ref_ext_src_info + */ + _NO_MBG_API_ATTR int _MBG_API chk_dev_xmulti_ref_supp_ext_source_stats( const ALL_XMULTI_REF_INFO *info, int type ) ; + + /* + * Type is NOT an index of ::XMULTI_REF_INSTANCES::n_xmr_settings, + * but of ::MULTI_REF_TYPES. + * Depends on chk_dev_supp_xmulti_ref_ext_src_info. + * @see chk_dev_supp_xmulti_ref_ext_src_info + */ + _NO_MBG_API_ATTR int _MBG_API chk_dev_xmulti_ref_supp_ext_source_metrics( const ALL_XMULTI_REF_INFO *info, int type ) ; + + _NO_MBG_API_ATTR int _MBG_API chk_dev_ims_has_fdm( const ALL_IMS_INFO *info ) ; + _NO_MBG_API_ATTR int _MBG_API chk_dev_ims_is_volt_out_enabled( const ALL_IMS_STATE *ims_state, unsigned idx ) ; + _NO_MBG_API_ATTR int _MBG_API chk_dev_ims_is_volt_out_overload( const ALL_IMS_STATE *ims_state, unsigned idx ) ; + _NO_MBG_API_ATTR int _MBG_API chk_dev_ims_is_pll_locked( const ALL_IMS_STATE *ims_state, unsigned idx ) ; + _NO_MBG_API_ATTR int _MBG_API chk_dev_gpio_supp_ass_idx( const ALL_GPIO_INFO *gpio_info, unsigned idx ) ; + _NO_MBG_API_ATTR int _MBG_API chk_dev_gpio_dep_on_ass_idx( const ALL_GPIO_INFO *gpio_info, unsigned idx ) ; + /** + * @brief Checks whether GPIO supports status function + * + * @param[out] info Pointer to a ::ALL_GPIO_INFO structure to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_dev_has_gpio + * @see ::mbg_chk_dev_has_gpio + * @see ::free_all_gpio_info + */ + _NO_MBG_API_ATTR int _MBG_API chk_dev_gpio_has_status( const ALL_GPIO_INFO *info ) ; + + /** + * @brief Frees ::ALL_XBP_INFO structure + * + * @param[in] p Pointer to the ::ALL_XBP_INFO structure, which will be freed + * + * @see ::mbgextio_get_all_xbp_info + */ + void free_all_xbp_info ( ALL_XBP_INFO *p ) ; + + /** + * @brief Frees ::ALL_NET_CFG_INFO structure + * + * @param[in] p Pointer to the ::ALL_NET_CFG_INFO structure, which will be freed + * + * @see ::mbgextio_get_all_net_cfg_info + */ + void free_all_net_cfg_info ( ALL_NET_CFG_INFO *p ) ; + + /** + * @brief Frees ::ALL_NET_STATUS_INFO structure + * + * @param[in] p Pointer to the ::ALL_NET_STATUS_INFO structure, which will be freed + * + * @see ::mbgextio_get_all_net_status_info + */ + void free_all_net_status_info ( ALL_NET_STATUS_INFO *p ) ; + + /** + * @brief Frees ::ALL_SNMP_INFO structure + * + * @param[in] p Pointer to the ::ALL_SNMP_INFO structure, which will be freed + * + */ + void free_all_snmp_info ( ALL_SNMP_INFO *p ) ; + + /** + * @brief Frees ::ALL_MONITORING_INFO structure + * + * @param[in] p Pointer to the ::ALL_MONITORING_INFO structure, which will be freed + * + */ + void free_all_monitoring_info ( ALL_MONITORING_INFO *p ) ; + + /** + * @brief Frees ::ALL_MONITORING_STATUS structure + * + * @param[in] p Pointer to the ::ALL_MONITORING_STATUS structure, which will be freed + * + */ + void free_all_monitoring_status ( ALL_MONITORING_STATUS *p ) ; + + /** + * @brief Frees ::ALL_XMULTI_REF_INFO structure + * + * @param[in] p Pointer to the ::ALL_XMULTI_REF_INFO structure, which will be freed + * + * @see ::mbgextio_get_all_xmulti_ref_info + * @see ::mbg_get_all_xmulti_ref_info + */ + void free_all_xmulti_ref_info( ALL_XMULTI_REF_INFO *p ) ; + + /** + * @brief Frees ::ALL_XMULTI_REF_STATUS structure + * + * @param[in] p Pointer to the ::ALL_XMULTI_REF_STATUS structure, which will be freed + * + * @see ::mbgextio_get_all_xmulti_ref_status + * @see ::mbg_get_all_xmulti_ref_status + */ + void free_all_xmulti_ref_status( ALL_XMULTI_REF_STATUS *p ) ; + + /** + * @brief Frees ::ALL_PTP_V1_COMMON_DATASETS structure allocated by ::mbgextio_get_all_ptp_v1_common_datasets + * + * @param[in] p Pointer to the ::ALL_PTP_V1_COMMON_DATASETS structure, which will be freed + * + * @see ::mbgextio_get_all_ptp_v1_common_datasets + */ + void free_all_ptp_v1_common_datasets( ALL_PTP_V1_COMMON_DATASETS *p ) ; + + /** + * @brief Frees ::ALL_PTP_V2_COMMON_DATASETS structure allocated by ::mbgextio_get_all_ptp_v2_common_datasets + * + * @param[in] p Pointer to the ::ALL_PTP_V2_COMMON_DATASETS structure, which will be freed + * + * @see ::mbgextio_get_all_ptp_v2_common_datasets + */ + void free_all_ptp_v2_common_datasets( ALL_PTP_V2_COMMON_DATASETS *p ) ; + + /** + * @brief Frees ::ALL_NTP_CFG_INFO structure + * + * @param[in] p Pointer to the ::ALL_NTP_CFG_INFO structure, which will be freed + * + * @see ::mbgextio_get_all_ntp_cfg_info + */ + void free_all_ntp_cfg_info( ALL_NTP_CFG_INFO *p ) ; + + /** + * @brief Frees ::ALL_NTP_STATUS structure + * + * @param[in] p Pointer to the ::ALL_NTP_STATUS structure, which will be freed + * + * @see ::mbgextio_get_all_ntp_status + */ + void free_all_ntp_status( ALL_NTP_STATUS *p ) ; + + /** + * @brief Frees memory allocated by ::mbgextio_get_all_ims_info + * + * @param[in] p Pointer to the ::ALL_IMS_INFO structure, which will be freed + * + * @see ::mbgextio_dev_has_ims + * @see ::mbgextio_get_all_ims_info + * @see ::mbgextio_get_all_ims_state + */ + void free_all_ims_info( ALL_IMS_INFO *p ) ; + + /** + * @brief Frees memory allocated by ::mbgextio_get_all_ims_state + * + * @param[in] p Pointer to the ::ALL_IMS_STATE structure, which will be freed + * + * @see ::mbgextio_dev_has_ims + * @see ::mbgextio_get_all_ims_info + * @see ::mbgextio_get_all_ims_state + */ + void free_all_ims_state( ALL_IMS_STATE *p ) ; + + /** + * @brief Frees memory allocated by ::mbgextio_get_all_gpio_info + * + * @param[in] p Pointer to the ::ALL_GPIO_INFO structure, which will be freed + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_dev_has_gpio + * @see ::mbgextio_get_all_gpio_info + */ + void free_all_gpio_info( ALL_GPIO_INFO *p ) ; + + /** + * @brief Frees memory allocated by ::mbgextio_get_all_io_port_info + * + * @param[in] p Pointer to the ::ALL_IO_PORT_INFO structure, which will be freed + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_dev_has_io_ports + * @see ::mbgextio_get_all_io_port_info + * @see ::mbgextio_get_all_io_port_status + * @see ::free_all_io_port_status + */ + void free_all_io_port_info( ALL_IO_PORT_INFO *p ) ; + + /** + * @brief Frees memory allocated by ::mbgextio_get_all_io_port_status + * + * @param[in] p Pointer to the ::ALL_IO_PORT_STATUS structure, which will be freed + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_dev_has_io_ports + * @see ::mbgextio_get_all_io_port_info + * @see ::mbgextio_get_all_io_port_status + * @see ::free_all_io_port_info + */ + void free_all_io_port_status( ALL_IO_PORT_STATUS *p ) ; + + /** + * @brief Frees memory allocated by ::mbgextio_get_all_gpio_state + * + * @param[in] p Pointer to the ::ALL_GPIO_STATE structure, which will be freed + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_dev_has_gpio + * @see ::mbgextio_get_all_gpio_state + */ + void free_all_gpio_state( ALL_GPIO_STATE *p ) ; + + /** + * Allocates memory for a new ::UCAP_ENTRY structure + * + * @return The new allocated ::UCAP_ENTRY or NULL if the calloc call was not successful + */ + UCAP_ENTRY* calloc_ucap_entry( void ) ; + + /** + * @brief Frees memory allocated by ::mbgextio_get_all_ucap_info + * + * @param[in] p Pointer to the ::ALL_UCAP_INFO structure, which will be freed + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbgextio_dev_has_ucap + * @see ::mbg_chk_dev_has_ucap + * @see ::mbgextio_get_all_ucap_info + * @see ::mbg_get_all_ucap_info + */ + void free_all_ucap_info( ALL_UCAP_INFO *p ) ; + + /** + * @brief Frees ::ALL_UCAP_NET_INFO structure + * + * @param[in] p Pointer to the ::ALL_UCAP_NET_INFO structure, which will be freed + * + * @see ::mbgextio_get_all_ucap_net_info + */ + void free_all_ucap_net_info( ALL_UCAP_NET_INFO *p ) ; + + /** + * @brief Set up a ::NTP_TSTAMP structure from a hex string with a time in seconds and binary fractions + * + * @param[in] s A string with a time in seconds since NTP epoch 1900-01-01, + * with binary fractions separated by decimal point, + * e.g. 'dc763e43.73bd5a8f' as printed by the ntpq utility + * @param[out] p Address of a ::NTP_TSTAMP structure to be set up + * + * @see ::str_ntp_hex_to_nano_time_64 + */ + void str_ntp_hex_to_ntp_tstamp( const char *s, NTP_TSTAMP *p ) ; + + /** + * @brief Convert a ::NTP_TSTAMP structure to a ::NANO_TIME_64 structure + * + * @param[in] p_nts The ::NTP_TSTAMP structure to be converted + * @param[out] p_nt64 The ::NANO_TIME_64 structure to be filled up + */ + void ntp_tstamp_to_nanotime_64( const NTP_TSTAMP *p_nts, NANO_TIME_64 *p_nt64 ) ; + + /** + * @brief Set up a ::NANO_TIME_64 structure from a hex string with a time in seconds and binary fractions + * + * @param[in] s A string with a time in seconds since epoch 1900-01-01, + * with binary fractions separated by decimal point, + * e.g. 'dc763e43.73bd5a8f' as printed by the ntpq utility + * @param[out] p Address of a ::NANO_TIME_64 structure to be set up + * + * @see ::str_ntp_hex_to_ntp_tstamp + */ + void str_ntp_hex_to_nano_time_64( const char *s, NANO_TIME_64 *p ) ; + + +/* ----- function prototypes end ----- */ + +#endif // !defined( MBG_TGT_KERNEL ) + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _CFG_HLP_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/charcode.h b/src/external/bsd/meinberg/dist/mbglib/common/charcode.h new file mode 100755 index 0000000..9605c95 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/charcode.h @@ -0,0 +1,275 @@ + +/************************************************************************** + * + * $Id: charcode.h 1.4 2016/08/10 12:25:41 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for pcpslstr.c. + * + * ----------------------------------------------------------------------- + * $Log: charcode.h $ + * Revision 1.4 2016/08/10 12:25:41 martin + * Check for MBG_TGT_POSIX instead of MBG_TGT_UNIX. + * Revision 1.3 2015/11/11 14:55:59 martin + * Support Unicode and UTF-8 encodings. + * Revision 1.2 2014/04/24 14:13:17 martin + * Added new codes and conversion table initializers. + * Revision 1.1 2012/11/20 13:41:24 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _CHARCODE_H +#define _CHARCODE_H + + +/* Other headers to be included */ + +#include <mbg_tgt.h> + +#if MBG_TGT_HAS_WCHAR_T + #include <wchar.h> +#endif + +#ifdef _CHARCODE + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined( MBG_TGT_LINUX ) + + #define MBG_UML_UTF8 + +#elif defined( MBG_TGT_WIN32 ) \ + || defined( MBG_TGT_POSIX ) \ + || defined( MBG_TGT_QNX ) + + #define MBG_UML_ANSI + +#else + + #define MBG_UML_DOS + +#endif + + + +// upper case 'A' umlaut +#define ANSI_UC_A_UML '\xC4' // uppercase ANSI char +#define ANSI_US_A_UML "\xC4" // uppercase ANSI string literal + +#define DOS_UC_A_UML '\x8E' // uppercase DOS char +#define DOS_US_A_UML "\x8E" // uppercase DOS string literal + +#define UNICODE_US_A_UML "\u00C4" // uppercase Unicode string literal + +#define UTF8_US_A_UML "\xc3\x84" // uppercase UTF-8 string literal + + + +// upper case 'O' umlaut +#define ANSI_UC_O_UML '\xD6' // uppercase ANSI char +#define ANSI_US_O_UML "\xD6" // uppercase ANSI string literal + +#define DOS_UC_O_UML '\x99' // uppercase DOS char +#define DOS_US_O_UML "\x99" // uppercase DOS string literal + +#define UNICODE_US_O_UML "\u00D6" // uppercase Unicode string literal + +#define UTF8_US_O_UML "\xc3\x96" // uppercase UTF-8 string literal + + + +// upper case 'U' umlaut +#define ANSI_UC_U_UML '\xDC' // uppercase ANSI char +#define ANSI_US_U_UML "\xDC" // uppercase ANSI string literal + +#define DOS_UC_U_UML '\x9A' // uppercase DOS char +#define DOS_US_U_UML "\x9A" // uppercase DOS string literal + +#define UNICODE_US_U_UML "\u00DC" // uppercase Unicode string literal + +#define UTF8_US_U_UML "\xc3\x9c" // uppercase UTF-8 string literal + + + +// lower case 'a' umlaut +#define ANSI_LC_A_UML '\xE4' // lowercase ANSI char +#define ANSI_LS_A_UML "\xE4" // lowercase ANSI string literal + +#define DOS_LC_A_UML '\x84' // lowercase DOS char +#define DOS_LS_A_UML "\x84" // lowercase DOS string literal + +#define UNICODE_LS_A_UML "\u00E4" // lowercase Unicode string literal + +#define UTF8_LS_A_UML "\xc3\xa4" // lowercase UTF-8 string literal + + + +// lower case 'o' umlaut +#define ANSI_LC_O_UML '\xF6' // lowercase ANSI char +#define ANSI_LS_O_UML "\xF6" // lowercase ANSI string literal + +#define DOS_LC_O_UML '\x94' // lowercase DOS char +#define DOS_LS_O_UML "\x94" // lowercase DOS string literal + +#define UNICODE_LS_O_UML "\u00F6" // lowercase Unicode string literal + +#define UTF8_LS_O_UML "\xc3\xb6" // lowercase UTF-8 string literal + + + +// lower case 'u' umlaut +#define ANSI_LC_U_UML '\xFC' // lowercase ANSI char +#define ANSI_LS_U_UML "\xFC" // lowercase ANSI string literal + +#define DOS_LC_U_UML '\x81' // lowercase DOS char +#define DOS_LS_U_UML "\x81" // lowercase DOS string literal + +#define UNICODE_LS_U_UML "\u00FC" // lowercase Unicode string literal + +#define UTF8_LS_U_UML "\xc3\xbc" // lowercase UTF-8 string literal + + + +// 'sz' umlaut +#define ANSI_LC_SZ_UML '\xDF' // ANSI char +#define ANSI_LS_SZ_UML "\xDF" // ANSI string literal + +#define DOS_LC_SZ_UML '\xE1' // DOS char +#define DOS_LS_SZ_UML "\xE1" // DOS string literal + +#define UNICODE_LS_SZ_UML "\u00DF" // Unicode string literal + +#define UTF8_LS_SZ_UML "\xc3\x9f" // UTF-8 string literal + + + +// degree character +#define ANSI_C_DEGREE '\xB0' // ANSI char +#define ANSI_S_DEGREE "\xB0" // ANSI string literal + +#define DOS_C_DEGREE '\xF8' // DOS char +#define DOS_S_DEGREE "\xF8" // DOS string literal + +#define UNICODE_S_DEGREE "\u00E0" // Unicode string liter + +#define UTF8_S_DEGREE "\xc2\xb0" // UTF-8 string literal + + + +// greek mu character (micro sign) +#define ANSI_C_MU '\xB5' // ANSI char +#define ANSI_S_MU "\xB5" // ANSI string literal + +#define DOS_C_MU '\xE6' // DOS char +#define DOS_S_MU "\xE6" // DOS string literal + +#define UNICODE_S_MU "\u00B5" // Unicode string liter + +#define UTF8_S_MU "\xc2\xb5" // UTF-8 string literal + + + +#if defined( MBG_UML_UTF8 ) + + #define UCAE UTF8_US_A_UML + #define UCOE UTF8_US_O_UML + #define UCUE UTF8_US_U_UML + + #define LCAE UTF8_LS_A_UML + #define LCOE UTF8_LS_O_UML + #define LCUE UTF8_LS_U_UML + + #define LCSZ UTF8_LS_SZ_UML + #define DEG UTF8_S_DEGREE + #define MU UTF8_S_MU + +#elif defined( MBG_UML_ANSI ) + + #define UCAE ANSI_US_A_UML + #define UCOE ANSI_US_O_UML + #define UCUE ANSI_US_U_UML + + #define LCAE ANSI_LS_A_UML + #define LCOE ANSI_LS_O_UML + #define LCUE ANSI_LS_U_UML + + #define LCSZ ANSI_LS_SZ_UML + #define DEG ANSI_S_DEGREE + #define MU ANSI_S_MU + +#elif defined( MBG_UML_DOS ) + + #define UCAE DOS_US_A_UML + #define UCOE DOS_US_O_UML + #define UCUE DOS_US_U_UML + + #define LCAE DOS_LS_A_UML + #define LCOE DOS_LS_O_UML + #define LCUE DOS_LS_U_UML + + #define LCSZ DOS_LS_SZ_UML + #define DEG DOS_S_DEGREE + #define MU DOS_S_MU + +#else + + #error Need to define default encoding for umlauts. + +#endif + + + +// A string initializer which can be used to set up a string +// to check if all umlauts are displayed correctly. +#define UMLAUTS_STRING UCAE UCOE UCUE LCAE LCOE LCUE LCSZ DEG MU + + +#define ANSI_UMLAUTS \ +{ \ + ANSI_UC_A_UML, ANSI_UC_O_UML, ANSI_UC_U_UML, \ + ANSI_LC_A_UML, ANSI_LC_O_UML, ANSI_LC_U_UML, \ + ANSI_LC_SZ_UML, ANSI_C_DEGREE, ANSI_C_MU, 0 \ +} + + +#define DOS_UMLAUTS \ +{ \ + DOS_UC_A_UML, DOS_UC_O_UML, DOS_UC_U_UML, \ + DOS_LC_A_UML, DOS_LC_O_UML, DOS_LC_U_UML, \ + DOS_LC_SZ_UML, DOS_C_DEGREE, DOS_S_MU, 0 \ +} + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + +/* (no header definitions found) */ + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _CHARCODE_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/chk_time_info.c b/src/external/bsd/meinberg/dist/mbglib/common/chk_time_info.c new file mode 100755 index 0000000..e1d1756 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/chk_time_info.c @@ -0,0 +1,163 @@ + +/************************************************************************** + * + * $Id: chk_time_info.c 1.4 2017/07/05 09:00:14 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * System time checking support functions. + * + * ----------------------------------------------------------------------- + * $Log: chk_time_info.c $ + * Revision 1.4 2017/07/05 09:00:14 martin + * Use safe string functions from str_util.c. + * Account for PCPS_HRT_BIN_FRAC_SCALE renamed + * to MBG_FRAC32_UNITS_PER_SEC. + * Revision 1.3 2013/07/30 12:55:33 martin + * Updated file description. + * Revision 1.2 2013/03/04 16:01:01 martin + * Use common function setup_hr_time_cycles_from_timestamp_cycles(). + * Made snprint_chk_time_info() more flexible. + * Revision 1.1 2012/05/29 09:52:26 martin + * Initial revision. + * + **************************************************************************/ + +#define _CHK_TIME_INFO + #include <chk_time_info.h> +#undef _CHK_TIME_INFO + +#include <toolutil.h> +#include <str_util.h> + +#include <stdio.h> + + +//##++++++ +extern MBG_PC_CYCLES_FREQUENCY cyc_freq; + + +static /*HDR*/ +MBG_PC_CYCLES do_filter( FILTER *p, MBG_PC_CYCLES cyc ) +{ + if ( p->entries < MAX_FILTER_ENTRIES ) + p->entries++; + + if ( ++( p->index ) >= MAX_FILTER_ENTRIES ) + p->index = 0; + + // update the sum of filter entries + p->sum -= p->cyc[p->index]; // subtract oldest sample + p->cyc[p->index] = cyc; // save new sample + p->sum += cyc; // add new sample + + return p->sum / p->entries; // return mean value + +} /* do_filter */ + + + +/*HDR*/ +int mbg_chk_time_info( MBG_DEV_HANDLE dh, MBG_CHK_TIME_INFO *p, FILTER *p_filter, int fast_ts_only ) +{ + MBG_PC_CYCLES tmp; + PCPS_TIME_STAMP *p_ref_ts; + MBG_PC_CYCLES *p_ref_cyc; + MBG_SYS_TIME_CYCLES *p_sys_tic; + int rc; + + memset( p, 0, sizeof( *p ) ); + + if ( fast_ts_only ) + { + MBG_TIME_INFO_TSTAMP tsi; + + rc = mbg_get_time_info_tstamp( dh, &tsi ); + setup_hr_time_cycles_from_timestamp_cycles( &p->hrti.ref_hr_time_cycles, &tsi.ref_tstamp_cycles ); + p->hrti.sys_time_cycles = tsi.sys_time_cycles; + } + else + rc = mbg_get_time_info_hrt( dh, &p->hrti ); + + if ( rc < 0 ) + return rc; + + + p_ref_ts = &p->hrti.ref_hr_time_cycles.t.tstamp; + p_ref_cyc = &p->hrti.ref_hr_time_cycles.cycles; + p_sys_tic = &p->hrti.sys_time_cycles; + + p->d_ref = (double) p_ref_ts->sec + ( (double) p_ref_ts->frac ) / (double) MBG_FRAC32_UNITS_PER_SEC; + p->d_sys = (double) p_sys_tic->sys_time.secs + (double) p_sys_tic->sys_time.nano_secs / 1e9; + + p->ltcy_cyc = mbg_delta_pc_cycles( p_ref_cyc, &p_sys_tic->cyc_after ); + p->exec_cyc = mbg_delta_pc_cycles( &p_sys_tic->cyc_after, &p_sys_tic->cyc_before ); + p->exec_cyc_limit = p_filter ? do_filter( p_filter, p->exec_cyc ) : 0; + + if ( cyc_freq ) + { + p->ltcy_sec = ( (double) p->ltcy_cyc ) / (double) cyc_freq; + p->exec_sec = ( (double) p->exec_cyc ) / (double) cyc_freq; + p->exec_sec_limit = ( (double) p->exec_cyc_limit ) / (double) cyc_freq; + } + + // Compensate latencies between time stamps -> + // normalize ref time to system time stamp + p->d_ref_comp = p->d_ref - p->ltcy_sec; + + // Try to set the limit to 1.7 of the mean execution cycles. + tmp = ( 7 * p->exec_cyc_limit ) / 10; + + // If execution takes only a few cycles make sure the limit + // is above the mean number of cycles. + if ( tmp == 0 ) + tmp++; + + p->exec_cyc_limit += tmp; + + return MBG_SUCCESS; + +} // mbg_chk_time_info + + + +/*HDR*/ +size_t snprint_chk_time_info( char *s, size_t max_len, const MBG_CHK_TIME_INFO *p, const PCPS_DEV *p_dev, + int frac_digits, int print_raw ) +{ + size_t n = 0; + + if ( p_dev ) + n += snprintf_safe( &s[n], max_len - n, "%-9s: ", _pcps_type_name( p_dev ) ); + + n += mbg_snprint_hr_tstamp( &s[n], max_len - n, &p->hrti.ref_hr_time_cycles.t.tstamp, 0, 0 ); // raw timestamp? + + n += snprintf_safe( &s[n], max_len - n, " %.*f %.*f ", + frac_digits, p->d_ref, + frac_digits, p->d_sys ); + + n += snprintf_safe( &s[n], max_len - n, "%+.*f, ltcy: ", + frac_digits, p->d_ref_comp - p->d_sys ); + + + if ( cyc_freq ) // print latency and execution time in microseconds + { + n += snprintf_safe( &s[n], max_len - n, "%.2f us, exec: %.2f us, limit: %.2f us", + p->ltcy_sec * 1e6, p->exec_sec * 1e6, p->exec_sec_limit * 1e6 ); + } + else // print latency and execution time in cycles only + { + n += snprintf_safe( &s[n], max_len - n, "%lli cyc, exec: %lli cyc, limit: %lli cyc", + (long long) p->ltcy_cyc, (long long) p->exec_cyc, + (long long) p->exec_cyc_limit ); + } + + if ( print_raw ) + n += snprintf_safe( &s[n], max_len - n, ", raw: %+.*f", + frac_digits, p->d_ref - p->d_sys ); + + return n; + +} // snprint_chk_time_info + diff --git a/src/external/bsd/meinberg/dist/mbglib/common/chk_time_info.h b/src/external/bsd/meinberg/dist/mbglib/common/chk_time_info.h new file mode 100755 index 0000000..1a66f6b --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/chk_time_info.h @@ -0,0 +1,113 @@ + +/************************************************************************** + * + * $Id: chk_time_info.h 1.3 2017/07/05 09:01:46 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for chk_time_info.c. + * + * ----------------------------------------------------------------------- + * $Log: chk_time_info.h $ + * Revision 1.3 2017/07/05 09:01:46 martin + * Tiny cleanup. + * Updated function prototypes. + * Revision 1.2 2013/03/04 16:02:31 martin + * Updated function prototypes. + * Revision 1.1 2012/05/29 09:52:27 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _CHK_TIME_INFO_H +#define _CHK_TIME_INFO_H + + +/* Other headers to be included */ + +#include <mbgdevio.h> + + +#ifdef _CHK_TIME_INFO + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if 0 && defined( _USE_PACK ) // use default alignment + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +#if !defined( MAX_FILTER_ENTRIES ) + #define MAX_FILTER_ENTRIES 32 +#endif + + +typedef struct +{ + MBG_PC_CYCLES cyc[MAX_FILTER_ENTRIES]; + MBG_PC_CYCLES sum; + int entries; + int index; +} FILTER; + + +typedef struct +{ + MBG_TIME_INFO_HRT hrti; + + MBG_PC_CYCLES ltcy_cyc; + MBG_PC_CYCLES exec_cyc; + MBG_PC_CYCLES exec_cyc_limit; + + double ltcy_sec; + double exec_sec; + double exec_sec_limit; + + double d_sys; + double d_ref; + double d_ref_comp; + +} MBG_CHK_TIME_INFO; + + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + int mbg_chk_time_info( MBG_DEV_HANDLE dh, MBG_CHK_TIME_INFO *p, FILTER *p_filter, int fast_ts_only ) ; + size_t snprint_chk_time_info( char *s, size_t max_len, const MBG_CHK_TIME_INFO *p, const PCPS_DEV *p_dev, int frac_digits, int print_raw ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + + +#undef _ext +#undef _DO_INIT + +#endif /* _CHK_TIME_INFO_H */ + diff --git a/src/external/bsd/meinberg/dist/mbglib/common/cnv_wday.h b/src/external/bsd/meinberg/dist/mbglib/common/cnv_wday.h index 7736135..327d69d 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/cnv_wday.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/cnv_wday.h @@ -1,7 +1,7 @@ /***************************************************************************/ /* */ -/* File: CNV_WDAY.H $Revision: 1.1 $ */ +/* File: CNV_WDAY.H $Revision: 1.2 $ */ /* */ /* Project: Common C Library */ /* */ @@ -24,18 +24,10 @@ /* */ /***************************************************************************/ - #ifndef _CNV_WDAY_H - /* Other headers to be included */ - - -#ifdef __cplusplus -extern "C" { -#endif - #ifdef _CNV_WDAY #define _ext #else @@ -45,6 +37,10 @@ extern "C" { /* Start of header body */ +#ifdef __cplusplus +extern "C" { +#endif + /* use the following macros if sure that the source value is in range */ @@ -80,11 +76,6 @@ extern "C" { #define _wday_chk_sun17_to_sun06( d ) _inrng( (d), _wday_sun17_to_sun06( (d) ), 1, 0, 7, 6 ) #define _wday_chk_sun06_to_sun17( d ) _inrng( (d), _wday_sun06_to_sun17( (d) ), 0, 1, 6, 7 ) - -/* function prototypes: */ - -/* #include <CNV_WDAY.hdr> not needed yet */ - /* End of header body */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/ctry.c b/src/external/bsd/meinberg/dist/mbglib/common/ctry.c index ef647d0..73cbe3f 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/ctry.c +++ b/src/external/bsd/meinberg/dist/mbglib/common/ctry.c @@ -19,7 +19,6 @@ * by giving the different strings as function arguments. * Revision 1.6 2007/03/29 12:21:51 martin * New functions lstr_idx() and lstr_array_idx(). - * Revision 1.1 2010/06/01 07:57:03 philipp * Revision 1.5 2004/10/26 07:39:37Z martin * Use C99 fixed-size definitions where appropriate. * Revision 1.4 2001/09/14 12:02:12 MARTIN diff --git a/src/external/bsd/meinberg/dist/mbglib/common/ctry.h b/src/external/bsd/meinberg/dist/mbglib/common/ctry.h index 08d1238..3d791ff 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/ctry.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/ctry.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: ctry.h 1.12 2011/06/22 07:37:57 martin REL_M $ + * $Id: ctry.h 1.14 2017/06/23 09:53:27 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,14 +10,19 @@ * * ----------------------------------------------------------------------- * $Log: ctry.h $ - * Revision 1.12 2011/06/22 07:37:57 martin + * Revision 1.14 2017/06/23 09:53:27 martin + * Fixed spelling in an earlier log message. + * Revision 1.13 2012/11/29 12:01:09 martin + * Don't include mbg_tgt.h explicitly since this will anyway be + * included by words.h for non-firmware targets. So mbg_tgt.h + * must not necessarily be added to firmware projects. + * Revision 1.12 2011/06/22 07:37:57Z martin * Cleaned up handling of pragma pack(). * Revision 1.11 2010/07/15 08:33:41 martin * Added some macros implemented by Stefan. * Updated function prototypes. * Revision 1.10 2007/03/29 12:21:10 martin * Updated function prototypes. - * Revision 1.1 2010/06/01 07:57:04 philipp * Revision 1.9 2004/10/26 07:38:50Z martin * Redefined interface data types using C99 fixed-size definitions. * Updated function prototypes. @@ -33,11 +38,11 @@ * Revision 1.4 2000/11/27 14:13:27 MARTIN * New types CLSTR, PLSTR, and PCLSTR. * New macro _lstr() calls lstr_lng() for the current language. - * Definitions associated with ctry_fmt_dt() and ctry_fmt_times() + * Definitions associated with ctry_fmt_dt() and ctry_fmt_times() * have been moved to a new file ctry_fmt.h. * Updated function prototypes. * Revision 1.3 2000/08/17 15:35:02 MARTIN - * No init function by default (previously DOS), + * No init function by default (previously DOS), * Revision 1.2 2000/07/21 09:48:34 MARTIN * Initial revision * @@ -49,7 +54,6 @@ /* Other headers to be included */ -#include <mbg_tgt.h> #include <words.h> #if defined( MBG_TGT_NETWARE ) diff --git a/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.c b/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.c index 4d35644..d8ada7c 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.c +++ b/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: ctrydttm.c 1.5 2008/11/24 16:15:46 martin REL_M $ + * $Id: ctrydttm.c 1.7 2015/11/09 11:22:12 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,11 +11,16 @@ * * ----------------------------------------------------------------------- * $Log: ctrydttm.c $ - * Revision 1.5 2008/11/24 16:15:46 martin + * Revision 1.7 2015/11/09 11:22:12 martin + * Modified snprint_ctry_dt_short() and fixed snprint_ctry_dt(). + * Revision 1.6 2015/08/31 10:00:46 martin + * Use safe string functions from str_util.c. + * This required renaming of functions and changing parameters. + * Revision 1.5 2008/11/24 16:15:46Z martin * Don't use sprintf() without format string. * Revision 1.4 2000/11/27 10:06:27 MARTIN * Renamed local variable wday_str to lstrs_wday. - * If macro USER_LSTR_WDAY is defined, lstrs_wday can be declared + * If macro USER_LSTR_WDAY is defined, lstrs_wday can be declared * externally to override the defaults. * Revision 1.3 2000/09/14 15:13:25 MARTIN * Renamed sprint_short_ctry_dt() to sprint_ctry_dt_short() to match @@ -30,6 +35,7 @@ #undef _CTRYDTTM #include <ctry.h> +#include <str_util.h> #include <stdio.h> @@ -53,45 +59,44 @@ extern LANGUAGE language; /*HDR*/ -ushort sprint_02u( char *s, uchar uc ) +size_t snprint_02u( char *s, size_t max_len, uchar uc ) { - return( sprintf( s, "%02u", uc ) ); + return snprintf_safe( s, max_len, "%02u", uc ); -} // sprint_02u +} // snprint_02u /*HDR*/ -ushort sprint_04u( char *s, ushort us ) +size_t snprint_04u( char *s, size_t max_len, ushort us ) { - return( sprintf( s, "%04u", us ) ); + return snprintf_safe( s, max_len, "%04u", us ); -} // sprint_04u +} // snprint_04u /*HDR*/ -ushort sprint_ctry_wday( char *s, uchar wday, ushort language ) +size_t snprint_ctry_wday( char *s, size_t max_len, uchar wday, ushort language ) { if ( language >= N_LNG ) language = LNG_ENGLISH; - return( sprintf( s, "%s", ( wday < DAYS_PER_WEEK ) ? - lstrs_wday[language][wday] : "--" ) ); + return snprintf_safe( s, max_len, "%s", ( wday < DAYS_PER_WEEK ) ? + lstrs_wday[language][wday] : "--" ); -} // sprint_ctry_wday +} // snprint_ctry_wday /*HDR*/ -ushort sprint_ctry_dt_short( char *s, uchar mday, uchar month ) +size_t snprint_ctry_dt_short( char *s, size_t max_len, uchar mday, uchar month ) { uchar tmp_1; uchar tmp_2; ushort n = 0; - - switch( ctry.dt_fmt ) + switch ( ctry.dt_fmt ) { case DT_FMT_YYYYMMDD: case DT_FMT_MMDDYYYY: @@ -106,79 +111,77 @@ ushort sprint_ctry_dt_short( char *s, uchar mday, uchar month ) } // switch - n = sprint_02u( s, tmp_1 ); - s[n++] = ctry.dt_sep; - n += sprint_02u( &s[n], tmp_2 ); - s[n++] = ctry.dt_sep; - s[n] = 0; + n = snprint_02u( s, max_len, tmp_1 ); + n += sn_cpy_char_safe( &s[n], max_len - n, ctry.dt_sep ); + n += snprint_02u( &s[n], max_len - n, tmp_2 ); - return( n ); + return n; -} // sprint_ctry_dt_short +} // snprint_ctry_dt_short /*HDR*/ -ushort sprint_ctry_dt( char *s, uchar mday, uchar month, ushort year ) +size_t snprint_ctry_dt( char *s, size_t max_len, uchar mday, uchar month, ushort year ) { - ushort n = 0; - + size_t n = 0; if ( ctry.dt_fmt == DT_FMT_YYYYMMDD ) { - n = sprint_04u( s, year ); - s[n++] = ctry.dt_sep; + n += snprint_04u( &s[n], max_len - n, year ); + n += sn_cpy_char_safe( &s[n], max_len - n, ctry.dt_sep ); } - n += sprint_ctry_dt_short( &s[n], mday, month ); + n += snprint_ctry_dt_short( &s[n], max_len - n, mday, month ); - if ( ctry.dt_fmt == DT_FMT_YYYYMMDD ) - s[--n] = 0; - else - n += sprint_04u( &s[n], year ); + if ( ctry.dt_fmt != DT_FMT_YYYYMMDD ) + { + n += sn_cpy_char_safe( &s[n], max_len - n, ctry.dt_sep ); + n += snprint_04u( &s[n], max_len - n, year ); + } - return( n ); + return n; -} // sprint_ctry_dt +} // snprint_ctry_dt /*HDR*/ -ushort sprint_ctry_tm_short( char *s, uchar hour, uchar minute ) +size_t snprint_ctry_tm_short( char *s, size_t max_len, uchar hour, uchar minute ) { - ushort n = sprint_02u( s, hour ); - s[n++] = ctry.tm_sep; - n += sprint_02u( &s[n], minute ); + size_t n = snprint_02u( s, max_len, hour ); + n += sn_cpy_char_safe( &s[n], max_len - n, ctry.tm_sep ); + n += snprint_02u( &s[n], max_len - n, minute ); - return( n ); + return n; -} // sprint_ctry_tm_short +} // snprint_ctry_tm_short /*HDR*/ -ushort sprint_ctry_tm( char *s, uchar hour, uchar minute, uchar second ) +size_t snprint_ctry_tm( char *s, size_t max_len, uchar hour, uchar minute, uchar second ) { - ushort n = sprint_ctry_tm_short( s, hour, minute ); - s[n++] = ctry.tm_sep; - n += sprint_02u( &s[n], second ); + size_t n = snprint_ctry_tm_short( s, max_len, hour, minute ); + n += sn_cpy_char_safe( &s[n], max_len - n, ctry.tm_sep ); + n += snprint_02u( &s[n], max_len - n, second ); - return( n ); + return n; -} // sprint_ctry_tm +} // snprint_ctry_tm /*HDR*/ -ushort sprint_ctry_tm_long( char *s, uchar hour, uchar minute, uchar second, - long frac, ushort frac_digits ) +size_t snprint_ctry_tm_long( char *s, size_t max_len, uchar hour, uchar minute, + uchar second, long frac, ushort frac_digits ) { - ushort n = sprint_ctry_tm( s, hour, minute, second ); - s[n++] = '.'; - n += sprintf( &s[n], "%0*lu", frac_digits, frac ); + size_t n = snprint_ctry_tm( s, max_len, hour, minute, second ); + n += sn_cpy_char_safe( &s[n], max_len - n, '.' ); + n += snprintf_safe( &s[n], max_len - n, "%0*lu", frac_digits, frac ); - return( n ); + return n; -} // sprint_ctry_tm_long +} // snprint_ctry_tm_long diff --git a/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.h b/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.h index ce613d7..0d2807e 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/ctrydttm.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: ctrydttm.h 1.3 2000/09/14 15:13:45 MARTIN REL_M $ + * $Id: ctrydttm.h 1.5 2015/08/31 10:00:46 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,10 @@ * * ----------------------------------------------------------------------- * $Log: ctrydttm.h $ + * Revision 1.5 2015/08/31 10:00:46 martin + * Fixed DOS build. + * Revision 1.4 2015/08/27 16:28:25Z martin + * Updated function prototypes. * Revision 1.3 2000/09/14 15:13:45 MARTIN * Updated function prototypes. * Revision 1.2 2000/07/21 11:50:43 MARTIN @@ -25,6 +29,8 @@ #include <ctry.h> +#include <stdlib.h> + #ifdef __cplusplus extern "C" { @@ -49,14 +55,14 @@ extern "C" { /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ - ushort sprint_02u( char *s, uchar uc ) ; - ushort sprint_04u( char *s, ushort us ) ; - ushort sprint_ctry_wday( char *s, uchar wday, ushort language ) ; - ushort sprint_ctry_dt_short( char *s, uchar mday, uchar month ) ; - ushort sprint_ctry_dt( char *s, uchar mday, uchar month, ushort year ) ; - ushort sprint_ctry_tm_short( char *s, uchar hour, uchar minute ) ; - ushort sprint_ctry_tm( char *s, uchar hour, uchar minute, uchar second ) ; - ushort sprint_ctry_tm_long( char *s, uchar hour, uchar minute, uchar second, long frac, ushort frac_digits ) ; + size_t snprint_02u( char *s, size_t max_len, uchar uc ) ; + size_t snprint_04u( char *s, size_t max_len, ushort us ) ; + size_t snprint_ctry_wday( char *s, size_t max_len, uchar wday, ushort language ) ; + size_t snprint_ctry_dt_short( char *s, size_t max_len, uchar mday, uchar month ) ; + size_t snprint_ctry_dt( char *s, size_t max_len, uchar mday, uchar month, ushort year ) ; + size_t snprint_ctry_tm_short( char *s, size_t max_len, uchar hour, uchar minute ) ; + size_t snprint_ctry_tm( char *s, size_t max_len, uchar hour, uchar minute, uchar second ) ; + size_t snprint_ctry_tm_long( char *s, size_t max_len, uchar hour, uchar minute, uchar second, long frac, ushort frac_digits ) ; /* ----- function prototypes end ----- */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/deviohlp.c b/src/external/bsd/meinberg/dist/mbglib/common/deviohlp.c new file mode 100755 index 0000000..b0a1180 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/deviohlp.c @@ -0,0 +1,1717 @@ + +/************************************************************************** + * + * $Id: deviohlp.c 1.3 2017/07/05 13:47:44 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Device configuration helper functions. This is an extension to + * mbgdevio.c providing useful functions to simplify reading/writing + * complex device configuration structure sets. + * + * Warning: + * These functions should not be implemented in a DLL / shared library + * since the parameter sizes might vary with different versions + * of the API calls, which which would make different versions of + * precompiled libraries incompatible to each other. + * + * ----------------------------------------------------------------------- + * $Log: deviohlp.c $ + * Revision 1.3 2017/07/05 13:47:44 martin + * Many configuration functions provided by thomas-b, + * philipp, and martin. + * Revision 1.2 2012/10/15 13:48:35Z martin + * Added functions mbg_get_all_ptp_cfg_info(), mbg_save_all_ptp_cfg_info(). + * Account for renamed structure. + * Updated doxygen comments. + * Revision 1.1 2011/08/03 15:37:00Z martin + * Initial revision with functions moved here from mbgdevio. + * + **************************************************************************/ + +#define _DEVIOHLP + #include <deviohlp.h> +#undef _DEVIOHLP + +#include <str_util.h> +#include <lan_util.h> +#include <stdio.h> + + +#define DEFAULT_BAUD_RATES_DCF \ +( \ + MBG_PORT_HAS_300 | \ + MBG_PORT_HAS_600 | \ + MBG_PORT_HAS_1200 | \ + MBG_PORT_HAS_2400 | \ + MBG_PORT_HAS_4800 | \ + MBG_PORT_HAS_9600 \ +) + +#define DEFAULT_BAUD_RATES_DCF_HS \ +( \ + MBG_PORT_HAS_300 | \ + MBG_PORT_HAS_600 | \ + MBG_PORT_HAS_1200 | \ + MBG_PORT_HAS_2400 | \ + MBG_PORT_HAS_4800 | \ + MBG_PORT_HAS_9600 | \ + MBG_PORT_HAS_19200 | \ + MBG_PORT_HAS_38400 \ +) + + +#define DEFAULT_FRAMINGS_DCF \ +( \ + MBG_PORT_HAS_7E2 | \ + MBG_PORT_HAS_8N1 | \ + MBG_PORT_HAS_8N2 | \ + MBG_PORT_HAS_8E1 \ +) + + +/*HDR*/ +int chk_feat_supp( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, MBG_CHK_SUPP_FNC *chk_supp_fnc, + MBG_ERR_MSG_FNC *err_msg_fnc, const char *not_supp_msg ) +{ + const char *cp = NULL; + int rc = MBG_SUCCESS; // assume option is supported + + if ( chk_supp_fnc == NULL ) // no check function specified + goto out; + + + // A check function has been specified, so we must call it to check if + // the specific parameter/command is supported by this particular device. + + if ( dh == MBG_INVALID_DEV_HANDLE ) + { + cp = "Tried checking feature support with invalid device handle."; + rc = MBG_ERR_INV_HANDLE; + goto out; + } + + rc = chk_supp_fnc( dh ); + + if ( mbg_rc_is_success( rc ) ) + goto out; // return with success + + + if ( rc == MBG_ERR_NOT_SUPP_BY_DEV ) + { + cp = not_supp_msg; + goto fail; + } + + + cp = "Failed to check if supported"; //##++++ TODO:proper error msg + +fail: + if ( err_msg_fnc && cp ) + err_msg_fnc( p_dev, cp ); + +out: + return rc; + +} // chk_feat_supp + + + +/*HDR*/ +/** + * @brief Read or setup all GNSS status information + * + * This function should be called preferably to get a summary of + * the GNSS status from GNSS receivers (GPS, GLONASS, ...). + * + * The function ::mbg_get_device_info must have been called before, and + * the returned ::PCPS_DEV structure has to be passed to this function. + * + * If the device supports this then the low level GNSS API functions + * are called directly to collect the status information. If the device + * doesn't support the GNSS API but is a pure GPS receiver then the GPS + * API functions are called and the GNSS data structures are filled up + * accordingly, so the calling application can always evaluate the + * GNSS data structures in ::ALL_GNSS_INFO. + * + * If neither GPS nor another GNSS system is supported then this function + * returns the ::MBG_ERR_NOT_SUPP_BY_DEV error. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] p_agi Pointer to a ::ALL_GNSS_INFO to be filled + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_get_gps_stat_info + * @see ::mbg_get_gps_gnss_mode_info + * @see ::mbg_get_gps_all_gnss_sat_info + */ +int mbg_chk_get_all_gnss_info( MBG_DEV_HANDLE dh, ALL_GNSS_INFO *p_agi ) +{ + int rc = MBG_ERR_UNSPEC; + + memset( p_agi, 0, sizeof( *p_agi ) ); + + // First we check if the device is a GPS receiver, + // which includes GNSS receivers. + rc = mbg_chk_dev_is_gps( dh ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + + // Read the STAT_INFO structure which is supported by all GPS + // and GNSS receivers. + rc = mbg_get_gps_stat_info( dh, &p_agi->stat_info ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + + // Check if the device is a GNSS receiver, i.e. can track satellites + // from different systems (GPS, GLONASS, Beidou, ...). + rc = mbg_chk_dev_is_gnss( dh ); + + if ( mbg_rc_is_success( rc ) ) + { + // The device is a GNSS receiver, i.e. it can track satellites + // from different systems (GPS, GLONASS, Beidou, ...). + // Read some specific GNSS information. + rc = mbg_get_gps_gnss_mode_info( dh, &p_agi->gnss_mode_info ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + + rc = chk_set_n_gnss_supp( p_agi ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + + // If the the device supports the current API we can simply + // retrieve status information for each individual GNSS system. + rc = mbg_get_gps_all_gnss_sat_info( dh, p_agi->gnss_sat_info_idx, &p_agi->gnss_mode_info ); + goto out; + } + + + // If we get here then the device is a pure GPS receiver + // which neither supports additional GNSS systems nor the + // associated data structures, so we set up all GNSS + // data structures for GPS only. + rc = setup_gps_only_gnss_info_from_statinfo( p_agi ); + +out: + return rc; + +} // mbg_chk_get_all_gnss_info + + + +#if !MBGDEVIO_SIMPLE + +/*HDR*/ +/** + * @brief Read all serial port settings and supported configuration parameters + * + * The functions ::mbg_get_device_info and ::mbg_setup_receiver_info + * must have been called before, and the returned ::PCPS_DEV and + * ::RECEIVER_INFO structures have to be passed to this function. + * + * The complementary function ::mbg_save_serial_settings should be used + * to write the modified serial port configuration back to the board. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[in] *p_dev Pointer to a valid ::PCPS_DEV structure + * @param[out] *p_rpcfg Pointer to a ::RECEIVER_PORT_CFG structure to be filled up + * @param[in] *p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return ::MBG_SUCCESS or error code returned by device I/O control function + * + * @see ::mbg_get_device_info + * @see ::mbg_setup_receiver_info + * @see ::mbg_save_serial_settings + */ +int mbg_get_serial_settings( MBG_DEV_HANDLE dh, + const PCPS_DEV *p_dev, + RECEIVER_PORT_CFG *p_rpcfg, + const RECEIVER_INFO *p_ri ) +{ + int rc; + + memset( p_rpcfg, 0, sizeof( *p_rpcfg ) ); + + if ( _pcps_has_receiver_info( p_dev ) ) + { + // The device provides a RECEIVER_INFO, so we can simply read all + // serial port configuration and supported string types directly. + + rc = mbg_get_gps_all_port_info( dh, p_rpcfg->pii, p_ri ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + rc = mbg_get_gps_all_str_type_info( dh, p_rpcfg->stii, p_ri ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + } + else + { + // The device doesn't support a RECEIVER_INFO, so this is + // an old GPS or non-GPS device. + + if ( _pcps_is_gps( p_dev ) ) + { + // Read the serial port configuration from an old GPS device using + // a legacy API call and set up current structures accordingly. + + rc = mbg_get_gps_port_parm( dh, &p_rpcfg->tmp_pp ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + rc = setup_port_info_from_port_settings( p_rpcfg->pii, &p_rpcfg->tmp_pp, p_ri ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + // Also set up default string type information. + rc = setup_default_str_type_info_idx( p_rpcfg->stii, p_ri ); + } + else + { + // Not all legacy non-GPS clocks have a serial port. + if ( _pcps_has_serial( p_dev ) ) + { + // Read the serial port configuration from an old non-GPS device using + // a legacy API call and set up current structures accordingly. + + PCPS_SERIAL ser_code; + + rc = mbg_get_serial( dh, &ser_code ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + port_info_from_pcps_serial( p_rpcfg->pii, ser_code, + _pcps_has_serial_hs( p_dev ) ? + DEFAULT_BAUD_RATES_DCF_HS : + DEFAULT_BAUD_RATES_DCF + ); + // Also set up default string type information. + rc = setup_default_str_type_info_idx( p_rpcfg->stii, p_ri ); + } + } + + } + + rc = MBG_SUCCESS; + +out: + return rc; + +} // mbg_get_serial_settings + + + +/*HDR*/ +/** + * @brief Write the configuration settings for a single serial port to a device + * + * Modifications to the serial port configuration should be made only + * after ::mbg_get_serial_settings had been called to read all serial port + * settings and supported configuration parameters. + * This function has finally to be called once for every serial port + * the configuration of which has been modified. + * + * As also required by ::mbg_get_serial_settings, the functions + * ::mbg_get_device_info and ::mbg_setup_receiver_info must have been + * called before, and the returned ::PCPS_DEV and ::RECEIVER_INFO structures + * vave to be passed to this function. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[in] *p_dev Pointer to a valid ::PCPS_DEV structure + * @param[in] *p_rpcfg Pointer to a valid ::RECEIVER_PORT_CFG structure + * @param[in] port_num Index of the serial port to be saved + * + * @return ::MBG_SUCCESS or error code returned by device I/O control function. + * + * @see ::mbg_get_serial_settings + * @see ::mbg_get_device_info + * @see ::mbg_setup_receiver_info + */ +int mbg_save_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, + RECEIVER_PORT_CFG *p_rpcfg, int port_num ) +{ + int rc; + + if ( _pcps_has_receiver_info( p_dev ) ) + { + rc = mbg_set_gps_port_settings( dh, &p_rpcfg->pii[port_num].port_info.port_settings, port_num ); + } + else + { + if ( _pcps_is_gps( p_dev ) ) + { + port_parm_from_port_settings( &p_rpcfg->tmp_pp, port_num, + &p_rpcfg->pii[port_num].port_info.port_settings, 1 ); + + rc = mbg_set_gps_port_parm( dh, &p_rpcfg->tmp_pp ); + } + else + { + PCPS_SERIAL ser_code; + + pcps_serial_from_port_info( &ser_code, p_rpcfg->pii ); + + rc = mbg_set_serial( dh, &ser_code ); + } + } + + return rc; + +} // mbg_save_serial_settings + + + +/*HDR*/ +/** + * @brief Read all network configuration into an ::ALL_NET_CFG_INFO structure + * + * Reads the network configuration of a device via the LAN_IP4 API and + * translates the structures into NET_CFG structures. + * + * As soon as available, this function should make use of the NET_CFG API. + * + * A ::ALL_NET_CFG_INFO and the appropriate number of ::MBG_NET_INTF_LINK_INFO_IDX, + * ::MBG_NET_INTF_ADDR_INFO_IDX, ::MBG_IP_ADDR_IDX, ::MBG_NET_NAME_IDX and + * ::MBG_NET_INTF_ROUTE_INFO_IDX will be allocated and need to be freed later + * by calling ::free_all_net_cfg_info + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] p Pointer to a pointer of ::ALL_NET_CFG_INFO + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_get_lan_if_info + * @see ::mbg_get_ip4_settings + * @see ::free_all_net_cfg_info + */ +int mbg_get_all_net_cfg_info( MBG_DEV_HANDLE dh, ALL_NET_CFG_INFO **p ) +{ + ALL_NET_CFG_INFO *net_cfg_info = *p; + int rc; + + if ( net_cfg_info == NULL ) + { + net_cfg_info = ( ALL_NET_CFG_INFO * )calloc( 1, sizeof( *net_cfg_info ) ); + if ( net_cfg_info == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + } + + // TODO Use NET_CFG API as soon as its available for PCI/PCIe devices + rc = mbg_chk_dev_has_lan_intf( dh ); + + if ( mbg_rc_is_success( rc ) ) + { + LAN_IF_INFO lan_if_info; + IP4_SETTINGS ip4_settings; + + if ( net_cfg_info->glb_cfg_info.n_supp_intf_link != 0 ) + goto out; + + rc = mbg_get_lan_if_info( dh, &lan_if_info ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + if ( net_cfg_info->link_infos == NULL ) + { + net_cfg_info->link_infos = ( MBG_NET_INTF_LINK_INFO_IDX * )calloc( 1, sizeof( *net_cfg_info->link_infos ) ); + if ( net_cfg_info->link_infos == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + } + + net_cfg_info->glb_cfg_info.glb_settings.num_intf_link = 1; + + memset( &net_cfg_info->link_infos[0], 0, sizeof( net_cfg_info->link_infos[0] ) ); + + net_cfg_info->link_infos[0].info.supp_states = MBG_NET_INTF_LINK_STATE_MASK_UP; + net_cfg_info->link_infos[0].info.supp_types = MBG_NET_INTF_LINK_TYPE_MASK_PHYS | MBG_NET_INTF_LINK_TYPE_MASK_VLAN; + net_cfg_info->link_infos[0].info.supp_speed_modes = MBG_NET_INTF_LINK_SPEED_MODE_MASK_10_T_HALF | MBG_NET_INTF_LINK_SPEED_MODE_MASK_10_T_FULL | MBG_NET_INTF_LINK_SPEED_MODE_MASK_100_T_HALF | MBG_NET_INTF_LINK_SPEED_MODE_MASK_100_T_FULL; + net_cfg_info->link_infos[0].info.supp_port_types = MBG_NET_INTF_LINK_PORT_TYPE_MASK_TP; + + snprintf_safe( net_cfg_info->link_infos[0].info.link_settings.name, sizeof( net_cfg_info->link_infos[0].info.link_settings.name ), "lan0" ); + net_cfg_info->link_infos[0].info.link_settings.mac_addr = lan_if_info.mac_addr; + net_cfg_info->link_infos[0].info.link_settings.if_index = 0; + net_cfg_info->link_infos[0].info.link_settings.type = MBG_NET_INTF_LINK_TYPE_PHYS; + net_cfg_info->link_infos[0].info.link_settings.port_type = MBG_NET_INTF_LINK_PORT_TYPE_TP; + + if ( net_cfg_info->glb_cfg_info.n_supp_intf_addr != 0 ) + goto out; + + rc = mbg_get_ip4_settings( dh, &ip4_settings ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + if( ip4_settings.flags & IP4_MSK_LINK ) + { + net_cfg_info->link_infos->info.link_settings.states |= MBG_NET_INTF_LINK_STATE_MASK_UP; + net_cfg_info->link_infos->info.link_settings.states |= MBG_NET_INTF_LINK_STATE_MASK_LOWER_UP; + } + + if ( net_cfg_info->addr_infos == NULL ) + { + net_cfg_info->addr_infos = ( MBG_NET_INTF_ADDR_INFO_IDX * )calloc( 1, sizeof( *net_cfg_info->addr_infos ) ); + if ( net_cfg_info->addr_infos == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + } + + net_cfg_info->glb_cfg_info.glb_settings.num_intf_addr = 1; + + memset( &net_cfg_info->addr_infos[0], 0, sizeof( net_cfg_info->addr_infos[0] ) ); + + net_cfg_info->addr_infos[0].info.supp_flags = MBG_NET_INTF_ADDR_MASK_DHCP4; + + snprintf_safe( net_cfg_info->addr_infos[0].info.addr_settings.label, sizeof( net_cfg_info->addr_infos[0].info.addr_settings.label ), "lan0:0" ); + + if ( ip4_settings.flags & IP4_MSK_VLAN ) + { + net_cfg_info->link_infos = ( MBG_NET_INTF_LINK_INFO_IDX * )realloc( net_cfg_info->link_infos, 2 * sizeof( *net_cfg_info->link_infos ) ); + if ( net_cfg_info->link_infos == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + + net_cfg_info->glb_cfg_info.glb_settings.num_intf_link = 2; + + memset(&net_cfg_info->link_infos[1], 0, sizeof(net_cfg_info->link_infos[1])); + + net_cfg_info->link_infos[1].idx = 1; + net_cfg_info->link_infos[1].info.supp_states = MBG_NET_INTF_LINK_STATE_MASK_UP; + net_cfg_info->link_infos[1].info.supp_types = MBG_NET_INTF_LINK_TYPE_MASK_VLAN; + net_cfg_info->link_infos[1].info.supp_speed_modes = MBG_NET_INTF_LINK_SPEED_MODE_MASK_10_T_HALF | MBG_NET_INTF_LINK_SPEED_MODE_MASK_10_T_FULL | MBG_NET_INTF_LINK_SPEED_MODE_MASK_100_T_HALF | MBG_NET_INTF_LINK_SPEED_MODE_MASK_100_T_FULL; + net_cfg_info->link_infos[1].info.supp_port_types = MBG_NET_INTF_LINK_PORT_TYPE_MASK_TP; + + snprintf_safe( net_cfg_info->link_infos[1].info.link_settings.name, sizeof( net_cfg_info->link_infos[1].info.link_settings.name ), "vlan0" ); + net_cfg_info->link_infos[1].info.link_settings.mac_addr = net_cfg_info->link_infos[0].info.link_settings.mac_addr; + net_cfg_info->link_infos[1].info.link_settings.if_index = 1; + net_cfg_info->link_infos[1].info.link_settings.ass_if_index = 0; + net_cfg_info->link_infos[1].info.link_settings.states = net_cfg_info->link_infos[0].info.link_settings.states; + net_cfg_info->link_infos[1].info.link_settings.type = MBG_NET_INTF_LINK_TYPE_VLAN; + net_cfg_info->link_infos[1].info.link_settings.vlan_cfg = ip4_settings.vlan_cfg; + + net_cfg_info->addr_infos[0].info.addr_settings.ass_if_index = 1; + } + + if ( ip4_settings.flags & IP4_MSK_DHCP ) + net_cfg_info->addr_infos[0].info.addr_settings.flags |= MBG_NET_INTF_ADDR_MASK_DHCP4; + + net_cfg_info->addr_infos[0].info.addr_settings.ip.type = MBG_IP_ADDR_TYPE_IP4; + net_cfg_info->addr_infos[0].info.addr_settings.ip.u_addr.ip4_addr = ip4_settings.ip_addr; + + net_cfg_info->addr_infos[0].info.addr_settings.broadcast.type = MBG_IP_ADDR_TYPE_IP4; + net_cfg_info->addr_infos[0].info.addr_settings.broadcast.u_addr.ip4_addr = ip4_settings.broad_addr; + + net_cfg_info->addr_infos[0].info.addr_settings.prefix_bits = get_ip4_net_mask_bits(&ip4_settings.netmask); + + if ( net_cfg_info->glb_cfg_info.n_supp_intf_route == 0 ) + { + if ( net_cfg_info->route_infos == NULL ) + { + net_cfg_info->route_infos = ( MBG_NET_INTF_ROUTE_INFO_IDX * )calloc( 1, sizeof( *net_cfg_info->route_infos ) ); + if ( net_cfg_info->route_infos == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + } + + net_cfg_info->glb_cfg_info.glb_settings.num_intf_route = 1; + + memset( &net_cfg_info->route_infos[0], 0, sizeof( net_cfg_info->route_infos[0] ) ); + + net_cfg_info->route_infos[0].info.route_settings.type = MBG_NET_INTF_ROUTE_TYPE_DEFAULT_GATEWAY; + net_cfg_info->route_infos[0].info.route_settings.gateway.type = MBG_IP_ADDR_TYPE_IP4; + net_cfg_info->route_infos[0].info.route_settings.gateway.u_addr.ip4_addr = ip4_settings.gateway; + if ( ip4_settings.gateway != 0 ) + { + if(net_cfg_info->glb_cfg_info.glb_settings.num_intf_link == 2) + net_cfg_info->route_infos[0].info.route_settings.ass_if_index = 1; + } + else net_cfg_info->route_infos[0].info.route_settings.ass_if_index = (uint32_t)-1; + + } + + } + +out: + if ( mbg_rc_is_error( rc ) ) + { + free_all_net_cfg_info( net_cfg_info ); + net_cfg_info = NULL; + } + + *p = net_cfg_info; + + return rc; + +} // mbg_get_all_net_cfg_info + + + +/*HDR*/ +/** + * @brief Write all network settings to a device + * + * The complementary function ::mbg_get_all_net_cfg_info should + * have been used to read the original network settings and + * supported configuration parameters. + * + * The appropriate settings are translated into LAN_IP4 structures + * and send to the device using the appropriate API functions. + * + * As soon as available, this function should make use of the NET_CFG API. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[in] p Pointer to a pointer of ::ALL_NET_CFG_INFO + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_set_ip4_settings + */ +int mbg_save_all_net_cfg_info( MBG_DEV_HANDLE dh, ALL_NET_CFG_INFO *p ) +{ + // TODO: Use NET_CFG API as soon as its available for PCI/PCIe devices + int rc = mbg_chk_dev_has_lan_intf( dh ); + + if ( mbg_rc_is_success( rc ) ) + { + IP4_SETTINGS ip4_settings; + memset( &ip4_settings, 0, sizeof( ip4_settings ) ); + + if ( p->addr_infos[0].info.addr_settings.ip.type == MBG_IP_ADDR_TYPE_IP4 ) + ip4_settings.ip_addr = p->addr_infos[0].info.addr_settings.ip.u_addr.ip4_addr; + + ip4_settings.netmask = ip4_net_mask_from_cidr( p->addr_infos[0].info.addr_settings.prefix_bits ); + ip4_settings.broad_addr = ip4_broad_addr_from_addr( &ip4_settings.ip_addr, &ip4_settings.netmask ); + + if ( p->route_infos[0].info.route_settings.gateway.type == MBG_IP_ADDR_TYPE_IP4 ) + ip4_settings.gateway = p->route_infos[0].info.route_settings.gateway.u_addr.ip4_addr; + + if ( ( p->glb_cfg_info.glb_settings.num_intf_link > 1 ) && ( p->addr_infos[0].info.addr_settings.ass_if_index == 1 ) ) + { + ip4_settings.flags |= IP4_MSK_VLAN; + ip4_settings.vlan_cfg = p->link_infos[1].info.link_settings.vlan_cfg; + } + + if ( ( p->addr_infos[0].info.addr_settings.flags & MBG_NET_INTF_ADDR_MASK_DHCP4 ) == MBG_NET_INTF_ADDR_MASK_DHCP4 ) + ip4_settings.flags |= IP4_MSK_DHCP; + + rc = mbg_set_ip4_settings( dh, &ip4_settings ); + } + + return rc; + +} // mbg_save_all_net_cfg_info + + + +/*HDR*/ +/** + * @brief Read current network status into an ::ALL_NET_STATUS_INFO structure + * + * Reads the network status of a device via the LAN_IP4 API and + * translates the structures into NET_CFG structures. + * + * As soon as available, this function should make use of the NET_CFG API. + * + * A ::ALL_NET_STATUS_INFO and the appropriate number of ::MBG_NET_INTF_LINK_INFO_IDX, + * ::MBG_NET_INTF_ADDR_INFO_IDX, ::MBG_IP_ADDR_IDX, ::MBG_NET_NAME_IDX and + * ::MBG_NET_INTF_ROUTE_INFO_IDX will be allocated and need to be freed later + * by calling ::free_all_net_status_info + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] p Pointer to a pointer of ::ALL_NET_STATUS_INFO + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_get_lan_if_info + * @see ::mbg_get_ip4_state + * @see ::free_all_net_status_info + */ +int mbg_get_all_net_status_info( MBG_DEV_HANDLE dh, ALL_NET_STATUS_INFO **p ) +{ + ALL_NET_STATUS_INFO *net_status_info = *p; + int rc; + + if ( net_status_info == NULL ) + { + net_status_info = ( ALL_NET_STATUS_INFO * )calloc( 1, sizeof( *net_status_info ) ); + if ( net_status_info == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + } + + // TODO Use NET_CFG API as soon as its available for PCI/PCIe devices + rc = mbg_chk_dev_has_lan_intf( dh ); + + if ( mbg_rc_is_success( rc ) ) + { + LAN_IF_INFO lan_if_info; + IP4_SETTINGS ip4_state; + + if ( net_status_info->glb_cfg_info.n_supp_intf_link != 0 ) + goto out; + + rc = mbg_get_lan_if_info( dh, &lan_if_info ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + if ( net_status_info->link_infos == NULL ) + { + net_status_info->link_infos = ( MBG_NET_INTF_LINK_INFO_IDX * )calloc( 1, sizeof( *net_status_info->link_infos ) ); + if ( net_status_info->link_infos == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + } + + net_status_info->glb_cfg_info.glb_settings.num_intf_addr = 1; + + memset( &net_status_info->link_infos[0], 0, sizeof( net_status_info->link_infos[0] ) ); + + net_status_info->link_infos[0].info.supp_states = MBG_NET_INTF_LINK_STATE_MASK_UP; + net_status_info->link_infos[0].info.supp_types = MBG_NET_INTF_LINK_TYPE_MASK_PHYS | MBG_NET_INTF_LINK_TYPE_MASK_VLAN; + net_status_info->link_infos[0].info.supp_speed_modes = MBG_NET_INTF_LINK_SPEED_MODE_MASK_10_T_HALF | MBG_NET_INTF_LINK_SPEED_MODE_MASK_10_T_FULL | MBG_NET_INTF_LINK_SPEED_MODE_MASK_100_T_HALF | MBG_NET_INTF_LINK_SPEED_MODE_MASK_100_T_FULL; + net_status_info->link_infos[0].info.supp_port_types = MBG_NET_INTF_LINK_PORT_TYPE_MASK_TP; + + snprintf_safe( net_status_info->link_infos[0].info.link_settings.name, sizeof( net_status_info->link_infos[0].info.link_settings.name ), "lan0" ); + net_status_info->link_infos[0].info.link_settings.mac_addr = lan_if_info.mac_addr; + net_status_info->link_infos[0].info.link_settings.if_index = 0; + net_status_info->link_infos[0].info.link_settings.type = MBG_NET_INTF_LINK_TYPE_PHYS; + net_status_info->link_infos[0].info.link_settings.port_type = MBG_NET_INTF_LINK_PORT_TYPE_TP; + + if ( net_status_info->glb_cfg_info.n_supp_intf_addr != 0 ) + goto out; + + rc = mbg_get_ip4_state( dh, &ip4_state ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + if( ip4_state.flags & IP4_MSK_LINK ) + { + net_status_info->link_infos[0].info.link_settings.states |= MBG_NET_INTF_LINK_STATE_MASK_UP; + net_status_info->link_infos[0].info.link_settings.states |= MBG_NET_INTF_LINK_STATE_MASK_LOWER_UP; + } + + if ( net_status_info->addr_infos == NULL ) + { + net_status_info->addr_infos = ( MBG_NET_INTF_ADDR_INFO_IDX * )realloc( net_status_info->addr_infos, sizeof( *net_status_info->addr_infos ) ); + if ( net_status_info->addr_infos == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + } + + net_status_info->glb_cfg_info.glb_settings.num_intf_addr = 1; + + memset( &net_status_info->addr_infos[0], 0, sizeof( net_status_info->addr_infos[0] ) ); + + net_status_info->addr_infos[0].info.supp_flags = MBG_NET_INTF_ADDR_MASK_DHCP4; + + snprintf_safe( net_status_info->addr_infos[0].info.addr_settings.label, sizeof( net_status_info->addr_infos[0].info.addr_settings.label ), "lan0:0" ); + + if ( ip4_state.flags & IP4_MSK_VLAN ) + { + net_status_info->link_infos = ( MBG_NET_INTF_LINK_INFO_IDX * )realloc( net_status_info->link_infos, 2 * sizeof( *net_status_info->link_infos ) ); + if ( net_status_info->link_infos == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + + net_status_info->glb_cfg_info.glb_settings.num_intf_link = 2; + + memset(&net_status_info->link_infos[1], 0, sizeof(net_status_info->link_infos[1])); + + net_status_info->link_infos[1].idx = 1; + net_status_info->link_infos[1].info.supp_states = MBG_NET_INTF_LINK_STATE_MASK_UP; + net_status_info->link_infos[1].info.supp_types = MBG_NET_INTF_LINK_TYPE_MASK_VLAN; + net_status_info->link_infos[1].info.supp_speed_modes = MBG_NET_INTF_LINK_SPEED_MODE_MASK_10_T_HALF | MBG_NET_INTF_LINK_SPEED_MODE_MASK_10_T_FULL | MBG_NET_INTF_LINK_SPEED_MODE_MASK_100_T_HALF | MBG_NET_INTF_LINK_SPEED_MODE_MASK_100_T_FULL; + net_status_info->link_infos[1].info.supp_port_types = MBG_NET_INTF_LINK_PORT_TYPE_MASK_TP; + + snprintf_safe( net_status_info->link_infos[1].info.link_settings.name, sizeof( net_status_info->link_infos[1].info.link_settings.name ), "vlan0" ); + net_status_info->link_infos[1].info.link_settings.mac_addr = net_status_info->link_infos[0].info.link_settings.mac_addr; + net_status_info->link_infos[1].info.link_settings.if_index = 1; + net_status_info->link_infos[1].info.link_settings.ass_if_index = 0; + net_status_info->link_infos[1].info.link_settings.states = net_status_info->link_infos[0].info.link_settings.states; + net_status_info->link_infos[1].info.link_settings.type = MBG_NET_INTF_LINK_TYPE_VLAN; + net_status_info->link_infos[1].info.link_settings.vlan_cfg = ip4_state.vlan_cfg; + + net_status_info->addr_infos[0].info.addr_settings.ass_if_index = 1; + } + + if ( ip4_state.flags & IP4_MSK_DHCP ) + net_status_info->addr_infos[0].info.addr_settings.flags |= MBG_NET_INTF_ADDR_MASK_DHCP4; + + net_status_info->addr_infos[0].info.addr_settings.ip.type = MBG_IP_ADDR_TYPE_IP4; + net_status_info->addr_infos[0].info.addr_settings.ip.u_addr.ip4_addr = ip4_state.ip_addr; + + net_status_info->addr_infos[0].info.addr_settings.broadcast.type = MBG_IP_ADDR_TYPE_IP4; + net_status_info->addr_infos[0].info.addr_settings.broadcast.u_addr.ip4_addr = ip4_state.broad_addr; + + net_status_info->addr_infos[0].info.addr_settings.prefix_bits = get_ip4_net_mask_bits(&ip4_state.netmask); + + if ( net_status_info->glb_cfg_info.n_supp_intf_route == 0 ) + { + if ( net_status_info->route_infos == NULL ) + { + net_status_info->route_infos = ( MBG_NET_INTF_ROUTE_INFO_IDX * )calloc( 1, sizeof( *net_status_info->route_infos ) ); + if ( net_status_info->route_infos == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + } + + net_status_info->glb_cfg_info.glb_settings.num_intf_route = 1; + + memset( &net_status_info->route_infos[0], 0, sizeof( net_status_info->route_infos[0] ) ); + + net_status_info->route_infos[0].info.route_settings.type = MBG_NET_INTF_ROUTE_TYPE_DEFAULT_GATEWAY; + net_status_info->route_infos[0].info.route_settings.gateway.type = MBG_IP_ADDR_TYPE_IP4; + net_status_info->route_infos[0].info.route_settings.gateway.u_addr.ip4_addr = ip4_state.gateway; + if ( ip4_state.gateway != 0 ) + { + if(net_status_info->glb_cfg_info.glb_settings.num_intf_link == 2) + net_status_info->route_infos[0].info.route_settings.ass_if_index = 1; + } + else net_status_info->route_infos[0].info.route_settings.ass_if_index = (uint32_t)-1; + + } + + } + +out: + if ( mbg_rc_is_error( rc ) ) + { + free_all_net_status_info( net_status_info ); + net_status_info = NULL; + } + + *p = net_status_info; + + return rc; + +} // mbg_get_all_net_status_info + + + +/*HDR*/ +/** + * @brief Read all PTP settings and supported configuration parameters + * + * The complementary function ::mbg_save_all_ptp_cfg_info should + * be used to write the modified configuration back to the device. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] *p Pointer to a ::ALL_PTP_CFG_INFO structure to be filled up + * + * @return ::MBG_SUCCESS or error code returned by device I/O control function. + * + * @see ::mbg_save_all_ptp_cfg_info + * @see ::mbg_get_ptp_cfg_info + * @see ::mbg_get_ptp_uc_master_cfg_limits + * @see ::mbg_get_all_ptp_uc_master_info + * @see ::mbg_chk_dev_has_ptp + * @see ::mbg_chk_dev_has_ptp_unicast + */ +int mbg_get_all_ptp_cfg_info( MBG_DEV_HANDLE dh, ALL_PTP_CFG_INFO *p ) +{ + int rc = MBG_SUCCESS; + + memset( p, 0, sizeof( *p ) ); + + rc = mbg_get_ptp_cfg_info( dh, &p->ptp_cfg_info ); + + if ( rc < 0 ) + return rc; + + if ( p->ptp_cfg_info.supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) + { + rc = mbg_get_ptp_uc_master_cfg_limits( dh, &p->ptp_uc_master_cfg_limits ); + + if ( rc < 0 ) + return rc; + + if ( p->ptp_uc_master_cfg_limits.n_supp_master > MAX_PARM_PTP_UC_MASTER ) + { + // The number of PTP unicast masters supported by this device + // exceeds the number of unicast masters supporterd by this driver. + return MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP; + } + + rc = mbg_get_all_ptp_uc_master_info( dh, p->all_ptp_uc_master_info_idx, + &p->ptp_uc_master_cfg_limits ); + if ( rc < 0 ) + return rc; + } + + return MBG_SUCCESS; + +} // mbg_get_all_ptp_cfg_info + + + +/*HDR*/ +/** + * @brief Write all PTP settings to a device + * + * The complementary function ::mbg_get_all_ptp_cfg_info should + * have been used to read the original PTP settings and supported + * configuration parameters. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[in] *p Pointer to a valid ::ALL_PTP_CFG_INFO structure + * + * @return ::MBG_SUCCESS or error code returned by device I/O control function. + * + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_set_ptp_cfg_settings + * @see ::mbg_set_ptp_uc_master_settings_idx + * @see ::mbg_chk_dev_has_ptp + * @see ::mbg_chk_dev_has_ptp_unicast + */ +int mbg_save_all_ptp_cfg_info( MBG_DEV_HANDLE dh, const ALL_PTP_CFG_INFO *p ) +{ + int rc = MBG_SUCCESS; + + rc = mbg_set_ptp_cfg_settings( dh, &p->ptp_cfg_info.settings ); + + if ( rc < 0 ) + return rc; + + + if ( p->ptp_cfg_info.supp_flags & PTP_CFG_MSK_SUPPORT_PTP_UNICAST ) + { + int i; + + for ( i = 0; i < p->ptp_uc_master_cfg_limits.n_supp_master; i++ ) + { + PTP_UC_MASTER_SETTINGS_IDX s; + + memset( &s, 0, sizeof( s ) ); + + s.idx = i; + s.settings = p->all_ptp_uc_master_info_idx[i].info.settings; + + rc = mbg_set_ptp_uc_master_settings_idx( dh, &s ); + + if ( rc < 0 ) + return rc; + } + } + + return MBG_SUCCESS; + +} // mbg_save_all_ptp_cfg_info + +#endif // !MBGDEVIO_SIMPLE + + +/*HDR*/ +/** + * @brief Read all XMR info into a newly or re-allocated ::ALL_XMULTI_REF_INFO + * + * @note ::mbg_chk_dev_has_xmr should be called before using this function + * + * A ::ALL_XMULTI_REF_INFO and a number of ::XMULTI_REF_INSTANCES::n_xmr_settings + * of ::XMULTI_REF_INFO_IDX and ::XMR_EXT_SRC_INFO_IDX will be allocated and needs + * to be freed by calling ::free_all_xmulti_ref_info + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] p Pointer to a pointer of ::ALL_XMULTI_REF_INFO + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::free_all_xmulti_ref_info + */ +int mbg_get_all_xmulti_ref_info( MBG_DEV_HANDLE dh, ALL_XMULTI_REF_INFO **p ) +{ + ALL_XMULTI_REF_INFO *xmr_info = *p; + int rc; + + if ( xmr_info == NULL ) + { + xmr_info = ( ALL_XMULTI_REF_INFO * )calloc( 1, sizeof( *xmr_info ) ); + if ( xmr_info == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + } + + // First, get the XMULTI_REF_INSTANCES to check how many sources are supported + rc = mbg_get_xmr_instances( dh, &xmr_info->instances ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + if ( xmr_info->infos == NULL ) + { + xmr_info->infos = ( XMULTI_REF_INFO_IDX * )calloc( xmr_info->instances.n_xmr_settings, sizeof( *xmr_info->infos ) ); + if ( xmr_info->infos == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + } + + rc = mbg_get_gps_all_xmr_info( dh, xmr_info->infos, &xmr_info->instances ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + if ( mbg_rc_is_success( chk_dev_xmulti_ref_supp_ext_src_info( xmr_info ) ) ) + { + // TODO!!! + // XMR_EXT_SRC_INFO_IDX can not be read out from bus devices, yet + // Therefore, remove the feature bit from this card + // Has to be changed as soon as low level functions are ready + // TODO!!! + xmr_info->instances.flags &= ~XMRIF_MSK_EXT_SRC_INFO_SUPP; + } + +out: + if ( mbg_rc_is_error( rc ) ) + { + free_all_xmulti_ref_info( xmr_info ); + xmr_info = NULL; + } + + *p = xmr_info; + + return rc; + +} // mbg_get_all_xmulti_ref_info + + +/*HDR*/ +/** + * @brief Set all extended multi ref settings to a device + * + * The complementary function ::mbg_get_all_xmulti_ref_info should + * have been used to read the original extended multi ref info. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] p Pointer to a ::ALL_XMULTI_REF_INFO structure with all settings + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_set_gps_xmr_settings_idx + */ +_NO_MBG_API_ATTR int _MBG_API mbg_save_all_xmulti_ref_info( MBG_DEV_HANDLE dh, ALL_XMULTI_REF_INFO *p ) +{ + int rc = MBG_SUCCESS, i; + XMULTI_REF_SETTINGS_IDX settings; + + for (i = 0; ( i < p->instances.n_xmr_settings ) && mbg_rc_is_success( rc ); i++ ) + { + settings.idx = i; + memcpy( &settings.settings, &p->infos[i].info.settings, sizeof( settings.settings ) ); + rc = mbg_set_gps_xmr_settings_idx( dh, &settings ); + } + + // if all settings have been successully set, send dummy structure with index -1 to apply settings + if( mbg_rc_is_success( rc ) ) + { + memset( &settings, 0, sizeof( settings ) ); + settings.idx = -1; + settings.settings.id.type = MULTI_REF_NONE; + rc = mbg_set_gps_xmr_settings_idx( dh, &settings ); + } + + return rc; + +} // mbg_save_all_xmulti_ref_info + + +/*HDR*/ +/** + * @brief Read all XMR status info into a newly or re-allocated ::ALL_XMULTI_REF_STATUS + * + * @note ::mbg_chk_dev_has_xmr should be called before using this function + * + * A ::ALL_XMULTI_REF_STATUS and a number of ::XMULTI_REF_INSTANCES::n_xmr_settings + * of ::XMULTI_REF_STATUS_IDX will be allocated and needs to be freed by calling + * ::free_all_xmulti_ref_status + * + * @param[in] dh Valid handle to a Meinberg device + * @param[in] info Pointer to the appropriate info structure + * @param[out] p Pointer to a pointer of ::ALL_XMULTI_REF_STATUS + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::free_all_xmulti_ref_status + */ +int mbg_get_all_xmulti_ref_status( MBG_DEV_HANDLE dh, const ALL_XMULTI_REF_INFO *info, ALL_XMULTI_REF_STATUS **p ) +{ + ALL_XMULTI_REF_STATUS *xmr_status = *p; + int rc; + + if ( info == NULL ) + return MBG_ERR_INV_PARM; + + if ( xmr_status == NULL ) + { + xmr_status = ( ALL_XMULTI_REF_STATUS * )calloc( 1, sizeof( *xmr_status ) ); + if ( xmr_status == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + } + + if ( xmr_status->status == NULL ) + { + xmr_status->status = ( XMULTI_REF_STATUS_IDX* )calloc( info->instances.n_xmr_settings, sizeof( *xmr_status->status ) ); + + if ( xmr_status->status == NULL ) + { + rc = MBG_ERR_NO_MEM; + goto out; + } + } + + rc = mbg_get_gps_all_xmr_status( dh, xmr_status->status, &info->instances ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + if ( mbg_rc_is_success( chk_dev_xmulti_ref_supp_ext_src_info( info ) ) ) + { + // TODO + // XMR_EXT_SRC_INFO_IDX can not be read out from bus devices, yet + } + +out: + if ( mbg_rc_is_error( rc ) ) + { + free_all_xmulti_ref_status( xmr_status ); + xmr_status = NULL; + } + + *p = xmr_status; + + return rc; + +} // mbg_get_all_xmulti_ref_status + + + +/*HDR*/ +/** + * @brief Read all user capture information and store it into a newly allocated or reused ::ALL_UCAP_INFO + * + * @note ::mbg_chk_dev_has_ucap should be called to check if this API is supported. + * + * The appropriate number of ::TTM structures will be allocated and needs to be freed + * by calling ::free_all_ucap_info. Existing user captures will not be removed, so the + * number of user captures can never decrease. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] p Pointer to a pointer to ::ALL_UCAP_INFO + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_chk_dev_has_ucap + * @see ::free_all_ucap_info + */ +int mbg_get_all_ucap_info( MBG_DEV_HANDLE dh, ALL_UCAP_INFO **p ) +{ + int rc; + ALL_UCAP_INFO *ucap_info = *p; + UCAP_ENTRY *new_entry, *old_entry; + + // if this function is called for the first time, allocate a new ::ALL_UCAP_INFO structure + if ( ucap_info == NULL ) + { + ucap_info = ( ALL_UCAP_INFO* )calloc( 1, sizeof( *ucap_info ) ); + if ( ucap_info == NULL ) + { + *p = NULL; + return MBG_ERR_NO_MEM; + } + mbg_klist_init(&ucap_info->list); + } + + do + { + new_entry = calloc_ucap_entry(); + if ( !new_entry ) + { + rc = MBG_ERR_NO_MEM; + goto err_out; + } + + rc = mbg_get_gps_ucap( dh, &new_entry->ttm ); + if ( mbg_rc_is_error( rc ) ) + goto err_out; + + if ( ( (uint8_t)new_entry->ttm.tm.sec == (uint8_t) 0xFF ) ) + { + free ( new_entry ); + new_entry = NULL; + break; + } + + if ( ucap_info->num_ucaps < MAX_UCAP_ENTRIES ) + { + mbg_klist_append_item(&ucap_info->list, &new_entry->head); + ++ucap_info->num_ucaps; + } + else + { + old_entry = mbg_klist_first_entry(&ucap_info->list, UCAP_ENTRY, head); + mbg_klist_delete_item(&old_entry->head); + free(old_entry); + mbg_klist_append_item(&ucap_info->list, &new_entry->head); + } + + } while (1); + + rc = MBG_SUCCESS; + + goto success_out; + +err_out: + free_all_ucap_info( ucap_info ); + ucap_info = NULL; + if ( new_entry ) + free( new_entry ); + +success_out: + *p = ucap_info; + + return rc; + +} // mbg_get_all_ucap_info + + + +#if 0 && defined( DEBUG ) // ### TODO + +/*HDR*/ +void test_gpio( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, int verbose ) +{ + int b; + int rc; + unsigned int i; + MBG_GPIO_CFG_LIMITS gpio_cfg_limits = { 0 }; + ALL_GPIO_INFO_IDX all_gpio_info_idx = { { 0 } }; + ALL_GPIO_STATUS_IDX all_gpio_status_idx = { { 0 } }; + + rc = mbg_chk_dev_has_gpio( dh ); + + printf( "\nGPIO chk supp: %i\n", rc ); + + rc = mbg_dev_has_gpio( dh, &b ); + + if ( rc != MBG_SUCCESS || !b ) + { + printf( "GPIO not supported, rc: %i, b: %i\n", rc, b ); + return; + } + + printf( "GPIO supported, rc: %i, b: %i\n", rc, b ); + + printf( "\nChecking GPIO:\n" ); + + rc = mbg_get_gpio_cfg_limits( dh, &gpio_cfg_limits ); + + if ( rc != MBG_SUCCESS ) + { + printf( "Failed to read GPIO limits, rc: %i\n", rc ); + return; + } + + printf( "Number of GPIO ports: %i\n", gpio_cfg_limits.num_io ); + + rc = mbg_get_gps_all_gpio_info( dh, all_gpio_info_idx, &gpio_cfg_limits ); + + if ( rc != MBG_SUCCESS ) + printf( "Failed to read all GPIO info, rc: %i\n", rc ); + + if ( !( gpio_cfg_limits.flags & MBG_GPIO_CFG_LIMIT_FLAG_MASK_STATUS_SUPP ) ) + printf( "GPIO status not supported (flag not set).\n" ); + else + { + rc = mbg_get_gps_all_gpio_status( dh, all_gpio_status_idx, &gpio_cfg_limits ); + + if ( rc != MBG_SUCCESS ) + printf( "Failed to read all GPIO status, rc: %i\n", rc ); + } + + + for ( i = 0; i < gpio_cfg_limits.num_io; i++ ) + { + MBG_GPIO_INFO *p_i = &all_gpio_info_idx[i].info; + MBG_GPIO_STATUS *p_st = &all_gpio_status_idx[i].status; + int gpio_type = p_i->settings.type; + + printf( "GPIO %i: type 0x%02X (%s)", i, + gpio_type, _get_gpio_type_name( gpio_type ) ); + + switch ( gpio_type ) + { + case MBG_GPIO_TYPE_FREQ_IN: // variable frequency input, freq == 0 if input not used + { + MBG_GPIO_FREQ_IN_SETTINGS *p = &p_i->settings.u.freq_in; +#if 0 + MBG_GPIO_FREQ freq; ///< frequency in range ::MBG_GPIO_FREQ_IN_SUPP::freq_min..::MBG_GPIO_FREQ_IN_SUPP::freq_max, or 0 if input is not used + uint32_t csc_limit; ///< max. cycle slip [1/1000 cycle units], see ::MBG_GPIO_FREQ_IN_SUPP::csc_limit_max + uint32_t shape; ///< selected signal shape, see ::MBG_GPIO_SIGNAL_SHAPES + uint32_t reserved; ///< reserved, currently always 0 + uint32_t flags; ///< reserved, currently always 0 +#endif + + } break; + + case MBG_GPIO_TYPE_FREQ_OUT: // variable frequency output + { + MBG_GPIO_FREQ_OUT_SETTINGS *p = &p_i->settings.u.freq_out; + + printf( " %lu.%lu Hz %s, phase %li.%03li deg", + (ulong) p->freq.hz, (ulong) p->freq.frac, + _get_gpio_signal_shape_name( p->shape ), + (long) p->milli_phase / 1000, + labs( (long) p->milli_phase % 1000 ) ); + + } break; + + case MBG_GPIO_TYPE_FIXED_FREQ_OUT: // fixed frequency output + { + MBG_GPIO_FIXED_FREQ_OUT_SETTINGS *p = &p_i->settings.u.ff_out; + +#if 0 +typedef struct +{ + uint32_t freq_idx; ///< fixed frequency index, see ::MBG_GPIO_FIXED_FREQS + uint32_t shape; ///< selected signal shape, see ::MBG_GPIO_SIGNAL_SHAPES + uint32_t reserved; ///< reserved, currently always 0 + uint32_t flags; ///< reserved, currently always 0 + +} MBG_GPIO_FIXED_FREQ_OUT_SETTINGS; +#endif + + printf( " %s %s", _get_gpio_fixed_freq_str( p->freq_idx ), + _get_gpio_signal_shape_name( p->shape ) ); + + } break; + + case MBG_GPIO_TYPE_BITS_IN: // framed data stream input + break; + + case MBG_GPIO_TYPE_BITS_OUT: // framed data stream output + break; + } + + printf( ", status 0x%02X (%s)", + p_st->port_state, _get_gpio_port_state_name( p_st->port_state ) ); + + printf( "\n" ); + } + +#if 0 + rc = mbg_set_gps_gpio_settings_idx( dh, MBG_GPIO_SETTINGS_IDX *p ) +#endif + +} // test_gpio + + + +/*HDR*/ +void test_xmr( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, int verbose ) +{ + static const char *multi_ref_names[N_MULTI_REF] = DEFAULT_MULTI_REF_NAMES; + + XMULTI_REF_INSTANCES xmr_instances = { 0 }; + ALL_XMULTI_REF_INFO_IDX all_xmulti_ref_info_idx = { { 0 } }; + ALL_XMULTI_REF_STATUS_IDX all_xmulti_ref_status_idx = { { 0 } }; + XMR_HOLDOVER_STATUS xmr_holdover_status; + + int b; + int rc; + int i; + + rc = mbg_chk_dev_has_xmr( dh ); + + printf( "\nXMR chk supp: %i\n", rc ); + + rc = mbg_dev_has_xmr( dh, &b ); + + if ( rc != MBG_SUCCESS || !b ) + { + printf( "XMR not supported, rc: %i, b: %i\n", rc, b ); + return; + } + + printf( "XMR supported, rc: %i, b: %i\n", rc, b ); + + printf( "\nChecking XMR:\n" ); + + rc = mbg_get_xmr_instances( dh, &xmr_instances ); + + if ( rc != MBG_SUCCESS ) + { + printf( "*** Failed to read XMR instances, rc: %i\n", rc ); + return; + } + + printf( "Slot %u, supp. XMR instances/priority levels: %u, flags: 0x%08lX\n", + xmr_instances.slot_id, xmr_instances.n_xmr_settings, + (ulong) xmr_instances.flags ); + + if ( verbose ) + { +// XMRIF_MSK_MRF_NONE_SUPP = ( 1UL << XMRIF_BIT_MRF_NONE_SUPP ), ///< see ::XMRIF_BIT_MRF_NONE_SUPP +//##++++++++++++++++++++ XMRIF_MSK_HOLDOVER_STATUS_SUPP = ( 1UL << XMRIF_BIT_HOLDOVER_STATUS_SUPP ) ///< see ::XMRIF_BIT_HOLDOVER_STATUS_SUPP + } + + + for ( i = 0; i < MAX_N_MULTI_REF_TYPES; i++ ) + { + int n_inst = xmr_instances.n_inst[i]; + + if ( i < N_MULTI_REF ) // a known signal type + { + if ( verbose ) + { + if ( n_inst ) + printf( "%u %s input%s supported\n", n_inst, + multi_ref_names[i], ( n_inst == 1 ) ? "" : "s" ); + else + if ( verbose > 1 ) + printf( "No %s input supported\n", multi_ref_names[i] ); + } + + continue; + } + + // If execution gets here then the signal type is unknown. + // Print a warning if the device supports instances of this signal type. + if ( n_inst ) + printf( "*** Warning: %u instances of unknown signal type idx %u supported!\n", + n_inst, i ); + } + + rc = mbg_get_gps_all_xmr_info( dh, all_xmulti_ref_info_idx, &xmr_instances ); + + if ( rc != MBG_SUCCESS ) + printf( "*** Failed to read all XMR info, rc: %i\n", rc ); + + rc = mbg_get_gps_all_xmr_status( dh, all_xmulti_ref_status_idx, &xmr_instances ); + + if ( rc != MBG_SUCCESS ) + printf( "*** Failed to read all XMR status, rc: %i\n", rc ); + + for ( i = 0; i < xmr_instances.n_xmr_settings; i++ ) + { + XMULTI_REF_INFO *p = &all_xmulti_ref_info_idx[i].info; + + printf( "XMR %i: %li\n", i, + (long) p->settings.bias.secs ); + +#if 0 + XMULTI_REF_SETTINGS_IDX xmrsi; + xmrsi.settings = p->settings; + xmrsi.settings.precision.nano_secs = i + 40; + xmrsi.settings.bias.secs = 0xA55ACDEF; + xmrsi.settings.bias.nano_secs = 0x12345678; + xmrsi.idx = i; + + rc = mbg_set_gps_xmr_settings_idx( dh, &xmrsi ); + + if ( rc != MBG_SUCCESS ) + printf( "Failed to write XMR settings %i, rc: %i\n", i, rc ); +#endif + } + + if ( !( xmr_instances.flags & XMRIF_MSK_HOLDOVER_STATUS_SUPP ) ) + printf( "*** Warning: XMR holdover status not supported!\n" ); + else + { + rc = mbg_get_xmr_holdover_status( dh, &xmr_holdover_status, &xmr_instances ); + + if ( rc != MBG_SUCCESS ) + printf( "*** Failed to read XMR holdover status, rc: %i\n", rc ); + else + { + printf( "XMR mode: %s, %s%s, %s%s, %s%s\n", + _get_xmr_holdover_status_mode_name( xmr_holdover_status.mode ), + ( xmr_holdover_status.flags & XMR_HLDOVR_MSK_IN_HOLDOVER ) ? "" : str_not_spc, "in holdover", + ( xmr_holdover_status.flags & XMR_HLDOVR_MSK_TRANSITION_ENBD ) ? "" : str_not_spc, "transition enabled", + ( xmr_holdover_status.flags & XMR_HLDOVR_MSK_IN_TRANSITION ) ? "" : str_not_spc, "in transition" + ); + +//##+++++ print_xmr_prio( xmr_holdover_status.curr_prio, "Current", +#if 0 +typedef struct +{ + uint8_t mode; ///< XMR/holdover mode, see ::XMR_HOLDOVER_STATUS_MODES + int8_t curr_prio; ///< current priority level, 0..::XMULTI_REF_INSTANCES::n_xmr_settings, or ::XMR_PRIO_LVL_UNSPEC + int8_t nxt_prio; ///< next priority level after holdover, 0..::XMULTI_REF_INSTANCES::n_xmr_settings, or ::XMR_PRIO_LVL_UNSPEC + uint8_t remote_watchdog; ///< counts down in ::XMR_HLDOVR_PRE_AUTONOMOUS mode + uint32_t reserved; ///< reserved, don't use, currently 0 + XMR_HOLDOVER_INTV elapsed; ///< elapsed time in holdover mode, only valid if ::XMR_HLDOVR_MSK_IN_HOLDOVER is set + XMR_HOLDOVER_INTV interval; ///< current holdover interval, only valid if ::XMR_HLDOVR_MSK_IN_HOLDOVER is set + uint32_t flags; ///< holdover status flags, see ::XMR_HOLDOVER_STATUS_FLAG_MASKS + +} XMR_HOLDOVER_STATUS; +#endif + + } + } + +} // test_xmr + +#endif // defined DEBUG + + + +static const int pcps_to_mbg_framing_tbl[N_PCPS_FR_DCF] = +{ + MBG_FRAMING_8N1, + MBG_FRAMING_7E2, + MBG_FRAMING_8N2, + MBG_FRAMING_8E1 +}; + + + +/*HDR*/ +void port_info_from_pcps_serial( + PORT_INFO_IDX *p_pii, + PCPS_SERIAL pcps_serial, + uint32_t supp_baud_rates +) +{ + PCPS_SER_PACK ser_pack; + PORT_INFO *p_pi; + PORT_SETTINGS *p_ps; + + ser_pack.pack = pcps_serial; + pcps_unpack_serial( &ser_pack ); + + p_pi = &p_pii[0].port_info; + p_ps = &p_pi->port_settings; + + p_ps->parm.baud_rate = mbg_baud_rate[ser_pack.baud]; + + strncpy_safe( p_ps->parm.framing, //### TODO + mbg_framing_str[pcps_to_mbg_framing_tbl[ser_pack.frame]], + sizeof( p_ps->parm.framing ) ); + + p_ps->parm.handshake = HS_NONE; + + p_ps->str_type = 0; + p_ps->mode = ser_pack.mode; + + p_pi->supp_baud_rates = supp_baud_rates; + p_pi->supp_framings = DEFAULT_FRAMINGS_DCF; + p_pi->supp_str_types = DEFAULT_SUPP_STR_TYPES_DCF; + +} // port_info_from_pcps_serial + + +/*HDR*/ +void pcps_serial_from_port_info( + PCPS_SERIAL *p, + const PORT_INFO_IDX *p_pii +) +{ + PCPS_SER_PACK ser_pack; + const PORT_INFO *p_pi = &p_pii[0].port_info; + const PORT_SETTINGS *p_ps = &p_pi->port_settings; + int framing_idx = get_framing_idx( p_ps->parm.framing ); + int i; + + + ser_pack.baud = get_baud_rate_idx( p_ps->parm.baud_rate ); + + // Translate the common framing index to the corresponding + // number used with the old PCPS_SERIAL parameter. + // This should always return a valid result since the + // framing index is expected to be selected from + // supported framings. + for ( i = 0; i < N_PCPS_FR_DCF; i++ ) + if ( pcps_to_mbg_framing_tbl[i] == framing_idx ) + break; + + ser_pack.frame = i; + + ser_pack.mode = p_ps->mode; + + pcps_pack_serial( &ser_pack ); + + *p = ser_pack.pack; + +} // pcps_serial_from_port_info + + + +/*-------------------------------------------------------------- + * Name: pcps_unpack_serial() + * + * Purpose: Unpack a structure with serial port parameters + * + * Input/Output: p address of a structure holding both the + * packed and unpacked information + * + * Ret value: -- + *-------------------------------------------------------------*/ + +/*HDR*/ +void pcps_unpack_serial( PCPS_SER_PACK *p ) +{ + uint8_t pack = p->pack; + + p->baud = (uint8_t) ( pack & BITMASK( PCPS_BD_BITS ) ); + p->frame = (uint8_t) ( ( pack >> PCPS_FR_SHIFT ) & BITMASK( PCPS_FR_BITS ) ); + p->mode = (uint8_t) ( ( pack >> PCPS_MOD_SHIFT ) & BITMASK( PCPS_MOD_BITS ) ); + +} // pcps_unpack_serial + + + +/*-------------------------------------------------------------- + * Name: pcps_pack_serial() + * + * Purpose: Pack a structure with serial port parameters + * + * Input/Output: p address of a structure holding both the + * packed and unpacked information + * + * Ret value: -- + *-------------------------------------------------------------*/ + +/*HDR*/ +void pcps_pack_serial( PCPS_SER_PACK *p ) +{ + p->pack = (uint8_t) ( ( p->baud & BITMASK( PCPS_BD_BITS ) ) + | ( ( p->frame & BITMASK( PCPS_FR_BITS ) ) << PCPS_FR_SHIFT ) + | ( ( p->mode & BITMASK( PCPS_MOD_BITS ) ) << PCPS_MOD_SHIFT ) ); + +} /* pcps_pack_serial */ + + + +/*-------------------------------------------------------------- + * Name: pcps_str_to_port() + * + * Purpose: Try to convert a string to a valid port + * address. + * + * Input: s the string + * + * Output: -- + * + * Ret value: a valid port number or 0 + *+-------------------------------------------------------------*/ + +/*HDR*/ +void pcps_setup_isa_ports( char *s, + int *port_vals, + int n_vals ) +{ + ushort i; + + + for ( i = 0; i < n_vals; i++ ) + { + if ( *s == 0 ) + break; + + *port_vals++ = (uint16_t) strtoul( s, &s, 16 ); + + if ( *s == ',' ) + s++; + } + +} // pcps_setup_isa_ports + + + +/*HDR*/ +const char *setup_device_type_name( char *s, size_t max_len, MBG_DEV_HANDLE dh, + const RECEIVER_INFO *p_ri ) +{ + size_t n = sn_cpy_str_safe( s, max_len, p_ri->model_name ); + + if ( mbg_rc_is_success( mbg_chk_dev_has_asic_version( dh ) ) ) + { + PCI_ASIC_VERSION asic_version; + + if ( mbg_rc_is_success( mbg_get_asic_version( dh, &asic_version ) ) ) + n += snprintf_safe( &s[n], max_len - n, " (PCI ASIC v%i.%02i)", + _convert_asic_version_number( asic_version ) >> 8, + _convert_asic_version_number( asic_version ) & 0xFF ); + } + + return s; + +} // setup_device_type_name + + + +/*HDR*/ +const char *setup_asic_features( char *s, size_t max_len, MBG_DEV_HANDLE dh ) +{ + size_t n = 0; + + if ( mbg_rc_is_success( mbg_chk_dev_has_asic_features( dh ) ) ) + { + PCI_ASIC_FEATURES asic_features; + + if ( mbg_rc_is_success( mbg_get_asic_features( dh, &asic_features ) ) ) + { + if ( asic_features & PCI_ASIC_HAS_MM_IO ) + n += sn_cpy_str_safe( &s[n], max_len - n, "Memory Mapped I/O" ); + + //### if ( asic_features & PCI_ASIC_HAS_PGMB_IRQ ) + // (implement this as loop) + } + } + + if ( n == 0 ) // nothing else printed + sn_cpy_str_safe( s, max_len, str_not_avail ); + + return s; + +} // setup_asic_features + + diff --git a/src/external/bsd/meinberg/dist/mbglib/common/deviohlp.h b/src/external/bsd/meinberg/dist/mbglib/common/deviohlp.h new file mode 100755 index 0000000..f06b72a --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/deviohlp.h @@ -0,0 +1,415 @@ + +/************************************************************************** + * + * $Id: deviohlp.h 1.4 2017/07/05 13:50:18 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for deviohlp.c. + * + * ----------------------------------------------------------------------- + * $Log: deviohlp.h $ + * Revision 1.4 2017/07/05 13:50:18 martin + * Moved definition of PCPS_SER_PACK here. + * Defined function type MBG_ERR_MSG_FNC. + * New structure PCPS_TIME_EXT. + * New inline function pcps_time_is_valid(). + * Updated function prototypes. + * Revision 1.3 2013/09/26 08:25:18Z martin + * Moved ALL_PTP_CFG_INFO definition to cfg_hlp.h. + * Updated doxygen comments. + * Revision 1.2 2012/10/15 13:51:18Z martin + * Include cfg_hlp.h. + * Added structure ALL_PTP_CFG_INFO. + * Updated function prototypes. + * Revision 1.1 2011/08/03 15:36:44Z martin + * Initial revision with functions moved here from mbgdevio. + * + **************************************************************************/ + +#ifndef _DEVIOHLP_H +#define _DEVIOHLP_H + + +/* Other headers to be included */ + +#include <mbgdevio.h> +#include <cfg_hlp.h> + + +#ifdef _DEVIOHLP + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief A helper structure used with configuration of old DCF77 clocks + * + * @deprecated This structure has been used with some very + * old DCF77 clocks to configure the serial interface. + * It has been deprecated by ::PORT_SETTINGS and ::PORT_INFO. + */ +typedef struct +{ + PCPS_SERIAL pack; ///< This packed byte is read from or written to the board + + uint8_t baud; ///< The unpacked baud rate code, see ::PCPS_BD_CODES + uint8_t frame; ///< The unpacked framing code, see ::PCPS_FR_CODES + uint8_t mode; ///< The unpacked mode code, see ::PCPS_MOD_CODES + +} PCPS_SER_PACK; + + + +typedef int MBG_ERR_MSG_FNC( const PCPS_DEV *p_dev, const char *s ); + + +/** + * @brief An extended time and status structure + * + * This structure provides monitoring and configuration tools + * with a unified structure containing the current time and + * extended status. The structure needs to be set up depending + * on the capabilities of a particular device and the API calls + * which could be used to retrieve the information. + */ +typedef struct +{ + PCPS_TIME t; ///< current date, time, and limited status + uint8_t comp_sig_mode; ///< 0..::N_CONN_SIG_MODES-1, see ::COMP_SIG_MODES + int16_t comp_sig_val; ///< compensated signal value, see @ref PCPS_SIG_VAL_DEFS + int32_t utc_offs; ///< %UTC offset, always expanded to [seconds] + PCPS_TIME_STATUS_X status_x; ///< extended status, see @see @ref PCPS_TIME_STATUS_FLAGS + uint16_t year; ///< full year number + uint32_t flags; ///< see ::PCPS_TIME_EXT_FLAGS + +} PCPS_TIME_EXT; + + + +/** + * @brief Check if a ::PCPS_TIME structure contains valid date and time + * + * @param[in] p The structure to be checked + * + * @return != 0 if date and time valid, else 0 + */ +static __mbg_inline +int pcps_time_is_valid( const PCPS_TIME *p ) +{ + return ( p->sec100 <= 99 ) + && ( p->sec <= 60 ) // allow for leap second + && ( p->min <= 59 ) + && ( p->hour <= 23 ) + && ( p->mday >= 1 ) && ( p->mday <= 31 ) + && ( p->wday >= 1 ) && ( p->wday <= 7 ) + && ( p->month >= 1 ) && ( p->month <= 12 ) + && ( p->year <= 99 ); + +} // pcps_time_is_valid + + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + int chk_feat_supp( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, MBG_CHK_SUPP_FNC *chk_supp_fnc, MBG_ERR_MSG_FNC *err_msg_fnc, const char *not_supp_msg ) ; + /** + * @brief Read or setup all GNSS status information + * + * This function should be called preferably to get a summary of + * the GNSS status from GNSS receivers (GPS, GLONASS, ...). + * + * The function ::mbg_get_device_info must have been called before, and + * the returned ::PCPS_DEV structure has to be passed to this function. + * + * If the device supports this then the low level GNSS API functions + * are called directly to collect the status information. If the device + * doesn't support the GNSS API but is a pure GPS receiver then the GPS + * API functions are called and the GNSS data structures are filled up + * accordingly, so the calling application can always evaluate the + * GNSS data structures in ::ALL_GNSS_INFO. + * + * If neither GPS nor another GNSS system is supported then this function + * returns the ::MBG_ERR_NOT_SUPP_BY_DEV error. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] p_agi Pointer to a ::ALL_GNSS_INFO to be filled + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_get_gps_stat_info + * @see ::mbg_get_gps_gnss_mode_info + * @see ::mbg_get_gps_all_gnss_sat_info + */ + int mbg_chk_get_all_gnss_info( MBG_DEV_HANDLE dh, ALL_GNSS_INFO *p_agi ) ; + + /** + * @brief Read all serial port settings and supported configuration parameters + * + * The functions ::mbg_get_device_info and ::mbg_setup_receiver_info + * must have been called before, and the returned ::PCPS_DEV and + * ::RECEIVER_INFO structures have to be passed to this function. + * + * The complementary function ::mbg_save_serial_settings should be used + * to write the modified serial port configuration back to the board. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[in] *p_dev Pointer to a valid ::PCPS_DEV structure + * @param[out] *p_rpcfg Pointer to a ::RECEIVER_PORT_CFG structure to be filled up + * @param[in] *p_ri Pointer to a valid ::RECEIVER_INFO structure + * + * @return ::MBG_SUCCESS or error code returned by device I/O control function + * + * @see ::mbg_get_device_info + * @see ::mbg_setup_receiver_info + * @see ::mbg_save_serial_settings + */ + int mbg_get_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, RECEIVER_PORT_CFG *p_rpcfg, const RECEIVER_INFO *p_ri ) ; + + /** + * @brief Write the configuration settings for a single serial port to a device + * + * Modifications to the serial port configuration should be made only + * after ::mbg_get_serial_settings had been called to read all serial port + * settings and supported configuration parameters. + * This function has finally to be called once for every serial port + * the configuration of which has been modified. + * + * As also required by ::mbg_get_serial_settings, the functions + * ::mbg_get_device_info and ::mbg_setup_receiver_info must have been + * called before, and the returned ::PCPS_DEV and ::RECEIVER_INFO structures + * vave to be passed to this function. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[in] *p_dev Pointer to a valid ::PCPS_DEV structure + * @param[in] *p_rpcfg Pointer to a valid ::RECEIVER_PORT_CFG structure + * @param[in] port_num Index of the serial port to be saved + * + * @return ::MBG_SUCCESS or error code returned by device I/O control function. + * + * @see ::mbg_get_serial_settings + * @see ::mbg_get_device_info + * @see ::mbg_setup_receiver_info + */ + int mbg_save_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, RECEIVER_PORT_CFG *p_rpcfg, int port_num ) ; + + /** + * @brief Read all network configuration into an ::ALL_NET_CFG_INFO structure + * + * Reads the network configuration of a device via the LAN_IP4 API and + * translates the structures into NET_CFG structures. + * + * As soon as available, this function should make use of the NET_CFG API. + * + * A ::ALL_NET_CFG_INFO and the appropriate number of ::MBG_NET_INTF_LINK_INFO_IDX, + * ::MBG_NET_INTF_ADDR_INFO_IDX, ::MBG_IP_ADDR_IDX, ::MBG_NET_NAME_IDX and + * ::MBG_NET_INTF_ROUTE_INFO_IDX will be allocated and need to be freed later + * by calling ::free_all_net_cfg_info + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] p Pointer to a pointer of ::ALL_NET_CFG_INFO + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_get_lan_if_info + * @see ::mbg_get_ip4_settings + * @see ::free_all_net_cfg_info + */ + int mbg_get_all_net_cfg_info( MBG_DEV_HANDLE dh, ALL_NET_CFG_INFO **p ) ; + + /** + * @brief Write all network settings to a device + * + * The complementary function ::mbg_get_all_net_cfg_info should + * have been used to read the original network settings and + * supported configuration parameters. + * + * The appropriate settings are translated into LAN_IP4 structures + * and send to the device using the appropriate API functions. + * + * As soon as available, this function should make use of the NET_CFG API. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[in] p Pointer to a pointer of ::ALL_NET_CFG_INFO + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_set_ip4_settings + */ + int mbg_save_all_net_cfg_info( MBG_DEV_HANDLE dh, ALL_NET_CFG_INFO *p ) ; + + /** + * @brief Read current network status into an ::ALL_NET_STATUS_INFO structure + * + * Reads the network status of a device via the LAN_IP4 API and + * translates the structures into NET_CFG structures. + * + * As soon as available, this function should make use of the NET_CFG API. + * + * A ::ALL_NET_STATUS_INFO and the appropriate number of ::MBG_NET_INTF_LINK_INFO_IDX, + * ::MBG_NET_INTF_ADDR_INFO_IDX, ::MBG_IP_ADDR_IDX, ::MBG_NET_NAME_IDX and + * ::MBG_NET_INTF_ROUTE_INFO_IDX will be allocated and need to be freed later + * by calling ::free_all_net_status_info + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] p Pointer to a pointer of ::ALL_NET_STATUS_INFO + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_get_lan_if_info + * @see ::mbg_get_ip4_state + * @see ::free_all_net_status_info + */ + int mbg_get_all_net_status_info( MBG_DEV_HANDLE dh, ALL_NET_STATUS_INFO **p ) ; + + /** + * @brief Read all PTP settings and supported configuration parameters + * + * The complementary function ::mbg_save_all_ptp_cfg_info should + * be used to write the modified configuration back to the device. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] *p Pointer to a ::ALL_PTP_CFG_INFO structure to be filled up + * + * @return ::MBG_SUCCESS or error code returned by device I/O control function. + * + * @see ::mbg_save_all_ptp_cfg_info + * @see ::mbg_get_ptp_cfg_info + * @see ::mbg_get_ptp_uc_master_cfg_limits + * @see ::mbg_get_all_ptp_uc_master_info + * @see ::mbg_chk_dev_has_ptp + * @see ::mbg_chk_dev_has_ptp_unicast + */ + int mbg_get_all_ptp_cfg_info( MBG_DEV_HANDLE dh, ALL_PTP_CFG_INFO *p ) ; + + /** + * @brief Write all PTP settings to a device + * + * The complementary function ::mbg_get_all_ptp_cfg_info should + * have been used to read the original PTP settings and supported + * configuration parameters. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[in] *p Pointer to a valid ::ALL_PTP_CFG_INFO structure + * + * @return ::MBG_SUCCESS or error code returned by device I/O control function. + * + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_set_ptp_cfg_settings + * @see ::mbg_set_ptp_uc_master_settings_idx + * @see ::mbg_chk_dev_has_ptp + * @see ::mbg_chk_dev_has_ptp_unicast + */ + int mbg_save_all_ptp_cfg_info( MBG_DEV_HANDLE dh, const ALL_PTP_CFG_INFO *p ) ; + + /** + * @brief Read all XMR info into a newly or re-allocated ::ALL_XMULTI_REF_INFO + * + * @note ::mbg_chk_dev_has_xmr should be called before using this function + * + * A ::ALL_XMULTI_REF_INFO and a number of ::XMULTI_REF_INSTANCES::n_xmr_settings + * of ::XMULTI_REF_INFO_IDX and ::XMR_EXT_SRC_INFO_IDX will be allocated and needs + * to be freed by calling ::free_all_xmulti_ref_info + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] p Pointer to a pointer of ::ALL_XMULTI_REF_INFO + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::free_all_xmulti_ref_info + */ + int mbg_get_all_xmulti_ref_info( MBG_DEV_HANDLE dh, ALL_XMULTI_REF_INFO **p ) ; + + /** + * @brief Set all extended multi ref settings to a device + * + * The complementary function ::mbg_get_all_xmulti_ref_info should + * have been used to read the original extended multi ref info. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] p Pointer to a ::ALL_XMULTI_REF_INFO structure with all settings + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_set_gps_xmr_settings_idx + */ + _NO_MBG_API_ATTR int _MBG_API mbg_save_all_xmulti_ref_info( MBG_DEV_HANDLE dh, ALL_XMULTI_REF_INFO *p ) ; + + /** + * @brief Read all XMR status info into a newly or re-allocated ::ALL_XMULTI_REF_STATUS + * + * @note ::mbg_chk_dev_has_xmr should be called before using this function + * + * A ::ALL_XMULTI_REF_STATUS and a number of ::XMULTI_REF_INSTANCES::n_xmr_settings + * of ::XMULTI_REF_STATUS_IDX will be allocated and needs to be freed by calling + * ::free_all_xmulti_ref_status + * + * @param[in] dh Valid handle to a Meinberg device + * @param[in] info Pointer to the appropriate info structure + * @param[out] p Pointer to a pointer of ::ALL_XMULTI_REF_STATUS + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::free_all_xmulti_ref_status + */ + int mbg_get_all_xmulti_ref_status( MBG_DEV_HANDLE dh, const ALL_XMULTI_REF_INFO *info, ALL_XMULTI_REF_STATUS **p ) ; + + /** + * @brief Read all user capture information and store it into a newly allocated or reused ::ALL_UCAP_INFO + * + * @note ::mbg_chk_dev_has_ucap should be called to check if this API is supported. + * + * The appropriate number of ::TTM structures will be allocated and needs to be freed + * by calling ::free_all_ucap_info. Existing user captures will not be removed, so the + * number of user captures can never decrease. + * + * @param[in] dh Valid handle to a Meinberg device + * @param[out] p Pointer to a pointer to ::ALL_UCAP_INFO + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_chk_dev_has_ucap + * @see ::free_all_ucap_info + */ + int mbg_get_all_ucap_info( MBG_DEV_HANDLE dh, ALL_UCAP_INFO **p ) ; + + void test_gpio( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, int verbose ) ; + void test_xmr( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, int verbose ) ; + void port_info_from_pcps_serial( PORT_INFO_IDX *p_pii, PCPS_SERIAL pcps_serial, uint32_t supp_baud_rates ) ; + void pcps_serial_from_port_info( PCPS_SERIAL *p, const PORT_INFO_IDX *p_pii ) ; + void pcps_unpack_serial( PCPS_SER_PACK *p ) ; + void pcps_pack_serial( PCPS_SER_PACK *p ) ; + void pcps_setup_isa_ports( char *s, int *port_vals, int n_vals ) ; + const char *setup_device_type_name( char *s, size_t max_len, MBG_DEV_HANDLE dh, const RECEIVER_INFO *p_ri ) ; + const char *setup_asic_features( char *s, size_t max_len, MBG_DEV_HANDLE dh ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _DEVIOHLP_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/gpsdefs.h b/src/external/bsd/meinberg/dist/mbglib/common/gpsdefs.h index b638657..32194a6 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/gpsdefs.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/gpsdefs.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: gpsdefs.h 1.91.1.24 2011/07/08 09:04:05 martin TRASH $ + * $Id: gpsdefs.h 1.125 2017/07/05 18:18:27 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -13,57 +13,255 @@ * * ----------------------------------------------------------------------- * $Log: gpsdefs.h $ - * Revision 1.91.1.24 2011/07/08 09:04:05 martin - * Renamed some PTP stuff. - * Added some definitions for PTP. - * Revision 1.91.1.23 2011/06/29 10:49:47 martin + * Revision 1.125 2017/07/05 18:18:27 martin + * New models GPS_MODEL_CTC100, GPS_MODEL_TCR180, + * GPS_MODEL_LUE180, GPS_MODEL_CPC_01, GPS_MODEL_TSU_01, + * GPS_MODEL_CMC_01, GPS_MODEL_SCU_01, GPS_MODEL_FCU_01, + * GPS_MODEL_CSM100, GPS_MODEL_LNE180SFP, GPS_MODEL_GTS180, + * GPS_MODEL_GPS180CSM, GPS_MODEL_GRC181, GPS_MODEL_N2X180, + * GPS_MODEL_GNS181PEX, GPS_MODEL_MDU180, GPS_MODEL_MDU312, + * GPS_MODEL_GPS165, GPS_MODEL_GNS181_UC, GPS_MODEL_PSX_4GE, + * GPS_MODEL_RSC180RDU, GPS_MODEL_USYNCPWR, GPS_MODEL_FDM180M, + * GPS_MODEL_LSG180, GPS_MODEL_GPS190, GPS_MODEL_GNS181 and + * associated definitions. + * New GPS_BUILTIN_FEATURE_BITS and associated definitions. + * New macros _setup_default_receiver_info_dcf() and + * _setup_default_receiver_info_gps() as well as associated + * definitions which can be used to set up a RECEIVER_INFO + * structure for legacy devices which don't provide it. + * New Receiver_INO feature bit GPS_FEAT_XFEATURE which + * indicates that a new, extended feature set is supported. + * Defined a new st of extended features (MBG_XFEATURE_BITS) + * and associated definitions. + * Moved definitions for NANO_TIME and NANO_TIME_64 to words.h. + * New IRIG TX codes ICODE_TX_A006_A136, ICODE_TX_A007_A137, + * and associated definitions. + * Renamed ICODE_RX_G142_G146 to ICODE_RX_G142, and + * ICODE_RX_G002_G006 to ICODE_RX_G002. + * New IRIG RX codes ICODE_RX_A136_A137, ICODE_RX_A006_A007, + * ICODE_RX_G146, ICODE_RX_G006, and associated definitions. + * New union POUT_DATA union used for varying configuration + * data in POUT_SETTINGS, depending on the output mode. + * New POUT_MODES POUT_PTTI_PPS, POUT_HAVEQUICK, and + * associated definitions. + * Definitions to support a configurable pulse shift + * of some programmable output signals. + * New multiref source MULTI_REF_SYNCE and associated + * definitions. + * Added a number of swab..() macros that were still missing. + * XMR statistics, XMR_QL and some other XMR stuff by andre. + * New GPIO types including video modes, and associated stuff. + * Renamed some structure fields and added some definitions + * related to FDM. + * Added some SCU_STAT_MASKS. + * New GNSS_TYPE_QZSS, and modified MBG_GNSS_MODE_INFO. + * New flag MBG_GNSS_FLAG_HAS_SV_STATUS, structure + * GNSS_SV_STATUS and associated definitions. + * A bunch of new structures and definitions for network + * configuration. + * Many new structures and definitions for NTP configuration. + * New structures and associated definitions used to send + * user capture events over the network (ext_ucap). + * New PTP_ROLES and associated stuff. + * Changed one of PTP_STATE's reserved fields to tsu_secs. + * Changed PTP_ANN_RCPT_TIMEOUT_MAX from 255 to 8. + * New PTP_CFG_FLAGS, PTP_OPT_EXTS flags, PTP_PRESETS_MASKS + * and associated definitions. + * Definitions for PTPv1 and v2 data sets, and PTP statistics. + * Preliminary definitions to support SMPTE and SDH. + * Definition for XBP addressing of devices. + * Definitions to support TLVs. + * Added LED and LNE API definitions. + * MBG_EXT_SYS_INFO_BITS and associated definitions for an + * extended sysinfo API. + * MBG_CLK_RES_INFO and associated stuff for clock resolution + * info. + * Definitions for configuration transaction handling. + * Definitions for a higher level I/O port API. + * Definitions for monitoring / notification. + * Definitions for USB locking. + * Preliminary licensing stuff. + * Defined macros in a safer way. + * Revision 1.124 2015/07/14 14:22:46 martin + * Doxygen fix. + * Revision 1.123 2015/07/06 13:00:10 martin + * Added definitions for VSG180, MSF180, WWVB180, and CPC180. + * Added definitions for PZF180. + * Definitions for SDI and MDU300 added by stephan. + * Definitions for HPS100 added by daniel. + * FDM180 and associated definitions added by paul. + * Started to support eXtended Binary Protocol (XBP). + * Merged daniel and gregoire's changes from the 1.120.2.x branch. + * Defines for IPv6 multicast scopes added by gregoire. + * XMR_EXT_SRC_INFO and associated XMR_SETTINGS_FLAG_MSKS flags + * defined by andre. + * Support XMULTI_REF_INFO::n_prio field again. + * Fixed _mbg_swab_gpio_cfg_limits() macro. + * Added MBG_NET_LINK_OPT_MASK_CAN_SYNCE to MBG_NET_LINK_OPT_MASKS. + * New PTP_ROLE_MASKS PTP_ROLE_NTP_SERVER and PTP_ROLE_NTP_CLIENT. + * Some PTP profile extensions added by daniel. + * Added missing defines for SPT. + * Added definitions for REL1000. + * Moved structure NANO_TIME_64 here. + * Revision 1.122 2014/07/29 08:57:44Z martin + * Updated doxygen comments. + * Revision 1.121 2014/07/17 09:41:50 martin + * Introduced XMR_HOLDOVER_STATUS, MBG_GPIO_STATUS, + * and associated definitions. + * Huge update and cleanup on doxygen comments. + * Revision 1.120 2014/05/27 08:34:40 martin + * Fixed braces in some _mbg_rcvr_is_..() macros. + * Definitions used with extended network cfg, VST, and SHS. + * Introduced XMR_HOLDOVER_STATUS. + * Introduced programmable output mode POUT_GPIO. + * Introduced oscillator type OCXO_SQ. + * Defined some new baud rates. + * Defines for IEEE C37.118.1-2011 CTQ. + * Support for new model SCG by paul. + * Support new model PPG180. + * New SCU control masks. + * New GNSS flag MBG_GNSS_FLAG_SAT_INFO_IDX_SUPP_SER. + * DEFAULT_MULTI_REF_NAMES_SHORT added by udo. + * Definitions used for NTP configuration by thomas-b and marvin. + * MBG_NET_ADDR structures changed to MBG_IP_ADDR, and + * associated symbols defined by marvin. + * Huge rework of comments in doxygen format. + * Revision 1.119 2013/12/05 10:13:13 daniel + * Support new PTP_CFG_FLAGS for 1-step-L2 and 1-step-P2P support + * Revision 1.118 2013/11/19 13:38:35 martin + * Added LAN_IF_TYPE_RSC. + * Revision 1.117 2013/11/18 14:13:39 martin + * Support model LNE_GB. + * Revision 1.116 2013/11/11 09:46:11 martin + * New PTP configuration flags PTP_CFG_SUPP_MCAST_SLAVE_FLAG and + * PTP_CFG_CAN_BE_MULTICAST_SLAVE, plus associated bit masks. + * New XMR_INST_FLAGS and XMR_INST_FLAG_MASKS defined by andre. + * Fixes for big-endian targets. + * Updated doxygen comments. + * Revision 1.115 2013/10/02 15:19:28 martin + * Changed PTP_CFG_SETTINGS::vlan_cfg back to a reserved field, + * and removed associated flag and flag mask. + * Revision 1.114 2013/09/25 11:02:10 martin + * Support models MRI, BPE, GLN180PEX, N2X, RSC180. + * Added feature bit GPS_FEAT_NTP. + * Enhanced VLAN configuration structures. + * Started to support IPv6. + * Renamed PTP_CFG_SETTINGS field "profile" to "selected_presets". + * Renamed PTP_CFG_INFO field "supp_profiles" to "supp_opt_ext". + * New PTP role PTP_ROLE_BOTH_MASTER. + * New PTP flag PTP_FLAG_ONE_STEP. + * Added some new PTP_CFG_FLAGS flags. + * Added PTP_OPT_EXTS and associated definitions. + * Added PTP_PRESETS and associated definitions. + * Added "tzdl" field to PTP_POWER_PROFILE_CFG. + * Made reserved PTP_CFG_SETTINGS field to "opt_ext" field. + * Made reserved PTP_CFG_SETTINGS field to "vlan_cfg" field. + * Made reserved PTP_STATE field to "parent_clock_class" and "parent_clock_accuracy". + * Definitions for MULTI_REF_EXT_OSC added by Andre. + * String initializers for supported HaveQuick formats added by Gregoire. + * Lots of doxygen changes. + * Revision 1.113 2013/04/04 09:02:01Z martin + * Added definitions to support HaveQuick. + * Fixed a typo. + * Revision 1.112 2013/02/19 15:39:13 martin + * New PTP settings field ann_rcpt_timeout and associated + * values PTP_ANN_RCPT_TIMEOUT_LIMITS. + * Changed many defines to named enums to simplify references + * with doxygen. + * Updated doxygen comments. + * Revision 1.111 2013/02/01 15:37:36 martin + * Added and modified a huge number of doxygen comments. + * Revision 1.110 2013/01/16 15:23:25 martin + * Fixed 2 comments which were interchanged. + * Revision 1.109 2013/01/11 10:39:34 martin + * Added definitions for IMS. + * Support XMR_HOLDOVER_INTV. + * New XMRS status bit XMRS_BIT_LOW_JITTER / XMRS_MSK_LOW_JITTER. + * Added framing type 8E2, though most UARTs don't support this. + * Added enum names and updated comments for doxygen. + * Revision 1.108 2012/10/30 11:31:16 martin + * Defined PTP_UC_MSG_DURATION_MIN and PTP_UC_MSG_DURATION_MAX. + * Fixed some doxygen comments. + * Changes by andre: changed reserved field to ssm and boc in BITS_OUT settings. + * Revision 1.107 2012/10/12 07:40:12 martin + * New PTP state flags PTP_FLAG_MSK_UTC_VALID and + * PTP_CFG_MSK_SUPP_UTC_VALID. + * Revision 1.106 2012/10/02 18:22:10 martin + * Added default baud rate and framing for binary protocol. + * Added definitions for IRIG codes E002/E112 and NASA36. + * Reworked GPIO structures. + * Added definitions for GRC, LIU, DCF600RS, and DCF600HS. + * New flag POUT_FIXED_PULSE_LEN. + * New flag POUT_NOT_INVERTIBLE. + * Unified capitalization in MBG_XMRS_STATUS_STRS. + * Revision 1.105 2012/06/01 16:31:16 martin + * Some TIME_SLOT definitions added by marvin. + * Moved some PTP configuration defaults and limits to ptpdflts.h. + * Revision 1.104 2012/04/11 16:02:55Z martin + * Fixed some doxygen comments. + * Revision 1.103 2012/04/02 11:08:57Z martin + * Extended description of GPS UTC/leap second data. + * Revision 1.102 2012/03/16 11:43:31 martin + * Fixed a potential compiler warning. + * Revision 1.101 2012/03/06 16:56:01Z martin + * Added support for PTP multicast auto role. + * Merged Daniel's definitions for PTP profile support. + * Support time slot mode for programmable pulse outputs. + * Support LNO180. + * Moved definition of MBG_MAC_ADDR here. + * Use MBG_MAC_ADDR in definition of LAN_IF_INFO. + * Revision 1.100 2012/01/17 13:33:55 martin + * Added new IRIG RX delay compensation code groups for G0xx and G1xx codes. + * As a consequence the value of N_IRIG_RX_COMP has changed. + * Added definition of IRIG_RX_COMP_MAX. + * Updated IRIG code classification macros. + * Removed obsolete/unused definition of CAL_REC_INFO. + * Added some comments. + * Revision 1.99 2011/12/09 09:22:03 martin + * Fixed a typo. + * Revision 1.98 2011/11/25 14:58:34 martin + * Renamed some evt_log definitions. + * Revision 1.97 2011/11/25 10:11:17 martin + * Initializers for XMRS status bit strings added by gregoire. + * New feature GPS_FEAT_EVT_LOG. + * Added definitions used with event logs. + * Moved cal_reg and gen_io stuff here. + * Added macro _mbg_swab_debug_status(). * Updated some comments. - * Revision 1.91.1.22 2011/06/29 09:07:50 martin - * Renamed PZF600PEX to PZF180PEX. - * Added MGR180, MSF600, WWVB600, and JJY600. - * Revision 1.91.1.21 2011/06/22 08:23:58 andre - * Revision 1.91.1.20 2011/06/21 14:11:31Z martin + * Revision 1.96 2011/10/11 13:40:46Z andre + * changed reserved field into slot_id in XMULTI_REF_INSTANCES + * Revision 1.95.1.1 2011/10/07 09:31:58Z andre + * Revision 1.95 2011/10/04 09:35:41Z martin + * Added support for ESI180. + * Changed RECEIVER_INFO::flags bit GPS_10MHZ_DISBD to a RECEIVER_INFO::features bit. + * Support MULTI_REF_INTERNAL, MULTI_REF_LWR and MULTI_REF_PZF. + * Added MBG_GPIO_BITS structure and associated definitions. + * Revision 1.94 2011/08/25 07:42:43Z martin + * Fixed a bug in macro _mbg_swab_pout_settings() where the 16 bit timeout + * field was swapped using a macro for 32 bit types. + * Use shorter names for some PTP unicast master default values. + * Revision 1.93 2011/08/10 08:19:38Z martin + * New PORT_INFO and PORT_SETTINGS flag PORT_FLAG_PORT_INVISIBLE. + * Revision 1.92 2011/07/29 09:49:35 martin + * Support PZF180PEX, MGR180, MSF600, WWVB600, JJY600, + * GPS180HS, and GPS180AMC. + * Added receiver info features GPS_FEAT_PTP_UNICAST + * and GPS_FEAT_XMRS_MULT_INSTC. + * Added receiver info flag bit GPS_10MHZ_DISBD. + * Added initializers for PTP timescale names. + * New PTP_STATE flags bit PTP_FLAG_MSK_IS_UNICAST. + * Made unused PTP_STATE fields num_clients and num_masters reserved. + * Account for different PTP roles. + * Added / renamed some definitions for PTP. + * Modified default string for PTP layer 2 protocol. * Support PTP unicast configuration. * Support GPIO configuration. - * Support PZF600PEX. - * Cleaned up handling of pragma pack(). - * Fixed a typo. - * Revision 1.91.1.19 2011/04/18 13:43:57 martin - * Doxygen changes. - * Revision 1.91.1.18 2011/04/18 13:00:33 martin - * Merged some modified comments from an older branch. - * Revision 1.91.1.17 2011/04/13 15:34:07 martin - * Added lots of comments in doxygen style. - * Revision 1.91.1.16 2011/04/11 09:15:00 andre - * Revision 1.91.1.15 2011/04/08 08:29:18Z andre - * Revision 1.91.1.14 2011/04/08 08:10:31Z martin - * Renamed .._INST_.. to .._INSTC_.. + * Introduced XMULTI_REF_INSTANCES. * Moved flags XMRS_..._IS_EXTERNAL and XMRS_..._INSTC_EXCEEDED * to definitions for XMULTI_REF_STATUS::status. - * Revision 1.91.1.13 2011/04/07 15:50:16 martin - * Introduced XMULTI_REF_INSTANCES: - * Converted some comments to Doxygen style. - * Revision 1.91.1.12 2011/04/07 13:52:04 martin - * Revision 1.91.1.11 2011/04/07 13:23:41 martin - * Started to add GPIO support and configuration stuff. - * Revision 1.91.1.10 2011/04/07 10:38:43 martin - * Modified default string for PTP layer 2 protocol. - * Revision 1.91.1.9 2011/04/07 10:29:36 martin - * Added initializers for PTP timescale names. - * Revision 1.91.1.8 2011/02/23 15:11:23 martin - * New PTP_STATE flags bit PTP_FLAG_MSK_IS_UNICAST. - * Revision 1.91.1.7 2011/02/23 15:05:54 martin - * Made unused PTP_STATE fields num_clients and num_masters reserved. - * Revision 1.91.1.6 2011/02/23 14:47:22 martin + * Some comments added, updated, and converted to doxygen style. + * Cleaned up handling of pragma pack(). * Removed trailing whitespace and hard tabs. - * Revision 1.91.1.5 2011/02/23 13:17:06 daniel - * Revision 1.91.1.4 2011/02/17 14:39:13Z daniel - * Account for different PTP roles. - * Revision 1.91.1.3 2011/02/15 14:24:53 martin - * Revision 1.91.1.2 2011/02/15 11:30:56 martin - * New feature GPS_FEAT_PTP_UNICAST. - * Revision 1.91.1.1 2011/02/15 10:54:28 daniel - * Started to support configuration for PTP unicast. * Revision 1.91 2011/01/31 11:23:56Z martin * Added model type name definitions for GPS180PEX and TCR180PEX. * Introduced synthesizer mode for programmable outputs. @@ -89,7 +287,7 @@ * Added support for new model GLN170. * Revision 1.87 2010/03/10 11:29:37Z martin * Added definitions for GPS180. - * Added multiref source 1 PPS plus associated string. + * Added multi ref source 1 PPS plus associated string. * Revision 1.86 2010/02/17 14:16:42 martin * Added definitions for PZF600 and TCR600. * Revision 1.85 2010/02/15 11:34:36 martin @@ -159,7 +357,7 @@ * Added definitions for PTP270PEX and FRC511PEX. * Revision 1.67 2008/07/17 08:54:52Z martin * Added macros to convert the endianess of structures. - * Added multiref fixed frequency source. + * Added multi ref fixed frequency source. * Revision 1.66 2008/05/19 14:49:07 daniel * Renamed s_addr to start_addr in FPGA_INFO. * Revision 1.65 2008/05/19 09:00:01Z martin @@ -181,7 +379,7 @@ * Added definitions to support GPS170PEX. * Revision 1.60 2007/09/13 12:37:35Z martin * Modified and added initializers for TZDL. - * Added multiref source PTP over E1. + * Added multi ref source PTP over E1. * Added codes for MSF511 and GRC170 devices. * Modified XMULTI_REF_SETTINGS and XMULTI_REF_STATUS structures. * Avoid inclusion of other Meinberg headers in non-Meinberg projects. @@ -234,7 +432,7 @@ * Added ROM_CSUM, RCV_TIMEOUT, and IGNORE_LOCK types. * Revision 1.44 2006/05/18 09:34:41Z martin * Added definitions for POUT max. pulse_len and max timeout. - * Changed comment for POUT_SETTINGS::timeout: + * Changed comment for POUT_SETTINGS::timeout. * Units are minutes, not seconds. * Added definition for MAX_POUT_TIME_STR_PORTS. * Added definitions for POUT mode 10MHz. @@ -307,7 +505,7 @@ * Revision 1.20 2003/04/03 11:03:44Z martin * Extended definitions for IRIG support. * Revision 1.19 2003/01/31 13:38:20 MARTIN - * Modified type of RECEIVER_INFO.fixed_freq field. + * Modified type of RECEIVER_INFO::fixed_freq field. * Revision 1.18 2002/10/28 09:24:07 MARTIN * Added/renamed some POUT related symbols. * Revision 1.17 2002/09/05 10:58:39 MARTIN @@ -379,6 +577,7 @@ #endif + /* Start of header body */ #if defined( _USE_PACK ) @@ -387,12 +586,36 @@ #endif + /* "magic" number */ #define MEINBERG_MAGIC 0x6AAC -#define MIN_SVNO 1 /* min. SV number */ -#define MAX_SVNO 32 /* max. SV number */ -#define N_SVNO ( MAX_SVNO - MIN_SVNO + 1) /* number of possibly active SVs */ +/** + * @brief GNSS satellite numbers + * + * @todo: Check if MAX_SVNO_GLN is 94 instead of 95, and thus + * N_SVNO_GLN is 30 instead of 31, as reported by Wikipedia. + */ +enum GNSS_SVNOS +{ + MIN_SVNO_GPS = 1, ///< min. GPS satellite PRN number + MAX_SVNO_GPS = 32, ///< max. GPS satellite PRN number + N_SVNO_GPS = 32, ///< max. number of active GPS satellites + + MIN_SVNO_WAAS = 33, ///< min. WAAS satellite number + MAX_SVNO_WAAS = 64, ///< max. WAAS satellite number + N_SVNO_WAAS = 32, ///< max. number of active WAAS satellites + + MIN_SVNO_GLONASS = 65, ///< min. Glonass satellite number (64 + sat slot ID) + MAX_SVNO_GLONASS = 95, ///< max. Glonass satellite number (64 + sat slot ID) + N_SVNO_GLONASS = 31 ///< max. number of active Glonass satellites +}; + +// for compatibility with GPS-only software: +#define MIN_SVNO MIN_SVNO_GPS ///< min. SV number +#define MAX_SVNO MAX_SVNO_GPS ///< max. SV number +#define N_SVNO N_SVNO_GPS ///< number of possibly active SVs + #define GPS_ID_STR_LEN 16 @@ -402,41 +625,42 @@ #define GPS_EPLD_STR_SIZE ( GPS_EPLD_STR_LEN + 1 ) -#define DEFAULT_GPS_TICKS_PER_SEC 10000000L /* system time base */ +#define DEFAULT_GPS_TICKS_PER_SEC 10000000L ///< system time base, see ::GPS_TICKS_PER_SEC #if !defined( GPS_TICKS_PER_SEC ) /* * The actual ticks per seconds may vary for different * GPS receiver models. If this is the case, the receiver - * model support the RECEIVER_INFO structure which contains + * model support the ::RECEIVER_INFO structure which contains * the actual value. */ - #define GPS_TICKS_PER_SEC DEFAULT_GPS_TICKS_PER_SEC + #define GPS_TICKS_PER_SEC DEFAULT_GPS_TICKS_PER_SEC ///< see ::DEFAULT_GPS_TICKS_PER_SEC + #endif -typedef uint16_t SVNO; /* the number of a SV */ -typedef uint16_t HEALTH; /* a SV's health code */ -typedef uint16_t CFG; /* a SV's configuration code */ -typedef uint16_t IOD; /* Issue-Of-Data code */ +typedef uint16_t SVNO; ///< the number of an SV (Space Vehicle, i.e. satellite) +typedef uint16_t HEALTH; ///< an SV's 6 bit health code +typedef uint16_t CFG; ///< an SV's 4 bit configuration code +typedef uint16_t IOD; ///< Issue-Of-Data code /* the type of various checksums */ #ifndef _CSUM_DEFINED - typedef uint16_t CSUM; + typedef uint16_t CSUM; ///< checksum used by some structures stored in non-volatile memory #define _CSUM_DEFINED - - #define _mbg_swab_csum( _p ) _mbg_swab16( _p ) #endif +#define _mbg_swab_csum( _p ) _mbg_swab16( _p ) + + /** * @brief The type of a GPS command code * - * These command codes can be passed via - * @ref gps_cmds_serial "serial port" (see @file gpsserio.h), or - * @ref gps_cmds_bus "system bus" (see @file pcpsdefs.h). + * @see ::GPS_CMD_CODES + * @see ::PC_GPS_CMD_CODES */ typedef uint16_t GPS_CMD; @@ -448,23 +672,27 @@ typedef uint16_t GPS_CMD; * * Contains a software revision code, plus an optional * identifier for a customized version. + * + * @see @ref group_ext_sys_info */ typedef struct { - uint16_t code; /**< Version number, e.g. 0x0120 means v1.20 */ - char name[GPS_ID_STR_SIZE]; /**< Optional string identifying a customized version */ - uint8_t reserved; /**< Reserved field to yield even structure size */ + uint16_t code; ///< Version number, e.g. 0x0120 means v1.20 + char name[GPS_ID_STR_SIZE]; ///< Optional string identifying a customized firmware version, should be empty in standard versions + uint8_t reserved; ///< Reserved field to yield even structure size + } SW_REV; #define _mbg_swab_sw_rev( _p ) \ +do \ { \ _mbg_swab16( &(_p)->code ); \ -} +} while ( 0 ) /** - * @defgroup group_bvar_stat BVAR_STAT status of buffered GPS data + * @defgroup group_bvar_stat Status of buffered (non-volatile) data * * Status word, associated bit numbers and bit masks indicating * whether certain data from the GPS satellites are @@ -476,93 +704,141 @@ typedef struct * @{ */ /** - * @brief Status flags of battery buffered data received - * from GPS satellites. + * @brief Status flags of battery buffered data + * + * Related to data received from the satellites, or data derived thereof. * * All '0' means OK, single bits set to '1' indicate * the associated type of GPS data is not available. + * + * @see ::BVAR_FLAGS */ typedef uint16_t BVAR_STAT; #define _mbg_swab_bvar_stat( _p ) _mbg_swab16( (_p) ) -/** @brief Enumeration of bits used with BVAR_STAT */ -enum +/** + * @brief Enumeration of flag bits used to define ::BVAR_FLAGS + * + * For each bit which is set this means the associated data set in + * non-volatile memory is not available, or incomplete. + * Most data sets will just be re-collected from the data streams sent + * by the satellites. However, the receiver position has usually been + * computed earlier during normal operation, and will be re-computed + * when a sufficient number of satellites can be received. + * + * @see ::BVAR_STAT + * @see ::BVAR_FLAGS + * @see ::BVAR_FLAG_NAMES + */ +enum BVAR_FLAG_BITS { - BVAR_BIT_CFGH_INVALID, - BVAR_BIT_ALM_NOT_COMPLETE, - BVAR_BIT_UTC_INVALID, - BVAR_BIT_IONO_INVALID, - BVAR_BIT_RCVR_POS_INVALID, - N_BVAR_BIT /**< @brief number of defined ::BVAR_STAT bits */ + BVAR_BIT_CFGH_INVALID, ///< Satellite configuration and health parameters incomplete + BVAR_BIT_ALM_NOT_COMPLETE, ///< Almanac parameters incomplete + BVAR_BIT_UTC_INVALID, ///< %UTC offset parameters incomplete + BVAR_BIT_IONO_INVALID, ///< Ionospheric correction parameters incomplete + BVAR_BIT_RCVR_POS_INVALID, ///< No valid receiver position available + N_BVAR_BIT ///< number of defined ::BVAR_STAT bits }; -#define BVAR_CFGH_INVALID ( 1UL << BVAR_BIT_CFGH_INVALID ) /**< @brief Configuration and health data (::CFGH) not valid */ -#define BVAR_ALM_NOT_COMPLETE ( 1UL << BVAR_BIT_ALM_NOT_COMPLETE ) /**< @brief Almanach data (::ALM) not complete */ -#define BVAR_UTC_INVALID ( 1UL << BVAR_BIT_UTC_INVALID ) /**< @brief UTC data not valid */ -#define BVAR_IONO_INVALID ( 1UL << BVAR_BIT_IONO_INVALID ) /**< @brief Ionospheric correction data (::IONO) not valid */ -#define BVAR_RCVR_POS_INVALID ( 1UL << BVAR_BIT_RCVR_POS_INVALID ) /**< @brief Receiver position (::POS) not valid */ - -#define BVAR_MASK ( ( 1UL << N_BVAR_BIT ) - 1 ) /**< @brief Bit mask for all defined bits */ -/** @} group_bvar_stat */ +/** + * @brief Bit masks associated with ::BVAR_FLAG_BITS + * + * Used with ::BVAR_STAT. + * + * @see ::BVAR_STAT + * @see ::BVAR_FLAG_BITS + * @see ::BVAR_FLAG_NAMES + */ +enum BVAR_FLAGS +{ + BVAR_CFGH_INVALID = ( 1UL << BVAR_BIT_CFGH_INVALID ), ///< see ::BVAR_BIT_CFGH_INVALID + BVAR_ALM_NOT_COMPLETE = ( 1UL << BVAR_BIT_ALM_NOT_COMPLETE ), ///< see ::BVAR_BIT_ALM_NOT_COMPLETE + BVAR_UTC_INVALID = ( 1UL << BVAR_BIT_UTC_INVALID ), ///< see ::BVAR_BIT_UTC_INVALID + BVAR_IONO_INVALID = ( 1UL << BVAR_BIT_IONO_INVALID ), ///< see ::BVAR_BIT_IONO_INVALID + BVAR_RCVR_POS_INVALID = ( 1UL << BVAR_BIT_RCVR_POS_INVALID ), ///< see ::BVAR_BIT_RCVR_POS_INVALID +}; +#define BVAR_MASK ( ( 1UL << N_BVAR_BIT ) - 1 ) ///< Bit mask for all defined bits /** - A structure used to hold a fixed frequency value. - frequ[kHz] = khz_val * 10^range -*/ + * @brief String initializer for ::BVAR_STAT flag names + * + * @see ::BVAR_STAT + * @see ::BVAR_FLAG_BITS + * @see ::BVAR_FLAGS + */ +#define BVAR_FLAG_NAMES \ +{ \ + "Sat. config and health", \ + "Almanac", \ + "UTC offset", \ + "Ionospheric correction", \ + "Receiver position" \ +} +/** @} defgroup group_bvar_stat */ + + + +/** + * @brief A structure used to hold a fixed frequency value + * + * @note frequ[kHz] = khz_val * 10^range + */ typedef struct { - uint16_t khz_val; /* the base frequency in [kHz] */ - int16_t range; /* an optional base 10 exponent */ + uint16_t khz_val; ///< the base frequency in [kHz] + int16_t range; ///< an optional base 10 exponent + } FIXED_FREQ_INFO; #define _mbg_swab_fixed_freq_info( _p ) \ +do \ { \ _mbg_swab16( &(_p)->khz_val ); \ _mbg_swab16( &(_p)->range ); \ -} +} while ( 0 ) + +/** + * @brief A data type to specify feature flags within ::RECEIVER_INFO + */ +typedef uint32_t RI_FEATURES; ///< see @ref GPS_FEATURE_MASKS -typedef uint32_t RI_FEATURES; // type of RECEIVER_INFO::features field -/* - * The following code defines features and properties - * of the various GPS receivers. Older GPS receivers - * may require a recent firmvare version to support - * this, or may not support this at all. - */ - -/** - * The structure is ordered in a way that all fields - * except chars or arrays of chars are word-aligned. - */ -typedef struct -{ - uint16_t model_code; /**< identifier for receiver model */ - SW_REV sw_rev; /**< software revision and ID */ - char model_name[GPS_ID_STR_SIZE]; /**< ASCIIZ, name of receiver model */ - char sernum[GPS_ID_STR_SIZE]; /**< ASCIIZ, serial number */ - char epld_name[GPS_EPLD_STR_SIZE]; /**< ASCIIZ, file name of EPLD image */ - uint8_t n_channels; /**< number of sats to be tracked simultaneously */ - uint32_t ticks_per_sec; /**< resolution of fractions of seconds */ - RI_FEATURES features; /**< optional features, see below */ - FIXED_FREQ_INFO fixed_freq; /**< optional non-standard fixed frequency */ - uint8_t osc_type; /**< type of installed oscillator, see below */ - uint8_t osc_flags; /**< oscillator flags, see below */ - uint8_t n_ucaps; /**< number of user time capture inputs */ - uint8_t n_com_ports; /**< number of on-board serial ports */ - uint8_t n_str_type; /**< max num of string types supported by any port */ - uint8_t n_prg_out; /**< number of programmable pulse outputs */ - uint16_t flags; /**< additional information, see below */ +/** + * @brief A structure used to identify a device type and supported features + * + * @note This may not be supported by some very old devices. + */ +typedef struct +{ + uint16_t model_code; ///< identifier for receiver model, see ::GPS_MODEL_CODES + SW_REV sw_rev; ///< software revision and ID + char model_name[GPS_ID_STR_SIZE]; ///< ASCIIZ, name of receiver model + char sernum[GPS_ID_STR_SIZE]; ///< ASCIIZ, serial number + char epld_name[GPS_EPLD_STR_SIZE]; ///< ASCIIZ, file name of EPLD image (optional) + uint8_t n_channels; ///< number of satellites which can be tracked simultaneously + uint32_t ticks_per_sec; ///< resolution of fractions of seconds, see ::GPS_TICKS_PER_SEC + RI_FEATURES features; ///< optional features, see @ref GPS_FEATURE_MASKS + FIXED_FREQ_INFO fixed_freq; ///< optional non-standard fixed frequency, may be 0 if not supported + uint8_t osc_type; ///< type of installed oscillator, see ::GPS_OSC_TYPES + uint8_t osc_flags; ///< oscillator flags, actually not used and always 0 + uint8_t n_ucaps; ///< number of user time capture inputs + uint8_t n_com_ports; ///< number of on-board serial ports + uint8_t n_str_type; ///< max num of string types supported by any port + uint8_t n_prg_out; ///< number of programmable pulse outputs + uint16_t flags; ///< additional information, see ::RECEIVER_INFO_FLAG_MASKS + } RECEIVER_INFO; #define _mbg_swab_receiver_info( _p ) \ +do \ { \ _mbg_swab16( &(_p)->model_code ); \ _mbg_swab_sw_rev( &(_p)->sw_rev ); \ @@ -570,13 +846,16 @@ typedef struct _mbg_swab32( &(_p)->features ); \ _mbg_swab_fixed_freq_info( &(_p)->fixed_freq ); \ _mbg_swab16( &(_p)->flags ); \ -} +} while ( 0 ) /** - * Valid codes for RECEIVER_INFO.model_code: + * @brief Known device ID codes for ::RECEIVER_INFO::model_code + * + * @see @ref GPS_MODEL_NAMES + * @see ::DEFAULT_GPS_MODEL_NAMES */ -enum +enum GPS_MODEL_CODES { GPS_MODEL_UNKNOWN, GPS_MODEL_GPS166, @@ -617,21 +896,82 @@ enum GPS_MODEL_MSF600, GPS_MODEL_WWVB600, GPS_MODEL_JJY600, + GPS_MODEL_GPS180HS, + GPS_MODEL_GPS180AMC, + GPS_MODEL_ESI180, + GPS_MODEL_CPE180, + GPS_MODEL_LNO180, + GPS_MODEL_GRC180, + GPS_MODEL_LIU, + GPS_MODEL_DCF600HS, + GPS_MODEL_DCF600RS, + GPS_MODEL_MRI, + GPS_MODEL_BPE, + GPS_MODEL_GLN180PEX, + GPS_MODEL_N2X, + GPS_MODEL_RSC180, + GPS_MODEL_LNE_GB, + GPS_MODEL_PPG180, + GPS_MODEL_SCG, + GPS_MODEL_MDU300, + GPS_MODEL_SDI, + GPS_MODEL_FDM180, + GPS_MODEL_SPT, + GPS_MODEL_PZF180, + GPS_MODEL_REL1000, + GPS_MODEL_HPS100, + GPS_MODEL_VSG180, + GPS_MODEL_MSF180, + GPS_MODEL_WWVB180, + GPS_MODEL_CPC180, + GPS_MODEL_CTC100, + GPS_MODEL_TCR180, + GPS_MODEL_LUE180, + GPS_MODEL_CPC_01, + GPS_MODEL_TSU_01, + GPS_MODEL_CMC_01, + GPS_MODEL_SCU_01, + GPS_MODEL_FCU_01, + GPS_MODEL_CSM100, + GPS_MODEL_LNE180SFP, + GPS_MODEL_GTS180, + GPS_MODEL_GPS180CSM, + GPS_MODEL_GRC181, + GPS_MODEL_N2X180, + GPS_MODEL_GNS181PEX, + GPS_MODEL_MDU180, + GPS_MODEL_MDU312, + GPS_MODEL_GPS165, + GPS_MODEL_GNS181_UC, + GPS_MODEL_PSX_4GE, + GPS_MODEL_RSC180RDU, + GPS_MODEL_USYNCPWR, + GPS_MODEL_FDM180M, + GPS_MODEL_LSG180, // Line Signal Generator + GPS_MODEL_GPS190, + GPS_MODEL_GNS181, N_GPS_MODEL /* If new model codes are added then care must be taken - * to update the associated string initializers below - * accordingly, and to check whether the classification macros - * also cover the new model names. */ + * to update the associated string initializers GPS_MODEL_NAMES + * and GPS_MODEL_NAME_TABLE accordingly, and to check whether + * the classification macros also cover the new model names. + */ }; +/** + * @brief Model name strings used with Meinberg devices + * + * String initializers for each of the device models + * enumerated in ::GPS_MODEL_CODES. + * + * @see ::GPS_MODEL_CODES + * @see ::DEFAULT_GPS_MODEL_NAMES + * + * @anchor GPS_MODEL_NAMES @{ */ -/* - * String initializers for each of the GPS - * receiver models enum'ed above: - */ -#define GPS_MODEL_NAME_UNKNOWN "(unknown)" +#define GPS_MODEL_NAME_UNKNOWN "Unknown" #define GPS_MODEL_NAME_GPS166 "GPS166" #define GPS_MODEL_NAME_GPS167 "GPS167" #define GPS_MODEL_NAME_GPS167SV "GPS167SV" @@ -670,13 +1010,76 @@ enum #define GPS_MODEL_NAME_MSF600 "MSF600" #define GPS_MODEL_NAME_WWVB600 "WWVB600" #define GPS_MODEL_NAME_JJY600 "JJY600" +#define GPS_MODEL_NAME_GPS180HS "GPS180HS" +#define GPS_MODEL_NAME_GPS180AMC "GPS180AMC" +#define GPS_MODEL_NAME_ESI180 "ESI180" +#define GPS_MODEL_NAME_CPE180 "CPE180" +#define GPS_MODEL_NAME_LNO180 "LNO180" +#define GPS_MODEL_NAME_GRC180 "GRC180" +#define GPS_MODEL_NAME_LIU "LIU" +#define GPS_MODEL_NAME_DCF600HS "DCF600HS" +#define GPS_MODEL_NAME_DCF600RS "DCF600RS" +#define GPS_MODEL_NAME_MRI "MRI" +#define GPS_MODEL_NAME_BPE "BPE" +#define GPS_MODEL_NAME_GLN180PEX "GLN180PEX" +#define GPS_MODEL_NAME_N2X "N2X" +#define GPS_MODEL_NAME_RSC180 "RSC180" +#define GPS_MODEL_NAME_LNE_GB "LNE_GB" +#define GPS_MODEL_NAME_PPG180 "PPG180" +#define GPS_MODEL_NAME_SCG "SCG" +#define GPS_MODEL_NAME_MDU300 "MDU300" +#define GPS_MODEL_NAME_SDI "SDI" +#define GPS_MODEL_NAME_FDM180 "FDM180" +#define GPS_MODEL_NAME_SPT "SPT" +#define GPS_MODEL_NAME_PZF180 "PZF180" +#define GPS_MODEL_NAME_REL1000 "REL1000" +#define GPS_MODEL_NAME_HPS100 "HPS100" +#define GPS_MODEL_NAME_VSG180 "VSG180" +#define GPS_MODEL_NAME_MSF180 "MSF180" +#define GPS_MODEL_NAME_WWVB180 "WWVB180" +#define GPS_MODEL_NAME_CPC180 "CPC180" +#define GPS_MODEL_NAME_CTC100 "CTC100" +#define GPS_MODEL_NAME_TCR180 "TCR180" +#define GPS_MODEL_NAME_LUE180 "LUE180" +#define GPS_MODEL_NAME_CPC_01 "CPC_01" +#define GPS_MODEL_NAME_TSU_01 "TSU_01" +#define GPS_MODEL_NAME_CMC_01 "CMC_01" +#define GPS_MODEL_NAME_SCU_01 "SCU_01" +#define GPS_MODEL_NAME_FCU_01 "FCU_01" +#define GPS_MODEL_NAME_CSM100 "CSM100" +#define GPS_MODEL_NAME_LNE180SFP "LNE180SFP" +#define GPS_MODEL_NAME_GTS180 "GTS180" +#define GPS_MODEL_NAME_GPS180CSM "GPS180CSM" +#define GPS_MODEL_NAME_GRC181 "GRC181" +#define GPS_MODEL_NAME_N2X180 "N2X180" +#define GPS_MODEL_NAME_GNS181PEX "GNS181PEX" +#define GPS_MODEL_NAME_MDU180 "MDU180" +#define GPS_MODEL_NAME_MDU312 "MDU312" +#define GPS_MODEL_NAME_GPS165 "GPS165" +#define GPS_MODEL_NAME_GNS181_UC "GNS181_UC" +#define GPS_MODEL_NAME_PSX_4GE "PSX_4GE" +#define GPS_MODEL_NAME_RSC180RDU "RSC180RDU" +#define GPS_MODEL_NAME_USYNCPWR "MICROSYNC-PWR" +#define GPS_MODEL_NAME_FDM180M "FDM180M" +#define GPS_MODEL_NAME_LSG180 "LSG180" +#define GPS_MODEL_NAME_GPS190 "GPS190" +#define GPS_MODEL_NAME_GNS181 "GNS181" + +/** @} anchor GPS_MODEL_NAMES */ -/* - * The definition below can be used to initialize - * an array of N_GPS_MODEL type name strings. - * Including the trailing 0, each name must not - * exceed GPS_ID_STR_SIZE chars. + +/** + * @brief An initializer for a table of device names + * + * Can be used to initialize an array of ::N_GPS_MODEL + * type name strings. + * + * @note Including the trailing 0, each name must not + * exceed ::GPS_ID_STR_SIZE chars. + * + * @see ::GPS_MODEL_CODES + * @see @ref GPS_MODEL_NAMES */ #define DEFAULT_GPS_MODEL_NAMES \ { \ @@ -718,9 +1121,778 @@ enum GPS_MODEL_NAME_MGR180, \ GPS_MODEL_NAME_MSF600, \ GPS_MODEL_NAME_WWVB600, \ - GPS_MODEL_NAME_JJY600 \ + GPS_MODEL_NAME_JJY600, \ + GPS_MODEL_NAME_GPS180HS, \ + GPS_MODEL_NAME_GPS180AMC, \ + GPS_MODEL_NAME_ESI180, \ + GPS_MODEL_NAME_CPE180, \ + GPS_MODEL_NAME_LNO180, \ + GPS_MODEL_NAME_GRC180, \ + GPS_MODEL_NAME_LIU, \ + GPS_MODEL_NAME_DCF600HS, \ + GPS_MODEL_NAME_DCF600RS, \ + GPS_MODEL_NAME_MRI, \ + GPS_MODEL_NAME_BPE, \ + GPS_MODEL_NAME_GLN180PEX, \ + GPS_MODEL_NAME_N2X, \ + GPS_MODEL_NAME_RSC180, \ + GPS_MODEL_NAME_LNE_GB, \ + GPS_MODEL_NAME_PPG180, \ + GPS_MODEL_NAME_SCG, \ + GPS_MODEL_NAME_MDU300, \ + GPS_MODEL_NAME_SDI, \ + GPS_MODEL_NAME_FDM180, \ + GPS_MODEL_NAME_SPT, \ + GPS_MODEL_NAME_PZF180, \ + GPS_MODEL_NAME_REL1000, \ + GPS_MODEL_NAME_HPS100, \ + GPS_MODEL_NAME_VSG180, \ + GPS_MODEL_NAME_MSF180, \ + GPS_MODEL_NAME_WWVB180, \ + GPS_MODEL_NAME_CPC180, \ + GPS_MODEL_NAME_CTC100, \ + GPS_MODEL_NAME_TCR180, \ + GPS_MODEL_NAME_LUE180, \ + GPS_MODEL_NAME_CPC_01, \ + GPS_MODEL_NAME_TSU_01, \ + GPS_MODEL_NAME_CMC_01, \ + GPS_MODEL_NAME_SCU_01, \ + GPS_MODEL_NAME_FCU_01, \ + GPS_MODEL_NAME_CSM100, \ + GPS_MODEL_NAME_LNE180SFP, \ + GPS_MODEL_NAME_GTS180, \ + GPS_MODEL_NAME_GPS180CSM, \ + GPS_MODEL_NAME_GRC181, \ + GPS_MODEL_NAME_N2X180, \ + GPS_MODEL_NAME_GNS181PEX, \ + GPS_MODEL_NAME_MDU180, \ + GPS_MODEL_NAME_MDU312, \ + GPS_MODEL_NAME_GPS165, \ + GPS_MODEL_NAME_GNS181_UC, \ + GPS_MODEL_NAME_PSX_4GE, \ + GPS_MODEL_NAME_RSC180RDU, \ + GPS_MODEL_NAME_USYNCPWR, \ + GPS_MODEL_NAME_FDM180M, \ + GPS_MODEL_NAME_LSG180, \ + GPS_MODEL_NAME_GPS190, \ + GPS_MODEL_NAME_GNS181 \ +} + + + + +/** + * @brief Definitions used to classify devices and built-in features + * + * @see ::GPS_MODEL_CODES + * @see ::GPS_BUILTIN_FEATURE_BITS + * @see @ref GPS_BUILTIN_FEATURE_MASKS + * + * @anchor GPS_BUILTIN_FEATURE_DEFS @{ */ + + +/** + * @brief A data type to hold a mask of @ref GPS_BUILTIN_FEATURE_MASKS + * + * @see @ref GPS_BUILTIN_FEATURE_MASKS + */ +typedef uint32_t BUILTIN_FEATURE_MASK; + + +/** + * @brief Enumeration of classifiers and built-in features + * + * @see ::GPS_MODEL_CODES + * @see @ref GPS_BUILTIN_FEATURE_MASKS + */ +enum GPS_BUILTIN_FEATURE_BITS +{ + GPS_BIT_MODEL_IS_GPS, + GPS_BIT_MODEL_IS_GNSS, + GPS_BIT_MODEL_IS_TCR, + GPS_BIT_MODEL_IS_DCF_AM, + GPS_BIT_MODEL_IS_DCF_PZF, + GPS_BIT_MODEL_IS_MSF, + GPS_BIT_MODEL_IS_JJY, + GPS_BIT_MODEL_IS_WWVB, + + GPS_BIT_MODEL_IS_BUS_LVL_DEV, + GPS_BIT_MODEL_HAS_BVAR_STAT, + GPS_BIT_MODEL_HAS_POS_XYZ, + GPS_BIT_MODEL_HAS_POS_LLA, + GPS_BIT_MODEL_HAS_TIME_TTM, + GPS_BIT_MODEL_HAS_TZDL, + GPS_BIT_MODEL_HAS_TZCODE, + GPS_BIT_MODEL_HAS_ANT_INFO, + + GPS_BIT_MODEL_HAS_ENABLE_FLAGS, + GPS_BIT_MODEL_HAS_STAT_INFO, + GPS_BIT_MODEL_HAS_ANT_CABLE_LEN, + GPS_BIT_MODEL_HAS_SCU_STAT, + GPS_BIT_MODEL_HAS_SV_INFO, + + GPS_BIT_MODEL_HAS_XMR_HOLDOVER_INTV, + +#if 0 //### TODO This has to be discussed + GPS_BIT_MODEL_IS_LNO, + GPS_BIT_MODEL_IS_SCU, +#endif + + N_GPS_BUILTIN_FEATURE_BITS +}; + + + +/** + * @brief Bit masks associated with classifiers and built-in features + * + * @see ::GPS_MODEL_CODES + * @see ::GPS_BUILTIN_FEATURE_BITS + * + * @anchor GPS_BUILTIN_FEATURE_MASKS @{ */ + +#define GPS_MODEL_IS_GPS ( 1UL << GPS_BIT_MODEL_IS_GPS ) ///< see ::GPS_BIT_MODEL_IS_GPS +#define GPS_MODEL_IS_GNSS ( 1UL << GPS_BIT_MODEL_IS_GNSS ) ///< see ::GPS_BIT_MODEL_IS_GNSS +#define GPS_MODEL_IS_TCR ( 1UL << GPS_BIT_MODEL_IS_TCR ) ///< see ::GPS_BIT_MODEL_IS_TCR +#define GPS_MODEL_IS_DCF_AM ( 1UL << GPS_BIT_MODEL_IS_DCF_AM ) ///< see ::GPS_BIT_MODEL_IS_DCF_AM +#define GPS_MODEL_IS_DCF_PZF ( 1UL << GPS_BIT_MODEL_IS_DCF_PZF ) ///< see ::GPS_BIT_MODEL_IS_DCF_PZF +#define GPS_MODEL_IS_MSF ( 1UL << GPS_BIT_MODEL_IS_MSF ) ///< see ::GPS_BIT_MODEL_IS_MSF +#define GPS_MODEL_IS_JJY ( 1UL << GPS_BIT_MODEL_IS_JJY ) ///< see ::GPS_BIT_MODEL_IS_JJY +#define GPS_MODEL_IS_WWVB ( 1UL << GPS_BIT_MODEL_IS_WWVB ) ///< see ::GPS_BIT_MODEL_IS_WWVB + +#define GPS_MODEL_IS_BUS_LVL_DEV ( 1UL << GPS_BIT_MODEL_IS_BUS_LVL_DEV ) ///< see ::GPS_BIT_MODEL_IS_BUS_LVL_DEV +#define GPS_MODEL_HAS_BVAR_STAT ( 1UL << GPS_BIT_MODEL_HAS_BVAR_STAT ) ///< see ::GPS_BIT_MODEL_HAS_BVAR_STAT +#define GPS_MODEL_HAS_POS_XYZ ( 1UL << GPS_BIT_MODEL_HAS_POS_XYZ ) ///< see ::GPS_BIT_MODEL_HAS_POS_XYZ +#define GPS_MODEL_HAS_POS_LLA ( 1UL << GPS_BIT_MODEL_HAS_POS_LLA ) ///< see ::GPS_BIT_MODEL_HAS_POS_LLA +#define GPS_MODEL_HAS_TIME_TTM ( 1UL << GPS_BIT_MODEL_HAS_TIME_TTM ) ///< see ::GPS_BIT_MODEL_HAS_TIME_TTM +#define GPS_MODEL_HAS_TZDL ( 1UL << GPS_BIT_MODEL_HAS_TZDL ) ///< see ::GPS_BIT_MODEL_HAS_TZDL +#define GPS_MODEL_HAS_TZCODE ( 1UL << GPS_BIT_MODEL_HAS_TZCODE ) ///< see ::GPS_BIT_MODEL_HAS_TZCODE +#define GPS_MODEL_HAS_ANT_INFO ( 1UL << GPS_BIT_MODEL_HAS_ANT_INFO ) ///< see ::GPS_BIT_MODEL_HAS_ANT_INFO + +#define GPS_MODEL_HAS_ENABLE_FLAGS ( 1UL << GPS_BIT_MODEL_HAS_ENABLE_FLAGS ) ///< see ::GPS_BIT_MODEL_HAS_ENABLE_FLAGS +#define GPS_MODEL_HAS_STAT_INFO ( 1UL << GPS_BIT_MODEL_HAS_STAT_INFO ) ///< see ::GPS_BIT_MODEL_HAS_STAT_INFO +#define GPS_MODEL_HAS_ANT_CABLE_LEN ( 1UL << GPS_BIT_MODEL_HAS_ANT_CABLE_LEN ) ///< see ::GPS_BIT_MODEL_HAS_ANT_CABLE_LEN +#define GPS_MODEL_HAS_SCU_STAT ( 1UL << GPS_BIT_MODEL_HAS_SCU_STAT ) ///< see ::GPS_BIT_MODEL_HAS_SCU_STAT +#define GPS_MODEL_HAS_SV_INFO ( 1UL << GPS_BIT_MODEL_HAS_SV_INFO ) ///< see ::GPS_BIT_MODEL_HAS_SV_INFO + +#if 0 // ### TODO This has to be discussed + #define GPS_MODEL_IS_LNO ( 1UL << GPS_BIT_MODEL_IS_LNO ) ///< see ::GPS_BIT_MODEL_IS_LNO + #define GPS_MODEL_IS_SCU ( 1UL << GPS_BIT_MODEL_IS_SCU ) ///< see ::GPS_BIT_MODEL_IS_SCU +#endif + +// ### TODO do we need the next one? +#define GPS_MODEL_HAS_XMR_HOLDOVER_INTV ( 1UL << GPS_BIT_MODEL_HAS_XMR_HOLDOVER_INTV ) ///< see ::GPS_BIT_MODEL_HAS_XMR_HOLDOVER_INTV + +//### TODO: should we use an extra flag? +#define GPS_MODEL_HAS_POS ( GPS_MODEL_HAS_POS_XYZ | GPS_MODEL_HAS_POS_LLA ) + +/** @} anchor GPS_BUILTIN_FEATURE_MASKS */ + + +#if 0 //##++ more potential builtin features and classifiers + + GPS_MODEL_HAS_CFGH | \ + GPS_MODEL_HAS_ALM | \ + GPS_MODEL_HAS_EPH | \ + GPS_MODEL_HAS_UTC | \ + GPS_MODEL_HAS_IONO \ + +#define GPS_MODEL_HAS_AUTO_ON // -- +#define GPS_MODEL_HAS_AUTO_OFF // -- +#define GPS_MODEL_HAS_SW_REV // deprecated, use only if ri not supported +#define GPS_MODEL_HAS_BVAR_STAT // req +#define GPS_MODEL_HAS_POS_XYZ // GPS_MODEL_IS_GPS, GPS_MODEL_HAS_POS, GPS_MODEL_HAS_POS_XYZ ? +#define GPS_MODEL_HAS_POS_LLA // GPS_MODEL_IS_GPS, GPS_MODEL_HAS_POS, GPS_MODEL_HAS_POS_LLA ? +#define GPS_MODEL_HAS_TZDL // req +#define GPS_MODEL_HAS_PORT_PARM // deprecated, use only if ri not supported +#define GPS_MODEL_HAS_SYNTH // ri GPS_HAS_SYNTH +#define GPS_MODEL_HAS_ANT_INFO // GPS_MODEL_IS_GPS, also GNSS, or req? +#define GPS_MODEL_HAS_UCAP // ri n_ucap +#define GPS_MODEL_HAS_ENABLE_FLAGS // req +#define GPS_MODEL_HAS_STAT_INFO // req +#define GPS_MODEL_HAS_SWITCH_PARMS // deprecated, use ... +#define GPS_MODEL_HAS_STRING_PARMS // deprecated, use ... +#define GPS_MODEL_HAS_ANT_CABLE_LEN // GPS_MODEL_IS_GPS, also GNSS, or req? +#define GPS_MODEL_HAS_SYNC_OUTAGE_DELAY // custom +#define GPS_MODEL_HAS_PULSE_INFO // custom +#define GPS_MODEL_HAS_OPT_FEATURES // deprecated, use ri +#define GPS_MODEL_HAS_IRIG_TX_SETTINGS // ri GPS_HAS_IRIG_TX +#define GPS_MODEL_HAS_RECEIVER_INFO // -- +#define GPS_MODEL_HAS_STR_TYPE_INFO_IDX // ri n_str_type +#define GPS_MODEL_HAS_PORT_INFO_IDX // ri n_com +#define GPS_MODEL_HAS_PORT_SETTINGS_IDX // ri n_com +#define GPS_MODEL_HAS_POUT_INFO_IDX // ri n_pout +#define GPS_MODEL_HAS_POUT_SETTINGS_IDX // ri n_pout +#define GPS_MODEL_HAS_IRIG_TX_INFO // ri GPS_HAS_IRIG_TX +#define GPS_MODEL_HAS_MULTI_REF_SETTINGS // ri GPS_HAS_MULTI_REF +#define GPS_MODEL_HAS_MULTI_REF_INFO // ri GPS_HAS_MULTI_REF +#define GPS_MODEL_HAS_ROM_CSUM // ? +#define GPS_MODEL_HAS_MULTI_REF_STATUS // ri ... +#define GPS_MODEL_HAS_RCV_TIMEOUT // ri ... +#define GPS_MODEL_HAS_IRIG_RX_SETTINGS // ri ... +#define GPS_MODEL_HAS_IRIG_RX_INFO // ri ... +#define GPS_MODEL_HAS_REF_OFFS // ri ... +#define GPS_MODEL_HAS_DEBUG_STATUS // +#define GPS_MODEL_HAS_XMR_SETTINGS_IDX // +#define GPS_MODEL_HAS_XMR_INFO_IDX // +#define GPS_MODEL_HAS_XMR_STATUS_IDX // +#define GPS_MODEL_HAS_OPT_SETTINGS // +#define GPS_MODEL_HAS_OPT_INFO // +#define GPS_MODEL_HAS_CLR_UCAP_BUFF // +#define GPS_MODEL_HAS_TIME_SCALE // +#define GPS_MODEL_HAS_NAV_ENG_SETTINGS // +#define GPS_MODEL_HAS_RAW_IRIG_DATA // +#define GPS_MODEL_HAS_GPIO_CFG_LIMITS // +#define GPS_MODEL_HAS_GPIO_INFO_IDX // +#define GPS_MODEL_HAS_GPIO_SETTINGS_IDX // +#define GPS_MODEL_HAS_XMR_INSTANCES // +#define GPS_MODEL_HAS_CLR_EVT_LOG // +#define GPS_MODEL_HAS_NUM_EVT_LOG_ENTRIES // +#define GPS_MODEL_HAS_FIRST_EVT_LOG_ENTRY // +#define GPS_MODEL_HAS_NEXT_EVT_LOG_ENTRY // +#define GPS_MODEL_HAS_LNO_STATUS // +#define GPS_MODEL_HAS_IMS_STATE // +#define GPS_MODEL_HAS_IMS_SENSOR_STATE_IDX // +#define GPS_MODEL_HAS_XMR_HOLDOVER_INTV // +#define GPS_MODEL_HAS_HAVEQUICK_RX_SETTINGS // +#define GPS_MODEL_HAS_HAVEQUICK_RX_INFO // +#define GPS_MODEL_HAS_HAVEQUICK_TX_SETTINGS // +#define GPS_MODEL_HAS_HAVEQUICK_TX_INFO // +#define GPS_MODEL_HAS_PTP_CFG // +#define GPS_MODEL_HAS_PTP_STATE // +#define GPS_MODEL_HAS_PTP_UC_MASTER_CFG_LIMITS // +#define GPS_MODEL_HAS_PTP_UC_MASTER_CFG // +#define GPS_MODEL_HAS_NTP_GLB_CFG // +#define GPS_MODEL_HAS_NTP_CLNT_MODE_CFG // +#define GPS_MODEL_HAS_NTP_SRV_MODE_CFG // +#define GPS_MODEL_HAS_NTP_PEER_SETTINGS_IDX // +#define GPS_MODEL_HAS_NTP_SYS_STATE // +#define GPS_MODEL_HAS_NTP_PEER_STATE_IDX // +#define GPS_MODEL_HAS_SHS // +#define GPS_MODEL_HAS_SHS_STATUS // +#define GPS_MODEL_HAS_NET_GLB_CFG // +#define GPS_MODEL_HAS_NET_DNS_SRVR // +#define GPS_MODEL_HAS_NET_DNS_SRCH_DOM // +#define GPS_MODEL_HAS_NET_STAT_DNS_SRVR // +#define GPS_MODEL_HAS_NET_STAT_DNS_SRCH_DOM // +#define GPS_MODEL_HAS_GNSS_SAT_INFO_IDX // + +#define GPS_MODEL_HAS_CFGH // +#define GPS_MODEL_HAS_ALM // +#define GPS_MODEL_HAS_EPH // +#define GPS_MODEL_HAS_UTC // +#define GPS_MODEL_HAS_IONO // +#define GPS_MODEL_HAS_ASCII_MSG // + +#define GPS_MODEL_HAS_GLNS_ALM // +#define GPS_MODEL_HAS_GNSS_SAT_INFO // +//#define GPS_MODEL_HAS_GNSS_MODE // + +#define GPS_MODEL_HAS_IP4_SETTINGS // +#define GPS_MODEL_HAS_LAN_IF_INFO // +#define GPS_MODEL_HAS_IP4_STATE // + +#define GPS_MODEL_HAS_CRYPTED_PACKET // +#define GPS_MODEL_HAS_CRYPTED_RAW_PACKET // + +#define GPS_MODEL_HAS_SECU_INFO // +#define GPS_MODEL_HAS_SECU_SETTINGS // +#define GPS_MODEL_HAS_SECU_PUBLIC_KEY // + +#endif //##++ more potential builtin features and classifiers + + + +/** + * @brief Common builtin features of all GPS receivers + * + * @see ::BUILTIN_FEAT_GPS_BUS_LVL + * @see ::BUILTIN_FEAT_GNSS + */ +#define BUILTIN_FEAT_GPS \ +( \ + GPS_MODEL_IS_GPS | \ + GPS_MODEL_HAS_BVAR_STAT | \ + GPS_MODEL_HAS_POS_XYZ | \ + GPS_MODEL_HAS_POS_LLA | \ + GPS_MODEL_HAS_TIME_TTM | \ + GPS_MODEL_HAS_TZDL | \ + GPS_MODEL_HAS_ANT_INFO | \ + GPS_MODEL_HAS_ENABLE_FLAGS | \ + GPS_MODEL_HAS_STAT_INFO | \ + GPS_MODEL_HAS_ANT_CABLE_LEN | \ + GPS_MODEL_HAS_SV_INFO \ +) + + +/** + * @brief Common builtin features of all GNSS receivers + * + * GNSS includes GPS but optionally other satellite systems, + * and the associated API. + * + * @see ::BUILTIN_FEAT_GNSS_BUS_LVL + * @see ::BUILTIN_FEAT_GPS + */ +#define BUILTIN_FEAT_GNSS \ +( \ + BUILTIN_FEAT_GPS | \ + GPS_MODEL_IS_GNSS \ +) + + + +/** + * @brief Common builtin features of all simple TCR devices + */ +#define BUILTIN_FEAT_TCR_1 \ +( \ + GPS_MODEL_IS_TCR \ +) + + +/** + * @brief Common builtin features of all enhanced TCR devices + */ +#define BUILTIN_FEAT_TCR_2 \ +( \ + GPS_MODEL_IS_TCR | \ + GPS_MODEL_HAS_TIME_TTM | \ + GPS_MODEL_HAS_TZDL | \ + GPS_MODEL_HAS_ANT_INFO | \ + GPS_MODEL_HAS_ENABLE_FLAGS \ +) + + + +/** + * @brief Common builtin features of all simple DCF77 AM receivers + */ +#define BUILTIN_FEAT_DCF_1 \ +( \ + GPS_MODEL_IS_DCF_AM | \ + GPS_MODEL_HAS_TZCODE \ +) + + +/** + * @brief Common builtin features of all enhanced DCF77 AM receivers + */ +#define BUILTIN_FEAT_DCF_2 \ +( \ + GPS_MODEL_IS_DCF_AM | \ + GPS_MODEL_HAS_TIME_TTM | \ + GPS_MODEL_HAS_TZDL | \ + GPS_MODEL_HAS_ANT_INFO | \ + GPS_MODEL_HAS_ENABLE_FLAGS \ +) + + +/** + * @brief Common builtin features of all simple DCF77 PZF receivers + */ +#define BUILTIN_FEAT_DCF_PZF_1 \ +( \ + GPS_MODEL_IS_DCF_PZF | \ + GPS_MODEL_HAS_TZCODE \ +) + + +/** + * @brief Common builtin features of all enhanced DCF77 PZF receivers + */ +#define BUILTIN_FEAT_DCF_PZF_2 \ +( \ + GPS_MODEL_IS_DCF_PZF | \ + GPS_MODEL_HAS_TIME_TTM | \ + GPS_MODEL_HAS_TZDL | \ + GPS_MODEL_HAS_ANT_INFO | \ + GPS_MODEL_HAS_ENABLE_FLAGS \ +) + + + +/** + * @brief Common builtin features of all simple MSF receivers + */ +#define BUILTIN_FEAT_MSF_1 \ +( \ + GPS_MODEL_IS_MSF | \ + GPS_MODEL_HAS_TZCODE \ +) + + +/** + * @brief Common builtin features of all enhanced MSF receivers + */ +#define BUILTIN_FEAT_MSF_2 \ +( \ + GPS_MODEL_IS_MSF | \ + GPS_MODEL_HAS_TIME_TTM | \ + GPS_MODEL_HAS_TZDL | \ + GPS_MODEL_HAS_ANT_INFO | \ + GPS_MODEL_HAS_ENABLE_FLAGS \ +) + + + +/** + * @brief Common builtin features of all simple WWVB receivers + */ +#define BUILTIN_FEAT_WVB_1 \ +( \ + GPS_MODEL_IS_WWVB | \ + GPS_MODEL_HAS_TZCODE \ +) + + +/** + * @brief Common builtin features of all enhanced WWVB receivers + */ +#define BUILTIN_FEAT_WVB_2 \ +( \ + GPS_MODEL_IS_WWVB | \ + GPS_MODEL_HAS_TZDL \ +) + + + +/** + * @brief Common builtin features of all simple JJY receivers + */ +#define BUILTIN_FEAT_JJY_1 \ +( \ + GPS_MODEL_IS_JJY | \ + GPS_MODEL_HAS_TZCODE \ +) + + + +/** + * @brief Common builtin features of all N2X devices + */ +#define BUILTIN_FEAT_COMM_N2X \ +( \ + GPS_MODEL_HAS_TIME_TTM | \ + GPS_MODEL_HAS_TZDL | \ + GPS_MODEL_HAS_ENABLE_FLAGS \ +) + + + +/** + * @brief Common builtin features of all bus-level GPS receivers + */ +#define BUILTIN_FEAT_GPS_BUS_LVL ( BUILTIN_FEAT_GPS | GPS_MODEL_IS_BUS_LVL_DEV ) + + +/** + * @brief Common builtin features of all bus-level GNSS receivers + */ +#define BUILTIN_FEAT_GNSS_BUS_LVL ( BUILTIN_FEAT_GNSS | GPS_MODEL_IS_BUS_LVL_DEV ) + + +/** + * @brief Common builtin features of all simple, bus-level TCR devices + */ +#define BUILTIN_FEAT_TCR_1_BUS_LVL ( BUILTIN_FEAT_TCR_1 | GPS_MODEL_IS_BUS_LVL_DEV ) + +/** + * @brief Common builtin features of all enhanced, bus-level TCR devices + */ +#define BUILTIN_FEAT_TCR_2_BUS_LVL ( BUILTIN_FEAT_TCR_2 | GPS_MODEL_IS_BUS_LVL_DEV ) + + +/** + * @brief Common builtin features of all simple, bus-level DCF77 AM receivers + */ +#define BUILTIN_FEAT_DCF_1_BUS_LVL ( BUILTIN_FEAT_DCF_1 | GPS_MODEL_IS_BUS_LVL_DEV ) + +/** + * @brief Common builtin features of all enhanced, bus-level DCF77 AM receivers + */ +#define BUILTIN_FEAT_DCF_2_BUS_LVL ( BUILTIN_FEAT_DCF_2 | GPS_MODEL_IS_BUS_LVL_DEV ) + +/** + * @brief Common builtin features of all enhanced, bus-level DCF77 PZF receivers + */ +#define BUILTIN_FEAT_DCF_PZF_2_BUS_LVL ( BUILTIN_FEAT_DCF_PZF_2 | GPS_MODEL_IS_BUS_LVL_DEV ) + + + +/** + * @brief Definitions of builtin features per device type + * + * @see ::GPS_MODEL_CODES + * @see @ref GPS_MODEL_BUILTIN_FEATURES + * + * @anchor GPS_MODEL_BUILTIN_FEATURE_MASKS @{ */ + +#define BUILTIN_FEAT_GPS166 ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_GPS167 ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_GPS167SV ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_GPS167PC ( BUILTIN_FEAT_GPS_BUS_LVL ) +#define BUILTIN_FEAT_GPS167PCI ( BUILTIN_FEAT_GPS_BUS_LVL ) +#define BUILTIN_FEAT_GPS163 ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_GPS168PCI ( BUILTIN_FEAT_GPS_BUS_LVL ) +#define BUILTIN_FEAT_GPS161 ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_GPS169PCI ( BUILTIN_FEAT_GPS_BUS_LVL ) +#define BUILTIN_FEAT_TCR167PCI ( BUILTIN_FEAT_TCR_2_BUS_LVL ) +#define BUILTIN_FEAT_GPS164 ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_GPS170PCI ( BUILTIN_FEAT_GPS_BUS_LVL ) +#define BUILTIN_FEAT_PZF511 ( BUILTIN_FEAT_DCF_PZF_1 ) +#define BUILTIN_FEAT_GPS170 ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_TCR511 ( BUILTIN_FEAT_TCR_1_BUS_LVL | GPS_MODEL_HAS_TIME_TTM ) //### TODO Or full TCR_2? +#define BUILTIN_FEAT_AM511 ( BUILTIN_FEAT_DCF_1 ) +#define BUILTIN_FEAT_MSF511 ( BUILTIN_FEAT_MSF_1 ) +#define BUILTIN_FEAT_GRC170 ( BUILTIN_FEAT_GNSS ) +#define BUILTIN_FEAT_GPS170PEX ( BUILTIN_FEAT_GPS_BUS_LVL ) +#define BUILTIN_FEAT_GPS162 ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_PTP270PEX ( GPS_MODEL_IS_BUS_LVL_DEV ) +#define BUILTIN_FEAT_FRC511PEX ( GPS_MODEL_IS_BUS_LVL_DEV ) +#define BUILTIN_FEAT_GEN170 ( 0 ) +#define BUILTIN_FEAT_TCR170PEX ( BUILTIN_FEAT_TCR_2_BUS_LVL ) +#define BUILTIN_FEAT_WWVB511 ( BUILTIN_FEAT_WVB_1 ) +#define BUILTIN_FEAT_MGR170 ( 0 ) +#define BUILTIN_FEAT_JJY511 ( BUILTIN_FEAT_JJY_1 ) +#define BUILTIN_FEAT_PZF600 ( BUILTIN_FEAT_DCF_PZF_1 ) //### TODO Or full PZF_2? +#define BUILTIN_FEAT_TCR600 ( BUILTIN_FEAT_TCR_1 | GPS_MODEL_HAS_TIME_TTM ) //### TODO Or full TCR_2? +#define BUILTIN_FEAT_GPS180 ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_GLN170 ( BUILTIN_FEAT_GNSS) +#define BUILTIN_FEAT_GPS180PEX ( BUILTIN_FEAT_GPS_BUS_LVL ) +#define BUILTIN_FEAT_TCR180PEX ( BUILTIN_FEAT_TCR_2_BUS_LVL ) +#define BUILTIN_FEAT_PZF180PEX ( BUILTIN_FEAT_DCF_PZF_2_BUS_LVL ) +#define BUILTIN_FEAT_MGR180 ( 0 ) +#define BUILTIN_FEAT_MSF600 ( BUILTIN_FEAT_MSF_1 ) //### TODO Or full MSF_2? +#define BUILTIN_FEAT_WWVB600 ( BUILTIN_FEAT_WVB_1 ) //### TODO Or full WVB_2? +#define BUILTIN_FEAT_JJY600 ( BUILTIN_FEAT_JJY_1 ) //### TODO Or full JJY_2? +#define BUILTIN_FEAT_GPS180HS ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_GPS180AMC ( BUILTIN_FEAT_GPS_BUS_LVL ) +#define BUILTIN_FEAT_ESI180 ( 0 ) +#define BUILTIN_FEAT_CPE180 ( 0 ) +#define BUILTIN_FEAT_LNO180 ( 0 ) +#define BUILTIN_FEAT_GRC180 ( BUILTIN_FEAT_GNSS ) +#define BUILTIN_FEAT_LIU ( 0 ) +#define BUILTIN_FEAT_DCF600HS ( BUILTIN_FEAT_DCF_2 ) //### TODO +#define BUILTIN_FEAT_DCF600RS ( BUILTIN_FEAT_DCF_2 ) //### TODO +#define BUILTIN_FEAT_MRI ( 0 ) +#define BUILTIN_FEAT_BPE ( 0 ) +#define BUILTIN_FEAT_GLN180PEX ( BUILTIN_FEAT_GNSS_BUS_LVL ) +#define BUILTIN_FEAT_N2X ( BUILTIN_FEAT_COMM_N2X ) +#define BUILTIN_FEAT_RSC180 ( GPS_MODEL_HAS_SCU_STAT ) +#define BUILTIN_FEAT_LNE_GB ( 0 ) +#define BUILTIN_FEAT_PPG180 ( 0 ) +#define BUILTIN_FEAT_SCG ( 0 ) +#define BUILTIN_FEAT_MDU300 ( 0 ) +#define BUILTIN_FEAT_SDI ( 0 ) +#define BUILTIN_FEAT_FDM180 ( GPS_MODEL_HAS_TZDL | GPS_MODEL_HAS_ENABLE_FLAGS ) +#define BUILTIN_FEAT_SPT ( 0 ) +#define BUILTIN_FEAT_PZF180 ( BUILTIN_FEAT_DCF_PZF_2 ) +#define BUILTIN_FEAT_REL1000 ( 0 ) +#define BUILTIN_FEAT_HPS100 ( 0 ) +#define BUILTIN_FEAT_VSG180 ( 0 ) +#define BUILTIN_FEAT_MSF180 ( BUILTIN_FEAT_MSF_2 ) +#define BUILTIN_FEAT_WWVB180 ( BUILTIN_FEAT_WVB_2 ) +#define BUILTIN_FEAT_CPC180 ( 0 ) +#define BUILTIN_FEAT_CTC100 ( 0 ) +#define BUILTIN_FEAT_TCR180 ( BUILTIN_FEAT_TCR_2 ) +#define BUILTIN_FEAT_LUE180 ( 0 ) +#define BUILTIN_FEAT_CPC_01 ( 0 ) +#define BUILTIN_FEAT_TSU_01 ( 0 ) +#define BUILTIN_FEAT_CMC_01 ( 0 ) +#define BUILTIN_FEAT_SCU_01 ( 0 ) +#define BUILTIN_FEAT_FCU_01 ( 0 ) +#define BUILTIN_FEAT_CSM100 ( 0 ) +#define BUILTIN_FEAT_LNE180SFP ( 0 ) +#define BUILTIN_FEAT_GTS180 ( 0 ) +#define BUILTIN_FEAT_GPS180CSM ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_GRC181 ( BUILTIN_FEAT_GNSS ) +#define BUILTIN_FEAT_N2X180 ( BUILTIN_FEAT_COMM_N2X ) +#define BUILTIN_FEAT_GNS181PEX ( BUILTIN_FEAT_GNSS_BUS_LVL ) +#define BUILTIN_FEAT_MDU180 ( GPS_MODEL_HAS_SCU_STAT ) +#define BUILTIN_FEAT_MDU312 ( 0 ) +#define BUILTIN_FEAT_GPS165 ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_GNS181_UC ( BUILTIN_FEAT_GNSS ) +#define BUILTIN_FEAT_PSX_4GE ( 0 ) +#define BUILTIN_FEAT_RSC180RDU ( GPS_MODEL_HAS_SCU_STAT ) +#define BUILTIN_FEAT_USYNCPWR ( 0 ) +#define BUILTIN_FEAT_FDM180M ( GPS_MODEL_HAS_TZDL | GPS_MODEL_HAS_ENABLE_FLAGS ) +#define BUILTIN_FEAT_LSG180 ( 0 ) +#define BUILTIN_FEAT_GPS190 ( BUILTIN_FEAT_GPS ) +#define BUILTIN_FEAT_GNS181 ( BUILTIN_FEAT_GNSS ) + +/** + * @brief Feature mask used for legacy devices + * + * This code is used to set builtin feature flags + * legacy devices not listed here, so we can simply + * search for ::BUILTIN_FEAT_UNDEFINED to identify + * such devices. The numeric value is just 0, though. + */ +#define BUILTIN_FEAT_UNDEFINED ( 0 ) + +/** @} anchor GPS_MODEL_BUILTIN_FEATURE_MASKS */ + + + +/** + * @brief Initializer for a table of built-in features per device + * + * Last entry is all zero to indicated end of table. + * + * @see ::GPS_MODEL_CODES + * @see @ref GPS_MODEL_BUILTIN_FEATURE_MASKS + */ +#define GPS_MODEL_BUILTIN_FEATURES \ +{ \ + { GPS_MODEL_GPS166, BUILTIN_FEAT_GPS166 }, \ + { GPS_MODEL_GPS167, BUILTIN_FEAT_GPS167 }, \ + { GPS_MODEL_GPS167SV, BUILTIN_FEAT_GPS167SV }, \ + { GPS_MODEL_GPS167PC, BUILTIN_FEAT_GPS167PC }, \ + { GPS_MODEL_GPS167PCI, BUILTIN_FEAT_GPS167PCI }, \ + { GPS_MODEL_GPS163, BUILTIN_FEAT_GPS163 }, \ + { GPS_MODEL_GPS168PCI, BUILTIN_FEAT_GPS168PCI }, \ + { GPS_MODEL_GPS161, BUILTIN_FEAT_GPS161 }, \ + { GPS_MODEL_GPS169PCI, BUILTIN_FEAT_GPS169PCI }, \ + { GPS_MODEL_TCR167PCI, BUILTIN_FEAT_TCR167PCI }, \ + { GPS_MODEL_GPS164, BUILTIN_FEAT_GPS164 }, \ + { GPS_MODEL_GPS170PCI, BUILTIN_FEAT_GPS170PCI }, \ + { GPS_MODEL_PZF511, BUILTIN_FEAT_PZF511 }, \ + { GPS_MODEL_GPS170, BUILTIN_FEAT_GPS170 }, \ + { GPS_MODEL_TCR511, BUILTIN_FEAT_TCR511 }, \ + { GPS_MODEL_AM511, BUILTIN_FEAT_AM511 }, \ + { GPS_MODEL_MSF511, BUILTIN_FEAT_MSF511 }, \ + { GPS_MODEL_GRC170, BUILTIN_FEAT_GRC170 }, \ + { GPS_MODEL_GPS170PEX, BUILTIN_FEAT_GPS170PEX }, \ + { GPS_MODEL_GPS162, BUILTIN_FEAT_GPS162 }, \ + { GPS_MODEL_PTP270PEX, BUILTIN_FEAT_PTP270PEX }, \ + { GPS_MODEL_FRC511PEX, BUILTIN_FEAT_FRC511PEX }, \ + { GPS_MODEL_GEN170, BUILTIN_FEAT_GEN170 }, \ + { GPS_MODEL_TCR170PEX, BUILTIN_FEAT_TCR170PEX }, \ + { GPS_MODEL_WWVB511, BUILTIN_FEAT_WWVB511 }, \ + { GPS_MODEL_MGR170, BUILTIN_FEAT_MGR170 }, \ + { GPS_MODEL_JJY511, BUILTIN_FEAT_JJY511 }, \ + { GPS_MODEL_PZF600, BUILTIN_FEAT_PZF600 }, \ + { GPS_MODEL_TCR600, BUILTIN_FEAT_TCR600 }, \ + { GPS_MODEL_GPS180, BUILTIN_FEAT_GPS180 }, \ + { GPS_MODEL_GLN170, BUILTIN_FEAT_GLN170 }, \ + { GPS_MODEL_GPS180PEX, BUILTIN_FEAT_GPS180PEX }, \ + { GPS_MODEL_TCR180PEX, BUILTIN_FEAT_TCR180PEX }, \ + { GPS_MODEL_PZF180PEX, BUILTIN_FEAT_PZF180PEX }, \ + { GPS_MODEL_MGR180, BUILTIN_FEAT_MGR180 }, \ + { GPS_MODEL_MSF600, BUILTIN_FEAT_MSF600 }, \ + { GPS_MODEL_WWVB600, BUILTIN_FEAT_WWVB600 }, \ + { GPS_MODEL_JJY600, BUILTIN_FEAT_JJY600 }, \ + { GPS_MODEL_GPS180HS, BUILTIN_FEAT_GPS180HS }, \ + { GPS_MODEL_GPS180AMC, BUILTIN_FEAT_GPS180AMC }, \ + { GPS_MODEL_ESI180, BUILTIN_FEAT_ESI180 }, \ + { GPS_MODEL_CPE180, BUILTIN_FEAT_CPE180 }, \ + { GPS_MODEL_LNO180, BUILTIN_FEAT_LNO180 }, \ + { GPS_MODEL_GRC180, BUILTIN_FEAT_GRC180 }, \ + { GPS_MODEL_LIU, BUILTIN_FEAT_LIU }, \ + { GPS_MODEL_DCF600HS, BUILTIN_FEAT_DCF600HS }, \ + { GPS_MODEL_DCF600RS, BUILTIN_FEAT_DCF600RS }, \ + { GPS_MODEL_MRI, BUILTIN_FEAT_MRI }, \ + { GPS_MODEL_BPE, BUILTIN_FEAT_BPE }, \ + { GPS_MODEL_GLN180PEX, BUILTIN_FEAT_GLN180PEX }, \ + { GPS_MODEL_N2X, BUILTIN_FEAT_N2X }, \ + { GPS_MODEL_RSC180, BUILTIN_FEAT_RSC180 }, \ + { GPS_MODEL_LNE_GB, BUILTIN_FEAT_LNE_GB }, \ + { GPS_MODEL_PPG180, BUILTIN_FEAT_PPG180 }, \ + { GPS_MODEL_SCG, BUILTIN_FEAT_SCG }, \ + { GPS_MODEL_MDU300, BUILTIN_FEAT_MDU300 }, \ + { GPS_MODEL_SDI, BUILTIN_FEAT_SDI }, \ + { GPS_MODEL_FDM180, BUILTIN_FEAT_FDM180 }, \ + { GPS_MODEL_SPT, BUILTIN_FEAT_SPT }, \ + { GPS_MODEL_PZF180, BUILTIN_FEAT_PZF180 }, \ + { GPS_MODEL_REL1000, BUILTIN_FEAT_REL1000 }, \ + { GPS_MODEL_HPS100, BUILTIN_FEAT_HPS100 }, \ + { GPS_MODEL_VSG180, BUILTIN_FEAT_VSG180 }, \ + { GPS_MODEL_MSF180, BUILTIN_FEAT_MSF180 }, \ + { GPS_MODEL_WWVB180, BUILTIN_FEAT_WWVB180 }, \ + { GPS_MODEL_CPC180, BUILTIN_FEAT_CPC180 }, \ + { GPS_MODEL_CTC100, BUILTIN_FEAT_CTC100 }, \ + { GPS_MODEL_TCR180, BUILTIN_FEAT_TCR180 }, \ + { GPS_MODEL_LUE180, BUILTIN_FEAT_LUE180 }, \ + { GPS_MODEL_CPC_01, BUILTIN_FEAT_CPC_01 }, \ + { GPS_MODEL_TSU_01, BUILTIN_FEAT_TSU_01 }, \ + { GPS_MODEL_CMC_01, BUILTIN_FEAT_CMC_01 }, \ + { GPS_MODEL_SCU_01, BUILTIN_FEAT_SCU_01 }, \ + { GPS_MODEL_FCU_01, BUILTIN_FEAT_FCU_01 }, \ + { GPS_MODEL_CSM100, BUILTIN_FEAT_CSM100 }, \ + { GPS_MODEL_LNE180SFP, BUILTIN_FEAT_LNE180SFP }, \ + { GPS_MODEL_GTS180, BUILTIN_FEAT_GTS180 }, \ + { GPS_MODEL_GPS180CSM, BUILTIN_FEAT_GPS180CSM }, \ + { GPS_MODEL_GRC181, BUILTIN_FEAT_GRC181 }, \ + { GPS_MODEL_N2X180, BUILTIN_FEAT_N2X180 }, \ + { GPS_MODEL_GNS181PEX, BUILTIN_FEAT_GNS181PEX }, \ + { GPS_MODEL_MDU180, BUILTIN_FEAT_MDU180 }, \ + { GPS_MODEL_MDU312, BUILTIN_FEAT_MDU312 }, \ + { GPS_MODEL_GPS165, BUILTIN_FEAT_GPS165 }, \ + { GPS_MODEL_GNS181_UC, BUILTIN_FEAT_GNS181_UC }, \ + { GPS_MODEL_PSX_4GE, BUILTIN_FEAT_PSX_4GE }, \ + { GPS_MODEL_RSC180RDU, BUILTIN_FEAT_RSC180RDU }, \ + { GPS_MODEL_USYNCPWR, BUILTIN_FEAT_USYNCPWR }, \ + { GPS_MODEL_FDM180M, BUILTIN_FEAT_FDM180M }, \ + { GPS_MODEL_LSG180, BUILTIN_FEAT_LSG180 }, \ + { GPS_MODEL_GPS190, BUILTIN_FEAT_GPS190 }, \ + { GPS_MODEL_GNS181, BUILTIN_FEAT_GNS181 }, \ + { 0, 0 } \ } +/** @} anchor GPS_BUILTIN_FEATURE_DEFS */ + + + +/** + * @brief Initialize a ::RECEIVER_INFO structure for legacy DCF77 receivers + * + * Legacy DCF77 receivers may not provide a ::RECEIVER_INFO structure, + * but have well-known properties which can be used to set up a + * default ::RECEIVER_INFO. + * + * @param[in,out] _p Pointer to a ::RECEIVER_INFO STRUCTURE to be set up + * @param[in] _pdev Pointer to a ::PCPS_DEV structure read before + * + * @see ::_setup_default_receiver_info_gps + */ +#define _setup_default_receiver_info_dcf( _p, _pdev ) \ +do \ +{ \ + memset( (_p), 0, sizeof( *(_p) ) ); \ + \ + (_p)->ticks_per_sec = DEFAULT_GPS_TICKS_PER_SEC; \ + (_p)->n_ucaps = 0; \ + (_p)->n_com_ports = _pcps_has_serial( _pdev ) ? 1 : 0; \ + (_p)->n_str_type = ( (_p)->n_com_ports != 0 ) ? \ + DEFAULT_N_STR_TYPE_DCF : 0; \ +} while ( 0 ) + + + +/** + * @brief Initialize a ::RECEIVER_INFO structure for legacy GPS receivers + * + * Legacy GPS receivers may not provide a ::RECEIVER_INFO structure, + * but have well-known properties which can be used to set up a + * default ::RECEIVER_INFO. + * + * @param[in,out] _p Pointer to a ::RECEIVER_INFO STRUCTURE to be set up + * + * @see ::_setup_default_receiver_info_dcf + */ +#define _setup_default_receiver_info_gps( _p ) \ +do \ +{ \ + memset( (_p), 0, sizeof( *(_p) ) ); \ + \ + (_p)->ticks_per_sec = DEFAULT_GPS_TICKS_PER_SEC; \ + (_p)->n_ucaps = 2; \ + (_p)->n_com_ports = DEFAULT_N_COM; \ + (_p)->n_str_type = DEFAULT_N_STR_TYPE_GPS; \ +} while ( 0 ) + + /* * The macros below can be used to classify a receiver, @@ -730,11 +1902,11 @@ enum #define _mbg_rcvr_is_plug_in( _p_ri ) \ ( strstr( (_p_ri)->model_name, "PC" ) || \ - ( strstr( (_p_ri)->model_name, "PEX" ) ) + strstr( (_p_ri)->model_name, "PEX" ) ) #define _mbg_rcvr_is_gps( _p_ri ) \ ( strstr( (_p_ri)->model_name, "GPS" ) || \ - ( strstr( (_p_ri)->model_name, "MGR" ) ) + strstr( (_p_ri)->model_name, "MGR" ) ) #define _mbg_rcvr_is_mobile_gps( _p_ri ) \ ( strstr( (_p_ri)->model_name, "MGR" ) ) @@ -784,7 +1956,7 @@ enum #define _mbg_rcvr_is_glonass( _p_ri ) \ ( strstr( (_p_ri)->model_name, "GRC" ) || \ - ( strstr( (_p_ri)->model_name, "GLN" ) ) + strstr( (_p_ri)->model_name, "GLN" ) ) #define _mbg_rcvr_is_glonass_plug_in( _p_ri ) \ ( _mbg_rcvr_is_glonass( _p_ri ) && \ @@ -798,13 +1970,17 @@ enum _mbg_rcvr_is_plug_in( _p_ri ) ) + /** - * The classification codes for oscillators below - * are used with RECEIVER_INFO.osc_type. New codes - * must be appended to the enumeration, so the sequence - * of codes does NOT reflect the order of quality: + * @brief Known oscillator types used with ::RECEIVER_INFO::osc_type + * + * The sequence of codes does NOT reflect the order of quality. + * New oscillator type codes will just be appended to the enumeration. + * + * @see ::DEFAULT_GPS_OSC_NAMES + * @see ::DEFAULT_GPS_OSC_QUALITY_IDX */ -enum +enum GPS_OSC_TYPES { GPS_OSC_UNKNOWN, GPS_OSC_TCXO_LQ, @@ -816,14 +1992,19 @@ enum GPS_OSC_RUBIDIUM, GPS_OSC_TCXO_MQ, GPS_OSC_OCXO_DHQ, + GPS_OSC_OCXO_SQ, N_GPS_OSC }; -/* - * The sequence and number of oscillator names - * listed below must correspond to the enumeration - * above: +/** + * @brief Oscillator type name string initializer + * + * The sequence and number of oscillator names has to + * correspond to the enumeration in ::GPS_OSC_TYPES + * + * @see ::GPS_OSC_TYPES + * @see ::DEFAULT_GPS_OSC_QUALITY_IDX */ #define DEFAULT_GPS_OSC_NAMES \ { \ @@ -836,15 +2017,21 @@ enum "OCXO XHQ", \ "RUBIDIUM", \ "TCXO MQ", \ - "OCXO DHQ" \ + "OCXO DHQ", \ + "OCXO SQ" \ } -/* - * The initializer below can be used to initialize - * an array (e.g. "int osc_quality_idx[N_GPS_OSC]") - * which allows to display the oscillator types - * ordered by quality: +/** + * @brief Oscillator quality index + * + * Can be used to initialize a index array + * (e.g. "int osc_quality_idx[N_GPS_OSC];") + * allowing to display the oscillator types + * ordered by quality + * + * @see ::GPS_OSC_TYPES + * @see ::DEFAULT_GPS_OSC_NAMES */ #define DEFAULT_GPS_OSC_QUALITY_IDX \ { \ @@ -853,6 +2040,7 @@ enum GPS_OSC_TCXO_MQ, \ GPS_OSC_TCXO_HQ, \ GPS_OSC_OCXO_LQ, \ + GPS_OSC_OCXO_SQ, \ GPS_OSC_OCXO_MQ, \ GPS_OSC_OCXO_HQ, \ GPS_OSC_OCXO_DHQ, \ @@ -862,45 +2050,71 @@ enum -/* - * Codes to be used with RECEIVER_INFO.osc_flags - * are not yet used/required, so they are reserved - * for future use. - */ - - /** - * The codes below enumerate some features which may be - * supported by a given clock, or not. + * @brief Enumeration of device features flags reported in ::RI_FEATURES + * + * Used with ::RECEIVER_INFO::features. Each flags indicates if a device + * supports the associated feature, but due to the limited bit size of + * the ::RI_FEATURES type the number of these features is limited to 32. + * + * To extend the number of possible features the ::MBG_XFEATURE_BITS, the + * ::MBG_XFEATURE_BUFFER structure and associated definitions have been + * introduced, which are supported by devices which have ::GPS_HAS_XFEATURE + * set in ::RI_FEATURES. + * + * @see ::RI_FEATURES + * @see ::MBG_XFEATURE_BITS + * @see ::MBG_XFEATURE_BUFFER */ -enum +enum GPS_FEATURE_BITS { - GPS_FEAT_PPS, /**< has pulse per second output */ - GPS_FEAT_PPM, /**< has pulse per minute output */ - GPS_FEAT_SYNTH, /**< has programmable synthesizer output */ - GPS_FEAT_DCFMARKS, /**< has DCF77 compatible time mark output */ - GPS_FEAT_IRIG_TX, /**< has on-board IRIG output */ - GPS_FEAT_IRIG_RX, /**< has on-board IRIG input */ - GPS_FEAT_LAN_IP4, /**< has LAN IPv4 interface */ - GPS_FEAT_MULTI_REF, /**< has multiple input sources with priorities */ - GPS_FEAT_RCV_TIMEOUT, /**< timeout after GPS reception has stopped */ - GPS_FEAT_IGNORE_LOCK, /**< supports "ignore lock", alternatively */ - /**< MBG_OPT_BIT_EMU_SYNC may be supported */ - GPS_FEAT_5_MHZ, /**< output 5 MHz rather than 100 kHz */ - GPS_FEAT_XMULTI_REF, /**< has extended multiple input source configuration */ - GPS_FEAT_OPT_SETTINGS, /**< supports MBG_OPT_SETTINGS */ - GPS_FEAT_TIME_SCALE, /**< supports configurable time scale (UTC, TAI, GPS, ...) */ - GPS_FEAT_IRIG_CTRL_BITS, /**< supports IRIG control bits */ - GPS_FEAT_PTP, /**< has PTP support */ - GPS_FEAT_NAV_ENGINE_SETTINGS, /**< supports navigation engine configuration */ - GPS_FEAT_RAW_IRIG_DATA, /**< supports reading raw IRIG input data */ - GPS_FEAT_RAW_IRIG_TIME, /**< supports reading decoded IRIG time */ - GPS_FEAT_PTP_UNICAST, /**< has PTP Unicast support */ - GPS_FEAT_GPIO, /**< has general purpose in/outputs */ - N_GPS_FEATURE /**< the number of valid features */ + GPS_FEAT_PPS, ///< has pulse per second output + GPS_FEAT_PPM, ///< has pulse per minute output + GPS_FEAT_SYNTH, ///< has programmable synthesizer output + GPS_FEAT_DCFMARKS, ///< has DCF77 compatible time mark output + GPS_FEAT_IRIG_TX, ///< has on-board IRIG output + GPS_FEAT_IRIG_RX, ///< has on-board IRIG input + GPS_FEAT_LAN_IP4, ///< has simple LAN IPv4 interface, superseded by ::GPS_FEAT_NET_CFG + GPS_FEAT_MULTI_REF, ///< has multiple input sources with priorities, superseded by ::GPS_FEAT_XMULTI_REF + + GPS_FEAT_RCV_TIMEOUT, ///< timeout after GPS reception has stopped + GPS_FEAT_IGNORE_LOCK, ///< supports "ignore lock", ::MBG_OPT_BIT_EMU_SYNC can be set alternatively + GPS_FEAT_5_MHZ, ///< output 5 MHz rather than 100 kHz + GPS_FEAT_XMULTI_REF, ///< has extended multiple input source configuration, supersedes ::GPS_FEAT_MULTI_REF + GPS_FEAT_OPT_SETTINGS, ///< supports ::MBG_OPT_SETTINGS + GPS_FEAT_TIME_SCALE, ///< supports configurable time scale (%UTC, TAI, GPS, ...) + GPS_FEAT_IRIG_CTRL_BITS, ///< supports IRIG control bits (::MBG_IRIG_CTRL_BITS) + GPS_FEAT_PTP, ///< has PTP support + + GPS_FEAT_NAV_ENGINE_SETTINGS, ///< supports navigation engine configuration + GPS_FEAT_RAW_IRIG_DATA, ///< supports reading raw IRIG input data (::MBG_RAW_IRIG_DATA) + GPS_FEAT_RAW_IRIG_TIME, ///< supports reading decoded IRIG time (::PCPS_IRIG_TIME) + GPS_FEAT_PTP_UNICAST, ///< has PTP Unicast support + GPS_FEAT_GPIO, ///< has general purpose inputs/outputs + GPS_FEAT_XMRS_MULT_INSTC, ///< multiple XMRS instances of the same ref type supported (::XMULTI_REF_INSTANCES) + GPS_FEAT_10MHZ_DISBD, ///< 10 MHz output is always disabled + GPS_FEAT_EVT_LOG, ///< Event logging supported + + GPS_FEAT_IMS, ///< supports IMS data structures + GPS_FEAT_HAVEQUICK, ///< supports HaveQuick structures + GPS_FEAT_NTP, ///< supports NTP structures + GPS_FEAT_NET_CFG, ///< supports extended network interface configuration, supersedes ::GPS_FEAT_LAN_IP4 + GPS_FEAT_VST, ///< supports VST (Versatile Storage) API and structures + GPS_FEAT_SHS, ///< supports SHS (Secure Hybrid System) API and structures + GPS_FEAT_XBP, ///< supports XBP (eXtended Binary Protocol) API and structures, see @ref group_xbp + GPS_FEAT_XFEATURE, ///< support eXtended features, see @ref group_xfeature + N_GPS_FEATURE ///< the number of known ::GPS_FEATURE_BITS, should now be at its limit, i.e. 32. + + // WARNING: There are no more unassigned feature bits available here. + // New features have to be defined using the ::MBG_XFEATURE_BITS }; +/** + * @brief Names of device features + * + * @see ::GPS_FEATURE_BITS + */ #define DEFAULT_GPS_FEATURE_NAMES \ { \ "Pulse Per Second", \ @@ -923,37 +2137,197 @@ enum "Raw IRIG Data", \ "Raw IRIG Time", \ "PTP/IEEE1588 Unicast", \ - "General Purpose I/O" \ + "General Purpose I/O", \ + "Multiple XMRS Instances", \ + "10 MHz Output Disabled", \ + "Event Logging", \ + "IMS data", \ + "HaveQuick", \ + "NTP", \ + "Ext. Network Config", \ + "Versatile Storage", \ + "SHS", \ + "Extended Binary Protocol", \ + "Extended Features" \ } -/* - * Bit masks used with RECEIVER_INFO.features - * (others are reserved): - */ -#define GPS_HAS_PPS ( 1UL << GPS_FEAT_PPS ) -#define GPS_HAS_PPM ( 1UL << GPS_FEAT_PPM ) -#define GPS_HAS_SYNTH ( 1UL << GPS_FEAT_SYNTH ) -#define GPS_HAS_DCFMARKS ( 1UL << GPS_FEAT_DCFMARKS ) -#define GPS_HAS_IRIG_TX ( 1UL << GPS_FEAT_IRIG_TX ) -#define GPS_HAS_IRIG_RX ( 1UL << GPS_FEAT_IRIG_RX ) -#define GPS_HAS_LAN_IP4 ( 1UL << GPS_FEAT_LAN_IP4 ) -#define GPS_HAS_MULTI_REF ( 1UL << GPS_FEAT_MULTI_REF ) -#define GPS_HAS_RCV_TIMEOUT ( 1UL << GPS_FEAT_RCV_TIMEOUT ) -#define GPS_HAS_IGNORE_LOCK ( 1UL << GPS_FEAT_IGNORE_LOCK ) -#define GPS_HAS_5_MHZ ( 1UL << GPS_FEAT_5_MHZ ) -#define GPS_HAS_XMULTI_REF ( 1UL << GPS_FEAT_XMULTI_REF ) -#define GPS_HAS_OPT_SETTINGS ( 1UL << GPS_FEAT_OPT_SETTINGS ) -#define GPS_HAS_TIME_SCALE ( 1UL << GPS_FEAT_TIME_SCALE ) -#define GPS_HAS_IRIG_CTRL_BITS ( 1UL << GPS_FEAT_IRIG_CTRL_BITS ) -#define GPS_HAS_PTP ( 1UL << GPS_FEAT_PTP ) -#define GPS_HAS_NAV_ENGINE_SETTINGS ( 1UL << GPS_FEAT_NAV_ENGINE_SETTINGS ) -#define GPS_HAS_RAW_IRIG_DATA ( 1UL << GPS_FEAT_RAW_IRIG_DATA ) -#define GPS_HAS_RAW_IRIG_TIME ( 1UL << GPS_FEAT_RAW_IRIG_TIME ) -#define GPS_HAS_PTP_UNICAST ( 1UL << GPS_FEAT_PTP_UNICAST ) -#define GPS_HAS_GPIO ( 1UL << GPS_FEAT_GPIO ) - -#define GPS_HAS_REF_OFFS GPS_HAS_IRIG_RX +/** + * @brief Bit masks used with ::RECEIVER_INFO::features + * + * @see ::GPS_FEATURE_BITS + * + * @anchor GPS_FEATURE_MASKS @{ */ + +#define GPS_HAS_PPS ( 1UL << GPS_FEAT_PPS ) ///< see ::GPS_FEAT_PPS +#define GPS_HAS_PPM ( 1UL << GPS_FEAT_PPM ) ///< see ::GPS_FEAT_PPM +#define GPS_HAS_SYNTH ( 1UL << GPS_FEAT_SYNTH ) ///< see ::GPS_FEAT_SYNTH +#define GPS_HAS_DCFMARKS ( 1UL << GPS_FEAT_DCFMARKS ) ///< see ::GPS_FEAT_DCFMARKS +#define GPS_HAS_IRIG_TX ( 1UL << GPS_FEAT_IRIG_TX ) ///< see ::GPS_FEAT_IRIG_TX +#define GPS_HAS_IRIG_RX ( 1UL << GPS_FEAT_IRIG_RX ) ///< see ::GPS_FEAT_IRIG_RX +#define GPS_HAS_LAN_IP4 ( 1UL << GPS_FEAT_LAN_IP4 ) ///< see ::GPS_FEAT_LAN_IP4 +#define GPS_HAS_MULTI_REF ( 1UL << GPS_FEAT_MULTI_REF ) ///< see ::GPS_FEAT_MULTI_REF + +#define GPS_HAS_RCV_TIMEOUT ( 1UL << GPS_FEAT_RCV_TIMEOUT ) ///< see ::GPS_FEAT_RCV_TIMEOUT +#define GPS_HAS_IGNORE_LOCK ( 1UL << GPS_FEAT_IGNORE_LOCK ) ///< see ::GPS_FEAT_IGNORE_LOCK +#define GPS_HAS_5_MHZ ( 1UL << GPS_FEAT_5_MHZ ) ///< see ::GPS_FEAT_5_MHZ +#define GPS_HAS_XMULTI_REF ( 1UL << GPS_FEAT_XMULTI_REF ) ///< see ::GPS_FEAT_XMULTI_REF +#define GPS_HAS_OPT_SETTINGS ( 1UL << GPS_FEAT_OPT_SETTINGS ) ///< see ::GPS_FEAT_OPT_SETTINGS +#define GPS_HAS_TIME_SCALE ( 1UL << GPS_FEAT_TIME_SCALE ) ///< see ::GPS_FEAT_TIME_SCALE +#define GPS_HAS_IRIG_CTRL_BITS ( 1UL << GPS_FEAT_IRIG_CTRL_BITS ) ///< see ::GPS_FEAT_IRIG_CTRL_BITS +#define GPS_HAS_PTP ( 1UL << GPS_FEAT_PTP ) ///< see ::GPS_FEAT_PTP + +#define GPS_HAS_NAV_ENGINE_SETTINGS ( 1UL << GPS_FEAT_NAV_ENGINE_SETTINGS ) ///< see ::GPS_FEAT_NAV_ENGINE_SETTINGS +#define GPS_HAS_RAW_IRIG_DATA ( 1UL << GPS_FEAT_RAW_IRIG_DATA ) ///< see ::GPS_FEAT_RAW_IRIG_DATA +#define GPS_HAS_RAW_IRIG_TIME ( 1UL << GPS_FEAT_RAW_IRIG_TIME ) ///< see ::GPS_FEAT_RAW_IRIG_TIME +#define GPS_HAS_PTP_UNICAST ( 1UL << GPS_FEAT_PTP_UNICAST ) ///< see ::GPS_FEAT_PTP_UNICAST +#define GPS_HAS_GPIO ( 1UL << GPS_FEAT_GPIO ) ///< see ::GPS_FEAT_GPIO +#define GPS_HAS_XMRS_MULT_INSTC ( 1UL << GPS_FEAT_XMRS_MULT_INSTC ) ///< see ::GPS_FEAT_XMRS_MULT_INSTC +#define GPS_HAS_10MHZ_DISBD ( 1UL << GPS_FEAT_10MHZ_DISBD ) ///< see ::GPS_FEAT_10MHZ_DISBD +#define GPS_HAS_EVT_LOG ( 1UL << GPS_FEAT_EVT_LOG ) ///< see ::GPS_FEAT_EVT_LOG + +#define GPS_HAS_IMS ( 1UL << GPS_FEAT_IMS ) ///< see ::GPS_FEAT_IMS +#define GPS_HAS_HAVEQUICK ( 1UL << GPS_FEAT_HAVEQUICK ) ///< see ::GPS_FEAT_HAVEQUICK +#define GPS_HAS_NTP ( 1UL << GPS_FEAT_NTP ) ///< see ::GPS_FEAT_NTP +#define GPS_HAS_NET_CFG ( 1UL << GPS_FEAT_NET_CFG ) ///< see ::GPS_FEAT_NET_CFG +#define GPS_HAS_VST ( 1UL << GPS_FEAT_VST ) ///< see ::GPS_FEAT_VST +#define GPS_HAS_SHS ( 1UL << GPS_FEAT_SHS ) ///< see ::GPS_FEAT_SHS +#define GPS_HAS_XBP ( 1UL << GPS_FEAT_XBP ) ///< see ::GPS_FEAT_XBP +#define GPS_HAS_XFEATURE ( 1UL << GPS_FEAT_XFEATURE ) ///< see ::GPS_FEAT_XFEATURE + +// the next ones are special since they just shadow another flag: +#define GPS_HAS_REF_OFFS GPS_HAS_IRIG_RX ///< always supported with IRIG inputs, see ::GPS_HAS_IRIG_RX +#define GPS_HAS_DEBUG_STATUS GPS_HAS_IRIG_RX ///< always supported with IRIG inputs, see ::GPS_HAS_IRIG_RX + +/** @} anchor GPS_FEATURE_MASKS */ + + +/** + * @defgroup group_xfeature Extended feature definitions + * + * @note These structures and definitions are only supported by a device + * if ::GPS_HAS_XFEATURE is set in ::RECEIVER_INFO::features. + * + * @{ */ + + +/** + * @brief The maximum number of feature bits supported by the MBG_XFEATURE API. + * + * Warning: Changing this number breaks API compatibility! + * + * @see ::MBG_XFEATURE_BITS + */ +#define MAX_XFEATURE_BITS 1024 + + + +/** + * @brief Enumeration of defined extended features. + * + * @see ::MBG_XFEATURE_NAMES + * @see ::MBG_XFEATURE_BUFFER + */ +enum MBG_XFEATURE_BITS +{ + MBG_XFEATURE_TLV_API, ///< Supports generic TLV API, see @ref group_tlv_api + MBG_XFEATURE_SAVE_CFG, ///< Supports the ::GPS_SAVE_CFG command + MBG_XFEATURE_LED_API, ///< Supports programmable LED API, see @ref group_led_api + MBG_XFEATURE_LNE_API, ///< Supports specific LNE API, see @ref group_lne_api + MBG_XFEATURE_PWR_CTL_API, ///< Supports power control, see @ref group_pwr_ctl_api + MBG_XFEATURE_EXT_SYS_INFO, ///< Supports extended revision information, see @ref group_ext_sys_info + MBG_XFEATURE_TRANSACTIONS, ///< Supports the ::GPS_BEGIN_TRANSACTION and ::GPS_END_TRANSACTION commands, see also ::MBG_TRANSACTION_TYPES + MBG_XFEATURE_REBOOT, ///< Supports the ::GPS_REBOOT command + MBG_XFEATURE_CLK_RES_INFO, ///< Supports the ::GPS_CLK_RES_INFO command, see @ref group_clk_res_info + MBG_XFEATURE_UCAP_NET, ///< Supports the ::GPS_UCAP_NET_GLB_INFO and ::GPS_UCAP_NET_RECV_INFO_IDX commands, see @ref group_ucap_net + MBG_XFEATURE_REQ_TTM, ///< Supports TTM requests via GPS_TIME command + MBG_XFEATURE_IO_PORTS, ///< Supports I/O port structures, see @ref group_io_ports + MBG_XFEATURE_MONITORING, ///< Supports monitoring / notifications, see @ref group_monitoring + MBG_XFEATURE_XHE, ///< Supports XHE external rubidium unit I/O commands + MBG_XFEATURE_USB_LOCK, ///< Supports USB interrupt structures, see @ref group_usb_lock + N_MBG_XFEATURE ///< Number of defined extended features + // NOTE If new features are appended here then an appropriate feature + // name string has to be appended to ::MBG_XFEATURE_NAMES, and care must + // be taken that ::N_MBG_XFEATURE doesn't exceed ::MAX_XFEATURE_BITS. +}; + + + +/** + * @brief Names of extended device features + * + * Can be used to initialize a string array of ::N_MBG_XFEATURE entries, + * so the number of strings must correspond to ::N_MBG_XFEATURE. + * + * @see ::MBG_XFEATURE_BITS + */ +#define MBG_XFEATURE_NAMES \ +{ \ + "Generic TLV API", \ + "Save Config On Card", \ + "Programmable LED API", \ + "LNE API", \ + "Power Control API", \ + "Extended Revision Info", \ + "Transaction commands", \ + "Reboot command", \ + "Clock Resolution Info", \ + "Extended User Captures", \ + "Request TTM", \ + "I/O Ports", \ + "Monitoring", \ + "XHE unit", \ + "USB lock" \ +} + + + +/** + * @brief Array size required to store all extended features + * + * The number of bytes required to store up to ::MAX_XFEATURE_BITS + * feature bits in a byte array. + */ +#define MAX_XFEATURE_BYTES ( MAX_XFEATURE_BITS / 8 ) + + + +/** + * @brief A structure used to store extended device features. + * + * Up to ::MAX_XFEATURE_BITS totally can be stored, but only + * ::N_MBG_XFEATURE extended features are currently defined. + * The ::_set_xfeature_bit macro should be used by the firmware + * to set a feature bit in the buffer, and the ::check_xfeature + * function should be used to implement API calls which test if an + * extended feature is supported. + * + * @see ::_set_xfeature_bit + * @see ::check_xfeature + */ +typedef struct +{ + uint8_t b[MAX_XFEATURE_BYTES]; + +} MBG_XFEATURE_BUFFER; + + + +/** + * @brief Set an extended feature bit in a ::MBG_XFEATURE_BUFFER + * + * Should be used by the firmware only to set one of the ::MBG_XFEATURE_BITS + * in an ::MBG_XFEATURE_BUFFER after power-up. + * + * @param[in] _xf_bit One of the ::MBG_XFEATURE_BITS + * @param[in] _xf_buffp Pointer to an ::MBG_XFEATURE_BUFFER + */ +#define _set_xfeature_bit( _xf_bit, _xf_buffp ) \ + _set_array_bit( _xf_bit, (_xf_buffp)->b, MAX_XFEATURE_BYTES ) + + +/** @} defgroup group_xfeature */ + /* @@ -969,16 +2343,32 @@ enum } -/* - * Codes to be used with RECEIVER_INFO::flags: +/** + * @brief Bits used to define ::RECEIVER_INFO_FLAG_MASKS */ -#define GPS_OSC_CFG_SUPP 0x0001 // GPS_OSC_CFG supported -#define GPS_IRIG_FO_IN 0x0002 // IRIG input via fiber optics -#define GPS_HAS_FPGA 0x0004 // device provides on-board FPGA +enum RECEIVER_INFO_FLAG_BITS +{ + GPS_BIT_OSC_CFG_SUPP, ///< oscillator cfg is supported, see ::RECEIVER_INFO::osc_type + GPS_BIT_IRIG_FO_IN, ///< IRIG input via fiber optics + GPS_BIT_HAS_FPGA, ///< device provides on-board FPGA + N_RECEIVER_INFO_FLAG_BITS ///< number of known bits +}; + + +/** + * @brief Bit masks to be used with ::RECEIVER_INFO::flags + */ +enum RECEIVER_INFO_FLAG_MASKS +{ + GPS_OSC_CFG_SUPP = ( 1UL << GPS_BIT_OSC_CFG_SUPP ), ///< see ::GPS_BIT_OSC_CFG_SUPP + GPS_IRIG_FO_IN = ( 1UL << GPS_BIT_IRIG_FO_IN ), ///< see ::GPS_BIT_IRIG_FO_IN + GPS_HAS_FPGA = ( 1UL << GPS_BIT_HAS_FPGA ) ///< see ::GPS_BIT_HAS_FPGA +}; + /* - * If the GPS_HAS_FPGA flag is set in RECEIVER_INFO::flags then the card + * If the ::GPS_HAS_FPGA flag is set in ::RECEIVER_INFO::flags then the card * provides an FPGA and the following information about the FPGA is available: */ #define FPGA_NAME_LEN 31 // max name length @@ -992,11 +2382,7 @@ typedef union { CSUM csum; uint32_t fsize; - #if _IS_MBG_FIRMWARE - uint32_t start_addr; - #else - uint8_t *start_addr; - #endif + uint32_t start_addr; char name[FPGA_NAME_SIZE]; } hdr; @@ -1014,6 +2400,7 @@ typedef struct { CSUM csum; uint16_t fpga_start_seg; // Number of the 4k block where an FPGA image is located + } FPGA_START_INFO; #define DEFAULT_FPGA_START_SEG 0x60 @@ -1027,172 +2414,202 @@ typedef struct /** - Date and time referred to the linear time scale defined by GPS. - GPS time is defined by the number of weeks since midnight from - January 5, 1980 to January 6, 1980 plus the number of seconds of - the current week plus fractions of a second. GPS time differs from - UTC because UTC is corrected with leap seconds while GPS time scale - is continuous. -*/ + * @brief A structure used to hold time in GPS format + * + * Date and time refer to the linear time scale defined by GPS, with + * the epoch starting at %UTC midnight at the beginning of January 6, 1980. + * + * GPS time is counted by the week numbers since the epoch, plus second + * of the week, plus fraction of the second. The week number transmitted + * by the satellites rolls over from 1023 to 0, but Meinberg devices + * just continue to count the weeks beyond the 1024 week limit to keep + * the receiver's internal time. + * + * %UTC time differs from GPS time since a number of leap seconds have + * been inserted in the %UTC time scale after the GPS epoch. The number + * of leap seconds is disseminated by the satellites using the ::UTC + * parameter set, which also provides info on pending leap seconds. + */ typedef struct { - uint16_t wn; /**< the week number since GPS has been installed */ - uint32_t sec; /**< the second of that week */ - uint32_t tick; /**< fractions of a second; scale: 1/GPS_TICKS_PER_SEC */ + uint16_t wn; ///< the week number since the GPS system has been put into operation + uint32_t sec; ///< the second of that week + uint32_t tick; ///< fractions of a second, 1/::RECEIVER_INFO::ticks_per_sec units + } T_GPS; #define _mbg_swab_t_gps( _p ) \ +do \ { \ _mbg_swab16( &(_p)->wn ); \ _mbg_swab32( &(_p)->sec ); \ _mbg_swab32( &(_p)->tick ); \ -} +} while ( 0 ) /** - Local date and time computed from GPS time. The current number - of leap seconds have to be added to get UTC from GPS time. - Additional corrections could have been made according to the - time zone/daylight saving parameters (TZDL, see below) defined - by the user. The status field can be checked to see which corrections - have been applied. -*/ + * @brief Local date and time computed from GPS time + * + * The current number of leap seconds have to be added to get %UTC + * from GPS time. Additional corrections could have been made according + * to the time zone/daylight saving parameters ::TZDL defined by the user. + * The status field can be checked to see which corrections + * have actually been applied. + * + * @note Conversion from GPS time to %UTC and/or local time can only be + * done if some valid ::UTC correction parameters are available in the + * receiver's non-volatile memory. + */ typedef struct { - int16_t year; /**< year number, 0..9999 */ - int8_t month; /**< month, 1..12 */ - int8_t mday; /**< day of month, 1..31 */ - int16_t yday; /**< day of year, 1..366 */ - int8_t wday; /**< day of week, 0..6 == Sun..Sat */ - int8_t hour; /**< hours, 0..23 */ - int8_t min; /**< minutes, 0..59 */ - int8_t sec; /**< seconds, 0..59 */ - int32_t frac; /**< fractions of a second; scale: 1/GPS_TICKS_PER_SEC */ - int32_t offs_from_utc; /**< local time's offset from UTC */ - uint16_t status; /**< status flags */ + int16_t year; ///< year number, 0..9999 + int8_t month; ///< month, 1..12 + int8_t mday; ///< day of month, 1..31 + int16_t yday; ///< day of year, 1..365, or 366 in case of leap year + int8_t wday; ///< day of week, 0..6 == Sun..Sat + int8_t hour; ///< hours, 0..23 + int8_t min; ///< minutes, 0..59 + int8_t sec; ///< seconds, 0..59, or 60 in case of inserted leap second + int32_t frac; ///< fractions of a second, 1/::RECEIVER_INFO::ticks_per_sec units + int32_t offs_from_utc; ///< local time offset from %UTC [sec] + uint16_t status; ///< status flags, see ::TM_GPS_STATUS_BIT_MASKS + } TM_GPS; #define _mbg_swab_tm_gps( _p ) \ +do \ { \ _mbg_swab16( &(_p)->year ); \ _mbg_swab16( &(_p)->yday ); \ _mbg_swab32( &(_p)->frac ); \ _mbg_swab32( &(_p)->offs_from_utc ); \ _mbg_swab16( &(_p)->status ); \ -} - +} while ( 0 ) -/* status flag bits used with conversion from GPS time to local time */ -enum +/** + * @brief Status flag bits used to define ::TM_GPS_STATUS_BIT_MASKS + * + * These bits report info on the time conversion from GPS time to %UTC + * and/or local time as well as device status info. + * + * @see ::TM_GPS_STATUS_BIT_MASKS + */ +enum TM_GPS_STATUS_BITS { - TM_BIT_UTC, /* UTC correction has been made */ - TM_BIT_LOCAL, /* UTC has been converted to local time */ - TM_BIT_DL_ANN, /* state of daylight saving is going to change */ - TM_BIT_DL_ENB, /* daylight saving is enabled */ - TM_BIT_LS_ANN, /* leap second will be inserted */ - TM_BIT_LS_ENB, /* current second is leap second */ - TM_BIT_LS_ANN_NEG, /* set in addition to TM_LS_ANN if leap sec negative */ - TM_BIT_INVT, /* invalid time, e.g. if RTC battery empty */ - - TM_BIT_EXT_SYNC, /* sync'd externally */ - TM_BIT_HOLDOVER, /* holdover mode after previous sync. */ - TM_BIT_ANT_SHORT, /* antenna cable short circuited */ - TM_BIT_NO_WARM, /* OCXO has not warmed up */ - TM_BIT_ANT_DISCONN, /* antenna currently disconnected */ - TM_BIT_SYN_FLAG, /* TIME_SYN output is low */ - TM_BIT_NO_SYNC, /* time sync actually not verified */ - TM_BIT_NO_POS /* position actually not verified, LOCK LED off */ -}; - -// Type of an extended TM status which is mainly used by the firmware. -typedef uint32_t TM_STATUS_EXT; // extended status, mainly used by the firmware - -// The lower 16 bits of the TM_STATUS_X type correspond to those defined above, -// and the upper bits are defined below: -enum + TM_BIT_UTC, ///< %UTC correction has been made + TM_BIT_LOCAL, ///< %UTC has been converted to local time according to ::TZDL settings + TM_BIT_DL_ANN, ///< state of daylight saving is going to change + TM_BIT_DL_ENB, ///< daylight saving is in effect + TM_BIT_LS_ANN, ///< leap second pending + TM_BIT_LS_ENB, ///< current second is leap second + TM_BIT_LS_ANN_NEG, ///< set in addition to ::TM_BIT_LS_ANN if leap sec is negative + TM_BIT_INVT, ///< invalid time, e.g. if RTC battery bas been empty + + TM_BIT_EXT_SYNC, ///< synchronized externally + TM_BIT_HOLDOVER, ///< in holdover mode after previous synchronization + TM_BIT_ANT_SHORT, ///< antenna cable short circuited + TM_BIT_NO_WARM, ///< oscillator control loop not settled + TM_BIT_ANT_DISCONN, ///< antenna currently disconnected + TM_BIT_SYN_FLAG, ///< clock not synchronized, reflects the state of the "time sync error" output pin + TM_BIT_NO_SYNC, ///< time sync actually not verified + TM_BIT_NO_POS ///< position actually not verified, LOCK LED off +}; + + +/** + * @brief Status flag masks used with ::TM_GPS::status + * + * These bits report info on the time conversion from GPS time to %UTC + * and/or local time as well as device status info. + * + * @see ::TM_GPS_STATUS_BITS + */ +enum TM_GPS_STATUS_BIT_MASKS { - TM_BIT_SCALE_GPS = 16, - TM_BIT_SCALE_TAI - // the remaining bits are reserved + TM_UTC = ( 1UL << TM_BIT_UTC ), ///< see ::TM_BIT_UTC + TM_LOCAL = ( 1UL << TM_BIT_LOCAL ), ///< see ::TM_BIT_LOCAL + TM_DL_ANN = ( 1UL << TM_BIT_DL_ANN ), ///< see ::TM_BIT_DL_ANN + TM_DL_ENB = ( 1UL << TM_BIT_DL_ENB ), ///< see ::TM_BIT_DL_ENB + TM_LS_ANN = ( 1UL << TM_BIT_LS_ANN ), ///< see ::TM_BIT_LS_ANN + TM_LS_ENB = ( 1UL << TM_BIT_LS_ENB ), ///< see ::TM_BIT_LS_ENB + TM_LS_ANN_NEG = ( 1UL << TM_BIT_LS_ANN_NEG ), ///< see ::TM_BIT_LS_ANN_NEG + TM_INVT = ( 1UL << TM_BIT_INVT ), ///< see ::TM_BIT_INVT + + TM_EXT_SYNC = ( 1UL << TM_BIT_EXT_SYNC ), ///< see ::TM_BIT_EXT_SYNC + TM_HOLDOVER = ( 1UL << TM_BIT_HOLDOVER ), ///< see ::TM_BIT_HOLDOVER + TM_ANT_SHORT = ( 1UL << TM_BIT_ANT_SHORT ), ///< see ::TM_BIT_ANT_SHORT + TM_NO_WARM = ( 1UL << TM_BIT_NO_WARM ), ///< see ::TM_BIT_NO_WARM + TM_ANT_DISCONN = ( 1UL << TM_BIT_ANT_DISCONN ), ///< see ::TM_BIT_ANT_DISCONN + TM_SYN_FLAG = ( 1UL << TM_BIT_SYN_FLAG ), ///< see ::TM_BIT_SYN_FLAG + TM_NO_SYNC = ( 1UL << TM_BIT_NO_SYNC ), ///< see ::TM_BIT_NO_SYNC + TM_NO_POS = ( 1UL << TM_BIT_NO_POS ) ///< see ::TM_BIT_NO_POS }; -/* bit masks corresponding to the flag bits above */ -#define TM_UTC ( 1UL << TM_BIT_UTC ) -#define TM_LOCAL ( 1UL << TM_BIT_LOCAL ) -#define TM_DL_ANN ( 1UL << TM_BIT_DL_ANN ) -#define TM_DL_ENB ( 1UL << TM_BIT_DL_ENB ) -#define TM_LS_ANN ( 1UL << TM_BIT_LS_ANN ) -#define TM_LS_ENB ( 1UL << TM_BIT_LS_ENB ) -#define TM_LS_ANN_NEG ( 1UL << TM_BIT_LS_ANN_NEG ) -#define TM_INVT ( 1UL << TM_BIT_INVT ) +/** + * @brief Type of an extended TM status which is mainly used inside the firmware + */ +typedef uint32_t TM_STATUS_EXT; -#define TM_EXT_SYNC ( 1UL << TM_BIT_EXT_SYNC ) -#define TM_HOLDOVER ( 1UL << TM_BIT_HOLDOVER ) -#define TM_ANT_SHORT ( 1UL << TM_BIT_ANT_SHORT ) -#define TM_NO_WARM ( 1UL << TM_BIT_NO_WARM ) -#define TM_ANT_DISCONN ( 1UL << TM_BIT_ANT_DISCONN ) -#define TM_SYN_FLAG ( 1UL << TM_BIT_SYN_FLAG ) -#define TM_NO_SYNC ( 1UL << TM_BIT_NO_SYNC ) -#define TM_NO_POS ( 1UL << TM_BIT_NO_POS ) +/** + * @brief Enumeration of extended status bits used with ::TM_STATUS_EXT + * + * @note The lower 16 bits correspond to ::TM_GPS_STATUS_BITS + */ +enum TM_GPS_STATUS_BITS_EX +{ + TM_BIT_SCALE_GPS = 16, ///< time scale configured to return GPS time + TM_BIT_SCALE_TAI ///< time scale configured to return TAI + // the remaining bits are reserved +}; -// The following bits are only used with the TM_STATUS_X type: +// The following bits are only used with the ::TM_STATUS_X type: #define TM_SCALE_GPS ( 1UL << TM_BIT_SCALE_GPS ) #define TM_SCALE_TAI ( 1UL << TM_BIT_SCALE_TAI ) #define TM_MSK_TIME_VALID ( TM_UTC | TM_SCALE_GPS | TM_SCALE_TAI ) + /** * @brief A structure used to transmit information on date and time + * + * This structure can be used to transfer the current time, in which + * case the channel field has to be set to -1, or an event capture time + * retrieved from the on-board FIFO, in which case the channel field + * contains the index of the time capture input, e.g. 0 or 1. */ typedef struct { - int16_t channel; /**< -1: the current time; 0, 1: capture 0, 1 */ - T_GPS t; /**< time in GPS format */ - TM_GPS tm; /**< that time converted to local time */ + int16_t channel; ///< -1: the current on-board time; >= 0 the capture channel number + T_GPS t; ///< time in GPS scale and format + TM_GPS tm; ///< time converted to %UTC and/or local time according to ::TZDL settings + } TTM; #define _mbg_swab_ttm( _p ) \ +do \ { \ _mbg_swab16( &(_p)->channel ); \ _mbg_swab_t_gps( &(_p)->t ); \ _mbg_swab_tm_gps( &(_p)->tm ); \ -} - +} while ( 0 ) -typedef struct -{ - int32_t nano_secs; // [nanoseconds] - int32_t secs; // [seconds] -} NANO_TIME; - -#define _mbg_swab_nano_time( _p ) \ -{ \ - _mbg_swab32( &(_p)->nano_secs ); \ - _mbg_swab32( &(_p)->secs ); \ -} - -// The macro below checks if a NANO_TIME value is negative. -#define _nano_time_negative( _nt ) \ - ( ( (_nt)->secs < 0 ) || ( (_nt)->nano_secs < 0 ) ) - - - -/* Two types of variables used to store a position. Type XYZ is */ -/* used with a position in earth centered, earth fixed (ECEF) */ -/* coordinates whereas type LLA holds such a position converted */ -/* to geographic coordinates as defined by WGS84 (World Geodetic */ -/* System from 1984). */ #ifndef _XYZ_DEFINED - /* sequence and number of components of a cartesian position */ - enum { XP, YP, ZP, N_XYZ }; + /** + * @brief Sequence and number of components of a cartesian position + */ + enum XYZ_FIELDS { XP, YP, ZP, N_XYZ }; // x, y, z - /** @brief An array holding a cartesian position */ - typedef double XYZ[N_XYZ]; /**< values are in [m] */ + /** + * @brief A position in cartesian coordinates + * + * Usually earth centered, earth fixed (ECEF) coordinates. + */ + typedef double XYZ[N_XYZ]; ///< values are in [m], see ::XYZ_FIELDS #define _XYZ_DEFINED #endif @@ -1201,11 +2618,20 @@ typedef struct #ifndef _LLA_DEFINED - /* sequence and number of components of a geographic position */ - enum { LAT, LON, ALT, N_LLA }; /* latitude, longitude, altitude */ - - /** @brief An array holding a geographic position */ - typedef double LLA[N_LLA]; /**< lon, lat in [rad], alt in [m] */ + /** + * @brief Sequence and number of components of a geographic position + */ + enum LLA_FIELDS { LAT, LON, ALT, N_LLA }; /* latitude, longitude, altitude */ + + /** + * @brief A geographic position based on latitude, longitude, and altitude + * + * The geographic position associated to specific cartesian coordinates + * depends on the characteristics of the ellipsoid used for the computation, + * the so-called geographic datum. GPS uses the WGS84 (World Geodetic System + * from 1984) ellipsoid by default. + */ + typedef double LLA[N_LLA]; ///< lon, lat in [rad], alt in [m], see ::LLA_FIELDS #define _LLA_DEFINED #endif @@ -1214,65 +2640,74 @@ typedef struct /** - @defgroup group_synth Synthesizer parameters - - Synthesizer frequency is expressed as a - four digit decimal number (freq) to be multiplied by 0.1 Hz and an - base 10 exponent (range). If the effective frequency is less than - 10 kHz its phase is synchronized corresponding to the variable phase. - Phase may be in a range from -360 deg to +360 deg with a resolution - of 0.1 deg, so the resulting numbers to be stored are in a range of - -3600 to +3600. - - Example:<br> - Assume the value of freq is 2345 (decimal) and the value of phase is 900. - If range == 0 the effective frequency is 234.5 Hz with a phase of +90 deg. - If range == 1 the synthesizer will generate a 2345 Hz output frequency - and so on. - - Limitations:<br> - If freq == 0 the synthesizer is disabled. If range == 0 the least - significant digit of freq is limited to 0, 3, 5 or 6. The resulting - frequency is shown in the examples below: - - freq == 1230 --> 123.0 Hz - - freq == 1233 --> 123 1/3 Hz (real 1/3 Hz, NOT 123.3 Hz) - - freq == 1235 --> 123.5 Hz - - freq == 1236 --> 123 2/3 Hz (real 2/3 Hz, NOT 123.6 Hz) - - If range == MAX_RANGE the value of freq must not exceed 1000, so the - output frequency is limited to 10 MHz. - @{ -*/ + * @defgroup group_synth Synthesizer parameters + * + * Synthesizer frequency is expressed as a + * four digit decimal number (freq) to be multiplied by 0.1 Hz and an + * base 10 exponent (range). If the effective frequency is less than + * 10 kHz its phase is synchronized corresponding to the variable phase. + * Phase may be in a range from -360 deg to +360 deg with a resolution + * of 0.1 deg, so the resulting numbers to be stored are in a range of + * -3600 to +3600. + * + * Example:<br> + * Assume the value of freq is 2345 (decimal) and the value of phase is 900. + * If range == 0 the effective frequency is 234.5 Hz with a phase of +90 deg. + * If range == 1 the synthesizer will generate a 2345 Hz output frequency + * and so on. + * + * Limitations:<br> + * If freq == 0 the synthesizer is disabled. If range == 0 the least + * significant digit of freq is limited to 0, 3, 5 or 6. The resulting + * frequency is shown in the examples below: + * - freq == 1230 --> 123.0 Hz + * - freq == 1233 --> 123 1/3 Hz (real 1/3 Hz, NOT 123.3 Hz) + * - freq == 1235 --> 123.5 Hz + * - freq == 1236 --> 123 2/3 Hz (real 2/3 Hz, NOT 123.6 Hz) + * + * If range == ::MAX_SYNTH_RANGE the value of freq must not exceed 1000, so + * the output frequency is limited to 10 MHz (see ::MAX_SYNTH_FREQ_VAL). + * + * @{ */ -#define N_SYNTH_FREQ_DIGIT 4 /**< number of digits to edit */ -#define MAX_SYNTH_FREQ 1000 /**< if range == MAX_SYNTH_RANGE */ +#define N_SYNTH_FREQ_DIGIT 4 ///< number of digits to edit +#define MAX_SYNTH_FREQ 1000 ///< if range == ::MAX_SYNTH_RANGE #define MIN_SYNTH_RANGE 0 #define MAX_SYNTH_RANGE 5 #define N_SYNTH_RANGE ( MAX_SYNTH_RANGE - MIN_SYNTH_RANGE + 1 ) -#define N_SYNTH_PHASE_DIGIT 4 -#define MAX_SYNTH_PHASE 3600 +#define N_SYNTH_PHASE_DIGIT 4 +#define MAX_SYNTH_PHASE 3600 + +#define MAX_SYNTH_FREQ_EDIT 9999 ///< max sequence of digits when editing -#define MAX_SYNTH_FREQ_EDIT 9999 /**< max sequence of digits when editing */ -/** @brief The maximum frequency that can be configured for the synthesizer */ -#define MAX_SYNTH_FREQ_VAL 10000000UL /**< 10 MHz */ +/** + * @brief The maximum frequency that can be configured for the synthesizer + */ +#define MAX_SYNTH_FREQ_VAL 10000000UL ///< 10 MHz /* == MAX_SYNTH_FREQ * 10^(MAX_SYNTH_RANGE-1) */ -/** @brief The synthesizer's phase is only be synchronized if the frequency is below this limit */ -#define SYNTH_PHASE_SYNC_LIMIT 10000UL /**< 10 kHz */ +/** + * @brief The synthesizer's phase is only be synchronized if the frequency is below this limit + */ +#define SYNTH_PHASE_SYNC_LIMIT 10000UL ///< 10 kHz /** - the position of the decimal point if the frequency is - printed as 4 digit value */ + * A Macro used to determine the position of the decimal point + * when printing the synthesizer frequency as 4 digit value + */ #define _synth_dp_pos_from_range( _r ) \ ( ( ( N_SYNTH_RANGE - (_r) ) % ( N_SYNTH_FREQ_DIGIT - 1 ) ) + 1 ) /** - An initializer for commonly displayed synthesizer frequency units - (N_SYNTH_RANGE strings) */ + * @brief Synthesizer frequency units + * + * An initializer for commonly displayed synthesizer frequency units + * (::N_SYNTH_RANGE strings) + */ #define DEFAULT_FREQ_RANGES \ { \ "Hz", \ @@ -1285,86 +2720,118 @@ typedef struct +/** + * @brief Synthesizer configuration parameters + */ typedef struct { - int16_t freq; /**< four digits used; scale: 0.1; e.g. 1234 -> 123.4 Hz */ - int16_t range; /**< scale factor for freq; 0..MAX_SYNTH_RANGE */ - int16_t phase; /**< -MAX_SYNTH_PHASE..+MAX_SYNTH_PHASE; >0 -> pulses later */ + int16_t freq; ///< four digits used; scale: 0.1 Hz; e.g. 1234 -> 123.4 Hz + int16_t range; ///< scale factor for freq; 0..::MAX_SYNTH_RANGE + int16_t phase; ///< -::MAX_SYNTH_PHASE..+::MAX_SYNTH_PHASE; >0 -> pulses later + } SYNTH; #define _mbg_swab_synth( _p ) \ +do \ { \ _mbg_swab16( &(_p)->freq ); \ _mbg_swab16( &(_p)->range ); \ _mbg_swab16( &(_p)->phase ); \ -} +} while ( 0 ) /** - The definitions below can be used to query the - current synthesizer state. + * @brief Enumeration of synthesizer states */ -enum +enum SYNTH_STATES { - SYNTH_DISABLED, /**< disbled by cfg, i.e. freq == 0.0 */ - SYNTH_OFF, /**< not enabled after power-up */ - SYNTH_FREE, /**< enabled, but not synchronized */ - SYNTH_DRIFTING, /**< has initially been sync'd, but now running free */ - SYNTH_SYNC, /**< fully synchronized */ - N_SYNTH_STATE /**< the number of known states */ + SYNTH_DISABLED, ///< disbled by cfg, i.e. freq == 0.0 + SYNTH_OFF, ///< not enabled after power-up + SYNTH_FREE, ///< enabled, but not synchronized + SYNTH_DRIFTING, ///< has initially been sync'd, but now running free + SYNTH_SYNC, ///< fully synchronized + N_SYNTH_STATE ///< the number of known states }; + +/** + * @brief A structure used to report the synthesizer state + */ typedef struct { - uint8_t state; /**< state code as enumerated above */ - uint8_t flags; /**< reserved, currently always 0 */ + uint8_t state; ///< state code as enumerated in ::SYNTH_STATES + uint8_t flags; ///< reserved, currently always 0 + } SYNTH_STATE; #define _mbg_swab_synth_state( _p ) _nop_macro_fnc() #define SYNTH_FLAG_PHASE_IGNORED 0x01 -/** @} group_synth */ +/** @} defgroup group_synth */ -/** - @defgroup group_tzdl Time zone/daylight saving parameters - Example: <br> - For automatic daylight saving enable/disable in Central Europe, - the variables are to be set as shown below: <br> - - offs = 3600L one hour from UTC - - offs_dl = 3600L one additional hour if daylight saving enabled - - tm_on = first Sunday from March 25, 02:00:00h ( year |= DL_AUTO_FLAG ) - - tm_off = first Sunday from October 25, 03:00:00h ( year |= DL_AUTO_FLAG ) - - name[0] == "CET " name if daylight saving not enabled - - name[1] == "CEST " name if daylight saving is enabled - @{ -*/ -/** the name of a time zone, 5 characters plus trailing zero */ +/** + * @defgroup group_tzdl Time zone / daylight saving parameters + * + * Example: <br> + * For automatic daylight saving enable/disable in Central Europe, + * the variables are to be set as shown below: <br> + * - offs = 3600L one hour from %UTC + * - offs_dl = 3600L one additional hour if daylight saving enabled + * - tm_on = first Sunday from March 25, 02:00:00h ( year |= ::DL_AUTO_FLAG ) + * - tm_off = first Sunday from October 25, 03:00:00h ( year |= ::DL_AUTO_FLAG ) + * - name[0] == "CET " name if daylight saving not enabled + * - name[1] == "CEST " name if daylight saving is enabled + * + * @{ */ + +/** + * @brief The name of a time zone + * + * @note Up to 5 printable characters, plus trailing zero + */ typedef char TZ_NAME[6]; +/** + * @brief Time zone / daylight saving parameters + * + * This structure is used to specify how a device converts on-board %UTC + * to local time, including computation of beginning and end of daylight + * saving time (DST), if required. + * + * @note The ::TZDL structure contains members of type ::TM_GPS to specify + * the times for beginning and end of DST. However, the ::TM_GPS::frac, + * ::TM_GPS::offs_from_utc, and ::TM_GPS::status fields of these ::TZDL::tm_on + * and ::TZDL::tm_off members are ignored for the conversion to local time, + * and thus should be 0. + */ typedef struct { - int32_t offs; /**< offset from UTC to local time [sec] */ - int32_t offs_dl; /**< additional offset if daylight saving enabled [sec] */ - TM_GPS tm_on; /**< date/time when daylight saving starts */ - TM_GPS tm_off; /**< date/time when daylight saving ends */ - TZ_NAME name[2]; /**< names without and with daylight saving enabled */ + int32_t offs; ///< standard offset from %UTC to local time [sec] + int32_t offs_dl; ///< additional offset if daylight saving enabled [sec] + TM_GPS tm_on; ///< date/time when daylight saving starts + TM_GPS tm_off; ///< date/time when daylight saving ends + TZ_NAME name[2]; ///< names without and with daylight saving enabled + } TZDL; #define _mbg_swab_tzdl( _p ) \ +do \ { \ _mbg_swab32( &(_p)->offs ); \ _mbg_swab32( &(_p)->offs_dl ); \ _mbg_swab_tm_gps( &(_p)->tm_on ); \ _mbg_swab_tm_gps( &(_p)->tm_off ); \ -} +} while ( 0 ) /** - If the year in tzdl.tm_on and tzdl.tm_off is or'ed with that constant, - the receiver automatically generates daylight saving year by year. + * @brief A flag indicating automatic computation of DST + * + * If this flag is or'ed to the year numbers in ::TZDL::tm_on and ::TZDL::tm_off + * then daylight saving is computed automatically year by year. */ #define DL_AUTO_FLAG 0x8000 @@ -1372,20 +2839,20 @@ typedef struct // Below there are some initializers for commonly used TZDL configurations: -#define DEFAULT_TZDL_AUTO_YEAR ( 2007 | DL_AUTO_FLAG ) +#define DEFAULT_TZDL_AUTO_YEAR ( (int16_t) ( 2007L | DL_AUTO_FLAG ) ) -#define DEFAULt_TZDL_OFFS_DL 3600L /**< usually DST is +1 hour */ +#define DEFAULt_TZDL_OFFS_DL 3600L ///< usually DST is +1 hour /** - The symbol below can be used to initialize both the tm_on - and tm_off fields for time zones which do not switch to DST: + * An initializer for ::TZDL::tm_on and ::TZDL::tm_off for time zones + * which do not observe DST. */ #define DEFAULT_TZDL_TM_ON_OFF_NO_DST \ { DEFAULT_TZDL_AUTO_YEAR, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 } -// Settings used with UTC: +// Settings used with %UTC: #define TZ_INFO_UTC "UTC (Universal Time, Coordinated)" @@ -1393,22 +2860,23 @@ typedef struct #define DEFAULT_TZDL_UTC \ { \ - 0L, /**< offs */ \ - 0L, /**< offs_dl */ \ - DEFAULT_TZDL_TM_ON_OFF_NO_DST, /**< tm_on */ \ - DEFAULT_TZDL_TM_ON_OFF_NO_DST, /**< tm_off */ \ - DEFAULT_TZDL_NAMES_UTC /**< name[] */ \ + 0L, /* offs */ \ + 0L, /* offs_dl */ \ + DEFAULT_TZDL_TM_ON_OFF_NO_DST, /* tm_on */ \ + DEFAULT_TZDL_TM_ON_OFF_NO_DST, /* tm_off */ \ + DEFAULT_TZDL_NAMES_UTC /* name */ \ } /** - The symbols below specify beginning and end of DST for - Central Europe, as constituted by the European Parliament: - */ - + * @brief An initializer for ::TZDL::tm_on according to the rules for Central Europe + */ #define DEFAULT_TZDL_TM_ON_CET_CEST \ { DEFAULT_TZDL_AUTO_YEAR, 3, 25, 0, 0, 2, 0, 0, 0L, 0L, 0 } +/** + * @brief An initializer for ::TZDL::tm_off according to the rules for Central Europe + */ #define DEFAULT_TZDL_TM_OFF_CET_CEST \ { DEFAULT_TZDL_AUTO_YEAR, 10, 25, 0, 0, 3, 0, 0, 0L, 0L, 0 } @@ -1425,20 +2893,20 @@ typedef struct #define DEFAULT_TZDL_CET_CEST_EN \ { \ - DEFAULT_TZDL_OFFS_CET, /**< offs */ \ - DEFAULt_TZDL_OFFS_DL, /**< offs_dl */ \ - DEFAULT_TZDL_TM_ON_CET_CEST, /**< tm_on */ \ - DEFAULT_TZDL_TM_OFF_CET_CEST, /**< tm_off */ \ - DEFAULT_TZDL_NAMES_CET_CEST_EN /**< name[] */ \ + DEFAULT_TZDL_OFFS_CET, /* offs */ \ + DEFAULt_TZDL_OFFS_DL, /* offs_dl */ \ + DEFAULT_TZDL_TM_ON_CET_CEST, /* tm_on */ \ + DEFAULT_TZDL_TM_OFF_CET_CEST, /* tm_off */ \ + DEFAULT_TZDL_NAMES_CET_CEST_EN /* name */ \ } #define DEFAULT_TZDL_CET_CEST_DE \ { \ - DEFAULT_TZDL_OFFS_CET, /**< offs */ \ - DEFAULt_TZDL_OFFS_DL, /**< offs_dl */ \ - DEFAULT_TZDL_TM_ON_CET_CEST, /**< tm_on */ \ - DEFAULT_TZDL_TM_OFF_CET_CEST, /**< tm_off */ \ - DEFAULT_TZDL_NAMES_CET_CEST_DE /**< name[] */ \ + DEFAULT_TZDL_OFFS_CET, /* offs */ \ + DEFAULt_TZDL_OFFS_DL, /* offs_dl */ \ + DEFAULT_TZDL_TM_ON_CET_CEST, /* tm_on */ \ + DEFAULT_TZDL_TM_OFF_CET_CEST, /* tm_off */ \ + DEFAULT_TZDL_NAMES_CET_CEST_DE /* name */ \ } @@ -1468,7 +2936,7 @@ typedef struct DEFAULt_TZDL_OFFS_DL, /* offs_dl */ \ DEFAULT_TZDL_TM_ON_EET_EEST, /* tm_on */ \ DEFAULT_TZDL_TM_OFF_EET_EEST, /* tm_off */ \ - DEFAULT_TZDL_NAMES_EET_EEST_EN /* name[] */ \ + DEFAULT_TZDL_NAMES_EET_EEST_EN /* name */ \ } #define DEFAULT_TZDL_EET_EEST_DE \ @@ -1477,96 +2945,136 @@ typedef struct DEFAULt_TZDL_OFFS_DL, /* offs_dl */ \ DEFAULT_TZDL_TM_ON_EET_EEST, /* tm_on */ \ DEFAULT_TZDL_TM_OFF_EET_EEST, /* tm_off */ \ - DEFAULT_TZDL_NAMES_EET_EEST_DE /* name[] */ \ + DEFAULT_TZDL_NAMES_EET_EEST_DE /* name */ \ } -/** @} group_tzdl */ +/** @} defgroup group_tzdl */ + + /** + * @brief Antenna status and error at reconnect information + * * The structure below reflects the status of the antenna, * the times of last disconnect/reconnect, and the board's - * clock offset after the disconnection interval. + * clock offset when it has synchronized again after the + * disconnection interval. + * + * @note ::ANT_INFO::status changes back to ::ANT_RECONN only + * after the antenna has been reconnected <b>and</b> the + * receiver has re-synchronized to the satellite signal. + * In this case ::ANT_INFO::delta_t reports the time offset + * before resynchronization, i.e. how much the internal + * time has drifted while the antenna was disconnected. */ typedef struct { - int16_t status; /**< current status of antenna */ - TM_GPS tm_disconn; /**< time of antenna disconnect */ - TM_GPS tm_reconn; /**< time of antenna reconnect */ - int32_t delta_t; /**< clock offs. at reconn. time in #GPS_TICKS_PER_SEC */ + int16_t status; ///< current status of antenna, see ::ANT_STATUS_CODES + TM_GPS tm_disconn; ///< time of antenna disconnect + TM_GPS tm_reconn; ///< time of antenna reconnect + int32_t delta_t; ///< clock offs at reconn. time in 1/::RECEIVER_INFO::ticks_per_sec units + } ANT_INFO; #define _mbg_swab_ant_info( _p ) \ +do \ { \ _mbg_swab16( &(_p)->status ); \ _mbg_swab_tm_gps( &(_p)->tm_disconn ); \ _mbg_swab_tm_gps( &(_p)->tm_reconn ); \ _mbg_swab32( &(_p)->delta_t ); \ -} +} while ( 0 ) /** - The status field may be set to one of the values below: -*/ -enum + * @brief Status code used with ::ANT_INFO::status + */ +enum ANT_STATUS_CODES { - ANT_INVALID, /**< struct not set yet because ant. has not been disconn. */ - ANT_DISCONN, /**< ant. now disconn., tm_reconn and delta_t not set */ - ANT_RECONN /**< ant. has been disconn. and reconn., all fields valid */ + ANT_INVALID, ///< No other fields valid since antenna has not yet been disconnected + ANT_DISCONN, ///< Antenna is disconnected, tm_reconn and delta_t not yet set + ANT_RECONN, ///< Antenna has been disconnect, and receiver sync. after reconnect, so all fields valid + N_ANT_STATUS_CODES ///< the number of known status codes }; -/* Defines used with ENABLE_FLAGS */ - -#define EF_OFF 0x00 /**< outputs off until sync'd */ -#define EF_SERIAL_BOTH 0x03 /**< both serial ports on */ -#define EF_PULSES_BOTH 0x03 /**< both pulses P_SEC and P_MIN on */ -#define EF_FREQ_ALL 0x07 /**< all fixed freq. outputs on */ -#define EF_SYNTH 0x01 /**< synth. on */ /** - The structure holds some flags which let - the corresponding outputs be disabled after power-up until - the receiver has synchronized (flag == 0x00, the default) or force - the outputs to be enabled immediately after power-up. The fixed - frequency output is hard-wired to be enabled immediately after - power-up, so the code for freq must always be 0x03. -*/ + * @brief A structure controlling when output signals are enabled + * + * The structure holds some flags which let the corresponding outputs + * be disabled after power-up until the receiver has synchronized + * (flags == ::EF_OFF, the default) or force the outputs to be enabled + * immediately after power-up. The fixed frequency output is hard-wired + * to be enabled immediately after power-up, so ::ENABLE_FLAGS::freq must + * always be set to ::EF_FREQ_ALL. + */ typedef struct { - uint16_t serial; /**< #EF_OFF or #EF_SERIAL_BOTH */ - uint16_t pulses; /**< #EF_OFF or #EF_PULSES_BOTH */ - uint16_t freq; /**< always #EF_FREQ_ALL */ - uint16_t synth; /**< #EF_OFF or #EF_SYNTH */ + uint16_t serial; ///< ::EF_OFF or ::EF_SERIAL_BOTH + uint16_t pulses; ///< ::EF_OFF or ::EF_PULSES_BOTH + uint16_t freq; ///< always ::EF_FREQ_ALL + uint16_t synth; ///< ::EF_OFF or ::EF_SYNTH + } ENABLE_FLAGS; #define _mbg_swab_enable_flags( _p ) \ +do \ { \ _mbg_swab16( &(_p)->serial ); \ _mbg_swab16( &(_p)->pulses ); \ _mbg_swab16( &(_p)->freq ); \ _mbg_swab16( &(_p)->synth ); \ -} +} while ( 0 ) + + +/** + * @brief Codes used with ::ENABLE_FLAGS + **/ +enum ENABLE_FLAGS_CODES +{ + EF_OFF = 0x00, ///< associated outputs off until synchronized + + EF_SERIAL_BOTH = 0x03, ///< both serial ports on, use with ::ENABLE_FLAGS::serial + EF_PULSES_BOTH = 0x03, ///< both pulses P_SEC and P_MIN on, use with ::ENABLE_FLAGS::pulses + EF_FREQ_ALL = 0x07, ///< all fixed freq. outputs on, use with ::ENABLE_FLAGS::freq + EF_SYNTH = 0x01 ///< synthesizer on, use with ::ENABLE_FLAGS::synth +}; -/* A struct used to hold the settings of a serial port: */ #ifndef _COM_HS_DEFINED - /* types of handshake */ - enum { HS_NONE, HS_XONXOFF, HS_RTSCTS, N_COM_HS }; + /** + * @brief Enumeration of handshake modes + */ + enum COM_HANSHAKE_MODES { HS_NONE, HS_XONXOFF, HS_RTSCTS, N_COM_HS }; #define _COM_HS_DEFINED #endif #ifndef _COM_PARM_DEFINED + /** + * @brief A data type to configure a serial port's baud rate + * + * @see ::MBG_BAUD_RATES + */ typedef int32_t BAUD_RATE; - /* indices used to identify a parameter in the framing string */ - enum { F_DBITS, F_PRTY, F_STBITS }; + /** + * @brief Indices used to identify a parameter in the framing string + * + * @see ::MBG_FRAMING_STRS + */ + enum MBG_FRAMING_STR_IDXS { F_DBITS, F_PRTY, F_STBITS }; + /** + * @brief A structure to store the configuration of a serial port + */ typedef struct { - BAUD_RATE baud_rate; /* e.g. 19200L */ - char framing[4]; /* e.g. "8N1" */ - int16_t handshake; /* a numeric value, only HS_NONE supported yet */ + BAUD_RATE baud_rate; ///< transmission speed, e.g. 19200L, see ::MBG_BAUD_RATES + char framing[4]; ///< ASCIIZ framing string, e.g. "8N1" or "7E2", see ::MBG_FRAMING_STRS + int16_t handshake; ///< handshake mode, yet only ::HS_NONE supported + } COM_PARM; #define _COM_PARM_DEFINED @@ -1575,18 +3083,22 @@ typedef struct #define _mbg_swab_baud_rate( _p ) _mbg_swab32( _p ) #define _mbg_swab_com_parm( _p ) \ +do \ { \ _mbg_swab_baud_rate( &(_p)->baud_rate ); \ _mbg_swab16( &(_p)->handshake ); \ -} +} while ( 0 ) -/* - * Indices of any supported baud rates. - * Note that not each baud rate must be supported by - * any clock model and/or port: +/** + * @brief Enumeration of serial port baud rates + * + * @note Most clock models and/or serial ports don't support all defined baud rates. + * + * @see ::MBG_BAUD_RATES + * @see ::MBG_BAUD_RATE_MASKS */ -enum +enum MBG_BAUD_RATE_CODES { MBG_BAUD_RATE_300, MBG_BAUD_RATE_600, @@ -1596,12 +3108,23 @@ enum MBG_BAUD_RATE_9600, MBG_BAUD_RATE_19200, MBG_BAUD_RATE_38400, - N_MBG_BAUD_RATES /* the number of supported baud rates */ + MBG_BAUD_RATE_57600, + MBG_BAUD_RATE_115200, + MBG_BAUD_RATE_230400, + MBG_BAUD_RATE_460800, + MBG_BAUD_RATE_921600, + N_MBG_BAUD_RATES ///< the number of known baud rates }; -/* - * An initializer for a table of baud rate values. - * The values must correspond to the enumeration above. +/** + * @brief An initializer for a table of baud rate values + * + * These values can be used with ::COM_PARM::baud_rate, if the device + * supports the particular baud rate. + * + * The values must correspond to the enumeration ::MBG_BAUD_RATE_CODES + * + * @see ::MBG_BAUD_RATE_CODES */ #define MBG_BAUD_RATES \ { \ @@ -1612,12 +3135,20 @@ enum 4800L, \ 9600L, \ 19200L, \ - 38400L \ + 38400L, \ + 57600L, \ + 115200L, \ + 230400L, \ + 460800L, \ + 921600L \ } -/* - * An initializer for a table of baud rate strings. - * The values must correspond to the enumeration above. +/** + * @brief An initializer for a table of baud rate strings + * + * The values must correspond to the enumeration ::MBG_BAUD_RATE_CODES + * + * @see ::MBG_BAUD_RATE_CODES */ #define MBG_BAUD_STRS \ { \ @@ -1628,32 +3159,49 @@ enum "4800", \ "9600", \ "19200", \ - "38400" \ + "38400", \ + "57600", \ + "115200", \ + "230400", \ + "460800", \ + "921600" \ } -/* - * The bit masks below can be used to determine which baud rates - * are supported by a serial port. This may vary between - * different ports of the same device since different - * types of UART are used which must not necessarily support - * each baud rate: - */ -#define MBG_PORT_HAS_300 ( 1UL << MBG_BAUD_RATE_300 ) -#define MBG_PORT_HAS_600 ( 1UL << MBG_BAUD_RATE_600 ) -#define MBG_PORT_HAS_1200 ( 1UL << MBG_BAUD_RATE_1200 ) -#define MBG_PORT_HAS_2400 ( 1UL << MBG_BAUD_RATE_2400 ) -#define MBG_PORT_HAS_4800 ( 1UL << MBG_BAUD_RATE_4800 ) -#define MBG_PORT_HAS_9600 ( 1UL << MBG_BAUD_RATE_9600 ) -#define MBG_PORT_HAS_19200 ( 1UL << MBG_BAUD_RATE_19200 ) -#define MBG_PORT_HAS_38400 ( 1UL << MBG_BAUD_RATE_38400 ) +/** + * @brief Bit masks associated with baud rates enumerated in ::MBG_BAUD_RATE_CODES + * + * These bit masks are used e.g. with ::PORT_INFO::supp_baud_rates to + * determine which baud rates are supported by a particular serial port. + * + * @see ::MBG_BAUD_RATE_CODES + * @see ::MBG_FRAMING_MASKS + */ +enum MBG_BAUD_RATE_MASKS +{ + MBG_PORT_HAS_300 = ( 1UL << MBG_BAUD_RATE_300 ), ///< see ::MBG_BAUD_RATE_300 + MBG_PORT_HAS_600 = ( 1UL << MBG_BAUD_RATE_600 ), ///< see ::MBG_BAUD_RATE_600 + MBG_PORT_HAS_1200 = ( 1UL << MBG_BAUD_RATE_1200 ), ///< see ::MBG_BAUD_RATE_1200 + MBG_PORT_HAS_2400 = ( 1UL << MBG_BAUD_RATE_2400 ), ///< see ::MBG_BAUD_RATE_2400 + MBG_PORT_HAS_4800 = ( 1UL << MBG_BAUD_RATE_4800 ), ///< see ::MBG_BAUD_RATE_4800 + MBG_PORT_HAS_9600 = ( 1UL << MBG_BAUD_RATE_9600 ), ///< see ::MBG_BAUD_RATE_9600 + MBG_PORT_HAS_19200 = ( 1UL << MBG_BAUD_RATE_19200 ), ///< see ::MBG_BAUD_RATE_19200 + MBG_PORT_HAS_38400 = ( 1UL << MBG_BAUD_RATE_38400 ), ///< see ::MBG_BAUD_RATE_38400 + MBG_PORT_HAS_57600 = ( 1UL << MBG_BAUD_RATE_57600 ), ///< see ::MBG_BAUD_RATE_57600 + MBG_PORT_HAS_115200 = ( 1UL << MBG_BAUD_RATE_115200 ), ///< see ::MBG_BAUD_RATE_115200 + MBG_PORT_HAS_230400 = ( 1UL << MBG_BAUD_RATE_230400 ), ///< see ::MBG_BAUD_RATE_230400 + MBG_PORT_HAS_460800 = ( 1UL << MBG_BAUD_RATE_460800 ), ///< see ::MBG_BAUD_RATE_460800 + MBG_PORT_HAS_921600 = ( 1UL << MBG_BAUD_RATE_921600 ) ///< see ::MBG_BAUD_RATE_921600 +}; -/* - * Indices of any supported framings. - * Note that not each framing must be supported by - * any clock model and/or port: +/** + * @brief Enumeration of all known serial port framings + * + * @note Most clock models and/or serial ports don't support all defined framing types. + * + * @see ::MBG_FRAMING_STRS */ -enum +enum MBG_FRAMING_CODES { MBG_FRAMING_7N2, MBG_FRAMING_7E1, @@ -1664,12 +3212,21 @@ enum MBG_FRAMING_7O1, MBG_FRAMING_7O2, MBG_FRAMING_8O1, - N_MBG_FRAMINGS /* the number of supported framings */ + MBG_FRAMING_8E2, ///< Note: most serial ports don't support this! + N_MBG_FRAMINGS ///< the number of known framings }; -/* - * An initializer for a table of framing strings. - * The values must correspond to the enumeration above. +/** + * @brief An initializer for a table of known framing strings + * + * These values can be used with ::COM_PARM::framing, if the device + * supports the particular framing. + * + * The values must correspond to the enumeration ::MBG_FRAMING_CODES + * + * @see ::MBG_FRAMING_CODES + * @see ::MBG_FRAMING_MASKS + * @see ::MBG_FRAMING_STR_IDXS */ #define MBG_FRAMING_STRS \ { \ @@ -1681,25 +3238,80 @@ enum "8E1", \ "7O1", \ "7O2", \ - "8O1" \ + "8O1", \ + "8E2" \ } -/* - * The bit masks below can be used to determine which framings - * are supported by a serial port. This may vary between - * different ports of the same device since different - * types of UART are used which must not necessarily support - * each framing type: +/** + * @brief Bit masks associated with framings enumerated in ::MBG_FRAMING_CODES + * + * These bit masks are used e.g. with ::PORT_INFO::supp_framings to + * determine which framings are supported by a particular serial port. + * + * @see ::MBG_FRAMING_CODES + * @see ::MBG_FRAMING_STRS + */ +enum MBG_FRAMING_MASKS +{ + MBG_PORT_HAS_7N2 = ( 1UL << MBG_FRAMING_7N2 ), ///< see ::MBG_FRAMING_7N2 + MBG_PORT_HAS_7E1 = ( 1UL << MBG_FRAMING_7E1 ), ///< see ::MBG_FRAMING_7E1 + MBG_PORT_HAS_7E2 = ( 1UL << MBG_FRAMING_7E2 ), ///< see ::MBG_FRAMING_7E2 + MBG_PORT_HAS_8N1 = ( 1UL << MBG_FRAMING_8N1 ), ///< see ::MBG_FRAMING_8N1 + MBG_PORT_HAS_8N2 = ( 1UL << MBG_FRAMING_8N2 ), ///< see ::MBG_FRAMING_8N2 + MBG_PORT_HAS_8E1 = ( 1UL << MBG_FRAMING_8E1 ), ///< see ::MBG_FRAMING_8E1 + MBG_PORT_HAS_7O1 = ( 1UL << MBG_FRAMING_7O1 ), ///< see ::MBG_FRAMING_7O1 + MBG_PORT_HAS_7O2 = ( 1UL << MBG_FRAMING_7O2 ), ///< see ::MBG_FRAMING_7O2 + MBG_PORT_HAS_8O1 = ( 1UL << MBG_FRAMING_8O1 ), ///< see ::MBG_FRAMING_8O1 + MBG_PORT_HAS_8E2 = ( 1UL << MBG_FRAMING_8E2 ) ///< see ::MBG_FRAMING_8E2 +}; + + + +/** + * @brief Definitions used with the Meinberg binary protocol + * + * @anchor GPS_BIN_PROT_DEFS @{ */ + +/** + * @brief Framing used with the binary protocol + * + * Different data length, or parity settings would corrupt + * the binary data. + */ +#define MBG_DEFAULT_FRAMING "8N1" + +/** + * @brief The standard baud rate used for the binary protocol + * + * This is supported by most devices. Some new devices may also + * support ::MBG_DEFAULT_BAUDRATE_HS + */ +#define MBG_DEFAULT_BAUDRATE 19200L + +/** + * @brief The high speed baud rate used for the binary protocol + * + * This is not supported by older devices which work + * with ::MBG_DEFAULT_BAUDRATE only. */ -#define MBG_PORT_HAS_7N2 ( 1UL << MBG_FRAMING_7N2 ) -#define MBG_PORT_HAS_7E1 ( 1UL << MBG_FRAMING_7E1 ) -#define MBG_PORT_HAS_7E2 ( 1UL << MBG_FRAMING_7E2 ) -#define MBG_PORT_HAS_8N1 ( 1UL << MBG_FRAMING_8N1 ) -#define MBG_PORT_HAS_8N2 ( 1UL << MBG_FRAMING_8N2 ) -#define MBG_PORT_HAS_8E1 ( 1UL << MBG_FRAMING_8E1 ) -#define MBG_PORT_HAS_7O1 ( 1UL << MBG_FRAMING_7O1 ) -#define MBG_PORT_HAS_7O2 ( 1UL << MBG_FRAMING_7O2 ) -#define MBG_PORT_HAS_8O1 ( 1UL << MBG_FRAMING_8O1 ) +#define MBG_DEFAULT_BAUDRATE_HS 115200L + + +/** + * @brief Strings used to force connection settings for the binary protocol + * + * If a device supports this and receives one of these ASCII strings + * then it temporarily switches the serial port to some well-known + * baud rate and framing appropriate for the binary protocol. + * + * @anchor GPS_BIN_PROT_CMD_STRS @{ */ + +#define MBG_FORCE_CONN_CMD_STR "\nDFC\n" ///< switch to ::MBG_DEFAULT_BAUDRATE +#define MBG_FORCE_CONN_HS_CMD_STR "\nDFCHS\n" ///< switch to ::MBG_DEFAULT_BAUDRATE_HS + +/** @} anchor GPS_BIN_PROT_CMD_STRS */ + +/** @} anchor GPS_BIN_PROT_DEFS */ @@ -1756,106 +3368,136 @@ enum ) -/* - * The structure below is more flexible if different receiver - * models have different numbers of serial ports, so the old - * structure PORT_PARM will become obsolete. +/** + * @brief Configuration settings of a serial port + * + * @note This should be used preferably instead of + * ::PORT_PARM, which is deprecated. */ typedef struct { - COM_PARM parm; /* speed, framing, etc. */ - uint8_t mode; /* per second, per minute, etc. */ - uint8_t str_type; /* type of the output string */ - uint32_t flags; /* reserved for future use, currently 0 */ + COM_PARM parm; ///< transmission speed, framing, etc. + uint8_t mode; ///< string mode, see ::STR_MODES + uint8_t str_type; ///< index of the supported time string formats, see ::STR_TYPE_INFO_IDX + uint32_t flags; ///< reserved, don't use, currently 0 + } PORT_SETTINGS; #define _mbg_swab_port_settings( _p ) \ +do \ { \ _mbg_swab_com_parm( &(_p)->parm ); \ _mbg_swab32( &(_p)->flags ); \ -} +} while ( 0 ) -/* - * The definitions below can be used to mark specific fields of a - * PORT_SETTINGS structure, e.g. when editing build a mask indicating - * which of the fields have changed or which are not valid. +/** + * @brief Flag bits used to mark individual ::PORT_SETTINGS fields + * + * These definitions can be used to mark specific fields of a + * ::PORT_SETTINGS structure, e.g. which fields have changed when + * editing, or which fields have settings which are not valid. */ -enum +enum MBG_COM_CFG_STATUS_BITS { - MBG_PS_BIT_BAUD_RATE_OVR_SW, /* Baud rate index exceeds num supp by driver SW */ - MBG_PS_BIT_BAUD_RATE_OVR_DEV, /* Baud rate index exceeds num supp by device */ - MBG_PS_BIT_BAUD_RATE, /* Baud rate not supp by given port */ - MBG_PS_BIT_FRAMING_OVR_SW, /* Framing index exceeds num supp by driver SW */ - MBG_PS_BIT_FRAMING_OVR_DEV, /* Framing index exceeds num supp by device */ - MBG_PS_BIT_FRAMING, /* Framing not supp by given port */ - MBG_PS_BIT_HS_OVR_SW, /* Handshake index exceeds num supp by driver SW */ - MBG_PS_BIT_HS, /* Handshake mode not supp by given port */ - MBG_PS_BIT_STR_TYPE_OVR_SW, /* String type index exceeds num supp by driver SW */ - MBG_PS_BIT_STR_TYPE_OVR_DEV, /* String type index exceeds num supp by device */ - MBG_PS_BIT_STR_TYPE, /* String type not supp by given port */ - MBG_PS_BIT_STR_MODE_OVR_SW, /* String mode index exceeds num supp by driver SW */ - MBG_PS_BIT_STR_MODE_OVR_DEV, /* String mode index exceeds num supp by device */ - MBG_PS_BIT_STR_MODE, /* String mode not supp by given port and string type */ - MBG_PS_BIT_FLAGS_OVR_SW, /* Flags not supp by driver SW */ - MBG_PS_BIT_FLAGS, /* Flags not supp by device */ + MBG_PS_BIT_BAUD_RATE_OVR_SW, ///< Baud rate index exceeds num supp by driver SW + MBG_PS_BIT_BAUD_RATE_OVR_DEV, ///< Baud rate index exceeds num supp by device + MBG_PS_BIT_BAUD_RATE, ///< Baud rate not supp by given port + MBG_PS_BIT_FRAMING_OVR_SW, ///< Framing index exceeds num supp by driver SW + MBG_PS_BIT_FRAMING_OVR_DEV, ///< Framing index exceeds num supp by device + MBG_PS_BIT_FRAMING, ///< Framing not supp by given port + MBG_PS_BIT_HS_OVR_SW, ///< Handshake index exceeds num supp by driver SW + MBG_PS_BIT_HS, ///< Handshake mode not supp by given port + MBG_PS_BIT_STR_TYPE_OVR_SW, ///< String type index exceeds num supp by driver SW + MBG_PS_BIT_STR_TYPE_OVR_DEV, ///< String type index exceeds num supp by device + MBG_PS_BIT_STR_TYPE, ///< String type not supp by given port + MBG_PS_BIT_STR_MODE_OVR_SW, ///< String mode index exceeds num supp by driver SW + MBG_PS_BIT_STR_MODE_OVR_DEV, ///< String mode index exceeds num supp by device + MBG_PS_BIT_STR_MODE, ///< String mode not supp by given port and string type + MBG_PS_BIT_FLAGS_OVR_SW, ///< Flags not supp by driver SW + MBG_PS_BIT_FLAGS, ///< Flags not supp by device N_MBG_PS_BIT }; -#define MBG_PS_MSK_BAUD_RATE_OVR_SW ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_SW ) -#define MBG_PS_MSK_BAUD_RATE_OVR_DEV ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_DEV ) -#define MBG_PS_MSK_BAUD_RATE ( 1UL << MBG_PS_BIT_BAUD_RATE ) -#define MBG_PS_MSK_FRAMING_OVR_SW ( 1UL << MBG_PS_BIT_FRAMING_OVR_SW ) -#define MBG_PS_MSK_FRAMING_OVR_DEV ( 1UL << MBG_PS_BIT_FRAMING_OVR_DEV ) -#define MBG_PS_MSK_FRAMING ( 1UL << MBG_PS_BIT_FRAMING ) -#define MBG_PS_MSK_HS_OVR_SW ( 1UL << MBG_PS_BIT_HS_OVR_SW ) -#define MBG_PS_MSK_HS ( 1UL << MBG_PS_BIT_HS ) -#define MBG_PS_MSK_STR_TYPE_OVR_SW ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_SW ) -#define MBG_PS_MSK_STR_TYPE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_DEV ) -#define MBG_PS_MSK_STR_TYPE ( 1UL << MBG_PS_BIT_STR_TYPE ) -#define MBG_PS_MSK_STR_MODE_OVR_SW ( 1UL << MBG_PS_BIT_STR_MODE_OVR_SW ) -#define MBG_PS_MSK_STR_MODE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_MODE_OVR_DEV ) -#define MBG_PS_MSK_STR_MODE ( 1UL << MBG_PS_BIT_STR_MODE ) -#define MBG_PS_MSK_FLAGS_OVR_SW ( 1UL << MBG_PS_BIT_FLAGS_OVR_SW ) -#define MBG_PS_MSK_FLAGS ( 1UL << MBG_PS_BIT_FLAGS ) +/** + * @brief Flag bit masks associated with ::MBG_COM_CFG_STATUS_BITS + * + * These definitions can be used to mark specific fields of a + * ::PORT_SETTINGS structure, e.g. which fields have changed when + * editing, or which fields have settings which are not valid. + * + * @anchor MBG_COM_CFG_STATUS_MASKS @{ */ +#define MBG_PS_MSK_BAUD_RATE_OVR_SW ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_SW ) ///< see ::MBG_PS_BIT_BAUD_RATE_OVR_SW +#define MBG_PS_MSK_BAUD_RATE_OVR_DEV ( 1UL << MBG_PS_BIT_BAUD_RATE_OVR_DEV ) ///< see ::MBG_PS_BIT_BAUD_RATE_OVR_DEV +#define MBG_PS_MSK_BAUD_RATE ( 1UL << MBG_PS_BIT_BAUD_RATE ) ///< see ::MBG_PS_BIT_BAUD_RATE +#define MBG_PS_MSK_FRAMING_OVR_SW ( 1UL << MBG_PS_BIT_FRAMING_OVR_SW ) ///< see ::MBG_PS_BIT_FRAMING_OVR_SW +#define MBG_PS_MSK_FRAMING_OVR_DEV ( 1UL << MBG_PS_BIT_FRAMING_OVR_DEV ) ///< see ::MBG_PS_BIT_FRAMING_OVR_DEV +#define MBG_PS_MSK_FRAMING ( 1UL << MBG_PS_BIT_FRAMING ) ///< see ::MBG_PS_BIT_FRAMING +#define MBG_PS_MSK_HS_OVR_SW ( 1UL << MBG_PS_BIT_HS_OVR_SW ) ///< see ::MBG_PS_BIT_HS_OVR_SW +#define MBG_PS_MSK_HS ( 1UL << MBG_PS_BIT_HS ) ///< see ::MBG_PS_BIT_HS +#define MBG_PS_MSK_STR_TYPE_OVR_SW ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_SW ) ///< see ::MBG_PS_BIT_STR_TYPE_OVR_SW +#define MBG_PS_MSK_STR_TYPE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_TYPE_OVR_DEV ) ///< see ::MBG_PS_BIT_STR_TYPE_OVR_DEV +#define MBG_PS_MSK_STR_TYPE ( 1UL << MBG_PS_BIT_STR_TYPE ) ///< see ::MBG_PS_BIT_STR_TYPE +#define MBG_PS_MSK_STR_MODE_OVR_SW ( 1UL << MBG_PS_BIT_STR_MODE_OVR_SW ) ///< see ::MBG_PS_BIT_STR_MODE_OVR_SW +#define MBG_PS_MSK_STR_MODE_OVR_DEV ( 1UL << MBG_PS_BIT_STR_MODE_OVR_DEV ) ///< see ::MBG_PS_BIT_STR_MODE_OVR_DEV +#define MBG_PS_MSK_STR_MODE ( 1UL << MBG_PS_BIT_STR_MODE ) ///< see ::MBG_PS_BIT_STR_MODE +#define MBG_PS_MSK_FLAGS_OVR_SW ( 1UL << MBG_PS_BIT_FLAGS_OVR_SW ) ///< see ::MBG_PS_BIT_FLAGS_OVR_SW +#define MBG_PS_MSK_FLAGS ( 1UL << MBG_PS_BIT_FLAGS ) ///< see ::MBG_PS_BIT_FLAGS +/** @} anchor MBG_COM_CFG_STATUS_MASKS */ -/* - * The structure below adds an index number to the structure - * above to allow addressing of several instances: + + +/** + * @brief Configuration settings of a specific serial port + * + * This structure should be sent to a device to configure + * a specific serial port. The number of supported ports + * is ::RECEIVER_INFO::n_com_ports. + * + * @note The ::PORT_INFO_IDX structure should be read from + * a device to retrieve the current settings and capabilities. + * + * @see ::STR_TYPE_INFO */ typedef struct { - uint16_t idx; /* 0..RECEIVER_INFO.n_com_port-1 */ + uint16_t idx; ///< port index, 0..::RECEIVER_INFO::n_com_ports-1 PORT_SETTINGS port_settings; + } PORT_SETTINGS_IDX; #define _mbg_swab_port_settings_idx( _p ) \ +do \ { \ _mbg_swab16( &(_p)->idx ); \ _mbg_swab_port_settings( &(_p)->port_settings ); \ -} +} while ( 0 ) -/* - * The structure below holds the current settings - * for a port, plus additional informaton on the - * port's capabilities. This can be read by setup - * programs to allow setup of supported features - * only. +/** + * @brief Current settings and general capabilities of a serial port + * + * @note This structure should be read from a device to retrieve + * the current settings of a serial port plus its capabilities, + * e.g. supported baud rates, supported string formats, etc. + * + * @see ::STR_TYPE_INFO */ typedef struct { - PORT_SETTINGS port_settings; /* COM port settings as defined above */ - uint32_t supp_baud_rates; /* bit mask of baud rates supp. by this port */ - uint32_t supp_framings; /* bit mask of framings supp. by this port */ - uint32_t supp_str_types; /* bit mask, bit 0 set if str_type[0] supp. */ - uint32_t reserved; /* reserved for future use, currently 0 */ - uint32_t flags; /* reserved for future use, currently 0 */ + PORT_SETTINGS port_settings; ///< current configuration of the port + uint32_t supp_baud_rates; ///< bit mask of baud rates supp. by this port, see ::MBG_BAUD_RATE_MASKS + uint32_t supp_framings; ///< bit mask of framings supp. by this port, see ::MBG_FRAMING_MASKS + uint32_t supp_str_types; ///< bit mask of string types supp. by this port, i.e. bit 0 set if str_type[0] is supp. + uint32_t reserved; ///< reserved for future use, currently always 0 + uint32_t flags; ///< see ::PORT_INFO_FLAGS + } PORT_INFO; #define _mbg_swab_port_info( _p ) \ +do \ { \ _mbg_swab_port_settings( &(_p)->port_settings ); \ _mbg_swab32( &(_p)->supp_baud_rates ); \ @@ -1863,80 +3505,159 @@ typedef struct _mbg_swab32( &(_p)->supp_str_types ); \ _mbg_swab32( &(_p)->reserved ); \ _mbg_swab32( &(_p)->flags ); \ -} +} while ( 0 ) -/* - * The structure below adds an index number to the structure - * above to allow addressing of several instances: +/** + * @brief Flags bits used to define ::PORT_INFO_FLAGS + * + * @see ::PORT_INFO_FLAGS + */ +enum PORT_INFO_FLAG_BITS +{ + PORT_INFO_FLAG_BIT_PORT_INVISIBLE, ///< port is used internally and should not be displayed by config apps + PORT_INFO_FLAG_BIT_BIN_PROT_HS, ///< port supports binary protocol at high speed, see ::MBG_DEFAULT_BAUDRATE_HS + N_PORT_INFO_FLAG_BITS ///< the number of defined bits +}; + + +/** + * @brief Bit masks used with ::PORT_INFO::flags + * + * @see ::PORT_INFO_FLAG_BITS + */ +enum PORT_INFO_FLAGS +{ + PORT_INFO_FLAG_PORT_INVISIBLE = ( 1UL << PORT_INFO_FLAG_BIT_PORT_INVISIBLE ), ///< see ::PORT_INFO_FLAG_BIT_PORT_INVISIBLE + PORT_INFO_FLAG_BIN_PROT_HS = ( 1UL << PORT_INFO_FLAG_BIT_BIN_PROT_HS ) ///< see ::PORT_INFO_FLAG_BIT_BIN_PROT_HS +}; + + +/** + * @brief Current settings and general capabilities of a specific serial port + * + * This structure should be read from the device to retrieve the + * current settings of a specific serial port plus its capabilities, + * e.g. supported baud rates, supported string formats, etc. + * The number of supported ports is ::RECEIVER_INFO::n_com_ports. + * + * @note The ::PORT_SETTINGS_IDX structure should be send back to + * the device to configure the specified serial port. */ typedef struct { - uint16_t idx; /* 0..RECEIVER_INFO.n_com_port-1 */ + uint16_t idx; ///< port index, 0..::RECEIVER_INFO::n_com_ports-1 PORT_INFO port_info; + } PORT_INFO_IDX; #define _mbg_swab_port_info_idx( _p ) \ +do \ { \ _mbg_swab16( &(_p)->idx ); \ _mbg_swab_port_info( &(_p)->port_info ); \ -} +} while ( 0 ) -/* - * The structure below keeps information for a given - * string type, e.g. which modes can be used with that - * string type: +/** + * @brief Information on a supported string format + * + * Information includes the name of the string format, which + * transmission modes are supported, etc. + * + * The number of string types, and which string types are supported + * depends on the device type and firmware version. + * + * @note Multiple structures ::STR_TYPE_INFO_IDX should be read + * to retrieve all supported string types. */ typedef struct { - uint32_t supp_modes; /* bit mask of modes supp. with this string type */ - char long_name[23]; /* long name of the string format */ - char short_name[11]; /* short name of the string format */ - uint16_t flags; /* reserved, currently always 0 */ + uint32_t supp_modes; ///< bit mask of modes supp. for this string type, see ::STR_MODE_MASKS + char long_name[23]; ///< long name of the string format + char short_name[11]; ///< short name of the string format + uint16_t flags; ///< reserved, currently always 0 + } STR_TYPE_INFO; #define _mbg_swab_str_type_info( _p ) \ +do \ { \ _mbg_swab32( &(_p)->supp_modes ); \ _mbg_swab16( &(_p)->flags ); \ -} +} while ( 0 ) -/* - * The structure below adds an index number to the structure - * above to allow addressing of several instances: +/** + * @brief Information on a specific supported string format + * + * This structure should be read from a device to retrieve information + * on a specific supported time string type from an array of supported + * string types. The number of supported string types is returned + * in ::RECEIVER_INFO::n_str_type. + * + * A selected index number can be saved in ::PORT_SETTINGS::str_type to + * configure the selected string type for the specific serial port. */ typedef struct { - uint16_t idx; /* 0..RECEIVER_INFO.n_str_type-1 */ + uint16_t idx; ///< string type index, 0..::RECEIVER_INFO::n_str_type-1 STR_TYPE_INFO str_type_info; + } STR_TYPE_INFO_IDX; #define _mbg_swab_str_type_info_idx( _p ) \ +do \ { \ _mbg_swab16( &(_p)->idx ); \ _mbg_swab_str_type_info( &(_p)->str_type_info ); \ -} +} while ( 0 ) -/* - * The codes below define valid modes for time strings, - * i.e. the condition when a string is being sent - * via the serial port: +/** + * @brief Enumeration of modes supported for time string transmission + * + * This determines e.g. at which point in time a string starts + * to be transmitted via the serial port. + * Used with ::PORT_SETTINGS::mode. + * + * @see ::STR_MODE_MASKS */ -enum +enum STR_MODES +{ + STR_ON_REQ, ///< transmission on request by received '?' character only + STR_PER_SEC, ///< transmission automatically if second changes + STR_PER_MIN, ///< transmission automatically if minute changes + STR_AUTO, ///< transmission automatically if required, e.g. on capture event + STR_ON_REQ_SEC, ///< transmission if second changes and a request has been received before + N_STR_MODE ///< the number of known modes +}; + + +/** + * @brief Bit masks associated with ::STR_MODES + * + * Used with ::STR_TYPE_INFO::supp_modes to indicate which + * transmission modes are supported by the particular string type. + * + * @see ::STR_MODES + */ +enum STR_MODE_MASKS { - STR_ON_REQ, /* on request only */ - STR_PER_SEC, /* automatically if second changes */ - STR_PER_MIN, /* automatically if minute changes */ - STR_AUTO, /* automatically if required, e.g. on capture event */ - STR_ON_REQ_SEC, /* if second changes and a request has been received */ - N_STR_MODE /* the number of valid modes */ + MSK_STR_ON_REQ = ( 1UL << STR_ON_REQ ), ///< see ::STR_ON_REQ + MSK_STR_PER_SEC = ( 1UL << STR_PER_SEC ), ///< see ::STR_PER_SEC + MSK_STR_PER_MIN = ( 1UL << STR_PER_MIN ), ///< see ::STR_PER_MIN + MSK_STR_AUTO = ( 1UL << STR_AUTO ), ///< see ::STR_AUTO + MSK_STR_ON_REQ_SEC = ( 1UL << STR_ON_REQ_SEC ) ///< see ::STR_ON_REQ_SEC }; +/** + * @brief Initializer for short name strings associated with ::STR_MODES + * + * @see ::STR_MODES + */ #define DEFAULT_SHORT_MODE_NAMES \ { \ "'?'", \ @@ -1947,9 +3668,12 @@ enum } -/* - * Default initializers for English mode string names. Initializers - * for multi-language strings can be found in pcpslstr.h. +/** + * @brief Default initializers for English mode name strings + * + * Initializers for multi-language strings can be found in pcpslstr.h. + * + * @see ::STR_MODES */ #define ENG_MODE_NAME_STR_ON_REQ "on request '?' only" #define ENG_MODE_NAME_STR_PER_SEC "per second" @@ -1957,6 +3681,14 @@ enum #define ENG_MODE_NAME_STR_AUTO "automatically" #define ENG_MODE_NAME_STR_ON_REQ_SEC "sec after request" + +/** + * @brief Initializer for an English mode name string table + * + * Initializers for multi-language strings can be found in pcpslstr.h. + * + * @see ::STR_MODES + */ #define DEFAULT_ENG_MODE_NAMES \ { \ ENG_MODE_NAME_STR_ON_REQ, \ @@ -1966,17 +3698,6 @@ enum ENG_MODE_NAME_STR_ON_REQ_SEC \ } -/* - * The definitions below are used to set up bit masks - * which restrict the modes which can be used with - * a given string type: - */ -#define MSK_STR_ON_REQ ( 1UL << STR_ON_REQ ) -#define MSK_STR_PER_SEC ( 1UL << STR_PER_SEC ) -#define MSK_STR_PER_MIN ( 1UL << STR_PER_MIN ) -#define MSK_STR_AUTO ( 1UL << STR_AUTO ) -#define MSK_STR_ON_REQ_SEC ( 1UL << STR_ON_REQ_SEC ) - /* * The modes below are supported by most string types: @@ -2001,8 +3722,56 @@ enum /** - * The number of serial ports which were available - * with all GPS receiver models: + * @brief The number of string types supported by legacy DCF77 receivers + * + * For receivers supporting a ::RECEIVER_INFO this should be determined + * from ::RECEIVER_INFO::n_str_type. + * + * @see ::DEFAULT_SUPP_STR_TYPES_DCF + */ +#define DEFAULT_N_STR_TYPE_DCF 1 + +/** + * @brief Bit mask of string types supported by legacy DCF77 receivers + * + * For receivers supporting a ::RECEIVER_INFO this should be determined + * from ::PORT_INFO::supp_str_types. + * + * @see ::DEFAULT_N_STR_TYPE_DCF + */ +#define DEFAULT_SUPP_STR_TYPES_DCF \ + ( ( 1UL << DEFAULT_N_STR_TYPE_DCF ) - 1 ) + + + +/** + * @brief The number of string types supported by legacy GPS receivers + * + * For receivers supporting a ::RECEIVER_INFO this should be determined + * from ::RECEIVER_INFO::n_str_type. + * + * @see ::DEFAULT_SUPP_STR_TYPES_GPS + */ +#define DEFAULT_N_STR_TYPE_GPS 2 + +/** + * @brief Bit mask of string types supported by legacy GPS receivers + * + * For receivers supporting a ::RECEIVER_INFO this should be determined + * from ::PORT_INFO::supp_str_types. + * + * @see ::DEFAULT_N_STR_TYPE_GPS + */ +#define DEFAULT_SUPP_STR_TYPES_GPS \ + ( ( 1UL << DEFAULT_N_STR_TYPE_GPS ) - 1 ) + + + +/* + * The number of serial ports which are at least available + * even with very old GPS receiver models. For devices providing + * a ::RECEIVER_INFO structure the number of provided COM ports + * is available in ::RECEIVER_INFO::n_com_ports. */ #define DEFAULT_N_COM 2 @@ -2015,16 +3784,20 @@ enum #endif /** - * The structure used to store the modes of both serial ports:<br> - * <b>(now obsolete)</b> + * @brief A The structure used to store the configuration of two serial ports + * + * @deprecated This structure is deprecated, ::PORT_SETTINGS and related structures + * should be used instead, if supported by the device. */ typedef struct { - COM_PARM com[DEFAULT_N_COM]; /**< COM0 and COM1 settings */ - uint8_t mode[DEFAULT_N_COM]; /**< COM0 and COM1 output mode */ + COM_PARM com[DEFAULT_N_COM]; ///< COM0 and COM1 settings + uint8_t mode[DEFAULT_N_COM]; ///< COM0 and COM1 output mode + } PORT_PARM; #define _mbg_swab_port_parm( _p ) \ +do \ { \ int i; \ for ( i = 0; i < DEFAULT_N_COM; i++ ) \ @@ -2032,13 +3805,17 @@ typedef struct _mbg_swab_com_parm( &(_p)->com[i] ); \ /* no need to swap mode byte */ \ } \ -} +} while ( 0 ) -/* - * The codes below were used with the obsolete - * PORT_PARM.mode above. They are defined for - * compatibility with older devices only: +/** + * @brief Deprecated codes for mode of operation + * + * @deprecated These codes have been used with the + * deprecated ::PORT_PARM::mode. They are only still + * defined for compatibility with older devices. + * + * @see ::STR_MODES */ enum { @@ -2054,75 +3831,135 @@ enum /** - @defgroup group_icode IRIG codes - - The following definitions are used to configure an optional - on-board IRIG input or output. Which frame types are supported - by a device depends on the device type, and may eventually - depend on the device's firmware version. - - All IRIG frames transport the day-of-year number plus the time-of-day, - and include a control field segment which can transport user defined - information. - - Some newer IRIG frames are compatible with older frame types but support - well defined extensions like the year number, local time offset, DST status, - etc., in the control fields: - - - Supported IRIG signal code types: - - \b A002: 1000 bps, DCLS, time-of-year - - \b A003: 1000 bps, DCLS, time-of-year, SBS - - \b A132: 1000 bps, 10 kHz carrier, time-of-year - - \b A133: 1000 bps, 10 kHz carrier, time-of-year, SBS - - \b B002: 100 bps, DCLS, time-of-year - - \b B003: 100 bps, DCLS, time-of-year, SBS - - \b B122: 100 bps, 1 kHz carrier, time-of-year - - \b B123: 100 bps, 1 kHz carrier, time-of-year, SBS - - \b B006: 100 bps, DCLS, complete date - - \b B007: 100 bps, DCLS, complete date, SBS - - \b B126: 100 bps, 1 kHz carrier, complete date - - \b B127: 100 bps, 1 kHz carrier, complete date, SBS - - \b B220/1344: 100 bps, DCLS, manchester encoded, IEEE1344 extensions - - \b B222: 100 bps, DCLS, manchester encoded, time-of-year - - \b B223: 100 bps, DCLS, manchester encoded, time-of-year, SBS - - \b G002: 10 kbps, DCLS, time-of-year - - \b G142: 10 kbps, 100 kHz carrier, time-of-year - - \b G006: 10 kbps, DCLS, complete date - - \b G146: 10 kbps, 100 kHz carrier, complete date - - \b AFNOR: 100 bps, 1 kHz carrier, SBS, complete date - - <b> AFNOR DC:</b> 100 bps, DCLS, SBS, complete date - - \b IEEE1344: 100 bps, 1 kHz carrier, time-of-year, SBS, IEEE1344 extensions (B120) - - <b> IEEE1344 DC:</b> 100 bps, DCLS, time-of-year, SBS, IEEE1344 extensions (B000) - - \b C37.118: like IEEE1344, but UTC offset with reversed sign - - \b C37.118 DC: like IEEE1344 DC, but UTC offset with reversed sign - - - time-of-year: day-of-year, hours, minutes, seconds - - complete date: time-of-year plus year number - - SBS: straight binary seconds, second-of-day - - AFNOR codes are based on the french standard AFNOR NF S87-500 - - IEEE1344 codes are defined in IEEE standard 1344-1995. The code frame is compatible - with B002/B122 but provides some well defined extensions in the control field which - include a quality indicator (time figure of merit, TFOM), year number, DST and leap - second status, and local time offset from UTC. - - C37.118 codes are defined in IEEE standard C37.118-2005 which includes a revised version - of the IEEE 1344 standard from 1995. These codes provide the same extensions as IEEE 1344 - but unfortunately define the UTC offset with reversed sign. - - @note There are 3rd party IRIG devices out there which apply the UTC offset as specified - in C37.118, but claim to be compatible with IEEE 1344. So if local time is transmitted - by the IRIG signal then care must be taken that the UTC offset is evaluated by the IRIG - receiver in the same way as computed by the IRIG generator. Otherwise the UTC - time computed by the receiver may be <b>wrong</b>. - @{ - */ - -/** - * Definitions used with IRIG transmitters which usually output both - * the unmodulated and the modulated IRIG signals at the same time: */ -enum + * @defgroup group_icode IRIG time codes + * + * The following definitions are used to configure an optional + * on-board IRIG input or output. Which frame types are supported + * by a device depends on the device type, and may eventually + * depend on the device's firmware version. + * + * All IRIG frames transport the day-of-year number plus the time-of-day, + * and include a control field segment which can transport user defined + * information. + * + * Some newer IRIG frames are compatible with older frame types but support + * well defined extensions like the year number, local time offset, DST status, + * etc., in the control fields: + * + * The following specification can be found in IRIG Standard 200-04 (September 2004): + * + * Format A: 1k pps + * Format B: 100 pps + * Format D: 1 ppm + * Format E: 10 pps + * Format G: 10k pps + * Format H: 1 pps + * + * 1st digit: Modulation Frequency + * 0 Pulse width code + * 1 Sine wave, amplitude modulated + * 2 Manchester modulated + * + * 2nd digit: Frequency / Resolution + * 0: No carrier / index count interval + * 1: 100 Hz / 10 ms + * 2: 1 kHz / 1 ms + * 3: 10 kHz / 0.1 ms + * 4: 100 kHz / 10 ms + * 5: 1 MHz / 1 ms + * + * 3rd digit: Coded expressions + * 0: DOY+TOD, CF, SBS + * 1: DOY+TOD, CF + * 2: DOY+TOD + * 3: DOY+TOD, SBS + * 4: DOY+TOD, Year, CF, SBS + * 5: DOY+TOD, Year, CF + * 6: DOY+TOD, Year + * 7: DOY+TOD, Year, SBS + * + * + * Table of Permissible Code Formats + * + * Letter 1st digit 2nd digit 3rd digit + * ---------------------------------------------- + * A 0,1,2 0,3,4,5 0,1,2,3,4,5,6,7 + * B 0,1,2 0,2,3,4,5 0,1,2,3,4,5,6,7 + * D 0,1 0,1,2 1,2 + * E 0,1 0,1,2 1,2,5,6 + * G 0,1,2 0,4,5 1,2,5,6 + * H 0,1 0,1,2 1,2 + * + * - Known IRIG signal code types: + * - \b A002: 1000 bps, DCLS, time-of-year + * - \b A003: 1000 bps, DCLS, time-of-year, SBS + * - \b A132: 1000 bps, 10 kHz carrier, time-of-year + * - \b A133: 1000 bps, 10 kHz carrier, time-of-year, SBS + * - \b B002: 100 bps, DCLS, time-of-year + * - \b B003: 100 bps, DCLS, time-of-year, SBS + * - \b B122: 100 bps, 1 kHz carrier, time-of-year + * - \b B123: 100 bps, 1 kHz carrier, time-of-year, SBS + * - \b B006: 100 bps, DCLS, complete date + * - \b B007: 100 bps, DCLS, complete date, SBS + * - \b B126: 100 bps, 1 kHz carrier, complete date + * - \b B127: 100 bps, 1 kHz carrier, complete date, SBS + * - \b B220/1344: 100 bps, DCLS, manchester encoded, IEEE1344 extensions + * - \b B222: 100 bps, DCLS, manchester encoded, time-of-year + * - \b B223: 100 bps, DCLS, manchester encoded, time-of-year, SBS + * - \b G002: 10 kbps, DCLS, time-of-year + * - \b G142: 10 kbps, 100 kHz carrier, time-of-year + * - \b G006: 10 kbps, DCLS, complete date + * - \b G146: 10 kbps, 100 kHz carrier, complete date + * - \b AFNOR: 100 bps, 1 kHz carrier, SBS, complete date + * - \b AFNOR DC: 100 bps, DCLS, SBS, complete date + * - \b IEEE1344: 100 bps, 1 kHz carrier, time-of-year, SBS, IEEE 1344 extensions (B120) + * - \b IEEE1344 DC: 100 bps, DCLS, time-of-year, SBS, IEEE 1344 extensions (B000) + * - \b C37.118: like IEEE 1344, but %UTC offset applied with reversed sign + * - \b C37.118 DC: like IEEE 1344 DC, but %UTC offset applied with reversed sign + * + * - time-of-year: day-of-year, hours, minutes, seconds + * - complete date: time-of-year plus year number + * - SBS: straight binary seconds, second-of-day + * + * AFNOR codes are based on the french standard AFNOR NF S87-500 + * + * IEEE 1344 codes are defined in IEEE standard 1344-1995. The code frame is compatible + * with B002/B122 but provides some well defined extensions in the control field which + * include a quality indicator (time figure of merit, TFOM), year number, DST and leap + * second status, and local time offset from %UTC. + * + * IEEE C37.118 codes are defined in IEEE standard C37.118-2005 which includes a revised version + * of the IEEE 1344 standard from 1995. These codes provide the same extensions as IEEE 1344 + * but unfortunately determine that the %UTC offset has to be applied with reversed sign. + * + * For example, if a -6 hours UTC offset is transmitted in the time code:<br> + * IEEE 1344: (IRIG time 14:43:27 h) - (offs -6 h) = (UTC 20:43:27)<br> + * IEEE C37.118: (IRIG time 14:43:27 h) + (offs -6 h) = (UTC 08:43:27)<br> + * + * @see @ref MSK_ICODE_RX_UTC_OFFS_ADD and @ref MSK_ICODE_RX_UTC_OFFS_SUB + * + * @note There are 3rd party IRIG devices out there which apply the %UTC offset as specified + * in IEEE C37.118-2005, but claim to be compatible with IEEE 1344. So if local time is transmitted + * by the timecode then care must be taken that the %UTC offset is evaluated by the timecode + * receiver in the same way as computed by the timecode generator. Otherwise the %UTC + * time computed by the receiver may be <b>wrong</b>. + * + * @{ */ + +/** + * @brief Known IRIG TX code formats + * + * Used with ::IRIG_SETTINGS::icode for IRIG transmitters. + * For IRIG receivers see ::ICODE_RX_CODES. + * + * Meinberg timecode transmitters always generate the unmodulated (DCLS) + * and usually the modulated timecode signals internally at the same time, + * so the code definitions always refer to both. + * + * @note Not all device may provide both the modulated and unmodulated + * signal externally. + */ +enum ICODE_TX_CODES { ICODE_TX_B002_B122, ICODE_TX_B003_B123, @@ -2130,88 +3967,122 @@ enum ICODE_TX_A003_A133, ICODE_TX_AFNOR, ICODE_TX_IEEE1344, - ICODE_TX_B2201344, // DCLS only - ICODE_TX_B222, // DCLS only - ICODE_TX_B223, // DCLS only + ICODE_TX_B2201344, ///< DCLS only + ICODE_TX_B222, ///< DCLS only + ICODE_TX_B223, ///< DCLS only ICODE_TX_B006_B126, ICODE_TX_B007_B127, ICODE_TX_G002_G142, ICODE_TX_G006_G146, ICODE_TX_C37118, - N_ICODE_TX /**< number of code types */ + ICODE_TX_TXC101, + ICODE_TX_E002_E112, + ICODE_TX_NASA36, + ICODE_TX_A006_A136, + ICODE_TX_A007_A137, + N_ICODE_TX ///< number of known codes }; /** - * Initializers for format name strings. + * @brief Initializers for TX timecode format name strings + * + * @see ::ICODE_TX_CODES */ -#define DEFAULT_ICODE_TX_NAMES \ -{ \ - "B002+B122", \ - "B003+B123", \ - "A002+A132", \ - "A003+A133", \ - "AFNOR NF S87-500", \ - "IEEE1344", \ - "B220(1344) DCLS", \ - "B222 DCLS", \ - "B223 DCLS", \ - "B006+B126", \ - "B007+B127", \ - "G002+G142", \ - "G006+G146", \ - "C37.118" \ -} - -/** - * Initializers for short name strings which must not - * be longer than 10 printable characters. +#define DEFAULT_ICODE_TX_NAMES \ +{ \ + /* B002_B122 */ "B002+B122", \ + /* B003_B123 */ "B003+B123", \ + /* A002_A132 */ "A002+A132", \ + /* A003_A133 */ "A003+A133", \ + /* AFNOR */ "AFNOR NF S87-500", \ + /* IEEE1344 */ "IEEE 1344", \ + /* B2201344 */ "B220(1344) DCLS", \ + /* B222 */ "B222 DCLS", \ + /* B223 */ "B223 DCLS", \ + /* B006_B126 */ "B006+B126", \ + /* B007_B127 */ "B007+B127", \ + /* G002_G142 */ "G002+G142", \ + /* G006_G146 */ "G006+G146", \ + /* C37118 */ "IEEE C37.118", \ + /* TXC101 */ "TXC-101 DTR-6", \ + /* E002_E112 */ "E002+E112", \ + /* NASA36 */ "NASA 36", \ + /* A006_A136 */ "A006+A136", \ + /* A007_A137 */ "A007+A137" \ +} + +/** + * @brief Initializers for short TX timecode format name strings + * + * @note Must not be longer than 10 printable characters + * + * @see ::ICODE_TX_CODES */ #define DEFAULT_ICODE_TX_NAMES_SHORT \ { \ - "B002+B122", \ - "B003+B123", \ - "A002+A132", \ - "A003+A133", \ - "AFNOR NF-S", \ - "IEEE1344", \ - "B220/1344", \ - "B222 DC", \ - "B223 DC", \ - "B006+B126", \ - "B007+B127", \ - "G002+G142", \ - "G006+G146", \ - "C37.118" \ + /* B002_B122 */ "B002+B122", \ + /* B003_B123 */ "B003+B123", \ + /* A002_A132 */ "A002+A132", \ + /* A003_A133 */ "A003+A133", \ + /* AFNOR */ "AFNOR NF S", \ + /* IEEE1344 */ "IEEE 1344", \ + /* B2201344 */ "B220/1344", \ + /* B222 */ "B222 DC", \ + /* B223 */ "B223 DC", \ + /* B006_B126 */ "B006+B126", \ + /* B007_B127 */ "B007+B127", \ + /* G002_G142 */ "G002+G142", \ + /* G006_G146 */ "G006+G146", \ + /* C37118 */ "C37.118", \ + /* TXC101 */ "TXC-101", \ + /* E002_E112 */ "E002+E112", \ + /* NASA36 */ "NASA 36", \ + /* A006_A136 */ "A006+A136", \ + /* A007_A137 */ "A007+A137" \ } /** - * Initializers for English format description strings. + * @brief Initializers for English TX format description strings + * + * @see ::ICODE_TX_CODES */ -#define DEFAULT_ICODE_TX_DESCRIPTIONS_ENG \ -{ \ - "100 bps, DCLS or 1 kHz carrier", \ - "100 bps, DCLS or 1 kHz carrier, SBS", \ - "1000 bps, DCLS or 10 kHz carrier", \ - "1000 bps, DCLS or 10 kHz carrier, SBS", \ - "100 bps, DCLS or 1 kHz carrier, SBS, complete date", \ - "100 bps, DCLS or 1 kHz carrier, SBS, complete date, time zone info", \ - "100 bps, Manchester enc., DCLS only, SBS, complete date, time zone info", \ - "100 bps, Manchester enc., DCLS only", \ - "100 bps, Manchester enc., DCLS only, SBS", \ - "100 bps, DCLS or 1 kHz carrier, complete date", \ - "100 bps, DCLS or 1 kHz carrier, complete date, SBS", \ - "10 kbps, DCLS or 100 kHz carrier", \ - "10 kbps, DCLS or 100 kHz carrier, complete date", \ - "like IEEE1344, but UTC offset with reversed sign" \ +#define DEFAULT_ICODE_TX_DESCRIPTIONS_ENG \ +{ \ + /* B002_B122 */ "100 bps, DCLS or 1 kHz carrier", \ + /* B003_B123 */ "100 bps, DCLS or 1 kHz carrier, SBS", \ + /* A002_A132 */ "1000 bps, DCLS or 10 kHz carrier", \ + /* A003_A133 */ "1000 bps, DCLS or 10 kHz carrier, SBS", \ + /* AFNOR */ "100 bps, DCLS or 1 kHz carrier, complete date, SBS", \ + /* IEEE1344 */ "100 bps, DCLS or 1 kHz carrier, 2 digit year number, SBS, UTC offset, DST and Leap sec status", \ + /* B2201344 */ "100 bps, Manchester enc., DCLS only, 2 digit year number, SBS, UTC offset, DST and Leap sec status", \ + /* B222 */ "100 bps, Manchester enc., DCLS only", \ + /* B223 */ "100 bps, Manchester enc., DCLS only, SBS", \ + /* B006_B126 */ "100 bps, DCLS or 1 kHz carrier, 2 digit year number", \ + /* B007_B127 */ "100 bps, DCLS or 1 kHz carrier, 2 digit year number, SBS", \ + /* G002_G142 */ "10 kbps, DCLS or 100 kHz carrier", \ + /* G006_G146 */ "10 kbps, DCLS or 100 kHz carrier, 2 digit year number", \ + /* C37118 */ "100 bps, DCLS or 1 kHz carrier, 2 digit year number, SBS, UTC offs. reverse to 1344, DST/Leap sec status", \ + /* TXC101 */ "code from TV time sync device TXC-101 DTR-6", \ + /* E002_E112 */ "10 bps, DCLS or 100 Hz carrier", \ + /* NASA36 */ "100 bps, DCLS or 1 kHz carrier", \ + /* A006_A136 */ "1000 bps, DCLS or 10 kHz carrier, 2 digit year number", \ + /* A007_A137 */ "1000 bps, DCLS or 10 kHz carrier, 2 digit year number, SBS" \ } -/* - * The definitions below are used to set up bit masks - * which restrict the IRIG formats which are supported - * by a given IRIG transmitter device: - */ + +/** + * @brief Bit masks used with ::IRIG_INFO::supp_codes for TX + * + * These bit masks are used with timecode receivers only + * + * @see @ref ICODE_TX_CODES + * @see @ref ICODE_RX_CODES + * @see @ref ICODE_RX_MASKS + * + * @anchor ICODE_TX_MASKS @{ */ + #define MSK_ICODE_TX_B002_B122 ( 1UL << ICODE_TX_B002_B122 ) #define MSK_ICODE_TX_B003_B123 ( 1UL << ICODE_TX_B003_B123 ) #define MSK_ICODE_TX_A002_A132 ( 1UL << ICODE_TX_A002_A132 ) @@ -2226,19 +4097,35 @@ enum #define MSK_ICODE_TX_G002_G142 ( 1UL << ICODE_TX_G002_G142 ) #define MSK_ICODE_TX_G006_G146 ( 1UL << ICODE_TX_G006_G146 ) #define MSK_ICODE_TX_C37118 ( 1UL << ICODE_TX_C37118 ) +#define MSK_ICODE_TX_TXC101 ( 1UL << ICODE_TX_TXC101 ) +#define MSK_ICODE_TX_E002_E112 ( 1UL << ICODE_TX_E002_E112 ) +#define MSK_ICODE_TX_NASA36 ( 1UL << ICODE_TX_NASA36 ) +#define MSK_ICODE_TX_A006_A136 ( 1UL << ICODE_TX_A006_A136 ) +#define MSK_ICODE_TX_A007_A137 ( 1UL << ICODE_TX_A007_A137 ) + +/** @} anchor ICODE_TX_MASKS */ + /** - * A mask of IRIG formats with manchester encoded DC output: + * @brief A mask of IRIG TX formats with manchester encoded DC output */ #define MSK_ICODE_TX_DC_MANCH \ ( \ - MSK_ICODE_TX_B2201344 | \ - MSK_ICODE_TX_B222 | \ + MSK_ICODE_TX_B2201344 | \ + MSK_ICODE_TX_B222 | \ MSK_ICODE_TX_B223 \ ) /** - * A mask of IRIG formats with 1 kHz carrier: + * @brief A mask of IRIG TX formats with 100 Hz carrier + */ +#define MSK_ICODE_TX_100HZ \ +( \ + MSK_ICODE_TX_E002_E112 \ +) + +/** + * @brief A mask of IRIG TX formats with 1 kHz carrier */ #define MSK_ICODE_TX_1KHZ \ ( \ @@ -2251,80 +4138,224 @@ enum MSK_ICODE_TX_B223 | \ MSK_ICODE_TX_B006_B126 | \ MSK_ICODE_TX_B007_B127 | \ - MSK_ICODE_TX_C37118 \ + MSK_ICODE_TX_C37118 | \ + MSK_ICODE_TX_NASA36 \ ) /** - * A mask of IRIG formats with 10 kHz carrier: + * @brief A mask of IRIG TX formats with 10 kHz carrier */ #define MSK_ICODE_TX_10KHZ \ ( \ MSK_ICODE_TX_A002_A132 | \ - MSK_ICODE_TX_A003_A133 \ + MSK_ICODE_TX_A003_A133 | \ + MSK_ICODE_TX_A006_A136 | \ + MSK_ICODE_TX_A007_A137 \ ) /** - * A mask of IRIG formats with 100 kHz carrier: + * @brief A mask of IRIG TX formats with 100 kHz carrier */ #define MSK_ICODE_TX_100KHZ \ ( \ - MSK_ICODE_TX_G002_G142 | \ + MSK_ICODE_TX_G002_G142 | \ MSK_ICODE_TX_G006_G146 \ ) /** - * A mask of IRIG formats with 100 bps data rate: + * @brief A mask of IRIG TX formats with 10 bps data rate + */ +#define MSK_ICODE_TX_10BPS \ +( \ + MSK_ICODE_TX_E002_E112 \ +) + +/** + * @brief A mask of IRIG TX formats with 100 bps data rate */ #define MSK_ICODE_TX_100BPS \ ( \ - MSK_ICODE_TX_B002_B122 | \ - MSK_ICODE_TX_B003_B123 | \ - MSK_ICODE_TX_AFNOR | \ - MSK_ICODE_TX_IEEE1344 | \ - MSK_ICODE_TX_B006_B126 | \ - MSK_ICODE_TX_B007_B127 | \ + MSK_ICODE_TX_B002_B122 | \ + MSK_ICODE_TX_B003_B123 | \ + MSK_ICODE_TX_AFNOR | \ + MSK_ICODE_TX_IEEE1344 | \ + MSK_ICODE_TX_B006_B126 | \ + MSK_ICODE_TX_B007_B127 | \ MSK_ICODE_TX_C37118 \ ) /** - * A mask of IRIG formats with 1000 bps data rate: + * @brief A mask of IRIG TX formats with 1000 bps data rate */ #define MSK_ICODE_TX_1000BPS \ ( \ - MSK_ICODE_TX_A002_A132 | \ - MSK_ICODE_TX_A003_A133 \ + MSK_ICODE_TX_A002_A132 | \ + MSK_ICODE_TX_A003_A133 | \ + MSK_ICODE_TX_A006_A136 | \ + MSK_ICODE_TX_A007_A137 \ ) /** - * A mask of IRIG formats with 10 kbps data rate: + * @brief A mask of IRIG TX formats with 10 kbps data rate */ #define MSK_ICODE_TX_10000BPS \ ( \ - MSK_ICODE_TX_G002_G142 | \ + MSK_ICODE_TX_G002_G142 | \ MSK_ICODE_TX_G006_G146 \ ) /** - * A mask of IRIG formats which support TFOM: + * @brief A mask of IRIG TX formats supporting 10ths of seconds + */ +#define MSK_ICODE_TX_HAS_SEC10THS \ +( \ + MSK_ICODE_TX_A002_A132 | \ + MSK_ICODE_TX_A003_A133 | \ + MSK_ICODE_TX_G002_G142 | \ + MSK_ICODE_TX_G006_G146 | \ + MSK_ICODE_TX_A006_A136 | \ + MSK_ICODE_TX_A007_A137 \ +) + +/** + * @brief A mask of IRIG TX formats supporting 100ths of seconds + */ +#define MSK_ICODE_TX_HAS_SEC100THS \ +( \ + MSK_ICODE_TX_G002_G142 | \ + MSK_ICODE_TX_G006_G146 \ +) + +/** + * @brief A mask of IRIG TX formats providing a short year number after P5 + * + * The IEEE codes, the AFNOR codes, and some IRIG codes provide a + * 2 digit year number after position identifier P5. However, some + * IRIG G codes provide a 100ths-of-seconds field after P5,and + * eventually provide a year number after P6. + * + * @see @ref MSK_ICODE_TX_HAS_SHORT_YEAR_AFTER_P6 + * @see @ref MSK_ICODE_TX_HAS_ANY_SHORT_YEAR + */ +#define MSK_ICODE_TX_HAS_SHORT_YEAR_AFTER_P5 \ +( \ + MSK_ICODE_TX_AFNOR | \ + MSK_ICODE_TX_IEEE1344 | \ + MSK_ICODE_TX_B2201344 | \ + MSK_ICODE_TX_B006_B126 | \ + MSK_ICODE_TX_B007_B127 | \ + MSK_ICODE_TX_C37118 | \ + MSK_ICODE_TX_A006_A136 | \ + MSK_ICODE_TX_A007_A137 \ +) + +/** + * @brief A mask of IRIG TX formats providing a short year number after P6 + * + * While most time codes that provide a year number do this after P5, + * there are some IRIG codes which provide a 100ths-of-seconds field + * at that position, and eventually provide a year number after P6. + * + * @see @ref MSK_ICODE_TX_HAS_SHORT_YEAR_AFTER_P5 + * @see @ref MSK_ICODE_TX_HAS_ANY_SHORT_YEAR + */ + #define MSK_ICODE_TX_HAS_SHORT_YEAR_AFTER_P6 \ +( \ + MSK_ICODE_TX_G006_G146 \ +) + +/** + * @brief A mask of IRIG TX formats providing a short year number in general + * + * Depending on the code format, the year number can be transmitted + * either after position identifier P5, or after P6. + * + * @see @ref MSK_ICODE_TX_HAS_SHORT_YEAR_AFTER_P5 + * @see @ref MSK_ICODE_TX_HAS_SHORT_YEAR_AFTER_P6 + */ +#define MSK_ICODE_TX_HAS_ANY_SHORT_YEAR \ +( \ + MSK_ICODE_TX_HAS_SHORT_YEAR_AFTER_P5 | \ + MSK_ICODE_TX_HAS_SHORT_YEAR_AFTER_P6 \ +) + +/** + * @brief A mask of IRIG TX formats supporting TFOM */ #define MSK_ICODE_TX_HAS_TFOM \ ( \ - MSK_ICODE_TX_IEEE1344 | \ + MSK_ICODE_TX_IEEE1344 | \ + MSK_ICODE_TX_C37118 \ +) + +/** + * @brief A mask of IRIG TX formats supporting CTQ continuous time quality + * + * This has been introduced in IEEE C37.118.1-2011 + */ +#define MSK_ICODE_TX_HAS_CTQ \ +( \ + MSK_ICODE_TX_IEEE1344 | \ MSK_ICODE_TX_C37118 \ ) /** - * A mask of IRIG formats which support time zone information: + * @brief A mask of IRIG TX formats supporting time zone information */ #define MSK_ICODE_TX_HAS_TZI \ ( \ - MSK_ICODE_TX_IEEE1344 | \ + MSK_ICODE_TX_IEEE1344 | \ MSK_ICODE_TX_C37118 \ ) /** - * The default mask of IRIG formats supported by - * IRIG transmitters: + * @brief IRIG TX formats where UTC offset must be subtracted to yield UTC + * + * A mask of IRIG formats where the decoded UTC offset must be + * subtracted from the time decoded from the IRIG signal to yield UTC, e.g.:<br> + * (IRIG time 14:43:27 h) - (offs -6 h) = (UTC 20:43:27) + */ +#define MSK_ICODE_TX_UTC_OFFS_SUB \ +( \ + MSK_ICODE_TX_IEEE1344 \ +) + +/** + * @brief IRIG TX formats where UTC offset must be added to yield UTC + * + * A mask of IRIG formats where the decoded UTC offset must be + * added to the time decoded from the IRIG signal to yield UTC, e.g.:<br> + * (IRIG time 14:43:27 h) + (offs -6 h) = (UTC 08:43:27) + */ +#define MSK_ICODE_TX_UTC_OFFS_ADD \ +( \ + MSK_ICODE_TX_C37118 \ +) + +/** + * @brief A mask of IRIG TX formats supporting a day of week number + */ +#define MSK_ICODE_TX_HAS_AFNOR_WDAY \ +( \ + MSK_ICODE_TX_AFNOR | \ + MSK_ICODE_TX_AFNOR_DC \ +) + +/** + * @brief A mask of IRIG TX formats supporting a date (day-of-month, month) + */ +#define MSK_ICODE_TX_HAS_AFNOR_DATE \ +( \ + MSK_ICODE_TX_AFNOR | \ + MSK_ICODE_TX_AFNOR_DC \ +) + + +/** + * @brief The default mask of IRIG TX formats supported by IRIG transmitters + * + * @note The formats which are actually supported should be retrieved + * from the device */ #if !defined( SUPP_MSK_ICODE_TX ) #define SUPP_MSK_ICODE_TX \ @@ -2340,105 +4371,159 @@ enum /** - * Definitions used with IRIG receivers which decode - * two similar IRIG codes (with or without SBS) - * at the same time. + * @brief Known IRIG RX code formats + * + * Used with ::IRIG_SETTINGS::icode for IRIG receivers. + * For IRIG transmitters see ::ICODE_TX_CODES. + * + * The SBS value is redundant and can easily by computed + * from the time-of-day, so Meinberg time code receivers + * usually don't evaluate the SBS field anyway, and thus + * it makes no difference if a code with or withour SBS + * is supplied. */ -enum +enum ICODE_RX_CODES { - ICODE_RX_B122_B123, // modulated - ICODE_RX_A132_A133, // modulated - ICODE_RX_B002_B003, // DCLS - ICODE_RX_A002_A003, // DCLS - ICODE_RX_AFNOR, // modulated - ICODE_RX_AFNOR_DC, // DCLS - ICODE_RX_IEEE1344, // modulated - ICODE_RX_IEEE1344_DC, // DCLS - ICODE_RX_B126_B127, // modulated - ICODE_RX_B006_B007, // DCLS - ICODE_RX_G142_G146, // modulated - ICODE_RX_G002_G006, // DCLS - ICODE_RX_C37118, // modulated - ICODE_RX_C37118_DC, // DCLS - ICODE_RX_TXC_101, // modulated - ICODE_RX_TXC_101_DC, // DCLS - N_ICODE_RX /* the number of valid signal code types */ + ICODE_RX_B122_B123, ///< modulated + ICODE_RX_A132_A133, ///< modulated + ICODE_RX_B002_B003, ///< DCLS + ICODE_RX_A002_A003, ///< DCLS + ICODE_RX_AFNOR, ///< modulated + ICODE_RX_AFNOR_DC, ///< DCLS + ICODE_RX_IEEE1344, ///< modulated + ICODE_RX_IEEE1344_DC, ///< DCLS + ICODE_RX_B126_B127, ///< modulated + ICODE_RX_B006_B007, ///< DCLS + ICODE_RX_G142, ///< modulated (G143 is undefined, SBS not supported with Gxxx) + ICODE_RX_G002, ///< DCLS (G003 is undefined, SBS not supported with Gxxx) + ICODE_RX_C37118, ///< modulated + ICODE_RX_C37118_DC, ///< DCLS + ICODE_RX_TXC101, ///< modulated + ICODE_RX_TXC101_DC, ///< DCLS + ICODE_RX_E112, ///< modulated + ICODE_RX_E002, ///< DCLS + ICODE_RX_NASA36, ///< modulated + ICODE_RX_NASA36_DC, ///< DCLS + ICODE_RX_A136_A137, ///< modulated + ICODE_RX_A006_A007, ///< DCLS + ICODE_RX_G146, ///< modulated (G147 is undefined, SBS not supported with Gxxx) + ICODE_RX_G006, ///< DCLS (G007 is undefined, SBS not supported with Gxxx) + N_ICODE_RX ///< the number of known codes }; /** - * Initializers for format name strings. + * @brief Initializers for RX timecode format name strings + * + * @see ::ICODE_RX_CODES */ #define DEFAULT_ICODE_RX_NAMES \ { \ - "B122/B123", \ - "A132/A133", \ - "B002/B003 (DCLS)", \ - "A002/A003 (DCLS)", \ - "AFNOR NF S87-500", \ - "AFNOR NF S87-500 (DCLS)", \ - "IEEE1344", \ - "IEEE1344 (DCLS)", \ - "B126/B127", \ - "B006/B007 (DCLS)", \ - "G142/G146", \ - "G002/G006 (DCLS)", \ - "C37.118", \ - "C37.118 (DCLS)", \ - "TXC-101 DTR-6", \ - "TXC-101 DTR-6 (DCLS)" \ -} - -/** - * Initializers for short name strings which must not - * be longer than 11 printable characters. - */ -#define DEFAULT_ICODE_RX_NAMES_SHORT \ -{ \ - "B122/B123", \ - "A132/A133", \ - "B002/B003", \ - "A002/A003", \ - "AFNOR NF-S", \ - "AFNOR DC", \ - "IEEE1344", \ - "IEEE1344 DC", \ - "B126/B127", \ - "B006/B007", \ - "G142/G146", \ - "G002/G006", \ - "C37.118", \ - "C37.118 DC", \ - "TXC-101", \ - "TXC-101 DC" \ + /* B122_B123 */ "B122/B123", \ + /* A132_A133 */ "A132/A133", \ + /* B002_B003 */ "B002/B003 (DCLS)", \ + /* A002_A003 */ "A002/A003 (DCLS)", \ + /* AFNOR */ "AFNOR NF S87-500", \ + /* AFNOR_DC */ "AFNOR NF S87-500 (DCLS)", \ + /* IEEE1344 */ "IEEE1344", \ + /* IEEE1344_DC */ "IEEE1344 (DCLS)", \ + /* B126_B127 */ "B126/B127", \ + /* B006_B007 */ "B006/B007 (DCLS)", \ + /* G142 */ "G142", \ + /* G002 */ "G002 (DCLS)", \ + /* C37118 */ "C37.118", \ + /* C37118_DC */ "C37.118 (DCLS)", \ + /* TXC101 */ "TXC-101 DTR-6", \ + /* TXC101_DC */ "TXC-101 DTR-6 (DCLS)", \ + /* E112 */ "E112", \ + /* E002 */ "E002 (DCLS)", \ + /* NASA36 */ "NASA-36", \ + /* NASA36_DC */ "NASA-36 (DCLS)", \ + /* A136_A137 */ "A136/A137", \ + /* A006_A007 */ "A006/A007 (DCLS)", \ + /* G146 */ "G146", \ + /* G006 */ "G006 (DCLS)" \ } - /** - * Initializers for English format description strings. + * @brief Initializers for short RX timecode format name strings + * + * @note Must not be longer than 11 printable characters + * + * @see ::ICODE_RX_CODES */ -#define DEFAULT_ICODE_RX_DESCRIPTIONS_ENG \ -{ \ - "100 bps, 1 kHz carrier, SBS optionally", \ - "1000 bps, 10 kHz carrier, SBS optionally", \ - "100 bps, DCLS, SBS optionally", \ - "1000 bps, DCLS, SBS optionally", \ - "100 bps, 1 kHz carrier, SBS, complete date", \ - "100 bps, DCLS, SBS, complete date", \ - "100 bps, 1 kHz carrier, SBS, time zone info", \ - "100 bps, DCLS, SBS, time zone info", \ - "100 bps, 1 kHz carrier, complete date, SBS optionally", \ - "100 bps, DCLS, complete date, SBS optionally", \ - "10 kbps, 100 kHz carrier, complete date optionally", \ - "10 kbps, DCLS, complete date optionally", \ - "like IEEE1344, but UTC offset with reversed sign", \ - "like IEEE1344 DC, but UTC offset with reversed sign", \ - "code from TV time sync device TXC-101 DTR-6", \ - "DC code from TV time sync device TXC-101 DTR-6" \ +#define DEFAULT_ICODE_RX_NAMES_SHORT \ +{ \ + /* B122_B123 */ "B122/B123", \ + /* A132_A133 */ "A132/A133", \ + /* B002_B003 */ "B002/B003", \ + /* A002_A003 */ "A002/A003", \ + /* AFNOR */ "AFNOR NF S", \ + /* AFNOR_DC */ "AFNOR DC", \ + /* IEEE1344 */ "IEEE1344", \ + /* IEEE1344_DC */ "IEEE1344 DC", \ + /* B126_B127 */ "B126/B127", \ + /* B006_B007 */ "B006/B007", \ + /* G142 */ "G142", \ + /* G002 */ "G002 DC", \ + /* C37118 */ "C37.118", \ + /* C37118_DC */ "C37.118 DC", \ + /* TXC101 */ "TXC-101", \ + /* TXC101_DC */ "TXC-101 DC", \ + /* E112 */ "E112", \ + /* E002 */ "E002 DC", \ + /* NASA36 */ "NASA-36", \ + /* NASA36_DC */ "NASA-36 DC", \ + /* A136_A137 */ "A136/A137", \ + /* A006_A007 */ "A006/A007", \ + /* G146 */ "G146", \ + /* G006 */ "G006 DC" \ } -/* - * Bit masks corresponding to the enumeration above: + +/** + * @brief Initializers for English RX format description strings + * + * @see ::ICODE_RX_CODES */ +#define DEFAULT_ICODE_RX_DESCRIPTIONS_ENG \ +{ \ + /* B122_B123 */ "100 bps, 1 kHz carrier, SBS optionally", \ + /* A132_A133 */ "1000 bps, 10 kHz carrier, SBS optionally", \ + /* B002_B003 */ "100 bps, DCLS, SBS optionally", \ + /* A002_A003 */ "1000 bps, DCLS, SBS optionally", \ + /* AFNOR */ "100 bps, 1 kHz carrier, complete date, SBS", \ + /* AFNOR_DC */ "100 bps, DCLS, complete date, SBS", \ + /* IEEE1344 */ "100 bps, 1 kHz carrier, SBS, time zone info", \ + /* IEEE1344_DC */ "100 bps, DCLS, SBS, time zone info", \ + /* B126_B127 */ "100 bps, 1 kHz carrier, 2 digit year number, SBS optionally", \ + /* B006_B007 */ "100 bps, DCLS, 2 digit year number, SBS optionally", \ + /* G142 */ "10 kbps, 100 kHz carrier", \ + /* G002 */ "10 kbps, DCLS", \ + /* C37118 */ "like IEEE1344, but UTC offset with reversed sign", \ + /* C37118_DC */ "like IEEE1344 DC, but UTC offset with reversed sign", \ + /* TXC101 */ "code from TV time sync device TXC-101 DTR-6", \ + /* TXC101_DC */ "DC code from TV time sync device TXC-101 DTR-6", \ + /* E112 */ "10 bps, 100 Hz carrier", \ + /* E002 */ "10 bps, DCLS", \ + /* NASA36 */ "100 bps, 1 kHz carrier", \ + /* NASA36_DC */ "100 bps, DCLS", \ + /* A136_A137 */ "1000 bps, 10 kHz carrier, 2 digit year number, SBS optionally", \ + /* A006_A007 */ "1000 bps, DCLS, 2 digit year number, SBS optionally", \ + /* G146 */ "10 kbps, 100 kHz carrier, 2 digit year number", \ + /* G006 */ "10 kbps, DCLS, 2 digit year number" \ +} + +/** + * @brief Bit masks used with ::IRIG_INFO::supp_codes for RX + * + * These bit masks are used with timecode receivers only + * + * @see @ref ICODE_RX_CODES + * @see @ref ICODE_TX_CODES + * @see @ref ICODE_TX_MASKS + * + * @anchor ICODE_RX_MASKS @{ */ + #define MSK_ICODE_RX_B122_B123 ( 1UL << ICODE_RX_B122_B123 ) #define MSK_ICODE_RX_A132_A133 ( 1UL << ICODE_RX_A132_A133 ) #define MSK_ICODE_RX_B002_B003 ( 1UL << ICODE_RX_B002_B003 ) @@ -2449,15 +4534,26 @@ enum #define MSK_ICODE_RX_IEEE1344_DC ( 1UL << ICODE_RX_IEEE1344_DC ) #define MSK_ICODE_RX_B126_B127 ( 1UL << ICODE_RX_B126_B127 ) #define MSK_ICODE_RX_B006_B007 ( 1UL << ICODE_RX_B006_B007 ) -#define MSK_ICODE_RX_G142_G146 ( 1UL << ICODE_RX_G142_G146 ) -#define MSK_ICODE_RX_G002_G006 ( 1UL << ICODE_RX_G002_G006 ) +#define MSK_ICODE_RX_G142 ( 1UL << ICODE_RX_G142 ) +#define MSK_ICODE_RX_G002 ( 1UL << ICODE_RX_G002 ) #define MSK_ICODE_RX_C37118 ( 1UL << ICODE_RX_C37118 ) #define MSK_ICODE_RX_C37118_DC ( 1UL << ICODE_RX_C37118_DC ) -#define MSK_ICODE_RX_TXC_101 ( 1UL << ICODE_RX_TXC_101 ) -#define MSK_ICODE_RX_TXC_101_DC ( 1UL << ICODE_RX_TXC_101_DC ) +#define MSK_ICODE_RX_TXC101 ( 1UL << ICODE_RX_TXC101 ) +#define MSK_ICODE_RX_TXC101_DC ( 1UL << ICODE_RX_TXC101_DC ) +#define MSK_ICODE_RX_E112 ( 1UL << ICODE_RX_E112 ) +#define MSK_ICODE_RX_E002 ( 1UL << ICODE_RX_E002 ) +#define MSK_ICODE_RX_NASA36 ( 1UL << ICODE_RX_NASA36 ) +#define MSK_ICODE_RX_NASA36_DC ( 1UL << ICODE_RX_NASA36_DC ) +#define MSK_ICODE_RX_A136_A137 ( 1UL << ICODE_RX_A136_A137 ) +#define MSK_ICODE_RX_A006_A007 ( 1UL << ICODE_RX_A006_A007 ) +#define MSK_ICODE_RX_G146 ( 1UL << ICODE_RX_G146 ) +#define MSK_ICODE_RX_G006 ( 1UL << ICODE_RX_G006 ) + +/** @} anchor ICODE_RX_MASKS */ + /** - * A mask of IRIG DCLS formats: + * @brief A mask of IRIG RX DCLS formats */ #define MSK_ICODE_RX_DC \ ( \ @@ -2466,12 +4562,25 @@ enum MSK_ICODE_RX_AFNOR_DC | \ MSK_ICODE_RX_IEEE1344_DC | \ MSK_ICODE_RX_B006_B007 | \ - MSK_ICODE_RX_G002_G006 | \ - MSK_ICODE_RX_C37118_DC \ + MSK_ICODE_RX_G002 | \ + MSK_ICODE_RX_C37118_DC | \ + MSK_ICODE_RX_TXC101_DC | \ + MSK_ICODE_RX_E002 | \ + MSK_ICODE_RX_NASA36_DC | \ + MSK_ICODE_RX_A006_A007 | \ + MSK_ICODE_RX_G006 \ +) + +/** + * @brief A mask of IRIG RX formats with 100 Hz carrier + */ +#define MSK_ICODE_RX_100HZ \ +( \ + MSK_ICODE_RX_E112 \ ) /** - * A mask of IRIG formats with 1 kHz carrier: + * @brief A mask of IRIG RX formats with 1 kHz carrier */ #define MSK_ICODE_RX_1KHZ \ ( \ @@ -2479,27 +4588,40 @@ enum MSK_ICODE_RX_AFNOR | \ MSK_ICODE_RX_IEEE1344 | \ MSK_ICODE_RX_B126_B127 | \ - MSK_ICODE_RX_C37118 \ + MSK_ICODE_RX_C37118 | \ + MSK_ICODE_RX_TXC101 | \ + MSK_ICODE_RX_NASA36 \ ) /** - * A mask of IRIG formats with 10 kHz carrier: + * @brief A mask of IRIG RX formats with 10 kHz carrier */ #define MSK_ICODE_RX_10KHZ \ ( \ - MSK_ICODE_RX_A132_A133 \ + MSK_ICODE_RX_A132_A133 | \ + MSK_ICODE_RX_A136_A137 \ ) /** - * A mask of IRIG formats with 100 kHz carrier: + * @brief A mask of IRIG RX formats with 100 kHz carrier */ #define MSK_ICODE_RX_100KHZ \ ( \ - MSK_ICODE_RX_G142_G146 \ + MSK_ICODE_RX_G142 | \ + MSK_ICODE_RX_G146 \ ) /** - * A mask of IRIG formats with 100 bps data rate: + * @brief A mask of IRIG RX formats with 10 bps data rate + */ +#define MSK_ICODE_RX_10BPS \ +( \ + MSK_ICODE_RX_E002_E112 | \ + MSK_ICODE_RX_E002_E002 \ +) + +/** + * @brief A mask of IRIG RX formats with 100 bps data rate */ #define MSK_ICODE_RX_100BPS \ ( \ @@ -2512,28 +4634,118 @@ enum MSK_ICODE_RX_B126_B127 | \ MSK_ICODE_RX_B006_B007 | \ MSK_ICODE_RX_C37118 | \ - MSK_ICODE_RX_C37118_DC \ + MSK_ICODE_RX_C37118_DC | \ + MSK_ICODE_RX_TXC101 | \ + MSK_ICODE_RX_TXC101_DC | \ + MSK_ICODE_RX_NASA36 | \ + MSK_ICODE_RX_NASA36_DC \ ) /** - * A mask of IRIG formats with 1000 bps data rate: + * @brief A mask of IRIG RX formats with 1000 bps data rate */ #define MSK_ICODE_RX_1000BPS \ ( \ - MSK_ICODE_RX_A132_A133 | \ - MSK_ICODE_RX_A002_A003 \ + MSK_ICODE_RX_A132_A133 | \ + MSK_ICODE_RX_A002_A003 | \ + MSK_ICODE_RX_A136_A137 | \ + MSK_ICODE_RX_A006_A007 \ ) /** - * A mask of IRIG formats with 10 kbps data rate: + * @brief A mask of IRIG RX formats with 10 kbps data rate */ #define MSK_ICODE_RX_10000BPS \ ( \ - MSK_ICODE_RX_G142_G146 \ + MSK_ICODE_RX_G142 | \ + MSK_ICODE_RX_G002 | \ + MSK_ICODE_RX_G146 | \ + MSK_ICODE_RX_G006 \ +) + +/** + * @brief A mask of IRIG RX formats supporting 10ths of seconds + */ +#define MSK_ICODE_RX_HAS_SEC10THS \ +( \ + MSK_ICODE_RX_A132_A133 | \ + MSK_ICODE_RX_A002_A003 | \ + MSK_ICODE_RX_G142 | \ + MSK_ICODE_RX_G002 | \ + MSK_ICODE_RX_A136_A137 | \ + MSK_ICODE_RX_A006_A007 | \ + MSK_ICODE_RX_G146 | \ + MSK_ICODE_RX_G006 \ +) + +/** + * @brief A mask of IRIG RX formats which support 100ths of seconds + */ +#define MSK_ICODE_RX_HAS_SEC100THS \ +( \ + MSK_ICODE_RX_G142 | \ + MSK_ICODE_RX_G002 | \ + MSK_ICODE_RX_G146 | \ + MSK_ICODE_RX_G006 \ +) + +/** + * @brief A mask of IRIG RX formats supporting a 2 digit year number after P5 + * + * Note: This macro specifies ONLY the codes where the year number + * is transmitted after position identifier P5. + * + * @see ::MSK_ICODE_RX_HAS_SHORT_YEAR_AFTER_P6 + * @see ::MSK_ICODE_RX_HAS_ANY_SHORT_YEAR + */ +#define MSK_ICODE_RX_HAS_SHORT_YEAR_AFTER_P5 \ +( \ + MSK_ICODE_RX_AFNOR | \ + MSK_ICODE_RX_AFNOR_DC | \ + MSK_ICODE_RX_IEEE1344 | \ + MSK_ICODE_RX_IEEE1344_DC | \ + MSK_ICODE_RX_B126_B127 | \ + MSK_ICODE_RX_B006_B007 | \ + MSK_ICODE_RX_C37118 | \ + MSK_ICODE_RX_C37118_DC | \ + MSK_ICODE_RX_A136_A137 | \ + MSK_ICODE_RX_A006_A007 \ +) + +/** + * @brief A mask of IRIG RX formats supporting a 2 digit year number after P6 + * + * Note: This macro specifies ONLY the codes where the year number + * is transmitted after position identifier P6. + * + * @see ::MSK_ICODE_RX_HAS_SHORT_YEAR_AFTER_P5 + * @see ::MSK_ICODE_RX_HAS_ANY_SHORT_YEAR + */ +#define MSK_ICODE_RX_HAS_SHORT_YEAR_AFTER_P6 \ +( \ + MSK_ICODE_RX_G146 | \ + MSK_ICODE_RX_G006 \ ) /** - * A mask of IRIG formats which support TFOM: + * @brief A mask of IRIG RX formats providing any 2 digit year number + * + * Note: Different sets of code frames may provide a year number + * in different locations of the transmitted code. + * + * @see ::MSK_ICODE_RX_HAS_SHORT_YEAR_AFTER_P5 + * @see ::MSK_ICODE_RX_HAS_SHORT_YEAR_AFTER_P6 + */ +#define MSK_ICODE_RX_HAS_ANY_SHORT_YEAR \ +( \ + MSK_ICODE_RX_HAS_SHORT_YEAR_AFTER_P5 | \ + MSK_ICODE_RX_HAS_SHORT_YEAR_AFTER_P6 \ +) + + + +/** + * @brief A mask of IRIG RX formats supporting TFOM time quality indicator */ #define MSK_ICODE_RX_HAS_TFOM \ ( \ @@ -2544,7 +4756,20 @@ enum ) /** - * A mask of IRIG formats which support time zone information: + * @brief A mask of IRIG RX formats supporting CTQ continuous time quality + * + * This has been introduced in IEEE C37.118.1-2011 + */ +#define MSK_ICODE_RX_HAS_CTQ \ +( \ + MSK_ICODE_RX_IEEE1344 | \ + MSK_ICODE_RX_IEEE1344_DC | \ + MSK_ICODE_RX_C37118 | \ + MSK_ICODE_RX_C37118_DC \ +) + +/** + * @brief A mask of IRIG RX formats supporting time zone information */ #define MSK_ICODE_RX_HAS_TZI \ ( \ @@ -2555,8 +4780,55 @@ enum ) /** - * The default mask of IRIG formats supported by - * IRIG receivers: + * @brief IRIG RX formats where UTC offset must be subtracted to yield UTC + * + * A mask of IRIG formats where the decoded UTC offset must be + * subtracted from the time decoded from the IRIG signal to yield UTC, e.g.:<br> + * (IRIG time 14:43:27 h) - (offs -6 h) = (UTC 20:43:27) + */ +#define MSK_ICODE_RX_UTC_OFFS_SUB \ +( \ + MSK_ICODE_RX_IEEE1344 | \ + MSK_ICODE_RX_IEEE1344_DC \ +) + +/** + * @brief IRIG RX formats where UTC offset must be added to yield UTC + * + * A mask of IRIG formats where the decoded UTC offset must be + * added to the time decoded from the IRIG signal to yield UTC, e.g.:<br> + * (IRIG time 14:43:27 h) + (offs -6 h) = (UTC 08:43:27) + */ +#define MSK_ICODE_RX_UTC_OFFS_ADD \ +( \ + MSK_ICODE_RX_C37118 | \ + MSK_ICODE_RX_C37118_DC \ +) + +/** + * @brief A mask of IRIG RX formats supporting a day of week number + */ +#define MSK_ICODE_RX_HAS_AFNOR_WDAY \ +( \ + MSK_ICODE_RX_AFNOR | \ + MSK_ICODE_RX_AFNOR_DC \ +) + +/** + * @brief A mask of IRIG RX formats supporting a date (day-of-month, month) + */ +#define MSK_ICODE_RX_HAS_AFNOR_DATE \ +( \ + MSK_ICODE_RX_AFNOR | \ + MSK_ICODE_RX_AFNOR_DC \ +) + + +/** + * @brief The default mask of IRIG RX formats supported by IRIG receivers + * + * @note The formats which are actually supported should be retrieved + * from the device */ #if !defined( SUPP_MSK_ICODE_RX ) #define SUPP_MSK_ICODE_RX \ @@ -2570,91 +4842,255 @@ enum ) #endif -/** @} group_icode */ +/** @} defgroup group_icode */ /** - * The structure below is used to configure an optional - * on-board IRIG output: + * @brief Configuration settings of an IRIG input or output + * + * @see @ref group_icode */ typedef struct { - uint16_t icode; /**< IRIG signal code, see \ref group_icode */ - uint16_t flags; /**< see \ref group_irig_flags */ + uint16_t icode; ///< IRIG signal code, see ::ICODE_RX_CODES and ::ICODE_TX_CODES + uint16_t flags; ///< see ::IFLAGS_BIT_MASKS + } IRIG_SETTINGS; #define _mbg_swab_irig_settings( _p ) \ +do \ { \ _mbg_swab16( &(_p)->icode ); \ _mbg_swab16( &(_p)->flags ); \ -} +} while ( 0 ) + /** - * @defgroup group_irig_flags Bit Masks used with IRIG_SETTINGS::flags + * @brief Flag bits used to define ::IFLAGS_BIT_MASKS * - * (others are reserved) - * @{ + * @see ::IFLAGS_BIT_MASKS */ -#define IFLAGS_DISABLE_TFOM 0x0001 /**< RX ignore/TX don't gen TFOM */ -#define IFLAGS_TX_GEN_LOCAL_TIME 0x0002 /**< gen local time, not UTC */ +enum IFLAGS_BITS +{ + IFLAGS_BIT_DISABLE_TFOM, ///< for RX ignore, for TX don't generate TFOM flag + IFLAGS_BIT_TX_GEN_LOCAL_TIME, ///< TX output local time instead of %UTC + N_IFLAGS_BITS ///< number of known bits +}; + -#define IFLAGS_MASK 0x0003 /**< flags above or'ed */ +/** + * @brief Bit masks used with ::IRIG_SETTINGS::flags + * + * @note The presence or absence of the ::IFLAGS_DISABLE_TFOM flag for the IRIG RX + * settings of some PCI cards may not be evaluated correctly by some firmware + * versions for those cards, even if an IRIG code has been configured which supports + * this flag. See the comments near the declaration of the ::_pcps_incoming_tfom_ignored + * macro in pcpsdev.h for details. + * + * @see ::IFLAGS_BITS + */ +enum IFLAGS_BIT_MASKS +{ + IFLAGS_DISABLE_TFOM = ( 1UL << IFLAGS_BIT_DISABLE_TFOM ), ///< see ::IFLAGS_BIT_DISABLE_TFOM + IFLAGS_TX_GEN_LOCAL_TIME = ( 1UL << IFLAGS_BIT_TX_GEN_LOCAL_TIME ), ///< see ::IFLAGS_BIT_TX_GEN_LOCAL_TIME -// Note: the presence or absence of the IFLAGS_DISABLE_TFOM flag for the IRIG RX -// settings of some PCI cards may not be evaluated correctly by some firmware -// versions for those cards, even if an IRIG code has been configured which supports -// this flag. See the comments near the declaration of the _pcps_incoming_tfom_ignored() -// macro in pcpsdev.h for details. + IFLAGS_MASK = ( ( 1UL << N_IFLAGS_BITS ) - 1 ) ///< mask of all known flags +}; -/** @} group_irig_flags */ /** * @brief Current IRIG settings and supported codes * - * Used to query the IRIG current IRIG settings + * Used to query the current IRIG settings * plus a mask of supported codes. */ typedef struct { - IRIG_SETTINGS settings; - uint32_t supp_codes; /**< bit mask of supported codes */ + IRIG_SETTINGS settings; ///< current settings + uint32_t supp_codes; ///< see @ref ICODE_TX_MASKS and @ref ICODE_RX_MASKS + } IRIG_INFO; #define _mbg_swab_irig_info( _p ) \ +do \ { \ _mbg_swab_irig_settings( &(_p)->settings ); \ _mbg_swab32( &(_p)->supp_codes ); \ +} while ( 0 ) + + +/** + * @defgroup group_irig_comp IRIG input delay compensation + * + * These definitions are used with IRIG RX delay compensation + * which is supported by some IRIG receivers. Delay compensation + * depends on the basic frame type, so there are different records + * required for the different frame type groups. + * + * @{ */ + +/** + * The number of coefficients of a compensation record + * for a single frame type group, and the structure + * which contains those coefficients. + */ +#define N_IRIG_RX_COMP_VAL 4 + +/** + * @brief A structure used to store compensation values + */ +typedef struct +{ + /** + * @brief Delay compensation values [100 ns units] + * + * @note Only the first value is actually used to compensate + * a delay, so the remaining values should be 0. + */ + int16_t c[N_IRIG_RX_COMP_VAL]; + +} IRIG_RX_COMP; + +#define _mbg_swab_irig_rx_comp( _p ) \ +do \ +{ \ + int i; \ + for ( i = 0; i < N_IRIG_RX_COMP_VAL; i++ ) \ + _mbg_swab16( &(_p)->c[i] ); \ +} while ( 0 ) + + +/** The absolute value of the maximum compensation value accepted by a device */ +#define IRIG_RX_COMP_MAX 999 // [100 ns units], i.e. valid range is +/-99.9 us + + + +/** + * @brief Structure used to retrieve the number of records for a given type + */ +typedef struct +{ + uint16_t type; ///< record type, see ::CAL_REC_TYPES + uint16_t idx; ///< index if several records of same type are supported, see ::IRIG_RX_COMP_GROUPS + +} CAL_REC_HDR; + +#define _mbg_swab_cal_rec_hdr( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->type ); \ + _mbg_swab16( &(_p)->idx ); \ +} while ( 0 ) + + +/** + * @brief Types to be used with ::CAL_REC_HDR::type + */ +enum CAL_REC_TYPES +{ + CAL_REC_TYPE_UNDEF, ///< undefined type + CAL_REC_TYPE_IRIG_RX_COMP, ///< IRIG receiver delay compensation + N_CAL_REC_TYPE ///< number of known types +}; + + +/** + * @brief Types to be used with ::CAL_REC_HDR::idx + * + * IRIG frame type groups to be distinguished for delay compensation. + */ +enum IRIG_RX_COMP_GROUPS +{ + IRIG_RX_COMP_B1, ///< codes B1xx, AFNOR, IEEE1344 + IRIG_RX_COMP_A1, ///< code A1xx + IRIG_RX_COMP_B0, ///< codes B0xx, AFNOR DC, IEEE1344 DC + IRIG_RX_COMP_A0, ///< code A0xx + IRIG_RX_COMP_G1, ///< code G14x + IRIG_RX_COMP_G0, ///< code G00x + N_IRIG_RX_COMP ///< number of compensation values +}; + + +/** + * @brief Initializers for format name strings + */ +#define DEFAULT_IRIG_RX_COMP_NAMES \ +{ \ + "B1xx/AFNOR/IEEE1344", \ + "A1xx", \ + "B0xx/AFNOR DC/IEEE1344 DC", \ + "A0xx", \ + "G14X", \ + "G00X", \ } -// The type below is used to read the board's debug status -// which also include IRIG decoder status: -typedef uint32_t MBG_DEBUG_STATUS; -// The debug status is bit coded as defined below: -enum +/** + * @brief Structure used to transfer calibration records + */ +typedef struct { - MBG_IRIG_BIT_WARMED_UP, /**< Osc has warmed up */ - MBG_IRIG_BIT_PPS_ACTIVE, /**< PPS output is active */ - MBG_IRIG_BIT_INV_CONFIG, /**< Invalid config, e.g. data csum error */ - MBG_IRIG_BIT_MSG_DECODED, /**< IRIG msg could be decoded */ - MBG_IRIG_BIT_MSG_INCONSISTENT, /**< IRIG msg contains inconsistent data */ - MBG_IRIG_BIT_LOOP_LOCKED, /**< Decoder control loop is locked */ - MBG_IRIG_BIT_JITTER_TOO_LARGE, /**< Phase jitter too large */ - MBG_IRIG_BIT_INV_REF_OFFS, /**< UTC ref offset not configured */ + CAL_REC_HDR hdr; ///< data header + IRIG_RX_COMP comp_data; ///< IRIG receiver delay compensation + +} CAL_REC_IRIG_RX_COMP; + +#define _mbg_swab_cal_rec_irig_rx_comp( _p ) \ +do \ +{ \ + _mbg_swab_cal_rec_hdr( &(_p)->hdr ); \ + _mbg_swab_irig_rx_comp( &(_p)->comp_data ); \ +} while ( 0 ) + +/** @} defgroup group_irig_comp */ + + + +/** + * @brief A data type used to read the board's debug status + * + * @note This also includes IRIG decoder status. + * + * @see @ref MBG_DEBUG_STATUS_BIT_MASKS + */ +typedef uint32_t MBG_DEBUG_STATUS; + +#define _mbg_swab_debug_status( _p ) \ + _mbg_swab32( _p ) - MBG_SYS_BIT_INV_TIME, /**< Internal time not valid/set */ - MBG_SYS_BIT_TIME_SET_VIA_API, /**< On board time set externally */ - MBG_SYS_BIT_INV_RTC, /**< On board RTC invalid */ - MBG_SYS_BIT_CPU_PLL_FAILED, /**< The CPU's PLL watchdog */ - N_MBG_DEBUG_BIT + +/** + * @brief Enumeration of flag bits used for debug status + * + * @see @ref MBG_DEBUG_STATUS_BIT_MASKS + */ +enum MBG_DEBUG_STATUS_BITS +{ + MBG_IRIG_BIT_WARMED_UP, ///< Osc has warmed up + MBG_IRIG_BIT_PPS_ACTIVE, ///< PPS output is active + MBG_IRIG_BIT_INV_CONFIG, ///< Invalid config, e.g. data csum error + MBG_IRIG_BIT_MSG_DECODED, ///< IRIG msg could be decoded + MBG_IRIG_BIT_MSG_INCONSISTENT, ///< IRIG msg contains inconsistent data + MBG_IRIG_BIT_LOOP_LOCKED, ///< Decoder control loop is locked + MBG_IRIG_BIT_JITTER_TOO_LARGE, ///< Phase jitter too large + MBG_IRIG_BIT_INV_REF_OFFS, ///< %UTC ref offset not configured + + MBG_SYS_BIT_INV_TIME, ///< Internal time not valid/set + MBG_SYS_BIT_TIME_SET_VIA_API, ///< On board time set externally + MBG_SYS_BIT_INV_RTC, ///< On board RTC invalid + MBG_SYS_BIT_CPU_PLL_FAILED, ///< The CPU's PLL watchdog + + N_MBG_DEBUG_BIT ///< The number of known bits }; -/* - * Initializers for IRIG status bit strings. +/** + * @brief Initializers for debug status bit strings + * + * @see ::MBG_DEBUG_STATUS_BITS */ #define MBG_DEBUG_STATUS_STRS \ { \ @@ -2674,6 +5110,12 @@ enum } +/** + * @brief Bit masks used with ::MBG_DEBUG_STATUS + * + * @see ::MBG_DEBUG_STATUS_BITS + * + * @anchor MBG_DEBUG_STATUS_BIT_MASKS @{ */ #define MBG_IRIG_MSK_WARMED_UP ( 1UL << MBG_IRIG_BIT_WARMED_UP ) #define MBG_IRIG_MSK_PPS_ACTIVE ( 1UL << MBG_IRIG_BIT_PPS_ACTIVE ) @@ -2689,73 +5131,133 @@ enum #define MBG_SYS_MSK_INV_RTC ( 1UL << MBG_SYS_BIT_INV_RTC ) #define MBG_SYS_MSK_CPU_PLL_FAILED ( 1UL << MBG_SYS_BIT_CPU_PLL_FAILED ) +/** @} anchor MBG_DEBUG_STATUS_BIT_MASKS */ -typedef int16_t MBG_REF_OFFS; /**< -MBG_REF_OFFS_MAX..MBG_REF_OFFS_MAX */ +/** + * @brief A data type used to configure the ref offset + * + * The ref offset if the offset of the incoming reference time from %UTC. + * For some types of signal (e.g. most IRIG frame formats) this can't be + * determined automatically. + * + * Valid range: -::MBG_REF_OFFS_MAX..::MBG_REF_OFFS_MAX, or ::MBG_REF_OFFS_NOT_CFGD + * + * @note There's a special flag ::MBG_REF_OFFS_NOT_CFGD indicating that + * this parameter is unconfigured, in which case a Meinberg time code + * receiver refuses to synchronize to the time code signal unless a time + * code frame has been configured which provides the UTC offset (namely + * IEEE 1344 or IEEE C37.118). + */ +typedef int16_t MBG_REF_OFFS; #define _mbg_swab_mbg_ref_offs( _p ) _mbg_swab16( (_p) ) -/** the maximum allowed positive / negative offset */ +/** + * @brief The maximum allowed positive / negative ref offset + */ #define MBG_REF_OFFS_MAX ( ( 12L * 60 ) + 30 ) // [minutes] /** - * the following value is used to indicate that the ref offset - * value has not yet been configured + * @brief A flag indicating that the ref offset has not yet been configured + * + * If this flag is set in ::MBG_REF_OFFS this means the ref offset + * (time offset from %UTC) has not yet been configured. This is usually + * the case for IRIG receiver devices right after they have been shipped. */ -#define MBG_REF_OFFS_NOT_CFGD 0x8000 +#define MBG_REF_OFFS_NOT_CFGD ( (MBG_REF_OFFS) 0x8000 ) + +/** + * @brief A structure used to configure optional settings + * + * Optional settings are a generic way to configure some extended settings. + */ typedef struct { - uint32_t flags; + uint32_t flags; ///< @see ::MBG_OPT_FLAGS + } MBG_OPT_SETTINGS; #define _mbg_swab_mbg_opt_settings( _p ) \ +do \ { \ _mbg_swab32( &(_p)->flags ); \ -} +} while ( 0 ) +/** + * @brief A structure used to configure optional settings + * + * This structure includes the current settings, and a bit mask + * indicating which flags are supported. + */ typedef struct { - MBG_OPT_SETTINGS settings; - uint32_t supp_flags; + MBG_OPT_SETTINGS settings; ///< current settings + uint32_t supp_flags; ///< bit mask of supported flags, see ::MBG_OPT_FLAGS + } MBG_OPT_INFO; #define _mbg_swab_mbg_opt_info( _p ) \ +do \ { \ _mbg_swab_mbg_opt_settings( &(_p)->settings ); \ _mbg_swab32( &(_p)->supp_flags ); \ -} +} while ( 0 ) -enum +/** + * @brief Enumeration of flag bits used to define ::MBG_OPT_FLAGS + */ +enum MBG_OPT_BITS { - MBG_OPT_BIT_STR_UTC, /**< serial string contains UTC time */ - MBG_OPT_BIT_EMU_SYNC, /**< emulate/pretend to be synchronized, */ - /**< alternatively GPS_FEAT_IGNORE_LOCK may be supported */ + MBG_OPT_BIT_STR_UTC, ///< serial time string contains %UTC time + MBG_OPT_BIT_EMU_SYNC, ///< always pretend to be synchronized, alternatively ::GPS_FEAT_IGNORE_LOCK may be supported N_MBG_OPT_BIT }; -/* - * Bit masks corresponding to the enumeration above: + +/** + * @brief Bit masks according to ::MBG_OPT_BITS + * + * Used with ::MBG_OPT_SETTINGS::flags and ::MBG_OPT_INFO::supp_flags. */ -#define MBG_OPT_FLAG_STR_UTC ( 1UL << MBG_OPT_BIT_STR_UTC ) -#define MBG_OPT_FLAG_EMU_SYNC ( 1UL << MBG_OPT_BIT_EMU_SYNC ) +enum MBG_OPT_FLAGS +{ + MBG_OPT_FLAG_STR_UTC = ( 1UL << MBG_OPT_BIT_STR_UTC ), ///< see ::MBG_OPT_BIT_STR_UTC + MBG_OPT_FLAG_EMU_SYNC = ( 1UL << MBG_OPT_BIT_EMU_SYNC ) ///< see ::MBG_OPT_BIT_EMU_SYNC +}; -// bit coded return type for PCPS_GET_IRIG_CTRL_BITS -typedef uint32_t MBG_IRIG_CTRL_BITS; +/** + * @brief Bit coded return type for ::PCPS_GET_IRIG_CTRL_BITS + * + * The control bits a time code receiver has decoded from + * the incoming time code signal. + * + * @note ::MBG_RAW_IRIG_DATA is more versatile and should + * be used preferably, if supported. + * + * @see ::MBG_RAW_IRIG_DATA + */ +typedef uint32_t MBG_IRIG_CTRL_BITS; #define _mbg_swab_irig_ctrl_bits( _p ) _mbg_swab32( _p ) -// The following macro extracts the 4 bit TFOM code from the -// IRIG control bits read from a card. This only works if the received -// IRIG code is a code which supports TFOM, this is currently -// only IEEE1344. +/** + * @brief Extract the TFOM code from ::MBG_IRIG_CTRL_BITS + * + * The resulting code is only valid if the configured IRIG code frame format + * supports this. See @ref MSK_ICODE_TX_HAS_TFOM and @ref MSK_ICODE_RX_HAS_TFOM + * + * As specified in the IEEE 1344 standard as "Time Quality", the TFOM code is + * the range 0x0 (locked, maximum accuracy) to 0xF (failed, data unreliable). + */ #define _pcps_tfom_from_irig_ctrl_bits( _p ) \ ( ( ( *(_p) ) >> 24 ) & 0x0F ) @@ -2764,24 +5266,33 @@ typedef uint32_t MBG_IRIG_CTRL_BITS; #define RAW_IRIG_SIZE 16 /** - The buffer below can be used to get the raw data bits - from the IRIG decoder. A maximum number of RAW_IRIG_SIZE - bytes can be filled. If less bytes are used then the rest - of the bytes are filled with zeros. - - The first IRIG bit received from the transmitter is saved - in the MSB (bit 7) of data_bytes[0], etc. -*/ + * @brief A buffer used to read raw IRIG data bits from an IRIG receiver + * + * Used to get the raw data bits from the IRIG decoder. A maximum number + * of ::RAW_IRIG_SIZE bytes can be filled up, depending on the IRIG code. + * If less bytes are used then the rest of the bytes are filled with zeros. + * + * @note The first IRIG bit received from the transmitter is saved + * in the MSB (bit 7) of data_bytes[0], etc. + */ typedef struct { uint8_t data_bytes[RAW_IRIG_SIZE]; + } MBG_RAW_IRIG_DATA; -// The following macro extracts the 4 bit TFOM code from the raw -// data bits read from a card. This only works if the received -// IRIG code is a code which supports TFOM, this is currently -// only IEEE1344. -#define _pcps_tfom_from_raw_irig_data( _p ) \ +#define _mbg_swab_mbg_raw_irig_data( _p ) _nop_macro_fnc() + +/** + * @brief Extract the TFOM code from ::MBG_RAW_IRIG_DATA + * + * The resulting code is only valid if the configured IRIG code frame format + * supports this. See @ref MSK_ICODE_TX_HAS_TFOM and @ref MSK_ICODE_RX_HAS_TFOM + * + * As specified in the IEEE 1344 standard as "Time Quality", the TFOM code is + * the range 0x0 (locked, maximum accuracy) to 0xF (failed, data unreliable). + */ +#define _pcps_tfom_from_raw_irig_data( _p ) \ ( ( ( (_p)->data_bytes[9] >> 2 ) & 0x08 ) \ | ( ( (_p)->data_bytes[9] >> 4 ) & 0x04 ) \ | ( ( (_p)->data_bytes[9] >> 6 ) & 0x02 ) \ @@ -2790,32 +5301,43 @@ typedef struct /** - @defgroup group_time_scale Time Scale Configuration - - The structures and defines can be used to configure the GPS receiver's - basic time scale. By default this is UTC which can optionally - be converted to some local time. However, some applications - prefer TAI or pure GPS time. This can be configured using the - structures below if the GPS_HAS_TIME_SCALE flag is set in - RECEIVER_INFO::features. - @{ -*/ + * @defgroup group_time_scale Time Scale Configuration + * + * Used to configure the GPS receiver's basic time scale. + * By default this is %UTC which can optionally be converted + * to some local time. However, some applications prefer + * TAI or pure GPS time. This can be configured using the + * structures below if the ::GPS_HAS_TIME_SCALE flag is set + * in ::RECEIVER_INFO::features. + * + * @{ */ -enum +/** + * @brief Known time scales + * + * @see ::MBG_TIME_SCALE_MASKS + * @see ::TM_SCALE_GPS + * @see ::TM_SCALE_TAI + */ +enum MBG_TIME_SCALES { - MBG_TIME_SCALE_DEFAULT, /**< UTC or local time, t_gps - deltat_ls */ - MBG_TIME_SCALE_GPS, /**< GPS time, monotonical */ - MBG_TIME_SCALE_TAI, /**< TAI, t_gps + GPS_TAI_OFFSET seconds */ + MBG_TIME_SCALE_DEFAULT, ///< %UTC or local time according to ::UTC parameters and ::TZDL configuration + MBG_TIME_SCALE_GPS, ///< GPS time as sent by the satellites, monotonical + MBG_TIME_SCALE_TAI, ///< TAI, i.e. GPS time plus constant offset (see ::GPS_TAI_OFFSET) N_MBG_TIME_SCALE }; -#define MBG_TIME_SCALE_MSK_DEFAULT ( 1UL << MBG_TIME_SCALE_DEFAULT ) -#define MBG_TIME_SCALE_MSK_GPS ( 1UL << MBG_TIME_SCALE_GPS ) -#define MBG_TIME_SCALE_MSK_TAI ( 1UL << MBG_TIME_SCALE_TAI ) - -// See also the extended status bits TM_SCALE_GPS and TM_SCALE_TAI -// indicating the active time scale setting. - +/** + * @brief Bit masks for known time scales + * + * @see ::MBG_TIME_SCALES + */ +enum MBG_TIME_SCALE_MASKS +{ + MBG_TIME_SCALE_MSK_DEFAULT = ( 1UL << MBG_TIME_SCALE_DEFAULT ), ///< see ::MBG_TIME_SCALE_DEFAULT + MBG_TIME_SCALE_MSK_GPS = ( 1UL << MBG_TIME_SCALE_GPS ), ///< see ::MBG_TIME_SCALE_GPS + MBG_TIME_SCALE_MSK_TAI = ( 1UL << MBG_TIME_SCALE_TAI ) ///< see ::MBG_TIME_SCALE_TAI +}; #define MBG_TIME_SCALE_STRS \ { \ @@ -2827,70 +5349,87 @@ enum /** - The fixed time offset between the GPS and TAI time scales, in seconds -*/ -#define GPS_TAI_OFFSET 19 /**< [s], TAI = GPS + GPS_TAI_OFFSET */ + * @brief The constant time offset between the GPS and TAI time scales, in seconds + */ +#define GPS_TAI_OFFSET 19 ///< [s], TAI = GPS + GPS_TAI_OFFSET +/** + * @brief Time scale configuration settings + */ typedef struct { - uint8_t scale; /**< current time scale code from the enum above */ - uint8_t flags; /**< reserved, currently always 0 */ + uint8_t scale; ///< current time scale code, see ::MBG_TIME_SCALES + uint8_t flags; ///< reserved, don't use, currently always 0 + } MBG_TIME_SCALE_SETTINGS; #define _mbg_swab_mbg_time_scale_settings( _p ) \ _nop_macro_fnc() +/** + * @brief Time scale configuration settings plus capabilities + */ typedef struct { - MBG_TIME_SCALE_SETTINGS settings; /**< current settings */ - MBG_TIME_SCALE_SETTINGS max_settings; /**< numb. of scales, all supported flags */ - uint32_t supp_scales; /**< bit masks of supported scales */ + MBG_TIME_SCALE_SETTINGS settings; ///< current settings + MBG_TIME_SCALE_SETTINGS max_settings; ///< number of scales, all supported flags + uint32_t supp_scales; ///< bit masks of supported scales, see ::MBG_TIME_SCALE_MASKS + } MBG_TIME_SCALE_INFO; #define _mbg_swab_mbg_time_scale_info( _p ) \ +do \ { \ _mbg_swab_mbg_time_scale_settings( &(_p)->settings ); \ _mbg_swab_mbg_time_scale_settings( &(_p)->max_settings ); \ _mbg_swab32( &(_p)->supp_scales ); \ -} +} while ( 0 ) -/** @} group_time_scale */ +/** @} defgroup group_time_scale */ -/* - * The structures below are required to setup the programmable + +/** + * @defgroup group_pout_api Programmable Output API + * + * These structures below are used to configure the programmable * pulse outputs which are provided by some GPS receivers. * The number of programmable pulse outputs supported by a GPS - * receiver is reported in the RECEIVER_INFO.n_str_type field. - */ + * receiver is reported in the RECEIVER_INFO::n_prg_out field. + * + * @{ */ + /** - * The structure is used to define a date of year: + * @brief A calendar date including full year number */ typedef struct { - uint8_t mday; /* 1..28,29,30,31 */ - uint8_t month; /* 1..12 */ - uint16_t year; /* including century */ + uint8_t mday; ///< 1..28,29,30,31 + uint8_t month; ///< 1..12 + uint16_t year; ///< including century + } MBG_DATE; #define _mbg_swab_mbg_date( _p ) \ +do \ { \ _mbg_swab16( &(_p)->year ); \ -} +} while ( 0 ) /** - * The structure is used to define a time of day: + * @brief The time of day including hundredths of seconds */ typedef struct { - uint8_t hour; /**< 0..23 */ - uint8_t min; /**< 0..59 */ - uint8_t sec; /**< 0..59,60 */ - uint8_t sec100; /**< reserved, currently always 0 */ + uint8_t hour; ///< 0..23 + uint8_t min; ///< 0..59 + uint8_t sec; ///< 0..59,60 + uint8_t sec100; ///< 100ths of seconds + } MBG_TIME; #define _mbg_swab_mbg_time( _p ) \ @@ -2898,107 +5437,490 @@ typedef struct /** - * The structure defines a single date and time - * for switching operations: + * @brief Date and time specification for switching operations */ typedef struct { - MBG_DATE d; /* date to switch */ - MBG_TIME t; /* time to switch */ - uint8_t wday; /* reserved, currently always 0 */ - uint8_t flags; /* reserved, currently 0 */ + MBG_DATE d; ///< date to switch + MBG_TIME t; ///< time to switch + uint8_t wday; ///< reserved, currently always 0 + uint8_t flags; ///< reserved, currently 0 + } MBG_DATE_TIME; #define _mbg_swab_mbg_date_time( _p ) \ +do \ { \ _mbg_swab_mbg_date( &(_p)->d ); \ _mbg_swab_mbg_time( &(_p)->t ); \ -} +} while ( 0 ) /** - * The structure defines times and dates - * for an on/off cycle: + * @brief A structure to define on/off cycle times + * + * @note The ::MBG_TIME::sec100 field in ::POUT_TIME:on and + * ::POUT_TIME:off is not evaluated by the firmware and thus + * should always be set to 0. */ typedef struct { - MBG_DATE_TIME on; /* time and date to switch on */ - MBG_DATE_TIME off; /* time and date to switch off */ + MBG_DATE_TIME on; ///< date and time to switch on + MBG_DATE_TIME off; ///< date and time to switch off + } POUT_TIME; #define _mbg_swab_pout_time( _p ) \ +do \ { \ _mbg_swab_mbg_date_time( &(_p)->on ); \ _mbg_swab_mbg_date_time( &(_p)->off ); \ -} +} while ( 0 ) + + + +/** + * @brief The number of ::POUT_TIME settings for each programmable pulse output + * + * @note This can't be changed without breaking compatibility of the API + */ +#define N_POUT_TIMES 3 + +/** + * @brief A Generic data field for programmable output settings + */ +typedef union +{ + /// Switching times. See ::POUT_MODES_DATA_TM, ::POUT_MODES_DATA_TM_0 + POUT_TIME tm[N_POUT_TIMES]; + + uint8_t b[N_POUT_TIMES * sizeof( POUT_TIME )]; + + /// Only if ::POUT_SUPP_PULSE_SHIFT is set, this field can be used to + /// configure the time interval in [ns] by which output pulse slopes are + /// to be shifted. The configured pulse shift must be in the range + /// ::DEFAULT_POUT_PULSE_SHIFT_MIN through ::DEFAULT_POUT_PULSE_SHIFT_MAX. + /// The resolution / steps at which the pulse shift interval can be configured + /// is returned in ::POUT_INFO::pulse_shift_res. + /// @see ::POUT_MODES_DATA_PULSE_SHIFT + int32_t pulse_shift; + +} POUT_DATA; + +#define DEFAULT_POUT_PULSE_SHIFT_MIN -500000000L ///< Default minimum value for ::POUT_DATA::pulse_shift, in [ns] +#define DEFAULT_POUT_PULSE_SHIFT_MAX 499000000L ///< Default maximum value for ::POUT_DATA::pulse_shift, in [ns] /** - * The number of POUT_TIMEs for each programmable pulse output + * @brief Convert ::POUT_DATA endianess depending on the mode + * + * Assuming the mode is passed to the macro with correct endianess. */ -#define N_POUT_TIMES 3 +#define _mbg_swab_pout_data( _p, _mode ) \ +do \ +{ \ + uint32_t mode_mask = 1UL << _mode; \ + \ + if ( mode_mask & POUT_MODES_DATA_TM ) \ + { \ + int i; \ + \ + for ( i = 0; i < N_POUT_TIMES; i++ ) \ + _mbg_swab_pout_time( &(_p)->tm[i] ); \ + } \ + else \ + { \ + if ( mode_mask & POUT_MODES_DATA_TM_0 ) \ + _mbg_swab_pout_time( &(_p)->tm[0] ); \ + else \ + if ( mode_mask & POUT_MODES_DATA_PULSE_SHIFT ) \ + _mbg_swab32( &(_p)->pulse_shift ); \ + } \ + \ +} while ( 0 ) + + /** - * The structure is used to configure a single programmable - * pulse output. + * @brief Configuration settings for a single programmable pulse output */ typedef struct { - uint16_t mode; /**< mode of operation, codes defined below */ - uint16_t pulse_len; /**< 10 msec units, or COM port number */ - uint16_t timeout; /**< [min], for dcf_mode */ - uint16_t flags; /**< see below */ - POUT_TIME tm[N_POUT_TIMES]; /**< switching times */ + uint16_t mode; ///< Mode of operation, see ::POUT_MODES + uint16_t mode_param; ///< Optional parameter depending on the mode, see @ref POUT_MODES_PARAM_MASKS + + /// Timeout [min] which can be specified for some modes, see ::POUT_MODES_TIMEOUT, ::MAX_POUT_DCF_TIMOUT. + /// + /// If the clock looses synchronization then the output + /// - is disabled **immediately** if ::POUT_IF_SYNC_ONLY is set in ::POUT_SETTINGS::flags + /// - is disabled after ::POUT_SETTINGS::timeout, if timeout is not 0 (see ::MAX_POUT_DCF_TIMOUT) + /// - stays enabled if timeout is 0 **and** ::POUT_IF_SYNC_ONLY is **not** set + uint16_t timeout; + + uint16_t flags; ///< @see ::POUT_SETTINGS_FLAGS + POUT_DATA pout_data; ///< Additional configuration data, see ::POUT_DATA + } POUT_SETTINGS; -#define _mbg_swab_pout_settings( _p ) \ -{ \ - int i; \ - _mbg_swab16( &(_p)->mode ); \ - _mbg_swab16( &(_p)->pulse_len ); \ - _mbg_swab32( &(_p)->timeout ); \ - _mbg_swab16( &(_p)->flags ); \ - \ - for ( i = 0; i < N_POUT_TIMES; i++ ) \ - _mbg_swab_pout_time( &(_p)->tm[i] ); \ -} +/** + * @brief Convert ::POUT_SETTINGS endianess after reading from a device + */ +#define _mbg_swab_pout_settings_on_get( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->mode ); \ + _mbg_swab16( &(_p)->mode_param ); \ + _mbg_swab16( &(_p)->timeout ); \ + _mbg_swab16( &(_p)->flags ); \ + _mbg_swab_pout_data( &(_p)->pout_data, (_p)->mode ); \ +} while ( 0 ) + +/** + * @brief Convert ::POUT_SETTINGS endianess before writing to a device + */ +#define _mbg_swab_pout_settings_on_set( _p ) \ +do \ +{ \ + _mbg_swab_pout_data( &(_p)->pout_data, (_p)->mode ); \ + _mbg_swab16( &(_p)->mode ); \ + _mbg_swab16( &(_p)->mode_param ); \ + _mbg_swab16( &(_p)->timeout ); \ + _mbg_swab16( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Definitions used with ::POUT_TIME_SLOTS mode + * + * If ::POUT_SETTINGS::mode is set to ::POUT_TIME_SLOTS then the number + * of time slots per minute is stored in ::POUT_SETTINGS::mode_param. + * Valid numbers are all numbers n in the range ::MIN_TIME_SLOTS_PER_MINUTE + * to ::MAX_TIME_SLOTS_PER_MINUTE for which the remainder of 60 / n is 0. + * @see ::POUT_MODES_MODE_PARAM_AS_SLOTS_PER_MIN + * + * @anchor POUT_TIME_SLOTS_MODE_DEFS @{ */ + +#define MIN_TIME_SLOTS_PER_MINUTE 1 +#define MAX_TIME_SLOTS_PER_MINUTE 60 +#define TIME_SLOT_REGISTER_IN_SEC 60 + +#define TIMEOUT_DIVIDED_BY 10 +#define TIME_SLOT_SWITCH_OFF_BUFFER_MIN 50 / TIMEOUT_DIVIDED_BY +#define TIME_SLOT_SWITCH_OFF_BUFFER_MAX 500 / TIMEOUT_DIVIDED_BY +#define TIME_SLOT_SWITCH_OFF_BUFFER_STD 500 / TIMEOUT_DIVIDED_BY +#define TIME_SLOT_SWITCH_OFF_BUFFER_STEP_SIZE 50 / TIMEOUT_DIVIDED_BY + +#define _valid_time_slots_per_minute( _n ) \ + ( ( (_n) >= MIN_TIME_SLOTS_PER_MINUTE ) && \ + ( (_n) <= MAX_TIME_SLOTS_PER_MINUTE ) && \ + ( ( 60 % (_n) ) == 0 ) \ + ) + +/** @} anchor POUT_TIME_SLOTS_MODE_DEFS */ + -#define MAX_POUT_PULSE_LEN 1000 /**< 10 secs, in 10 msec units */ -#define MAX_POUT_DCF_TIMOUT ( 48 * 60 ) /**< 48 hours, in minutes */ +#define MAX_POUT_PULSE_LEN 1000 ///< 10 secs, in 10 msec units +#define MAX_POUT_DCF_TIMOUT ( 48 * 60 ) ///< 48 hours, in minutes + /** - * These codes are defined for POUT_SETTINGS.mode to setup - * the basic mode of operation for a single programmable pulse - * output: + * @brief Enumeration of known operation modes for programmable pulse outputs + * + * These codes are used with ::POUT_SETTINGS::mode. One or more of + * the remaining fields in ::POUT_SETTINGS are evaluated depending + * on the selected mode. Unused fields should be set to 0. + * + * Unless ::POUT_NOT_INVERTIBLE is set in ::POUT_INFO::flags + * the output signal level can be inverted if ::POUT_INVERTED + * is set in ::POUT_SETTINGS::flags. + * + * @note Not every programmable pulse output supports all modes. + * + * @see @ref POUT_MODE_MASKS + * @see @ref POUT_MODES_PARAM_MASKS + * @see @ref ENG_POUT_NAMES + * @see @ref ENG_POUT_HINTS */ -enum +enum POUT_MODES { - POUT_IDLE, /**< always off, or on if POUT_INVERTED */ - POUT_TIMER, /**< switch on/off at configured times */ - POUT_SINGLE_SHOT, /**< pulse at time POUT_SETTINGS.tm[0].on */ - POUT_CYCLIC_PULSE, /**< pulse every POUT_SETTINGS.tm[0].on.t interval */ - POUT_PER_SEC, /**< pulse if second changes */ - POUT_PER_MIN, /**< pulse if minute changes */ - POUT_PER_HOUR, /**< pulse if hour changes */ - POUT_DCF77, /**< emulate DCF77 signal */ - POUT_POS_OK, /**< on if pos. OK (nav_solved) */ - POUT_TIME_SYNC, /**< on if time sync (time_syn) */ - POUT_ALL_SYNC, /**< on if pos. OK and time sync */ - POUT_TIMECODE, /**< IRIG/AFNOR DCLS output */ - POUT_TIMESTR, /**< COM port number in pulse_len field */ - POUT_10MHZ, /**< 10 MHz fixed frequency */ - POUT_DCF77_M59, /**< DCF77-like signal with 500 ms pulse in 59th second */ - POUT_SYNTH, /**< programmable synthesizer frequency */ - N_POUT_MODES + /// Output is normally always 'off', or always 'on', if flag ::POUT_INVERTED is set. + POUT_IDLE, + + /// Switch 'on' or 'off' at the times specified in ::POUT_DATA::tm. + POUT_TIMER, + + /// Generate a pulse at the time specified in ::POUT_SETTINGS::pout_data::tm[0]::on. + /// Pulse length according to ::POUT_SETTINGS::mode_param, in [10 ms] units. + /// See ::MAX_POUT_PULSE_LEN. + POUT_SINGLE_SHOT, + + /// Generate a cyclic pulse at the interval specified in ::POUT_SETTINGS::pout_data::tm[0]:on::t. + /// Pulse length according to ::POUT_SETTINGS::mode_param, in [10 ms] units. + /// See ::MAX_POUT_PULSE_LEN. + POUT_CYCLIC_PULSE, + + /// Generate a pulse whenever the second changes. + /// Pulse length according to ::POUT_SETTINGS::mode_param, in [10 ms] units. + /// See ::MAX_POUT_PULSE_LEN. + POUT_PER_SEC, + + /// Generate a pulse whenever the minute changes. + /// Pulse length according to ::POUT_SETTINGS::mode_param, in [10 ms] units. + /// See ::MAX_POUT_PULSE_LEN. + POUT_PER_MIN, + + /// Generate a pulse whenever the hour changes. + /// Pulse length according to ::POUT_SETTINGS::mode_param, in [10 ms] units. + /// See ::MAX_POUT_PULSE_LEN. + POUT_PER_HOUR, + + /// Generate DCF77-compatible second marks. + /// See ::POUT_DCF77_M59, ::POUT_SETTINGS::timeout and ::MAX_POUT_DCF_TIMOUT. + POUT_DCF77, + + /// Output switched on if receiver position verified (condition nav_solved). + POUT_POS_OK, + + /// Output switched on if time synchronized (condition time_syn). + POUT_TIME_SYNC, + + /// Output switched on if both position verified and time synchronized. + POUT_ALL_SYNC, + + /// IRIG/AFNOR DCLS time code signal mapped to this output. + POUT_TIMECODE, + + /// Serial time string of one one of the serial ports mapped to this output. + /// ::POUT_SETTINGS::mode_param contains the number of the COM port. + /// See ::MAX_POUT_TIMESTR_PORTS. + POUT_TIMESTR, + + /// 10 MHz fixed frequency output. + POUT_10MHZ, + + /// DCF77-like signal with extra 500 ms pulse in the 59th second + /// (the original DCF77 signal has no such pulse). See ::POUT_DCF77, + /// ::POUT_SETTINGS::timeout and ::MAX_POUT_DCF_TIMOUT. + POUT_DCF77_M59, + + /// Output signal generated by the programmable frequency synthesizer. + POUT_SYNTH, + + /// Programmable time slots during each minute. + /// ::POUT_SETTINGS::mode_param specifies the time slots per minute. + /// Uses ::POUT_DATA. ::TODO + POUT_TIME_SLOTS, + + /// A GPIO input or output signal is reflected at this pulse output. + /// ::POUT_SETTINGS::mode_param specifies the GPIO number which must + /// be in the range 0..::MBG_GPIO_CFG_LIMITS::num_io. + POUT_GPIO, + + /// A 1 PPS signal with a fixed 20 us pulse length + POUT_PTTI_PPS, + + /// A HaveQuick signal as configured in ::HAVEQUICK_SETTINGS::format + POUT_HAVEQUICK, + + // New modes have to be added here at the end of the enumeration, and the + // POUT_MODE_MASKS, the POUT_MODES_PARAM_MASKS as well as string initializers + // (also in pcpslstr.h) have to be updated accordingly. + N_POUT_MODES ///< the number of known modes }; -/* - * Default initializers for English pulse mode names. Initializers - * for multi-language strings can be found in pcpslstr.h. +/** + * @brief Bit masks associated with ::POUT_MODES + * + * Used with ::POUT_INFO::supp_modes to specify which ::POUT_MODES + * are supported for a particular programmable output. + * + * @see ::POUT_MODES + * + * @anchor POUT_MODE_MASKS @{ */ + +#define MSK_POUT_IDLE ( 1UL << POUT_IDLE ) ///< see ::POUT_IDLE +#define MSK_POUT_TIMER ( 1UL << POUT_TIMER ) ///< see ::POUT_TIMER +#define MSK_POUT_SINGLE_SHOT ( 1UL << POUT_SINGLE_SHOT ) ///< see ::POUT_SINGLE_SHOT +#define MSK_POUT_CYCLIC_PULSE ( 1UL << POUT_CYCLIC_PULSE ) ///< see ::POUT_CYCLIC_PULSE +#define MSK_POUT_PER_SEC ( 1UL << POUT_PER_SEC ) ///< see ::POUT_PER_SEC +#define MSK_POUT_PER_MIN ( 1UL << POUT_PER_MIN ) ///< see ::POUT_PER_MIN +#define MSK_POUT_PER_HOUR ( 1UL << POUT_PER_HOUR ) ///< see ::POUT_PER_HOUR +#define MSK_POUT_DCF77 ( 1UL << POUT_DCF77 ) ///< see ::POUT_DCF77 +#define MSK_POUT_POS_OK ( 1UL << POUT_POS_OK ) ///< see ::POUT_POS_OK +#define MSK_POUT_TIME_SYNC ( 1UL << POUT_TIME_SYNC ) ///< see ::POUT_TIME_SYNC +#define MSK_POUT_ALL_SYNC ( 1UL << POUT_ALL_SYNC ) ///< see ::POUT_ALL_SYNC +#define MSK_POUT_TIMECODE ( 1UL << POUT_TIMECODE ) ///< see ::POUT_TIMECODE +#define MSK_POUT_TIMESTR ( 1UL << POUT_TIMESTR ) ///< see ::POUT_TIMESTR +#define MSK_POUT_10MHZ ( 1UL << POUT_10MHZ ) ///< see ::POUT_10MHZ +#define MSK_POUT_DCF77_M59 ( 1UL << POUT_DCF77_M59 ) ///< see ::POUT_DCF77_M59 +#define MSK_POUT_SYNTH ( 1UL << POUT_SYNTH ) ///< see ::POUT_SYNTH +#define MSK_POUT_TIME_SLOTS ( 1UL << POUT_TIME_SLOTS ) ///< see ::POUT_TIME_SLOTS +#define MSK_POUT_GPIO ( 1UL << POUT_GPIO ) ///< see ::POUT_GPIO +#define MSK_POUT_PTTI_PPS ( 1UL << POUT_PTTI_PPS ) ///< see ::POUT_PTTI_PPS +#define MSK_POUT_HAVEQUICK ( 1UL << POUT_HAVEQUICK ) ///< see ::POUT_HAVEQUICK + +/** @} anchor POUT_MODE_MASKS */ + + + +/** + * @brief Bit masks indicating which parameters relevant for which ::POUT_MODES + * + * @see ::POUT_MODES + * @see @ref POUT_MODE_MASKS + * + * @anchor POUT_MODES_PARAM_MASKS @{ */ + + +/** + * @brief POUT modes which use the full ::POUT_DATA::tm array as parameter + */ +#define POUT_MODES_DATA_TM \ +( \ + MSK_POUT_TIMER \ +) + + +/** + * @brief POUT modes which use only ::POUT_DATA::tm[0] as parameter + */ +#define POUT_MODES_DATA_TM_0 \ +( \ + MSK_POUT_SINGLE_SHOT | \ + MSK_POUT_CYCLIC_PULSE \ +) + + +/** + * @brief POUT modes which use ::POUT_SETTINGS::mode_param as pulse length + * + * @see ::MAX_POUT_PULSE_LEN + */ +#define POUT_MODES_MODE_PARAM_AS_PULSE_LEN \ +( \ + MSK_POUT_SINGLE_SHOT | \ + MSK_POUT_CYCLIC_PULSE | \ + MSK_POUT_PER_SEC | \ + MSK_POUT_PER_MIN | \ + MSK_POUT_PER_HOUR \ +) + + +/** + * @brief POUT modes which use ::POUT_SETTINGS::mode_param as COM port index number + */ +#define POUT_MODES_MODE_PARAM_AS_COM_IDX \ +( \ + MSK_POUT_TIMESTR \ +) + + +/** + * @brief POUT modes which use ::POUT_SETTINGS::mode_param as time slots per minute + * + * @see @ref POUT_TIME_SLOTS_MODE_DEFS + */ +#define POUT_MODES_MODE_PARAM_AS_SLOTS_PER_MIN \ +( \ + MSK_POUT_TIME_SLOTS \ +) + + +/** + * @brief POUT modes which use ::POUT_SETTINGS::mode_param as GPIO index number + */ +#define POUT_MODES_MODE_PARAM_AS_GPIO_IDX \ +( \ + MSK_POUT_GPIO \ +) + + +/** + * @brief POUT modes which use ::POUT_SETTINGS::timeout + */ +#define POUT_MODES_TIMEOUT \ +( \ + MSK_POUT_DCF77 | \ + MSK_POUT_DCF77_M59 \ +) + + +/** + * @brief POUT modes which which support ::POUT_TIMEBASE_UTC + */ +#define POUT_MODES_SUPP_TIMEBASE_UTC \ +( \ + MSK_POUT_DCF77 | \ + MSK_POUT_DCF77_M59 \ +) + + +/** + * @brief POUT modes which use ::POUT_DATA::pulse_shift + * + * @note: Supported only if ::POUT_SUPP_PULSE_SHIFT is set + */ +#define POUT_MODES_DATA_PULSE_SHIFT \ +( \ + MSK_POUT_PER_SEC | \ + MSK_POUT_PER_MIN | \ + MSK_POUT_PER_HOUR \ +) + + +/** + * @brief POUT modes which support ::POUT_SUPP_IF_SYNC_ONLY + * + * Even if ::POUT_SUPP_IF_SYNC_ONLY is set in ::POUT_INFO::flags + * the associated flag ::POUT_IF_SYNC_ONLY in ::POUT_SETTINGS::flags + * may be evaluated depending on the mode. + * + * Modes ::POUT_POS_OK, ::POUT_TIME_SYNC, and ::MSK_POUT_ALL_SYNC + * are explicitly excluded. + * + * For modes ::MSK_POUT_DCF77 and ::MSK_POUT_DCF77_M59 see also + * ::POUT_SETTINGS::timeout. */ +#define POUT_MODES_SUPP_IF_SYNC_ONLY \ +( \ + MSK_POUT_IDLE | \ + MSK_POUT_TIMER | \ + MSK_POUT_SINGLE_SHOT | \ + MSK_POUT_CYCLIC_PULSE | \ + MSK_POUT_PER_SEC | \ + MSK_POUT_PER_MIN | \ + MSK_POUT_PER_HOUR | \ + MSK_POUT_DCF77 | \ + MSK_POUT_TIMECODE | \ + MSK_POUT_TIMESTR | \ + MSK_POUT_10MHZ | \ + MSK_POUT_DCF77_M59 | \ + MSK_POUT_SYNTH | \ + MSK_POUT_TIME_SLOTS | \ + MSK_POUT_GPIO | \ + MSK_POUT_PTTI_PPS | \ + MSK_POUT_HAVEQUICK \ +) + +/** @} anchor POUT_MODES_PARAM_MASKS */ + + + +/** + * @brief Name strings associated with ::POUT_MODES + * + * Default initializers for English programmable output mode names. + * Initializers for multi-language strings can be found in pcpslstr.h. + * + * @see ::POUT_MODES + * @see ::DEFAULT_ENG_POUT_NAMES + * + * @anchor ENG_POUT_NAMES @{ */ + #define ENG_POUT_NAME_IDLE "Idle" #define ENG_POUT_NAME_TIMER "Timer" #define ENG_POUT_NAME_SINGLE_SHOT "Single Shot" @@ -3011,11 +5933,24 @@ enum #define ENG_POUT_NAME_TIME_SYNC "Time Sync" #define ENG_POUT_NAME_ALL_SYNC "All Sync" #define ENG_POUT_NAME_TIMECODE "DCLS Time Code" -#define ENG_POUT_NAME_TIMESTR "COM Time String" +#define ENG_POUT_NAME_TIMESTR "Serial Time String" #define ENG_POUT_NAME_10MHZ "10 MHz Frequency" #define ENG_POUT_NAME_DCF77_M59 "DCF77-like M59" #define ENG_POUT_NAME_SYNTH "Synthesizer Frequency" +#define ENG_POUT_NAME_TIME_SLOTS "Time Slots per Minute" +#define ENG_POUT_NAME_GPIO "GPIO Signal" +#define ENG_POUT_PTTI_PPS "PTTI 1 PPS" +#define ENG_POUT_HAVEQUICK "HaveQuick" + +/** @} anchor ENG_POUT_NAMES */ + + +/** + * @brief An initializer for a table of English POUT name strings + * + * @see @ref ENG_POUT_NAMES + */ #define DEFAULT_ENG_POUT_NAMES \ { \ ENG_POUT_NAME_IDLE, \ @@ -3033,10 +5968,25 @@ enum ENG_POUT_NAME_TIMESTR, \ ENG_POUT_NAME_10MHZ, \ ENG_POUT_NAME_DCF77_M59, \ - ENG_POUT_NAME_SYNTH \ + ENG_POUT_NAME_SYNTH, \ + ENG_POUT_NAME_TIME_SLOTS, \ + ENG_POUT_NAME_GPIO, \ + ENG_POUT_PTTI_PPS, \ + ENG_POUT_HAVEQUICK \ } +/** + * @brief Hint strings associated with ::POUT_MODES + * + * Default initializers for English programmable output mode hints. + * Initializers for multi-language strings can be found in pcpslstr.h. + * + * @see ::POUT_MODES + * @see ::DEFAULT_ENG_POUT_HINTS + * + * @anchor ENG_POUT_HINTS @{ */ + #define ENG_POUT_HINT_IDLE "Constant output level" #define ENG_POUT_HINT_TIMER "Switch based on configured on/off times" #define ENG_POUT_HINT_SINGLE_SHOT "Generate a single pulse of determined length" @@ -3053,7 +6003,19 @@ enum #define ENG_POUT_HINT_10MHZ "10 MHz fixed output frequency" #define ENG_POUT_HINT_DCF77_M59 "DCF77 time marks with 500 ms pulse in 59th second" #define ENG_POUT_HINT_SYNTH "Frequency generated by programmable synthesizer" +#define ENG_POUT_HINT_TIME_SLOTS "Output enabled during specified time slots per minute" +#define ENG_POUT_HINT_GPIO "Duplicated signal of the specified GPIO input or output" +#define ENG_POUT_HINT_PTTI_PPS "Generate 20us Pulse at beginning of the second" +#define ENG_POUT_HINT_HAVEQUICK "Duplicated HaveQuick Signal" +/** @} anchor ENG_POUT_HINTS */ + + +/** + * @brief An initializer for a table of English POUT hint strings + * + * @see @ref ENG_POUT_HINTS + */ #define DEFAULT_ENG_POUT_HINTS \ { \ ENG_POUT_HINT_IDLE, \ @@ -3071,145 +6033,278 @@ enum ENG_POUT_HINT_TIMESTR, \ ENG_POUT_HINT_10MHZ, \ ENG_POUT_HINT_DCF77_M59, \ - ENG_POUT_HINT_SYNTH \ + ENG_POUT_HINT_SYNTH, \ + ENG_POUT_HINT_TIME_SLOTS, \ + ENG_POUT_HINT_GPIO, \ + ENG_POUT_HINT_PTTI_PPS, \ + ENG_POUT_HINT_HAVEQUICK \ } -/* - * The definitions below are used to set up bit masks - * which restrict the modes which can be used with - * a given programmable output: - */ -#define MSK_POUT_IDLE ( 1UL << POUT_IDLE ) -#define MSK_POUT_TIMER ( 1UL << POUT_TIMER ) -#define MSK_POUT_SINGLE_SHOT ( 1UL << POUT_SINGLE_SHOT ) -#define MSK_POUT_CYCLIC_PULSE ( 1UL << POUT_CYCLIC_PULSE ) -#define MSK_POUT_PER_SEC ( 1UL << POUT_PER_SEC ) -#define MSK_POUT_PER_MIN ( 1UL << POUT_PER_MIN ) -#define MSK_POUT_PER_HOUR ( 1UL << POUT_PER_HOUR ) -#define MSK_POUT_DCF77 ( 1UL << POUT_DCF77 ) -#define MSK_POUT_POS_OK ( 1UL << POUT_POS_OK ) -#define MSK_POUT_TIME_SYNC ( 1UL << POUT_TIME_SYNC ) -#define MSK_POUT_ALL_SYNC ( 1UL << POUT_ALL_SYNC ) -#define MSK_POUT_TIMECODE ( 1UL << POUT_TIMECODE ) -#define MSK_POUT_TIMESTR ( 1UL << POUT_TIMESTR ) -#define MSK_POUT_10MHZ ( 1UL << POUT_10MHZ ) -#define MSK_POUT_DCF77_M59 ( 1UL << POUT_DCF77_M59 ) -#define MSK_POUT_SYNTH ( 1UL << POUT_SYNTH ) +/** + * @brief Flag bits used to define ::POUT_SETTINGS_FLAGS + * + * @see ::POUT_SETTINGS_FLAGS + */ +enum POUT_SETTINGS_FLAG_BITS +{ + /// Output level is to be inverted. Can only be used + /// if ::POUT_NOT_INVERTIBLE is **not** set, but is + /// supported by all ::POUT_MODES. + POUT_BIT_INVERTED, + + /// Enable output **only** while synchronized. This even overrides + /// the settings in ::ENABLE_FLAGS::pulses, so if this flag is set + /// the output is only enabled if the clock is synchronized, and is + /// disabled when synchronization is lost, i.e. the device enters + /// holdover mode. + /// This flag can only be used with outputs that have ::POUT_SUPP_IF_SYNC_ONLY + /// set, and is only supported for the ::POUT_MODES specified in + /// ::POUT_MODES_SUPP_IF_SYNC_ONLY. + POUT_BIT_IF_SYNC_ONLY, + + /// Output %UTC time instead of local time for DCF77 emulation. + /// This flag can only be used with outputs that have ::POUT_SUPP_DCF77_UTC + /// set, and is only supported for the ::POUT_MODES specified in + /// ::POUT_MODES_SUPP_TIMEBASE_UTC (e.g. ::POUT_DCF77 or ::POUT_DCF77_M59). + POUT_BIT_TIMEBASE_UTC, + + N_POUT_SETTINGS_FLAG_BITS ///< Number of known flag bits +}; -/* - * The codes below are used with POUT_SETTINGS::flags: + +/** + * @brief Flag bit masks used with ::POUT_SETTINGS::flags + * + * @see ::POUT_SETTINGS_FLAG_BITS */ -#define POUT_INVERTED 0x0001 // invert output level -#define POUT_IF_SYNC_ONLY 0x0002 // disable in holdover mode -#define POUT_TIMEBASE_UTC 0x0004 // use UTC, only applicable for DCF77 output +enum POUT_SETTINGS_FLAGS +{ + POUT_INVERTED = ( 1UL << POUT_BIT_INVERTED ), ///< see ::POUT_BIT_INVERTED, ::POUT_NOT_INVERTIBLE + POUT_IF_SYNC_ONLY = ( 1UL << POUT_BIT_IF_SYNC_ONLY ), ///< see ::POUT_BIT_IF_SYNC_ONLY, ::POUT_SUPP_IF_SYNC_ONLY + POUT_TIMEBASE_UTC = ( 1UL << POUT_BIT_TIMEBASE_UTC ) ///< see ::POUT_BIT_TIMEBASE_UTC, ::POUT_SUPP_DCF77_UTC +}; + /** - Since a clock may support more than one programmable - pulse output, setup tools must use the structure below - to read/set pulse output configuration. - The number of outputs supported by a receiver model - can be queried using the RECEIVER_INFO structure. + * @brief Configuration settings for a specific programmable pulse output + * + * This structure can be used to send configuration settings for a specific + * programmable output to a device. + * The number of supported outputs is RECEIVER_INFO::n_prg_out. + * + * @note The ::POUT_INFO_IDX structure should be read from + * a device to retrieve the current settings and capabilities. */ typedef struct { - uint16_t idx; /**< 0..RECEIVER_INFO.n_prg_out-1 */ + uint16_t idx; ///< 0..::RECEIVER_INFO::n_prg_out-1 POUT_SETTINGS pout_settings; + } POUT_SETTINGS_IDX; -#define _mbg_swab_pout_settings_idx( _p ) \ -{ \ - _mbg_swab16( &(_p)->idx ); \ - _mbg_swab_pout_settings( &(_p)->pout_settings ); \ -} +#define _mbg_swab_pout_settings_idx_on_set( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_pout_settings_on_set( &(_p)->pout_settings ); \ +} while ( 0 ) + +#define _mbg_swab_pout_settings_idx_on_get( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_pout_settings_on_get( &(_p)->pout_settings ); \ +} while ( 0 ) /** - The structure below holds the current settings - for a programmable pulse output, plus additional - informaton on the output's capabilities. - This can be read by setup programs to allow setup - of supported features only. + * @brief Current settings and general capabilities of a programmable pulse output + * + * This structure should be read from the device to retrieve the + * current settings of a programmable pulse output plus its capabilities, + * e.g. the supported output modes, etc. + * + * @note The ::POUT_INFO_IDX structure should be used to read + * current settings and capabilities of a specific output. */ typedef struct { POUT_SETTINGS pout_settings; - uint32_t supp_modes; /**< bit mask of modes supp. by this output */ - uint8_t timestr_ports; /**< bit mask of COM ports supported for POUT_TIMESTR */ - uint8_t reserved_0; /**< reserved for future use, currently 0 */ - uint16_t reserved_1; /**< reserved for future use, currently 0 */ - uint32_t flags; /**< see below */ + uint32_t supp_modes; ///< bit mask of modes supp. by this output, see @ref POUT_MODE_MASKS + uint8_t timestr_ports; ///< bit mask of COM ports supported for mode ::POUT_TIMESTR, see ::MAX_POUT_TIMESTR_PORTS + uint8_t pulse_shift_res; ///< pulse shift resolution, in [ns], only if ::POUT_SUPP_PULSE_SHIFT, see ::POUT_DATA::pulse_shift + uint16_t reserved_1; ///< reserved for future use, currently unused and always 0 + uint32_t flags; ///< @see ::POUT_INFO_FLAG_MASKS + } POUT_INFO; -#define _mbg_swab_pout_info( _p ) \ -{ \ - _mbg_swab_pout_settings( &(_p)->pout_settings ); \ - _mbg_swab32( &(_p)->supp_modes ); \ - _mbg_swab16( &(_p)->reserved_1 ); \ - _mbg_swab32( &(_p)->flags ); \ -} +#define _mbg_swab_pout_info_on_get( _p ) \ +do \ +{ \ + _mbg_swab_pout_settings_on_get( &(_p)->pout_settings ); \ + _mbg_swab32( &(_p)->supp_modes ); \ + _mbg_swab8( &(_p)->timestr_ports ); \ + _mbg_swab8( &(_p)->pulse_shift_res ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) -/** The max number of COM ports that can be handled by POUT_INFO::timestr_ports */ -#define MAX_POUT_TIMESTR_PORTS 8 +#define MAX_POUT_TIMESTR_PORTS 8 ///< The max number of COM ports that can be handled by ::POUT_INFO::timestr_ports -/* - * The codes below are used with POUT_INFO::flags: + +/** + * @brief Flag bits used to define ::POUT_INFO_FLAG_MASKS + * + * @see ::POUT_INFO_FLAG_MASKS + */ +enum POUT_INFO_FLAG_BITS +{ + POUT_BIT_SUPP_IF_SYNC_ONLY, ///< ::POUT_IF_SYNC_ONLY is supported for this output + POUT_BIT_SUPP_DCF77_UTC, ///< ::POUT_SUPP_DCF77_UTC is supported for this output + POUT_BIT_FIXED_PULSE_LEN, ///< pulse length is limited to the value ::POUT_SETTINGS::mode_param + POUT_BIT_NOT_INVERTIBLE, ///< output level can't be inverted, thus ::POUT_INVERTED is not supported for this output + POUT_BIT_SUPP_PULSE_SHIFT, ///< output slopes can be shifted, see ::POUT_DATA::pulse_shift + N_POUT_INFO_FLAG_BITS ///< number of known flag bits +}; + + +/** + * @brief Flag bit masks used with ::POUT_INFO::flags + * + * @see ::POUT_INFO_FLAG_BITS */ -#define POUT_SUPP_IF_SYNC_ONLY 0x0001 // supports disabling outputs in holdover mode -#define POUT_SUPP_DCF77_UTC 0x0002 // supports UTC output in DCF77 mode +enum POUT_INFO_FLAG_MASKS +{ + POUT_SUPP_IF_SYNC_ONLY = ( 1UL << POUT_BIT_SUPP_IF_SYNC_ONLY ), ///< see ::POUT_BIT_SUPP_IF_SYNC_ONLY, ::POUT_IF_SYNC_ONLY + POUT_SUPP_DCF77_UTC = ( 1UL << POUT_BIT_SUPP_DCF77_UTC ), ///< see ::POUT_BIT_SUPP_DCF77_UTC, ::POUT_SUPP_DCF77_UTC + POUT_FIXED_PULSE_LEN = ( 1UL << POUT_BIT_FIXED_PULSE_LEN ), ///< see ::POUT_BIT_FIXED_PULSE_LEN + POUT_NOT_INVERTIBLE = ( 1UL << POUT_BIT_NOT_INVERTIBLE ), ///< see ::POUT_BIT_NOT_INVERTIBLE, ::POUT_INVERTED + POUT_SUPP_PULSE_SHIFT = ( 1UL << POUT_BIT_SUPP_PULSE_SHIFT ) ///< see ::POUT_BIT_SUPP_PULSE_SHIFT, ::POUT_DATA::pulse_shift +}; + /** - The structure below adds an index number to the structure - above to allow addressing of several instances: + * @brief Current settings and general capabilities of a specific programmable pulse output + * + * This structure should be read from the device to retrieve the + * current settings of a specific programmable output plus its capabilities, + * e.g. supported modes of operation, etc. + * The number of supported ports is RECEIVER_INFO::n_prg_out. + * + * @note The ::POUT_SETTINGS_IDX structure should be send back to + * the device to configure the specified programmable pulse output. */ typedef struct { - uint16_t idx; /**< 0..RECEIVER_INFO.n_prg_out-1 */ + uint16_t idx; ///< 0..::RECEIVER_INFO::n_prg_out-1 POUT_INFO pout_info; + } POUT_INFO_IDX; -#define _mbg_swab_pout_info_idx( _p ) \ -{ \ - _mbg_swab16( &(_p)->idx ); \ - _mbg_swab_pout_info( &(_p)->pout_info ); \ -} +#define _mbg_swab_pout_info_idx_on_get( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_pout_info_on_get( &(_p)->pout_info ); \ +} while ( 0 ) +/** @} defgroup group_pout_api */ -/* - * The codes below are used with devices which support multiple - * ref time sources at the same time. The priorities of the - * supported ref time sources is configurable. - */ /** - * @brief All possibly supported ref time sources + * @defgroup group_multi_ref_all Support for multiple reference time sources + * + * Some devices can evaluate and synchronize to several different types + * of input signal, and eventually even several signals of the same type, + * e.g. several 1 PPS input signals. + * + * There are two different ways to configure multi ref devices. + * + * Newer devices which have the ::GPS_HAS_XMULTI_REF flag set in + * ::RECEIVER_INFO::features support the newer XMULTI_REF_... structures + * which provide a more flexible API, see @ref group_multi_ref_ext + * + * Older devices may have the ::GPS_FEAT_MULTI_REF flag set in which + * case an older API is supported, see @ref group_multi_ref_old + * + * Symbols defined in @ref group_multi_ref_common can be used + * with both APIs. + * + * @see @ref group_multi_ref_common + * @see @ref group_multi_ref_old + * @see @ref group_multi_ref_ext + * @{ */ + +/** + * @defgroup group_multi_ref_common Common multi ref definitions + * + * Common definitions used with both the old and the extended + * multi ref API. + * + * @{ */ + +/** + * @brief Enumeration of all known types of reference time source + * + * All known types of input signal which may possibly be supported + * by devices which support several different input signals, i.e. + * have the ::GPS_HAS_MULTI_REF or ::GPS_HAS_XMULTI_REF bit set + * in ::RECEIVER_INFO::features. Not all devices support each known + * type of input signal. + * + * @see @ref group_multi_ref_all + * @see ::DEFAULT_MULTI_REF_NAMES + * @see ::DEFAULT_MULTI_REF_NAMES_SHORT + * @see @ref MULTI_REF_TYPE_MASKS */ -enum +enum MULTI_REF_TYPES { - MULTI_REF_NONE = -1, /**< nothing, undefined */ - MULTI_REF_GPS = 0, /**< standard GPS */ - MULTI_REF_10MHZ, /**< 10 MHz input frequency */ - MULTI_REF_PPS, /**< 1 PPS input signal */ - MULTI_REF_10MHZ_PPS, /**< combined 10 MHz plus PPS */ - MULTI_REF_IRIG, /**< IRIG input */ - MULTI_REF_NTP, /**< Network Time Protocol (NTP) */ - MULTI_REF_PTP, /**< Precision Time Protocol (PTP, IEEE1588) */ - MULTI_REF_PTP_E1, /**< PTP over E1 */ - MULTI_REF_FREQ, /**< fixed frequency */ - MULTI_REF_PPS_STRING, /**< PPS in addition to string */ - MULTI_REF_GPIO, /**< variable input signal via GPIO */ - N_MULTI_REF /**< the number of defined sources, can not exceed bit number of uint32_t - 1 */ + /// This ref type must not be used as index, but marks particular + /// ::XMULTI_REF_SETTINGS structures as "unused". It is only + /// supported if bit ::XMRIF_BIT_MRF_NONE_SUPP is set. + MULTI_REF_NONE = -1, + + MULTI_REF_GPS = 0, ///< standard GPS + MULTI_REF_10MHZ, ///< 10 MHz input frequency + MULTI_REF_PPS, ///< 1 PPS input signal + MULTI_REF_10MHZ_PPS, ///< combined 10 MHz plus PPS + MULTI_REF_IRIG, ///< IRIG input + MULTI_REF_NTP, ///< Network Time Protocol (NTP) + MULTI_REF_PTP, ///< Precision Time Protocol (PTP/IEEE1588) + MULTI_REF_PTP_E1, ///< PTP over E1 + MULTI_REF_FREQ, ///< fixed frequency + MULTI_REF_PPS_STRING, ///< 1 PPS in addition to time string + MULTI_REF_GPIO, ///< variable input signal via GPIO + MULTI_REF_INTERNAL, ///< reserved, used internally by firmware only + MULTI_REF_PZF, ///< DCF77 PZF providing much more accuracy than a standard LWR + MULTI_REF_LWR, ///< long wave receiver. e.g. DCF77 AM, WWVB, MSF, JJY + MULTI_REF_GRC, ///< Glonass / GPS receiver + MULTI_REF_HAVEQUICK, ///< HaveQuick input + MULTI_REF_EXT_OSC, ///< external oscillator disciplined and looped back via 1 PPS I/O + MULTI_REF_SYNCE, ///< Synchronous Ethernet, needs (external) ethernet interface + N_MULTI_REF ///< the number of defined sources, must not exceed ::MAX_N_MULTI_REF_TYPES }; +/** + * @brief Theoretical maximum number of multi ref input signal types + * + * Actually only ::N_MULTI_REF types have been defined, but ::N_MULTI_REF + * must not exceed the number of bits which can be hold by a uint32_t type. + */ +#define MAX_N_MULTI_REF_TYPES 32 -/* - * Names of supported ref time sources + +/** + * @brief Names of known ref time sources + * + * @see ::MULTI_REF_TYPES */ #define DEFAULT_MULTI_REF_NAMES \ { \ @@ -3223,137 +6318,252 @@ enum "PTP over E1", \ "Fixed Freq. in", \ "PPS plus string", \ - "Var. freq. via GPIO" \ + "Var. freq. via GPIO", \ + "(reserved)", \ + "DCF77 PZF Receiver", \ + "Long Wave Receiver", \ + "GLONASS/GPS Receiver", \ + "HaveQuick Input", \ + "ext. Osc.", \ + "Synchronous Ethernet" \ } - -/* - * Bit masks used to indicate supported reference sources +/** + * @brief Short names of supported ref time sources + * + * Used e.g. to configure a particular input signal type + * + * @see ::MULTI_REF_TYPES */ -#define HAS_MULTI_REF_GPS ( 1UL << MULTI_REF_GPS ) -#define HAS_MULTI_REF_10MHZ ( 1UL << MULTI_REF_10MHZ ) -#define HAS_MULTI_REF_PPS ( 1UL << MULTI_REF_PPS ) -#define HAS_MULTI_REF_10MHZ_PPS ( 1UL << MULTI_REF_10MHZ_PPS ) -#define HAS_MULTI_REF_IRIG ( 1UL << MULTI_REF_IRIG ) -#define HAS_MULTI_REF_NTP ( 1UL << MULTI_REF_NTP ) -#define HAS_MULTI_REF_PTP ( 1UL << MULTI_REF_PTP ) -#define HAS_MULTI_REF_PTP_E1 ( 1UL << MULTI_REF_PTP_E1 ) -#define HAS_MULTI_REF_FREQ ( 1UL << MULTI_REF_FREQ ) -#define HAS_MULTI_REF_PPS_STRING ( 1UL << MULTI_REF_PPS_STRING ) -#define HAS_MULTI_REF_GPIO ( 1UL << MULTI_REF_GPIO ) +#define DEFAULT_MULTI_REF_NAMES_SHORT \ +{ \ + "GPS", \ + "FRQ", \ + "PPS", \ + "10MHZ+PPS", \ + "TCR", \ + "NTP", \ + "PTP", \ + "PTP_E1", \ + "FIXED_FREQ", \ + "STRING+PPS", \ + "GPIO", \ + "(reserved)", \ + "PZF", \ + "LWR", \ + "GGR", \ + "HQI", \ + "EXT", \ + "SYNCE" \ +} -/* - * There are 2 different ways to configure multi ref support - * provided by some devices. +/** + * @brief Bit masks associated with multi ref types * - * Newer devices which have the GPS_FEAT_XMULTI_REF flag set - * in RECEIVER_INFO::features support the newer XMULTI_REF_... - * structures which provide a more flexible interface. + * Used to indicate which multi ref types are supported, e.g. + * in ::XMULTI_REF_INFO::supp_ref or ::MULTI_REF_INFO::supp_ref. * - * Older devices which have the GPS_FEAT_MULTI_REF flag set - * support these MULTI_REF_... structures below where - * the number of supported input sources and priorities - * is limited to N_MULTI_REF_PRIO. - */ + * @see ::MULTI_REF_TYPES + * + * @anchor MULTI_REF_TYPE_MASKS @{ */ + +#define HAS_MULTI_REF_GPS ( 1UL << MULTI_REF_GPS ) ///< see ::MULTI_REF_GPS +#define HAS_MULTI_REF_10MHZ ( 1UL << MULTI_REF_10MHZ ) ///< see ::MULTI_REF_10MHZ +#define HAS_MULTI_REF_PPS ( 1UL << MULTI_REF_PPS ) ///< see ::MULTI_REF_PPS +#define HAS_MULTI_REF_10MHZ_PPS ( 1UL << MULTI_REF_10MHZ_PPS ) ///< see ::MULTI_REF_10MHZ_PPS +#define HAS_MULTI_REF_IRIG ( 1UL << MULTI_REF_IRIG ) ///< see ::MULTI_REF_IRIG +#define HAS_MULTI_REF_NTP ( 1UL << MULTI_REF_NTP ) ///< see ::MULTI_REF_NTP +#define HAS_MULTI_REF_PTP ( 1UL << MULTI_REF_PTP ) ///< see ::MULTI_REF_PTP +#define HAS_MULTI_REF_PTP_E1 ( 1UL << MULTI_REF_PTP_E1 ) ///< see ::MULTI_REF_PTP_E1 + +#define HAS_MULTI_REF_FREQ ( 1UL << MULTI_REF_FREQ ) ///< see ::MULTI_REF_FREQ +#define HAS_MULTI_REF_PPS_STRING ( 1UL << MULTI_REF_PPS_STRING ) ///< see ::MULTI_REF_PPS_STRING +#define HAS_MULTI_REF_GPIO ( 1UL << MULTI_REF_GPIO ) ///< see ::MULTI_REF_GPIO +#define HAS_MULTI_REF_INTERNAL ( 1UL << MULTI_REF_INTERNAL ) ///< see ::MULTI_REF_INTERNAL +#define HAS_MULTI_REF_PZF ( 1UL << MULTI_REF_PZF ) ///< see ::MULTI_REF_PZF +#define HAS_MULTI_REF_LWR ( 1UL << MULTI_REF_LWR ) ///< see ::MULTI_REF_LWR +#define HAS_MULTI_REF_GRC ( 1UL << MULTI_REF_GRC ) ///< see ::MULTI_REF_GRC +#define HAS_MULTI_REF_HAVEQUICK ( 1UL << MULTI_REF_HAVEQUICK ) ///< see ::MULTI_REF_HAVEQUICK + +#define HAS_MULTI_REF_EXT_OSC ( 1UL << MULTI_REF_EXT_OSC ) ///< see ::MULTI_REF_EXT_OSC +#define HAS_MULTI_REF_SYNCE ( 1UL << MULTI_REF_SYNCE ) ///< see ::MULTI_REF_SYNCE + +/** @} anchor MULTI_REF_TYPE_MASKS */ + +/** @} defgroup group_multi_ref_common */ -#define N_MULTI_REF_PRIO 4 /** - The structure below is used to configure the priority of - the supported ref sources. + * @defgroup group_multi_ref_old Definitions used with the old multi ref API + * + * This API has been deprecated by a newer one which should be used preferably. + * + * @see @ref group_multi_ref_ext + * + * @{ */ + +/** + * @brief Maximum number of input sources + * + * The number of supported input sources and priorities is + * limited to this value if the old API is used, i.e. if only + * the ::GPS_FEAT_MULTI_REF flag is set. + */ +#define N_MULTI_REF_PRIO 4 - The number stored in prio[0] of the array indicates the ref time - source with highest priority. If that source fails, the device - falls back to the source indicated by prio[1]. Each field of - the prio[] array must be set to one of the values 0..N_MULTI_REF-1, - or to -1 (0xFF) if the value is not assigned. + +/** + * @brief A structure used to configure the priority of the supported ref sources + * + * The number stored in prio[0] of the array indicates the ref time + * source with highest priority. If that source fails, the device + * falls back to the source indicated by prio[1]. Each field of + * the prio[] array has to be set to one of the values 0..::N_MULTI_REF-1, + * or to ::MULTI_REF_NONE if no time source is specified. */ typedef struct { uint8_t prio[N_MULTI_REF_PRIO]; + } MULTI_REF_SETTINGS; /** - The structure below is used to query the MULTI_REF configuration, - plus the supported ref sources. + * @brief A structure used to query MULTI_REF configuration parameters + * + * This also includes a bit mask of supported ref sources. */ typedef struct { - MULTI_REF_SETTINGS settings; /* current settings */ - uint32_t supp_ref; /* supp. HAS_MULTI_REF_... codes or'ed */ - uint16_t n_levels; /* supp. levels, 0..N_MULTI_REF_PRIO */ - uint16_t flags; /* reserved, currently 0 */ + MULTI_REF_SETTINGS settings; ///< current settings + uint32_t supp_ref; ///< bit mask of supported sources, see @ref MULTI_REF_TYPE_MASKS + uint16_t n_levels; ///< supported priority levels, 0..::N_MULTI_REF_PRIO-1 + uint16_t flags; ///< reserved, currently always 0 + } MULTI_REF_INFO; -/* - * The type below is used to query the MULTI_REF status information, +/** + * @brief A data type used to query MULTI_REF status information + * + * @see ::MULTI_REF_STATUS_BIT_MASKS */ -typedef uint16_t MULTI_REF_STATUS; /* flag bits as defined below */ +typedef uint16_t MULTI_REF_STATUS; -/* - * The bits and associated bit masks below are used with the - * MULTI_REF_STATUS type. Each bit is set if the associated - * condition is true and is reset if the condition is not true: +/** + * @brief Enumeration of multi ref status bits + * + * @see ::MULTI_REF_STATUS_BIT_MASKS */ -enum +enum MULTI_REF_STATUS_BITS { - WRN_MODULE_MODE, /* selected input mode was invalid, set to default */ - WRN_COLD_BOOT, /* GPS is in cold boot mode */ - WRN_WARM_BOOT, /* GPS is in warm boot mode */ - WRN_ANT_DISCONN, /* antenna is disconnected */ - WRN_10MHZ_UNLOCK, /* impossible to lock to external 10MHz reference */ - WRN_1PPS_UNLOCK, /* impossible to lock to external 1PPS reference */ - WRN_GPS_UNLOCK, /* impossible to lock to GPS */ - WRN_10MHZ_MISSING, /* external 10MHz signal not available */ - WRN_1PPS_MISSING, /* external 1PPS signal not available */ - N_MULTI_REF_STATUS_BITS + WRN_MODULE_MODE, ///< selected input mode was invalid, set to default + WRN_COLD_BOOT, ///< GPS is in cold boot mode + WRN_WARM_BOOT, ///< GPS is in warm boot mode + WRN_ANT_DISCONN, ///< antenna is disconnected + WRN_10MHZ_UNLOCK, ///< impossible to lock to external 10 MHz reference + WRN_1PPS_UNLOCK, ///< impossible to lock to external 1 PPS reference + WRN_GPS_UNLOCK, ///< impossible to lock to GPS + WRN_10MHZ_MISSING, ///< external 10 MHz signal not available + WRN_1PPS_MISSING, ///< external 1 PPS signal not available + N_MULTI_REF_STATUS_BITS ///< the number of known bits }; -#define MSK_WRN_COLD_BOOT ( 1UL << WRN_COLD_BOOT ) -#define MSK_WRN_WARM_BOOT ( 1UL << WRN_WARM_BOOT ) -#define MSK_WRN_ANT_DISCONN ( 1UL << WRN_ANT_DISCONN ) -#define MSK_WRN_10MHZ_UNLOCK ( 1UL << WRN_10MHZ_UNLOCK ) -#define MSK_WRN_1PPS_UNLOCK ( 1UL << WRN_1PPS_UNLOCK ) -#define MSK_WRN_GPS_UNLOCK ( 1UL << WRN_GPS_UNLOCK ) -#define MSK_WRN_10MHZ_MISSING ( 1UL << WRN_10MHZ_MISSING ) -#define MSK_WRN_1PPS_MISSING ( 1UL << WRN_1PPS_MISSING ) -#define MSK_WRN_MODULE_MODE ( 1UL << WRN_MODULE_MODE ) + +/** + * @brief Bit masks associated with ::MULTI_REF_STATUS_BITS + * + * Used with ::MULTI_REF_STATUS. + * + * @see ::MULTI_REF_STATUS_BITS + */ +enum MULTI_REF_STATUS_BIT_MASKS +{ + MSK_WRN_COLD_BOOT = ( 1UL << WRN_COLD_BOOT ), ///< see ::WRN_COLD_BOOT + MSK_WRN_WARM_BOOT = ( 1UL << WRN_WARM_BOOT ), ///< see ::WRN_WARM_BOOT + MSK_WRN_ANT_DISCONN = ( 1UL << WRN_ANT_DISCONN ), ///< see ::WRN_ANT_DISCONN + MSK_WRN_10MHZ_UNLOCK = ( 1UL << WRN_10MHZ_UNLOCK ), ///< see ::WRN_10MHZ_UNLOCK + MSK_WRN_1PPS_UNLOCK = ( 1UL << WRN_1PPS_UNLOCK ), ///< see ::WRN_1PPS_UNLOCK + MSK_WRN_GPS_UNLOCK = ( 1UL << WRN_GPS_UNLOCK ), ///< see ::WRN_GPS_UNLOCK + MSK_WRN_10MHZ_MISSING = ( 1UL << WRN_10MHZ_MISSING ), ///< see ::WRN_10MHZ_MISSING + MSK_WRN_1PPS_MISSING = ( 1UL << WRN_1PPS_MISSING ), ///< see ::WRN_1PPS_MISSING + MSK_WRN_MODULE_MODE = ( 1UL << WRN_MODULE_MODE ) ///< see ::WRN_MODULE_MODE +}; + +/** @} defgroup group_multi_ref_old */ /** - * @defgroup group_xmr_cfg Extended multiref configuration stuff + * @defgroup group_multi_ref_ext Extended multi ref definitions + * + * If the ::GPS_HAS_XMULTI_REF feature is set in ::RECEIVER_INFO::features then + * the XMULTI_REF (extended multi ref, XMR) feature and API are supported and + * have to be used in favor of the older multi ref API (see @ref group_multi_ref_old). + * + * Devices supporting the XMULTI_REF feature provide a number of + * priority levels addressed by the priority index, starting at 0 + * for highest priority. A single reference time source from the set + * of supported sources can be assigned to each priority level. + * + * These structures are used to configure the individual time source for each + * priority level, and retrieve the status of the time source at each priority level. * - * If the RECEIVER_INFO::features flag GPS_FEAT_XMULTI_REF is set - * then the following XMULTI_REF_... data structures must be used - * instead of the older MULTI_REF_... structures. + * If ::GPS_HAS_XMRS_MULT_INSTC is also set in ::RECEIVER_INFO::features then + * ::XMULTI_REF_INSTANCES can be used to find out which types of input source + * are supported (::XMULTI_REF_INSTANCES::n_inst array entries != 0), and + * how many priority levels are supported to which an input source can be + * assigned (::XMULTI_REF_INSTANCES::n_xmr_settings). * - * Those devices support a number of priority levels addressed by - * the priority index, starting at 0 for highest priority. A single - * reference time source from the set of supported sources can be - * assigned to each priority level. + * If ::XMRIF_MSK_HOLDOVER_STATUS_SUPP is set in ::XMULTI_REF_INSTANCES::flags + * then ::XMR_HOLDOVER_STATUS can be used to monitor the switching between + * different time sources when they become available or unavailable. * - * These structures are used to configure the individual - * time source for each priority level, and retrieve the status - * of the time source at each priority level. + * If an XMR time source at a high priority level becomes unavailable the + * XMR control function tries to find and switch to a different time source + * at a lower level of the priority list, which is still available. + * + * On the other hand, if a time source at a higher priority level becomes + * available again, the XMR control function switches over to the time source + * at the higher priority even if the current time source is still available. + * + * If the accuracy of the time source at the next priority level is better than + * the accuracy of the time source at the current priority level then switching + * can be done immediately. However, if the next time source is worse than + * the current one it makes more sense to switch only after a certain holdover + * interval. + * + * The holdover interval is computed so that the time error due to the expected + * drift of the previously disciplined time base grows until it reaches the + * accuracy level of the next available reference time source. + * + * Only if the time source at the current priority level is still unavailable + * when the holdover interval expires the reference time source is switched + * to the time source at the next available priority level. * * @{ */ + /** * @brief Identifier for a reference source */ typedef struct { - uint8_t type; /**< 0..N_MULTI_REF-1 from the enum above */ - uint8_t instance; /**< instance number, if multiple instances are supported, else 0 */ + uint8_t type; ///< see ::MULTI_REF_TYPES, and note for ::XMRIF_BIT_MRF_NONE_SUPP + uint8_t instance; ///< instance number, if multiple instances are supported, else 0 } XMULTI_REF_ID; +#define _mbg_swab_xmulti_ref_id( _p ) \ +do \ +{ \ + _mbg_swab8( &(_p)->type ); \ + _mbg_swab8( &(_p)->instance ); \ +} while ( 0 ) + /** @@ -3361,56 +6571,129 @@ typedef struct */ typedef struct { - XMULTI_REF_ID id; /**< time source identifier */ - uint16_t flags; /**< reserved, currently always 0 */ - NANO_TIME bias; /**< time bias, e.g. path delay */ - NANO_TIME precision; /**< precision of the time source */ - uint32_t fine_limit; /**< smooth control if below this limit */ + XMULTI_REF_ID id; ///< reference time source identifier + uint16_t flags; ///< see ::XMR_SETTINGS_FLAG_MSKS and ::XMR_EXT_SRC_INFO::supp_flags + NANO_TIME bias; ///< time bias, e.g. path delay @todo specify sign vs. earlier/later + NANO_TIME precision; ///< precision of the time source + uint32_t reserved; ///< reserved, currently always 0 } XMULTI_REF_SETTINGS; +#define _mbg_swab_xmulti_ref_settings( _p ) \ +do \ +{ \ + _mbg_swab_xmulti_ref_id( &(_p)->id ); \ + _mbg_swab16( &(_p)->flags ); \ + _mbg_swab_nano_time( &(_p)->bias ); \ + _mbg_swab_nano_time( &(_p)->precision ); \ + _mbg_swab32( &(_p)->reserved ); \ +} while ( 0 ) + /** - * @brief Reference source configuration settings for a specific priority level + * @brief Reference source configuration for a specific priority level * - * @note After configuring, a structure with idx == 0xFFFF (-1) must be sent - * to let the changes become effective. + * @note After all other ::XMULTI_REF_SETTINGS_IDX configuration structures + * have been sent to a device, an additional structure with idx == -1 (0xFFFF) + * has to be sent to let the new settings come into effect. */ typedef struct { - uint16_t idx; /* the priority level index, highest == 0 */ - XMULTI_REF_SETTINGS settings; /* the settings configured for this level */ + uint16_t idx; ///< the priority level index (highest == 0), 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1 + XMULTI_REF_SETTINGS settings; ///< the settings configured for this level } XMULTI_REF_SETTINGS_IDX; +#define _mbg_swab_xmulti_ref_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_xmulti_ref_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +/** + * @brief Bit masks used to define ::XMR_SETTINGS_FLAG_MSKS + */ +enum XMR_SETTINGS_FLAG_BITS +{ + XMRSF_BIT_AUTO_BIAS_MASTER, ///< src is allowed to operate as zero asymmetry master + XMRSF_BIT_AUTO_BIAS_SLAVE, ///< accept static bias correction from zero asymmetry master + XMRSF_BIT_ASYMMETRY_STEP_DETECTION, ///< static bias auto correction in case of step + N_XMRSF_BITS ///< number of known flag bits +}; + + +/** + * @brief Bit masks used with ::XMULTI_REF_SETTINGS::flags and ::XMR_EXT_SRC_INFO::supp_flags + */ +enum XMR_SETTINGS_FLAG_MSKS +{ + XMRSF_MSK_AUTO_BIAS_MASTER = ( 1UL << XMRSF_BIT_AUTO_BIAS_MASTER ), ///< see ::XMRSF_BIT_AUTO_BIAS_MASTER + XMRSF_MSK_AUTO_BIAS_SLAVE = ( 1UL << XMRSF_BIT_AUTO_BIAS_SLAVE ), ///< see ::XMRSF_BIT_AUTO_BIAS_SLAVE + XMRSF_MSK_ASYMMETRY_STEP_DETECTION = ( 1UL << XMRSF_BIT_ASYMMETRY_STEP_DETECTION ) ///< see ::XMRSF_BIT_ASYMMETRY_STEP_DETECTION +}; + /** - * @brief Reference source configuration settings and capabilities + * @brief Reference source capabilities and current configuration */ typedef struct { - XMULTI_REF_SETTINGS settings; /**< current settings */ - uint32_t supp_ref; /**< bit mask of or'ed HAS_MULTI_REF_... codes */ - uint8_t n_supp_ref; /**< number of supported ref time sources */ - uint8_t n_prio; /**< number of supported priority levels */ - uint16_t flags; /**< currently always 0 */ + XMULTI_REF_SETTINGS settings; ///< current settings + + /** + * @deprecated Deprecated by ::XMULTI_REF_INSTANCES::n_inst. + * If ::GPS_HAS_XMRS_MULT_INSTC is *not* set then this field provides + * a bit mask of supported sources (see @ref MULTI_REF_TYPE_MASKS), + * and only a single instance of each source signal type is supported. + */ + uint32_t supp_ref; + + /** + * @deprecated Deprecated by ::XMULTI_REF_INSTANCES::n_xmr_settings. + * If ::GPS_HAS_XMRS_MULT_INSTC is *not* set then this field + * reports the number of priority levels supported by the device. + */ + uint8_t n_supp_ref; + + uint8_t n_prio; ///< reserved, don't use, currently always 0 //##++++ TODO: check which devices support/use this field + uint16_t flags; ///< reserved, don't use, currently always 0 } XMULTI_REF_INFO; +#define _mbg_swab_xmulti_ref_info( _p ) \ +do \ +{ \ + _mbg_swab_xmulti_ref_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_ref ); \ + _mbg_swab8( &(_p)->n_supp_ref ); \ + _mbg_swab8( &(_p)->n_prio ); \ + _mbg_swab16( &(_p)->flags ); \ +} while ( 0 ) + /** - * @brief Reference source configuration settings and capabilities for a specific priority level + * @brief Reference source capabilities and current configuration for a specific priority level */ typedef struct { - uint16_t idx; /**< the priority level index, highest == 0 */ - XMULTI_REF_INFO info; /**< ref source cfg and capabilities */ + uint16_t idx; ///< the priority level index (highest == 0), 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1 + XMULTI_REF_INFO info; ///< ref source configuration and capabilities } XMULTI_REF_INFO_IDX; +#define _mbg_swab_xmulti_ref_info_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_xmulti_ref_info( &(_p)->info ); \ +} while ( 0 ) + /** @@ -3418,82 +6701,160 @@ typedef struct */ typedef struct { - XMULTI_REF_ID id; /**< time source identifier */ - uint16_t status; /**< flag bits as defined below */ - NANO_TIME offset; /**< time offset from main time base */ - uint32_t flags; /**< see flags specified below */ + XMULTI_REF_ID id; ///< time source identifier + uint16_t status; ///< status bits, see @ref XMR_REF_STATUS_BIT_MASKS + NANO_TIME offset; ///< time offset from main time base @todo specify sign vs. earlier/later + uint16_t flags; ///< flags, see ::XMR_QL // TODO ### + uint8_t ssm; ///< synchronization status message, if supported by signal source + uint8_t soc; ///< signal outage counter, incremented on loss of signal } XMULTI_REF_STATUS; +#define _mbg_swab_xmulti_ref_status( _p ) \ +do \ +{ \ + _mbg_swab_xmulti_ref_id( &(_p)->id ); \ + _mbg_swab16( &(_p)->status ); \ + _mbg_swab_nano_time( &(_p)->offset ); \ + _mbg_swab16( &(_p)->flags ); \ + _mbg_swab8( &(_p)->ssm ); \ + _mbg_swab8( &(_p)->soc ); \ +} while ( 0 ) + /** - * @brief Bits and masks used with XMULTI_REF_STATUS::flags - * - * @note If XMRS_FLAG_MULT_INSTC_SUPP is set then the API calls to read - * XMULTI_REF_INSTANCES is supported, otherwise it is not. + * @brief Status information on a ref time source at a specific priority level */ -enum +typedef struct { - XMRSF_BIT_MULT_INSTC_SUPP, /**< multiple instances of the same ref type supported */ - XMRSF_BIT_IS_EXTERNAL, /**< this ref source is on extension card */ - N_XMRS_FLAGS -}; + uint16_t idx; ///< the priority level index (highest == 0), 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1 + XMULTI_REF_STATUS status; ///< status information + +} XMULTI_REF_STATUS_IDX; -#define XMRSF_MSK_MULT_INSTC_SUPP ( 1UL << XMRSF_BIT_MULT_INSTC_SUPP ) -#define XMRSF_MSK_IS_EXTERNAL ( 1UL << XMRSF_BIT_IS_EXTERNAL ) +#define _mbg_swab_xmulti_ref_status_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_xmulti_ref_status( &(_p)->status ); \ +} while ( 0 ) /** - * @brief Status information on a ref time source at a specific priority level + * @brief ::TODO + * + * Used with the ::... field of ::XMULTI_REF_STATUS::flags + * + * @see ::XMULTI_REF_STATUS::flags + * @see ::XMR_QL_TDEV_MASK + * @see ::_GET_XMR_QL_TDEV + * @see ::_PUT_XMR_QL_TDEV + * @see ::XMR_QL_MTIE_MASK + * @see ::_GET_XMR_QL_MTIE + * @see ::_PUT_XMR_QL_MTIE */ -typedef struct +enum XMR_QL { - uint16_t idx; /**< the priority level index, highest == 0 */ - XMULTI_REF_STATUS status; /**< status information */ + XMR_QL_UNKNOWN, + XMR_QL_GREEN, + XMR_QL_YELLOW, + XMR_QL_RED, + N_XMR_QL +}; -} XMULTI_REF_STATUS_IDX; +#define XMR_QL_TDEV_MASK ( 0x03 << 0 ) +#define XMR_QL_MTIE_MASK ( 0x03 << 2 ) + +#define _GET_XMR_QL_TDEV( _x ) ( ( ( _x ) & XMR_QL_TDEV_MASK ) >> 0 ) +#define _PUT_XMR_QL_TDEV( _x, _ql ) \ +do { \ + ( _x ) = ( ( _x ) & ~XMR_QL_TDEV_MASK ) | ( ( ( _ql ) << 0 ) & XMR_QL_TDEV_MASK ); \ +} while ( 0 ) + + +#define _GET_XMR_QL_MTIE( _x ) ( ( ( _x ) & XMR_QL_MTIE_MASK ) >> 2 ) +#define _PUT_XMR_QL_MTIE( _x, _ql ) \ +do { \ + ( _x ) = ( ( _x ) & ~XMR_QL_MTIE_MASK ) | ( ( ( _ql ) << 2 ) & XMR_QL_MTIE_MASK ); \ +} while ( 0 ) /** - * @brief Bits and bit masks used with XMULTI_REF_STATUS::status - * - * @note Flags XMRS_BIT_MULT_INSTC_SUPP and XMRS_BIT_NUM_SRC_EXC - * are set in the status flags for every priority if the associated - * condition is met. + * @brief XMULTI_REF status bits */ -enum +enum XMR_REF_STATUS_BITS { - XMRS_BIT_NOT_SUPP, /**< ref type cfg'd for this level is not supported */ - XMRS_BIT_NO_CONN, /**< input signal is disconnected */ - XMRS_BIT_NO_SIGNAL, /**< no input signal */ - XMRS_BIT_IS_MASTER, /**< reference is master source */ - XMRS_BIT_IS_LOCKED, /**< locked to input signal */ - XMRS_BIT_IS_ACCURATE, /**< oscillator control has reached full accuracy */ - XMRS_BIT_NOT_SETTLED, /**< reference time signal not settled */ - XMRS_BIT_NOT_PHASE_LOCKED, /**< oscillator not phase locked to PPS */ - XMRS_BIT_NUM_SRC_EXC, /**< number of available sources exceeds what can be handled */ - XMRS_BIT_IS_EXTERNAL, /**< this ref source is on extension card */ - N_XMRS_BITS /**< number of know status bits */ + XMRS_BIT_NOT_SUPP, ///< ref type cfg'd for this level is not supported + XMRS_BIT_NO_CONN, ///< input signal is disconnected + XMRS_BIT_NO_SIGNAL, ///< no input signal + XMRS_BIT_IS_MASTER, ///< reference is master source + XMRS_BIT_IS_LOCKED, ///< locked to input signal + XMRS_BIT_IS_ACCURATE, ///< oscillator control has reached full accuracy + XMRS_BIT_NOT_SETTLED, ///< reference time signal not settled + XMRS_BIT_NOT_PHASE_LOCKED, ///< oscillator not phase locked to PPS + XMRS_BIT_NUM_SRC_EXC, ///< number of available sources exceeds what can be handled + XMRS_BIT_IS_EXTERNAL, ///< this ref source is on extension card + XMRS_BIT_LOW_JITTER, ///< this ref source has low jitter + XMRS_BIT_ITU_LIMIT_VIOLATED, ///< ITU limits violated (valid if device has ::XMR_METRICS) + N_XMRS_BITS ///< number of know status bits }; -#define XMRS_MSK_NOT_SUPP ( 1UL << XMRS_BIT_NOT_SUPP ) -#define XMRS_MSK_NO_CONN ( 1UL << XMRS_BIT_NO_CONN ) -#define XMRS_MSK_NO_SIGNAL ( 1UL << XMRS_BIT_NO_SIGNAL ) -#define XMRS_MSK_IS_MASTER ( 1UL << XMRS_BIT_IS_MASTER ) -#define XMRS_MSK_IS_LOCKED ( 1UL << XMRS_BIT_IS_LOCKED ) -#define XMRS_MSK_IS_ACCURATE ( 1UL << XMRS_BIT_IS_ACCURATE ) -#define XMRS_MSK_NOT_SETTLED ( 1UL << XMRS_BIT_NOT_SETTLED ) -#define XMRS_MSK_NOT_PHASE_LOCKED ( 1UL << XMRS_BIT_NOT_PHASE_LOCKED ) -#define XMRS_MSK_NUM_SRC_EXC ( 1UL << XMRS_BIT_NUM_SRC_EXC ) -#define XMRS_MSK_IS_EXTERNAL ( 1UL << XMRS_BIT_IS_EXTERNAL ) + + +/** + * @brief Bit masks associated with ::XMR_REF_STATUS_BITS + * + * Used with ::XMULTI_REF_STATUS::status. + * + * @see ::XMR_REF_STATUS_BITS + * + * @anchor XMR_REF_STATUS_BIT_MASKS @{ */ + +#define XMRS_MSK_NOT_SUPP ( 1UL << XMRS_BIT_NOT_SUPP ) ///< see ::XMRS_BIT_NOT_SUPP +#define XMRS_MSK_NO_CONN ( 1UL << XMRS_BIT_NO_CONN ) ///< see ::XMRS_BIT_NO_CONN +#define XMRS_MSK_NO_SIGNAL ( 1UL << XMRS_BIT_NO_SIGNAL ) ///< see ::XMRS_BIT_NO_SIGNAL +#define XMRS_MSK_IS_MASTER ( 1UL << XMRS_BIT_IS_MASTER ) ///< see ::XMRS_BIT_IS_MASTER +#define XMRS_MSK_IS_LOCKED ( 1UL << XMRS_BIT_IS_LOCKED ) ///< see ::XMRS_BIT_IS_LOCKED +#define XMRS_MSK_IS_ACCURATE ( 1UL << XMRS_BIT_IS_ACCURATE ) ///< see ::XMRS_BIT_IS_ACCURATE +#define XMRS_MSK_NOT_SETTLED ( 1UL << XMRS_BIT_NOT_SETTLED ) ///< see ::XMRS_BIT_NOT_SETTLED +#define XMRS_MSK_NOT_PHASE_LOCKED ( 1UL << XMRS_BIT_NOT_PHASE_LOCKED ) ///< see ::XMRS_BIT_NOT_PHASE_LOCKED +#define XMRS_MSK_NUM_SRC_EXC ( 1UL << XMRS_BIT_NUM_SRC_EXC ) ///< see ::XMRS_BIT_NUM_SRC_EXC +#define XMRS_MSK_IS_EXTERNAL ( 1UL << XMRS_BIT_IS_EXTERNAL ) ///< see ::XMRS_BIT_IS_EXTERNAL +#define XMRS_MSK_LOW_JITTER ( 1UL << XMRS_BIT_LOW_JITTER ) ///< see ::XMRS_BIT_LOW_JITTER +#define XMRS_MSK_ITU_LIMIT_VIOLATED ( 1UL << XMRS_BIT_ITU_LIMIT_VIOLATED ) ///< see ::XMRS_BIT_ITU_LIMIT_VIOLATED + +/** @} anchor XMR_REF_STATUS_BIT_MASKS */ + + + +/** + * @brief XMRS status bit name strings + * + * @see ::XMR_REF_STATUS_BITS + */ +#define MBG_XMRS_STATUS_STRS \ +{ \ + "Ref type not supported", \ + "No connection", \ + "No signal", \ + "Is master", \ + "Is locked", \ + "Is accurate", \ + "Not settled", \ + "Phase not locked", \ + "Number sources exceeds limit", \ + "Is external", \ + "Low jitter", \ + "ITU Limit violated" \ +} /* - * An initializer for a XMULTI_REF_STATUS variable + * An initializer for a ::XMULTI_REF_STATUS variable * with status invalid / not used */ #define XMULTI_REF_STATUS_INVALID \ @@ -3505,236 +6866,3313 @@ enum } + /** - * @brief The number of supported instances of each ref source type + * @brief General info on supported XMR sources and instances + * + * @note This structure is only supported if ::GPS_HAS_XMRS_MULT_INSTC + * is set in ::RECEIVER_INFO::features. * - * @note This structure is only supported if bit XMRS_FLAG_MULT_INSTC_SUPP - * is set in XMULTI_REF_STATUS::flags. + * The field ::XMULTI_REF_INSTANCES::n_xmr_settings reports the maximum number + * of entries that can be held by the input source table provided by this device. + * The input source table entry with the lowest index has the highest priority, + * and values 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1 can be used as index + * when reading ::XMULTI_REF_INFO_IDX or ::XMULTI_REF_STATUS_IDX from the device, + * or when writing ::XMULTI_REF_SETTINGS_IDX to the device to configure + * the priority/order of input sources. + * + * An input source table entry is empty if ::XMULTI_REF_ID::type is set to + * ::MULTI_REF_NONE in ::XMULTI_REF_SETTINGS::id, and accordingly + * in ::XMULTI_REF_STATUS::id. + * + * The array ::XMULTI_REF_INSTANCES::n_inst reports how many instances are supported + * for every known reference type. For example, if 2 PPS input signals were supported + * then ::XMULTI_REF_INSTANCES::n_inst[::MULTI_REF_PPS] was set to 2. Even though + * this array can hold up to ::MAX_N_MULTI_REF_TYPES entries, the number entries + * which are actually used is ::N_MULTI_REF, according to the number of known + * reference signal types, which is less or equal than ::MAX_N_MULTI_REF_TYPES. */ typedef struct { - uint32_t flags; /**< currently always 0 */ - uint16_t n_xmr_settings; /**< number of configurable multi ref settings */ - uint16_t reserved; /**< number of configurable multi ref settings */ - uint8_t n_inst[32]; /**< N_MULTI_REF entries used, but can not exceed bit number of uint32_t - 1 */ + uint32_t flags; ///< see ::XMR_INST_FLAG_BIT_MASKS + uint16_t n_xmr_settings; ///< number of ::XMULTI_REF_INFO_IDX or ::XMULTI_REF_STATUS_IDX which can be retrieved + uint8_t slot_id; ///< ID of the slot in which this device is installed, 0 or up to 15, if multiple slots not supported + uint8_t reserved; ///< reserved, don't use, currently always 0 + uint8_t n_inst[MAX_N_MULTI_REF_TYPES]; ///< the number of supported instances of each input signal type + } XMULTI_REF_INSTANCES; -/** @} group_xmr_cfg */ +#define _mbg_swab_xmulti_ref_instances( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab16( &(_p)->n_xmr_settings ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of flag bits used with XMULTI_REF instances + * + * @see ::XMR_INST_FLAG_BIT_MASKS + */ +enum XMR_INST_FLAGS +{ + /// This flag indicates that configuration programs may set + /// ::XMULTI_REF_ID::type to ::MULTI_REF_NONE in ::XMULTI_REF_SETTINGS::id + /// for unused priority levels, and that this will be reflected in + /// ::XMULTI_REF_STATUS::id accordingly. With some older firmware versions + /// this was not supported. + XMRIF_BIT_MRF_NONE_SUPP, + + XMRIF_BIT_HOLDOVER_STATUS_SUPP, ///< ::XMR_HOLDOVER_STATUS and associated types supported + + XMRIF_BIT_EXT_SRC_INFO_SUPP, ///< ::XMR_EXT_SRC_INFO structure supported + + N_XMRIF_BITS ///< number of known flag bits +}; + + +/** + * @brief Bit masks associated with ::XMR_INST_FLAGS + * + * Used with ::XMULTI_REF_INSTANCES::flags. + * + * @see ::XMR_INST_FLAGS + */ +enum XMR_INST_FLAG_BIT_MASKS +{ + XMRIF_MSK_MRF_NONE_SUPP = ( 1UL << XMRIF_BIT_MRF_NONE_SUPP ), ///< see ::XMRIF_BIT_MRF_NONE_SUPP + XMRIF_MSK_HOLDOVER_STATUS_SUPP = ( 1UL << XMRIF_BIT_HOLDOVER_STATUS_SUPP ), ///< see ::XMRIF_BIT_HOLDOVER_STATUS_SUPP + XMRIF_MSK_EXT_SRC_INFO_SUPP = ( 1UL << XMRIF_BIT_EXT_SRC_INFO_SUPP ) ///< see ::XMRIF_BIT_EXT_SRC_INFO_SUPP +}; + + + +/** + * @brief XMR holdover interval, or elapsed holdover time, in [s] + */ +typedef uint32_t XMR_HOLDOVER_INTV; + +#define _mbg_swab_xmr_holdover_intv( _p ) \ + _mbg_swab32( _p ) + + + +/** + * @brief A code used to indicate that a input source table index is unspecified + */ +#define XMR_PRIO_LVL_UNSPEC -1 + + +/** + * @brief XMR holdover status + * + * Only supported if ::XMRIF_MSK_HOLDOVER_STATUS_SUPP is set in ::XMULTI_REF_INSTANCES::flags + * + * Reports the current holdover status including the elapsed holdover time + * and the currently active holdover interval, as well as the indices of the + * current and next XMR time source. + * + * The flag ::XMR_HLDOVR_MSK_IN_HOLDOVER is set if holdover mode is currently active. + * + * The fields ::XMR_HOLDOVER_STATUS::curr_prio and ::XMR_HOLDOVER_STATUS::nxt_prio + * specify the current or next priority level which can be in the range + * 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1, or ::XMR_PRIO_LVL_UNSPEC if the + * index is undefined, e.g. because no input source is available to which can + * be switched after the holdover interval. + * + * The ::XMR_HOLDOVER_STATUS::mode field indicates the current XMR/holdover mode + * which is usually ::XMR_HLDOVR_AUTONOMOUS. However, in certain applications + * XMR switching is controlled remotely, in which case ::XMR_HOLDOVER_STATUS::mode + * is set to ::XMR_HLDOVR_REMOTE. + * + * If the device is in remote mode and needs to switch XMR sources then mode changes + * to ::XMR_HLDOVR_PRE_AUTONOMOUS, and the ::XMR_HOLDOVER_STATUS::remote_watchdog + * starts to count down. If the watchdog expires before a remote switch command + * has been received the device switches to ::XMR_HLDOVR_AUTONOMOUS. + */ +typedef struct +{ + uint8_t mode; ///< XMR/holdover mode, see ::XMR_HOLDOVER_STATUS_MODES + int8_t curr_prio; ///< current priority level, 0..::XMULTI_REF_INSTANCES::n_xmr_settings, or ::XMR_PRIO_LVL_UNSPEC + int8_t nxt_prio; ///< next priority level after holdover, 0..::XMULTI_REF_INSTANCES::n_xmr_settings, or ::XMR_PRIO_LVL_UNSPEC + uint8_t remote_watchdog; ///< counts down in ::XMR_HLDOVR_PRE_AUTONOMOUS mode + uint32_t time_offset_ns; ///< estimated time offset in holdover operation + XMR_HOLDOVER_INTV elapsed; ///< elapsed time in holdover mode, only valid if ::XMR_HLDOVR_MSK_IN_HOLDOVER is set + XMR_HOLDOVER_INTV interval; ///< current holdover interval, only valid if ::XMR_HLDOVR_MSK_IN_HOLDOVER is set + uint32_t flags; ///< holdover status flags, see ::XMR_HOLDOVER_STATUS_FLAG_MASKS + +} XMR_HOLDOVER_STATUS; + +#define _mbg_swab_xmr_holdover_status( _p ) \ +do \ +{ \ + _mbg_swab8( &(_p)->mode ); \ + _mbg_swab8( &(_p)->curr_prio ); \ + _mbg_swab8( &(_p)->nxt_prio ); \ + _mbg_swab8( &(_p)->remote_watchdog ); \ + _mbg_swab32( &(_p)->time_offset_ns ); \ + _mbg_swab_xmr_holdover_intv( &(_p)->elapsed ); \ + _mbg_swab_xmr_holdover_intv( &(_p)->interval ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + + +/** + * @brief XMR holdover status modes + * + * Used with ::XMR_HOLDOVER_STATUS::mode. + * + * @see ::XMR_HOLDOVER_STATUS_MODE_NAMES + */ +enum XMR_HOLDOVER_STATUS_MODES +{ + XMR_HLDOVR_AUTONOMOUS, ///< autonomous mode, XMR sources are selected automatically by the device + XMR_HLDOVR_PRE_AUTONOMOUS, ///< going to switch to autonomous mode when ::XMR_HOLDOVER_STATUS::remote_watchdog reaches 0 + XMR_HLDOVR_REMOTE, ///< remote mode, XMR switching done by external command/control + N_XMR_HOLDOVER_STATUS_MODES ///< the number of known modes +}; + + +/** + * @brief String initializers for XMR holdover status mode + * + * @see ::XMR_HOLDOVER_STATUS_MODES + */ +#define XMR_HOLDOVER_STATUS_MODE_NAMES \ +{ \ + "Autonomous", \ + "Pre-Autonomous", \ + "Remote" \ +} + + + +/** + * @brief XMR holdover status flag bits + * + * Used to define ::XMR_HOLDOVER_STATUS_FLAG_MASKS. + */ +enum XMR_HOLDOVER_STATUS_FLAG_BITS +{ + XMR_HLDOVR_BIT_IN_HOLDOVER, ///< the device is currently in holdover mode + XMR_HLDOVR_BIT_TRANSITION_ENBD, ///< timebase is in transition (being slewed) after sources have been switched + XMR_HLDOVR_BIT_IN_TRANSITION, ///< transition is currently active, slewing in progress + XMR_HLDOVR_BIT_TIME_OFFS_VALID, ///< values in field ::XMR_HOLDOVER_STATUS::time_offset_ns are valid + N_XMR_HOLDOVER_STATUS_FLAG_BITS ///< the number of known status flags +}; + + +/** + * @brief XMR holdover status flag masks + * + * Used with ::XMR_HOLDOVER_STATUS::flags. + */ +enum XMR_HOLDOVER_STATUS_FLAG_MASKS +{ + XMR_HLDOVR_MSK_IN_HOLDOVER = ( 1UL << XMR_HLDOVR_BIT_IN_HOLDOVER ), ///< see ::XMR_HLDOVR_BIT_IN_HOLDOVER + XMR_HLDOVR_MSK_TRANSITION_ENBD = ( 1UL << XMR_HLDOVR_BIT_TRANSITION_ENBD ), ///< see ::XMR_HLDOVR_BIT_TRANSITION_ENBD + XMR_HLDOVR_MSK_IN_TRANSITION = ( 1UL << XMR_HLDOVR_BIT_IN_TRANSITION ), ///< see ::XMR_HLDOVR_BIT_IN_TRANSITION + XMR_HLDOVR_MSK_TIME_OFFS_VALID = ( 1UL << XMR_HLDOVR_BIT_TIME_OFFS_VALID ) ///< see ::XMR_HLDOVR_BIT_TIME_OFFS_VALID +}; + + + +/** + * @brief XMR source feature flag bits + * + * Used to define ::XMR_EXT_SRC_FEAT_FLAG_MSKS + */ +enum XMR_EXT_SRC_FEAT_FLAG_BITS +{ + XMR_EXT_SRC_FEAT_FLAG_BIT_STATS, ///< XMR source provides ::XMR_STATS + XMR_EXT_SRC_FEAT_FLAG_BIT_METRICS, ///< XMR source provides ::XMR_METRICS + N_XMR_EXT_SRC_FEAT_FLAG_BITS +}; + + + +/** + * @brief XMR source feature flag bit masks + * + * Used with ::XMR_EXT_SRC_INFO::feat_flags. + * + * @see ::XMR_EXT_SRC_FEAT_FLAG_BITS + */ +enum XMR_EXT_SRC_FEAT_FLAG_MSKS +{ + XMR_EXT_SRC_FEAT_FLAG_MSK_STATS = ( 1UL << XMR_EXT_SRC_FEAT_FLAG_BIT_STATS ), ///< see ::XMR_EXT_SRC_FEAT_FLAG_BIT_STATS + XMR_EXT_SRC_FEAT_FLAG_MSK_METRICS = ( 1UL << XMR_EXT_SRC_FEAT_FLAG_BIT_METRICS ) ///< see ::XMR_EXT_SRC_FEAT_FLAG_BIT_METRICS +}; + + + +typedef struct +{ + uint16_t supp_flags; ///< indicates which flags are supported by ::XMULTI_REF_SETTINGS::flags, see ::XMR_SETTINGS_FLAG_MSKS + uint16_t feat_flags; ///< see ::XMR_EXT_SRC_FEAT_FLAG_MSKS + uint32_t reserved_0; + +} XMR_EXT_SRC_INFO; + +#define _mbg_swab_xmr_ext_src_info( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->supp_flags ); \ + _mbg_swab16( &(_p)->feat_flags ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ +} while ( 0 ) + + + +typedef struct +{ + uint16_t idx; // + XMR_EXT_SRC_INFO info; // + +} XMR_EXT_SRC_INFO_IDX; // + +#define _mbg_swab_xmr_ext_src_info_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_xmr_ext_src_info( &(_p)->info ); \ +} while ( 0 ) + + + +/** + * @brief XMR statistics for a particular source + * + * This structure is only provided by an XMR source which has + * ::XMR_EXT_SRC_FEAT_FLAG_MSK_STATS set in ::XMR_EXT_SRC_INFO::feat_flags. + * + * @see ::XMR_STATS_IDX + * @see ::XMR_EXT_SRC_INFO::feat_flags + * @see ::XMR_EXT_SRC_FEAT_FLAG_MSK_STATS + */ +typedef struct +{ + uint32_t timestamp; ///< time stamp when the record was taken, UTC, seconds since 1970 + NANO_TIME last_mue; ///< mean value (mue) of prev. interval + NANO_TIME last_sigma; ///< standard deviation (sigma) of prev. interval + NANO_TIME last_max; ///< maximum value within interval + NANO_TIME last_min; ///< minimum value within interval + NANO_TIME reserved_0; ///< currently reserved, unused, always 0 + NANO_TIME step_comp_val; ///< current step compensation value + NANO_TIME auto_bias; ///< current time automatic bias compensation + uint32_t reserved_1; ///< currently reserved, unused, always 0 + uint32_t reserved_2; ///< currently reserved, unused, always 0 + uint32_t flags; ///< see ::XMR_STATS_FLAGS_MSKS + +} XMR_STATS; + +#define _mbg_swab_xmr_stats( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->timestamp ); \ + _mbg_swab_nano_time( &(_p)->last_mue ); \ + _mbg_swab_nano_time( &(_p)->last_sigma ); \ + _mbg_swab_nano_time( &(_p)->last_max ); \ + _mbg_swab_nano_time( &(_p)->last_min ); \ + _mbg_swab_nano_time( &(_p)->reserved_0 ); \ + _mbg_swab_nano_time( &(_p)->step_comp_val ); \ + _mbg_swab_nano_time( &(_p)->auto_bias ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of bits used to define ::XMR_STATS_FLAGS_MSKS + * + * @see ::XMR_STATS_FLAGS_MSKS + */ +enum XMR_STATS_FLAGS_BITS +{ + XMR_STATS_FLAG_BIT_STEP_DETECTED, ///< A time step was detected at the input source + XMR_STATS_FLAG_BIT_STEP_COMPENSATED, ///< A time step was compensated at the input source + XMR_STATS_FLAG_BIT_AUTO_BIAS_VALID, ///< The value in ::XMR_STATS::auto_bias is valid + N_XMR_STATS_FLAGS_BITS +}; + + + +/** + * @brief Flag bit masks used with ::XMR_STATS::flags + * + * @see ::XMR_STATS_FLAGS_BITS + */ +enum XMR_STATS_FLAGS_MSKS +{ + XMR_STATS_FLAG_MSK_STEP_DETECTED = ( 1UL << XMR_STATS_FLAG_BIT_STEP_DETECTED ), ///< see ::XMR_STATS_FLAG_BIT_STEP_DETECTED + XMR_STATS_FLAG_MSK_STEP_COMPENSATED = ( 1UL << XMR_STATS_FLAG_BIT_STEP_COMPENSATED ), ///< see ::XMR_STATS_FLAG_BIT_STEP_COMPENSATED + XMR_STATS_FLAG_MSK_AUTO_BIAS_VALID = ( 1UL << XMR_STATS_FLAG_BIT_AUTO_BIAS_VALID ) ///< see ::XMR_STATS_FLAG_BIT_AUTO_BIAS_VALID +}; + + + +/** + * @brief String initializers for XMR Stats Flags + * + * @see ::XMR_STATS_FLAGS_MSKS + */ +#define DEFAULT_XMR_STATS_FLAG_NAMES \ +{ \ + "Step Detected", \ + "Step Compensated", \ + "Auto BIAS valid" \ +} + + + +/** + * @brief XMR statistics for a particular source, with index + * + * @see ::XMR_STATS + */ +typedef struct +{ + uint16_t idx; ///< the priority level index (highest == 0), 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1 + XMR_STATS stats; ///< XMR statistics of the particular source + +} XMR_STATS_IDX; + +#define _mbg_swab_xmr_stats_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_xmr_stats( &(_p)->stats ); \ +} while ( 0 ) + + + +#define MAX_XMR_METRICS 20 + +typedef struct +{ + uint32_t timestamp; + uint32_t flags; ///< idx bit set if mtie[idx] is valid + uint8_t mtie_scale; ///< scale factors of MTIE + uint8_t tdev_scale; ///< scale factors of TDEV + uint16_t reserved_0; ///< currently unused + uint32_t reserved_1; ///< currently unused + uint32_t reserved_2; ///< currently unused + uint32_t mtie[MAX_XMR_METRICS]; ///< mtie scaled 32 bit fixed point unsigned + uint32_t tdev[MAX_XMR_METRICS]; ///< tdev scaled 32 bit fixed point unsigned + +} XMR_METRICS; + +#define _mbg_swab_xmr_metrics( _p ) \ +do \ +{ \ + int i; \ + \ + _mbg_swab32( &(_p)->timestamp ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab8( &(_p)->mtie_scale ); \ + _mbg_swab8( &(_p)->tdev_scale ); \ + _mbg_swab16( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + \ + for ( i = 0; i < MAX_XMR_METRICS; i++ ) \ + _mbg_swab32( &(_p)->mtie[i] ); \ + \ + for ( i = 0; i < MAX_XMR_METRICS; i++ ) \ + _mbg_swab32( &(_p)->tdev[i] ); \ + \ +} while ( 0 ) + + + +// conversion factor scaled FPU32 to double +#define _fpu32_to_double_fac( _x ) ( 1.0 / ( 4294967296.0 * ( _x ) ) ) + + + +/** + * @brief XMR timing metrics for a particular source, with index + * + * @see ::XMR_METRICS + */ +typedef struct +{ + uint16_t idx; + XMR_METRICS metrics; + +} XMR_METRICS_IDX; + +#define _mbg_swab_xmr_metrics_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_xmr_metrics( &(_p)->metrics ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of ITU limit masks + * + * Used for detection of ::XMR_METRICS mask violation. + * + * @see ::ITU_LIMIT_MASKS + * @see ::XMR_METRICS + */ +enum ITU_LIMITS +{ + ITU_LIMIT_G811_PRC, + ITU_LIMIT_G823_SSU, + ITU_LIMIT_G823_SEC, + ITU_LIMIT_G8272_PRTC, + ITU_LIMIT_G82721_EPRTC, + N_ITU_LIMITS +} ; + + + +/** + * @brief Enumeration of ITU limit masks + * + * Used for detection of ::XMR_METRICS mask violation. + * + * @see ::ITU_LIMITS + * @see ::XMR_METRICS + */ +enum ITU_LIMIT_MASKS +{ + MSK_ITU_LIMIT_G811_PRC = ( 1UL << ITU_LIMIT_G811_PRC ), + MSK_ITU_LIMIT_G823_SSU = ( 1UL << ITU_LIMIT_G823_SSU ), + MSK_ITU_LIMIT_G823_SEC = ( 1UL << ITU_LIMIT_G823_SEC ), + MSK_ITU_LIMIT_G8272_PRTC = ( 1UL << ITU_LIMIT_G8272_PRTC ), + MSK_ITU_LIMIT_G82721_EPRTC = ( 1UL << ITU_LIMIT_G82721_EPRTC ) +}; + + + +/** + * @brief String initializers for ITU limit masks + * + * Used for detection of ::XMR_METRICS mask violation. + * + * @see ::ITU_LIMITS + * @see ::XMR_METRICS + */ +#define ITU_LIMIT_SHORT_STRS \ +{ \ + "G811 (PRC)", \ + "G823 (SSU)", \ + "G823 (SEC)", \ + "G8272 (PRTC)", \ + "G82721 (ePRTC)" \ +} + + + +/** + * @brief supported limits for qualtity metrics + * + * @see ::XMR_METRICS + */ +typedef struct +{ + uint8_t ql_mask; ///< see :ITU_LIMIT_MASKS + uint8_t hysteresis; ///< hysteresis (percent) between yellow and red alarm + uint16_t reserved_0; + uint32_t reserved_1; + +} XMR_QL_SETTINGS; + + + +typedef struct +{ + uint32_t supp_ql_masks; ///< see :ITU_LIMIT_MASKS + uint32_t reserved_0; + uint32_t reserved_1; + XMR_QL_SETTINGS settings; + +} XMR_QL_INFO; + + + +typedef struct +{ + uint16_t idx; + XMR_QL_SETTINGS settings; + +} XMR_QL_SETTINGS_IDX; + + + +typedef struct +{ + uint16_t idx; + XMR_QL_INFO info; + +} XMR_QL_INFO_IDX; + + +/** @} defgroup group_multi_ref_ext */ + +/** @} defgroup group_multi_ref_all */ /** * @defgroup group_gpio GPIO port configuration stuff * + * @note This is only supported if ::GPS_HAS_GPIO is set + * in the ::RECEIVER_INFO::features mask. + * * @{ */ + /** * @brief General GPIO config info to be read from a device + * + * Used to query from a device how many GPIO ports are supported + * by the device, then index 0..::MBG_GPIO_CFG_LIMITS::num_io-1 + * configuration or status records can be read from or written to + * the device. */ typedef struct { - uint32_t num_io; /**< number of supported GPIO ports */ - uint32_t reserved; /**< currently always 0 */ - uint32_t flags; /**< currently always 0 */ + uint32_t num_io; ///< number of supported GPIO ports + uint32_t reserved; ///< reserved, currently always 0 + uint32_t flags; ///< see ::MBG_GPIO_CFG_LIMIT_FLAG_MASKS } MBG_GPIO_CFG_LIMITS; +#define _mbg_swab_mbg_gpio_cfg_limits( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->num_io ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief GPIO limits flag bits used to define ::MBG_GPIO_CFG_LIMIT_FLAG_MASKS + * + * @see ::MBG_GPIO_CFG_LIMIT_FLAG_MASKS + */ +enum MBG_GPIO_CFG_LIMIT_FLAG_BITS +{ + MBG_GPIO_CFG_LIMIT_FLAG_BIT_STATUS_SUPP, ///< indicates that ::MBG_GPIO_STATUS is supported + N_MBG_GPIO_CFG_LIMIT_FLAG_BITS +}; + + + +/** + * @brief GPIO limits flag masks associated with ::MBG_GPIO_CFG_LIMIT_FLAG_BITS + * + * Used with ::MBG_GPIO_CFG_LIMITS::flags + * + * @see ::MBG_GPIO_CFG_LIMIT_FLAG_BITS + */ +enum MBG_GPIO_CFG_LIMIT_FLAG_MASKS +{ + MBG_GPIO_CFG_LIMIT_FLAG_MASK_STATUS_SUPP = ( 1UL << MBG_GPIO_CFG_LIMIT_FLAG_BIT_STATUS_SUPP ), ///< see ::MBG_GPIO_CFG_LIMIT_FLAG_BIT_STATUS_SUPP +}; + + + +/** + * @brief Enumeration of GPIO types + * + * Usually a specific GPIO port can only be either an input + * or an output, and supports only a single signal type. + * This is due to hardware limitations, i.e. input or output + * circuitry required for the given signal. + * + * @see ::DEFAULT_GPIO_TYPES_SHORT_STRS + */ +enum MBG_GPIO_TYPES +{ + MBG_GPIO_TYPE_FREQ_IN, ///< Variable frequency input, freq == 0 if input not used + MBG_GPIO_TYPE_FREQ_OUT, ///< Variable frequency output + MBG_GPIO_TYPE_FIXED_FREQ_OUT, ///< Fixed frequency output + MBG_GPIO_TYPE_BITS_IN, ///< Framed data stream input + MBG_GPIO_TYPE_BITS_OUT, ///< Framed data stream output + MBG_GPIO_TYPE_VIDEO_OUT, ///< Video signal output (PAL, NTSC, ...) + MBG_GPIO_TYPE_VIDEO_SYNC_OUT, ///< Video sync signal output (H-Sync, V-Sync, ...) + MBG_GPIO_TYPE_STUDIO_CLOCK_OUT, ///< Studio clock output + MBG_GPIO_TYPE_DIGITAL_AUDIO_OUT, ///< Digital Audio output (DARS, ...) + N_MBG_GPIO_TYPES ///< Number of known types +}; + + + +#define DEFAULT_GPIO_TYPES_SHORT_STRS \ +{ \ + "Freq. In", \ + "Freq. Out", \ + "Fixed Freq Out", \ + "BITS In", \ + "BITS Out", \ + "Video Out", \ + "Video Sync Out", \ + "Studio Clock Out", \ + "Digital Audio Out" \ +} + + + +/** + * @brief Enumeration of known signal shapes + * + * Used to specify the signal shape of an input or output + * frequency signal. + * + * @see ::MBG_GPIO_SIGNAL_SHAPE_MASKS + * @see ::DEFAULT_GPIO_SIGNAL_SHAPE_NAMES + */ +enum MBG_GPIO_SIGNAL_SHAPES +{ + MBG_GPIO_SIGNAL_SHAPE_UNSPECIFIED, ///< unknown or unspecified signal shape + MBG_GPIO_SIGNAL_SHAPE_SINE, ///< sine wave + MBG_GPIO_SIGNAL_SHAPE_SQUARE, ///< square wave + N_MBG_GPIO_SIGNAL_SHAPES ///< number of known signal shapes +}; + + + +/** + * @brief Bit masks associated with ::MBG_GPIO_SIGNAL_SHAPES + * + * Used e.g. with ::MBG_GPIO_FREQ_IN_SUPP::supp_shapes, + * ::MBG_GPIO_FREQ_OUT_SUPP::supp_shapes, + * and ::MBG_GPIO_FIXED_FREQ_OUT_SUPP::supp_shapes. + * + * @see ::MBG_GPIO_SIGNAL_SHAPES + */ +enum MBG_GPIO_SIGNAL_SHAPE_MASKS +{ + MBG_GPIO_SIGNAL_SHAPE_MSK_UNSPECIFIED = ( 1UL << MBG_GPIO_SIGNAL_SHAPE_UNSPECIFIED ), ///< see ::MBG_GPIO_SIGNAL_SHAPE_UNSPECIFIED + MBG_GPIO_SIGNAL_SHAPE_MSK_SINE = ( 1UL << MBG_GPIO_SIGNAL_SHAPE_SINE ), ///< see ::MBG_GPIO_SIGNAL_SHAPE_SINE + MBG_GPIO_SIGNAL_SHAPE_MSK_SQUARE = ( 1UL << MBG_GPIO_SIGNAL_SHAPE_SQUARE ) ///< see ::MBG_GPIO_SIGNAL_SHAPE_SQUARE +}; + + + +/** + * @brief String initializers for GPIO signal shapes + * + * @see ::MBG_GPIO_SIGNAL_SHAPES + */ +#define DEFAULT_GPIO_SIGNAL_SHAPE_NAMES \ +{ \ + "(unspec. shape)", \ + "Sine wave", \ + "Rectangle Pulse" \ +} + /** * @brief A structure used to specify a variable frequency + * + * Used to specify a variable frequency for GPIO input or output */ typedef struct { - uint32_t hz; /**< integral number, Hz */ - uint32_t frac; /**< fractional part, binary */ + uint32_t hz; ///< integral number [Hz] + uint32_t frac; ///< fractional part, binary (0x80000000 --> 0.5, 0xFFFFFFFF --> 0.9999999...) } MBG_GPIO_FREQ; +#define _mbg_swab_mbg_gpio_freq( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->hz ); \ + _mbg_swab32( &(_p)->frac); \ +} while ( 0 ) + + /** - * @brief A structure used to specify a fixed frequency + * @brief Configuration of a GPIO variable frequency input + * + * Used as sub-structure of ::MBG_GPIO_SETTINGS. + * + * @see ::MBG_GPIO_TYPE_FREQ_IN + * @see ::MBG_GPIO_SETTINGS */ typedef struct { - uint32_t frq_bit; /**< fixed freq. bit mask ( see enum ) */ - uint32_t reserved; /**< reserved */ + MBG_GPIO_FREQ freq; ///< frequency in range ::MBG_GPIO_FREQ_IN_SUPP::freq_min..::MBG_GPIO_FREQ_IN_SUPP::freq_max, or 0 if input is not used + uint32_t csc_limit; ///< max. cycle slip [1/1000 cycle units], see ::MBG_GPIO_FREQ_IN_SUPP::csc_limit_max + uint32_t shape; ///< selected signal shape, see ::MBG_GPIO_SIGNAL_SHAPES + uint32_t reserved; ///< reserved, currently always 0 + uint32_t flags; ///< reserved, currently always 0 + +} MBG_GPIO_FREQ_IN_SETTINGS; + +#define _mbg_swab_mbg_gpio_freq_in_settings( _p ) \ +do \ +{ \ + _mbg_swab_mbg_gpio_freq( &(_p)->freq ); \ + _mbg_swab32( &(_p)->csc_limit ); \ + _mbg_swab32( &(_p)->shape ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + -} MBG_GPIO_FIXED_FREQ; /** - * @brief A structure used to configure a GPIO as frequency output + * @brief Supported options for a variable frequency GPIO input + * + * Used as sub-structure of ::MBG_GPIO_LIMITS. + * + * @see ::MBG_GPIO_TYPE_FREQ_IN + * @see ::MBG_GPIO_LIMITS */ typedef struct { - MBG_GPIO_FREQ freq; /**< frequency */ - int32_t milli_phase; /**< phase [1/1000 degree units] */ - uint32_t type; /**< sine, rectangle, etc. */ //##++++++++++++++ - uint32_t reserved; /**< currently always 0 */ - uint32_t flags; /**< currently always 0 */ + uint32_t freq_min; ///< minimum output frequency [Hz] + uint32_t freq_max; ///< maximum output frequency [Hz] + uint32_t csc_limit_max; ///< 1/1000 units of the signal period, limited due to 10 ns sampling interval, see ::MBG_GPIO_FREQ_IN_SETTINGS::csc_limit //##++++++++++++++++ + uint32_t supp_shapes; ///< bit mask of supported signal shapes, see ::MBG_GPIO_SIGNAL_SHAPE_MASKS + uint32_t supp_limits; ///< supported ITU limit masks for BITS signal see ::ITU_LIMIT_MASKS + uint32_t flags; ///< reserved, currently always 0 + +} MBG_GPIO_FREQ_IN_SUPP; + +#define _mbg_swab_mbg_gpio_freq_in_supp( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->freq_min ); \ + _mbg_swab32( &(_p)->freq_max ); \ + _mbg_swab32( &(_p)->csc_limit_max ); \ + _mbg_swab32( &(_p)->supp_shapes ); \ + _mbg_swab32( &(_p)->supp_limits ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) -} MBG_GPIO_FREQ_OUT_SETTINGS; /** - * @brief A structure used to configure a GPIO as frequency output + * @brief Configuration of a GPIO variable frequency output + * + * Used as sub-structure of ::MBG_GPIO_SETTINGS. + * + * @see ::MBG_GPIO_TYPE_FREQ_OUT + * @see ::MBG_GPIO_SETTINGS */ +typedef struct +{ + MBG_GPIO_FREQ freq; ///< frequency, see ::MBG_GPIO_FREQ_OUT_SUPP::freq_min and ::MBG_GPIO_FREQ_OUT_SUPP::freq_max + int32_t milli_phase; ///< phase [1/1000 degree units], see ::MBG_GPIO_FREQ_OUT_SUPP::milli_phase_max + uint32_t shape; ///< selected signal shape, see ::MBG_GPIO_SIGNAL_SHAPES + uint32_t reserved; ///< reserved, currently always 0 + uint32_t flags; ///< reserved, currently always 0 + +} MBG_GPIO_FREQ_OUT_SETTINGS; + +#define _mbg_swab_mbg_gpio_freq_out_settings( _p ) \ +do \ +{ \ + _mbg_swab_mbg_gpio_freq( &(_p)->freq ); \ + _mbg_swab32( &(_p)->milli_phase ); \ + _mbg_swab32( &(_p)->shape ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + +/** + * @brief Supported options for a variable frequency GPIO output + * + * Used as sub-structure of ::MBG_GPIO_LIMITS. + * + * @see ::MBG_GPIO_TYPE_FREQ_OUT + * @see ::MBG_GPIO_LIMITS + */ typedef struct { - MBG_GPIO_FREQ freq; /**< frequency */ - uint32_t csc_limit; /**< max. cycle slip [1/1000 cycle units] */ - uint32_t type; /**< sine, rectangle, etc. */ //##++++++++++++++ - uint32_t reserved; /**< currently always 0 */ - uint32_t flags; /**< currently always 0 */ + uint32_t freq_min; ///< minimum output frequency [Hz], see ::MBG_GPIO_FREQ_OUT_SETTINGS::freq + uint32_t freq_max; ///< maximum output frequency [Hz], see ::MBG_GPIO_FREQ_OUT_SETTINGS::freq + uint32_t freq_resolution; ///< frequency resolution [Hz], unspecified if 0 + uint32_t milli_phase_max; ///< max. abs. milli_phase, see ::MBG_GPIO_FREQ_OUT_SETTINGS::milli_phase + uint32_t supp_shapes; ///< bit mask of supported signal shapes, see ::MBG_GPIO_SIGNAL_SHAPE_MASKS + uint32_t reserved; ///< reserved, currently always 0 + uint32_t flags; ///< reserved, currently always 0 + +} MBG_GPIO_FREQ_OUT_SUPP; + +#define _mbg_swab_mbg_gpio_freq_out_supp( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->freq_min ); \ + _mbg_swab32( &(_p)->freq_max ); \ + _mbg_swab32( &(_p)->freq_resolution ); \ + _mbg_swab32( &(_p)->milli_phase_max ); \ + _mbg_swab32( &(_p)->supp_shapes ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) -} MBG_GPIO_FREQ_IN_SETTINGS; + + +/** + * @brief Enumeration of predefined fixed frequencies + * + * @see ::MBG_GPIO_FIXED_FREQ_MASKS + * @see ::MBG_GPIO_FIXED_FREQ_STRS + */ +enum MBG_GPIO_FIXED_FREQS +{ + MBG_GPIO_FIXED_FREQ_8kHz, ///< 8 kHz + MBG_GPIO_FIXED_FREQ_48kHz, ///< 48 kHz + MBG_GPIO_FIXED_FREQ_1MHz, ///< 1 MHz + MBG_GPIO_FIXED_FREQ_1544kHz, ///< 1.544 MHz + MBG_GPIO_FIXED_FREQ_2048kHz, ///< 2.048 MHz + MBG_GPIO_FIXED_FREQ_5MHz, ///< 5 MHz + MBG_GPIO_FIXED_FREQ_10MHz, ///< 10 MHz + MBG_GPIO_FIXED_FREQ_19440kHz, ///< 19.44 MHz + N_MBG_GPIO_FIXED_FREQ ///< number of predefined fixed frequencies +}; + + +/** + * @brief Bit masks associated with ::MBG_GPIO_FIXED_FREQS + * + * @see ::MBG_GPIO_FIXED_FREQS + * @see ::MBG_GPIO_FIXED_FREQ_STRS + */ +enum MBG_GPIO_FIXED_FREQ_MASKS +{ + MSK_MBG_GPIO_FIXED_FREQ_8kHz = ( 1UL << MBG_GPIO_FIXED_FREQ_8kHz ), ///< see ::MBG_GPIO_FIXED_FREQ_8kHz + MSK_MBG_GPIO_FIXED_FREQ_48kHz = ( 1UL << MBG_GPIO_FIXED_FREQ_48kHz ), ///< see ::MBG_GPIO_FIXED_FREQ_48kHz + MSK_MBG_GPIO_FIXED_FREQ_1MHz = ( 1UL << MBG_GPIO_FIXED_FREQ_1MHz ), ///< see ::MBG_GPIO_FIXED_FREQ_1MHz + MSK_MBG_GPIO_FIXED_FREQ_1544kHz = ( 1UL << MBG_GPIO_FIXED_FREQ_1544kHz ), ///< see ::MBG_GPIO_FIXED_FREQ_1544kHz + MSK_MBG_GPIO_FIXED_FREQ_2048kHz = ( 1UL << MBG_GPIO_FIXED_FREQ_2048kHz ), ///< see ::MBG_GPIO_FIXED_FREQ_2048kHz + MSK_MBG_GPIO_FIXED_FREQ_5MHz = ( 1UL << MBG_GPIO_FIXED_FREQ_5MHz ), ///< see ::MBG_GPIO_FIXED_FREQ_5MHz + MSK_MBG_GPIO_FIXED_FREQ_10MHz = ( 1UL << MBG_GPIO_FIXED_FREQ_10MHz ), ///< see ::MBG_GPIO_FIXED_FREQ_10MHz + MSK_MBG_GPIO_FIXED_FREQ_19440kHz = ( 1UL << MBG_GPIO_FIXED_FREQ_19440kHz ) ///< see ::MBG_GPIO_FIXED_FREQ_19440kHz +}; + + +/** + * @brief Initializers for an array of GPIO fixed frequency name strings + * + * @see ::MBG_GPIO_FIXED_FREQS + * @see ::MBG_GPIO_FIXED_FREQ_MASKS + */ +#define MBG_GPIO_FIXED_FREQ_STRS \ +{ \ + "8 kHz", \ + "48 kHz", \ + "1 MHz", \ + "1544 kHz", \ + "2048 kHz", \ + "5 MHz", \ + "10 MHz", \ + "19440 kHz" \ +} /** - * @brief A structure used to configure a GPIO as fixed frequency output + * @brief Configuration of a GPIO fixed frequency output + * + * Used as sub-structure of ::MBG_GPIO_SETTINGS. + * + * @see ::MBG_GPIO_TYPE_FIXED_FREQ_OUT + * @see ::MBG_GPIO_SETTINGS */ typedef struct { - MBG_GPIO_FIXED_FREQ freq; /**< frequency */ - uint32_t reserved_0; /**< supported frequencies bit mask, see enum */ - uint32_t type; /**< sine, rectangle, etc. */ //##++++++++++++++ - uint32_t reserved_1; /**< currently always 0 */ - uint32_t flags; /**< currently always 0 */ + uint32_t freq_idx; ///< fixed frequency index, see ::MBG_GPIO_FIXED_FREQS + uint32_t shape; ///< selected signal shape, see ::MBG_GPIO_SIGNAL_SHAPES + uint32_t reserved; ///< reserved, currently always 0 + uint32_t flags; ///< reserved, currently always 0 } MBG_GPIO_FIXED_FREQ_OUT_SETTINGS; +#define _mbg_swab_mbg_gpio_fixed_freq_out_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->freq_idx ); \ + _mbg_swab32( &(_p)->shape ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Supported options for a fixed frequency output + * + * Used as sub-structure of ::MBG_GPIO_LIMITS. + * + * @see ::MBG_GPIO_TYPE_FIXED_FREQ_OUT + * @see ::MBG_GPIO_LIMITS + */ +typedef struct +{ + uint32_t supp_freq; ///< bit mask of supported fixed frequencies, see ::MBG_GPIO_FIXED_FREQ_MASKS + uint32_t supp_shapes; ///< bit mask of supported signal shapes, see ::MBG_GPIO_SIGNAL_SHAPE_MASKS + uint32_t reserved; ///< reserved, currently always 0 + uint32_t supp_flags; ///< reserved, currently always 0 + +} MBG_GPIO_FIXED_FREQ_OUT_SUPP; + +#define _mbg_swab_mbg_gpio_fixed_freq_out_supp( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->supp_freq ); \ + _mbg_swab32( &(_p)->supp_shapes ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->supp_flags ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of BITS signal formats + * + * Used with ::MBG_GPIO_BITS_IN_SETTINGS::format and ::MBG_GPIO_BITS_OUT_SETTINGS::format + * + * @see ::MBG_GPIO_BITS_FORMAT_MASKS + */ +enum MBG_GPIO_BITS_FORMATS +{ + MBG_GPIO_BITS_E1_FRAMED, ///< 2.048 MBit + MBG_GPIO_BITS_T1_FRAMED, ///< 1.544 MBit + MBG_GPIO_BITS_E1_TIMING, ///< 2.048 MHz + MBG_GPIO_BITS_T1_TIMING, ///< 2.048 MHz + N_MBG_GPIO_BITS_FORMATS ///< number of defined formats +}; + + +/** + * @brief Bit masks associated with ::MBG_GPIO_BITS_FORMATS + * + * Used with ::MBG_GPIO_BITS_IN_SUPP::supp_fmts and ::MBG_GPIO_BITS_OUT_SUPP::supp_fmts. + * + * @see ::MBG_GPIO_BITS_FORMATS + */ +enum MBG_GPIO_BITS_FORMAT_MASKS +{ + MSK_MBG_GPIO_BITS_E1_FRAMED = ( 1UL << MBG_GPIO_BITS_E1_FRAMED ), ///< see ::MBG_GPIO_BITS_E1_FRAMED + MSK_MBG_GPIO_BITS_T1_FRAMED = ( 1UL << MBG_GPIO_BITS_T1_FRAMED ), ///< see ::MBG_GPIO_BITS_T1_FRAMED + MSK_MBG_GPIO_BITS_E1_TIMING = ( 1UL << MBG_GPIO_BITS_E1_TIMING ), ///< see ::MBG_GPIO_BITS_E1_TIMING + MSK_MBG_GPIO_BITS_T1_TIMING = ( 1UL << MBG_GPIO_BITS_T1_TIMING ) ///< see ::MBG_GPIO_BITS_T1_TIMING +}; + + +/** + * @brief Initializers for an array of GPIO bit format strings + * + * @see ::MBG_GPIO_BITS_FORMATS + * @see ::MBG_GPIO_BITS_FORMAT_MASKS + */ +#define MBG_GPIO_BITS_FORMAT_STRS \ +{ \ + "E1 Framed", \ + "T1 Framed", \ + "E1 Timing", \ + "T1 Timing" \ +} + + + +/** + * @brief Minimum and maximum known SSM values + * + * Values according to ITU G.704-1998 + * + * Used with ::MBG_GPIO_BITS_IN_SETTINGS::quality::e1.ssm + * and ::MBG_GPIO_BITS_OUT_SETTINGS::ssm. + */ +enum GPIO_SSM_VALS +{ + GPIO_SSM_UNKNOWN, ///< Quality unknown, existing synchronization network + GPIO_SSM_RSVD_1, ///< (reserved) + GPIO_SSM_G_811, ///< Rec. G.811 + GPIO_SSM_RSVD_3, ///< (reserved) + GPIO_SSM_SSU_A, ///< SSU-A + GPIO_SSM_RSVD_5, ///< (reserved) + GPIO_SSM_RSVD_6, ///< (reserved) + GPIO_SSM_RSVD_7, ///< (reserved) + GPIO_SSM_SSU_B, ///< SSU-B + GPIO_SSM_RSVD_9, ///< (reserved) + GPIO_SSM_RSVD_10, ///< (reserved) + GPIO_SSM_RSVD_SETS, ///< Synchronous Equipment Timing Source (SETS) + GPIO_SSM_RSVD_12, ///< (reserved) + GPIO_SSM_RSVD_13, ///< (reserved) + GPIO_SSM_RSVD_14, ///< (reserved) + GPIO_SSM_DONT_USE, ///< don't use + N_GPIO_SSM_VALS +}; + + + +/** + * @brief Minimum and maximum SA BITS groups + * + * Used with ::MBG_GPIO_BITS_IN_SETTINGS::quality::e1::sa_bits + * and ::MBG_GPIO_BITS_OUT_SETTINGS::sa_bits. + */ +enum GPIO_SA_BITS_GROUPS +{ + MIN_SA_BITS_GROUP = 4, + MAX_SA_BITS_GROUP = 8 +}; + + + +/** + * @brief Configuration of a GPIO as BITS input module + * + * Used as sub-structure of ::MBG_GPIO_SETTINGS. + * + * @see ::MBG_GPIO_TYPE_BITS_IN + * @see ::MBG_GPIO_SETTINGS + */ +typedef struct +{ + uint32_t format; ///< signal format, see ::MBG_GPIO_BITS_FORMATS + uint32_t reserved; ///< reserved, currently always 0 + uint32_t csc_limit; ///< max. cycle slip [1/1000 cycle units] + + union quality + { + struct e1 + { + uint8_t ssm; ///< minimum E1 SSM for acceptance, 0..::N_GPIO_SSM_VALS-1 + uint8_t sa_bits; ///< sa bits group carrying SSM, ::MIN_SA_BITS_GROUP..::MAX_SA_BITS_GROUP + uint16_t reserved; ///< reserved, currently always 0 + } e1; ///< used with E1 formats + + struct t1 + { + uint8_t min_boc; + uint8_t reserved_0; ///< reserved, currently always 0 + uint16_t reserved_1; ///< reserved, currently always 0 + } t1; ///< used with T1 formats + + uint32_t u32; ///< dummy to force at least 32 bit alignment + + } quality; + + uint32_t err_msk; ///< controls which types of error can be ignored, see ::MBG_GPIO_BITS_ERR_MASKS + uint32_t flags; ///< reserved, currently always 0 + +} MBG_GPIO_BITS_IN_SETTINGS; + +#define _mbg_swab_mbg_gpio_bits_in_settings( _p, _recv ) \ +do \ +{ \ + uint32_t f = (_p)->format; \ + if ( (_recv) ) \ + _mbg_swab32( &f); \ + _mbg_swab32( &(_p)->format ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->csc_limit ); \ + switch( f ) \ + { \ + case MBG_GPIO_BITS_E1_FRAMED : \ + case MBG_GPIO_BITS_E1_TIMING : \ + _mbg_swab8( &(_p)->quality.e1.ssm ); \ + _mbg_swab8( &(_p)->quality.e1.sa_bits ); \ + _mbg_swab16( &(_p)->quality.e1.reserved ); \ + break; \ + \ + case MBG_GPIO_BITS_T1_FRAMED : \ + case MBG_GPIO_BITS_T1_TIMING : \ + _mbg_swab8( &(_p)->quality.t1.min_boc ); \ + _mbg_swab8( &(_p)->quality.t1.reserved_0 ); \ + _mbg_swab16( &(_p)->quality.t1.reserved_1 ); \ + break; \ + \ + default: \ + break; \ + } \ + _mbg_swab32( &(_p)->err_msk ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of BITS input error conditions + */ +enum MBG_GPIO_BITS_ERRS +{ + MBG_GPIO_BITS_ERR_LOS, ///< loss of signal + MBG_GPIO_BITS_ERR_LOF, ///< loss of frame + N_MBG_GPIO_BITS_ERRS ///< number of known errors +}; + + +/** + * @brief Bit masks associated with BITS input error conditions + * + * Used with ::MBG_GPIO_BITS_IN_SETTINGS::err_msk + * + * @see ::MBG_GPIO_BITS_ERRS + */ +enum MBG_GPIO_BITS_ERR_MASKS +{ + MSK_MBG_GPIO_BITS_ERR_LOS = ( 1UL << MBG_GPIO_BITS_ERR_LOS ), ///< see ::MBG_GPIO_BITS_ERR_LOS + MSK_MBG_GPIO_BITS_ERR_LOF = ( 1UL << MBG_GPIO_BITS_ERR_LOF ) ///< see ::MBG_GPIO_BITS_ERR_LOF +}; + + + +/** + * @brief Supported options of a BITS GPIO input + * + * Used as sub-structure of ::MBG_GPIO_LIMITS. + * + * @see ::MBG_GPIO_TYPE_BITS_IN + * @see ::MBG_GPIO_LIMITS + */ +typedef struct +{ + uint32_t supp_fmts; ///< bit mask of supported formats, see ::MBG_GPIO_BITS_FORMAT_MASKS + uint32_t reserved; ///< reserved, currently always 0 + +} MBG_GPIO_BITS_IN_SUPP; + +#define _mbg_swab_mbg_gpio_bits_in_supp( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->supp_fmts ); \ + _mbg_swab32( &(_p)->reserved ); \ +} while ( 0 ) + + + +/** + * @brief Configuration of a GPIO as BITS output module + * + * Used as sub-structure of ::MBG_GPIO_SETTINGS. + * + * @see ::MBG_GPIO_TYPE_BITS_OUT + * @see ::MBG_GPIO_SETTINGS + */ +typedef struct +{ + uint32_t format; ///< signal format, see ::MBG_GPIO_BITS_FORMATS + uint32_t flags; ///< flags for encoder control etc., see ::MBG_GPIO_BITS_OUT_FLAG_MASKS + uint8_t sa_bits; ///< number of SA bit group for E1 SSM, ::MIN_SA_BITS_GROUP..::MAX_SA_BITS_GROUP + uint8_t ssm; ///< ssm for E1 mode, 0..::N_GPIO_SSM_VALS-1 + uint8_t boc; ///< boc for T1 mode, 0..0x1F //##++++++++++++++ + uint8_t reserved_0; ///< reserved, currently always 0 + uint32_t reserved_1; ///< reserved, currently always 0 + uint32_t reserved_2; ///< reserved, currently always 0 + uint32_t reserved_3; ///< reserved, currently always 0 + +} MBG_GPIO_BITS_OUT_SETTINGS; + +#define _mbg_swab_mbg_gpio_bits_out_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->format ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab8( &(_p)->sa_bits ); \ + _mbg_swab8( &(_p)->ssm ); \ + _mbg_swab8( &(_p)->boc ); \ + _mbg_swab8( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of flags used with BITS type GPIO outputs + * + * @see ::MBG_GPIO_BITS_OUT_FLAG_MASKS + * @see ::MBG_GPIO_BITS_OUT_FLAG_STRS + */ +enum MBG_GPIO_BITS_OUT_FLAGS +{ + MBG_GPIO_BITS_OUT_FLAG_HDB3, ///< enable HDB3 encoding (E1 mode only) + MBG_GPIO_BITS_OUT_FLAG_B8ZS, ///< enable B8ZS encoding (T1 mode only) + N_MBG_GPIO_BITS_OUT_FLAGS ///< number of known flags +}; + + +/** + * @brief Bit masks associated with ::MBG_GPIO_BITS_OUT_FLAGS + * + * Used with ::MBG_GPIO_BITS_OUT_SETTINGS::flags + * + * @see ::MBG_GPIO_BITS_OUT_FLAGS + * @see ::MBG_GPIO_BITS_OUT_FLAG_STRS + */ +enum MBG_GPIO_BITS_OUT_FLAG_MASKS +{ + MSK_MBG_GPIO_BITS_OUT_FLAG_HDB3 = ( 1UL << MBG_GPIO_BITS_OUT_FLAG_HDB3 ), ///< see ::MBG_GPIO_BITS_OUT_FLAG_HDB3 + MSK_MBG_GPIO_BITS_OUT_FLAG_B8ZS = ( 1UL << MBG_GPIO_BITS_OUT_FLAG_B8ZS ) ///< see ::MBG_GPIO_BITS_OUT_FLAG_B8ZS +}; + + +/** + * @brief String initializers for an array of GPIO BITS out flags + * + * @see ::MBG_GPIO_BITS_OUT_FLAGS + * @see ::MBG_GPIO_BITS_OUT_FLAG_MASKS + */ +#define MBG_GPIO_BITS_OUT_FLAG_STRS \ +{ \ + "HDB3", \ + "B8ZS" \ +} + + +/** + * @brief Supported options of a BITS type GPIO output + * + * Used as sub-structure of ::MBG_GPIO_LIMITS. + * + * @see ::MBG_GPIO_TYPE_BITS_OUT + * @see ::MBG_GPIO_LIMITS + */ +typedef struct +{ + uint32_t supp_fmts; ///< bit mask of supported formats, see ::MBG_GPIO_BITS_FORMAT_MASKS + uint32_t supp_flags; ///< bit mask of supported flags, see ::MBG_GPIO_BITS_OUT_FLAG_MASKS + +} MBG_GPIO_BITS_OUT_SUPP; + +#define _mbg_swab_mbg_gpio_bits_out_supp( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->supp_fmts ); \ + _mbg_swab32( &(_p)->supp_flags ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of Video signal formats + * + * Used with ::MBG_GPIO_VIDEO_OUT_SETTINGS::format + * + * @see ::MBG_GPIO_VIDEO_FORMAT_MASKS + */ +enum MBG_GPIO_VIDEO_FORMATS +{ + MBG_GPIO_VIDEO_FORMAT_OFF, ///< OFF + MBG_GPIO_VIDEO_SD_FORMAT_NTSC, ///< NTSC 525i + MBG_GPIO_VIDEO_SD_FORMAT_PAL, ///< PAL standard (Germany) 625i + MBG_GPIO_VIDEO_HD_FORMAT_720_P_50Hz, ///< SMPTE296M-3 720p at 50 Hz + MBG_GPIO_VIDEO_HD_FORMAT_1080_I_50Hz, ///< SMPTE274M-6 1080i at 50 Hz + MBG_GPIO_VIDEO_HD_FORMAT_720_P_59_94Hz, ///< SMPTE296M-1 720p at 59.94 Hz + MBG_GPIO_VIDEO_HD_FORMAT_1080_I_59_94Hz, ///< SMPTE274M-7 1080i at 59.94 Hz + MBG_GPIO_VIDEO_SD_FORMAT_PAL_M, ///< PAL M (Brazil) 525i + N_MBG_GPIO_VIDEO_FORMATS ///< number of defined video formats +}; + + + +/** + * @brief Bit masks associated with ::MBG_GPIO_VIDEO_FORMATS + * + * Used with ::MBG_GPIO_VIDEO_OUT_SUPP::supp_formats + * + * @see ::MBG_GPIO_VIDEO_FORMATS + */ +enum MBG_GPIO_VIDEO_FORMAT_MASKS +{ + MSK_MBG_GPIO_VIDEO_FORMAT_OFF = ( 1UL << MBG_GPIO_VIDEO_FORMAT_OFF ), ///< see ::MBG_GPIO_VIDEO_FORMAT_OFF + MSK_MBG_GPIO_VIDEO_SD_FORMAT_NTSC = ( 1UL << MBG_GPIO_VIDEO_SD_FORMAT_NTSC ), ///< see ::MBG_GPIO_VIDEO_SD_FORMAT_NTSC + MSK_MBG_GPIO_VIDEO_SD_FORMAT_PAL = ( 1UL << MBG_GPIO_VIDEO_SD_FORMAT_PAL ), ///< see ::MBG_GPIO_VIDEO_SD_FORMAT_PAL + MSK_MBG_GPIO_VIDEO_HD_FORMAT_720_P_50Hz = ( 1UL << MBG_GPIO_VIDEO_HD_FORMAT_720_P_50Hz ), ///< see ::MBG_GPIO_VIDEO_HD_FORMAT_720_P_50Hz + MSK_MBG_GPIO_VIDEO_HD_FORMAT_1080_I_50Hz = ( 1UL << MBG_GPIO_VIDEO_HD_FORMAT_1080_I_50Hz ), ///< see ::MBG_GPIO_VIDEO_HD_FORMAT_1080_I_50Hz + MSK_MBG_GPIO_VIDEO_HD_FORMAT_720_P_59_94Hz = ( 1UL << MBG_GPIO_VIDEO_HD_FORMAT_720_P_59_94Hz ), ///< see ::MBG_GPIO_VIDEO_HD_FORMAT_720_P_59_94Hz + MSK_MBG_GPIO_VIDEO_HD_FORMAT_1080_I_59_94Hz = ( 1UL << MBG_GPIO_VIDEO_HD_FORMAT_1080_I_59_94Hz ), ///< see ::MBG_GPIO_VIDEO_HD_FORMAT_1080_I_59_94Hz + MSK_MBG_GPIO_VIDEO_SD_FORMAT_PAL_M = ( 1UL << MBG_GPIO_VIDEO_SD_FORMAT_PAL_M ) ///< see ::MBG_GPIO_VIDEO_SD_FORMAT_PAL_M +}; + + +/** + * @brief A combination of bit masks for SD video formats + * @see ::MBG_GPIO_VIDEO_FORMAT_MASKS + */ +#define MBG_GPIO_VIDEO_SD_FORMATS ( MSK_MBG_GPIO_VIDEO_FORMAT_OFF | MSK_MBG_GPIO_VIDEO_SD_FORMAT_NTSC | MSK_MBG_GPIO_VIDEO_SD_FORMAT_PAL | \ + MSK_MBG_GPIO_VIDEO_SD_FORMAT_PAL_M ) + +/** + * @brief A combination of bit masks for HD video formats + * @see ::MBG_GPIO_VIDEO_FORMAT_MASKS + */ +#define MBG_GPIO_VIDEO_HD_FORMATS ( MSK_MBG_GPIO_VIDEO_FORMAT_OFF | MSK_MBG_GPIO_VIDEO_HD_FORMAT_720_P_50Hz | MSK_MBG_GPIO_VIDEO_HD_FORMAT_1080_I_50Hz | \ + MSK_MBG_GPIO_VIDEO_HD_FORMAT_720_P_59_94Hz | MSK_MBG_GPIO_VIDEO_HD_FORMAT_1080_I_59_94Hz ) + + + +/** + * @brief Initializers for an array of video output name strings + * + * @see ::MBG_GPIO_VIDEO_FORMATS + * @see ::MBG_GPIO_VIDEO_FORMAT_MASKS + */ +#define MBG_GPIO_VIDEO_OUT_STRS \ +{ \ + "OFF", \ + "NTSC (525i)", \ + "PAL (625i)", \ + "720p 50 Hz", \ + "1080i 50 Hz", \ + "720p 59.94 Hz", \ + "1080i 59.94 Hz", \ + "PAL M (525i)" \ +} + + + +/** + * @brief Enumeration of flags used with video type GPIO outputs + */ +enum MBG_GPIO_VIDEO_OUT_FLAGS +{ + MBG_GPIO_VIDEO_OUT_HAS_NO_FREE_CONF, ///< if set, Out1: HD, Out2: SD + MBG_GPIO_VIDEO_OUT_HAS_TC_SD, ///< supports Time Code for SD Black Bursts + N_MBG_GPIO_VIDEO_OUT_FLAGS ///< number of known flags +}; + + + +/** + * @brief Bit masks associated with ::MBG_GPIO_VIDEO_OUT_FLAGS + * + * Used with ::MBG_GPIO_VIDEO_OUT_SETTINGS::flags + * + * @see ::MBG_GPIO_VIDEO_OUT_FLAGS + */ +enum MBG_GPIO_VIDEO_OUT_FLAG_MASKS +{ + MSK_MBG_GPIO_VIDEO_OUT_HAS_NO_FREE_CONF = ( 1UL << MBG_GPIO_VIDEO_OUT_HAS_NO_FREE_CONF ), ///< see ::MBG_GPIO_VIDEO_OUT_HAS_NO_FREE_CONF + MSK_MBG_GPIO_VIDEO_OUT_HAS_TC_SD = ( 1UL << MBG_GPIO_VIDEO_OUT_HAS_TC_SD ) ///< see ::MBG_GPIO_VIDEO_OUT_HAS_TC_SD +}; + + + +/** + * @brief Enumeration of epochs used with video type GPIO outputs + * + * Used with ::MBG_GPIO_VIDEO_OUT_SETTINGS::epoch, and used to + * define ::MBG_GPIO_VIDEO_EPOCH_MASKS + * + * @see ::MBG_GPIO_VIDEO_EPOCH_MASKS + * @see ::MBG_GPIO_VIDEO_EPOCH_STRS + */ +enum MBG_GPIO_VIDEO_EPOCHS +{ + SMPTE_TAI_EPOCH_1970, ///< 1970-01-01 00:00:00 + SMPTE_TAI_EPOCH_1958, ///< 1958-01-01 00:00:00 + SMPTE_UTC_EPOCH_1972, ///< 1972-01-01 00:00:00 + SMPTE_GPS_EPOCH_1980, ///< 1980-01-06 00:00:00 + N_MBG_GPIO_VIDEO_EPOCHS ///< number of known epochs +}; + + + +/** + * @brief Bit masks associated with ::MBG_GPIO_VIDEO_EPOCHS + * + * Used with :: MBG_GPIO_VIDEO_OUT_SUPP::supp_epochs + * + * @see ::MBG_GPIO_VIDEO_EPOCHS + */ +enum MBG_GPIO_VIDEO_EPOCH_MASKS +{ + MSK_SMPTE_TAI_EPOCH_1970 = ( 1UL << SMPTE_TAI_EPOCH_1970 ), ///< see ::SMPTE_TAI_EPOCH_1970 + MSK_SMPTE_TAI_EPOCH_1958 = ( 1UL << SMPTE_TAI_EPOCH_1958 ), ///< see ::SMPTE_TAI_EPOCH_1958 + MSK_SMPTE_UTC_EPOCH_1972 = ( 1UL << SMPTE_UTC_EPOCH_1972 ), ///< see ::SMPTE_UTC_EPOCH_1972 + MSK_SMPTE_GPS_EPOCH_1980 = ( 1UL << SMPTE_GPS_EPOCH_1980 ) ///< see ::SMPTE_GPS_EPOCH_1980 +}; + + + +/** + * @brief Initializers for an array of video epoch strings + * + * @see ::MBG_GPIO_VIDEO_EPOCHS + */ +#define MBG_GPIO_VIDEO_EPOCH_STRS \ +{ \ + "TAI D1970-01-01 T00:00:00", \ + "TAI D1958-01-01 T00:00:00", \ + "UTC D1972-01-01 T00:00:00", \ + "GPS D1980-01-06 T00:00:00" \ +} + + + +/** + * @brief Enumeration of time code modes used with video type GPIO outputs + * + * Used with ::MBG_GPIO_VIDEO_OUT_SETTINGS::tc_mode + * + */ +enum MBG_GPIO_VIDEO_TC_MODES +{ + MBG_GPIO_VIDEO_TC_MODE_NONE, ///< None + MBG_GPIO_VIDEO_TC_MODE_VITC, ///< Vertical Interval Time Code + N_MBG_GPIO_VIDEO_TC_MODES +}; + + +/** + * @brief Bit masks associated with ::MBG_GPIO_VIDEO_TC_MODES + * + * Used with ::MBG_GPIO_VIDEO_OUT_SETTINGS::tc_mode + * + */ +enum MBG_GPIO_VIDEO_TC_MODE_MASKS +{ + MSK_MBG_GPIO_VIDEO_TC_MODE_NONE = ( 1UL << MBG_GPIO_VIDEO_TC_MODE_NONE ), ///< see ::MBG_GPIO_VIDEO_TC_MODE_NONE + MSK_MBG_GPIO_VIDEO_TC_MODE_VITC = ( 1UL << MBG_GPIO_VIDEO_TC_MODE_VITC ) ///< see ::MBG_GPIO_VIDEO_TC_MODE_VITC +}; + + +/** + * @brief Initializers for an array of video time code modes + * + * @see ::MBG_GPIO_VIDEO_TC_MODES + */ +#define MBG_GPIO_VIDEO_TC_MODE_STRS \ +{ \ + "None", \ + "VITC" \ +} + + + +/** + * @brief Configuration of a GPIO as video output module + * + * Used as sub-structure of ::MBG_GPIO_SETTINGS. + * + * @see ::MBG_GPIO_TYPE_VIDEO_OUT + * @see ::MBG_GPIO_SETTINGS + */ +typedef struct +{ + uint32_t format; ///< video format, see ::MBG_GPIO_VIDEO_FORMATS + uint32_t flags; ///< flags, see ::MBG_GPIO_VIDEO_OUT_FLAG_MASKS + int32_t phase_offset; ///< Phase offset in [ns] + uint8_t epoch; ///< epoch, see ::MBG_GPIO_VIDEO_EPOCHS + + uint8_t tc_mode; ///< time code mode, see ::MBG_GPIO_VIDEO_TC_MODES + uint8_t tc_line0; ///< first time code line location, valid lines: 6-22 + uint8_t tc_line1; ///< second time code line location, valid lines: 6-22 + + uint32_t reserved0; ///< reserved, currently always 0 + uint32_t reserved1; ///< reserved, currently always 0 + +} MBG_GPIO_VIDEO_OUT_SETTINGS; + +#define _mbg_swab_mbg_gpio_video_out_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->format ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab32( &(_p)->phase_offset ); \ + _mbg_swab8( &(_p)->epoch ); \ + _mbg_swab8( &(_p)->tc_mode ); \ + _mbg_swab8( &(_p)->tc_line0 ); \ + _mbg_swab8( &(_p)->tc_line1 ); \ + _mbg_swab32( &(_p)->reserved0 ); \ + _mbg_swab32( &(_p)->reserved1 ); \ +} while ( 0 ) + + + +/** + * @brief Supported options of a video type GPIO output + * + * Used as sub-structure of ::MBG_GPIO_LIMITS. + * + * @see ::MBG_GPIO_TYPE_VIDEO_OUT + * @see ::MBG_GPIO_LIMITS + */ +typedef struct +{ + uint32_t supp_formats; ///< supported video formats, see ::MBG_GPIO_VIDEO_FORMAT_MASKS + uint32_t supp_flags; ///< supported flags, see ::MBG_GPIO_VIDEO_OUT_FLAG_MASKS + uint32_t supp_epochs; ///< supported epochs, see ::MBG_GPIO_VIDEO_EPOCH_MASKS + + uint8_t supp_tc_modes; ///< supported tc_modes, see ::MBG_GPIO_VIDEO_TC_MODE_MASKS + + uint8_t reserved0; ///< reserved, currently always 0 + uint8_t reserved2; ///< reserved, currently always 0 + uint16_t reserved3; ///< reserved, currently always 0 + uint32_t reserved1; ///< reserved, currently always 0 + +} MBG_GPIO_VIDEO_OUT_SUPP; + +#define _mbg_swab_mbg_gpio_video_out_supp( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->supp_formats ); \ + _mbg_swab32( &(_p)->supp_flags ); \ + _mbg_swab32( &(_p)->supp_epochs ); \ + _mbg_swab8( &(_p)->supp_tc_modes ); \ + _mbg_swab8( &(_p)->reserved0 ); \ + _mbg_swab16( &(_p)->reserved2 ); \ + _mbg_swab16( &(_p)->reserved3 ); \ + _mbg_swab32( &(_p)->reserved1 ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of types used with video sync GPIO outputs + * Depends on configured video output + */ +enum MBG_GPIO_VIDEO_SYNC_TYPES +{ + MBG_GPIO_VIDEO_SYNC_TYPE_OFF, ///< Output Off + MBG_GPIO_VIDEO_SYNC_TYPE_SD_HSYNC, ///< SD horizontal sync + MBG_GPIO_VIDEO_SYNC_TYPE_SD_VSYNC, ///< SD vertical sync + MBG_GPIO_VIDEO_SYNC_TYPE_SD_FRAME, ///< SD frame/field sync + MBG_GPIO_VIDEO_SYNC_TYPE_SD_BLANK, ///< SD blanking interval + MBG_GPIO_VIDEO_SYNC_TYPE_HD_HSYNC, ///< HD horizontal sync + MBG_GPIO_VIDEO_SYNC_TYPE_HD_VSYNC, ///< HD vertical sync + MBG_GPIO_VIDEO_SYNC_TYPE_HD_FRAME, ///< HD frame/field sync + MBG_GPIO_VIDEO_SYNC_TYPE_HD_BLANK, ///< HD blanking interval + N_MBG_GPIO_VIDEO_SYNC_TYPES ///< number of known types +}; + + + +/** + * @brief Bit masks associated with ::MBG_GPIO_VIDEO_SYNC_TYPES + * + * Used with ::MBG_GPIO_VIDEO_SYNC_OUT_SUPP::supp_types + * + * @see ::MBG_GPIO_VIDEO_SYNC_TYPES + */ +enum MBG_GPIO_VIDEO_SYNC_TYPE_MASKS +{ + MSK_MBG_GPIO_VIDEO_SYNC_TYPE_OFF = ( 1UL << MBG_GPIO_VIDEO_SYNC_TYPE_OFF ), + MSK_MBG_GPIO_VIDEO_SYNC_TYPE_SD_HSYNC = ( 1UL << MBG_GPIO_VIDEO_SYNC_TYPE_SD_HSYNC ), + MSK_MBG_GPIO_VIDEO_SYNC_TYPE_SD_VSYNC = ( 1UL << MBG_GPIO_VIDEO_SYNC_TYPE_SD_VSYNC ), + MSK_MBG_GPIO_VIDEO_SYNC_TYPE_SD_FRAME = ( 1UL << MBG_GPIO_VIDEO_SYNC_TYPE_SD_FRAME ), + MSK_MBG_GPIO_VIDEO_SYNC_TYPE_SD_BLANK = ( 1UL << MBG_GPIO_VIDEO_SYNC_TYPE_SD_BLANK ), + MSK_MBG_GPIO_VIDEO_SYNC_TYPE_HD_HSYNC = ( 1UL << MBG_GPIO_VIDEO_SYNC_TYPE_HD_HSYNC ), + MSK_MBG_GPIO_VIDEO_SYNC_TYPE_HD_VSYNC = ( 1UL << MBG_GPIO_VIDEO_SYNC_TYPE_HD_VSYNC ), + MSK_MBG_GPIO_VIDEO_SYNC_TYPE_HD_FRAME = ( 1UL << MBG_GPIO_VIDEO_SYNC_TYPE_HD_FRAME ), + MSK_MBG_GPIO_VIDEO_SYNC_TYPE_HD_BLANK = ( 1UL << MBG_GPIO_VIDEO_SYNC_TYPE_HD_BLANK ) +}; + + + +/** + * @brief Initializers for an array of video sync output name strings + * + * @see ::MBG_GPIO_VIDEO_SYNC_TYPES + * @see ::MBG_GPIO_VIDEO_SYNC_TYPE_MASKS + */ +#define MBG_GPIO_VIDEO_SYNC_OUT_STRS \ +{ \ + "OFF", \ + "SD H-Sync", \ + "SD V-Sync", \ + "SD Frame", \ + "SD Blank", \ + "HD H-Sync", \ + "HD V-Sync", \ + "HD Frame", \ + "HD Blank" \ +} + + + +/** + * @brief A combination of bit masks for SD video sync types + * @see ::MBG_GPIO_VIDEO_SYNC_TYPE_MASKS + */ +#define MBG_GPIO_VIDEO_SYNC_SD_TYPES ( MSK_MBG_GPIO_VIDEO_SYNC_TYPE_OFF | MSK_MBG_GPIO_VIDEO_SYNC_TYPE_SD_HSYNC | MSK_MBG_GPIO_VIDEO_SYNC_TYPE_SD_VSYNC | \ + MSK_MBG_GPIO_VIDEO_SYNC_TYPE_SD_FRAME | MSK_MBG_GPIO_VIDEO_SYNC_TYPE_SD_BLANK ) + +/** + * @brief A combination of bit masks for HD video sync types + * @see ::MBG_GPIO_VIDEO_SYNC_TYPE_MASKS + */ +#define MBG_GPIO_VIDEO_SYNC_HD_TYPES ( MSK_MBG_GPIO_VIDEO_SYNC_TYPE_OFF | MSK_MBG_GPIO_VIDEO_SYNC_TYPE_HD_HSYNC | MSK_MBG_GPIO_VIDEO_SYNC_TYPE_HD_VSYNC | \ + MSK_MBG_GPIO_VIDEO_SYNC_TYPE_HD_FRAME | MSK_MBG_GPIO_VIDEO_SYNC_TYPE_HD_BLANK ) + + + +/** + * @brief Configuration of a GPIO as sync output module + * + * Used as sub-structure of ::MBG_GPIO_SETTINGS. + * + * @see ::MBG_GPIO_TYPE_VIDEO_SYNC_OUT + * @see ::MBG_GPIO_SETTINGS + */ +typedef struct +{ + uint32_t type; ///< sync type, see :: MBG_GPIO_SYNC_TYPES + uint32_t flags; ///< flags, currently always 0 + uint32_t reserved0; ///< reserved, currently always 0 + uint32_t reserved1; ///< reserved, currently always 0 + uint32_t reserved2; ///< reserved, currently always 0 + uint32_t reserved3; ///< reserved, currently always 0 + +} MBG_GPIO_VIDEO_SYNC_OUT_SETTINGS; + +#define _mbg_swab_mbg_gpio_video_sync_out_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->type ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab32( &(_p)->reserved0 ); \ + _mbg_swab32( &(_p)->reserved1 ); \ + _mbg_swab32( &(_p)->reserved2 ); \ + _mbg_swab32( &(_p)->reserved3 ); \ +} while ( 0 ) + + + +/** + * @brief Supported options of a sync type GPIO output + * + * Used as sub-structure of ::MBG_GPIO_LIMITS. + * + * @see ::MBG_GPIO_TYPE_VIDEO_SYNC_OUT + * @see ::MBG_GPIO_LIMITS + */ +typedef struct +{ + uint32_t supp_types; ///< supported types, see ::MBG_GPIO_VIDEO_SYNC_TYPE_MASKS + uint32_t supp_flags; ///< supported flags, currently always 0 + uint32_t reserved0; ///< reserved, currently always 0 + uint32_t reserved1; ///< reserved, currently always 0 + +} MBG_GPIO_VIDEO_SYNC_OUT_SUPP; + +#define _mbg_swab_mbg_gpio_video_sync_out_supp( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->supp_types ); \ + _mbg_swab32( &(_p)->supp_flags ); \ + _mbg_swab32( &(_p)->reserved0 ); \ + _mbg_swab32( &(_p)->reserved1 ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of studio clock base frequencies + * + * Used with ::MBG_GPIO_STUDIO_CLOCK_OUT_SETTINGS::base_freq + * + * @see ::MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_MASKS + */ +enum MBG_GPIO_STUDIO_CLOCK_BASE_FREQS +{ + MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_32KHZ, ///< 32 kHz base frequency + MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_44_1KHZ, ///< 44.1 kHz base frequency + MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_48KHZ, ///< 48 kHz base frequency + N_MBG_GPIO_STUDIO_CLOCK_BASE_FREQS ///< number of defined base frequencies +}; + + + +/** + * @brief Bit masks associated with ::MBG_GPIO_STUDIO_CLOCK_BASE_FREQS + * + * Used with ::MBG_GPIO_STUDIO_CLOCK_OUT_SUPP::supp_base_freqs + * + * @see ::MBG_GPIO_STUDIO_CLOCK_BASE_FREQS + */ +enum MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_MASKS +{ + MSK_MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_32KHZ = ( 1UL << MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_32KHZ ), ///< see ::MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_32KHZ + MSK_MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_44_1KHZ = ( 1UL << MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_44_1KHZ ), ///< see ::MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_44_1KHZ + MSK_MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_48KHZ = ( 1UL << MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_48KHZ ) ///< see ::MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_48KHZ +}; + + + +/** + * @brief Initializers for an array of base frequencies of studio clock output name strings + * + * @see ::MBG_GPIO_STUDIO_CLOCK_BASE_FREQS + * @see ::MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_MASKS + */ +#define MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_STRS \ +{ \ + "32 kHz", \ + "44.1 kHz", \ + "48 kHz" \ +} + + + +/** + * @brief Enumeration of studio clock scales + * + * Used with ::MBG_GPIO_STUDIO_CLOCK_OUT_SETTINGS::scale + * Multiply scale with base frequency + * + * @see ::MBG_GPIO_STUDIO_CLOCK_SCALE_MASKS + */ +enum MBG_GPIO_STUDIO_CLOCK_SCALES +{ + MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_32, + MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_16, + MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_8, + MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_4, + MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_2, + MBG_GPIO_STUDIO_CLOCK_SCALE_1, + MBG_GPIO_STUDIO_CLOCK_SCALE_2, + MBG_GPIO_STUDIO_CLOCK_SCALE_4, + MBG_GPIO_STUDIO_CLOCK_SCALE_8, + MBG_GPIO_STUDIO_CLOCK_SCALE_16, + MBG_GPIO_STUDIO_CLOCK_SCALE_32, + MBG_GPIO_STUDIO_CLOCK_SCALE_64, + MBG_GPIO_STUDIO_CLOCK_SCALE_128, + MBG_GPIO_STUDIO_CLOCK_SCALE_256, + MBG_GPIO_STUDIO_CLOCK_SCALE_512, + N_MBG_GPIO_STUDIO_CLOCK_SCALES ///< number of defined scales +}; + + + +/** + * @brief Bit masks associated with ::MBG_GPIO_STUDIO_CLOCK_SCALES + * + * Used with ::MBG_GPIO_STUDIO_CLOCK_OUT_SUPP::supp_scales[N_MBG_GPIO_STUDIO_CLOCK_BASE_FREQS] + * + * @see ::MBG_GPIO_STUDIO_CLOCK_SCALES + */ +enum MBG_GPIO_STUDIO_CLOCK_SCALE_MASKS +{ + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_32 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_32 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_32 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_16 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_16 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_16 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_8 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_8 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_8 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_4 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_4 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_4 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_2 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_2 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_1_DIV_2 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_1 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_1 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_1 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_2 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_2 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_2 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_4 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_4 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_4 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_8 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_8 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_8 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_16 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_16 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_16 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_32 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_32 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_32 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_64 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_64 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_64 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_128 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_128 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_128 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_256 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_256 ), ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_256 + MSK_MBG_GPIO_STUDIO_CLOCK_SCALE_512 = ( 1U << MBG_GPIO_STUDIO_CLOCK_SCALE_512 ) ///< see ::MBG_GPIO_STUDIO_CLOCK_SCALE_512 +}; + + + +/** + * @brief Initializers for an array of scales of studio clock output name strings + * + * @see ::MBG_GPIO_STUDIO_CLOCK_SCALES + * @see ::MBG_GPIO_STUDIO_CLOCK_SCALE_MASKS + */ +#define MBG_GPIO_STUDIO_CLOCK_SCALE_STRS \ +{ \ + "1/32", \ + "1/16", \ + "1/8", \ + "1/4", \ + "1/2", \ + "1", \ + "2", \ + "4", \ + "8", \ + "16", \ + "32", \ + "64", \ + "128", \ + "256", \ + "512" \ +} + + + +/** + * @brief Enumeration of flags used with studio clock type GPIO outputs + */ +enum MBG_GPIO_STUDIO_CLOCK_FLAGS +{ + MBG_GPIO_STUDIO_CLOCK_OUTPUT_ENABLED, ///< if set, enables output + N_MBG_GPIO_STUDIO_CLOCK_FLAGS ///< number of known flags +}; + + + +/** + * @brief Bit masks associated with ::MBG_GPIO_STUDIO_CLOCK_FLAGS + * + * Used with ::MBG_GPIO_STUDIO_CLOCK_OUT_SETTINGS::flags + * + * @see ::MBG_GPIO_STUDIO_CLOCK_FLAGS + */ +enum MBG_GPIO_STUDIO_CLOCK_FLAG_MASKS +{ + MSK_MBG_GPIO_STUDIO_CLOCK_OUTPUT_ENABLED = ( 1UL << MBG_GPIO_STUDIO_CLOCK_OUTPUT_ENABLED ) ///< see ::MBG_GPIO_STUDIO_CLOCK_OUTPUT_ENABLED +}; + + + +/** + * @brief Configuration of a GPIO as studio clock output module + * + * Used as sub-structure of ::MBG_GPIO_SETTINGS. + * + * @see ::MBG_GPIO_TYPE_STUDIO_CLOCK_OUT + * @see ::MBG_GPIO_SETTINGS + */ +typedef struct +{ + uint32_t base_freq; ///< base frequency, see ::MBG_GPIO_STUDIO_CLOCK_BASE_FREQS + uint32_t scale; ///< scale, see ::MBG_GPIO_STUDIO_CLOCK_SCALES + uint32_t flags; ///< flags, see ::MBG_GPIO_STUDIO_CLOCK_FLAGS + uint32_t reserved0; ///< reserved, currently always 0 + uint32_t reserved1; ///< reserved, currently always 0 + +} MBG_GPIO_STUDIO_CLOCK_OUT_SETTINGS; + +#define _mbg_swab_mbg_gpio_studio_clock_out_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->base_freq ); \ + _mbg_swab32( &(_p)->scale ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab32( &(_p)->reserved0 ); \ + _mbg_swab32( &(_p)->reserved1 ); \ +} while ( 0 ) + + + +#define MAX_SUPP_BASE_FREQUENCIES 8 ///< max. supported base frequencies for studio clock outputs + +/** + * @brief Configuration of a GPIO as studio clock output module + * + * Used as sub-structure of ::MBG_GPIO_LIMITS. + * + * @see ::MBG_GPIO_TYPE_STUDIO_CLOCK_OUT + * @see ::MBG_GPIO_LIMITS + */ +typedef struct +{ + uint8_t supp_base_freqs; ///< supported base frequencies, see ::MBG_GPIO_STUDIO_CLOCK_BASE_FREQ_MASKS + uint8_t reserved0; ///< reserved, currently always 0 + uint16_t reserved1; ///< reserved, currently always 0 + uint16_t supp_scales[MAX_SUPP_BASE_FREQUENCIES]; ///< supported scales for each base frequency, see ::MBG_GPIO_STUDIO_CLOCK_SCALE_MASKS + uint32_t supp_flags; ///< supported flags, see::MBG_GPIO_STUDIO_CLOCK_FLAG_MASKS + uint32_t reserved2; ///< reserved, currently always 0 + +} MBG_GPIO_STUDIO_CLOCK_OUT_SUPP; + +#define _mbg_swab_mbg_gpio_studio_clock_out_supp( _p ) \ +do \ +{ \ + uint8_t idx; \ + _mbg_swab8( &(_p)->supp_base_freqs ); \ + _mbg_swab8( &(_p)->reserved0 ); \ + _mbg_swab16( &(_p)->reserved1 ); \ + for( idx = 0; idx < MAX_SUPP_BASE_FREQUENCIES; idx++ ) \ + _mbg_swab16( &(_p)->supp_scales[idx] ); \ + _mbg_swab32( &(_p)->supp_flags ); \ + _mbg_swab32( &(_p)->reserved2 ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of types used with GPIO type digital audio outputs + * + * Used with ::MBG_GPIO_DIGITAL_AUDIO_OUT_SETTINGS::type, and to + * define ::MBG_GPIO_DIGITAL_AUDIO_TYPE_MASKS + * + * @see ::MBG_GPIO_DIGITAL_AUDIO_TYPE_MASKS + * @see ::MBG_GPIO_DIGITAL_AUDIO_TYPE_STRS + */ +enum MBG_GPIO_DIGITAL_AUDIO_TYPES +{ + MBG_GPIO_DIGITAL_AUDIO_TYPE_OFF, + MBG_GPIO_DIGITAL_AUDIO_TYPE_DARS, ///< DARS + N_MBG_GPIO_DIGITAL_AUDIO_TYPES ///< number of known types +}; + + + +/** + * @brief Bit masks associated with ::MBG_GPIO_DIGITAL_AUDIO_TYPES + * + * Used with :: MBG_GPIO_TYPE_DIGITAL_AUDIO_OUT_SUPP::supp_types + * + * @see ::MBG_GPIO_DIGITAL_AUDIO_TYPES + */ +enum MBG_GPIO_DIGITAL_AUDIO_TYPE_MASKS +{ + MSK_MBG_GPIO_DIGITAL_AUDIO_TYPE_OFF = ( 1UL << MBG_GPIO_DIGITAL_AUDIO_TYPE_OFF ), ///< see ::MBG_GPIO_DIGITAL_AUDIO_TYPE_OFF + MSK_MBG_GPIO_DIGITAL_AUDIO_TYPE_DARS = ( 1UL << MBG_GPIO_DIGITAL_AUDIO_TYPE_DARS ) ///< see ::MBG_GPIO_DIGITAL_AUDIO_TYPE_DARS +}; + + + +/** + * @brief Initializers for an array of video epoch strings + * + * @see ::MBG_GPIO_VIDEO_EPOCHS + */ +#define MBG_GPIO_DIGITAL_AUDIO_TYPE_STRS \ +{ \ + "OFF", \ + "DARS" \ +} + + + +/** + * @brief Enumeration of flags used with GPIO type digital audio outputs + */ +enum MBG_GPIO_DIGITAL_AUDIO_FLAGS +{ + MBG_GPIO_DIGITAL_AUDIO_RESERVED_FLAG, ///< reserved + N_MBG_GPIO_DIGITAL_AUDIO_FLAGS ///< number of known flags +}; + + + +/** + * @brief Bit masks associated with ::MBG_GPIO_DIGITAL_AUDIO_FLAGS + * + * Used with ::MBG_GPIO_DIGITAL_AUDIO_OUT_SETTINGS::flags + * + * @see ::MBG_GPIO_DIGITAL_AUDIO_FLAGS + */ +enum MBG_GPIO_DIGITAL_AUDIO_FLAG_MASKS +{ + MSK_MBG_GPIO_DIGITAL_AUDIO_RESERVED_FLAG = ( 1UL << MBG_GPIO_DIGITAL_AUDIO_RESERVED_FLAG ) ///< see ::MBG_GPIO_DIGITAL_AUDIO_RESERVED_FLAG +}; + + + +/** + * @brief Configuration of a GPIO digital audio output + * + * Used as sub-structure of ::MBG_GPIO_SETTINGS. + * + * @see ::MBG_GPIO_TYPE_DIGITAL_AUDIO_OUT + * @see ::MBG_GPIO_SETTINGS + */ +typedef struct +{ + uint32_t type; ///< digital audio type, see ::MBG_GPIO_DIGITAL_AUDIO_TYPES + uint32_t flags; ///< reserved, currently always 0 + uint32_t reserved0; ///< reserved, currently always 0 + uint32_t reserved1; ///< reserved, currently always 0 + uint32_t reserved2; ///< reserved, currently always 0 + +} MBG_GPIO_DIGITAL_AUDIO_OUT_SETTINGS; + +#define _mbg_swab_mbg_gpio_digital_audio_out_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->type ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab32( &(_p)->reserved0 ); \ + _mbg_swab32( &(_p)->reserved1 ); \ + _mbg_swab32( &(_p)->reserved2 ); \ +} while ( 0 ) + + + +/** + * @brief Supported options for digital audio output + * + * Used as sub-structure of ::MBG_GPIO_LIMITS. + * + * @see ::MBG_GPIO_TYPE_DIGITAL_AUDIO_OUT + * @see ::MBG_GPIO_LIMITS + */ +typedef struct +{ + uint32_t supp_types; ///< supported digital audio types, see ::MBG_GPIO_DIGITAL_AUDIO_TYPE_MASKS + uint32_t supp_flags; ///< reserved, currently always 0 + uint32_t reserved0; ///< reserved, currently always 0 + uint32_t reserved1; ///< reserved, currently always 0 + uint32_t reserved2; ///< reserved, currently always 0 + +} MBG_GPIO_DIGITAL_AUDIO_OUT_SUPP; + +#define _mbg_swab_mbg_gpio_digital_audio_out_supp( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->supp_types ); \ + _mbg_swab32( &(_p)->supp_flags ); \ + _mbg_swab32( &(_p)->reserved0 ); \ + _mbg_swab32( &(_p)->reserved1 ); \ + _mbg_swab32( &(_p)->reserved2 ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of general flags used with a GPIO + * + * @see ::MBG_GPIO_FLAG_MASKS + */ +enum MBG_GPIO_FLAGS +{ + MBG_GPIO_DEPENDS_ON_ASS_IO_IDX, ///< indicates that this output depends on GPIO with ::MBG_GPIO_SETTINGS::ass_io_idx and may not be configured independently + N_MBG_GPIO_FLAGS ///< number of known flags +}; + + + +/** + * @brief Bit masks associated with ::MBG_GPIO_FLAGS + * + * Used with ::MBG_GPIO_LIMITS::supp_flags and ::MBG_GPIO_SETTINGS::flags + * + * @see ::MBG_GPIO_FLAGS + */ +enum MBG_GPIO_FLAG_MASKS +{ + MSK_MBG_GPIO_DEPENDS_ON_ASS_IO_IDX = ( 1UL << MBG_GPIO_DEPENDS_ON_ASS_IO_IDX ) ///< see ::MBG_GPIO_DEPENDS_ON_ASS_IO_IDX +}; + + /** - * @brief A structure used to configure a GPIO port + * @brief A generic structure used to hold a GPIO port's settings */ typedef struct { - uint32_t mode; /** frequency out, frequency in, pulse out, etc. */ - uint32_t reserved; /**< currently always 0 */ - uint32_t flags; /**< currently always 0 */ + uint32_t type; ///< GPIO type, see ::MBG_GPIO_TYPES + uint16_t reserved_1; ///< reserved, currently always 0 + uint8_t reserved_2; ///< reserved, currently always 0 + uint8_t ass_io_idx; ///< associated GPIO index, only valid if ::MSK_MBG_GPIO_DEPENDS_ON_ASS_IO_IDX is set in flags field + + uint32_t flags; ///< flags, see ::MBG_GPIO_FLAG_MASKS + + /// settings depending on the GPIO type, see ::MBG_GPIO_TYPES union { - MBG_GPIO_FREQ_OUT_SETTINGS freq_out; /** if type is frequency output */ - MBG_GPIO_FREQ_IN_SETTINGS freq_in; /** if type is frequency input */ - MBG_GPIO_FIXED_FREQ_OUT_SETTINGS ff_out; /** if type is fixed frequency output */ + MBG_GPIO_FREQ_IN_SETTINGS freq_in; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_FREQ_IN + MBG_GPIO_FREQ_OUT_SETTINGS freq_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_FREQ_OUT + MBG_GPIO_FIXED_FREQ_OUT_SETTINGS ff_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_FIXED_FREQ_OUT + MBG_GPIO_BITS_IN_SETTINGS bits_in; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_BITS_IN + MBG_GPIO_BITS_OUT_SETTINGS bits_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_BITS_OUT + MBG_GPIO_VIDEO_OUT_SETTINGS video_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_VIDEO_OUT + MBG_GPIO_VIDEO_SYNC_OUT_SETTINGS video_sync_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_VIDEO_SYNC_OUT + MBG_GPIO_STUDIO_CLOCK_OUT_SETTINGS studio_clk_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_STUDIO_CLOCK_OUT + MBG_GPIO_DIGITAL_AUDIO_OUT_SETTINGS digital_audio_out; ///< if ::MBG_GPIO_SETTINGS::type is ::;MBG_GPIO_TYPE_DIGITAL_AUDIO_OUT } u; } MBG_GPIO_SETTINGS; +#define _mbg_swab_mbg_gpio_settings( _p, _recv ) \ +do \ +{ \ + uint32_t t = (_p)->type; \ + if ( (_recv) ) \ + _mbg_swab32( &t ); \ + _mbg_swab32( &(_p)->type ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab8( &(_p)->reserved_2 ); \ + _mbg_swab8( &(_p)->ass_io_idx ); \ + _mbg_swab32( &(_p)->flags ); \ + switch( t ) \ + { \ + case MBG_GPIO_TYPE_FREQ_IN : _mbg_swab_mbg_gpio_freq_in_settings( &(_p)->u.freq_in ); break; \ + case MBG_GPIO_TYPE_FREQ_OUT : _mbg_swab_mbg_gpio_freq_out_settings( &(_p)->u.freq_out ); break; \ + case MBG_GPIO_TYPE_FIXED_FREQ_OUT : _mbg_swab_mbg_gpio_fixed_freq_out_settings( &(_p)->u.ff_out ); break; \ + case MBG_GPIO_TYPE_BITS_IN : _mbg_swab_mbg_gpio_bits_in_settings( &(_p)->u.bits_in, (_recv) ); break; \ + case MBG_GPIO_TYPE_BITS_OUT : _mbg_swab_mbg_gpio_bits_out_settings( &(_p)->u.bits_out ); break; \ + case MBG_GPIO_TYPE_VIDEO_OUT : _mbg_swab_mbg_gpio_video_out_settings( &(_p)->u.video_out ); break; \ + case MBG_GPIO_TYPE_VIDEO_SYNC_OUT : _mbg_swab_mbg_gpio_video_sync_out_settings( &(_p)->u.video_sync_out ); break; \ + case MBG_GPIO_TYPE_STUDIO_CLOCK_OUT : _mbg_swab_mbg_gpio_studio_clock_out_settings( &(_p)->u.studio_clk_out ); break; \ + case MBG_GPIO_TYPE_DIGITAL_AUDIO_OUT : _mbg_swab_mbg_gpio_digital_audio_out_settings( &(_p)->u.digital_audio_out ); break; \ + default : break; \ + } \ +} while ( 0 ) + + + +/** + * @brief A GPIO port's current settings, plus port index + */ +typedef struct +{ + uint32_t idx; ///< port index, 0..::MBG_GPIO_CFG_LIMITS::num_io-1 + MBG_GPIO_SETTINGS settings; ///< current settings + +} MBG_GPIO_SETTINGS_IDX; + +#define _mbg_swab_mbg_gpio_settings_idx( _p, _recv ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_mbg_gpio_settings( &(_p)->settings, (_recv ) ); \ +} while ( 0 ) + + /** - * @brief A structure used to describe a GPIO ports limiting values + * @brief A generic structure used to specify a GPIO port's limits */ typedef struct { - uint32_t supp_modes; /**< supported modes */ - uint32_t reserved; - uint32_t supp_flags; /**< supported flags */ + uint32_t type; ///< GPIO type, see ::MBG_GPIO_TYPES + uint32_t reserved; ///< reserved, currently always 0 + uint32_t supp_flags; ///< supported flags, see ::MBG_GPIO_FLAG_MASKS + /// limits depending on the GPIO type, see ::MBG_GPIO_TYPES union { - MBG_GPIO_FREQ_OUT_SETTINGS freq_out; /** max. freq. values for output */ - MBG_GPIO_FREQ_IN_SETTINGS freq_in; /** max. freq. values for input */ - MBG_GPIO_FIXED_FREQ_OUT_SETTINGS ff_out; /** max. ff values for output */ + MBG_GPIO_FREQ_IN_SUPP freq_in; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_FREQ_IN + MBG_GPIO_FREQ_OUT_SUPP freq_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_FREQ_OUT + MBG_GPIO_FIXED_FREQ_OUT_SUPP ff_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_FIXED_FREQ_OUT + MBG_GPIO_BITS_IN_SUPP bits_in; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_BITS_IN + MBG_GPIO_BITS_OUT_SUPP bits_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_BITS_OUT + MBG_GPIO_VIDEO_OUT_SUPP video_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_VIDEO_OUT + MBG_GPIO_VIDEO_SYNC_OUT_SUPP video_sync_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_VIDEO_SYNC_OUT + MBG_GPIO_STUDIO_CLOCK_OUT_SUPP studio_clk_out; ///< if ::MBG_GPIO_SETTINGS::type is ::MBG_GPIO_TYPE_STUDIO_CLOCK_OUT + MBG_GPIO_DIGITAL_AUDIO_OUT_SUPP digital_audio_out; ///< if ::MBG_GPIO_SETTINGS::type is ::;MBG_GPIO_TYPE_DIGITAL_AUDIO_OUT } u; } MBG_GPIO_LIMITS; +#define _mbg_swab_mbg_gpio_limits( _p, _recv ) \ +do \ +{ \ + uint32_t t = (_p)->type; \ + if ( (_recv) ) \ + _mbg_swab32( &t ); \ + _mbg_swab32( &(_p)->type ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->supp_flags ); \ + switch( t ) \ + { \ + case MBG_GPIO_TYPE_FREQ_IN : _mbg_swab_mbg_gpio_freq_in_supp( &(_p)->u.freq_in ); break; \ + case MBG_GPIO_TYPE_FREQ_OUT : _mbg_swab_mbg_gpio_freq_out_supp( &(_p)->u.freq_out ); break; \ + case MBG_GPIO_TYPE_FIXED_FREQ_OUT : _mbg_swab_mbg_gpio_fixed_freq_out_supp( &(_p)->u.ff_out ); break; \ + case MBG_GPIO_TYPE_BITS_IN : _mbg_swab_mbg_gpio_bits_in_supp( &(_p)->u.bits_in ); break; \ + case MBG_GPIO_TYPE_BITS_OUT : _mbg_swab_mbg_gpio_bits_out_supp( &(_p)->u.bits_out ); break; \ + case MBG_GPIO_TYPE_VIDEO_OUT : _mbg_swab_mbg_gpio_video_out_supp( &(_p)->u.video_out ); break; \ + case MBG_GPIO_TYPE_VIDEO_SYNC_OUT : _mbg_swab_mbg_gpio_video_sync_out_supp( &(_p)->u.video_sync_out ); break; \ + case MBG_GPIO_TYPE_STUDIO_CLOCK_OUT : _mbg_swab_mbg_gpio_studio_clock_out_supp( &(_p)->u.studio_clk_out ); break; \ + case MBG_GPIO_TYPE_DIGITAL_AUDIO_OUT : _mbg_swab_mbg_gpio_digital_audio_out_supp( &(_p)->u.digital_audio_out ); break; \ + default : break; \ + } \ +} while ( 0 ) +/** + * @brief A GPIO port's current settings and limits + */ +typedef struct +{ + MBG_GPIO_SETTINGS settings; ///< current settings + MBG_GPIO_LIMITS limits; ///< limits of this GPIO port + +} MBG_GPIO_INFO; + + +#define _mbg_swab_mbg_gpio_info( _p, _recv ) \ +do \ +{ \ + _mbg_swab_mbg_gpio_settings( &(_p)->settings, (_recv) ); \ + _mbg_swab_mbg_gpio_limits( &(_p)->limits, (_recv) ); \ +} while ( 0 ) + /** - * @brief A structure used to configure a specific GPIO port + * @brief A GPIO port's current settings and limits, plus port index */ typedef struct { - uint32_t idx; /**< port number, 0..(MBG_GPIO_CFG_LIMITS::num_io - 1) */ - MBG_GPIO_SETTINGS settings; /**< configuration settings */ + uint32_t idx; ///< port index, 0..::MBG_GPIO_CFG_LIMITS::num_io-1 + MBG_GPIO_INFO info; ///< limits and current settings of this GPIO port -} MBG_GPIO_SETTINGS_IDX; +} MBG_GPIO_INFO_IDX; + +#define _mbg_swab_mbg_gpio_info_idx( _p, _recv ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_mbg_gpio_info( &(_p)->info, (_recv) ); \ +} while ( 0 ) /** - * @brief A structure used query the current GPIO port settings and capabilities + * @brief Status information on a single GPIO port */ typedef struct { - MBG_GPIO_SETTINGS settings; /**< current configuration */ - MBG_GPIO_LIMITS limits; /**< supp. and max. values */ -} MBG_GPIO_INFO; + uint8_t port_state; ///< see ::MBG_GPIO_PORT_STATES + uint8_t reserved_0; ///< reserved, currently unused and always 0 + uint16_t reserved_1; ///< reserved, currently unused and always 0 + uint32_t reserved_2; ///< reserved, currently unused and always 0 + uint32_t reserved_3; ///< reserved, currently unused and always 0 + +} MBG_GPIO_STATUS; + +#define _mbg_swab_mbg_gpio_status( _p ) \ +do \ +{ \ + _mbg_swab8( &(_p)->port_state ); \ + _mbg_swab8( &(_p)->reserved_0 ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ +} while ( 0 ) /** - * @brief A structure used to query configuration and capabilities of a specific GPIO port + * @brief Status information on a specific GPIO port */ typedef struct { - uint32_t idx; /**< port number, 0..(MBG_GPIO_CFG_LIMITS::num_io - 1) */ - MBG_GPIO_INFO info; /**< current settings and capabilities of this GPIO port */ -} MBG_GPIO_INFO_IDX; + uint16_t idx; ///< port index, 0..::MBG_GPIO_CFG_LIMITS::num_io-1 + MBG_GPIO_STATUS status; ///< status information + +} MBG_GPIO_STATUS_IDX; + +#define _mbg_swab_mbg_gpio_status_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_mbg_gpio_status( &(_p)->status ); \ +} while ( 0 ) /** - * @brief Definitions for MBG_GPIO_SETTINGS::mode + * @brief GPIO port states + * + * Used with ::MBG_GPIO_STATUS::port_state + * + * @see ::DEFAULT_GPIO_PORT_STATE_NAMES */ -enum +enum MBG_GPIO_PORT_STATES { - MBG_GPIO_SIGNAL_TYPE_FREQ_OUT, /**< variable frequency output */ - MBG_GPIO_SIGNAL_TYPE_FREQ_IN, /**< variable frequency inputs */ - MBG_GPIO_SIGNAL_TYPE_FIXED_FREQ_OUT, /**< fixed frequency outputs */ - N_MBG_GPIO_SIGNAL_TYPES /**< number of known modes */ + MBG_GPIO_PORT_UNUSED, ///< configured as unused input + MBG_GPIO_PORT_OUTPUT_ENBD, ///< configured output signal enabled + MBG_GPIO_INPUT_SIG_AVAIL, ///< input signal is available + N_MBG_GPIO_PORT_STATES ///< number of known port states }; /** - * @brief Definitions for MBG_GPIO_FF_OUT_SETTINGS::frq_bit + * @brief String initializers for GPIO port state names + * + * @see ::MBG_GPIO_PORT_STATES */ -enum +#define DEFAULT_GPIO_PORT_STATE_NAMES \ +{ \ + "unused", \ + "output enabled", \ + "input signal available" \ +} + + +/** @} defgroup group_gpio */ + + + +/** + * @defgroup group_havequick HaveQuick definitions + * + * @note This is only supported if the ::GPS_HAS_HAVEQUICK bit is set + * in the ::RECEIVER_INFO::features mask. + * + * @{ */ + + +/** + * @brief Enumeration of HaveQuick formats + * + * @see ::HAVEQUICK_SETTINGS::format + * @see ::HAVEQUICK_FORMAT_MASKS + */ +enum HAVEQUICK_FORMATS { - MBG_GPIO_FIXED_FREQ_8kHz, /**< 8kHz */ - MBG_GPIO_FIXED_FREQ_48kHz, /**< 48kHz */ - MBG_GPIO_FIXED_FREQ_1MHz, /**< 1MHz */ - MBG_GPIO_FIXED_FREQ_1544kHz, /**< 1.544MHz */ - MBG_GPIO_FIXED_FREQ_2048kHz, /**< 2.048MHz */ - MBG_GPIO_FIXED_FREQ_5MHz, /**< 5MHz */ - MBG_GPIO_FIXED_FREQ_10MHz, /**< 10MHz */ - MBG_GPIO_FIXED_FREQ_19440kHz, /**< 19.44MHz */ - N_MBG_GPIO_FIXED_FREQ /**< number of known frequencies */ + HQ_FMT_STANAG4246_1, + HQ_FMT_STANAG4246_2, + HQ_FMT_STANAG4246_PTTI, + HQ_FMT_STANAG4372_SATURN_1, + HQ_FMT_STANAG4372_SATURN_2, + HQ_FMT_STANAG4430_EXTD, + N_HQ_FMT ///< number of known formats }; -/**< Bit Masks to be used with MBG_GPIO_FF_OUT_SETTINGS::frq_bit */ -#define MSK_MBG_GPIO_FIXED_FREQ_8kHz ( 1UL << MBG_GPIO_FIXED_FREQ_8kHz ) -#define MSK_MBG_GPIO_FIXED_FREQ_48kHz ( 1UL << MBG_GPIO_FIXED_FREQ_48kHz ) -#define MSK_MBG_GPIO_FIXED_FREQ_1MHz ( 1UL << MBG_GPIO_FIXED_FREQ_1MHz ) -#define MSK_MBG_GPIO_FIXED_FREQ_1544kHz ( 1UL << MBG_GPIO_FIXED_FREQ_1544kHz ) -#define MSK_MBG_GPIO_FIXED_FREQ_2048kHz ( 1UL << MBG_GPIO_FIXED_FREQ_2048kHz ) -#define MSK_MBG_GPIO_FIXED_FREQ_5MHz ( 1UL << MBG_GPIO_FIXED_FREQ_5MHz ) -#define MSK_MBG_GPIO_FIXED_FREQ_10MHz ( 1UL << MBG_GPIO_FIXED_FREQ_10MHz ) -#define MSK_MBG_GPIO_FIXED_FREQ_19440kHz ( 1UL << MBG_GPIO_FIXED_FREQ_19440kHz ) - -/** @} group_gpio */ +/** + * @brief Bit masks associated with the enumerated HaveQuick formats + * + * @see ::HAVEQUICK_INFO::supp_formats + * @see ::HAVEQUICK_FORMATS + */ +enum HAVEQUICK_FORMAT_MASKS +{ + HQ_MSK_STANAG4246_1 = ( 1UL << HQ_FMT_STANAG4246_1 ), ///< see ::HQ_FMT_STANAG4246_1 + HQ_MSK_STANAG4246_2 = ( 1UL << HQ_FMT_STANAG4246_2 ), ///< see ::HQ_FMT_STANAG4246_2 + HQ_MSK_STANAG4246_PTTI = ( 1UL << HQ_FMT_STANAG4246_PTTI ), ///< see ::HQ_FMT_STANAG4246_PTTI + HQ_MSK_STANAG4372_SATURN_1 = ( 1UL << HQ_FMT_STANAG4372_SATURN_1 ), ///< see ::HQ_FMT_STANAG4372_SATURN_1 + HQ_MSK_STANAG4372_SATURN_2 = ( 1UL << HQ_FMT_STANAG4372_SATURN_2 ), ///< see ::HQ_FMT_STANAG4372_SATURN_2 + HQ_MSK_STANAG4430_EXTD = ( 1UL << HQ_FMT_STANAG4430_EXTD ) ///< see ::HQ_FMT_STANAG4430_EXTD +}; -/*------------------------------------------------------------------------*/ +/* + * String initializers for each Havequick format + */ +#define HQ_FMT_NAME_STANAG4246_1 "STANAG4246 1" +#define HQ_FMT_NAME_STANAG4246_2 "STANAG4246 2" +#define HQ_FMT_NAME_STANAG4246_PTTI "STANAG4246 PTTI" +#define HQ_FMT_NAME_STANAG4372_SATURN_1 "STANAG4372 SATURN 1" +#define HQ_FMT_NAME_STANAG4372_SATURN_2 "STANAG4372 SATURN 2" +#define HQ_FMT_NAME_STANAG4430_EXTD "STANAG4430 EXTD" + +#define HQ_FMT_SHRT_NAME_STANAG4246_1 "STG4246 1" +#define HQ_FMT_SHRT_NAME_STANAG4246_2 "STG4246 2" +#define HQ_FMT_SHRT_NAME_STANAG4246_PTTI "STG4246 PTTI" +#define HQ_FMT_SHRT_NAME_STANAG4372_SATURN_1 "STG4372 SATURN1" +#define HQ_FMT_SHRT_NAME_STANAG4372_SATURN_2 "STG4372 SATURN2" +#define HQ_FMT_SHRT_NAME_STANAG4430_EXTD "STG4430 EXTD" /* - * The types below are not used with all devices: + * The definition below can be used to initialize + * an array of ::N_HQ_FMT name strings. + */ +#define DEFAULT_HQ_FMT_NAMES \ +{ \ + HQ_FMT_NAME_STANAG4246_1, \ + HQ_FMT_NAME_STANAG4246_2, \ + HQ_FMT_NAME_STANAG4246_PTTI, \ + HQ_FMT_NAME_STANAG4372_SATURN_1, \ + HQ_FMT_NAME_STANAG4372_SATURN_2, \ + HQ_FMT_NAME_STANAG4430_EXTD \ +} + +#define DEFAULT_HQ_SHRT_FMT_NAMES \ +{ \ + HQ_FMT_SHRT_NAME_STANAG4246_1, \ + HQ_FMT_SHRT_NAME_STANAG4246_2, \ + HQ_FMT_SHRT_NAME_STANAG4246_PTTI, \ + HQ_FMT_SHRT_NAME_STANAG4372_SATURN_1, \ + HQ_FMT_SHRT_NAME_STANAG4372_SATURN_2, \ + HQ_FMT_SHRT_NAME_STANAG4430_EXTD \ +} + + + +/** + * @brief Configuration settings for a HaveQuick input or output + */ +typedef struct +{ + uint16_t format; ///< see ::HAVEQUICK_FORMATS + uint16_t flags; ///< see ::HAVEQUICK_FLAG_MASKS + int32_t offset; ///< Tx: unused, Rx: offset of incoming time in [s] + uint32_t reserved_0; ///< reserved, currently always 0 + uint32_t reserved_1; ///< reserved, currently always 0 + +} HAVEQUICK_SETTINGS; + +#define _mbg_swab_havequick_settings( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->format ); \ + _mbg_swab16( &(_p)->flags ); \ + _mbg_swab32( &(_p)->offset ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ +} while ( 0 ) + +/** + * @brief Current settings and capabilities of a HaveQuick input or output + */ +typedef struct +{ + HAVEQUICK_SETTINGS settings; ///< current settings + uint32_t supp_formats; ///< see ::HAVEQUICK_FORMAT_MASKS + uint16_t supp_flags; ///< mask of flags supported in settings, see ::HAVEQUICK_FLAG_MASKS + uint16_t reserved; ///< reserved, currently always 0 + +} HAVEQUICK_INFO; + +#define _mbg_swab_havequick_info( _p ) \ +do \ +{ \ + _mbg_swab_havequick_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_formats ); \ + _mbg_swab16( &(_p)->supp_flags ); \ + _mbg_swab16( &(_p)->reserved ); \ +} while ( 0 ) + + +/** + * @brief Known HaveQuick control flags + * + * @see ::HAVEQUICK_FLAG_MASKS + */ +enum HAVEQUICK_FLAG_BITS +{ + HQ_FLAG_TX_GEN_LOCAL_TIME, + HQ_FLAG_SIGNAL_INVERTED, + HQ_FLAG_USE_EXT_PPS, + N_HQ_FLAG_BITS +}; + + +/** + * @brief Bit masks associated with HaveQuick control flags + * + * @see ::HAVEQUICK_SETTINGS::flags + * @see ::HAVEQUICK_INFO::supp_flags + * @see ::HAVEQUICK_FLAG_BITS + */ +enum HAVEQUICK_FLAG_MASKS +{ + HQ_MSK_TX_GEN_LOCAL_TIME = ( 1UL << HQ_FLAG_TX_GEN_LOCAL_TIME ), ///< see ::HQ_FLAG_TX_GEN_LOCAL_TIME + HQ_MSK_SIGNAL_INVERTED = ( 1UL << HQ_FLAG_SIGNAL_INVERTED ), ///< see ::HQ_FLAG_SIGNAL_INVERTED + HQ_MSK_USE_EXT_PPS = ( 1UL << HQ_FLAG_USE_EXT_PPS ) ///< see ::HQ_FLAG_USE_EXT_PPS +}; + +/** @} defgroup group_havequick */ + + + +/** + * @defgroup group_evt_log Event logging support + * + * @note This is only available if ::GPS_HAS_EVT_LOG is set in ::RECEIVER_INFO::features. + * + * @{ */ + +/** + * @brief Number of event log entries that can be stored and yet have been saved + */ +typedef struct +{ + uint32_t used; ///< current number of saved log entries + uint32_t max; ///< max number of log entries which can be saved + +} MBG_NUM_EVT_LOG_ENTRIES; + +#define _mbg_swab_mbg_num_evt_log_entries( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->used ); \ + _mbg_swab32( &(_p)->max ); \ +} while ( 0 ) + + +typedef uint16_t MBG_EVT_CODE; +#define _mbg_swab_evt_code( _p ) _mbg_swab16( _p ) + +typedef uint16_t MBG_EVT_INFO; +#define _mbg_swab_evt_info( _p ) _mbg_swab16( _p ) + +/** + * @brief An event log entry + */ +typedef struct +{ + uint32_t time; ///< like time_t, seconds since 1970 + MBG_EVT_CODE code; ///< event ID or'ed with severity level, see @ref MBG_EVENT_CODES + MBG_EVT_INFO info; ///< optional event info, depending on event ID + +} MBG_EVT_LOG_ENTRY; + +#define _mbg_swab_mbg_evt_log_entry( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->time ); \ + _mbg_swab_evt_code( &(_p)->code ); \ + _mbg_swab_evt_info( &(_p)->info ); \ +} while ( 0 ) + + +// ::MBG_EVT_LOG_ENTRY::code is a combination of some bits used for the ID, +// plus some bits used for the severity/level. The sum of bits must not +// exceed (8 * sizeof ::MBG_EVT_LOG_ENTRY::code): + +#define MBG_EVT_ID_BITS 13 +#define MBG_EVT_LVL_BITS 3 + +#define MBG_EVT_ID_MASK ( (MBG_EVT_CODE) ( 1UL << MBG_EVT_ID_BITS ) - 1 ) +#define MBG_EVT_LVL_MASK ( (MBG_EVT_CODE) ( 1UL << MBG_EVT_LVL_BITS ) - 1 ) + + +// Combine an ID and Level to a code which can be stored +// in the code field: +#define _mbg_mk_evt_code( _id, _lvl ) \ + ( (MBG_EVT_CODE) ( (MBG_EVT_CODE)(_id) | ( (MBG_EVT_CODE)(_lvl) << MBG_EVT_ID_BITS ) ) ) + +// Extract the event ID from the code field: +#define _mbg_get_evt_id( _code ) \ + ( (_code) & MBG_EVT_ID_MASK ) + +// Extract the severity level from the code field: +#define _mbg_get_evt_lvl( _code ) \ + ( ( (_code) >> MBG_EVT_ID_BITS ) & MBG_EVT_LVL_MASK ) + + +/** + * @brief Enumeration of event IDs + * + * @see @ref MBG_EVENT_CODES + * @see @ref MBG_EVT_ID_BITS + * @see @ref MBG_EVT_LVL_BITS + */ +enum MBG_EVT_IDS +{ + MBG_EVT_ID_NONE, ///< no event (empty entry) + MBG_EVT_ID_POW_UP_RES, ///< power up reset + MBG_EVT_ID_WDOG_RES, ///< watchdog reset + MBG_EVT_ID_COLD_BOOT, ///< entering cold boot mode + MBG_EVT_ID_WARM_BOOT, ///< entering warm boot mode + MBG_EVT_ID_NORMAL_OP, ///< entering normal operation + MBG_EVT_ID_ANT_DISCONN, ///< antenna disconnect detected + MBG_EVT_ID_ANT_SHORT, ///< antenna short circuit detected + MBG_EVT_ID_ANT_OK, ///< antenna OK after failure + MBG_EVT_ID_LOW_SATS, ///< no satellites can be received though antenna not failing + N_MBG_EVT_ID +}; + + +#define ENG_EVT_ID_NAME_NONE "No event" +#define ENG_EVT_ID_NAME_POW_UP_RES "Power Up Reset" +#define ENG_EVT_ID_NAME_WDOG_RES "Watchdog Reset" +#define ENG_EVT_ID_NAME_COLD_BOOT "Cold Boot" +#define ENG_EVT_ID_NAME_WARM_BOOT "Warm Boot" +#define ENG_EVT_ID_NAME_NORMAL_OP "Normal Operation" +#define ENG_EVT_ID_NAME_ANT_DISCONN "Antenna Disconn." +#define ENG_EVT_ID_NAME_ANT_SHORT "Ant. Short-Circ." +#define ENG_EVT_ID_NAME_ANT_OK "Antenna OK" +#define ENG_EVT_ID_NAME_LOW_SATS "Few Sats Only" + + +#define MBG_EVT_ID_NAMES_ENG \ +{ \ + ENG_EVT_ID_NAME_NONE, \ + ENG_EVT_ID_NAME_POW_UP_RES, \ + ENG_EVT_ID_NAME_WDOG_RES, \ + ENG_EVT_ID_NAME_COLD_BOOT, \ + ENG_EVT_ID_NAME_WARM_BOOT, \ + ENG_EVT_ID_NAME_NORMAL_OP, \ + ENG_EVT_ID_NAME_ANT_DISCONN, \ + ENG_EVT_ID_NAME_ANT_SHORT, \ + ENG_EVT_ID_NAME_ANT_OK, \ + ENG_EVT_ID_NAME_LOW_SATS \ +} + + + +/** + * @brief Enumeration of event severity levels + * + * @see @ref MBG_EVENT_CODES + * @see @ref MBG_EVT_ID_BITS + * @see @ref MBG_EVT_LVL_BITS + */ +enum MBG_EVT_LVLS +{ + MBG_EVT_LVL_NONE, + MBG_EVT_LVL_DEBUG, + MBG_EVT_LVL_INFO, + MBG_EVT_LVL_WARN, + MBG_EVT_LVL_ERR, + MBG_EVT_LVL_CRIT, + N_MBG_EVT_LVL +}; + + +#define ENG_EVT_LVL_NAME_NONE "None" +#define ENG_EVT_LVL_NAME_DEBUG "Debug" +#define ENG_EVT_LVL_NAME_INFO "Info" +#define ENG_EVT_LVL_NAME_WARN "Warn" +#define ENG_EVT_LVL_NAME_ERR "Err" +#define ENG_EVT_LVL_NAME_CRIT "Crit." + + +#define MBG_EVT_LVL_NAMES_ENG \ +{ \ + ENG_EVT_LVL_NAME_NONE, \ + ENG_EVT_LVL_NAME_DEBUG, \ + ENG_EVT_LVL_NAME_INFO, \ + ENG_EVT_LVL_NAME_WARN, \ + ENG_EVT_LVL_NAME_ERR, \ + ENG_EVT_LVL_NAME_CRIT \ +} + + +/** + * @brief Predefined event codes with associated severity levels + * + * @see ::MBG_EVT_IDS + * @see ::MBG_EVT_LVLS + * + * @anchor MBG_EVENT_CODES @{ */ + +#define MBG_EVT_NONE _mbg_mk_evt_code( MBG_EVT_ID_NONE, MBG_EVT_LVL_NONE ) +#define MBG_EVT_POW_UP_RES _mbg_mk_evt_code( MBG_EVT_ID_POW_UP_RES, MBG_EVT_LVL_WARN ) +#define MBG_EVT_WDOG_RES _mbg_mk_evt_code( MBG_EVT_ID_WDOG_RES, MBG_EVT_LVL_CRIT ) +#define MBG_EVT_COLD_BOOT _mbg_mk_evt_code( MBG_EVT_ID_COLD_BOOT, MBG_EVT_LVL_ERR ) +#define MBG_EVT_WARM_BOOT _mbg_mk_evt_code( MBG_EVT_ID_WARM_BOOT, MBG_EVT_LVL_ERR ) +#define MBG_EVT_NORMAL_OP _mbg_mk_evt_code( MBG_EVT_ID_NORMAL_OP, MBG_EVT_LVL_INFO ) +#define MBG_EVT_ANT_DISCONN _mbg_mk_evt_code( MBG_EVT_ID_ANT_DISCONN, MBG_EVT_LVL_CRIT ) +#define MBG_EVT_ANT_SHORT _mbg_mk_evt_code( MBG_EVT_ID_ANT_SHORT, MBG_EVT_LVL_CRIT ) +#define MBG_EVT_ANT_OK _mbg_mk_evt_code( MBG_EVT_ID_ANT_OK, MBG_EVT_LVL_INFO ) +#define MBG_EVT_LOW_SATS _mbg_mk_evt_code( MBG_EVT_ID_LOW_SATS, MBG_EVT_LVL_WARN ) + +/** @} anchor MBG_EVENT_CODES */ + +/** @} defgroup group_evt_log */ + + + +/** + * @defgroup group_ims IMS support + * + * @note This is only supported if ::GPS_HAS_IMS is set in ::RECEIVER_INFO::features. + * + * @{ */ + +/** + * @brief Generic state of an IMS device + */ +typedef struct +{ + uint8_t chassis_id; ///< chassis ID, 0 if installed on the backplane + uint8_t slot_id; ///< slot number on the chassis + uint16_t num_sensors; ///< number of sensors provided by the device + uint32_t reserved; ///< reserved, currently always 0 + uint32_t flags; ///< see ::MBG_IMS_STATE_FLAG_MASKS + +} MBG_IMS_STATE; + +#define _mbg_swab_mbg_ims_state( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->num_sensors ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of bits used to define ::MBG_IMS_STATE_FLAG_MASKS + * + * @see ::MBG_IMS_STATE_FLAG_MASKS + */ +enum MBG_IMS_STATE_FLAG_BITS +{ + MBG_IMS_STATE_FLAG_BIT_HAS_FDM, ///< device supports FDM API + N_MBG_IMS_STATE_FLAG_BITS +}; + + +/** + * @brief Bit masks used with ::MBG_IMS_STATE::flags + * + * @see ::MBG_IMS_STATE_FLAG_BITS + */ +enum MBG_IMS_STATE_FLAG_MASKS +{ + MBG_IMS_STATE_FLAG_MSK_HAS_FDM = ( 1UL << MBG_IMS_STATE_FLAG_BIT_HAS_FDM ) ///< see ::MBG_IMS_STATE_FLAG_BIT_HAS_FDM +}; + + + +/** + * @brief Generic state of an IMS sensor + */ +typedef struct +{ + uint16_t type; ///< sensor type, see ::MBG_IMS_SENSORS + uint16_t idx; ///< index of the sensor of this type + int32_t val; ///< sensor value, in units according to the type + int16_t exp; ///< 10s exponent of the sensor value + uint16_t reserved; ///< currently unused, always 0 + uint32_t flags; ///< currently unused, always 0 + +} MBG_IMS_SENSOR_STATE; + +#define _mbg_swab_mbg_ims_sensor_state( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->type ); \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab32( &(_p)->val ); \ + _mbg_swab16( &(_p)->exp ); \ + _mbg_swab16( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + +/** + * @brief Generic state of an IMS sensor, with sensor index + */ +typedef struct +{ + uint32_t idx; ///< sensor index, 0..::MBG_IMS_STATE::num_sensors-1 + MBG_IMS_SENSOR_STATE state; ///< sensor state + +} MBG_IMS_SENSOR_STATE_IDX; + +#define _mbg_swab_mbg_ims_sensor_state_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_mbg_ims_sensor_state( &(_p)->state ); \ +} while ( 0 ) + + + +/** + * @brief IMS sensor types + * + * Used with ::MBG_IMS_SENSOR_STATE::type + */ +enum MBG_IMS_SENSORS +{ + MBG_IMS_SENSOR_TEMP_C, ///< temperature in degrees Celsius + MBG_IMS_SENSOR_VOLTAGE, ///< voltage in val/exp, output state in flags + MBG_IMS_SENSOR_PLL, ///< control voltage in val/exp, lock state in flags + N_MBG_IMS_SENSORS ///< number of supported sensor types +}; + + + +/** + * @brief IMS sensor state flags for voltage + * + * Used with ::MBG_IMS_SENSOR_STATE::flags in case ::MBG_IMS_SENSOR_STATE::type + * is ::MBG_IMS_SENSOR_VOLTAGE. + */ +enum MBG_IMS_SENSOR_STATE_FLAG_MASK_VOLTAGE +{ + MBG_IMS_SENSOR_VOLTAGE_OUT_ENB = 0x01, ///< output is enabled + MBG_IMS_SENSOR_VOLTAGE_OUT_OVR = 0x02 ///< output overload +}; + + +/** + * @brief IMS sensor state flags for PLL + * + * Used with ::MBG_IMS_SENSOR_STATE::flags in case ::MBG_IMS_SENSOR_STATE::type + * is ::MBG_IMS_SENSOR_PLL. + */ +enum MBG_IMS_SENSOR_STATE_FLAG_MASK_PLL +{ + MBG_IMS_SENSOR_PLL_LOCKED = 0x01 ///< PLL is locked +}; + + + +/** + * @brief DAC limit specs + */ +typedef struct +{ + int32_t dac_val_min; ///< min. possible DAC Value, positive or negative + int32_t dac_val_max; ///< max. possible DAC Value, positive or negative + + int32_t u_min; ///< min. possible real voltage range [mV], positive or negative, depending on ::MBG_DAC_SPECS::dac_val_min + int32_t u_max; ///< max. possible real voltage range [mV], positive or negative, depending on ::MBG_DAC_SPECS::dac_val_max + + uint32_t reserved_0; ///< reserved, currently always 0 + uint32_t reserved_1; ///< reserved, currently always 0 + +} MBG_DAC_SPECS; + +#define _mbg_swab_mbg_dac_specs( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->dac_val_min ); \ + _mbg_swab32( &(_p)->dac_val_max ); \ + _mbg_swab32( &(_p)->u_min ); \ + _mbg_swab32( &(_p)->u_max ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ +} while ( 0 ) + + + +/** + * @brief Output state of FDM device. + * + * @note This is only supported if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags + */ +typedef struct +{ + int32_t dac_val; ///< current DAC value, positive or negative + uint32_t mode; ///< current output mode, see ::MBG_IMS_FDM_OUTPUT_MODES + + MBG_DAC_SPECS dac_specs; ///< DAC specific limits + + uint32_t reserved_0; ///< reserved, currently always 0 + uint32_t reserved_1; ///< reserved, currently always 0 + +} MBG_IMS_FDM_OUTPUT_STATE; + +#define _mbg_swab_mbg_ims_fdm_output_state( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->dac_val ); \ + _mbg_swab32( &(_p)->mode ); \ + _mbg_swab_mbg_dac_specs( &(_p)->dac_specs ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ +} while ( 0 ) + + + +/** + * @brief Output state of FDM device plus index. + */ +typedef struct +{ + uint32_t idx; + MBG_IMS_FDM_OUTPUT_STATE state; + +} MBG_IMS_FDM_OUTPUT_STATE_IDX; + +#define _mbg_swab_mbg_ims_fdm_output_state_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_mbg_ims_fdm_output_state( &(_p)->state ); \ +} while ( 0 ) + + + +/** + * @brief Output settings of FDM device + * + * @note This is only supported if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags + */ +typedef struct +{ + uint32_t mode; ///< mode, see ::MBG_IMS_FDM_OUTPUT_MODES + uint32_t reserved; ///< reserved, currently always 0 + +} MBG_IMS_FDM_OUTPUT_SETTINGS; + +#define _mbg_swab_mbg_ims_fdm_output_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->mode ); \ + _mbg_swab32( &(_p)->reserved ); \ +} while ( 0 ) + + +/** + * @brief Output settings for FDM devices plus index. + */ +typedef struct +{ + uint32_t idx; + MBG_IMS_FDM_OUTPUT_SETTINGS settings; + +} MBG_IMS_FDM_OUTPUT_SETTINGS_IDX; + +#define _mbg_swab_mbg_ims_fdm_output_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_mbg_ims_fdm_output_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +/** + * @brief Specific output settings and limits. + */ +typedef struct +{ + MBG_IMS_FDM_OUTPUT_SETTINGS settings; ///< current settings + uint32_t supp_modes; ///< supported modes, see ::MBG_IMS_FDM_OUTPUT_MODE_MASKS + MBG_DAC_SPECS dac_specs; ///< DAC specific limits + +} MBG_IMS_FDM_OUTPUT_INFO; + +#define _mbg_swab_mbg_ims_fdm_output_info( _p ) \ +do \ +{ \ + _mbg_swab_mbg_ims_fdm_output_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_modes ); \ + _mbg_swab_mbg_dac_specs( &(_p)->dac_specs ); \ +} while ( 0 ) + + + +/** + * @brief Specific output settings and limits, plus index. + */ +typedef struct +{ + uint32_t idx; + MBG_IMS_FDM_OUTPUT_INFO info; + +} MBG_IMS_FDM_OUTPUT_INFO_IDX; + +#define _mbg_swab_mbg_ims_fdm_output_info_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_mbg_ims_fdm_output_info( &(_p)->info ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of known output modes + * + * Used with ::MBG_IMS_FDM_OUTPUT_STATE::mode + * + * @see ::MBG_IMS_FDM_OUTPUT_MODE_MASKS + */ +enum MBG_IMS_FDM_OUTPUT_MODES +{ + MBG_IMS_FDM_OUTPUT_MODE_FD, ///< Analog output reflects frequency deviation + MBG_IMS_FDM_OUTPUT_MODE_TD, ///< Analog output reflects time deviation + N_MBG_IMS_FDM_OUTPUT_MODES ///< Number of known output modes +}; + + + +/** + * @brief Bit masks used with ::MBG_IMS_FDM_OUTPUT_STATE::mode + * + * @see ::MBG_IMS_FDM_OUTPUT_MODES + */ +enum MBG_IMS_FDM_OUTPUT_MODE_MASKS +{ + MBG_IMS_FDM_OUTPUT_MODE_MSK_FD = ( 1UL << MBG_IMS_FDM_OUTPUT_MODE_FD ), ///< see ::MBG_IMS_FDM_OUTPUT_MODE_FD + MBG_IMS_FDM_OUTPUT_MODE_MSK_TD = ( 1UL << MBG_IMS_FDM_OUTPUT_MODE_TD ) ///< see ::MBG_IMS_FDM_OUTPUT_MODE_TD +}; + + + +/** + * @brief A generic structure used to specify FDM limits + */ +typedef struct +{ + uint8_t n_outputs; ///< number of outputs per module + uint8_t reserved_0; ///< reserved, currently always 0 + uint16_t reserved_1; ///< reserved, currently always 0 + + uint32_t fd_neg_limit; ///< min. frequency deviation limit, 1/::MBG_IMS_FDM_LIMITS::fd_scale Hz units + uint32_t fd_pos_limit; ///< max. frequency deviation limit, 1/::MBG_IMS_FDM_LIMITS::fd_scale Hz units + uint32_t fd_scale; ///< scale for ::MBG_IMS_FDM_LIMITS::fd_neg_limit and ::MBG_IMS_FDM_LIMITS::fd_pos_limit + + uint32_t td_neg_limit; ///< min. time deviation limit, 1/::MBG_IMS_FDM_LIMITS::td_scale s units + uint32_t td_pos_limit; ///< max. time deviation limit, 1/::MBG_IMS_FDM_LIMITS::td_scale s units + uint32_t td_scale; ///< scale for ::MBG_IMS_FDM_LIMITS::td_neg_limit and ::MBG_IMS_FDM_LIMITS::td_pos_limit + + uint32_t reserved_2; ///< reserved, currently always 0 + +} MBG_IMS_FDM_LIMITS; + +#define _mbg_swab_mbg_ims_fdm_limits( _p ) \ +do \ +{ \ + _mbg_swab8( &(_p)->n_outputs ); \ + _mbg_swab8( &(_p)->reserved_0 ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + \ + _mbg_swab32( &(_p)->fd_neg_limit ); \ + _mbg_swab32( &(_p)->fd_pos_limit ); \ + _mbg_swab32( &(_p)->fd_scale ); \ + \ + _mbg_swab32( &(_p)->td_neg_limit ); \ + _mbg_swab32( &(_p)->td_pos_limit ); \ + _mbg_swab32( &(_p)->td_scale ); \ + \ + _mbg_swab32( &(_p)->reserved_2 ); \ +} while ( 0 ) + + + +/** + * @brief State of FDM device + * + * @note This is only supported if ::MBG_IMS_STATE_FLAG_MSK_HAS_FDM is set in ::MBG_IMS_STATE::flags. + * + */ +typedef struct +{ + MBG_GPIO_FREQ freq; ///< Current frequency + + NANO_TIME_64 t_ref; ///< Current reference time + NANO_TIME_64 t_plt; ///< Current power line time + NANO_TIME_64 t_sync; ///< Last sync Time (reference time) + + uint32_t line_freq; ///< Nominal line frequency, see ::MBG_IMS_FDM_LINE_FREQS + uint32_t flags; ///< Flags, see ::MBG_IMS_FDM_STATE_FLAG_MASKS + uint32_t reserved; ///< Reserved, currently always 0 + +} MBG_IMS_FDM_STATE; + +#define _mbg_swab_mbg_ims_fdm_state( _p ) \ +do \ +{ \ + _mbg_swab_mbg_gpio_freq( &(_p)->freq ); \ + _mbg_swab_nano_time_64( &(_p)->t_ref ); \ + _mbg_swab_nano_time_64( &(_p)->t_plt ); \ + _mbg_swab_nano_time_64( &(_p)->t_sync ); \ + _mbg_swab32( &(_p)->line_freq ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab32( &(_p)->reserved ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration known line frequencies + * + * Used with ::MBG_IMS_FDM_STATE::line_freq + * + * @see ::MBG_IMS_FDM_LINE_FREQ_MASKS + */ +enum MBG_IMS_FDM_LINE_FREQS +{ + MBG_IMS_FDM_LINE_FREQ_AUTO, ///< Auto detect line frequency + MBG_IMS_FDM_LINE_FREQ_50HZ, ///< 50Hz line frequency + MBG_IMS_FDM_LINE_FREQ_60HZ, ///< 60Hz line frequency + N_MBG_IMS_FDM_LINE_FREQS ///< number of known line frequencies +}; + + +/** + * @brief Bit masks corresponding to defined line frequencies + * + * @see ::MBG_IMS_FDM_LINE_FREQS + */ +enum MBG_IMS_FDM_LINE_FREQ_MASKS +{ + MBG_IMS_FDM_LINE_FREQ_MSK_AUTO = ( 1UL << MBG_IMS_FDM_LINE_FREQ_AUTO ), ///< see ::MBG_IMS_FDM_LINE_FREQ_AUTO + MBG_IMS_FDM_LINE_FREQ_MSK_50HZ = ( 1UL << MBG_IMS_FDM_LINE_FREQ_50HZ ), ///< see ::MBG_IMS_FDM_LINE_FREQ_50HZ + MBG_IMS_FDM_LINE_FREQ_MSK_60HZ = ( 1UL << MBG_IMS_FDM_LINE_FREQ_60HZ ) ///< see ::MBG_IMS_FDM_LINE_FREQ_60HZ +}; + + +/** + * @brief Initializers for an array of line freq. name strings + * + * @see ::MBG_IMS_FDM_LINE_FREQS + */ +#define MBG_IMS_FDM_LINE_FREQ_STRS \ +{ \ + "Auto", \ + "50 Hz", \ + "60 Hz", \ +} + + +/** + * @brief Enumeration of flag bits used to define ::MBG_IMS_FDM_STATE_FLAG_MASKS + */ +enum MBG_IMS_FDM_STATE_FLAG_BITS +{ + MBG_IMS_FDM_STATE_FLAG_BIT_SYNC_AFTER_RESET, ///< if sync'ed after reset + MBG_IMS_FDM_STATE_FLAG_BIT_PLT_IS_LOCKED, ///< Power Line Time is locked + MBG_IMS_FDM_STATE_FLAG_BIT_FD_OVERFLOW, ///< Frequency deviation overflow occurred + MBG_IMS_FDM_STATE_FLAG_BIT_TD_OVERFLOW, ///< Time deviation overflow occurred + N_MBG_IMS_FDM_STATE_FLAG_BITS ///< number of known state flag bits +}; + + +/** + * @brief Bit masks used with ::MBG_IMS_FDM_STATE::flags + * + * @see ::MBG_IMS_FDM_STATE_FLAG_BITS + */ +enum MBG_IMS_FDM_STATE_FLAG_MASKS +{ + MBG_IMS_FDM_STATE_FLAG_MSK_SYNC_AFTER_RESET = ( 1UL << MBG_IMS_FDM_STATE_FLAG_BIT_SYNC_AFTER_RESET ), ///< see ::MBG_IMS_FDM_STATE_FLAG_BIT_SYNC_AFTER_RESET + MBG_IMS_FDM_STATE_FLAG_MSK_PLT_IS_LOCKED = ( 1UL << MBG_IMS_FDM_STATE_FLAG_BIT_PLT_IS_LOCKED ), ///< see ::MBG_IMS_FDM_STATE_FLAG_BIT_PLT_IS_LOCKED + MBG_IMS_FDM_STATE_FLAG_MSK_FD_OVERFLOW = ( 1UL << MBG_IMS_FDM_STATE_FLAG_BIT_FD_OVERFLOW ), ///< see ::MBG_IMS_FDM_STATE_FLAG_BIT_FD_OVERFLOW + MBG_IMS_FDM_STATE_FLAG_MSK_TD_OVERFLOW = ( 1UL << MBG_IMS_FDM_STATE_FLAG_BIT_TD_OVERFLOW ) ///< see ::MBG_IMS_FDM_STATE_FLAG_BIT_TD_OVERFLOW +}; + + + +/** + * @brief FDM device settings + * + * @note This is only supported if ::MBG_IMS_STATE_FLAG_BIT_HAS_FDM is set in ::MBG_IMS_STATE::flags. + * + */ +typedef struct +{ + uint32_t fd_neg_limit; ///< min. frequency deviation limit in 1 mHz steps + uint32_t fd_pos_limit; ///< max. frequency deviation limit in 1 mHz steps + + uint32_t td_neg_limit; ///< min. time deviation limit in 1 ms steps + uint32_t td_pos_limit; ///< max. time deviation limit in 1 ms steps + + uint32_t line_freq; ///< nominal line frequency, see ::MBG_IMS_FDM_LINE_FREQS + uint32_t reserved; ///< reserved, currently always 0 + +} MBG_IMS_FDM_SETTINGS; + +#define _mbg_swab_mbg_ims_fdm_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->fd_neg_limit ); \ + _mbg_swab32( &(_p)->fd_pos_limit ); \ + _mbg_swab32( &(_p)->td_neg_limit ); \ + _mbg_swab32( &(_p)->td_pos_limit ); \ + _mbg_swab32( &(_p)->line_freq ); \ + _mbg_swab32( &(_p)->reserved ); \ +} while ( 0 ) + + + +/** + * @brief IMS FDM flags + * + * @see ::MBG_IMS_FDM_FLAG_MASKS + */ +enum MBG_IMS_FDM_FLAGS +{ + MBG_IMS_FDM_FLAG_CAN_SET_TDEV, ///< Device supports command GPS_FDM_SET_TD + N_MBG_IMS_FDM_FLAGS ///< Number of known FDM flags +}; + + + +/** + * @brief IMS FDM flag masks + * + * @see ::MBG_IMS_FDM_FLAGS + */ +enum MBG_IMS_FDM_FLAG_MASKS +{ + MBG_IMS_FDM_FLAG_MASK_CAN_SET_TDEV = ( 1UL << MBG_IMS_FDM_FLAG_CAN_SET_TDEV ) ///< see ::MBG_IMS_FDM_FLAG_CAN_SET_TDEV +}; + + + +/** + * @brief Specific FDM settings and limits. */ +typedef struct +{ + MBG_IMS_FDM_SETTINGS settings; + uint32_t supp_line_freqs; ///< Bit mask of supported line frequencies, see ::MBG_IMS_FDM_LINE_FREQ_MASKS + uint32_t reserved; ///< Reserved, currently always 0 + uint32_t flags; ///< Flags, see ::MBG_IMS_FDM_FLAG_MASKS + +} MBG_IMS_FDM_INFO; + +#define _mbg_swab_mbg_ims_fdm_info( _p ) \ +do \ +{ \ + _mbg_swab_mbg_ims_fdm_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_line_freqs ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + +/** @} defgroup group_ims */ + + + +/** + * @defgroup group_generic_io Generic I/O support. + * + * The definitions below are used with the GENERIC_IO API. + * + * This API is <b>NOT</b> supported by all devices, it depends on + * the type of the device, and the firmware version. The macro + * _pcps_has_generic_io() or the corresponding function + * mbg_dev_has_generic_io() should be used by applications to + * check whether a particular bus-level device supports this. + * + * @{ */ + +typedef uint16_t GEN_IO_INFO_TYPE; + +#define _mbg_swab_gen_io_info_type( _p ) \ + _mbg_swab16( _p ) + + + +/** + * @brief The data structure used with the ::PCPS_GEN_IO_GET_INFO command + * + * Used to determine how many data sets of a specific type are supported + * by the device. + */ +typedef struct +{ + GEN_IO_INFO_TYPE type; // see ::PCPS_GEN_IO_TYPES + uint16_t num; // supported number of data sets of the specified type + +} GEN_IO_INFO; + +#define _mbg_swab_gen_io_info( _p ) \ +do \ +{ \ + _mbg_swab_gen_io_info_type( &(_p)->type ); \ + _mbg_swab16( &(_p)->num ); \ +} while ( 0 ) + + + +/** + * @brief Data types used with ::GEN_IO_INFO::type + * + * The first type specifier, ::PCPS_GEN_IO_GET_INFO, can + * be used to find out which of the other data types are + * supported, and how many data sets of the specified type + * are supported by a device. + */ +enum PCPS_GEN_IO_TYPES +{ + PCPS_GEN_IO_GET_INFO, ///< ::GEN_IO_INFO (read only) + PCPS_GEN_IO_CAL_REC_IRIG_RX_COMP, ///< ::CAL_REC_IRIG_RX_COMP (read/write) + N_PCPS_GEN_IO_TYPE ///< number of known types +}; + +/** @} defgroup group_generic_io */ + + typedef uint16_t ROM_CSUM; /* The ROM checksum */ -typedef uint16_t RCV_TIMEOUT; /* [min] (only if HAS_RCV_TIMEOUT) */ -typedef uint16_t IGNORE_LOCK; /* (only if GPS_HAS_IGNORE_LOCK) */ +typedef uint16_t RCV_TIMEOUT; /* [min] (only if ::HAS_RCV_TIMEOUT) */ +typedef uint16_t IGNORE_LOCK; /* (only if ::GPS_HAS_IGNORE_LOCK) */ /* - * Originally IGNORE_LOG above has been a boolean value (equal or + * Originally ::IGNORE_LOG above has been a boolean value (equal or * not equal 0) which was evaluated the same way for all ports. * * Due to special firmware requirements it has been changed to a @@ -3763,93 +10201,158 @@ typedef uint16_t IGNORE_LOCK; /* (only if GPS_HAS_IGNORE_LOCK) */ ( (_il) & ( _ignore_lock_for_port(_n) | IGNORE_LOCK_FOR_ALL_PORTS ) ) -/*------------------------------------------------------------------------*/ -/* +/** + * @defgroup group_scu Definitions used with SCU devices + * * The structures below are used with the SCU multiplexer board - * in a redundant system: - */ + * in a redundant system. + * + * @see ::GPS_MODEL_IS_SCU + * + * @{ */ typedef struct { - uint32_t hw_id; // hardware identification - uint32_t fw_id; // firmware identification - uint16_t flags; // reserved currently 0 - uint8_t clk0_info; // reference clock 0 type - uint8_t clk1_info; // reference clock 1 type - uint16_t epld_status; // epld status word, see defintions below - uint16_t epld_control; // epld control word, see defintions below + uint32_t hw_id; ///< hardware identification + uint32_t fw_id; ///< firmware identification + uint16_t flags; ///< reserved currently 0 + uint8_t clk0_info; ///< reference clock 0 type + uint8_t clk1_info; ///< reference clock 1 type + uint16_t epld_status; ///< EPLD status word, see ::SCU_STAT_MASKS + uint16_t epld_control; ///< EPLD control word, see ::SCU_CTRL_MASKS + } SCU_STAT_INFO; +#define _mbg_swab_scu_stat_info( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->hw_id ); \ + _mbg_swab32( &(_p)->fw_id ); \ + _mbg_swab16( &(_p)->flags ); \ + _mbg_swab8( &(_p)->clk0_info ); \ + _mbg_swab8( &(_p)->clk1_info ); \ + _mbg_swab16( &(_p)->epld_status ); \ + _mbg_swab16( &(_p)->epld_control ); \ +} while ( 0 ) + + + typedef struct { - uint16_t epld_control_mask; // control mask, determines which bit is to be changed - uint16_t epld_control_value; // control value, determines value of bits to be changed - uint32_t flags; // reserved, currently 0 + uint16_t epld_control_mask; ///< control mask, determines which bit is to be changed, see ::SCU_CTRL_MASKS + uint16_t epld_control_value; ///< control value, determines value of bits to be changed, see ::SCU_CTRL_MASKS + uint32_t flags; ///< reserved, currently 0 + } SCU_STAT_SETTINGS; -// definitions for status word bit masks -#define MSK_EPLD_STAT_TS1 0x0001 // state of time sync signal clk_1 -#define MSK_EPLD_STAT_TS2 0x0002 // state of time sync signal clk_2 -#define MSK_EPLD_STAT_TL_ERROR 0x0004 // state of time limit error input -#define MSK_EPLD_STAT_PSU1_OK 0x0008 // state of power supply 1 monitoring input -#define MSK_EPLD_STAT_PSU2_OK 0x0010 // state of power supply 2 monitoring input -#define MSK_EPLD_STAT_AUTO 0x0020 // AUTOMATIC/REMOTE or MANUAL Mode -#define MSK_EPLD_STAT_SEL 0x0040 // select bit for output MUX, ( clk_1 = 0 ) -#define MSK_EPLD_STAT_ENA 0x0080 // enable Bit for output MUX, set if enabled -#define MSK_EPLD_STAT_ACO 0x4000 // Access control override bit -#define MSK_EPLD_STAT_WDOG_OK 0x8000 // WDT_OK set to zero if watchdog expired +#define _mbg_swab_scu_stat_settings( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->epld_control_mask ); \ + _mbg_swab16( &(_p)->epld_control_value ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + -#define MSK_EPLD_CNTL_SEL_REM 0x0800 // remote select for output MUX ( clk_1 = 0 ) -#define MSK_EPLD_CNTL_DIS_REM 0x1000 // remote disable for output MUX -#define MSK_EPLD_CNTL_REMOTE 0x2000 // must be set to enable remote operation -#define MSK_EPLD_CNTL_SEL_SNMP 0x4000 // connect COM0 channels to XPORT -#define MSK_EPLD_CNTL_ENA_SNMP 0x8000 // select clk for comm. ( clk1 = 0 ) +/** + * @brief Bit masks used to check the SCU EPLD status + * + * Used with ::SCU_STAT_INFO::epld_status + */ +enum SCU_STAT_MASKS +{ + MSK_EPLD_STAT_TS1 = 0x0001, ///< state of time sync signal clk_1 + MSK_EPLD_STAT_TS2 = 0x0002, ///< state of time sync signal clk_2 + MSK_EPLD_STAT_TL_ERROR = 0x0004, ///< state of time limit error input + MSK_EPLD_STAT_PSU1_OK = 0x0008, ///< state of power supply 1 monitoring input + MSK_EPLD_STAT_PSU2_OK = 0x0010, ///< state of power supply 2 monitoring input + MSK_EPLD_STAT_AUTO = 0x0020, ///< AUTOMATIC/REMOTE or MANUAL Mode + MSK_EPLD_STAT_SEL = 0x0040, ///< select bit for output MUX, ( clk_1 = 0 ) + MSK_EPLD_STAT_ENA = 0x0080, ///< enable Bit for output MUX, set if enabled + MSK_EPLD_STAT_HAS_LAN = 0x0100, ///< indicates that the device has a network interface + MSK_EPLD_STAT_RESERVED0 = 0x0200, ///< reserved, DO NOT USE! + MSK_EPLD_STAT_RESERVED1 = 0x0400, ///< reserved, DO NOT USE! + MSK_EPLD_STAT_HAS_4_PSUS = 0x0800, ///< indicates 4 power supplies instead of 2 + MSK_EPLD_STAT_PSU3_OK = 0x1000, ///< state of power supply 3 monitoring input + MSK_EPLD_STAT_PSU4_OK = 0x2000, ///< state of power supply 4 monitoring input + MSK_EPLD_STAT_ACO = 0x4000, ///< Access control override bit + MSK_EPLD_STAT_WDOG_OK = 0x8000 ///< WDT_OK set to zero if watchdog expired +}; -/* - * Definitions for clk0_info and clk1_info, can be used to determine - * the reference clock type connected to SCU input channel 0 and 1: + +/** + * @brief Bit masks used to control the SCU EPLD + * + * Used with ::SCU_STAT_INFO::epld_control, ::SCU_STAT_SETTINGS::epld_control_mask, + * and ::SCU_STAT_SETTINGS::epld_control_value. */ -enum +enum SCU_CTRL_MASKS +{ + MSK_EPLD_CTL_DISB_SERIAL = 0x0001, ///< disable serial output on error + MSK_EPLD_CTL_DISB_PPS = 0x0002, ///< disable PPS output on error + MSK_EPLD_CTL_DISB_10MHZ = 0x0004, ///< disable 10 MHz output on error + + MSK_EPLD_CNTL_SEL_REM = 0x0800, ///< remote select for output MUX (clk_1 = 0) + MSK_EPLD_CNTL_DIS_REM = 0x1000, ///< remote disable for output MUX + MSK_EPLD_CNTL_REMOTE = 0x2000, ///< must be set to enable remote operation + MSK_EPLD_CNTL_SEL_SNMP = 0x4000, ///< select clk for comm. (clk1 = 0) + MSK_EPLD_CNTL_ENA_SNMP = 0x8000, ///< connect COM0 channels to XPORT +}; + + + +/** + * @brief Definitions for ::SCU_STAT_INFO::clk0_info and ::SCU_STAT_INFO::clk1_info + * + * Can be used to determine the reference clock type connected to the SCU input channels. + */ +enum SCU_CLK_INFO_TYPES { - SCU_CLK_INFO_GPS, // ref. clock is GPS receiver - SCU_CLK_INFO_DCF_PZF, // ref. clock is DCF77 PZF receiver - SCU_CLK_INFO_DCF_AM, // ref. clock is DCF77 AM receiver - SCU_CLK_INFO_TCR // ref. clock is IRIG time code receiver + SCU_CLK_INFO_GPS, ///< ref. clock is GPS receiver + SCU_CLK_INFO_DCF_PZF, ///< ref. clock is DCF77 PZF receiver + SCU_CLK_INFO_DCF_AM, ///< ref. clock is DCF77 AM receiver + SCU_CLK_INFO_TCR, ///< ref. clock is IRIG time code receiver + N_SCU_CLK_INFO ///< number of known types }; +/** @} defgroup group_scu */ + /*------------------------------------------------------------------------*/ +#define REMOTE 0x10 +#define BOOT 0x20 + /** * @brief Satellite receiver modes of operation. * - * @note Some of the code combinations are obsolete with recent + * @note Some of the code combinations are deprecated with recent * satellite receivers. However, this doesn't matter since the mode * is just read from the receiver. */ -#define REMOTE 0x10 -#define BOOT 0x20 - -#define TRACK ( 0x01 ) -#define AUTO_166 ( 0x02 ) -#define WARM_166 ( 0x03 | BOOT ) -#define COLD_166 ( 0x04 | BOOT ) -#define AUTO_BC ( 0x05 | REMOTE ) -#define WARM_BC ( 0x06 | REMOTE | BOOT ) -#define COLD_BC ( 0x07 | REMOTE | BOOT ) -#define UPDA_166 ( 0x08 | BOOT ) -#define UPDA_BC ( 0x09 | REMOTE | BOOT ) +enum RECEIVER_MODES +{ + TRACK = ( 0x01 ), + AUTO_166 = ( 0x02 ), + WARM_166 = ( 0x03 | BOOT ), + COLD_166 = ( 0x04 | BOOT ), + AUTO_BC = ( 0x05 | REMOTE ), + WARM_BC = ( 0x06 | REMOTE | BOOT ), + COLD_BC = ( 0x07 | REMOTE | BOOT ), + UPDA_166 = ( 0x08 | BOOT ), + UPDA_BC = ( 0x09 | REMOTE | BOOT ) +}; typedef int16_t DAC_VAL; #define _mbg_swab_dac_val( _p ) \ - _mbg_swab16( _p ); + _mbg_swab16( _p ) @@ -3858,21 +10361,23 @@ typedef int16_t DAC_VAL; */ typedef struct { - uint16_t mode; /**< Mode of operation, see predefined codes */ - uint16_t good_svs; /**< Numb. of satellites that can currently be received and used */ - uint16_t svs_in_view; /**< Numb. of satellites that should be in view according to the almanac data */ - DAC_VAL dac_val; /**< Oscillator fine DAC value */ - DAC_VAL dac_cal; /**< Oscillator calibration DAC value ( see #OSC_DAC_RANGE, #OSC_DAC_BIAS ) */ + uint16_t mode; ///< Mode of operation, see ::RECEIVER_MODES + uint16_t good_svs; ///< Numb. of satellites that can currently be received and used + uint16_t svs_in_view; ///< Numb. of satellites that should be visible above the horizon + DAC_VAL dac_val; ///< Oscillator fine DAC value + DAC_VAL dac_cal; ///< Oscillator calibration DAC value ( see ::OSC_DAC_RANGE, ::OSC_DAC_BIAS ) + } STAT_INFO; #define _mbg_swab_stat_info( _p ) \ +do \ { \ _mbg_swab16( &(_p)->mode ); \ _mbg_swab16( &(_p)->good_svs ); \ _mbg_swab16( &(_p)->svs_in_view ); \ _mbg_swab_dac_val( &(_p)->dac_val ); \ _mbg_swab_dac_val( &(_p)->dac_cal ); \ -} +} while ( 0 ) #define OSC_DAC_RANGE 4096UL @@ -3882,96 +10387,372 @@ typedef struct /** * @brief An enumeration of known satellite navigation systems + * + * @see ::MBG_GNSS_TYPE_MASKS + * @see ::GNSS_TYPE_STRS */ -enum +enum MBG_GNSS_TYPES { - GNSS_TYPE_GPS, /**< GPS, United States */ - GNSS_TYPE_GLONASS, /**< GLONASS, Russia */ - GNSS_TYPE_BEIDOU, /**< BEIDOU, China */ - GNSS_TYPE_GALILEO, /**< GALILEO, Europe */ - N_GNSS_TYPES /**< Number of defined codes */ + GNSS_TYPE_GPS, ///< GPS, United States + GNSS_TYPE_GLONASS, ///< GLONASS, Russia + GNSS_TYPE_BEIDOU, ///< BEIDOU, China + GNSS_TYPE_GALILEO, ///< GALILEO, Europe + GNSS_TYPE_WAAS, ///< WAAS, Wide Area Augmentation System + GNSS_TYPE_EGNOS, ///< EGNOS, European Geostationary Navigation Overlay Service + GNSS_TYPE_QZSS, ///< QZSS, Quasi Zenit Satellite System + N_GNSS_TYPES ///< Number of defined codes }; + +/** + * @brief Bit masks associated with ::MBG_GNSS_TYPES + * + * @see ::MBG_GNSS_TYPES + */ +enum MBG_GNSS_TYPE_MASKS +{ + MBG_GNSS_TYPE_MSK_GPS = ( 1UL << GNSS_TYPE_GPS ), ///< see ::GNSS_TYPE_GPS + MBG_GNSS_TYPE_MSK_GLONASS = ( 1UL << GNSS_TYPE_GLONASS ), ///< see ::GNSS_TYPE_GLONASS + MBG_GNSS_TYPE_MSK_BEIDOU = ( 1UL << GNSS_TYPE_BEIDOU ), ///< see ::GNSS_TYPE_BEIDOU + MBG_GNSS_TYPE_MSK_GALILEO = ( 1UL << GNSS_TYPE_GALILEO ), ///< see ::GNSS_TYPE_GALILEO + MBG_GNSS_TYPE_MSK_WAAS = ( 1UL << GNSS_TYPE_WAAS ), ///< see ::GNSS_TYPE_WAAS + MBG_GNSS_TYPE_MSK_EGNOS = ( 1UL << GNSS_TYPE_EGNOS ), ///< see ::GNSS_TYPE_EGNOS + MBG_GNSS_TYPE_MSK_QZSS = ( 1UL << GNSS_TYPE_QZSS ) ///< see ::GNSS_TYPE_QZSS +}; + + +/** + * @brief Name strings for the the known satellite navigation systems + * + * @see ::MBG_GNSS_TYPES + */ #define GNSS_TYPE_STRS \ { \ "GPS", \ "GLONASS", \ - "BEIDOU" , \ - "GALILEO" \ + "BEIDOU", \ + "GALILEO", \ + "WAAS", \ + "EGNOS", \ + "QZSS" \ } -#define MBG_GNSS_TYPE_MSK_GPS ( 1UL << GNSS_TYPE_GPS ) -#define MBG_GNSS_TYPE_MSK_GLONASS ( 1UL << GNSS_TYPE_GLONASS ) -#define MBG_GNSS_TYPE_MSK_BEIDOU ( 1UL << GNSS_TYPE_BEIDOU ) -#define MBG_GNSS_TYPE_MSK_GALILEO ( 1UL << GNSS_TYPE_GALILEO ) - #define N_GNSS_MODE_PRIO 8 +/** + * @brief GNSS mode settings + * + * @see ::MBG_GNSS_TYPES + */ typedef struct { - uint32_t gnss_set; /**< current set of GNSS types */ - uint8_t prio[N_GNSS_MODE_PRIO]; /**< index 0 for highest priority, use GNSS enumeration above, init with 0xFF if not supported */ - uint32_t flags; /**< see below */ + uint32_t gnss_set; ///< bit mask of currently used GNSS systems, see ::MBG_GNSS_TYPE_MASKS + uint8_t prio[N_GNSS_MODE_PRIO]; ///< see ::MBG_GNSS_TYPES, unused fields set to 0xFF, idx 0 is highest prio + uint32_t flags; ///< unused, currently always 0 (should be named MBG_GNSS_MODE_SETTINGS_FLAG_MASKS) + } MBG_GNSS_MODE_SETTINGS; #define _mbg_swab_mbg_gnss_mode_settings( _p ) \ +do \ { \ _mbg_swab32( &(_p)->gnss_set ); \ _mbg_swab32( &(_p)->flags ); \ -} +} while ( 0 ) typedef struct { - MBG_GNSS_MODE_SETTINGS settings; /**< current GNSS mode settings */ - uint32_t supp_gnss_types; /**< bit masks of supported GNSS types */ - uint32_t flags; /**< indicates which of the defined flags are supported by the device */ + MBG_GNSS_MODE_SETTINGS settings; ///< Current GNSS mode settings + uint32_t supp_gnss_types; ///< Bit masks of supported GNSS types, see ::MBG_GNSS_TYPE_MASKS + uint16_t flags; ///< See ::MBG_GNSS_MODE_INFO_FLAG_MASKS + uint16_t n_sv_status; ///< Number of ::GNSS_SV_STATUS_IDX structures that can be read (only if ::MBG_GNSS_FLAG_MSK_HAS_SV_STATUS) + } MBG_GNSS_MODE_INFO; #define _mbg_swab_mbg_gnss_mode_info( _p ) \ +do \ { \ _mbg_swab_mbg_gnss_mode_settings( &(_p)->settings ); \ _mbg_swab32( &(_p)->supp_gnss_types ); \ - _mbg_swab32( &(_p)->flags ); \ -} + _mbg_swab16( &(_p)->flags ); \ + _mbg_swab16( &(_p)->n_sv_status ); \ +} while ( 0 ) + /** - * @brief Flags used with MBG_GNSS_MODE_SETTINGS::flags and MBG_GNSS_MODE_INFO::flags + * @brief Flag bits used to define ::MBG_GNSS_MODE_INFO_FLAG_MASKS + * + * @see ::MBG_GNSS_MODE_INFO_FLAG_MASKS */ -enum +enum MBG_GNSS_MODE_INFO_FLAG_BITS { - MBG_GNSS_FLAG_EXCLUSIVE, /**< (read only) only one of the supported GNSS systems can be used at the same time */ - MBG_GNSS_FLAG_HAS_PRIORITY, /**< (read only) priority can be configured using the MBG_GNSS_MODE_SETTINGS::prio field */ + MBG_GNSS_FLAG_EXCLUSIVE, ///< Only one of the supported GNSS systems can be used at the same time + MBG_GNSS_FLAG_HAS_PRIORITY, ///< Priority can be configured using the ::MBG_GNSS_MODE_SETTINGS::prio field + MBG_GNSS_FLAG_SAT_INFO_IDX_SUPP_SER, ///< The ::GNSS_SAT_INFO_IDX structure is supported by the device + MBG_GNSS_FLAG_HAS_SV_STATUS, ///< The ::GNSS_SV_STATUS_IDX structure is supported by the device N_MBG_GNSS_FLAGS }; -#define MBG_GNSS_FLAG_MSK_EXCLUSIVE ( 1UL << MBG_GNSS_FLAG_EXCLUSIVE ) -#define MBG_GNSS_FLAG_MSK_HAS_PRIORITY ( 1UL << MBG_GNSS_FLAG_HAS_PRIORITY ) +/** + * @brief Flag masks used with ::MBG_GNSS_MODE_INFO::flags + * + * @see ::MBG_GNSS_MODE_INFO_FLAG_BITS + */ +enum MBG_GNSS_MODE_INFO_FLAG_MASKS +{ + MBG_GNSS_FLAG_MSK_EXCLUSIVE = ( 1UL << MBG_GNSS_FLAG_EXCLUSIVE ), ///< see ::MBG_GNSS_FLAG_EXCLUSIVE + MBG_GNSS_FLAG_MSK_HAS_PRIORITY = ( 1UL << MBG_GNSS_FLAG_HAS_PRIORITY ), ///< see ::MBG_GNSS_FLAG_HAS_PRIORITY + MBG_GNSS_FLAG_MSK_SAT_INFO_IDX_SUPP_SER = ( 1UL << MBG_GNSS_FLAG_SAT_INFO_IDX_SUPP_SER ), ///< see ::MBG_GNSS_FLAG_SAT_INFO_IDX_SUPP_SER + MBG_GNSS_FLAG_MSK_HAS_SV_STATUS = ( 1UL << MBG_GNSS_FLAG_HAS_SV_STATUS ) ///< see ::MBG_GNSS_FLAG_HAS_SV_STATUS +}; -#define MAX_USED_SATS 32 + +#define MAX_USED_SATS 32 /** - * @brief SV information from a certain GNSS type. + * @brief Satellite information for a particular GNSS type. */ typedef struct { - uint8_t gnss_type; /**< GNSS type from the enumeration above */ - uint8_t reserved; - uint16_t good_svs; - uint16_t svs_in_view; - uint8_t svs[MAX_USED_SATS]; + uint8_t gnss_type; ///< GNSS type as enumerated in ::MBG_GNSS_TYPES + uint8_t reserved; ///< Reserved, currently always 0 + uint16_t good_svs; ///< Num. of satellites that can currently be received and used + uint16_t svs_in_view; ///< Num. of satellites that should be visible above the horizon + uint8_t svs[MAX_USED_SATS]; ///< IDs of the satellites actually used for navigation, 0 == not used + } GNSS_SAT_INFO; #define _mbg_swab_gnss_sat_info( _p ) \ +do \ { \ _mbg_swab16( &(_p)->good_svs ); \ _mbg_swab16( &(_p)->svs_in_view ); \ -} +} while ( 0 ) + + + +/** + * @brief One of several sets of satellite information for a particular GNSS type. + * + * + */ +typedef struct +{ + /// GNSS system type index according to ::MBG_GNSS_MODE_INFO::supp_gnss_types. + /// I.e., idx 0 corresponds to the GNSS system for which the least significant + /// bit is set in ::MBG_GNSS_MODE_INFO::supp_gnss_types, idx 1 corresponds to + /// GNSS system for which the next higher bit is set, etc. This must *not* + /// necessarily match the sequence of the ::MBG_GNSS_TYPES enumeration. + uint16_t idx; + + GNSS_SAT_INFO gnss_sat_info; ///< see ::GNSS_SAT_INFO + +} GNSS_SAT_INFO_IDX; + +#define _mbg_swab_gnss_sat_info_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_gnss_sat_info( &(_p)->gnss_sat_info ); \ +} while ( 0 ) + + + +/** + * @defgroup group_gnss_sv_status GNSS Satellite Status + * + * @note These structures and associated types are only supported by a device + * if ::MBG_GNSS_FLAG_MSK_HAS_SV_STATUS is set // ::FIXME + * + * @{ */ + +/** + * @brief Detailed GNSS satellite status + * + * @see ::GNSS_SV_STATUS_IDX + * @see @ref group_gnss_sv_stat_flags + */ +typedef struct +{ + uint8_t gnss_type; ///< GNSS type as enumerated in ::MBG_GNSS_TYPES + uint8_t svno; ///< Satellite number, see ::TODO + uint8_t cn_ratio; ///< Carrier-to-noise ratio [dbHz] + int8_t elev; ///< Elevation [deg], range: -90..90 deg + + int16_t azim; ///< Azimuth [deg], range: 0..360 deg + int16_t pr_residual; ///< Pseudo range residual [m] + + uint32_t stat_flags; ///< see @ref group_gnss_sv_stat_flags + +} GNSS_SV_STATUS; + +#define _mbg_swab_gnss_sv_status( _p ) \ +do \ +{ \ + _mbg_swab8( &(_p)->gnss_type ); \ + _mbg_swab8( &(_p)->svno ); \ + _mbg_swab8( &(_p)->cn_ratio ); \ + _mbg_swab8( &(_p)->elev ); \ + _mbg_swab16( &(_p)->azim ); \ + _mbg_swab16( &(_p)->pr_residual ); \ + _mbg_swab32( &(_p)->stat_flags ); \ +} while ( 0 ) + + + +/** + * @defgroup group_gnss_sv_stat_flags GNSS status flags encoding + * + * Used with ::GNSS_SV_STATUS::stat_flags. + * + * @{ */ + +/// Bits 0 to 2 are a 3 bit quality indicator, see ::GNSS_SV_STAT_QUALITY_INDS +#define _gnss_sv_stat_quality_ind( __stat_flags ) \ + ( (uint8_t) ( (__stat_flags) & 0x00000007UL ) ) + +/// Bit 3 is set if the SV is actually used for navigation +#define _gnss_sv_stat_sv_used( __stat_flags ) \ + ( ( (__stat_flags) & 0x00000008UL ) != 0 ) + +/// Bits 4 and 5 are a 2 bit health code, see ::GNSS_SV_STAT_HEALTH_CODES +#define _gnss_sv_stat_health_code( __stat_flags ) \ + ( (uint8_t) ( ( (__stat_flags) & 0x00000030UL ) >> 4 ) ) + +/// Bit 6 is set if differential correction is available for this SV +#define _gnss_sv_stat_diff_corr( __stat_flags ) \ + ( ( (__stat_flags) & 0x00000040UL ) != 0 ) + +/// Bit 7 is set if carrier smoothed pseudorange is used for this SV +#define _gnss_sv_stat_smoothed( __stat_flags ) \ + ( ( (__stat_flags) & 0x00000080UL ) != 0 ) + +/// Bits 8 to 10 are a 3 bit code indicating the orbit source, see ::GNSS_SV_STAT_ORBIT_SOURCES +#define _gnss_sv_stat_orbit_src( __stat_flags ) \ + ( (uint8_t) ( ( (__stat_flags) & 0x00000700UL ) >> 8 ) ) + +/// Bit 11 is set if ephemeris parameters are available for this SV +#define _gnss_sv_stat_eph_avail( __stat_flags ) \ + ( ( (__stat_flags) & 0x00000800UL ) != 0 ) + +/// Bit 12 is set if almanac parameters are available for this SV +#define _gnss_sv_stat_alm_avail( __stat_flags ) \ + ( ( (__stat_flags) & 0x00001000UL ) != 0 ) + +/// Bit 13 is set if AssistNow Offline data is available for this SV +#define _gnss_sv_stat_ano_avail( __stat_flags ) \ + ( ( (__stat_flags) & 0x00002000UL ) != 0 ) + +/// Bit 14 is set if AssistNow Autonomous data is available for this SV +#define _gnss_sv_stat_aop_avail( __stat_flags ) \ + ( ( (__stat_flags) & 0x00004000UL ) != 0 ) + +/// Bit 15 is reserved. + +/// Bit 16 is set if SBAS corrections have been used for this SV +#define _gnss_sv_stat_sbas_corr_used( __stat_flags ) \ + ( ( (__stat_flags) & 0x00010000UL ) != 0 ) + +/// Bit 17 is set if RTCM corrections have been used for this SV +#define _gnss_sv_stat_rtcm_corr_used( __stat_flags ) \ + ( ( (__stat_flags) & 0x00020000UL ) != 0 ) + +/// Bits 18 and 19 are reserved. + +/// Bit 20 is set if pseudorange corrections have been used for this SV +#define _gnss_sv_stat_pr_corr_used( __stat_flags ) \ + ( ( (__stat_flags) & 0x00100000UL ) != 0 ) + +/// Bit 21 is set if carrier range corrections have been used for this SV +#define _gnss_sv_stat_cr_corr_used( __stat_flags ) \ + ( ( (__stat_flags) & 0x00200000UL ) != 0 ) + +/// Bit 22 is set if range rate (doppler) corrections have been used for this SV +#define _gnss_sv_stat_do_corr_used( __stat_flags ) \ + ( ( (__stat_flags) & 0x00400000UL ) != 0 ) + +/// Bits 23 to 31 are reserved. + +/** @} defgroup group_gnss_sv_stat_flags */ + + +/** + * @brief Quality indicators used with ::GNSS_SV_STATUS::stat_flags + * + * @see ::_gnss_sv_stat_quality_ind + */ +enum GNSS_SV_STAT_QUALITY_INDS +{ + GNSS_SV_STAT_NO_SIGNAL, ///< No signal + GNSS_SV_STAT_SEARCHING, ///< Searching signal + GNSS_SV_STAT_ACQUIRED, ///< Signal acquired + GNSS_SV_STAT_UNUSABLE, ///< Signal detected but unusable + GNSS_SV_STAT_CODE_LOCKED, ///< Code locked and time synchronized + GNSS_SV_STAT_CODE_CARRIER_LOCKED, ///< Code and carrier locked, and time synchronized + GNSS_SV_STAT_CODE_CARRIER_LOCKED_2, ///< Code and carrier locked, and time synchronized + GNSS_SV_STAT_CODE_CARRIER_LOCKED_3 ///< Code and carrier locked, and time synchronized +}; + + +/** + * @brief Health indicators used with ::GNSS_SV_STATUS::stat_flags + * + * @see ::_gnss_sv_stat_health_code + */ +enum GNSS_SV_STAT_HEALTH_CODES +{ + GNSS_SV_STAT_HEALTH_UNKNOWN, ///< Health status unknown + GNSS_SV_STAT_HEALTH_OK, ///< Healthy + GNSS_SV_STAT_HEALTH_NOT_OK ///< Unhealthy +}; + + +/** + * @brief Orbit source codes used with ::GNSS_SV_STATUS::stat_flags + * + * @see ::_gnss_sv_stat_orbit_src + */ +enum GNSS_SV_STAT_ORBIT_SOURCES +{ + GNSS_SV_STAT_ORBIT_SRC_UNKNOWN, ///< Orbit source unknown + GNSS_SV_STAT_ORBIT_SRC_EPH, ///< Ephemeris data used for orbit + GNSS_SV_STAT_ORBIT_SRC_ALM, ///< Almanac data used for orbit + GNSS_SV_STAT_ORBIT_SRC_ASSN_OFFL, ///< AssistNow Offline orbit is used + GNSS_SV_STAT_ORBIT_SRC_ASSN_AUTO, ///< AssistNow Autonomous orbit is used + GNSS_SV_STAT_ORBIT_OTHER_1, ///< Other orbit information is used + GNSS_SV_STAT_ORBIT_OTHER_2, ///< Other orbit information is used + GNSS_SV_STAT_ORBIT_OTHER_3 ///< Other orbit information is used +}; + + + +/** + * @brief Detailed GNSS satellite status, plus index + * + * @see ::GNSS_SV_STATUS + */ +typedef struct +{ + uint32_t idx; ///< Range 0..::MBG_GNSS_MODE_INFO::n_sv_status-1 + GNSS_SV_STATUS gnss_sv_status; + +} GNSS_SV_STATUS_IDX; + +#define _mbg_swab_gnss_sv_status_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_gnss_sv_status( &(_p)->gnss_sv_status ); \ +} while ( 0 ) + + +/** @} defgroup group_gnss_sv_status */ + #ifndef _IDENT_DEFINED @@ -3987,11 +10768,14 @@ typedef struct #endif #define _mbg_swab_ident( _p ) \ +do \ { \ int i; \ for ( i = 0; i < 4; i++ ) \ _mbg_swab32( &(_p)->lw[i] ); \ -} +} while ( 0 ) + + /** * @brief A data type used to configure the length of an antenna cable [m] @@ -4003,14 +10787,28 @@ typedef uint16_t ANT_CABLE_LEN; /** - * @defgroup group_ip4_cfg Simple configuration and status - * of an optional LAN interface. + * @defgroup group_net_cfg Network configuration stuff * - * @note This is only supported if the flag GPS_HAS_LAN_IP4 is set - * in RECEIVER_INFO::features. + * @{ */ + +/** + * @defgroup group_net_basic_types Basic network parameter types * * @{ */ +/** + * @brief The MAC address of a network interface + */ +typedef struct +{ + uint8_t b[6]; + +} MBG_MAC_ADDR; + +#define _mbg_swab_mbg_mac_addr( _p ) \ + _nop_macro_fnc() + + /** * @brief An IPv4 address @@ -4018,57 +10816,172 @@ typedef uint16_t ANT_CABLE_LEN; typedef uint32_t IP4_ADDR; #define _mbg_swab_ip4_addr( _p ) \ - _mbg_swab32( _p ); + _mbg_swab32( _p ) + +/** @brief The number of bits used for an IPv6 address */ +#define IP6_ADDR_BITS 128 + +/** @brief The number of bytes used for an IPv6 address */ +#define IP6_ADDR_BYTES ( IP6_ADDR_BITS / 8 ) // == 16 + /** - * @brief Settings of an IPv4 network interface + * @brief An IPv6 address */ typedef struct { - IP4_ADDR ip_addr; /**< the IP address */ - IP4_ADDR netmask; /**< the network mask */ - IP4_ADDR broad_addr; /**< the broadcast address */ - IP4_ADDR gateway; /**< the default gateway */ - uint16_t flags; /**< flags as specified below */ - uint16_t vlan_cfg; /**< VLAN configuration, see below */ + uint8_t b[IP6_ADDR_BYTES]; ///< bytes holding the address bits (not the string notation), b[0] == LSBs -} IP4_SETTINGS; +} IP6_ADDR; -#define _mbg_swab_ip4_settings( _p ) \ -{ \ - _mbg_swab_ip4_addr( &(_p)->ip_addr ); \ - _mbg_swab_ip4_addr( &(_p)->netmask ); \ - _mbg_swab_ip4_addr( &(_p)->broad_addr ); \ - _mbg_swab_ip4_addr( &(_p)->gateway ); \ - _mbg_swab16( &(_p)->flags ); \ - _mbg_swab16( &(_p)->vlan_cfg ); \ +#define _mbg_swab_ip6_addr( _p ) _nop_macro_fnc() + + + +/** + * @brief An IPv6 address plus number of netmask bits + */ +typedef struct +{ + IP6_ADDR addr; ///< bit mask of the bytes holding the address bits, b[0] == LSBs + uint8_t prefix; ///< Number of subnet mask bits for CIDR notation, e.g. 24 for /24 + uint8_t reserved[3]; ///< Reserved, alignment, currently 0 + +} IP6_ADDR_CIDR; + + + +/** @brief The max number of chars required for an IPv6 address string */ +#define MAX_IP6_ADDR_STR_LEN 43 ///< e.g. 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/128 + +/** @brief Buffer size required to store an IPv6 address string */ +#define IP6_ADDR_STR_SIZE ( MAX_IP6_ADDR_STR_LEN + 1 ) ///< ::MAX_IP6_ADDR_STR_LEN + terminating 0 + +/** @brief A buffer for an IPv6 address string */ +typedef char IP6_ADDR_STR[IP6_ADDR_STR_SIZE]; + + + +/** + * @brief Possible IPv6 Multicast Scopes + * + * If the first (most significant) byte of an IPv6 address is 0xFF this + * indicates that the address is a multicast address, and in this case + * the second byte determines the scope for which the specified address + * is valid. These scope ID numbers are assigned in RFC 7346 which + * supersedes RFC 4291. + * + * @see ::IPV6_MULTICAST_SCOPE_NAME_TABLE_ENTRIES + */ +enum IPV6_MULTICAST_SCOPES +{ + IPV6_MULTICAST_SCOPE_INTF_LOCAL = 0x01, ///< Interface-Local scope + IPV6_MULTICAST_SCOPE_LINK_LOCAL, ///< Link-Local scope + IPV6_MULTICAST_SCOPE_REALM_LOCAL, ///< Realm-Local scope + IPV6_MULTICAST_SCOPE_ADMIN_LOCAL, ///< Admin-Local scope + IPV6_MULTICAST_SCOPE_SITE_LOCAL, ///< Site-Local scope + IPV6_MULTICAST_SCOPE_ORGA_LOCAL = 0x08, ///< Organization-Local scope + IPV6_MULTICAST_SCOPE_GLOBAL_SCOPE = 0x0E ///< Global scope +}; + + +/** + * @brief Name strings for IPv6 multicast scopes + * + * This can e.g. be used to initialize an array of ::MBG_CODE_NAME_TABLE_ENTRY elements. + * + * @see ::IPV6_MULTICAST_SCOPES + */ +#define IPV6_MULTICAST_SCOPE_NAME_TABLE_ENTRIES \ +{ \ + { IPV6_MULTICAST_SCOPE_INTF_LOCAL, "FF01 - Interface-Local Scope" }, \ + { IPV6_MULTICAST_SCOPE_LINK_LOCAL, "FF02 - Link-Local Scope" }, \ + { IPV6_MULTICAST_SCOPE_REALM_LOCAL, "FF03 - Realm-Local Scope" }, \ + { IPV6_MULTICAST_SCOPE_ADMIN_LOCAL, "FF04 - Admin-Local Scope" }, \ + { IPV6_MULTICAST_SCOPE_SITE_LOCAL, "FF05 - Site-Local Scope" }, \ + { IPV6_MULTICAST_SCOPE_ORGA_LOCAL, "FF08 - Organization-Local Scope" }, \ + { IPV6_MULTICAST_SCOPE_GLOBAL_SCOPE, "FF0E - Global Scope" }, \ + { 0, NULL } \ } + +/** + * @brief The maximum length of a fully qualified host/domain domain name (FQDN) + * + * In theory each single component (host name, domain name, top level domain name) + * of a FQDN can have up to 63 characters, but the overall length is limited to + * 255 characters (see RFC-1123). We specify one more character for the trailing 0. + */ +#define MBG_MAX_HOSTNAME_LEN 256 + + +/** + * @brief A buffer for a fully qualified domain name (FQDN) or a numeric IP address string + */ +typedef char MBG_HOSTNAME[MBG_MAX_HOSTNAME_LEN]; ///< ASCIIZ format + +#define _mbg_swab_mbg_host_name( _p ) _nop_macro_fnc() + + +/** @} defgroup group_net_basic_types */ + + + +/** + * @brief The maximum length of an interface name + * + * We use an extra name here for the Meinberg-specific structures + * to avoid a name clash with system definitions, e.g. Linux systems + * define IFNAMSIZ usually as 16 in linux/if.h. + */ +#define MBG_IFNAMSIZ 16 + + +/** + * @brief Hardware type for identification of physical interfaces + * + */ +enum MBG_NET_HW_TYPES +{ + MBG_NET_HW_TYPE_UNKNOWN, + MBG_ARPHRD_ETHER, + N_MBG_NET_HW_TYPES +}; + + +/** + * @defgroup group_vlan_cfg Definitions used with VLAN configuration + * + * @{ */ + /** - * @brief Definitions used with IP4_SETTINGS::vlan_cfg + * @brief VLAN configuration * - * @note IP4_SETTINGS::vlan_cfg contains a combination of - * a VLAN ID number plus a VLAN priority code. + * @note This is a combination of a VLAN ID number plus a VLAN priority code. */ -#define VLAN_ID_BITS 12 //< number of bits to hold the ID -#define N_VLAN_ID ( 1 << VLAN_ID_BITS ) //< number of ID values -#define MIN_VLAN_ID 0 //< minimum ID value -#define MAX_VLAN_ID ( N_VLAN_ID - 1 ) //< maximum ID value +typedef uint16_t MBG_VLAN_CFG; + +#define _mbg_swab_mbg_vlan_cfg( _p ) _mbg_swab16( _p ) + +#define VLAN_ID_BITS 12 ///< number of bits to hold the ID +#define N_VLAN_ID ( 1 << VLAN_ID_BITS ) ///< number of ID values +#define MIN_VLAN_ID 0 ///< minimum ID value +#define MAX_VLAN_ID ( N_VLAN_ID - 1 ) ///< maximum ID value // vlan_id = ( vlan_cfg >> VLAN_ID_SHIFT ) & VLAN_ID_MSK #define VLAN_ID_SHIFT 0 #define VLAN_ID_MSK ( ( 1 << VLAN_ID_BITS ) - 1 ) -#define VLAN_PRIORITY_BITS 3 //< number of bits to hold priority -#define N_VLAN_PRIORITY ( 1 << VLAN_PRIORITY_BITS ) //< number of priority values -#define MIN_VLAN_PRIORITY 0 //< minimum priority -#define MAX_VLAN_PRIORITY ( N_VLAN_PRIORITY - 1 ) //< maximum priority +#define VLAN_PRIORITY_BITS 3 ///< number of bits to hold priority +#define N_VLAN_PRIORITY ( 1 << VLAN_PRIORITY_BITS ) ///< number of priority values +#define MIN_VLAN_PRIORITY 0 ///< minimum priority +#define MAX_VLAN_PRIORITY ( N_VLAN_PRIORITY - 1 ) ///< maximum priority // vlan_priority = ( vlan_cfg >> VLAN_PRIORITY_SHIFT ) & VLAN_PRIORITY_MSK -#define VLAN_PRIORITY_SHIFT ( ( 8 * sizeof( uint16_t ) ) - VLAN_PRIORITY_BITS ) +#define VLAN_PRIORITY_SHIFT ( ( 8 * sizeof( MBG_VLAN_CFG ) ) - VLAN_PRIORITY_BITS ) #define VLAN_PRIORITY_MSK ( ( 1 << VLAN_PRIORITY_BITS ) - 1 ) /** @@ -4078,92 +10991,1406 @@ typedef struct #define _decode_vlan_priority( _cfg ) ( ( (_cfg) >> VLAN_PRIORITY_SHIFT ) & VLAN_PRIORITY_MSK ) #define _encode_vlan_cfg( _id, _prty ) ( ( (_id) << VLAN_ID_SHIFT ) | ( (_prty) << VLAN_PRIORITY_SHIFT ) ) +/** @} defgroup group_vlan_cfg */ -#if 0 //##++ currently not used - -/* Misc configuration */ - -typedef struct -{ - uint16_t id; /* service ID, see below */ - uint16_t index; /* used if several same svcs must be cfg'd, e.g. DNS */ - char host[50]; /* see below */ - -} IP_CFG; +/** + * @defgroup group_ip4_cfg Simple IPv4-only configuration or status + * + * This is only supported if the flag ::GPS_HAS_LAN_IP4 is set + * in ::RECEIVER_INFO::features. + * @see @ref group_ext_net_cfg Extended network configuration and status + * + * @{ */ -/* Description of a service running on a device */ - +/** + * @brief Settings of an IPv4-only network interface + */ typedef struct { - uint16_t id; /* service ID, see below */ - uint16_t socket; /* the socket on which the service is listening */ - uint32_t flags; /* see below */ + IP4_ADDR ip_addr; ///< the IP address + IP4_ADDR netmask; ///< the network mask + IP4_ADDR broad_addr; ///< the broadcast address + IP4_ADDR gateway; ///< the default gateway + uint16_t flags; ///< see ::MBG_IP4_FLAG_MASKS + MBG_VLAN_CFG vlan_cfg; ///< VLAN configuration -} IP_SERVICE; +} IP4_SETTINGS; -#endif // 0 +#define _mbg_swab_ip4_settings( _p ) \ +do \ +{ \ + _mbg_swab_ip4_addr( &(_p)->ip_addr ); \ + _mbg_swab_ip4_addr( &(_p)->netmask ); \ + _mbg_swab_ip4_addr( &(_p)->broad_addr ); \ + _mbg_swab_ip4_addr( &(_p)->gateway ); \ + _mbg_swab16( &(_p)->flags ); \ + _mbg_swab_mbg_vlan_cfg( &(_p)->vlan_cfg ); \ +} while ( 0 ) /** - * @brief LAN interface information + * @brief Simple LAN interface information * * This structure can be retrieved from a device * to check the device's capabilities. + * + * It is only supported if the flag ::GPS_HAS_LAN_IP4 is set + * in ::RECEIVER_INFO::features. + * + * @see @ref group_ext_net_cfg Extended network configuration and status */ typedef struct { - uint16_t type; //< type of LAN interface, see below - uint8_t mac_addr[6]; //< MAC address - uint16_t ver_code; //< version number, high byte.low byte, in hex - char ver_str[GPS_ID_STR_SIZE]; //< version string - char sernum[GPS_ID_STR_SIZE]; //< serial number - uint32_t rsvd_0; //< reserved, currently always 0 - uint16_t flags; //< flags as specified below - uint16_t rsvd_1; //< reserved, currently always 0 + uint16_t type; ///< type of LAN interface, see ::LAN_IF_TYPES + MBG_MAC_ADDR mac_addr; ///< MAC address + uint16_t ver_code; ///< version number (hex) + char ver_str[GPS_ID_STR_SIZE]; ///< version string + char sernum[GPS_ID_STR_SIZE]; ///< serial number + uint32_t rsvd_0; ///< reserved, currently always 0 + uint16_t flags; ///< see ::MBG_IP4_FLAG_MASKS + uint16_t rsvd_1; ///< reserved, currently always 0 } LAN_IF_INFO; #define _mbg_swab_lan_if_info( _p ) \ +do \ { \ _mbg_swab16( &(_p)->type ); \ _mbg_swab16( &(_p)->ver_code ); \ _mbg_swab32( &(_p)->rsvd_0 ); \ _mbg_swab16( &(_p)->flags ); \ _mbg_swab16( &(_p)->rsvd_1 ); \ +} while ( 0 ) + + +/** + * @brief Codes used with ::LAN_IF_INFO::type + */ +enum LAN_IF_TYPES +{ + LAN_IF_TYPE_XPORT, ///< LAN interface on an XPORT, superseded by RSC devices + LAN_IF_TYPE_PTP, ///< LAN interface is a special PTP interface + LAN_IF_TYPE_RSC, ///< RSC device, supersedes XPORT + N_LAN_IF_TYPE ///< number of defined LAN interface types +}; + + +/** + * @brief Enumeration of flag bits used with ::IP4_SETTINGS::flags and ::LAN_IF_INFO::flags + * + * @see ::MBG_IP4_FLAG_MASKS + */ +enum MBG_IP4_FLAG_BITS +{ + /// In ::LAN_IF_INFO::flags this reports if DHCP is supported by the device. + /// If supported then it can also be used with ::IP4_SETTINGS::flags to enable + /// or disable DHCP for the network interface. + IP4_BIT_DHCP, + + /// Only used with ::IP4_SETTINGS::flags. Set if port link has been established. + IP4_BIT_LINK, + + /// In ::LAN_IF_INFO::flags this reports if VLAN is supported by the device. + /// If supported then it can also be used with ::IP4_SETTINGS::flags to enable + /// or disable VLAN for the network interface. + IP4_BIT_VLAN, + + N_IP4_BIT ///< number of defined flag bits +}; + + +/** + * @brief Bit masks used with ::IP4_SETTINGS::flags and ::LAN_IF_INFO::flags + * + * @see ::MBG_IP4_FLAG_BITS + */ +enum MBG_IP4_FLAG_MASKS +{ + IP4_MSK_DHCP = ( 1UL << IP4_BIT_DHCP ), ///< see ::IP4_BIT_DHCP + IP4_MSK_LINK = ( 1UL << IP4_BIT_LINK ), ///< see ::IP4_BIT_LINK + IP4_MSK_VLAN = ( 1UL << IP4_BIT_VLAN ), ///< see ::IP4_BIT_VLAN +}; + +/** @} defgroup group_ip4_cfg */ + + + +/** + * @defgroup group_ext_net_cfg_types Types used for extended network configuration and status + * + * @{ */ + +/** + * @brief Enumeration of types used with ::MBG_IP_ADDR::type + */ +enum MBG_IP_ADDR_TYPES +{ + MBG_IP_ADDR_TYPE_UNKNOWN, + MBG_IP_ADDR_TYPE_IP4, + MBG_IP_ADDR_TYPE_IP6, + N_MBG_IP_ADDR_TYPES +}; + +/* + * Default initializers for English mode string names. Initializers + * for multi-language strings can be found in tmonlstr.h. + */ +#define MBG_IP_ADDR_TYPE_STR_ENG_UNKNOWN "unknown" +#define MBG_IP_ADDR_TYPE_STR_ENG_IP4 "IPv4" +#define MBG_IP_ADDR_TYPE_STR_ENG_IP6 "IPv6" + +#define MBG_IP_ADDR_TYPE_NAMES_ENG \ +{ \ + MBG_IP_ADDR_TYPE_STR_ENG_UNKNOWN, \ + MBG_IP_ADDR_TYPE_STR_ENG_IP4, \ + MBG_IP_ADDR_TYPE_STR_ENG_IP6 \ } +/** + * @brief Feature flag bits used to define ::MBG_NET_GLB_CFG_INFO_MASKS + * + * @see ::MBG_NET_GLB_CFG_INFO_MASKS + */ +enum MBG_NET_GLB_CFG_INFO_FLAGS +{ + MBG_NET_GLB_SUPP_STAGE_2, ///< Supports commands which have been added in stage 2 + MBG_NET_GLB_SUPP_BONDING, ///< Supports bonding + N_MBG_NET_GLB_INFO_FLAGS +}; + /** - * @brief Codes used with LAN_IF_INFO::type + * @brief Flag masks used with ::MBG_NET_GLB_CFG_INFO::feat_flags + * + * @see ::MBG_NET_GLB_CFG_INFO_FLAGS */ -enum +enum MBG_NET_GLB_CFG_INFO_MASKS { - LAN_IF_TYPE_XPORT, //< LAN interface on an XPORT - LAN_IF_TYPE_PTP, //< LAN interface is a special PTP interface - N_LAN_IF_TYPE //< number of defined LAN interface types + MBG_NET_GLB_SUPP_STAGE_2_MASK = (1UL << MBG_NET_GLB_SUPP_STAGE_2), ///< see ::MBG_NET_GLB_SUPP_STAGE_2 + MBG_NET_GLB_SUPP_BONDING_MASK = (1UL << MBG_NET_GLB_SUPP_BONDING) ///< see ::MBG_NET_GLB_SUPP_BONDING }; + /** - * @brief Flags used with IP4_SETTINGS::flags and LAN_IF_INFO::flags + * @brief Network interface link speed mode enumeration + * + * @see @ref MBG_NET_INTF_LINK_SPEED_MODE_MASKS */ -enum +enum MBG_NET_INTF_LINK_SPEED_MODES +{ + MBG_NET_INTF_LINK_SPEED_MODE_UNKNOWN, ///< Unknown speed mode + MBG_NET_INTF_LINK_SPEED_MODE_10_T_HALF, ///< 10baseT Half Duplex (10 MBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_10_T_FULL, ///< 10baseT Full Duplex (10 MBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_100_T_HALF, ///< 100baseT Half Duplex (100 MBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_100_T_FULL, ///< 100baseT Full Duplex (100 MBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_1000_T_HALF, ///< 1000baseT Half Duplex (1 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_1000_T_FULL, ///< 1000baseT Full Duplex (1 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_1000_KX_FULL, ///< 1000baseKX Full Duplex (1 GBit/s) + + MBG_NET_INTF_LINK_SPEED_MODE_2500_X_FULL, ///< 2500baseX Full Duplex (2.5 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_10000_T_FULL, ///< 10000baseT Full Duplex (10 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_10000_KX4_FULL, ///< 10000baseKX4 Full Duplex (10 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_10000_KR_FULL, ///< 10000baseKR Full Duplex (10 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_10000_R_FEC, ///< 10000baseR FEC (forward error correction) (10 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_20000_MLD2_FULL, ///< 20000baseMLD2 Full Duplex (20 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_20000_KR2_FULL, ///< 20000baseKR2 Full Duplex (20 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_40000_KR4_FULL, ///< 40000baseKR4 Full Duplex (40 GBit/s) + + MBG_NET_INTF_LINK_SPEED_MODE_40000_CR4_FULL, ///< 40000baseCR4 Full Duplex (40 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_40000_SR4_FULL, ///< 40000baseSR4 Full Duplex (40 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_40000_LR4_FULL, ///< 40000baseLR4 Full Duplex (40 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_56000_KR4_FULL, ///< 56000baseKR4 Full Duplex (56 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_56000_CR4_FULL, ///< 56000baseCR4 Full Duplex (56 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_56000_SR4_FULL, ///< 56000baseSR4 Full Duplex (56 GBit/s) + MBG_NET_INTF_LINK_SPEED_MODE_56000_LR4_FULL, ///< 56000baseLR4 Full Duplex (56 GBit/s) + + N_MBG_NET_INTF_LINK_SPEED_MODES +}; + + + +/** + * @brief Network interface link speed mode masks + * + * @see ::MBG_NET_INTF_LINK_SPEED_MODES + * + * @anchor MBG_NET_INTF_LINK_SPEED_MODE_MASKS @{ */ + +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_UNKNOWN ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_UNKNOWN ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_UNKNOWN +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_10_T_HALF ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_10_T_HALF ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_10_T_HALF +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_10_T_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_10_T_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_10_T_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_100_T_HALF ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_100_T_HALF ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_100_T_HALF +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_100_T_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_100_T_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_100_T_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_1000_T_HALF ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_1000_T_HALF ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_1000_T_HALF +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_1000_T_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_1000_T_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_1000_T_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_1000_KX_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_1000_KX_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_1000_KX_FULL + +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_2500_X_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_2500_X_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_2500_X_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_10000_T_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_10000_T_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_10000_T_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_10000_KX4_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_10000_KX4_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_10000_KX4_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_10000_KR_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_10000_KR_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_10000_KR_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_10000_R_FEC ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_10000_R_FEC ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_10000_R_FEC +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_20000_MLD2_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_20000_MLD2_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_20000_MLD2_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_20000_KR2_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_20000_KR2_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_20000_KR2_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_40000_KR4_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_40000_KR4_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_40000_KR4_FULL + +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_40000_CR4_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_40000_CR4_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_40000_CR4_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_40000_SR4_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_40000_SR4_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_40000_SR4_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_40000_LR4_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_40000_LR4_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_40000_LR4_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_56000_KR4_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_56000_KR4_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_56000_KR4_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_56000_CR4_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_56000_CR4_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_56000_CR4_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_56000_SR4_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_56000_SR4_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_56000_SR4_FULL +#define MBG_NET_INTF_LINK_SPEED_MODE_MASK_56000_LR4_FULL ( 1UL << MBG_NET_INTF_LINK_SPEED_MODE_56000_LR4_FULL ) ///< see ::MBG_NET_INTF_LINK_SPEED_MODE_56000_LR4_FULL + +/** @} anchor MBG_NET_INTF_LINK_SPEED_MODE_MASKS */ + + + +/** + * @brief Network interface link speeds [Mb/s] + * + * @see @ref MBG_NET_INTF_LINK_SPEED_MODE_MASKS + */ +enum MBG_NET_INTF_LINK_SPEEDS +{ + MBG_NET_INTF_LINK_SPEED_UNKNOWN = 0UL, + MBG_NET_INTF_LINK_SPEED_10 = 10UL, + MBG_NET_INTF_LINK_SPEED_100 = 100UL, + MBG_NET_INTF_LINK_SPEED_1000 = 1000UL, + MBG_NET_INTF_LINK_SPEED_2500 = 2500UL, + MBG_NET_INTF_LINK_SPEED_10000 = 10000UL, + MBG_NET_INTF_LINK_SPEED_20000 = 20000UL, + MBG_NET_INTF_LINK_SPEED_40000 = 40000UL, + MBG_NET_INTF_LINK_SPEED_56000 = 56000UL +}; + + + +/** + * @brief Network interface link port types + * + * @see ::MBG_NET_INTF_LINK_PORT_TYPE_MASKS + */ +enum MBG_NET_INTF_LINK_PORT_TYPES +{ + MBG_NET_INTF_LINK_PORT_TYPE_UNKNOWN, ///< Unknown port type + MBG_NET_INTF_LINK_PORT_TYPE_TP, ///< Twisted Pair (TP) copper cable + MBG_NET_INTF_LINK_PORT_TYPE_FIBRE, ///< Fibre Optic (FO) cable + MBG_NET_INTF_LINK_PORT_TYPE_BNC, ///< Coaxial BNC cable + MBG_NET_INTF_LINK_PORT_TYPE_AUI, ///< Attachment Unit Interface (AUI), externel transceiver + MBG_NET_INTF_LINK_PORT_TYPE_MII, ///< Media Independent Interface (MII), external receiver + MBG_NET_INTF_LINK_PORT_TYPE_DA, ///< Direct attach SFP+ connection + N_MBG_NET_INTF_LINK_PORT_TYPES +}; + + + +/** + * @brief Network interface link port masks + * + * @see ::MBG_NET_INTF_LINK_PORT_TYPES + */ +enum MBG_NET_INTF_LINK_PORT_TYPE_MASKS +{ + MBG_NET_INTF_LINK_PORT_TYPE_MASK_UNKNOWN = ( 1UL << MBG_NET_INTF_LINK_PORT_TYPE_UNKNOWN ), ///< see ::MBG_NET_INTF_LINK_PORT_TYPE_UNKNOWN + MBG_NET_INTF_LINK_PORT_TYPE_MASK_TP = ( 1UL << MBG_NET_INTF_LINK_PORT_TYPE_TP ), ///< see ::MBG_NET_INTF_LINK_PORT_TYPE_TP + MBG_NET_INTF_LINK_PORT_TYPE_MASK_FIBRE = ( 1UL << MBG_NET_INTF_LINK_PORT_TYPE_FIBRE ), ///< see ::MBG_NET_INTF_LINK_PORT_TYPE_FIBRE + MBG_NET_INTF_LINK_PORT_TYPE_MASK_BNC = ( 1UL << MBG_NET_INTF_LINK_PORT_TYPE_BNC ), ///< see ::MBG_NET_INTF_LINK_PORT_TYPE_BNC + MBG_NET_INTF_LINK_PORT_TYPE_MASK_AUI = ( 1UL << MBG_NET_INTF_LINK_PORT_TYPE_AUI ), ///< see ::MBG_NET_INTF_LINK_PORT_TYPE_AUI + MBG_NET_INTF_LINK_PORT_TYPE_MASK_MII = ( 1UL << MBG_NET_INTF_LINK_PORT_TYPE_MII ), ///< see ::MBG_NET_INTF_LINK_PORT_TYPE_MII + MBG_NET_INTF_LINK_PORT_TYPE_MASK_DA = ( 1UL << MBG_NET_INTF_LINK_PORT_TYPE_DA ) ///< see ::MBG_NET_INTF_LINK_PORT_TYPE_DA +}; + + + +/** + * @brief Initializers for network interface link port type long strings + * + * @see ::MBG_NET_INTF_LINK_PORT_TYPES + */ +#define MBG_NET_INTF_LINK_PORT_TYPE_LONG_STRS \ +{ \ + "Unknown", \ + "Twisted Pair", \ + "Fibre Optic", \ + "Coaxial BNC", \ + "Attachment Unit Interface", \ + "Media Independent Interface", \ + "Direct Attach SFP+" \ +} + + +/** + * @brief Initializers for network interface link port type short strings + * + * @see ::MBG_NET_INTF_LINK_PORT_TYPES + */ +#define MBG_NET_INTF_LINK_PORT_TYPE_SHORT_STRS \ +{ \ + "Unknown", \ + "TP", \ + "FO", \ + "BNC", \ + "AUI", \ + "MII", \ + "DA" \ +} + + + +/** + * @brief Network interface link state bits + * + * @see @ref MBG_NET_INTF_LINK_STATE_MASKS + * + * @note See official Linux kernel documentation + * https://www.kernel.org/doc/Documentation/networking/operstates.txt + * for states below and explanations. Windows supports this in nearly the same way + * using similar names struct IP_ADAPTER_ADDRESSES which is explained at + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa366058%28v=vs.85%29.aspx + */ +enum MBG_NET_INTF_LINK_STATE_BITS +{ + MBG_NET_INTF_LINK_STATE_BIT_UP, + MBG_NET_INTF_LINK_STATE_BIT_RUNNING, + MBG_NET_INTF_LINK_STATE_BIT_LOWER_UP, + MBG_NET_INTF_LINK_STATE_BIT_DORMANT, + MBG_NET_INTF_LINK_STATE_BIT_BROADCAST, + MBG_NET_INTF_LINK_STATE_BIT_MULTICAST, + MBG_NET_INTF_LINK_STATE_BIT_ALL_MULTI, + MBG_NET_INTF_LINK_STATE_BIT_DEBUG, + + MBG_NET_INTF_LINK_STATE_BIT_LOOPBACK, + MBG_NET_INTF_LINK_STATE_BIT_POINT_TO_POINT, + MBG_NET_INTF_LINK_STATE_BIT_NO_ARP, + MBG_NET_INTF_LINK_STATE_BIT_PROMISC, + MBG_NET_INTF_LINK_STATE_BIT_MASTER, + MBG_NET_INTF_LINK_STATE_BIT_SLAVE, + MBG_NET_INTF_LINK_STATE_BIT_PORT_SEL, + MBG_NET_INTF_LINK_STATE_BIT_AUTO_MEDIA, + + MBG_NET_INTF_LINK_STATE_BIT_ECHO, + MBG_NET_INTF_LINK_STATE_BIT_DYNAMIC, + MBG_NET_INTF_LINK_STATE_BIT_NO_TRAILERS, + + N_MBG_NET_INTF_LINK_STATE_BITS +}; + + + +/** + * @brief Network interface link state masks + * + * @see ::MBG_NET_INTF_LINK_STATE_BITS (reclined to Linux' if.h, Windows is similiar) + * + * @anchor MBG_NET_INTF_LINK_STATE_MASKS @{ */ + +#define MBG_NET_INTF_LINK_STATE_MASK_UP ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_UP ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_UP +#define MBG_NET_INTF_LINK_STATE_MASK_RUNNING ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_RUNNING ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_RUNNING +#define MBG_NET_INTF_LINK_STATE_MASK_LOWER_UP ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_LOWER_UP ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_LOWER_UP +#define MBG_NET_INTF_LINK_STATE_MASK_DORMANT ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_DORMANT ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_DORMANT +#define MBG_NET_INTF_LINK_STATE_MASK_BROADCAST ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_BROADCAST ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_BROADCAST +#define MBG_NET_INTF_LINK_STATE_MASK_MULTICAST ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_MULTICAST ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_MULTICAST +#define MBG_NET_INTF_LINK_STATE_MASK_ALL_MULTI ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_ALL_MULTI ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_ALL_MULTI +#define MBG_NET_INTF_LINK_STATE_MASK_DEBUG ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_DEBUG ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_DEBUG + +#define MBG_NET_INTF_LINK_STATE_MASK_LOOPBACK ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_LOOPBACK ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_LOOPBACK +#define MBG_NET_INTF_LINK_STATE_MASK_POINT_TO_POINT ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_POINT_TO_POINT ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_POINT_TO_POINT +#define MBG_NET_INTF_LINK_STATE_MASK_NO_ARP ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_NO_ARP ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_NO_ARP +#define MBG_NET_INTF_LINK_STATE_MASK_PROMISC ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_PROMISC ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_PROMISC +#define MBG_NET_INTF_LINK_STATE_MASK_MASTER ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_MASTER ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_MASTER +#define MBG_NET_INTF_LINK_STATE_MASK_SLAVE ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_SLAVE ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_SLAVE +#define MBG_NET_INTF_LINK_STATE_MASK_PORT_SEL ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_PORT_SEL ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_PORT_SEL +#define MBG_NET_INTF_LINK_STATE_MASK_AUTO_MEDIA ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_AUTO_MEDIA ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_AUTO_MEDIA + +#define MBG_NET_INTF_LINK_STATE_MASK_ECHO ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_ECHO ) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_ECHO +#define MBG_NET_INTF_LINK_STATE_MASK_DYNAMIC ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_DYNAMIC) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_DYNAMIC +#define MBG_NET_INTF_LINK_STATE_MASK_NO_TRAILERS ( 1UL << MBG_NET_INTF_LINK_STATE_BIT_NO_TRAILERS) ///< see ::MBG_NET_INTF_LINK_STATE_BIT_NO_TRAILERS + +/** @} anchor MBG_NET_INTF_LINK_STATE_MASKS */ + + + +/** + * @brief Network interface link option bits + * + * @see ::MBG_NET_INTF_LINK_OPT_MASKS + */ +enum MBG_NET_INTF_LINK_OPTS +{ + MBG_NET_INTF_LINK_OPT_CAN_SET_MAC, + MBG_NET_INTF_LINK_OPT_CAN_SYNCE_IN, + MBG_NET_INTF_LINK_OPT_CAN_SYNCE_OUT, + MBG_NET_INTF_LINK_OPT_CAN_AUTONEG, + MBG_NET_INTF_LINK_OPT_CAN_NTP_HW_TS, + MBG_NET_INTF_LINK_OPT_CAN_PTP_HW_TS, + N_MBG_NET_INTF_LINK_OPTS +}; + + + +/** + * @brief Network interface link option masks + * + * @see ::MBG_NET_INTF_LINK_OPTS + */ +enum MBG_NET_INTF_LINK_OPT_MASKS +{ + MBG_NET_INTF_LINK_OPT_MASK_CAN_SET_MAC = ( 1UL << MBG_NET_INTF_LINK_OPT_CAN_SET_MAC ), ///< see ::MBG_NET_INTF_LINK_OPT_CAN_SET_MAC + MBG_NET_INTF_LINK_OPT_MASK_CAN_SYNCE_IN = ( 1UL << MBG_NET_INTF_LINK_OPT_CAN_SYNCE_IN ), ///< see ::MBG_NET_INTF_LINK_OPT_CAN_SYNCE_IN + MBG_NET_INTF_LINK_OPT_MASK_CAN_SYNCE_OUT = ( 1UL << MBG_NET_INTF_LINK_OPT_CAN_SYNCE_OUT ), ///< see ::MBG_NET_INTF_LINK_OPT_CAN_SYNCE_OUT + MBG_NET_INTF_LINK_OPT_MASK_CAN_AUTONEG = ( 1UL << MBG_NET_INTF_LINK_OPT_CAN_AUTONEG ), ///< see ::MBG_NET_INTF_LINK_OPT_CAN_AUTONEG + MBG_NET_INTF_LINK_OPT_MASK_CAN_NTP_HW_TS = ( 1UL << MBG_NET_INTF_LINK_OPT_CAN_NTP_HW_TS ), ///< see ::MBG_NET_INTF_LINK_OPT_CAN_NTP_HW_TS + MBG_NET_INTF_LINK_OPT_MASK_CAN_PTP_HW_TS = ( 1UL << MBG_NET_INTF_LINK_OPT_CAN_PTP_HW_TS ) ///< see ::MBG_NET_INTF_LINK_OPT_CAN_PTP_HW_TS +}; + + + +/** + * @brief Network interface link bonding mode + * + * Used with ::MBG_NET_INTF_LINK_SETTINGS::bond_mode + * + * @note if_bonding.h contains bonding modes under Linux, found no hint under Windows. + * BUT: Something similiar (concerning naming) can be configured under Windows + * via GUI in device manager, if supported. + */ +enum MBG_NET_INTF_LINK_BOND_MODES +{ + MBG_NET_INTF_LINK_BOND_MODE_ROUNDROBIN, + MBG_NET_INTF_LINK_BOND_MODE_ACTIVEBACKUP, + MBG_NET_INTF_LINK_BOND_MODE_XOR, + MBG_NET_INTF_LINK_BOND_MODE_BROADCAST, + MBG_NET_INTF_LINK_BOND_MODE_8023AD, + MBG_NET_INTF_LINK_BOND_MODE_TLB, + MBG_NET_INTF_LINK_BOND_MODE_ALB, + N_MBG_NET_INTF_LINK_BOND_MODES +}; + + + +/** + * @brief Network interface link bonding mode masks + * + * @see ::MBG_NET_INTF_LINK_BOND_MODES + */ +enum MBG_NET_INTF_LINK_BOND_MODE_MASKS +{ + MBG_NET_INTF_LINK_BOND_MODE_MASK_ROUNDROBIN = ( 1UL << MBG_NET_INTF_LINK_BOND_MODE_ROUNDROBIN ), ///< see ::MBG_NET_INTF_LINK_BOND_MODE_ROUNDROBIN + MBG_NET_INTF_LINK_BOND_MODE_MASK_ACTIVEBACKUP = ( 1UL << MBG_NET_INTF_LINK_BOND_MODE_ACTIVEBACKUP ), ///< see ::MBG_NET_INTF_LINK_BOND_MODE_ACTIVEBACKUP + MBG_NET_INTF_LINK_BOND_MODE_MASK_XOR = ( 1UL << MBG_NET_INTF_LINK_BOND_MODE_XOR ), ///< see ::MBG_NET_INTF_LINK_BOND_MODE_XOR + MBG_NET_INTF_LINK_BOND_MODE_MASK_BROADCAST = ( 1UL << MBG_NET_INTF_LINK_BOND_MODE_BROADCAST ), ///< see ::MBG_NET_INTF_LINK_BOND_MODE_BROADCAST + MBG_NET_INTF_LINK_BOND_MODE_MASK_8023AD = ( 1UL << MBG_NET_INTF_LINK_BOND_MODE_8023AD ), ///< see ::MBG_NET_INTF_LINK_BOND_MODE_8023AD + MBG_NET_INTF_LINK_BOND_MODE_MASK_TLB = ( 1UL << MBG_NET_INTF_LINK_BOND_MODE_TLB ), ///< see ::MBG_NET_INTF_LINK_BOND_MODE_TLB + MBG_NET_INTF_LINK_BOND_MODE_MASK_ALB = ( 1UL << MBG_NET_INTF_LINK_BOND_MODE_ALB ), ///< see ::MBG_NET_INTF_LINK_BOND_MODE_ALB +}; + + + +/** + * @brief Network interface link bonding mode name strings + * + * @see ::MBG_NET_INTF_LINK_BOND_MODES + */ +#define MBG_NET_INTF_LINK_BOND_MODE_STRS \ +{ \ + "Round Robin", \ + "Active Backup", \ + "XOR", \ + "Broadcast", \ + "802.3ad (LACP)", \ + "TLB", \ + "ALB" \ +} + + + +/** + * @brief Network interface link bonding states + * + * Used with ::MBG_NET_INTF_LINK_SETTINGS::bond_state + */ +enum MBG_NET_INTF_LINK_BOND_STATES +{ + MBG_NET_INTF_LINK_BOND_STATE_ACTIVE, + MBG_NET_INTF_LINK_BOND_STATE_BACKUP, + N_MBG_NET_INTF_LINK_BOND_STATES +}; + + +/** + * @brief Network interface link type bits + * + * Used with ::MBG_NET_INTF_LINK_SETTINGS::type + * + * @see ::MBG_NET_INTF_LINK_TYPE_MASKS + */ +enum MBG_NET_INTF_LINK_TYPES +{ + MBG_NET_INTF_LINK_TYPE_PHYS, ///< Real physical network interface + MBG_NET_INTF_LINK_TYPE_VLAN, ///< VLAN interface, assigned to physical interface + MBG_NET_INTF_LINK_TYPE_BOND, ///< Bonding interface, which acts as bonding master + N_MBG_NET_INTF_LINK_TYPE_BITS +}; + + +/** + * @brief Network interface link type masks + * + * Used with ::MBG_NET_INTF_LINK_INFO::supp_types + * + * @see ::MBG_NET_INTF_LINK_TYPES + */ +enum MBG_NET_INTF_LINK_TYPE_MASKS +{ + MBG_NET_INTF_LINK_TYPE_MASK_PHYS = ( 1UL << MBG_NET_INTF_LINK_TYPE_PHYS ), ///< see ::MBG_NET_INTF_LINK_TYPE_PHYS + MBG_NET_INTF_LINK_TYPE_MASK_VLAN = ( 1UL << MBG_NET_INTF_LINK_TYPE_VLAN ), ///< see ::MBG_NET_INTF_LINK_TYPE_VLAN + MBG_NET_INTF_LINK_TYPE_MASK_BOND = ( 1UL << MBG_NET_INTF_LINK_TYPE_BOND ) ///< see ::MBG_NET_INTF_LINK_TYPE_BOND +}; + + +/** + * @brief Network interface address bits + * + * @see ::MBG_NET_INTF_ADDR_MASKS + * + * Used with ::MBG_NET_INTF_ADDR_INFO::supp_flags and ::MBG_NET_INTF_ADDR_SETTINGS::flags + */ +enum MBG_NET_INTF_ADDR_BITS +{ + MBG_NET_INTF_ADDR_BIT_DHCP4, ///< Address has been automatically assigned by DHCP via IPv4 + MBG_NET_INTF_ADDR_BIT_DHCP6, ///< Address has been automatically assigned by DHCP via IPv6 + N_MBG_NET_INTF_ADDR_FLAGS +}; + + + +/** + * @brief Network interface address masks + * + * @see ::MBG_NET_INTF_ADDR_BITS + */ +enum MBG_NET_INTF_ADDR_MASKS +{ + MBG_NET_INTF_ADDR_MASK_DHCP4 = ( 1UL << MBG_NET_INTF_ADDR_BIT_DHCP4 ), ///< see ::MBG_NET_INTF_ADDR_BIT_DHCP4 + MBG_NET_INTF_ADDR_MASK_DHCP6 = ( 1UL << MBG_NET_INTF_ADDR_BIT_DHCP6 ) ///< see ::MBG_NET_INTF_ADDR_BIT_DHCP6 +}; + + +enum MBG_NET_INTF_ROUTE_TYPES +{ + MBG_NET_INTF_ROUTE_TYPE_UNKNOWN, + MBG_NET_INTF_ROUTE_TYPE_DEFAULT_GATEWAY, + MBG_NET_INTF_ROUTE_TYPE_DEST_GATEWAY, + MBG_NET_INTF_ROUTE_TYPE_DEST_ADDR, + N_MBG_NET_INTF_ROUTE_TYPES +}; + +/** @} defgroup group_ext_net_cfg_types */ + + + +/** + * @defgroup group_ext_net_cfg Extended network configuration and status + * + * This is only supported if the flag ::GPS_HAS_NET_CFG is set + * in ::RECEIVER_INFO::features. + * + * @{ */ + +/** + * @brief Global network configuration settings + */ +typedef struct +{ + MBG_HOSTNAME hostname; ///< hostname, eventually FQDN including domain name + + uint8_t num_intf_link; ///< number of detected/configured physical network interfaces (links), see ::MBG_NET_INTF_LINK_INFO_IDX + uint8_t num_intf_addr; ///< number of configured interface addresses, see ::MBG_NET_INTF_ADDR_INFO_IDX + uint8_t num_dns_srvr; ///< number of configured DNS servers, see ::MBG_IP_ADDR_IDX + uint8_t num_dns_srch_dom; ///< number of configured DNS search domains, see ::MBG_NET_NAME_IDX + uint8_t num_intf_route; ///< number of configured interface routes, see ::MBG_NET_INTF_ROUTE_INFO_IDX + + uint8_t reserved; ///< currently reserved, always 0 + uint16_t flags; ///< currently reserved, always 0 + +} MBG_NET_GLB_CFG_SETTINGS; + +#define _mbg_swab_net_glb_cfg_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + +/** + * @brief Global current network settings and supported features + */ +typedef struct +{ + MBG_NET_GLB_CFG_SETTINGS glb_settings; + uint16_t n_supp_intf_link; ///< max. number of supported physical network interfaces (links), see ::MBG_NET_INTF_LINK_SETTINGS_IDX, ::MBG_NET_INTF_LINK_INFO_IDX + uint16_t n_supp_intf_addr; ///< max. number of supported interface addresses, see ::MBG_NET_INTF_ADDR_SETTINGS_IDX, ::MBG_NET_INTF_ADDR_INFO_IDX + uint16_t n_supp_dns_srvr; ///< max. number of supported DNS server addresses, using ::MBG_IP_ADDR_IDX records + uint16_t n_supp_dns_srch_dom; ///< max. number of supported DNS search domain records, using ::MBG_NET_NAME_IDX records + uint16_t n_supp_intf_route; ///< max. number of supported interface routes, see ::MBG_NET_INTF_ROUTE_SETTINGS_IDX, ::MBG_NET_INTF_ROUTE_INFO_IDX + uint16_t max_hostname_len; ///< max. length of hostname including trailing 0; if set to 0, max. length is 256 (see rfc1123) + uint32_t reserved_1; ///< currently reserved, always 0 + uint32_t reserved_2; ///< currently reserved, always 0 + uint32_t feat_flags; ///< Feature flags, see ::MBG_NET_GLB_CFG_INFO_MASKS + uint32_t flags_2; ///< currently reserved, always 0 + +} MBG_NET_GLB_CFG_INFO; + +#define _mbg_swab_net_glb_cfg_info( _p ) \ +do \ +{ \ + _mbg_swab_net_glb_cfg_settings( &(_p)->glb_settings ); \ + _mbg_swab16( &(_p)->n_supp_intf_link ); \ + _mbg_swab16( &(_p)->n_supp_intf_addr ); \ + _mbg_swab16( &(_p)->n_supp_dns_srvr ); \ + _mbg_swab16( &(_p)->n_supp_dns_srch_dom ); \ + _mbg_swab16( &(_p)->n_supp_intf_route ); \ + _mbg_swab16( &(_p)->max_hostname_len ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->feat_flags ); \ + _mbg_swab32( &(_p)->flags_2 ); \ +} while ( 0 ) + + + +/** + * @brief An IPv4 or IPv6 network address + */ +typedef struct +{ + uint8_t type; ///< see ::MBG_IP_ADDR_TYPES + uint8_t reserved_1; ///< reserved, currently always 0 @todo Do we need this as scope indicator? + uint16_t reserved_2; ///< reserved, currently always 0 + + union u_addr + { + IP4_ADDR ip4_addr; ///< IPv4 address if ::MBG_IP_ADDR::type == MBG_IP_ADDR_TYPE_IP4 + IP6_ADDR ip6_addr; ///< IPv6 address if ::MBG_IP_ADDR::type == MBG_IP_ADDR_TYPE_IP6 + } u_addr; + +} MBG_IP_ADDR; + +#define _mbg_swab_ip_addr( _p ) \ +do \ +{ \ + _mbg_swab8( &(_p)->type ); \ + _mbg_swab8( &(_p)->reserved_1 ); \ + _mbg_swab16( &(_p)->reserved_2 ); \ + \ + switch ( (_p)->type ) \ + { \ + case MBG_IP_ADDR_TYPE_IP4: \ + _mbg_swab_ip4_addr( &(_p)->u_addr.ip4_addr ); \ + break; \ + \ + case MBG_IP_ADDR_TYPE_IP6: \ + _mbg_swab_ip6_addr( &(_p)->u_addr.ip6_addr ); \ + break; \ + } \ + \ +} while ( 0 ) + + + +/** + * @brief An IPv4 or IPv6 network address, plus index + */ +typedef struct +{ + uint16_t idx; + MBG_IP_ADDR addr; ///< network address + +} MBG_IP_ADDR_IDX; + +#define _mbg_swab_ip_addr_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_ip_addr( &(_p)->addr ); \ +} while ( 0 ) + + +/** + * @brief An IPv4 or IPv6 network address plus UDP or TCP port number + */ +typedef struct +{ + MBG_IP_ADDR addr; ///< see ::MBG_IP_ADDR + + uint16_t port; ///< UDP or TCP port + uint16_t flags; ///< currently always 0 + //##+++++ TODO should the flags field indicate if the port is UDP and/or TCP? + +} MBG_IP_ADDR_PORT; + +#define _mbg_swab_ip_addr_port( _p ) \ +do \ +{ \ + _mbg_swab_ip_addr( &(_p)->addr ); \ + _mbg_swab16( &(_p)->port ); \ + _mbg_swab16( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Network host or domain name + */ +typedef struct +{ + MBG_HOSTNAME name; + +} MBG_NET_NAME; + +#define _mbg_swab_net_name( _p ) \ +do \ +{ \ + _mbg_swab_mbg_host_name( &(_p)->name ); \ +} while ( 0 ) + + + +/** + * @brief Network host or domain name, plus index + */ +typedef struct +{ + uint16_t idx; + MBG_NET_NAME net_name; + +} MBG_NET_NAME_IDX; + +#define _mbg_swab_net_name_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_net_name( &(_p)->net_name ); \ +} while ( 0 ) + + + +/** + * @brief Physical network interface link specific settings + */ +typedef struct +{ + char name[MBG_IFNAMSIZ]; ///< Interface name + MBG_MAC_ADDR mac_addr; ///< Physical hardware address + MBG_MAC_ADDR broadcast; ///< Physical broadcast address + + uint32_t if_index; ///< Interface index assigned by the kernel + uint32_t common_if_index; ///< Common interface index assigned by the lib (associated with the MAC address), + ///< Valid if ::MBG_NET_INTF_LINK_SETTINGS::type is ::MBG_NET_INTF_LINK_TYPE_PHYS + uint32_t ass_if_index; ///< Interface index of the associated physical interface link, + ///< Valid if ::MBG_NET_INTF_LINK_SETTINGS::type is ::MBG_NET_INTF_LINK_TYPE_VLAN + + uint32_t flags; ///< Reserved, currently 0 + uint32_t states; ///< see @ref MBG_NET_INTF_LINK_STATE_MASKS + + uint32_t hw_type; ///< Hardware type of interface (see ::MBG_NET_HW_TYPES) + uint32_t mtu; ///< Max. packet size in bytes + uint32_t txqlen; ///< Transmission queue length (number of packets) + uint32_t speed; ///< Link speed in MBit/s + + uint8_t type; ///< see ::MBG_NET_INTF_LINK_TYPES + uint8_t duplex; ///< Duplex mode, half (0) or full (1) + uint8_t autoneg; ///< Indicates, whether autonegotiation is enabled or disabled + uint8_t port_type; ///< see ::MBG_NET_INTF_LINK_PORT_TYPES + + uint8_t bond_mode; ///< Bonding mode, see ::MBG_NET_INTF_LINK_BOND_MODES + ///< Valid if ::MBG_NET_INTF_LINK_STATE_MASK_MASTER is set in ::MBG_NET_INTF_LINK_SETTINGS::states + uint8_t bond_state; ///< Status of this interface in the bonding group, see ::MBG_NET_INTF_LINK_BOND_STATES + ///< Valid if MBG_NET_INTF_LINK_STATE_MASK_SLAVE is set in ::MBG_NET_INTF_LINK_SETTINGS::states + uint16_t bond_idx; ///< Interface index of the bonding master link, see ::MBG_NET_INTF_LINK_SETTINGS::if_index + ///< Valid, if MBG_NET_INTF_LINK_STATE_MASK_SLAVE is set in ::MBG_NET_INTF_LINK_SETTINGS::states + + uint16_t vlan_cfg; ///< VLAN configuration options, see ::MBG_VLAN_CFG + ///< Valid if ::MBG_NET_INTF_LINK_SETTINGS::type is ::MBG_NET_INTF_LINK_TYPE_VLAN + uint16_t reserved_1; ///< Reserved, currently 0 + + uint32_t reserved_2; ///< Reserved, currently 0 + uint32_t reserved_3; ///< Reserved, currently 0 + +} MBG_NET_INTF_LINK_SETTINGS; + +#define _mbg_swab_net_intf_link_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->if_index ); \ + _mbg_swab32( &(_p)->common_if_index ); \ + _mbg_swab32( &(_p)->ass_if_index ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab32( &(_p)->states ); \ + _mbg_swab32( &(_p)->hw_type ); \ + _mbg_swab32( &(_p)->mtu ); \ + _mbg_swab32( &(_p)->txqlen ); \ + _mbg_swab32( &(_p)->speed ); \ + _mbg_swab16( &(_p)->bond_idx ); \ + _mbg_swab16( &(_p)->vlan_cfg ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ +} while ( 0 ) + + + +/** + * @brief Link (physical interface) specific settings, plus index + */ +typedef struct +{ + uint16_t idx; ///< 0..::MBG_NET_GLB_CFG_INFO::n_supp_intf_link-1 + MBG_NET_INTF_LINK_SETTINGS settings; + +} MBG_NET_INTF_LINK_SETTINGS_IDX; + +#define _mbg_swab_net_intf_link_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_net_intf_link_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +/** + * @brief Link (physical interface) specific settings, flags and supported features + */ +typedef struct +{ + MBG_NET_INTF_LINK_SETTINGS link_settings; ///< see ::MBG_NET_INTF_LINK_SETTINGS + uint32_t supp_flags; ///< Reserved, currently 0 + uint32_t supp_states; ///< see @ref MBG_NET_INTF_LINK_STATE_MASKS + uint32_t supp_types; ///< see ::MBG_NET_INTF_LINK_TYPE_MASKS + uint32_t supp_speed_modes; ///< see @ref MBG_NET_INTF_LINK_SPEED_MODE_MASKS + uint32_t supp_port_types; ///< see ::MBG_NET_INTF_LINK_PORT_TYPE_MASKS + uint32_t supp_opts; ///< see ::MBG_NET_INTF_LINK_OPT_MASKS + uint32_t supp_bond_modes; ///< see ::MBG_NET_INTF_LINK_BOND_MODE_MASKS + uint32_t reserved_1; + uint32_t reserved_2; + uint32_t reserved_3; + uint32_t reserved_4; +} MBG_NET_INTF_LINK_INFO; + +#define _mbg_swab_net_intf_link_info( _p ) \ +do \ +{ \ + _mbg_swab_net_intf_link_settings( &(_p)->link_settings ); \ + _mbg_swab32( &(_p)->supp_flags ); \ + _mbg_swab32( &(_p)->supp_states ); \ + _mbg_swab32( &(_p)->supp_types ); \ + _mbg_swab32( &(_p)->supp_speed_modes ); \ + _mbg_swab32( &(_p)->supp_port_types ); \ + _mbg_swab32( &(_p)->supp_opts ); \ + _mbg_swab32( &(_p)->supp_bond_modes ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ + _mbg_swab32( &(_p)->reserved_4 ); \ +} while ( 0 ) + + + +/** + * @brief Query MBG_NET_INTF_LINK_INFO by its index + */ +typedef struct +{ + uint16_t idx; ///< 0..::MBG_NET_GLB_CFG_SETTINGS::num_intf_link-1 + MBG_NET_INTF_LINK_INFO info; ///< see ::MBG_NET_INTF_LINK_INFO + +} MBG_NET_INTF_LINK_INFO_IDX; + +#define _mbg_swab_net_intf_link_info_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_net_intf_link_info( &(_p)->info ); \ +} while ( 0 ) + + +/** + * @brief Network interface address specific settings, flags and supported features + * + * @note Use if_index to identify uniquely its associated network link. + */ +typedef struct +{ + char label[MBG_IFNAMSIZ]; ///< Interface label + + uint32_t addr_index; ///< Index of the address on the physical interface it is assigned to + uint32_t ass_if_index; ///< Index of the associated interface link, see ::MBG_NET_INTF_LINK_SETTINGS::if_index + + uint32_t flags; ///< see ::MBG_NET_INTF_ADDR_MASKS + + MBG_IP_ADDR ip; ///< IP address associated with this interface + MBG_IP_ADDR broadcast; ///< Broadcast address associated with this interface + + uint8_t prefix_bits; ///< Number of subnet mask bits for CIDR notation, e.g. 24 for /24 + uint8_t reserved_1; ///< Reserved, currently 0 + uint16_t reserved_2; ///< Reserved, currently 0 + + uint32_t reserved_3; ///< Reserved, currently 0 + uint32_t reserved_4; ///< Reserved, currently 0 + uint32_t reserved_5; ///< Reserved, currently 0 + +} MBG_NET_INTF_ADDR_SETTINGS; + +#define _mbg_swab_net_intf_addr_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->addr_index ); \ + _mbg_swab32( &(_p)->ass_if_index ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab_ip_addr( &(_p)->ip ); \ + _mbg_swab_ip_addr( &(_p)->broadcast ); \ + _mbg_swab16( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ + _mbg_swab32( &(_p)->reserved_4 ); \ + _mbg_swab32( &(_p)->reserved_5 ); \ +} while ( 0 ) + + +/** + * @brief Query MBG_NET_INTF_ADDR_SETTINGS by its index + */ +typedef struct +{ + uint16_t idx; ///< 0..::MBG_NET_GLB_CFG_SETTINGS::num_intf_addr-1 + MBG_NET_INTF_ADDR_SETTINGS settings; ///< see ::MBG_NET_INTF_ADDR_SETTINGS + +} MBG_NET_INTF_ADDR_SETTINGS_IDX; + +#define _mbg_swab_net_intf_addr_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_net_intf_addr_settings( &(_p)->settings ); \ +} while ( 0 ) + + +/** + * @brief Network interface address specific settings, flags and supported features + */ +typedef struct +{ + MBG_NET_INTF_ADDR_SETTINGS addr_settings; ///< see ::MBG_NET_INTF_ADDR_SETTINGS + uint32_t supp_flags; ///< see ::MBG_NET_INTF_ADDR_MASKS + uint32_t reserved_1; ///< Reserved, currently 0 + uint32_t reserved_2; ///< Reserved, currently 0 + +} MBG_NET_INTF_ADDR_INFO; + +#define _mbg_swab_net_intf_addr_info( _p ) \ +do \ +{ \ + _mbg_swab_net_intf_addr_settings( &(_p)->addr_settings ); \ + _mbg_swab32( &(_p)->supp_flags ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ +} while ( 0 ) + + +/** + * @brief Query MBG_NET_INTF_ADDR_INFO by its index + */ +typedef struct +{ + uint16_t idx; ///< 0..::MBG_NET_GLB_CFG_SETTINGS::num_intf_addr-1 + MBG_NET_INTF_ADDR_INFO info; ///< see ::MBG_NET_INTF_ADDR_INFO + +} MBG_NET_INTF_ADDR_INFO_IDX; + +#define _mbg_swab_net_intf_addr_info_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_net_intf_addr_info( &(_p)->info ); \ +} while ( 0 ) + + +/** + * @brief Network interface route specific settings + * + * @note Use link_mac and ass_addr_idx to identify the associated network address and network link (via address) + */ +typedef struct +{ + uint8_t type; ///< Type of the route entry, see ::MBG_NET_INTF_ROUTE_TYPES + uint8_t reserved_1; ///< Reserved, currently 0 + uint16_t reserved_2; ///< Reserved, currently 0 + + MBG_IP_ADDR gateway; ///< Gateway IP address, only used if type is + ///< ::MBG_NET_INTF_ROUTE_TYPE_DEFAULT_GATEWAY or ::MBG_NET_INTF_ROUTE_TYPE_DEST_GATEWAY + MBG_IP_ADDR dst; ///< Destination IP address, only used if ::MBG_NET_INTF_ROUTE_SETTINGS::type is + ///< ::MBG_NET_INTF_ROUTE_TYPE_DEST_GATEWAY or ::MBG_NET_INTF_ROUTE_TYPE_DEST_ADDR + uint8_t dst_prefix_bits; ///< Prefix Bits for the destination address + + uint32_t ass_if_index; ///< Index of the associated interface link, see ::MBG_NET_INTF_LINK_SETTINGS::if_index + uint32_t ass_addr_index; ///< Index of the associated interface address, see ::MBG_NET_INTF_ADDR_SETTINGS::addr_index, + ///< Valid if ::MBG_NET_INTF_ROUTE_SETTINGS::type is ::MBG_NET_INTF_ROUTE_TYPE_DEST_GATEWAY or ::MBG_NET_INTF_ROUTE_TYPE_DEST_ADDR + + uint32_t reserved_3; ///< Reserved, currently 0 + uint32_t reserved_4; ///< Reserved, currently 0 + uint32_t reserved_5; ///< Reserved, currently 0 + +} MBG_NET_INTF_ROUTE_SETTINGS; + +#define _mbg_swab_net_intf_route_settings( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->reserved_2 ); \ + _mbg_swab_ip_addr( &(_p)->gateway ); \ + _mbg_swab_ip_addr( &(_p)->dst ); \ + _mbg_swab32( &(_p)->ass_if_index ); \ + _mbg_swab32( &(_p)->ass_addr_index ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ + _mbg_swab32( &(_p)->reserved_4 ); \ + _mbg_swab32( &(_p)->reserved_5 ); \ +} while ( 0 ) + + +/** + * @brief Query MBG_NET_INTF_ROUTE_SETTINGS by its index + */ +typedef struct +{ + uint16_t idx; ///< 0..::MBG_NET_GLB_CFG_SETTINGS::num_intf_route-1 + MBG_NET_INTF_ROUTE_SETTINGS settings; ///< see ::MBG_NET_INTF_ROUTE_SETTINGS + +} MBG_NET_INTF_ROUTE_SETTINGS_IDX; + +#define _mbg_swab_net_intf_route_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_net_intf_route_settings( &(_p)->settings ); \ +} while ( 0 ) + + +/** + * @brief Network interface address specific settings + */ +typedef struct +{ + MBG_NET_INTF_ROUTE_SETTINGS route_settings; ///< see ::MBG_NET_INTF_ROUTE_SETTINGS + uint32_t reserved_1; ///< Reserved, currently 0 + uint32_t reserved_2; ///< Reserved, currently 0 + uint32_t reserved_3; ///< Reserved, currently 0 + uint32_t reserved_4; ///< Reserved, currently 0 +} MBG_NET_INTF_ROUTE_INFO; + +#define _mbg_swab_net_intf_route_info( _p ) \ +do \ +{ \ + _mbg_swab_net_intf_route_settings( &(_p)->route_settings ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ + _mbg_swab32( &(_p)->reserved_4 ); \ +} while ( 0 ) + + +/** + * @brief Query MBG_NET_INTF_ROUTE_INFO by its index + */ +typedef struct +{ + uint16_t idx; ///< 0..::MBG_NET_GLB_CFG_SETTINGS::num_intf_route-1 + MBG_NET_INTF_ROUTE_INFO info; ///< see ::MBG_NET_INTF_ROUTE_INFO + +} MBG_NET_INTF_ROUTE_INFO_IDX; + +#define _mbg_swab_net_intf_route_info_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_net_intf_route_info( &(_p)->info ); \ +} while ( 0 ) + + +/** @} defgroup group_ext_net_cfg */ + +/** @} defgroup group_net_cfg */ + + + + + +/** + * @defgroup group_ucap_net User Captures via Network + * + * @note Group for the user capture via network feature + * Only supported if ::MBG_XFEATURE_UCAP_NET is set in extended features + * Corresponding GPS commands are ::GPS_UCAP_NET_GLB_INFO and ::GPS_UCAP_NET_RECV_INFO_IDX + * + * @{ */ + + +#define MBG_UCAP_NET_DEFAULT_UDP_PORT 50815 + +/** + * @brief Transfer mode for user captures via network + * + * @see ::MBG_UCAP_NET_TRANSF_MODE_MASKS + * + * Used with ::MBG_UCAP_NET_RECV_SETTINGS::mode + */ +enum MBG_UCAP_NET_TRANSF_MODE +{ + MBG_UCAP_NET_TRANSF_MODE_UNKNOWN, ///< Unknown transfer mode + MBG_UCAP_NET_TRANSF_MODE_ON_REQ, ///< User captures will be transferred on request only + MBG_UCAP_NET_TRANSF_MODE_AUTO, ///< User captures are being transferred automatically + N_MBG_UCAP_NET_TRANSF_MODES +}; + + +/** + * @brief Masks for transfer mode used with ::MBG_UCAP_NET_GLB_INFO::supp_modes + * + * @see ::MBG_UCAP_NET_TRANSF_MODE + */ +enum MBG_UCAP_NET_TRANSF_MODE_MASKS +{ + MBG_UCAP_NET_TRANSF_MODE_MASK_UNKNOWN = ( 1UL << MBG_UCAP_NET_TRANSF_MODE_UNKNOWN ), ///< see ::MBG_UCAP_NET_TRANSF_MODE_UNKNOWN + MBG_UCAP_NET_TRANSF_MODE_MASK_ON_REQ = ( 1UL << MBG_UCAP_NET_TRANSF_MODE_ON_REQ ), ///< see ::MBG_UCAP_NET_TRANSF_MODE_ON_REQ + MBG_UCAP_NET_TRANSF_MODE_MASK_AUTO = ( 1UL << MBG_UCAP_NET_TRANSF_MODE_AUTO ) ///< see ::MBG_UCAP_NET_TRANSF_MODE_AUTO +}; + + + +/** + * @brief Transfer protocol for user captures via network + * + * @see ::MBG_UCAP_NET_TRANSF_PROTO_MASKS + * + * Used with ::MBG_UCAP_NET_RECV_SETTINGS::proto + */ +enum MBG_UCAP_NET_TRANSF_PROTO +{ + MBG_UCAP_NET_TRANSF_PROTO_UNKNOWN, ///< Unknown transfer mode + MBG_UCAP_NET_TRANSF_PROTO_UDP, ///< User captures are transferred via UDP + N_MBG_UCAP_NET_TRANSF_PROTOS +}; + + +/** + * @brief Masks for transfer protocol used with ::MBG_UCAP_NET_GLB_INFO::supp_protos + * + * @see ::MBG_UCAP_NET_TRANSF_PROTO + */ +enum MBG_UCAP_NET_TRANSF_PROTO_MASKS +{ + MBG_UCAP_NET_TRANSF_PROTO_MASK_UNKNOWN = ( 1UL << MBG_UCAP_NET_TRANSF_PROTO_UNKNOWN ), ///< see ::MBG_UCAP_NET_TRANSF_PROTO_UNKNOWN + MBG_UCAP_NET_TRANSF_PROTO_MASK_UDP = ( 1UL << MBG_UCAP_NET_TRANSF_PROTO_UDP ) ///< see ::MBG_UCAP_NET_TRANSF_PROTO_UDP +}; + + + +/** + * @brief Supported flags for user captures via network + * + * @see ::MBG_UCAP_NET_SUPP_FLAG_MASKS + */ +enum MBG_UCAP_NET_SUPP_FLAGS +{ + MBG_UCAP_NET_SUPP_FLAG_IPV6, + N_MBG_UCAP_NET_SUPP_FLAGS +}; + + +/** + * @brief Masks for supported flags used with ::MBG_UCAP_NET_GLB_INFO::supp_flags + * + * @see ::MBG_UCAP_NET_TRANSF_PROTO + */ +enum MBG_UCAP_NET_SUPP_FLAG_MASKS { - IP4_BIT_DHCP, //< DHCP supported (LAN_IF_INFO) / enabled (IP4_SETTINGS) - IP4_BIT_LINK, //< used only in IP4_SETTINGS to report link state - IP4_BIT_VLAN, //< VLAN supported (LAN_IF_INFO) / enabled (IP4_SETTINGS) - N_IP4_BIT //< number of defined flag bits + MBG_UCAP_NET_SUPP_FLAG_MASK_IPV6 = ( 1UL << MBG_UCAP_NET_SUPP_FLAG_IPV6 ) ///< see ::MBG_UCAP_NET_SUPP_FLAG_IPV6 }; -#define IP4_MSK_DHCP ( 1UL << IP4_BIT_DHCP ) -#define IP4_MSK_LINK ( 1UL << IP4_BIT_LINK ) -#define IP4_MSK_VLAN ( 1UL << IP4_BIT_VLAN ) -/** @} group_ip4_cfg */ +/** + * @brief Global settings for user captures via network + * + * @note This structure shall be used to set the current global settings of a device + * with GPS command ::GPS_UCAP_NET_GLB_INFO. + */ +typedef struct +{ + uint32_t num_recvs; ///< Number of configured network receivers, see ::MBG_UCAP_NET_RECV_INFO_IDX + uint32_t reserved_0; ///< Reserved, currently always 0 + uint32_t reserved_1; ///< Reserved, currently always 0 + uint32_t reserved_2; ///< Reserved, currently always 0 + +} MBG_UCAP_NET_GLB_SETTINGS; + + +#define _mbg_swab_ucap_net_glb_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->num_recvs ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ +} while ( 0 ) + + + +/** + * @brief Global settings, features and flags for user captures via network + * + * @note This structure shall be used to read the current global settings from a device + * with GPS command ::GPS_UCAP_NET_GLB_INFO. + */ +typedef struct +{ + MBG_UCAP_NET_GLB_SETTINGS settings; ///< see ::MBG_UCAP_NET_GLB_SETTINGS + + uint32_t n_supp_recvs; ///< Number of supported network receivers, see ::MBG_UCAP_NET_RECV_INFO_IDX + uint32_t supp_modes; ///< Supported transfer modes, see ::MBG_UCAP_NET_TRANSF_MODE_MASKS + uint32_t supp_protos; ///< Supported transfer protocols, see ::MBG_UCAP_NET_TRANSF_PROTO_MASKS + uint32_t reserved_0; ///< Reserved, currently always 0 + uint32_t reserved_1; ///< Reserved, currently always 0 + uint32_t supp_flags; ///< Supported flags, see ::MBG_UCAP_NET_SUPP_FLAG_MASKS + +} MBG_UCAP_NET_GLB_INFO; + + +#define _mbg_swab_ucap_net_glb_info( _p ) \ +do \ +{ \ + _mbg_swab_ucap_net_glb_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->n_supp_recvs ); \ + _mbg_swab32( &(_p)->supp_modes ); \ + _mbg_swab32( &(_p)->supp_protos ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->supp_flags ); \ +} while ( 0 ) + + + +/** + * @brief Settings for receivers of user captures via network + */ +typedef struct +{ + uint8_t mode; ///< Transfer mode, see ::MBG_UCAP_NET_TRANSF_MODE + uint8_t proto; ///< Transfer protocol, see ::MBG_UCAP_NET_TRANSF_PROTO + uint16_t reserved_1; ///< Reserved, currently always 0 + + uint32_t reserved_2; ///< Reserved, currently always 0 + uint32_t reserved_3; ///< Reserved, currently always 0 + uint32_t ucaps; ///< Bit mask for active user captures + + MBG_IP_ADDR_PORT addr; ///< Destination IP and port address of the network receiver, see ::MBG_IP_ADDR_PORT + +} MBG_UCAP_NET_RECV_SETTINGS; + + +#define _mbg_swab_ucap_net_recv_settings( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ + _mbg_swab32( &(_p)->ucaps ); \ + _mbg_swab_ip_addr_port( &(_p)->addr ); \ +} while ( 0 ) + + + +/** + * @brief Settings for receivers of user captures via network + * + * @note This structure shall be used to write the settings to the device + * with GPS command ::GPS_UCAP_NET_RECV_INFO_IDX. + * This can be done for index 0 to ::MBG_UCAP_NET_GLB_SETTINGS::num_recvs-1. + * + * @see ::MBG_UCAP_NET_RECV_SETTINGS + */ +typedef struct +{ + uint16_t idx; ///< 0..::MBG_UCAP_NET_GLB_SETTINGS::num_recvs-1 + MBG_UCAP_NET_RECV_SETTINGS settings; ///< see ::MBG_UCAP_NET_RECV_SETTINGS + +} MBG_UCAP_NET_RECV_SETTINGS_IDX; + + +#define _mbg_swab_ucap_net_recv_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_ucap_net_recv_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +/** + * @brief Settings, features and flags for receivers of user captures via network + */ +typedef struct +{ + MBG_UCAP_NET_RECV_SETTINGS settings; ///< see ::MBG_UCAP_NET_RECV_SETTINGS + + uint32_t reserved_0; ///< Reserved, currently always 0 + uint32_t reserved_1; ///< Reserved, currently always 0 + uint32_t reserved_2; ///< Reserved, currently always 0 + uint32_t reserved_3; ///< Reserved, currently always 0 + +} MBG_UCAP_NET_RECV_INFO; + + +#define _mbg_swab_ucap_net_recv_info( _p ) \ +do \ +{ \ + _mbg_swab_ucap_net_recv_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ +} while ( 0 ) + + + +/** + * @brief Settings, features and flags for receivers of user captures via network + * + * @note This structure shall be used to read the current settings from the device + * with GPS command ::GPS_UCAP_NET_RECV_INFO_IDX. + * This can be done for index 0 to ::MBG_UCAP_NET_GLB_SETTINGS::num_recvs-1. + * + * @see ::MBG_UCAP_NET_RECV_INFO + */ +typedef struct +{ + uint16_t idx; ///< 0..::MBG_UCAP_NET_GLB_INFO::n_supp_recvs-1 + MBG_UCAP_NET_RECV_INFO info; ///< see ::MBG_UCAP_NET_RECV_INFO + +} MBG_UCAP_NET_RECV_INFO_IDX; + + +#define _mbg_swab_ucap_net_recv_info_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_ucap_net_recv_info( &(_p)->info ); \ +} while ( 0 ) + +/** @} defgroup ext_ucap */ @@ -4174,33 +12401,44 @@ enum /** * @brief Enumeration of protocols possibly used with PTP + * + * @see ::PTP_NW_PROT_MASKS */ -enum +enum PTP_NW_PROTS { - PTP_NW_PROT_BIT_RESERVED, //< reserved - PTP_NW_PROT_BIT_UDP_IPV4, //< IPv4 - PTP_NW_PROT_BIT_UDP_IPV6, //< IPv6 - PTP_NW_PROT_BIT_IEEE_802_3, //< Ethernet (raw layer 2) - PTP_NW_PROT_BIT_DEVICE_NET, //< DeviceNet - PTP_NW_PROT_BIT_CONTROL_NET, //< ControlNet - PTP_NW_PROT_BIT_PROFINET, //< ProfiNet - N_PTP_NW_PROT //< number of defined protocols -}; - -#define PTP_NW_PROT_MSK_RESERVED ( 1UL << PTP_NW_PROT_BIT_RESERVED ) -#define PTP_NW_PROT_MSK_UDP_IPV4 ( 1UL << PTP_NW_PROT_BIT_UDP_IPV4 ) -#define PTP_NW_PROT_MSK_UDP_IPV6 ( 1UL << PTP_NW_PROT_BIT_UDP_IPV6 ) -#define PTP_NW_PROT_MSK_IEEE_802_3 ( 1UL << PTP_NW_PROT_BIT_IEEE_802_3 ) -#define PTP_NW_PROT_MSK_DEVICE_NET ( 1UL << PTP_NW_PROT_BIT_DEVICE_NET ) -#define PTP_NW_PROT_MSK_CONTROL_NET ( 1UL << PTP_NW_PROT_BIT_CONTROL_NET ) -#define PTP_NW_PROT_MSK_PROFINET ( 1UL << PTP_NW_PROT_BIT_PROFINET ) - -#if !defined( DEFAULT_PTP_NW_PROT_MASK ) - #define DEFAULT_PTP_NW_PROT_MASK ( PTP_NW_PROT_MSK_UDP_IPV4 | PTP_NW_PROT_MSK_IEEE_802_3 ) -#endif + PTP_NW_PROT_RESERVED, ///< reserved + PTP_NW_PROT_UDP_IPV4, ///< IPv4 + PTP_NW_PROT_UDP_IPV6, ///< IPv6 + PTP_NW_PROT_IEEE_802_3, ///< Ethernet (raw layer 2) + PTP_NW_PROT_DEVICE_NET, ///< DeviceNet + PTP_NW_PROT_CONTROL_NET, ///< ControlNet + PTP_NW_PROT_PROFINET, ///< ProfiNet + N_PTP_NW_PROT ///< number of defined protocols +}; + + +/** + * @brief Bit masks for enumerated protocols possibly used with PTP + * + * @see ::PTP_NW_PROTS + */ +enum PTP_NW_PROT_MASKS +{ + PTP_NW_PROT_MSK_RESERVED = ( 1UL << PTP_NW_PROT_RESERVED ), ///< see ::PTP_NW_PROT_RESERVED + PTP_NW_PROT_MSK_UDP_IPV4 = ( 1UL << PTP_NW_PROT_UDP_IPV4 ), ///< see ::PTP_NW_PROT_UDP_IPV4 + PTP_NW_PROT_MSK_UDP_IPV6 = ( 1UL << PTP_NW_PROT_UDP_IPV6 ), ///< see ::PTP_NW_PROT_UDP_IPV6 + PTP_NW_PROT_MSK_IEEE_802_3 = ( 1UL << PTP_NW_PROT_IEEE_802_3 ), ///< see ::PTP_NW_PROT_IEEE_802_3 + PTP_NW_PROT_MSK_DEVICE_NET = ( 1UL << PTP_NW_PROT_DEVICE_NET ), ///< see ::PTP_NW_PROT_DEVICE_NET + PTP_NW_PROT_MSK_CONTROL_NET = ( 1UL << PTP_NW_PROT_CONTROL_NET ), ///< see ::PTP_NW_PROT_CONTROL_NET + PTP_NW_PROT_MSK_PROFINET = ( 1UL << PTP_NW_PROT_PROFINET ) ///< see ::PTP_NW_PROT_PROFINET +}; + + /** * @brief Name strings for the protocols possibly used with PTP + * + * @see ::PTP_NW_PROTS */ #define PTP_NW_PROT_STRS \ { \ @@ -4216,10 +12454,12 @@ enum /** * @brief Short name strings for the protocols possibly used with PTP + * + * @see ::PTP_NW_PROTS */ #define PTP_NW_PROT_STRS_SHORT \ { \ - "RES", \ + "RSV", \ "IP4", \ "IP6", \ "ETH", \ @@ -4232,19 +12472,19 @@ enum /** * @brief Possible states of a PTP port */ -enum +enum PTP_PORT_STATES { - PTP_PORT_STATE_UNINITIALIZED, //< uninitialized - PTP_PORT_STATE_INITIALIZING, //< currently initializing - PTP_PORT_STATE_FAULTY, //< faulty - PTP_PORT_STATE_DISABLED, //< disabled - PTP_PORT_STATE_LISTENING, //< listening for PTP packets - PTP_PORT_STATE_PRE_MASTER, //< going to become master - PTP_PORT_STATE_MASTER, //< master - PTP_PORT_STATE_PASSIVE, //< passive - PTP_PORT_STATE_UNCALIBRATED, //< uncalibrated - PTP_PORT_STATE_SLAVE, //< slave - N_PTP_PORT_STATE //< number of defined port states + PTP_PORT_STATE_UNINITIALIZED, ///< uninitialized + PTP_PORT_STATE_INITIALIZING, ///< currently initializing + PTP_PORT_STATE_FAULTY, ///< faulty + PTP_PORT_STATE_DISABLED, ///< disabled + PTP_PORT_STATE_LISTENING, ///< listening for PTP packets + PTP_PORT_STATE_PRE_MASTER, ///< going to become master + PTP_PORT_STATE_MASTER, ///< master + PTP_PORT_STATE_PASSIVE, ///< passive + PTP_PORT_STATE_UNCALIBRATED, ///< uncalibrated + PTP_PORT_STATE_SLAVE, ///< slave + N_PTP_PORT_STATE ///< number of defined port states }; @@ -4271,53 +12511,70 @@ enum */ typedef struct { - uint8_t value; //< the parameter value - const char *name; //< the parameter name + uint8_t value; ///< the parameter value + const char *name; ///< the parameter name + } PTP_TABLE; + /** * @brief An enumeration of PTP delay mechanisms * * @note This is different than the numeric values specified * in the published specs for IEEE1588. In addition, the specs - * define 0x14 for "disabled". + * define code 0x14 for "disabled". + * + * @see ::PTP_DELAY_MECH_MASKS + * @see ::PTP_DELAY_MECH_NAMES */ -enum +enum PTP_DELAY_MECHS { - PTP_DELAY_MECH_BIT_E2E, //< End-to-End (in PTP2 specs: 0x01) - PTP_DELAY_MECH_BIT_P2P, //< Peer-to-Peer (in PTP2 specs: 0x02) - N_PTP_DELAY_MECH //< number of defined delay mechanisms + PTP_DELAY_MECH_E2E, ///< End-to-End (in PTP2 specs: 0x01) + PTP_DELAY_MECH_P2P, ///< Peer-to-Peer (in PTP2 specs: 0x02) + N_PTP_DELAY_MECH ///< number of defined delay mechanisms }; -#define PTP_DELAY_MECH_MSK_E2E ( 1UL << PTP_DELAY_MECH_BIT_E2E ) -#define PTP_DELAY_MECH_MSK_P2P ( 1UL << PTP_DELAY_MECH_BIT_P2P ) -#if !defined( DEFAULT_PTP_DELAY_MECH_MASK ) - #define DEFAULT_PTP_DELAY_MECH_MASK ( PTP_DELAY_MECH_MSK_E2E | PTP_DELAY_MECH_MSK_P2P ) -#endif +/** + * @brief Bit masks associated with enumerated PTP delay mechanisms + * + * @see ::PTP_DELAY_MECH_MASKS + */ +enum PTP_DELAY_MECH_MASKS +{ + PTP_DELAY_MECH_MSK_E2E = ( 1UL << PTP_DELAY_MECH_E2E ), ///< see ::PTP_DELAY_MECH_E2E + PTP_DELAY_MECH_MSK_P2P = ( 1UL << PTP_DELAY_MECH_P2P ) ///< see ::PTP_DELAY_MECH_P2P +}; + + +#define PTP_DELAY_MECH_NAME_E2E "E2E" +#define PTP_DELAY_MECH_NAME_P2P "P2P" /** * @brief Name strings for the PTP delay mechanisms + * + * @see ::PTP_DELAY_MECHS */ #define PTP_DELAY_MECH_NAMES \ { \ - "E2E", \ - "P2P" \ + PTP_DELAY_MECH_NAME_E2E, \ + PTP_DELAY_MECH_NAME_P2P \ } -#define PTP_CLOCK_ACCURACY_NUM_BIAS 0x20 - /** * @brief An enumeration of accuracy classes used with PTP * * @note This enumeration does not start at 0 but with a bias - * specified by PTP_CLOCK_ACCURACY_NUM_BIAS. + * specified by ::PTP_CLOCK_ACCURACY_NUM_BIAS. + * + * @see ::PTP_CLOCK_ACCURACY_STRS */ -enum +enum PTP_CLOCK_ACCURACIES { + PTP_CLOCK_ACCURACY_NUM_BIAS = 0x20, PTP_CLOCK_ACCURACY_25ns = PTP_CLOCK_ACCURACY_NUM_BIAS, PTP_CLOCK_ACCURACY_100ns, PTP_CLOCK_ACCURACY_250ns, @@ -4341,6 +12598,8 @@ enum PTP_CLOCK_ACCURACY_RESERVED_3, PTP_CLOCK_ACCURACY_RESERVED_4, N_PTP_CLOCK_ACCURACY + //##++++ TODO: Add a code for 0xFE (unknown), or eventually + // redesign the lookup of associated strings completely. }; @@ -4348,8 +12607,10 @@ enum * @brief Name strings for PTP accuracy classes * * @note The enumeration does not start at 0 but with a bias - * specified by PTP_CLOCK_ACCURACY_NUM_BIAS, so this bias needs + * specified by ::PTP_CLOCK_ACCURACY_NUM_BIAS, so this bias needs * to be accounted for when accessing a string table. + * + * @see ::PTP_CLOCK_ACCURACIES */ #define PTP_CLOCK_ACCURACY_STRS \ { \ @@ -4381,20 +12642,27 @@ enum /** * @brief Codes to specify the type of a time source used with PTP + * + * @see ::PTP_TIME_SOURCE_TABLE */ -#define PTP_TIME_SOURCE_ATOMIC_CLOCK 0x10 -#define PTP_TIME_SOURCE_GPS 0x20 -#define PTP_TIME_SOURCE_TERRESTRIAL_RADIO 0x30 -#define PTP_TIME_SOURCE_PTP 0x40 -#define PTP_TIME_SOURCE_NTP 0x50 -#define PTP_TIME_SOURCE_HAND_SET 0x60 -#define PTP_TIME_SOURCE_OTHER 0x90 -#define PTP_TIME_SOURCE_INTERNAL_OSCILLATOR 0xA0 +enum PTP_TIME_SOURCES +{ + PTP_TIME_SOURCE_ATOMIC_CLOCK = 0x10, + PTP_TIME_SOURCE_GPS = 0x20, + PTP_TIME_SOURCE_TERRESTRIAL_RADIO = 0x30, + PTP_TIME_SOURCE_PTP = 0x40, + PTP_TIME_SOURCE_NTP = 0x50, + PTP_TIME_SOURCE_HAND_SET = 0x60, + PTP_TIME_SOURCE_OTHER = 0x90, + PTP_TIME_SOURCE_INTERNAL_OSCILLATOR = 0xA0 +}; /** * @brief A table of PTP time source codes plus associated name strings + * + * @see ::PTP_TIME_SOURCES */ #define PTP_TIME_SOURCE_TABLE \ { \ @@ -4413,41 +12681,116 @@ enum /** * @brief An enumeration of roles which can be taken by a PTP node * - * @note A role in this context specifies a certain mode of operation. + * A role in this context specifies a certain mode of operation. + * Depending on its specification a devices may not be able to take + * each of the specified roles. + * + * @note: A device in MULTICAST_AUTO role can be either master or slave, + * so the port state needs to be checked to determine the current + * mode of operation. + * + * @see ::PTP_ROLE_MASKS + * @see ::PTP_ROLE_STRS + * @see ::PTP_ROLE_STRS_SHORT + */ +enum PTP_ROLES +{ + PTP_ROLE_MULTICAST_SLAVE, ///< slave in multicast mode + PTP_ROLE_UNICAST_SLAVE, ///< slave in unicast mode + PTP_ROLE_MULTICAST_MASTER, ///< multicast master + PTP_ROLE_UNICAST_MASTER, ///< unicast master + PTP_ROLE_MULTICAST_AUTO, ///< multicast master or slave (auto selection) + PTP_ROLE_BOTH_MASTER, ///< simultanous multicast and unicast master + PTP_ROLE_NTP_SERVER, ///< NTP Unicast Server + PTP_ROLE_NTP_CLIENT, ///< NTP Unicast Client + PTP_ROLE_TIME_MONITOR, ///< Time Monitor for external PTP or NTP devices + PTP_ROLE_V1_MASTER, ///< PTPv1 Master in Multicast mode + PTP_ROLE_V1_SLAVE, ///< PTPv1 Slave in Multicast mode + N_PTP_ROLES ///< number of defined roles +}; + + +/** + * @brief Bit mask associated with ::PTP_ROLES + * + * A role in this context specifies a certain mode of operation. * Depending on its specification a devices may not be able to take * each of the specified roles. + * + * @note: A device in MULTICAST_AUTO role can be either master or slave, + * so the port state needs to be checked to determine the current + * mode of operation. + * + * @see ::PTP_ROLES + * @see ::get_supp_ptp_role_mask */ -enum +enum PTP_ROLE_MASKS { - PTP_ROLE_MULTICAST_SLAVE, //< slave in multicast mode - PTP_ROLE_UNICAST_SLAVE, //< slave in unicast mode - PTP_ROLE_MULTICAST_MASTER, //< multicast master - PTP_ROLE_UNICAST_MASTER, //< unicast master - N_PTP_ROLES //< number of defined roles + PTP_ROLE_MSK_MULTICAST_SLAVE = ( 1UL << PTP_ROLE_MULTICAST_SLAVE ), ///< see ::PTP_ROLE_MULTICAST_SLAVE + PTP_ROLE_MSK_UNICAST_SLAVE = ( 1UL << PTP_ROLE_UNICAST_SLAVE ), ///< see ::PTP_ROLE_UNICAST_SLAVE + PTP_ROLE_MSK_MULTICAST_MASTER = ( 1UL << PTP_ROLE_MULTICAST_MASTER ), ///< see ::PTP_ROLE_MULTICAST_MASTER + PTP_ROLE_MSK_UNICAST_MASTER = ( 1UL << PTP_ROLE_UNICAST_MASTER ), ///< see ::PTP_ROLE_UNICAST_MASTER + PTP_ROLE_MSK_MULTICAST_AUTO = ( 1UL << PTP_ROLE_MULTICAST_AUTO ), ///< see ::PTP_ROLE_MULTICAST_AUTO + PTP_ROLE_MSK_BOTH_MASTER = ( 1UL << PTP_ROLE_BOTH_MASTER ), ///< see ::PTP_ROLE_BOTH_MASTER + PTP_ROLE_MSK_NTP_SERVER = ( 1UL << PTP_ROLE_NTP_SERVER ), ///< see ::PTP_ROLE_NTP_SERVER + PTP_ROLE_MSK_NTP_CLIENT = ( 1UL << PTP_ROLE_NTP_CLIENT ), ///< see ::PTP_ROLE_NTP_CLIENT + PTP_ROLE_MSK_TIME_MONITOR = ( 1UL << PTP_ROLE_TIME_MONITOR ), ///< see ::PTP_ROLE_TIME_MONITOR + PTP_ROLE_MSK_V1_MASTER = ( 1UL << PTP_ROLE_V1_MASTER ), ///< see ::PTP_ROLE_MULTICAST_MASTER + PTP_ROLE_MSK_V1_SLAVE = ( 1UL << PTP_ROLE_V1_SLAVE ) ///< see ::PTP_ROLE_UNICAST_SLAVE }; +#define PTP_ROLE_MSK_SLAVES ( PTP_ROLE_MSK_MULTICAST_SLAVE \ + | PTP_ROLE_MSK_UNICAST_SLAVE \ + | PTP_ROLE_MSK_MULTICAST_AUTO ) + +#define PTP_ROLE_MSK_MASTERS ( PTP_ROLE_MSK_MULTICAST_MASTER \ + | PTP_ROLE_MSK_UNICAST_MASTER \ + | PTP_ROLE_MSK_MULTICAST_AUTO \ + | PTP_ROLE_BOTH_MASTER ) + + /** * @brief Name strings for defined PTP roles + * + * @see ::PTP_ROLES + * @see ::PTP_ROLE_STRS_SHORT */ #define PTP_ROLE_STRS \ { \ "Multicast Slave", \ "Unicast Slave", \ "Multicast Master", \ - "Unicast Master" \ + "Unicast Master", \ + "Multicast (Auto)", \ + "UC+MC Master", \ + "NTP Server", \ + "NTP Client", \ + "Time Monitor", \ + "V1 Master", \ + "V1 Slave" \ } /** * @brief Short name strings for defined PTP roles + * + * @see ::PTP_ROLES + * @see ::PTP_ROLE_STRS */ #define PTP_ROLE_STRS_SHORT \ { \ "MCS", \ "UCS", \ "MCM", \ - "UCM" \ + "UCM", \ + "MCA", \ + "UMM", \ + "NSV", \ + "NCL", \ + "MON", \ + "V1M", \ + "V1S" \ } @@ -4460,6 +12803,7 @@ enum typedef struct { uint8_t b[8]; + } PTP_CLOCK_ID; #define _mbg_swab_ptp_clock_id( _p ) _nop_macro_fnc() // nothing to swap @@ -4469,9 +12813,6 @@ typedef struct /** * @brief A PTP port ID - * - * @note This usually consists of a 6 byte MAC address with - * 2 fixed bytes inserted, or all ones as wildcard. */ typedef uint16_t PTP_PORT_ID; @@ -4481,16 +12822,84 @@ typedef uint16_t PTP_PORT_ID; /** + * @brief A PTP port identity + * + * @note For further information, see IEEE 1588-2008, chapter 5.3.5 + * + * @see ::PTP_CLOCK_ID + * @see ::PTP_PORT_ID + */ +typedef struct +{ + PTP_CLOCK_ID clock_identity; + PTP_PORT_ID port_number; + +} PTP_PORT_IDENTITY; + + +#define _mbg_swab_ptp_port_identity( _p ) \ +{ \ + _mbg_swab_ptp_clock_id( &(_p)->clock_identity ); \ + _mbg_swab_ptp_port_id( &(_p)->port_number ); \ +} + + +/** + * @brief PTP clock quality + * + * @note For further information, see IEEE 1588-2008, chapter 5.3.7 + */ +typedef struct +{ + uint8_t clock_class; ///< PTP clock class representing the current sync status + int8_t clock_accuracy; ///< see ::PTP_CLOCK_ACCURACIES + uint16_t log_variance; ///< PTP offset scaled log variance representing the time stability + +} PTP_CLOCK_QUALITY; + + +#define _mbg_swab_ptp_clock_quality( _p ) \ +{ \ + _mbg_swab8( &(_p)->clock_class ); \ + _mbg_swab8( &(_p)->clock_accuracy ); \ + _mbg_swab16( &(_p)->log_variance ); \ +} + + +/** + * @brief PTP time interval + * + * @note For further information, see IEEE 1588-2008, chapter 5.3.2 + * + */ +typedef struct +{ + int64_t scaled_nanoseconds; + +} PTP_TIME_INTERVAL; + + +#define _mbg_swab_ptp_time_interval( _p ) \ +{ \ + _mbg_swab64( &(_p)->scaled_nanoseconds ); \ +} + + +/** * @brief An enumeration of time scales used with PTP * * @note The standard time scale used by PTP is TAI, which is a linear time scale. - * The protocol provides a UTC offset to be able to convert TAI to compute UTC, which - * can observe leap seconds. For the arbitrary time scale the UTC offset is unspecified. + * The protocol provides a %UTC offset to be able to convert TAI to compute %UTC, which + * can observe leap seconds. For the arbitrary time scale the %UTC offset is unspecified, + * so arbitrary time can be %UTC, or something else. + * + * @see ::PTP_TIMESCALE_NAMES + * @see ::PTP_TIMESCALE_NAMES_SHORT */ -enum +enum PTP_TIME_SCALES { - PTP_TIMESCALE_PTP, /* default */ - PTP_TIMESCALE_ARB, + PTP_TIMESCALE_PTP, ///< PTP default, TAI + PTP_TIMESCALE_ARB, ///< arbitrary time scale, maybe %UTC N_PTP_TIMESCALE }; @@ -4510,6 +12919,9 @@ enum /** * @brief A table of name strings for the PTP time scales + * + * @see ::PTP_TIME_SCALES + * @see ::PTP_TIMESCALE_NAMES_SHORT */ #define PTP_TIMESCALE_NAMES \ { \ @@ -4519,6 +12931,9 @@ enum /** * @brief A table of short name strings for the PTP time scales + * + * @see ::PTP_TIME_SCALES + * @see ::PTP_TIMESCALE_NAMES */ #define PTP_TIMESCALE_NAMES_SHORT \ { \ @@ -4533,38 +12948,41 @@ enum */ typedef struct { - //##++++ Do we need a port identifier ?? - uint16_t nw_prot; /**< one of the enumerated protocols (@see N_PTP_NW_PROT) */ - uint8_t ptp_prot_version; /**< PTP protocol version, 1, or 2, usually 2 for v2 */ - uint8_t port_state; /**< one of the enumerated port states (@see N_PTP_PORT_STATE ) */ - uint32_t flags; /**< bit masks as defined below */ - NANO_TIME offset; /**< estimated time offset from the upstream time source */ + uint16_t nw_prot; ///< one of the enumerated protocols, see ::PTP_NW_PROTS + uint8_t ptp_prot_version; ///< PTP protocol version, 1, or 2, usually 2 for v2 + uint8_t port_state; ///< one of the enumerated port states, see ::PTP_PORT_STATES + uint32_t flags; ///< see ::PTP_STATE_FLAGS + NANO_TIME offset; ///< estimated time offset from the upstream time source NANO_TIME path_delay; NANO_TIME mean_path_delay; NANO_TIME delay_asymmetry; - PTP_CLOCK_ID gm_id; /**< identifier ot the upstream time source */ + PTP_CLOCK_ID gm_id; ///< identifier ot the upstream time source uint16_t clock_offset_scaled_log_variance; uint8_t clock_class; - uint8_t clock_accuracy; /**< one of the enumerated accuracy class codes (@see N_PTP_CLOCK_ACCURACY) */ + uint8_t clock_accuracy; ///< see ::PTP_CLOCK_ACCURACIES - uint32_t reserved_1; /**< reserved, currently always 0 */ - uint32_t reserved_2; /**< reserved, currently always 0 */ + uint32_t tsu_secs; ///< current seconds value of time stamp unit + uint32_t reserved_2; ///< reserved, currently always 0 - uint8_t domain_number; /**< the PTP clock domain number, 0:3 */ - uint8_t time_source; /**< one of the defined codes PTP_TIME_SOURCE_... */ - uint8_t delay_mech; /**< PTP_DELAY_MECH_BIT_E2E or PTP_DELAY_MECH_BIT_P2P */ + uint8_t domain_number; ///< the PTP clock domain number, 0:3 + uint8_t time_source; ///< see ::PTP_TIME_SOURCES + uint8_t delay_mech; ///< see ::PTP_DELAY_MECHS int8_t log_delay_req_intv; - int16_t utc_offset; /**< UTC offset observed against TAI */ - DAC_VAL osc_dac_cal; /**< disiplination value of the oscillator */ + int16_t utc_offset; ///< %UTC offset observed against TAI + DAC_VAL osc_dac_cal; ///< disciplination value of the oscillator - uint32_t reserved_3; /**< reserved, currently always 0 */ + uint8_t parent_clock_class; ///< clock class of the parent node + uint8_t parent_clock_accuracy; ///< clock accuracy of the parent node, see ::PTP_CLOCK_ACCURACIES + + uint16_t reserved_3; ///< reserved, currently always 0 } PTP_STATE; #define _mbg_swab_ptp_state( _p ) \ +do \ { \ _mbg_swab16( &(_p)->nw_prot ); \ _mbg_swab32( &(_p)->flags ); \ @@ -4574,65 +12992,48 @@ typedef struct _mbg_swab_nano_time( &(_p)->delay_asymmetry ); \ _mbg_swab_ptp_clock_id( &(_p)->gm_id ); \ _mbg_swab16( &(_p)->clock_offset_scaled_log_variance ); \ - _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->tsu_secs ); \ _mbg_swab32( &(_p)->reserved_2 ); \ _mbg_swab16( &(_p)->utc_offset ); \ _mbg_swab_dac_val( &(_p)->osc_dac_cal ); \ - _mbg_swab32( &(_p)->reserved_3 ); \ -} + _mbg_swab16( &(_p)->reserved_3 ); \ +} while ( 0 ) /** - * @brief Flag bits used with PTP_STATE::flags + * @brief Flags bits used with PTP_STATE::flags + * + * @see ::PTP_STATE_FLAG_MASKS */ -enum +enum PTP_STATE_FLAGS { - PTP_FLAG_BIT_SLAVE_ONLY, /**< the port can only be slave */ - PTP_FLAG_BIT_IS_SLAVE, /**< the port is currently slave */ - PTP_FLAG_BIT_TIMESCALE_IS_PTP, /**< the timescale is PTP standard, not arbitrary */ - PTP_FLAG_BIT_LS_ANN, /**< a leap second is being announced */ - PTP_FLAG_BIT_LS_ANN_NEG, /**< the announced leap second is negative */ - PTP_FLAG_BIT_IS_UNICAST, /**< the port currently operates in unicast mode */ - N_PTP_FLAG_BIT /**< the number of defined flag bits */ + PTP_FLAG_SLAVE_ONLY, ///< the port can only be slave + PTP_FLAG_IS_SLAVE, ///< the port is currently slave + PTP_FLAG_TIMESCALE_IS_PTP, ///< the timescale is PTP standard, not arbitrary + PTP_FLAG_LS_ANN, ///< a leap second is being announced + PTP_FLAG_LS_ANN_NEG, ///< the announced leap second is negative + PTP_FLAG_IS_UNICAST, ///< the port currently operates in unicast mode + PTP_FLAG_UTC_VALID, ///< %UTC parameters are valid + PTP_FLAG_ONE_STEP, ///< One-Step Clock active + N_PTP_STATE_FLAGS ///< the number of defined flag bits }; -#define PTP_FLAG_MSK_SLAVE_ONLY ( 1UL << PTP_FLAG_BIT_SLAVE_ONLY ) -#define PTP_FLAG_MSK_IS_SLAVE ( 1UL << PTP_FLAG_BIT_IS_SLAVE ) -#define PTP_FLAG_MSK_TIMESCALE_IS_PTP ( 1UL << PTP_FLAG_BIT_TIMESCALE_IS_PTP ) -#define PTP_FLAG_MSK_LS_ANN ( 1UL << PTP_FLAG_BIT_LS_ANN ) -#define PTP_FLAG_MSK_LS_ANN_NEG ( 1UL << PTP_FLAG_BIT_LS_ANN_NEG ) -#define PTP_FLAG_MSK_IS_UNICAST ( 1UL << PTP_FLAG_BIT_IS_UNICAST ) - - - -#define PTP_SYNC_INTERVAL_MIN -6 -#define PTP_SYNC_INTERVAL_MAX 6 - -#define PTP_DELAY_REQ_INTERVAL_MIN -6 -#define PTP_DELAY_REQ_INTERVAL_MAX 6 - -#define PTP_DEFAULT_UNICAST_SYNC_INTERVAL_MIN -4 -#define PTP_DEFAULT_UNICAST_SYNC_INTERVAL_MAX 4 - -#define PTP_DEFAULT_UNICAST_DELAY_REQ_INTERVAL_MIN -4 -#define PTP_DEFAULT_UNICAST_DELAY_REQ_INTERVAL_MAX 4 - -#define PTP_DEFAULT_UNICAST_ANNOUNCE_INTERVAL_MIN -4 -#define PTP_DEFAULT_UNICAST_ANNOUNCE_INTERVAL_MAX 4 - /** - * @defgroup group_ptp_uc_msg_duration_limits Unicast PTP masters send messages - * to a unicast slave only for a given interval as requested by the particular - * slave, which is called message duration. These symbols define the minimum and - * maximum message duration configured on a slave for a specific unicast master, - * i.e. for PTP_UC_MASTER_SETTINGS::message_duration. - * @{ */ - -#define PTP_UC_MSG_DURATION_MIN 10 //< minimum message duration [s] -#define PTP_UC_MSG_DURATION_MAX 1000 //< maximum message duration [s] -#define PTP_UC_MSG_DURATION_DEFAULT 60 //< default, though the specs say 300 s - -/** @} group_ptp_uc_msg_duration_limits */ + * @brief Flags masks used with PTP_STATE::flags + * + * @see ::PTP_STATE_FLAGS + */ +enum PTP_STATE_FLAG_MASKS +{ + PTP_FLAG_MSK_SLAVE_ONLY = ( 1UL << PTP_FLAG_SLAVE_ONLY ), ///< see ::PTP_FLAG_SLAVE_ONLY + PTP_FLAG_MSK_IS_SLAVE = ( 1UL << PTP_FLAG_IS_SLAVE ), ///< see ::PTP_FLAG_IS_SLAVE + PTP_FLAG_MSK_TIMESCALE_IS_PTP = ( 1UL << PTP_FLAG_TIMESCALE_IS_PTP ), ///< see ::PTP_FLAG_TIMESCALE_IS_PTP + PTP_FLAG_MSK_LS_ANN = ( 1UL << PTP_FLAG_LS_ANN ), ///< see ::PTP_FLAG_LS_ANN + PTP_FLAG_MSK_LS_ANN_NEG = ( 1UL << PTP_FLAG_LS_ANN_NEG ), ///< see ::PTP_FLAG_LS_ANN_NEG + PTP_FLAG_MSK_IS_UNICAST = ( 1UL << PTP_FLAG_IS_UNICAST ), ///< see ::PTP_FLAG_IS_UNICAST + PTP_FLAG_MSK_UTC_VALID = ( 1UL << PTP_FLAG_UTC_VALID ), ///< see ::PTP_FLAG_UTC_VALID + PTP_FLAG_MSK_ONE_STEP = ( 1UL << PTP_FLAG_ONE_STEP ) ///< see ::PTP_FLAG_ONE_STEP +}; @@ -4641,76 +13042,89 @@ enum */ typedef struct { - //##++++ Do we need a port identifier ?? - uint16_t nw_prot; /**< one of the enumerated and supported protocols (@see N_PTP_NW_PROT) */ - uint8_t profile; /**< PTP profile, currently only 0 = default */ - uint8_t domain_number; /**< the PTP clock domain number, 0:3 */ + uint16_t nw_prot; ///< see ::PTP_NW_PROTS + uint8_t selected_presets; ///< selected PTP presets, see ::PTP_PRESETS + uint8_t domain_number; ///< the PTP clock domain number, 0:3 - uint8_t delay_mech; /**< PTP_DELAY_MECH_BIT_E2E or PTP_DELAY_MECH_BIT_P2P, if supported */ - uint8_t ptp_role; /**< one of the enumerated PTP roles (@see N_PTP_ROLES) */ - uint8_t priority_1; /**< priority 1 */ - uint8_t priority_2; /**< priority 2 */ + uint8_t delay_mech; ///< see ::PTP_DELAY_MECHS + uint8_t ptp_role; ///< one of the supported PTP roles, see ::PTP_ROLES + uint8_t priority_1; ///< priority 1 + uint8_t priority_2; ///< priority 2 uint8_t dflt_clk_class_unsync_cold; // 6:255 uint8_t dflt_clk_class_unsync_warm; // 6:255 uint8_t dflt_clk_class_sync_cold; // 6:255 uint8_t dflt_clk_class_sync_warm; // 6:255 - uint8_t reserved_1; /**< reserved, currently always 0 */ - uint8_t reserved_2; /**< reserved, currently always 0 */ - int16_t sync_intv; /**< log2 of the sync interval [s] */ + uint8_t ann_rcpt_timeout; ///< announce msg. receipt timeout, see ::PTP_ANN_RCPT_TIMEOUT_LIMITS + uint8_t opt_ext; ///< optional configuration extension, see ::PTP_OPT_EXTS + int16_t sync_intv; ///< log2 of the sync interval [s] - int16_t ann_intv; /**< log2 of the announce interval [s] */ - int16_t delay_req_intv; /**< log2 of the delay request interval [s] */ + int16_t ann_intv; ///< log2 of the announce interval [s] + int16_t delay_req_intv; ///< log2 of the delay request interval [s] - uint32_t upper_bound; /**< sync state set to false if above this limit [ns] */ - uint32_t lower_bound; /**< sync state set to true if below this limit [ns] */ + uint32_t upper_bound; ///< sync state set to false if above this limit [ns] + uint32_t lower_bound; ///< sync state set to true if below this limit [ns] - uint32_t reserved_3; /**< reserved, currently always 0 */ - uint32_t flags; /**< bit masks as defined below */ + uint32_t reserved; ///< reserved, currently always 0 + uint32_t flags; ///< see @ref PTP_CFG_FLAG_MASKS } PTP_CFG_SETTINGS; -#define _mbg_swab_ptp_cfg_settings( _p ) \ -{ \ - _mbg_swab16( &(_p)->nw_prot ); \ - _mbg_swab16( &(_p)->sync_intv ); \ - _mbg_swab16( &(_p)->ann_intv ); \ - _mbg_swab16( &(_p)->delay_req_intv ); \ - _mbg_swab32( &(_p)->upper_bound ); \ - _mbg_swab32( &(_p)->lower_bound ); \ - _mbg_swab32( &(_p)->reserved_3 ); \ - _mbg_swab32( &(_p)->flags ); \ -} +#define _mbg_swab_ptp_cfg_settings( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->nw_prot ); \ + _mbg_swab16( &(_p)->sync_intv ); \ + _mbg_swab16( &(_p)->ann_intv ); \ + _mbg_swab16( &(_p)->delay_req_intv ); \ + _mbg_swab32( &(_p)->upper_bound ); \ + _mbg_swab32( &(_p)->lower_bound ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Possible values for PTP_CFG_SETTINGS::ann_rcpt_timeout + */ +enum PTP_ANN_RCPT_TIMEOUT_LIMITS +{ + PTP_ANN_RCPT_TIMEOUT_MIN = 2, + PTP_ANN_RCPT_TIMEOUT_MAX = 8, + DEFAULT_PTP_ANN_RCPT_TIMEOUT = 3 +}; /** - * @brief A structure to used to query the current configurration and capabilities of a PTP port + * @brief A structure to used to query the current configuration and capabilities of a PTP port */ typedef struct { - PTP_CFG_SETTINGS settings; /**< the current configuration */ + PTP_CFG_SETTINGS settings; ///< the current configuration - uint8_t ptp_proto_version; /**< PTP protocol version, 1, or 2, usually 2 for v2 */ - uint8_t reserved_1; /**< reserved, currently always 0 */ - uint16_t reserved_2; /**< reserved, currently always 0 */ + uint8_t ptp_proto_version; ///< PTP protocol version, 1, or 2, usually 2 for v2 + uint8_t reserved_1; ///< reserved, currently always 0 + uint16_t reserved_2; ///< reserved, currently always 0 - int16_t sync_intv_min; /**< log2 of minimum sync interval [s] */ - int16_t sync_intv_max; /**< log2 of maximum sync interval [s] */ - int16_t ann_intv_min; /**< log2 of minimum announce interval [s] */ - int16_t ann_intv_max; /**< log2 of maximum announce interval [s] */ - int16_t delay_req_intv_min; /**< log2 of minimum delay request interval [s] */ - int16_t delay_req_intv_max; /**< log2 of maximum delay request interval [s] */ + int16_t sync_intv_min; ///< log2 of minimum sync interval [s] + int16_t sync_intv_max; ///< log2 of maximum sync interval [s] + int16_t ann_intv_min; ///< log2 of minimum announce interval [s] + int16_t ann_intv_max; ///< log2 of maximum announce interval [s] + int16_t delay_req_intv_min; ///< log2 of minimum delay request interval [s] + int16_t delay_req_intv_max; ///< log2 of maximum delay request interval [s] - uint32_t supp_flags; /**< a bit mask of supported features (see below) */ - uint32_t supp_nw_prot; /**< a bit mask of supported network protocols */ - uint32_t supp_profiles; /**< a bit mask of supported profiles */ - uint32_t supp_delay_mech; /**< a bit mask of supported delay mechanisms */ + uint32_t supp_flags; ///< a bit mask of supported features, see @ref PTP_CFG_FLAG_MASKS + uint32_t supp_nw_prot; ///< a bit mask of supported network protocols, see ::PTP_NW_PROT_MASKS + uint32_t supp_opt_ext; ///< a bit mask of supported optional extensions, see ::PTP_OPT_EXT_MASKS + uint32_t supp_delay_mech; ///< a bit mask of supported delay mechanisms, see ::PTP_DELAY_MECH_MASKS } PTP_CFG_INFO; #define _mbg_swab_ptp_cfg_info( _p ) \ +do \ { \ _mbg_swab_ptp_cfg_settings( &(_p)->settings ); \ _mbg_swab16( &(_p)->reserved_2 ); \ @@ -4722,62 +13136,772 @@ typedef struct _mbg_swab16( &(_p)->delay_req_intv_max ); \ _mbg_swab32( &(_p)->supp_flags ); \ _mbg_swab32( &(_p)->supp_nw_prot ); \ - _mbg_swab32( &(_p)->supp_profiles ); \ + _mbg_swab32( &(_p)->supp_opt_ext ); \ _mbg_swab32( &(_p)->supp_delay_mech ); \ -} +} while ( 0 ) /** - * @brief Flags used with PTP_CFG_SETTINGS::flags and PTP_CFG_INFO::supp_flags + * @brief Flags bits used with PTP configuration + * + * Flags labeled [R/-] can only be used with ::PTP_CFG_INFO::supp_flags + * to indicate that the associated feature is supported in general. + * + * If a flag labeled [R/W] is set in ::PTP_CFG_INFO::supp_flags then + * this flag can also be used with ::PTP_CFG_SETTINGS::flags to control + * the associated feature. + * + * @note Originally, all devices supported the multicast slave role, so + * there was no extra flag to indicate this. However, some newer devices + * may not support the multicast slave role, so two new flags have been + * introduced to cope with this: + * If ::PTP_CFG_SUPP_MCAST_SLAVE_FLAG is set then a different flag + * ::PTP_CFG_CAN_BE_MULTICAST_SLAVE needs to be checked to tell if + * the multicast slave role is supported, or not. + * If ::PTP_CFG_SUPP_MCAST_SLAVE_FLAG is not set then the device + * definitely supports the multicast slave role. + * + * @see @ref PTP_CFG_FLAG_MASKS */ -enum +enum PTP_CFG_FLAGS { - PTP_CFG_BIT_TIME_SCALE_IS_PTP, /**< time scale is PTP/TAI, else arbitrary */ - PTP_CFG_BIT_V1_HW_COMPAT, /**< maybe required for certain NIC chips, not used by Meinberg */ - PTP_CFG_BIT_CAN_BE_UNICAST_SLAVE, /**< the PTP port can take the role of a unicast slave */ - PTP_CFG_BIT_CAN_BE_MULTICAST_MASTER, /**< the PTP port can take the role of a multicast master */ - PTP_CFG_BIT_CAN_BE_UNICAST_MASTER, /**< the PTP port can take the role of a unicast master */ - N_PTP_CFG_BIT /**< the number of defined bits */ + PTP_CFG_TIME_SCALE_IS_PTP, ///< [R/W] time scale is PTP/TAI, else arbitrary + PTP_CFG_V1_HW_COMPAT, ///< [R/W] maybe required for certain NIC chips, not used by Meinberg + PTP_CFG_CAN_BE_UNICAST_SLAVE, ///< [R/-] supports unicast slave role, see ::PTP_ROLE_UNICAST_SLAVE + PTP_CFG_CAN_BE_MULTICAST_MASTER, ///< [R/-] supports multicast master role, see ::PTP_ROLE_MULTICAST_MASTER + PTP_CFG_CAN_BE_UNICAST_MASTER, ///< [R/-] supports unicast master, see ::PTP_ROLE_UNICAST_MASTER + PTP_CFG_CAN_BE_MULTICAST_AUTO, ///< [R/-] can automatically become multicast master or slave, see ::PTP_CFG_CAN_BE_MULTICAST_AUTO + PTP_CFG_SUPP_UTC_VALID, ///< [R/-] ::PTP_FLAG_UTC_VALID bit in ::PTP_STATE::flags is supported + PTP_CFG_CAN_BE_BOTH_MASTER, ///< [R/-] supports unicast and multicast master role at the same time, see ::PTP_CFG_CAN_BE_BOTH_MASTER + + PTP_CFG_HYBRID_MASTER, ///< [R/W] supports hybrid mode in master roles + PTP_CFG_HYBRID_SLAVE, ///< [R/W] supports hybrid mode in slave roles + PTP_CFG_ONE_STEP_MASTER, ///< [R/W] supports one-step mode in master roles + PTP_CFG_MNGMNT_MSGS_DISB, ///< [R/W] supports disabling of PTP management messages + PTP_CFG_SUPP_MCAST_SLAVE_FLAG, ///< [R/-] indicates that ::PTP_CFG_CAN_BE_MULTICAST_SLAVE flag is supported and can be checked + PTP_CFG_CAN_BE_MULTICAST_SLAVE, ///< [R/-] if ::PTP_CFG_SUPP_MCAST_SLAVE_FLAG bit set, indicates if multicast slave role is supported + PTP_CFG_ONE_STEP_L2, ///< [R/-] supports the combination of One-Step and Layer2 mode + PTP_CFG_ONE_STEP_P2P, ///< [R/-] supports the combination of One-Step and P2P Delay Mechanism + + PTP_CFG_TSU_RESET, ///< [R/-] supports TSU reset via register cmd + PTP_CFG_NTP_HW_TS_MASTER, ///< [R/-] supports the NTP HW time stamping in Master mode + PTP_CFG_NTP_HW_TS_SLAVE, ///< [R/-] supports the NTP HW time stamping in Slave mode + PTP_CFG_SYNCE_MASTER, ///< [R/-] Hardware supports Synchronous Ethernet Out + PTP_CFG_SYNCE_SLAVE, ///< [R/-] Hardware supports Synchronous Ethernet In + PTP_CFG_HAS_MUX, ///< [R/-] Hardware supports multiplexed signal outputs + PTP_CFG_CAN_BE_TIME_MONITOR, ///< [R/-] can be Monitoring device for external PTP or NTP devices //### TODO Shouldn't this be an XFEATURE flag? + PTP_CFG_HAS_STATISTICS, ///< [R/-] ::MBG_PTP_STATISTICS_INFO can be queried + + PTP_CFG_CAN_BE_V1_MASTER, ///< [R/-] supports PTPv1 MASTER role + PTP_CFG_CAN_BE_V1_SLAVE, ///< [R/-] supports PTPv1 SLAVE role + PTP_CFG_HAS_V2_COMMON_DATASETS, ///< [R/-] PTPv2 common dataset structures (see IEEE1588-2008, chapter 8.2) can be queried + PTP_CFG_HAS_V1_COMMON_DATASETS, ///< [R/-] PTPv1 common dataset structures can be queried + + N_PTP_CFG_FLAGS ///< the number of defined flags }; -#define PTP_CFG_MSK_TIME_SCALE_IS_PTP ( 1UL << PTP_CFG_BIT_TIME_SCALE_IS_PTP ) -#define PTP_CFG_MSK_V1_HW_COMPAT ( 1UL << PTP_CFG_BIT_V1_HW_COMPAT ) -#define PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE ( 1UL << PTP_CFG_BIT_CAN_BE_UNICAST_SLAVE ) -#define PTP_CFG_MSK_CAN_BE_MULTICAST_MASTER ( 1UL << PTP_CFG_BIT_CAN_BE_MULTICAST_MASTER ) -#define PTP_CFG_MSK_CAN_BE_UNICAST_MASTER ( 1UL << PTP_CFG_BIT_CAN_BE_UNICAST_MASTER ) - -#define PTP_CFG_MSK_SUPPORT_PTP_ROLES ( PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE | \ - PTP_CFG_MSK_CAN_BE_MULTICAST_MASTER | \ - PTP_CFG_MSK_CAN_BE_UNICAST_MASTER ) +/** + * @defgroup group_PTP_CFG_FLAG_MASKS Bit masks used with PTP_CFG_INFO::supp_flags and PTP_CFG_SETTINGS::flags + * + * @see ::PTP_CFG_INFO::supp_flags + * @see ::PTP_CFG_SETTINGS::flags + * @see ::PTP_CFG_FLAGS + * + * @anchor PTP_CFG_FLAG_MASKS + * + * @{ */ +#define PTP_CFG_MSK_TIME_SCALE_IS_PTP ( 1UL << PTP_CFG_TIME_SCALE_IS_PTP ) ///< see ::PTP_CFG_TIME_SCALE_IS_PTP +#define PTP_CFG_MSK_V1_HW_COMPAT ( 1UL << PTP_CFG_V1_HW_COMPAT ) ///< see ::PTP_CFG_V1_HW_COMPAT +#define PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE ( 1UL << PTP_CFG_CAN_BE_UNICAST_SLAVE ) ///< see ::PTP_CFG_CAN_BE_UNICAST_SLAVE +#define PTP_CFG_MSK_CAN_BE_MULTICAST_MASTER ( 1UL << PTP_CFG_CAN_BE_MULTICAST_MASTER ) ///< see ::PTP_CFG_CAN_BE_MULTICAST_MASTER +#define PTP_CFG_MSK_CAN_BE_UNICAST_MASTER ( 1UL << PTP_CFG_CAN_BE_UNICAST_MASTER ) ///< see ::PTP_CFG_CAN_BE_UNICAST_MASTER +#define PTP_CFG_MSK_CAN_BE_MULTICAST_AUTO ( 1UL << PTP_CFG_CAN_BE_MULTICAST_AUTO ) ///< see ::PTP_CFG_CAN_BE_MULTICAST_AUTO +#define PTP_CFG_MSK_SUPP_UTC_VALID ( 1UL << PTP_CFG_SUPP_UTC_VALID ) ///< see ::PTP_CFG_SUPP_UTC_VALID +#define PTP_CFG_MSK_CAN_BE_BOTH_MASTER ( 1UL << PTP_CFG_CAN_BE_BOTH_MASTER ) ///< see ::PTP_CFG_CAN_BE_BOTH_MASTER + +#define PTP_CFG_MSK_HYBRID_MASTER ( 1UL << PTP_CFG_HYBRID_MASTER ) ///< see ::PTP_CFG_HYBRID_MASTER +#define PTP_CFG_MSK_HYBRID_SLAVE ( 1UL << PTP_CFG_HYBRID_SLAVE ) ///< see ::PTP_CFG_HYBRID_SLAVE +#define PTP_CFG_MSK_ONE_STEP_MASTER ( 1UL << PTP_CFG_ONE_STEP_MASTER ) ///< see ::PTP_CFG_ONE_STEP_MASTER +#define PTP_CFG_MSK_MNGMNT_MSGS_DISB ( 1UL << PTP_CFG_MNGMNT_MSGS_DISB ) ///< see ::PTP_CFG_MNGMNT_MSGS_DISB +#define PTP_CFG_MSK_SUPP_MCAST_SLAVE_FLAG ( 1UL << PTP_CFG_SUPP_MCAST_SLAVE_FLAG ) ///< see ::PTP_CFG_SUPP_MCAST_SLAVE_FLAG +#define PTP_CFG_MSK_CAN_BE_MULTICAST_SLAVE ( 1UL << PTP_CFG_CAN_BE_MULTICAST_SLAVE ) ///< see ::PTP_CFG_CAN_BE_MULTICAST_SLAVE +#define PTP_CFG_MSK_ONE_STEP_L2 ( 1UL << PTP_CFG_ONE_STEP_L2 ) ///< see ::PTP_CFG_ONE_STEP_L2 +#define PTP_CFG_MSK_ONE_STEP_P2P ( 1UL << PTP_CFG_ONE_STEP_P2P ) ///< see ::PTP_CFG_ONE_STEP_P2P + +#define PTP_CFG_MSK_TSU_RESET ( 1UL << PTP_CFG_TSU_RESET ) ///< see ::PTP_CFG_TSU_RESET +#define PTP_CFG_MSK_NTP_HW_TS_MASTER ( 1UL << PTP_CFG_NTP_HW_TS_MASTER ) ///< see ::PTP_CFG_NTP_HW_TS_MASTER +#define PTP_CFG_MSK_NTP_HW_TS_SLAVE ( 1UL << PTP_CFG_NTP_HW_TS_SLAVE) ///< see ::PTP_CFG_NTP_HW_TS_SLAVE +#define PTP_CFG_MSK_SYNCE_MASTER ( 1UL << PTP_CFG_SYNCE_MASTER ) ///< see ::PTP_CFG_SYNCE_MASTER +#define PTP_CFG_MSK_SYNCE_SLAVE ( 1UL << PTP_CFG_SYNCE_SLAVE ) ///< see ::PTP_CFG_SYNCE_SLAVE +#define PTP_CFG_MSK_HAS_MUX ( 1UL << PTP_CFG_HAS_MUX ) ///< see ::PTP_CFG_HAS_MUX +#define PTP_CFG_MSK_CAN_BE_TIME_MONITOR ( 1UL << PTP_CFG_CAN_BE_TIME_MONITOR ) ///< see ::PTP_CFG_CAN_BE_TIME_MONITOR +#define PTP_CFG_MSK_HAS_STATISTICS ( 1UL << PTP_CFG_HAS_STATISTICS ) ///< see ::PTP_CFG_HAS_STATISTICS + +#define PTP_CFG_MSK_CAN_BE_V1_MASTER ( 1UL << PTP_CFG_CAN_BE_V1_MASTER ) ///< see ::PTP_CFG_CAN_BE_V1_MASTER +#define PTP_CFG_MSK_CAN_BE_V1_SLAVE ( 1UL << PTP_CFG_CAN_BE_V1_SLAVE ) ///< see ::PTP_CFG_CAN_BE_V1_SLAVE +#define PTP_CFG_MSK_HAS_V2_COMMON_DATASETS ( 1UL << PTP_CFG_HAS_V2_COMMON_DATASETS ) ///< see ::PTP_CFG_HAS_V2_COMMON_DATASETS +#define PTP_CFG_MSK_HAS_V1_COMMON_DATASETS ( 1UL << PTP_CFG_HAS_V1_COMMON_DATASETS ) ///< see ::PTP_CFG_HAS_V1_COMMON_DATASETS + +/** @} defgroup group_PTP_CFG_FLAG_MASKS */ + + + +/** @brief A bit mask of the unicast role bits within the flag bits */ #define PTP_CFG_MSK_SUPPORT_PTP_UNICAST ( PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE | \ PTP_CFG_MSK_CAN_BE_UNICAST_MASTER ) + + +/** + * @brief Register in TSU-GbE FPGA to determine board features of the current TSU board revision + */ +typedef uint16_t PTP_HW_FEATURES; + + + +/** + * @brief Bits used to define ::PTP_HW_FEAT_MASKS + */ +enum PTP_HW_FEAT_BITS +{ + PTP_FEAT_SYNCE_EXT_MUX, ///< [R] supports SyncE and external signal multiplexer + N_PTP_HW_FEAT ///< the number of defined features +}; + + +// TODO fix comment linkage /** - * @brief Derive a "supported PTP roles" bit mask from PTP_CFG_INFO::supp_flags + * @brief Bit masks used with ::PTP_HW_FEATURES * - * There's no explicite flag to indicate that the role of a multicast slave - * is supported, since this role is always supported. The sequence of flags - * indicating that a specific optional role is supported matches the enumerated - * roles above, but don't start at bit 0. So we compine the optional flag bits - * with the LSB always set for the implicite multicast slave role to yield - * a bit mask which according to the enumerated roles. + * @see ::PTP_HW_FEAT_BITS */ -#define _get_supp_ptp_role_idx_msk( _f ) \ - ( 1UL | ( ( (_f) & PTP_CFG_MSK_SUPPORT_PTP_ROLES ) >> ( PTP_CFG_BIT_CAN_BE_UNICAST_SLAVE - 1 ) ) ) -//##+++++++++ #define _get_supp_ptp_roles( _r ) ((((_r) & ~3UL) >> PTP_CFG_BIT_V1_HW_COMPAT ) | 1UL) +enum PTP_HW_FEAT_MASKS +{ + PTP_HW_FEAT_MSK_SYNCE_EXT_MUX = ( 1UL << PTP_FEAT_SYNCE_EXT_MUX ) ///< see ::PTP_FEAT_SYNCE_EXT_MUX +}; + /** - * @brief A host's fully qualified domain name (FQDN), or a numeric IP address string + * @brief Known optional PTP protocol extensions, see ::PTP_CFG_SETTINGS::opt_ext * - * In theory each single component (host name, domain name, top level domain name) - * of a FQDN can have up to 63 characters, but the overall length is limited to - * 255 characters. We specify one more character for the trailing 0. + * @see ::PTP_OPT_EXT_MASKS + */ +enum PTP_OPT_EXTS +{ + PTP_OPT_EXT_NONE, ///< no extension used + PTP_OPT_EXT_POWER, ///< IEEE C37.238-2011 profile extension + PTP_OPT_EXT_TELECOM, ///< ITU-T G.8265.1 profile extension + PTP_OPT_EXT_TELECOM_PHASE, ///< ITU-T G.8275.1 profile extension + PTP_OPT_EXT_SMPTE, ///< SMPTE ST 2059-2 profile extension + PTP_OPT_EXT_8021AS, ///< IEEE 802.1AS profile extension + PTP_OPT_EXT_6185093, ///< IEC/IEEE FDIS 61850-9-3 Power Utility profile extension + PTP_OPT_EXT_TELECOM_PTS, ///< ITU-T G.8275.2 profile extension + N_PTP_OPT_EXT ///< number of known optional extensions +}; + + +/** + * @brief Flag masks used with ::PTP_CFG_INFO::supp_opt_ext + * + * @see ::PTP_OPT_EXTS + */ +enum PTP_OPT_EXT_MASKS +{ + PTP_MSK_OPT_EXT_NONE = ( 1UL << PTP_OPT_EXT_NONE ), ///< this is actually not used, see ::PTP_OPT_EXT_NONE + PTP_MSK_OPT_EXT_POWER = ( 1UL << PTP_OPT_EXT_POWER ), ///< see ::PTP_OPT_EXT_POWER + PTP_MSK_OPT_EXT_TELECOM = ( 1UL << PTP_OPT_EXT_TELECOM ), ///< see ::PTP_OPT_EXT_TELECOM + PTP_MSK_OPT_EXT_TELECOM_PHASE = ( 1UL << PTP_OPT_EXT_TELECOM_PHASE ), ///< see ::PTP_OPT_EXT_TELECOM_PHASE + PTP_MSK_OPT_EXT_SMPTE = ( 1UL << PTP_OPT_EXT_SMPTE ), ///< see ::PTP_OPT_EXT_SMPTE + PTP_MSK_OPT_EXT_8021AS = ( 1UL << PTP_OPT_EXT_8021AS ), ///< see ::PTP_OPT_EXT_8021AS + PTP_MSK_OPT_EXT_6185093 = ( 1UL << PTP_OPT_EXT_6185093 ), ///< see ::PTP_OPT_EXT_6185093 + PTP_MSK_OPT_EXT_TELECOM_PTS = ( 1UL << PTP_OPT_EXT_TELECOM_PTS ) ///< see ::PTP_OPT_EXT_TELECOM_PTS +}; + + + +/** + * @brief Enumeration of PTP cfg presets used with ::PTP_CFG_SETTINGS::selected_presets + * + * This can be used by configuration programs to determine + * the last recently selected presets. + * + * @see ::PTP_PRESETS_STRS + * @see ::PTP_PRESETS_MASKS + */ +enum PTP_PRESETS +{ + PTP_PRESETS_CUSTOM, ///< customizable, always supported + PTP_PRESETS_DFLT_E2E, ///< pure IEEE1588-2008 (PTPv2) with E2E + PTP_PRESETS_DFLT_P2P, ///< pure IEEE1588-2008 (PTPv2) with P2P + PTP_PRESETS_POWER, ///< IEEE C37.238 profile extension, only if ::PTP_MSK_OPT_EXT_POWER is set + PTP_PRESETS_TELECOM, ///< ITU-T G.8265.1 profile extension, only if ::PTP_MSK_OPT_EXT_TELECOM is set + PTP_PRESETS_TELECOM_PHASE, ///< ITU-T G.8275.1 profile extension, only if ::PTP_MSK_OPT_EXT_TELECOM_PHASE is set + PTP_PRESETS_SMPTE, ///< SMPTE ST 2059-2 profile extension, only if ::PTP_MSK_OPT_EXT_SMPTE is set + PTP_PRESETS_AES67, ///< AES67 media profile + PTP_PRESETS_8021AS, ///< IEEE 802.1AS -like profile, only if ::PTP_MSK_OPT_EXT_8021AS is set + PTP_PRESETS_6185093, ///< IEC/IEEE FDIS 61850-9-3, only if ::PTP_MSK_OPT_EXT_6185093 is set + PTP_PRESETS_TELECOM_PTS, ///< ITU-T G.8275.2 profile extension, only if ::PTP_MSK_OPT_EXT_TELECOM_PTS is set + PTP_PRESETS_DOCSIS_31, ///< only if ::PTP_MSK_OPT_EXT_TELECOM_PHASE is set + N_PTP_PRESETS ///< number of supported presets +}; + + +/** + * @brief Flag masks used with ::PTP_CFG_INFO::supp_opt_ext + * + * @see ::PTP_PRESETS + */ +enum PTP_PRESETS_MASKS +{ + PTP_MSK_PRESETS_CUSTOM = ( 1UL << PTP_PRESETS_CUSTOM ), ///< see ::PTP_PRESETS_CUSTOM + PTP_MSK_PRESETS_DFLT_E2E = ( 1UL << PTP_PRESETS_DFLT_E2E ), ///< see ::PTP_PRESETS_DFLT_E2E + PTP_MSK_PRESETS_DFLT_P2P = ( 1UL << PTP_PRESETS_DFLT_P2P ), ///< see ::PTP_PRESETS_DFLT_P2P + PTP_MSK_PRESETS_POWER = ( 1UL << PTP_PRESETS_POWER ), ///< see ::PTP_PRESETS_POWER + PTP_MSK_PRESETS_TELECOM = ( 1UL << PTP_PRESETS_TELECOM ), ///< see ::PTP_PRESETS_TELECOM + PTP_MSK_PRESETS_TELECOM_PHASE = ( 1UL << PTP_PRESETS_TELECOM_PHASE ), ///< see ::PTP_PRESETS_TELECOM_PHASE + PTP_MSK_PRESETS_SMPTE = ( 1UL << PTP_PRESETS_SMPTE ), ///< see ::PTP_PRESETS_SMPTE + PTP_MSK_PRESETS_AES67 = ( 1UL << PTP_PRESETS_AES67 ), ///< see ::PTP_PRESETS_AES67 + PTP_MSK_PRESETS_8021AS = ( 1UL << PTP_PRESETS_8021AS ), ///< see ::PTP_PRESETS_8021AS + PTP_MSK_PRESETS_6185093 = ( 1UL << PTP_PRESETS_6185093), ///< see ::PTP_PRESETS_6185093 + PTP_MSK_PRESETS_TELECOM_PTS = ( 1UL << PTP_PRESETS_TELECOM_PTS), ///< see ::PTP_PRESETS_TELECOM_PTS + PTP_MSK_PRESETS_DOCSIS_31 = ( 1UL << PTP_PRESETS_DOCSIS_31) ///< see ::PTP_PRESETS_DOCSIS_31 +}; + + +/** + * @brief Name strings for defined PTP presets + * + * @see ::PTP_PRESETS + */ +#define PTP_PRESETS_STRS \ +{ \ + "Custom", \ + "Default E2E IEEE1588-2008", \ + "Default P2P IEEE1588-2008", \ + "Power IEEE C37.238", \ + "Telecom ITU-T G.8265.1", \ + "Telecom ITU-T G.8275.1", \ + "SMPTE ST 2059-2", \ + "AES67 Media Profile", \ + "IEEE 802.1AS", \ + "Utility IEC 61850-9-3", \ + "Telecom ITU-T G.8275.2", \ + "DOCSIS 3.1" \ +} + + + +/** + * @brief Additional parameters for Power Profile + */ +#define PTP_POWER_PROFILE_GM_ID_MIN 3 +#define PTP_POWER_PROFILE_GM_ID_MAX 255 + +typedef struct +{ + uint32_t network_incaccuracy; ///< Pre-defined network inaccuracy from master in [ns] + uint8_t grandmaster_id; ///< [::PTP_POWER_PROFILE_GM_ID_MIN..::PTP_POWER_PROFILE_GM_ID_MAX] + uint8_t reserved_1; + uint16_t reserved_2; + TZDL tzdl; + +} PTP_POWER_PROFILE_CFG; + +#define _mbg_swab_ptp_power_profile_cfg( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->network_incaccuracy ); \ + _mbg_swab8( &(_p)->grandmaster_id ); \ + _mbg_swab8( &(_p)->reserved_1 ); \ + _mbg_swab16( &(_p)->reserved_2 ); \ + _mbg_swab_tzdl( &(_p)->tzdl ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +#if defined( _PRELIMINARY_CODE ) + +// TODO: These definitions are preliminary and maybe subject to changes. + +/** + * @brief SMPTE System Frame Rates according to SMPTE ST 2059-2 + * + * @see ::TODO + */ +enum SMPTE_SYSTEM_FRAME_RATES +{ + SMPTE_23_98HZ, + SMPTE_24HZ, + SMPTE_25HZ, + SMPTE_29_97HZ, + SMPTE_50HZ, + SMPTE_59_94HZ, + N_SMPTE_SYSTEM_FRAME_RATES +}; + + +#define SMPTE_SYSTEM_FRAME_RATE_STR \ +{ \ + "24Hz (23.98)", \ + "24Hz", \ + "25Hz", \ + "30Hz (29.97)", \ + "50Hz", \ + "60Hz (59.94)" \ +} + + +#define SMPTE_FRAME_RATE_NUM \ +{ \ + 24000, \ + 24000, \ + 25000, \ + 30000, \ + 50000, \ + 60000, \ +} + +#define SMPTE_FRAME_RATE_DENUM \ +{ \ + 1001, \ + 1000, \ + 1000, \ + 1001, \ + 1000, \ + 1001, \ +} + + +/** + * @brief Additional parameters for SMPTE ST 2059-2 profile + * + * This stucture holds the synchronization metadata required for the SMPTE profile. + * This structure is only used for internal storage of the data. The data is + * distributed through a network by using management messages and the dedicated + * organization extension TLV defined in the SMPTE profile. + */ +typedef struct +{ + /// Default system frame rate + /// Default video frame rate of the slave system as a lowest term rational. + /// The data type shall be composed of a pair of unsigned Int32 values coded + /// in big-endian form where the first shall be the numerator and the second + /// shall be the denominator. The denominator shall be the smallest value + /// that represents the frame rate denominator + /// For example, 29.97 Hz: (30000/1001) or 25 Hz: (25/1). + uint32_t defaultSystemFrameRateNum; + uint32_t defaultSystemFrameRateDenum; + /// Master locking status + /// Complementary information to clockClass (0: Not in use, 1: Free Run, + /// 2: Cold Locking, 3: Warm Locking, 4: Locked) + uint8_t masterLockingStatus; + /// Time Address Flags + /// Indicates the intended ST 12-1 flags. + /// Bit 0: Drop frame (0: Non-drop-frame, 1: Drop-frame) + /// Bit 1: Color Frame Identification (0: Not in use, 1: In use) + /// Bits 2-7: Reserved + uint8_t timeAddressFlags; + /// Current local offset + /// Offset in seconds of Local Time from grandmaster PTP time. For example, + /// if Local Time is Eastern Standard Time (North America) UTC-5 and the + /// number of leap seconds is 35, the value will be -18035 (decimal). + + uint8_t reserved_1; + uint8_t reserved_2; + + int32_t currentLocalOffset; + /// Jump seconds + /// The size of the next discontinuity, in seconds, of Local Time. A value + /// of zero indicates that no discontinuity is expected. A positive value + /// indicates that the discontinuity will cause the currentLocalOffset to increase. + int32_t jumpSeconds; + /// Time of next jump + /// The value of the seconds portion of the grandmastermaster PTP time at the time + /// that the next discontinuity of the currentLocalOffset will occur. The + /// discontinuity occurs at the start of the second indicated + uint8_t timeOfNextJump[6]; + /// Time of next jam + /// The value of the seconds portion of the PTP time corresponding to the next + /// scheduled occurrence of the Daily Jam. If no Daily Jam is scheduled, the + /// value of timeOfNextJam shall be zero. + uint8_t timeOfNextJam[6]; + /// Time of previous jam + /// The value of the seconds portion of the PTP time corresponding to the + /// previous occurrence of the Daily Jam. + uint8_t timeOfPreviousJam[6]; + /// Previous jam local offset + /// The value of currentLocalOffset at the previous daily jam time. + /// If a discontinuity of Local Time occurs at the jam time, this parameter + /// reflects the offset after the discontinuity. + uint8_t reserved_3; + uint8_t reserved_4; + uint32_t reserved_5; + + int32_t previousJamLocalOffset; + /// Daylight saving + /// Bit 0: Current Daylight Saving (0: Not in effect, 1: In effect) + /// Bit 1: Daylight Saving at next discontinuity (0: Not in effect, 1: In effect) + /// Bit 2: Daylight Saving at previous daily jam time (0: Not in effect, 1: In effect) + /// Bits 3-7: Reserved + uint8_t daylightSaving; + /// Leap second jump + /// The reason for the forthcoming discontinuity of currentLocalOffset indicated by + /// timeOfNextJump + /// Bit 0: + /// 0: Other than a change in the number of leap seconds (default) + /// 1: A change in number of leap seconds + /// Bits 1-7: Reserved + uint8_t leapSecondJump; + + uint8_t reserved_6; + uint8_t reserved_7; + + uint32_t reserved_8; + uint32_t reserved_9; + uint32_t reserved_10; + +} PTP_SMPTE_PROFILE_CFG; + + + +/** + * @brief Additional parameters for Telecom8275.1 profile + */ +typedef struct +{ + uint8_t use_alternate_multicast_address; + uint8_t reserved_1; + uint8_t reserved_2; + uint8_t reserved_3; + uint32_t reserved_4; + +} PTP_TELECOMG8275_PROFILE_CFG; + +#define _mbg_swab_ptp_telecom8275_profile_cfg( _p ) \ +do \ +{ \ + _mbg_swab8( &(_p)->use_alternate_multicast_mac_address ); \ + _mbg_swab8( &(_p)->reserved_1 ); \ + _mbg_swab8( &(_p)->reserved_2 ); \ + _mbg_swab8( &(_p)->reserved_3 ); \ + _mbg_swab32( &(_p)->reserved_4 ); \ +} while ( 0 ) + + + +/** + * @brief A type which holds one of the ITU-T SSM codes + * + * @see ::ITU_SSM_CODES + */ +typedef uint16_t ITU_SSM_CODE; + + + +/** + * @brief ITU-T SSM codes acc. to Recommendation G.781 + * + * @see ::ITU_SSM_CODE + */ +enum ITU_SSM_CODES +{ + ITU_SSM_CODE_STU_UKN, + ITU_SSM_CODE_PRS, + ITU_SSM_CODE_PRC, + ITU_SSM_CODE_INV3, + ITU_SSM_CODE_SSU_A_TNC, + ITU_SSM_CODE_INV5, + ITU_SSM_CODE_INV6, + ITU_SSM_CODE_ST2, + ITU_SSM_CODE_SSU_B, + ITU_SSM_CODE_INV9, + ITU_SSM_CODE_ST3, + ITU_SSM_CODE_SEC, + ITU_SSM_CODE_SMC, + ITU_SSM_CODE_ST3E, + ITU_SSM_CODE_PROV, + ITU_SSM_CODE_DNU_DUS, + N_ITU_SSM_CODES +}; + + +#define N_SSM_CODES_OPTION_1 5 +#define N_SSM_CODES_OPTION_2 9 + + +/** + * @brief Name strings for SSM codes, network option I + * + * @see ::ITU_SSM_CODES + */ +#define ITU_SSM_CODE_OPT_1_STRS \ +{ \ + "", \ + "", \ + "QL-PRC", \ + "", \ + "QL-SSU-A", \ + "", \ + "", \ + "", \ + "QL-SSU-B", \ + "", \ + "", \ + "QL-SEC", \ + "", \ + "", \ + "", \ + "QL-DNU" \ +} + + + +/** + * @brief Name strings for SSM codes, network option II + * + * @see ::ITU_SSM_CODES + */ +#define ITU_SSM_CODE_OPT_2_STRS \ +{ \ + "QL-STU", \ + "QL-PRS", \ + "", \ + "", \ + "QL-TNC", \ + "", \ + "", \ + "QL-ST2", \ + "", \ + "", \ + "QL-ST3", \ + "", \ + "QL-SMC", \ + "QL-ST3E", \ + "QL-PROV", \ + "QL-DUS" \ +} + + + +/** + * @brief Name strings for SSM codes, option I and II combined + * + * @see ::ITU_SSM_CODES + */ +#define ITU_SSM_CODE_STRS_COMBINED \ +{ \ + "QL-STU/UKN", \ + "QL-PRS", \ + "QL-PRC", \ + "QL-INV3", \ + "QL-SSU-A/TNC", \ + "QL-INV5", \ + "QL-INV6", \ + "QL-ST2", \ + "QL-SSU-B", \ + "QL-INV9", \ + "QL-EEC2/ST3", \ + "QL-EEC1/SEC", \ + "QL-SMC", \ + "QL-ST3E", \ + "QL-PROV", \ + "QL-DNU/DUS", \ +} + + + +/** + * @brief Maximum T1 SSM only quality levels + * + * @see ::T1_SSM_QLVL + * @see ::T1_SSM_QLVL_STRS + * @see ::T1_SSM_QLVL_ARRAY + */ +#define MAX_T1_SSM_QLVL 8 + + + +/** + * @brief T1 SSM only quality level (6 bit encoded) + * + * @see ::MAX_T1_SSM_QLVL + * @see ::T1_SSM_QLVL_STRS + * @see ::T1_SSM_QLVL_ARRAY + */ +enum T1_SSM_QLVL +{ + T1_SSM_QLVL_ST1_TRACE = 2, + T1_SSM_QLVL_SYNC_TRACE_UNKNOWN = 4, + T1_SSM_QLVL_ST2_TRACE = 6, + T1_SSM_QLVL_ST3_TRACE = 8, + T1_SSM_QLVL_SONET_MIN_CLOCK_TRACE = 17, + T1_SSM_QLVL_ST4_TRACE = 20, + T1_SSM_QLVL_DNU_FOR_SYNC = 24, + T1_SSM_QLVL_RESERVED = 32 +}; + + + +/** + * @brief T1 SSM only quality level array + * + * @see ::MAX_T1_SSM_QLVL + * @see ::T1_SSM_QLVL_STRS + * @see ::T1_SSM_QLVL + */ +#define T1_SSM_QLVL_ARRAY \ +{ \ + T1_SSM_QLVL_ST1_TRACE, \ + T1_SSM_QLVL_SYNC_TRACE_UNKNOWN, \ + T1_SSM_QLVL_ST2_TRACE, \ + T1_SSM_QLVL_ST3_TRACE, \ + T1_SSM_QLVL_SONET_MIN_CLOCK_TRACE, \ + T1_SSM_QLVL_ST4_TRACE, \ + T1_SSM_QLVL_DNU_FOR_SYNC, \ + T1_SSM_QLVL_RESERVED \ +} + + + +/** + * @brief Name strings for T1 SSM quality levels + * + * @see ::MAX_T1_SSM_QLVL + * @see ::T1_SSM_QLVL + * @see ::T1_SSM_QLVL_ARRAY + */ +#define T1_SSM_QLVL_STRS \ +{ \ + "Stratum 1 traceable", \ + "Synchronized traceability unknown", \ + "Stratum 2 traceable", \ + "Stratum 3 traceable", \ + "SONET minimum clock traceable", \ + "Stratum 4 traceable", \ + "Do not use for sync", \ + "Reserved for network sync" \ +} + + + +/** + * @brief SDH network options + * + * @see ::SDH_NETWORK_OPTION_MASKS + */ +enum SDH_NETWORK_OPTIONS +{ + SDH_NETWORK_OPTION_1, + SDH_NETWORK_OPTION_2, + N_SDH_NETWORK_OPTIONS + +}; + + + +/** + * @brief Flag masks used with MBG_SYNC_E_INFO::supp_sdh_network_opts ::FIXME + * + * @see ::SDH_NETWORK_OPTIONS + */ +enum SDH_NETWORK_OPTION_MASKS +{ + SDH_NETWORK_OPTION_1_MSK = ( 1UL << SDH_NETWORK_OPTION_1 ), ///< see ::SDH_NETWORK_OPTION_1 + SDH_NETWORK_OPTION_2_MSK = ( 1UL << SDH_NETWORK_OPTION_2 ), ///< see ::SDH_NETWORK_OPTION_2 +}; + + + +/** + * @brief Name strings for SDH network options + * + * @see ::SDH_NETWORK_OPTIONS + */ +#define SDH_NETWORK_OPTION_STRS \ +{ \ + "SDH Network Opt. 1", \ + "SDH Network Opt. 2", \ +} + + + +//##++++ TODO: shouldn't this be merged with / replaced by MBG_NET_LINK_MODES? +/** + * @brief Link modes for SyncE on a 1000BASE-T interface + * + * @see ::GBIT_LINK_COPPER_MODE_MASKS + */ +enum GBIT_LINK_COPPER_MODES +{ + GBIT_LINK_COPPER_AUTO, // valid if synce is disabled + GBIT_LINK_COPPER_FORCE_SYNCE_AUTO, + GBIT_LINK_COPPER_FORCE_OR_IS_MASTER, // Used in both structures, settings and status + GBIT_LINK_COPPER_FORCE_OR_IS_SLAVE, // Used in both structures, settings and status + GBIT_LINK_COPPER_PREFER_MASTER, + GBIT_LINK_COPPER_PREFER_SLAVE, + N_GBIT_LINK_COPPER_MODES +}; + + + +/** + * @brief Flag masks used with MBG_SYNC_E_INFO::supp_gbit_link_copper_modes ::FIXME + * + * @see ::GBIT_LINK_COPPER_MODES */ -typedef char MBG_HOSTNAME[256]; +enum GBIT_LINK_COPPER_MODE_MASKS +{ + GBIT_LINK_COPPER_AUTO_MSK = ( 1UL << GBIT_LINK_COPPER_AUTO ), ///< see ::GBIT_LINK_COPPER_AUTO_MSK + GBIT_LINK_COPPER_FORCE_SYNCE_AUTO_MSK = ( 1UL << GBIT_LINK_COPPER_FORCE_SYNCE_AUTO ), ///< see ::GBIT_LINK_COPPER_FORCE_SYNCE_AUTO + GBIT_LINK_COPPER_FORCE_OR_IS_MASTER_MSK = ( 1UL << GBIT_LINK_COPPER_FORCE_OR_IS_MASTER ), ///< see ::GBIT_LINK_COPPER_FORCE_OR_IS_MASTER + GBIT_LINK_COPPER_FORCE_OR_IS_SLAVE_MSK = ( 1UL << GBIT_LINK_COPPER_FORCE_OR_IS_SLAVE ), ///< see ::GBIT_LINK_COPPER_FORCE_OR_IS_SLAVE + GBIT_LINK_COPPER_PREFER_MASTER_MSK = ( 1UL << GBIT_LINK_COPPER_PREFER_MASTER ), ///< see ::GBIT_LINK_COPPER_PREFER_MASTER + GBIT_LINK_COPPER_PREFER_SLAVE_MSK = ( 1UL << GBIT_LINK_COPPER_PREFER_SLAVE ) ///< see ::GBIT_LINK_COPPER_PREFER_SLAVE +}; + + + +//##++++ TODO: shouldn't this be merged with MBG_NET_LINK_ROLE_BITS / MBG_NET_LINK_ROLE_MASKS? +/** + * @brief Link status for SyncE on a 1000BASE-T interface + * + * @see ::TODO + */ +enum GBIT_LINK_STATUS +{ + GBIT_LINK_COPPER_IS_MASTER, ///< GBIT Link is currently clock master + GBIT_LINK_COPPER_IS_SLAVE, ///< GBIT Link is currently clock slave + GBIT_LINK_COPPER_CFG_FAULT, ///< GBIT Link has a configruation fault (conflict with link partner + GBIT_LINK_COPPER_IS_FE, ///< Link is running on Fast Ethernet (no MASTER/SLAVE decision) + GBIT_LINK_DOWN, ///< Currently no link + GBIT_LINK_FIBER, ///< GBIT Linkup on SFP interface + N_GBIT_LINK_STATUS +}; + + +#define GBIT_LINK_STATUS_STRS \ +{ \ + "MASTER (1000BASE-T)", \ + "SLAVE (1000BASE-T)", \ + "CFG FAULT", \ + "AUTO (100BASE-TX)", \ + "LINK DOWN", \ + "AUTO (SFP LINK UP)", \ +} + +#else // !defined( _PRELIMINARY_CODE ), dummy declarations + +typedef int PTP_SMPTE_PROFILE_CFG; +typedef int PTP_TELECOMG8275_PROFILE_CFG; +typedef int ITU_SSM_CODE; + +#endif // defined( _PRELIMINARY_CODE ) + /** @@ -4785,20 +13909,21 @@ typedef char MBG_HOSTNAME[256]; */ typedef struct { - uint16_t n_supp_master; /**< number of unicast masters which can be specified */ - int16_t sync_intv_min; /**< log2 of minimum sync interval [s] */ - int16_t sync_intv_max; /**< log2 of maximum sync interval [s] */ - int16_t ann_intv_min; /**< log2 of minimum announce interval [s] */ - int16_t ann_intv_max; /**< log2 of maximum announce interval [s] */ - int16_t delay_req_intv_min; /**< log2 of minimum delay request interval [s] */ - int16_t delay_req_intv_max; /**< log2 of maximum delay request interval [s] */ - uint16_t reserved_0; /**< reserved, currently always 0 */ - uint32_t supp_flags; /**< a bit mask indicating which flags are supported */ - uint32_t reserved_1; /**< reserved, currently always 0 */ + uint16_t n_supp_master; ///< number of unicast masters which can be specified + int16_t sync_intv_min; ///< log2 of minimum sync interval [s] + int16_t sync_intv_max; ///< log2 of maximum sync interval [s] + int16_t ann_intv_min; ///< log2 of minimum announce interval [s] + int16_t ann_intv_max; ///< log2 of maximum announce interval [s] + int16_t delay_req_intv_min; ///< log2 of minimum delay request interval [s] + int16_t delay_req_intv_max; ///< log2 of maximum delay request interval [s] + uint16_t reserved_0; ///< reserved, currently always 0 + uint32_t supp_flags; ///< a bit mask indicating which flags are supported + uint32_t reserved_1; ///< reserved, currently always 0 } PTP_UC_MASTER_CFG_LIMITS; #define _mbg_swab_ptp_uc_master_cfg_limits( _p ) \ +do \ { \ _mbg_swab16( &(_p)->n_supp_master ); \ _mbg_swab16( &(_p)->sync_intv_min ); \ @@ -4810,34 +13935,39 @@ typedef struct _mbg_swab16( &(_p)->reserved_0 ); \ _mbg_swab32( &(_p)->supp_flags ); \ _mbg_swab32( &(_p)->reserved_1 ); \ -} +} while ( 0 ) + /** - * @brief Specification of unicast masters + * @brief Configuration settings specifiying how to query a PTP unicast master * * This structure is used on a unicast slave to specify the settings of * a unicast master polled by the slave. The number of unicast masters * which can be specified depends on the capabilities of the slave device - * and is returned in PTP_UC_MASTER_CFG_LIMITS::n_supp_master. + * and is returned in ::PTP_UC_MASTER_CFG_LIMITS::n_supp_master. + * + * The structure ::PTP_UC_MASTER_SETTINGS_IDX should be sent to the device + * to save the configuration. */ typedef struct { - MBG_HOSTNAME gm_host; /**< grandmaster's hostname or IP address */ - PTP_CLOCK_ID gm_clock_id; /**< use clock ID of master port, or PTP_CLOCK_ID_WILDCARD */ - PTP_PORT_ID gm_port_id; /**< use target port ID of master port (e.g. 135) or PTP_PORT_ID_WILDCARD */ - int16_t sync_intv; /**< sync interval [log2 s] */ - int16_t ann_intv; /**< announce interval [log2 s] */ - int16_t delay_req_intv; /**< delay request interval [log2 s]*/ - int32_t fix_offset; /**< constant time offset to be compensated [ns] */ - uint16_t message_duration; /**< time period until master stops sending messages [s] */ - uint16_t reserved_0; /**< reserved, currently always 0 */ - uint32_t reserved_1; /**< reserved, currently always 0 */ - uint32_t flags; /**< bit masks as specified below */ + MBG_HOSTNAME gm_host; ///< grandmaster's hostname or IP address + PTP_CLOCK_ID gm_clock_id; ///< use clock ID of master port, or ::PTP_CLOCK_ID_WILDCARD + PTP_PORT_ID gm_port_id; ///< use target port ID of master port (e.g. 135) or ::PTP_PORT_ID_WILDCARD + int16_t sync_intv; ///< sync interval [log2 s] + int16_t ann_intv; ///< announce interval [log2 s] + int16_t delay_req_intv; ///< delay request interval [log2 s] + int32_t fix_offset; ///< constant time offset to be compensated [ns] + uint16_t message_duration; ///< time period until master stops sending messages [s] + uint16_t reserved_0; ///< reserved, currently always 0 + uint32_t reserved_1; ///< reserved, currently always 0 + uint32_t flags; ///< reserved, currently always 0 } PTP_UC_MASTER_SETTINGS; #define _mbg_swab_ptp_uc_master_settings( _p ) \ +do \ { \ _mbg_swab_ptp_clock_id( &(_p)->gm_clock_id ); \ _mbg_swab_ptp_port_id( &(_p)->gm_port_id ); \ @@ -4849,176 +13979,4200 @@ typedef struct _mbg_swab16( &(_p)->reserved_0 ); \ _mbg_swab32( &(_p)->reserved_1 ); \ _mbg_swab32( &(_p)->flags ); \ -} +} while ( 0 ) + + + +/** + * @brief Unicast PTP master message duration limits + * + * Each unicast PTP master sends messages to a unicast slave only + * for a given interval as requested by the particular slave, which + * is called message duration. + * These symbols define the minimum and maximum message duration + * configured on a slave for a specific unicast master, i.e. for + * PTP_UC_MASTER_SETTINGS::message_duration. The values are defined + * in the PTP v2 standard. + */ +enum PTP_UC_MSG_DURATION_LIMITS +{ + PTP_UC_MSG_DURATION_MIN = 10, ///< minimum message duration [s] + PTP_UC_MSG_DURATION_MAX = 1000 ///< maximum message duration [s] +}; + /** - * @brief Specification of a certain unicast master + * @brief Configuration settings for a specific PTP unicast master */ typedef struct { - uint32_t idx; /**< index, 0..(PTP_UC_MASTER_CFG_LIMITS::n_supp_master - 1) */ - PTP_UC_MASTER_SETTINGS settings; /**< specification for the unicast master with that index */ + uint32_t idx; ///< index, 0..PTP_UC_MASTER_CFG_LIMITS::n_supp_master-1 + PTP_UC_MASTER_SETTINGS settings; ///< specification for the unicast master with that index } PTP_UC_MASTER_SETTINGS_IDX; #define _mbg_swab_ptp_uc_master_settings_idx( _p ) \ +do \ { \ _mbg_swab32( &(_p)->idx ); \ _mbg_swab_ptp_uc_master_settings( &(_p)->settings ); \ -} +} while ( 0 ) + /** - * @brief Capabilities and current settings of a unicast master + * @brief Current settings and general capabilities of a unicast master + * + * This structure is used with a PTP unicast slave device to specify + * a PTP unicast master which can be queried by the slave device. */ typedef struct { - PTP_UC_MASTER_SETTINGS settings; /**< current settings */ - uint32_t reserved; /**< reserved, currently always 0 */ - uint32_t flags; /**< reserved, currently always 0 */ + PTP_UC_MASTER_SETTINGS settings; ///< current settings + uint32_t reserved; ///< reserved, currently always 0 + uint32_t flags; ///< reserved, currently always 0 } PTP_UC_MASTER_INFO; #define _mbg_swab_ptp_uc_master_info( _p ) \ +do \ { \ _mbg_swab_ptp_uc_master_settings( &(_p)->settings ); \ _mbg_swab32( &(_p)->reserved ); \ _mbg_swab32( &(_p)->flags ); \ -} +} while ( 0 ) + /** - * @brief Capabilities and current settings of a specific unicast master + * @brief Current settings and general capabilities of a specific unicast master + * + * This structure is used with a PTP unicast slave device to specify + * a PTP unicast master which can be queried by the slave device. + * + * This structure should be read from the device to retrieve the + * current settings and capabilities. The number of supported + * configuration records is PTP_UC_MASTER_CFG_LIMITS::n_supp_master. + * + * @note The ::PTP_UC_MASTER_SETTINGS_IDX structure should be send back + * to the device to save the configuration. */ typedef struct { - uint32_t idx; /**< index, 0..(PTP_UC_MASTER_CFG_LIMITS::n_supp_master - 1) */ - PTP_UC_MASTER_INFO info; /**< capabilities and current settings */ + uint32_t idx; ///< index, 0..PTP_UC_MASTER_CFG_LIMITS::n_supp_master-1 + PTP_UC_MASTER_INFO info; ///< capabilities and current settings } PTP_UC_MASTER_INFO_IDX; #define _mbg_swab_ptp_uc_master_info_idx( _p ) \ +do \ { \ _mbg_swab32( &(_p)->idx ); \ _mbg_swab_ptp_uc_master_info( &(_p)->info ); \ +} while ( 0 ) + + + +typedef struct +{ + uint32_t counter_cfg; + uint32_t flags; + uint32_t reserved_1; + uint32_t reserved_2; + +} MBG_PTP_STATISTICS_SETTINGS; + + + +typedef struct +{ + MBG_PTP_STATISTICS_SETTINGS settings; + uint32_t supp_flags; ///< Supported settings, currently 0 + uint32_t reserved_1; + +} MBG_PTP_STATISTICS_INFO; + + + +typedef struct +{ + uint32_t status; ///< status word flags (use PacketCounterStat_e) + uint32_t rx; ///< overall Rx packet counter + uint32_t rxPerSec; ///< overall Rx packet counter + uint32_t tx; ///< overall Tx packet counter + uint32_t txPerSec; ///< overall Tx packet counter + /// invalid Rx packet counter + /// Indicates one of the following issues: wrong PTP version, wrong domain number, + /// message from self, message from other BC port, multicast message in unicast mode + /// or message extraction error (size error or inconsistent format). + uint32_t errorRx; + uint32_t announceMsgRx; ///< Accepted Announce message Rx counter + uint32_t announceMsgPerSecRx; ///< Accepted Announce message Rx counter + uint32_t announceMsgTx; ///< Announce message Tx counter + uint32_t announceMsgPerSecTx; ///< Announce message Tx counter + uint32_t syncMsgRx; ///< Accepted Sync message Rx counter + uint32_t syncMsgPerSecRx; ///< Accepted Sync message Rx counter + uint32_t syncMsgTx; ///< Sync message Tx counter + uint32_t syncMsgPerSecTx; ///< Sync message Tx counter + uint32_t followUpMsgRx; ///< Accepted Follow-up message Rx counter + uint32_t followUpMsgPerSecRx; ///< Accepted Follow-up message Rx counter + uint32_t followUpMsgTx; ///< Follow-up message Tx counter + uint32_t followUpMsgPerSecTx; ///< Follow-up message Tx counter + uint32_t dlyReqMsgRx; ///< Accepted Delay request message Rx counter + uint32_t dlyReqMsgPerSecRx; ///< Accepted Delay request message Rx counter + uint32_t dlyReqMsgTx; ///< Delay request message Tx counter + uint32_t dlyReqMsgPerSecTx; ///< Delay request message Tx counter + uint32_t dlyRespMsgRx; ///< Accepted Delay response message Rx counter + uint32_t dlyRespMsgPerSecRx; ///< Accepted Delay response message Rx counter + uint32_t dlyRespMsgTx; ///< Delay response message Tx counter + uint32_t dlyRespMsgPerSecTx; ///< Delay response message Tx counter + uint32_t pDlyReqMsgRx; ///< Accepted PDelay Request message Rx counter + uint32_t pDlyReqMsgPerSecRx; ///< Accepted PDelay Request message Rx counter + uint32_t pDlyReqMsgTx; ///< PDelay Request message Tx counter + uint32_t pDlyReqMsgPerSecTx; ///< PDelay Request message Tx counter + uint32_t pDlyRespMsgRx; ///< Accepted PDelay Response message Rx counter + uint32_t pDlyRespMsgPerSecRx; ///< Accepted PDelay Response message Rx counter + uint32_t pDlyRespMsgTx; ///< PDelay Response message Tx counter + uint32_t pDlyRespMsgPerSecTx; ///< PDelay Response message Tx counter + uint32_t pDlyFollowUpRx; ///< Accepted PDelay Follow-Up message Rx counter + uint32_t pDlyFollowUpPerSecRx; ///< Accepted PDelay Follow-Up message Rx counter + uint32_t pDlyFollowUpTx; ///< PDelay Follow-Up message Tx counter + uint32_t pDlyFollowUpPerSecTx; ///< PDelay Follow-Up message Tx counter + uint32_t signallingRx; ///< Accepted Signalling message Rx counter + uint32_t signallingPerSecRx; ///< Accepted Signalling message Rx counter + uint32_t signallingTx; ///< Signalling message Tx counter + uint32_t signallingPerSecTx; ///< Signalling message Tx counter + uint32_t mgmtRx; ///< Accepted Management message Rx counter + uint32_t mgmtPerSecRx; ///< Accepted Management message Rx counter + uint32_t mgmtTx; ///< Management message Tx counter + uint32_t mgmtPerSecTx; ///< Management message Tx counter + uint32_t mgmtErr; ///< Management error counter (rx) + uint32_t annReceptTout; ///< Announce recept timeout count + + uint32_t numUcConn; ///< Number of current Unicast client connections + uint32_t maxNumUcConn; ///< Maximum Number of Unicast client connections (due to licence or CPU performance) + uint32_t numMsgPerSec; ///< Number of all messages per second (TX/RX) + uint32_t maxMsgPerSec; ///< max allowed number of all messages per second in Multicast/Hybrid mode (due to licence or CPU performance) + +} MBG_PTP_STATISTICS_STATUS; + + + +enum PTP_V1_COMM_IDS +{ + V1_PTP_CLOSED, + V1_PTP_ETHER, + /* reserved */ + V1_PTP_FFBUS = 4, + V1_PTP_PROFIBUS, + V1_PTP_LON, + V1_PTP_DNET, + V1_PTP_SDS, + V1_PTP_CONTROLNET, + V1_PTP_CANOPEN, + /* reserved */ + V1_PTP_IEEE1394 = 243, + V1_PTP_IEEE802_11A, + V1_PTP_IEEE_WIRELESS, + V1_PTP_INFINIBAND, + V1_PTP_BLUETOOTH, + V1_PTP_IEEE802_15_1, + V1_PTP_IEEE1451_3, + V1_PTP_IEEE1451_5, + V1_PTP_USB, + V1_PTP_ISA, + V1_PTP_PCI, + V1_PTP_VXI, + V1_PTP_DEFAULT +}; + + + +#define PTP_CODE_STRING_LENGTH 4 +#define PTP_SUBDOMAIN_NAME_LENGTH 16 + + +/** + * @brief PTPv1 UUID structure used in ::MBG_PTP_V1_DEFAULT_DATASET + * + * @see ::MBG_PTP_V1_DEFAULT_DATASET + */ +typedef struct +{ + uint8_t communication_technology; + uint8_t reserved_1; + uint16_t reserved_2; + PTP_CLOCK_ID clock_uuid; + PTP_PORT_ID port_id; + uint16_t reserved_3; +} PTP_V1_UUID; + + +#define _mbg_swab_ptp_v1_uuid( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->reserved_2 ); \ + _mbg_swab_ptp_clock_id( &(_p)->clock_uuid ); \ + _mbg_swab_ptp_port_id( &(_p)->port_id ); \ + _mbg_swab16( &(_p)->reserved_3 ); \ +} while ( 0 ) + + + +/** + * @brief PTPv1 default dataset flags + * + * @see ::PTP_V1_DEFAULT_DATASET_FLAGS_MASKS + */ +enum PTP_V1_DEFAULT_DATASET_FLAGS +{ + V1_DFLT_CLK_FOLLOWUP_CAPABLE, + V1_DFLT_PREFERRED, + V1_DFLT_INITIALIZABLE, + V1_DFLT_EXT_TIMING, + V1_DFLT_IS_BC +}; + + + +/** + * @brief PTPv1 default dataset flag masks used with ::MBG_PTP_V1_DEFAULT_DATASET::flags + * + * @see ::PTP_V1_DEFAULT_DATASET_FLAGS + */ +enum PTP_V1_DEFAULT_DATASET_FLAGS_MASKS +{ + V1_DFLT_MSK_CLK_FOLLOWUP_CAPABLE = ( 1UL << V1_DFLT_CLK_FOLLOWUP_CAPABLE ), ///< see ::V1_DFLT_CLK_FOLLOWUP_CAPABLE + V1_DFLT_MSK_PREFERRED = ( 1UL << V1_DFLT_PREFERRED ), ///< see ::V1_DFLT_PREFERRED + V1_DFLT_MSK_INITIALIZABLE = ( 1UL << V1_DFLT_INITIALIZABLE ), ///< see ::V1_DFLT_INITIALIZABLE + V1_DFLT_MSK_EXT_TIMING = ( 1UL << V1_DFLT_EXT_TIMING), ///< see ::V1_DFLT_EXT_TIMING + V1_DFLT_MSK_IS_BC = ( 1UL << V1_DFLT_IS_BC ) ///< see ::V1_DFLT_IS_BC +}; + + + +/** + * @brief PTPv1 default dataset containing global information about the device + * + * @see ::PTP_V1_UUID + */ +typedef struct { + PTP_V1_UUID uuid; + uint8_t clock_stratum; + uint8_t clock_identifier[PTP_CODE_STRING_LENGTH]; + uint16_t clock_variance; + int8_t sync_interval; + uint8_t subdomain_name[PTP_SUBDOMAIN_NAME_LENGTH]; + uint16_t number_ports; + uint16_t number_foreign_records; + uint32_t flags; +} MBG_PTP_V1_DEFAULT_DATASET; + + +#define _mbg_swab_ptp_v1_default_dataset( _p ) \ +do \ +{ \ + _mbg_swab_ptp_v1_uuid( &(_p)->uuid ); \ + _mbg_swab16( &(_p)->clock_variance ); \ + _mbg_swab16( &(_p)->number_ports ); \ + _mbg_swab16( &(_p)->number_foreign_records ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief PTPv1 current dataset containing information about the synchronization status of the device + * + * @see ::NANO_TIME + */ +typedef struct +{ + uint16_t steps_removed; + uint16_t reserved_1; + NANO_TIME offset_from_master; + NANO_TIME one_way_delay; +} MBG_PTP_V1_CURRENT_DATASET; + + +#define _mbg_swab_ptp_v1_current_dataset( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->steps_removed ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab_nano_time( &(_p)->offset_from_master ); \ + _mbg_swab_nano_time( &(_p)->one_way_delay ); \ +} while ( 0 ) + + + +/** + * @brief PTPv1 parent dataset flags + * + * @see ::PTP_V1_PARENT_DATASET_FLAGS_MASKS + */ +enum PTP_V1_PARENT_DATASET_FLAGS +{ + V1_PARENT_FOLLOWUP_CAPABLE, + V1_PARENT_EXT_TIMING, + V1_PARENT_STATS, + V1_PARENT_UTC_REASONABLE, + V1_PARENT_GM_PREFERRED, + V1_PARENT_GM_IS_BC +}; + + + +/** + * @brief PTPv1 parent dataset flag masks used with ::MBG_PTP_V1_PARENT_DATASET::flags + * + * @see ::PTP_V1_PARENT_DATASET_FLAGS + */ +enum PTP_V1_PARENT_DATASET_FLAGS_MASKS +{ + V1_PARENT_MSK_FOLLOWUP_CAPABLE = ( 1UL << V1_PARENT_FOLLOWUP_CAPABLE ), ///< see ::V1_PARENT_FOLLOWUP_CAPABLE + V1_PARENT_MSK_EXT_TIMING = ( 1UL << V1_PARENT_EXT_TIMING ), ///< see ::V1_PARENT_EXT_TIMING + V1_PARENT_MSK_STATS = ( 1UL << V1_PARENT_STATS ), ///< see ::V1_PARENT_STATS + V1_PARENT_MSK_UTC_REASONABLE = ( 1UL << V1_PARENT_UTC_REASONABLE ), ///< see ::V1_PARENT_UTC_REASONABLE + V1_PARENT_MSK_GM_PREFERRED = ( 1UL << V1_PARENT_GM_PREFERRED ), ///< see ::V1_PARENT_GM_PREFERRED + V1_PARENT_MSK_GM_IS_BC = ( 1UL << V1_PARENT_GM_IS_BC ) ///< see ::V1_PARENT_GM_IS_BC +}; + + + +/** + * @brief PTPv1 parent dataset containing information about the master (parent) of the device + * + * @see ::PTP_V1_UUID + */ +typedef struct +{ + PTP_V1_UUID uuid; + uint16_t parent_last_sync_sequence_number; + int16_t parent_variance; + int16_t observed_variance; + uint16_t reserved_1; + int32_t observed_drift; + PTP_V1_UUID grandmaster_uuid; + uint8_t grandmaster_stratum; + uint8_t grandmaster_identifier[PTP_CODE_STRING_LENGTH]; + int16_t grandmaster_variance; + uint16_t grandmaster_sequence_number; + uint16_t reserved_2; + uint32_t flags; ///< see ::PTP_V1_PARENT_DATASET_FLAGS_MASKS + +} MBG_PTP_V1_PARENT_DATASET; + + +#define _mbg_swab_ptp_v1_parent_dataset( _p ) \ +do \ +{ \ + _mbg_swab_ptp_v1_uuid( &(_p)->uuid ); \ + _mbg_swab16( &(_p)->parent_last_sync_sequence_number ); \ + _mbg_swab16( &(_p)->parent_variance ); \ + _mbg_swab16( &(_p)->observed_variance ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->observed_drift ); \ + _mbg_swab_ptp_v1_uuid( &(_p)->grandmaster_uuid ); \ + _mbg_swab16( &(_p)->grandmaster_variance ); \ + _mbg_swab16( &(_p)->grandmaster_sequence_number ); \ + _mbg_swab16( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief PTPv1 time drop dataset flags + * + * @see ::PTP_V1_TIME_PROP_DATASET_FLAGS_MASKS + */ +enum PTP_V1_TIME_PROP_DATASET_DATASET_FLAGS +{ + V1_TPROP_LEAP_59, + V1_TPROP_LEAP_61 +}; + + + +/** + * @brief PTPv1 time drop dataset flag masks used with ::MBG_PTP_V1_TIME_PROPERTIES_DATASET::flags + * + * @see ::PTP_V1_TIME_PROP_DATASET_DATASET_FLAGS + */ +enum PTP_V1_TIME_PROP_DATASET_FLAGS_MASKS +{ + V1_TPROP_MSK_LEAP_59 = ( 1UL << V1_TPROP_LEAP_59 ), ///< see ::V1_TPROP_LEAP_59 + V1_TPROP_MSK_LEAP_61 = ( 1UL << V1_TPROP_LEAP_61 ) ///< see ::V1_TPROP_LEAP_61 +}; + + + +/** + * @brief PTPv1 time drop dataset + * + */ +typedef struct +{ + int16_t current_utc_offset; + uint16_t epoch_number; + uint32_t flags; ///< see ::PTP_V1_TIME_PROP_DATASET_FLAGS_MASKS + +} MBG_PTP_V1_TIME_PROPERTIES_DATASET; + + +#define _mbg_swab_ptp_v1_time_properties_dataset( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->current_utc_offset ); \ + _mbg_swab16( &(_p)->epoch_number ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief PTPv1 port dataset flags + * + * @see ::PTP_V1_PORT_DATASET_FLAGS_MASKS + */ +enum PTP_V1_PORT_DATASET_DATASET_FLAGS +{ + V1_PORT_DATASET_BURST_ENB, +}; + + + +/** + * @brief PTPv1 port dataset flag masks used with ::MBG_PTP_V1_PORT_DATASET::flags + * + * @see ::PTP_V1_PORT_DATASET_DATASET_FLAGS + */ +enum PTP_V1_PORT_DATASET_FLAGS_MASKS +{ + V1_PORT_DATASET_MSK_BURST_ENB = ( 1UL << V1_PORT_DATASET_BURST_ENB ), ///< see ::V1_PORT_DATASET_BURST_ENB +}; + + + +/** + * @brief PTPv1 port dataset containing information about the appropriate port of the device + * + * @see ::PTP_V1_UUID + */ +typedef struct +{ + uint8_t port_state; + uint8_t reserved_1; + uint16_t last_sync_event_sequence_number; + uint16_t last_general_event_sequence_number; + uint16_t reserved_2; + uint32_t subdomain_address; + uint16_t event_port_address; + uint16_t general_port_address; + PTP_V1_UUID uuid; + uint32_t flags; +} MBG_PTP_V1_PORT_DATASET; + + +#define _mbg_swab_ptp_v1_port_dataset( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->last_sync_event_sequence_number ); \ + _mbg_swab16( &(_p)->last_general_event_sequence_number ); \ + _mbg_swab16( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->subdomain_address ); \ + _mbg_swab16( &(_p)->event_port_address ); \ + _mbg_swab16( &(_p)->general_port_address ); \ + _mbg_swab_ptp_v1_uuid( &(_p)->uuid ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Index structure for PTPv1 port dataset + * + * @note Port dataset with index 0..::MBG_PTP_V1_DEFAULT_DATASET::number_ports - 1 can be queried from a device + * + * @see ::MBG_PTP_V1_PORT_DATASET + */ +typedef struct +{ + uint16_t idx; ///< Index of the port dataset, 0..::MBG_PTP_V1_DEFAULT_DATASET::number_ports - 1 + MBG_PTP_V1_PORT_DATASET port_dataset; ///< see ::MBG_PTP_V1_PORT_DATASET + +} MBG_PTP_V1_PORT_DATASET_IDX; + + +#define _mbg_swab_ptp_v1_port_dataset_idx( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_ptp_v1_port_dataset( &(_p)->port_dataset ); \ } -/** @} group_ptp */ +/** + * @brief Flags structure for the PTPv2 default dataset + * + * @note For further information, see IEEE 1588-2008, chapters 8.2.1 and 15.5.3.3.1 + * + * @see ::MBG_PTP_V2_DEFAULT_DATASET + */ +typedef struct +{ + uint8_t two_step : 1; ///< indicates, whether the clock is a two-step clock + uint8_t slave_only : 1; ///< indicates, whether the clock is a slave-only clock + uint8_t reserved : 6; ///< reserved, currently always 0 +} MBG_PTP_V2_DEFAULT_DATASET_FLAGS; +#define _mbg_swab_ptp_v2_default_dataset_flags( _p ) \ + _nop_macro_fnc() -/*------------------------------------------------------------------------*/ -/* Ephemeris parameters of one specific SV. Needed to compute the position */ -/* of a satellite at a given time with high precision. Valid for an */ -/* interval of 4 to 6 hours from start of transmission. */ - -typedef struct -{ - CSUM csum; /* checksum of the remaining bytes */ - int16_t valid; /* flag data are valid */ - - HEALTH health; /* health indication of transmitting SV [---] */ - IOD IODC; /* Issue Of Data, Clock */ - IOD IODE2; /* Issue of Data, Ephemeris (Subframe 2) */ - IOD IODE3; /* Issue of Data, Ephemeris (Subframe 3) */ - T_GPS tt; /* time of transmission */ - T_GPS t0c; /* Reference Time Clock [---] */ - T_GPS t0e; /* Reference Time Ephemeris [---] */ - - double sqrt_A; /* Square Root of semi-major Axis [sqrt(m)] */ - double e; /* Eccentricity [---] */ - double M0; /* +- Mean Anomaly at Ref. Time [rad] */ - double omega; /* +- Argument of Perigee [rad] */ - double OMEGA0; /* +- Longit. of Asc. Node of orbit plane [rad] */ - double OMEGADOT; /* +- Rate of Right Ascension [rad/sec] */ - double deltan; /* +- Mean Motion Diff. from computed value [rad/sec] */ - double i0; /* +- Inclination Angle [rad] */ - double idot; /* +- Rate of Inclination Angle [rad/sec] */ - double crc; /* +- Cosine Corr. Term to Orbit Radius [m] */ - double crs; /* +- Sine Corr. Term to Orbit Radius [m] */ - double cuc; /* +- Cosine Corr. Term to Arg. of Latitude [rad] */ - double cus; /* +- Sine Corr. Term to Arg. of Latitude [rad] */ - double cic; /* +- Cosine Corr. Term to Inclination Angle [rad] */ - double cis; /* +- Sine Corr. Term to Inclination Angle [rad] */ - - double af0; /* +- Clock Correction Coefficient 0 [sec] */ - double af1; /* +- Clock Correction Coefficient 1 [sec/sec] */ - double af2; /* +- Clock Correction Coefficient 2 [sec/sec^2] */ - double tgd; /* +- estimated group delay differential [sec] */ - - uint16_t URA; /* predicted User Range Accuracy */ - - uint8_t L2code; /* code on L2 channel [---] */ - uint8_t L2flag; /* L2 P data flag [---] */ -} EPH; +/** + * @brief PTPv2 default dataset + * + * @note For further information, see IEEE 1588-2008, chapters 8.2.1 and 15.5.3.3.1 + * + * @see ::MBG_PTP_V2_DEFAULT_DATASET_FLAGS + * @see ::PTP_CLOCK_QUALITY + * @see ::PTP_CLOCK_ID + */ +typedef struct +{ + MBG_PTP_V2_DEFAULT_DATASET_FLAGS flags; ///< flags field, see ::MBG_PTP_V2_DEFAULT_DATASET_FLAGS + uint8_t reserved_1; ///< reserved, currently always 0 + uint16_t number_ports; ///< number of PTP ports on the device + uint8_t priority_1; ///< priority 1 attribute for the local clock + PTP_CLOCK_QUALITY clock_quality; ///< quality of the local clock, see ::PTP_CLOCK_QUALITY + uint8_t priority_2; ///< priority 2 attribute for the local clock + PTP_CLOCK_ID clock_identity; ///< identity of the local clock, see ::PTP_CLOCK_ID + uint8_t domain_number; ///< domain attribute of the local clock + uint8_t reserved_2; ///< reserved, currently always 0 +} MBG_PTP_V2_DEFAULT_DATASET; -/* Almanac parameters of one specific SV. A reduced precision set of */ -/* parameters used to check if a satellite is in view at a given time. */ -/* Valid for an interval of more than 7 days from start of transmission. */ +#define _mbg_swab_ptp_v2_default_dataset( _p ) \ +{ \ + _mbg_swab_ptp_v2_default_dataset_flags( &(_p)->flags ); \ + _mbg_swab8( &(_p)->reserved_1 ); \ + _mbg_swab16( &(_p)->number_ports ); \ + _mbg_swab8( &(_p)->priority_1 ); \ + _mbg_swab_ptp_clock_quality( &(_p)->clock_quality ); \ + _mbg_swab8( &(_p)->priority_2 ); \ + _mbg_swab_ptp_clock_id( &(_p)->clock_identity ); \ + _mbg_swab8( &(_p)->domain_number ); \ + _mbg_swab8( &(_p)->reserved_2 ); \ +} + +/** + * @brief PTPv2 current dataset + * + * @note For further information, see IEEE 1588-2008, chapters 8.2.2 and 15.5.3.4.1 + * + * @see ::PTP_TIME_INTERVAL + */ typedef struct { - CSUM csum; /* checksum of the remaining bytes */ - int16_t valid; /* flag data are valid */ + uint16_t steps_removed; ///< number of communication paths between local clock and grandmaster + PTP_TIME_INTERVAL offset_from_master; ///< current time difference between master and slave, see ::PTP_TIME_INTERVAL + PTP_TIME_INTERVAL mean_path_delay; ///< current mean propagation time between master and slave, see ::PTP_TIME_INTERVAL - HEALTH health; /* [---] */ - T_GPS t0a; /* Reference Time Almanac [sec] */ +} MBG_PTP_V2_CURRENT_DATASET; + + +#define _mbg_swab_ptp_v2_current_dataset( _p ) \ +{ \ + _mbg_swab16( &(_p)->steps_removed ); \ + _mbg_swab_ptp_time_interval( &(_p)->offset_from_master ); \ + _mbg_swab_ptp_time_interval( &(_p)->mean_path_delay ); \ +} + + +/** + * @brief Flags structure for the PTPv2 parent dataset + * + * @note For further information, see IEEE 1588-2008, chapters 8.2.3.3 and 15.5.3.5.1.2 + * + * @see ::MBG_PTP_V2_PARENT_DATASET + */ +typedef struct +{ + uint8_t parent_stats : 1; ///< indicates whether the variance and change rate values are valid + uint8_t reserved : 7; ///< reserved, currently always 0 + +} MBG_PTP_V2_PARENT_DATASET_FLAGS; + +#define _mbg_swab_ptp_v2_parent_dataset_flags( _p )\ + _nop_macro_fnc() + + + +/** + * @brief PTPv2 parent dataset + * + * @note For further information, see IEEE 1588-2008, chapters 8.2.3 and 15.5.3.5.1 + * + * @see ::PTP_PORT_IDENTITY + * @see ::MBG_PTP_V2_PARENT_DATASET_FLAGS + * @see ::PTP_CLOCK_QUALITY + * @see ::PTP_CLOCK_ID + */ +typedef struct +{ + PTP_PORT_IDENTITY parent_port_identity; ///< Identity of the master port, that issues the sync messages, see ::PTP_PORT_IDENTITY + MBG_PTP_V2_PARENT_DATASET_FLAGS flags; ///< Flags field, see ::MBG_PTP_V2_PARENT_DATASET_FLAGS + uint8_t reserved; ///< Reserved, currently always 0 + uint16_t parent_log_variance; ///< Estimate of the parent clock's PTP variance, only valid if + ///< ::MBG_PTP_V2_PARENT_DATASET_FLAGS::parent_stats is set in ::MBG_PTP_V2_PARENT_DATASET::flags + int32_t parent_phase_change_rate; ///< Estimate of the parent clock's phase change rate, only valid if + ///< ::MBG_PTP_V2_PARENT_DATASET_FLAGS::parent_stats is set in ::MBG_PTP_V2_PARENT_DATASET::flags + uint8_t grandmaster_priority_1; ///< Priority 1 attribute of the grandmaster clock + PTP_CLOCK_QUALITY grandmaster_clock_quality; ///< Quality of the grandmaster clock, see ::PTP_CLOCK_QUALITY + uint8_t grandmaster_priority_2; ///< Priority 2 attribute of the grandmaster clock + PTP_CLOCK_ID grandmaster_identity; ///< Identity of the grandmaster clock, see ::PTP_CLOCK_ID + +} MBG_PTP_V2_PARENT_DATASET; + + +#define _mbg_swab_ptp_v2_parent_dataset( _p ) \ +{ \ + _mbg_swab_ptp_port_identity( &(_p)->parent_port_identity ); \ + _mbg_swab_ptp_v2_parent_dataset_flags( &(_p)->flags ); \ + _mbg_swab8( &(_p)->reserved ); \ + _mbg_swab16( &(_p)->parent_log_variance ); \ + _mbg_swab32( &(_p)->parent_phase_change_rate ); \ + _mbg_swab8( &(_p)->grandmaster_priority_1 ); \ + _mbg_swab_ptp_clock_quality( &(_p)->grandmaster_clock_quality ); \ + _mbg_swab8( &(_p)->grandmaster_priority_2 ); \ + _mbg_swab_ptp_clock_id( &(_p)->grandmaster_identity ); \ +} + + +/** + * @brief Flags structure for the PTPv2 time properties dataset + * + * @note For further information, see IEEE 1588-2008, chapters 8.2.4 and 15.5.3.6.1 + * + * @see ::MBG_PTP_V2_TIME_PROPERTIES_DATASET + */ +typedef struct +{ + uint8_t leap_61 : 1; ///< set, if the last minute of the current UTC day containts 61 seconds + uint8_t leap_59 : 1; ///< set, if the last minute of the current UTC day containts 59 seconds + uint8_t utc_offset_valid : 1; ///< set, if the current UTC offset is known to be correct + uint8_t ptp_timescale : 1; ///< set, if the timescale of the grandmaster clock is PTP + uint8_t time_traceable : 1; ///< set, if timescale and utc offset are traceable to a primary reference + uint8_t frequency_traceable : 1; ///< set, if the frequency determining the timescale is traceable to a primary reference + uint8_t reserved : 2; ///< reserved, currently always 0 + +} MBG_PTP_V2_TIME_PROPERTIES_DATASET_FLAGS; + + +#define _mbg_swab_ptp_v2_time_properties_dataset_flags( _p ) \ + _nop_macro_fnc() + + +/** + * @brief PTPv2 time properties dataset + * + * @note For further information, see IEEE 1588-2008, chapters 8.2.4 and 15.5.3.6.1 + * + * @see ::MBG_PTP_V2_TIME_PROPERTIES_DATASET_FLAGS + */ +typedef struct +{ + int16_t current_utc_offset; ///< offset between TAI and UTC in seconds + MBG_PTP_V2_TIME_PROPERTIES_DATASET_FLAGS flags; ///< flags field, see ::MBG_PTP_V2_TIME_PROPERTIES_DATASET_FLAGS + uint8_t time_source; ///< source of time used by the grandmaster clock, see ::PTP_TIME_SOURCES + +} MBG_PTP_V2_TIME_PROPERTIES_DATASET; + + +#define _mbg_swab_ptp_v2_time_properties_dataset( _p ) \ +{ \ + _mbg_swab16( &(_p)->current_utc_offset ); \ + _mbg_swab_ptp_v2_time_properties_dataset_flags( &(_p)->flags ); \ + _mbg_swab8( &(_p)->time_source ); \ +} + + +/** + * @brief PTPv2 port dataset + * + * @note For further information, see IEEE 1588-2008, chapters 8.2.5 and 15.5.3.7.1 + * + * @see ::PTP_PORT_IDENTITY + * @see ::PTP_TIME_INTERVAL + * @see ::MBG_PTP_V2_PORT_DATASET_IDX + */ +typedef struct +{ + PTP_PORT_IDENTITY port_identity; ///< identity of the local port, see ::PTP_PORT_IDENTITY + uint8_t port_state; ///< state of the protocol engine associated with this port, see ::PTP_PORT_STATES + int8_t log_min_delay_req_interval; ///< minimum delay request interval for this port + PTP_TIME_INTERVAL peer_mean_path_delay; ///< estimate of the current one-way propagation delay on the link, only valid if P2P is used, see ::PTP_TIME_INTERVAL + int8_t log_announce_interval; ///< announce interval to be used by this port + uint8_t announce_receipt_timeout; ///< shall be an integral multiple of ::MBG_PTP_V2_PORT_DATASET::log_announce_interval + int8_t log_sync_interval; ///< mean sync interval to be used for multicast messages + uint8_t delay_mechanism; ///< propagation delay measuring option, see ::PTP_DELAY_MECHS + int8_t log_min_pdelay_req_interval; ///< minimum peer delay request interval for this port + uint8_t version_number : 4; ///< PTP version in use on the port + uint8_t reserved : 4; ///< reserved, currently always 0 + +} MBG_PTP_V2_PORT_DATASET; + + +#define _mbg_swab_ptp_v2_port_dataset( _p ) \ +{ \ + _mbg_swab_ptp_port_identity( &(_p)->port_identity ); \ + _mbg_swab8( &(_p)->port_state ); \ + _mbg_swab8( &(_p)->log_min_delay_req_interval ); \ + _mbg_swab_ptp_time_interval( &(_p)->peer_mean_path_delay ); \ + _mbg_swab8( &(_p)->log_announce_interval ); \ + _mbg_swab8( &(_p)->announce_receipt_timeout ); \ + _mbg_swab8( &(_p)->log_sync_interval ); \ + _mbg_swab8( &(_p)->delay_mechanism ); \ + _mbg_swab8( &(_p)->log_min_pdelay_req_interval ); \ +} + + +/** + * @brief Index structure for PTPv2 port dataset + * + * @note Port dataset with index 0..::MBG_PTP_V2_DEFAULT_DATASET::number_ports - 1 can be queried from a device + * + * @see ::MBG_PTP_V2_PORT_DATASET + */ +typedef struct +{ + uint16_t idx; ///< Index of the port dataset, 0..::MBG_PTP_V2_DEFAULT_DATASET::number_ports - 1 + MBG_PTP_V2_PORT_DATASET port_dataset; ///< see ::MBG_PTP_V2_PORT_DATASET + +} MBG_PTP_V2_PORT_DATASET_IDX; + + +#define _mbg_swab_ptp_v2_port_dataset_idx( _p ) \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_ptp_v2_port_dataset( &(_p)->port_dataset ); \ +} + + +/** @} defgroup group_ptp */ + + + +/** + * @defgroup group_ntp Definitions used with NTP + * + * @{ */ + + +/** + * @brief Enumeration of known NTP roles + * + * @see ::NTP_GLB_SETTINGS::ntp_role + */ +enum NTP_ROLES +{ + NTP_ROLE_NONE = 0, ///< NTP services disabled + NTP_ROLE_CLIENT, ///< NTP client + NTP_ROLE_SERVER, ///< NTP server + NTP_ROLE_CLIENT_SERVER, ///< both NTP client and server + N_NTP_ROLES ///< number of supported roles +}; + + +/** + * @brief Flag masks associated with NTP roles + * + * @see ::NTP_GLB_INFO::supp_ntp_roles + */ +enum NTP_ROLE_MASKS +{ + NTP_MSK_ROLE_NONE = ( 1UL << NTP_ROLE_NONE ), ///< see ::NTP_ROLE_NONE + NTP_MSK_ROLE_CLIENT = ( 1UL << NTP_ROLE_CLIENT ), ///< see ::NTP_ROLE_CLIENT + NTP_MSK_ROLE_SERVER = ( 1UL << NTP_ROLE_SERVER ), ///< see ::NTP_ROLE_SERVER + NTP_MSK_ROLE_CLIENT_SERVER = ( 1UL << NTP_ROLE_CLIENT_SERVER ), ///< see ::NTP_ROLE_CLIENT_SERVER +}; + + +/** + * @brief Enumeration of global NTP flags + * + * @see @ref NTP_FLAG_MASKS + */ +enum NTP_FLAGS +{ + NTP_IPV4, ///< NTP via IPv4/UDP + NTP_IPV6, ///< NTP via IPv6/UDP + NTP_SYMM_KEYS, ///< support symmetric key authentication (MD5) + NTP_AUTOKEY, ///< include authentication fields encrypted using the autokey scheme + NTP_BURST, ///< send a burst of eight packets at each polling cycle + NTP_IBURST, ///< send a burst of eight packets at the first polling cycle + NTP_NO_SELECT, ///< marks a server as not to be selected for time synchronization + NTP_PREEMPT, ///< specifies the association as preemptable rather than the default persistent + NTP_PREFER, ///< marks a server as preferred peer for time synchronization + NTP_TRUE, ///< force the association to assume truechimer status; always survive the selection and clustering algorithms + NTP_BROADCAST, ///< transmission via broadcast, point to multipoint + NTP_MULTICAST, ///< transmission via multicast, point to multipoint + NTP_MANYCAST, ///< transmission via manycast, point to multipoint + NTP_POOL, ///< peer shall be treated as a pool server + NTP_PEER, ///< specifies a symmetric-active association should be used with this server + NTP_BROADCASTCLIENT, ///< receive broadcast messages on all interfaces + NTP_MULTICASTCLIENT, ///< receive messages from the given multicast group + NTP_MANYCASTCLIENT, ///< manycast shall be used on the given multicast address to discover peers + NTP_RESTRICTIONS, ///< NTP supports restrictions + NTP_DISCARD, ///< NTP supports "discard" rate limiting + NTP_REFCLOCKS, ///< NTP supports refclocks + NTP_STATISTICS, ///< NTP supports statistics (e.g. clockstats, loopstats, etc...) + NTP_MISCELLANEOUS, ///< NTP supports misc options (e.g. tinker, driftfile, orphan mode, etc...) + NTP_TRUSTED_KEYS, ///< NTP supports specifying trusted symmetric keys + NTP_FIXED_REFCLOCKS, ///< NTP refclocks not configurable + + N_NTP_FLAGS +}; + + + +/** + * @brief Flag masks associated with ::NTP_FLAGS + * + * Used with ::NTP_GLB_INFO::supp_flags, ::NTP_GLB_SETTINGS::flags, NTP_CLNT_MODE_INFO::supp_flags, + * ::NTP_CLNT_MODE_INFO::supp_peer_flags, ::NTP_CLNT_MODE_SETTINGS::flags, ::NTP_PEER_SETTINGS::flags, + * ::NTP_SRV_MODE_SETTINGS::flags, and ::NTP_SRV_MODE_INFO::supp_flags. + * + * @todo We may need structures to configure symmetric keys, and autokey certificates. + * + * @see ::NTP_FLAGS + * + * @anchor NTP_FLAG_MASKS @{ */ + +#define NTP_MSK_IPV4 ( 1UL << NTP_IPV4 ) ///< see ::NTP_IPV4 +#define NTP_MSK_IPV6 ( 1UL << NTP_IPV6 ) ///< see ::NTP_IPV6 +#define NTP_MSK_SYMM_KEYS ( 1UL << NTP_SYMM_KEYS ) ///< see ::NTP_SYMM_KEYS; if set, ::NTP_SYMM_KEY_LIMITS can be queried +#define NTP_MSK_AUTOKEY ( 1UL << NTP_AUTOKEY ) ///< see ::NTP_AUTOKEY +#define NTP_MSK_BURST ( 1UL << NTP_BURST ) ///< see ::NTP_BURST +#define NTP_MSK_IBURST ( 1UL << NTP_IBURST ) ///< see ::NTP_IBURST +#define NTP_MSK_NO_SELECT ( 1UL << NTP_NO_SELECT ) ///< see ::NTP_NO_SELECT +#define NTP_MSK_PREEMPT ( 1UL << NTP_PREEMPT ) ///< see ::NTP_PREEMPT +#define NTP_MSK_PREFER ( 1UL << NTP_PREFER ) ///< see ::NTP_PREFER +#define NTP_MSK_TRUE ( 1UL << NTP_TRUE ) ///< see ::NTP_TRUE +#define NTP_MSK_BROADCAST ( 1UL << NTP_BROADCAST ) ///< see ::NTP_BROADCAST +#define NTP_MSK_MULTICAST ( 1UL << NTP_MULTICAST ) ///< see ::NTP_MULTICAST +#define NTP_MSK_MANYCAST ( 1UL << NTP_MANYCAST ) ///< see ::NTP_MANYCAST +#define NTP_MSK_POOL ( 1UL << NTP_POOL ) ///< see ::NTP_POOL +#define NTP_MSK_PEER ( 1UL << NTP_PEER ) ///< see ::NTP_PEER +#define NTP_MSK_BROADCASTCLIENT ( 1UL << NTP_BROADCASTCLIENT) ///< see ::NTP_BROADCASTCLIENT +#define NTP_MSK_MULTICASTCLIENT ( 1UL << NTP_MULTICASTCLIENT) ///< see ::NTP_MULTICASTCLIENT +#define NTP_MSK_MANYCASTCLIENT ( 1UL << NTP_MANYCASTCLIENT) ///< see ::NTP_MANYCASTCLIENT +#define NTP_MSK_RESTRICTIONS ( 1UL << NTP_RESTRICTIONS ) ///< see ::NTP_RESTRICTIONS +#define NTP_MSK_DISCARD ( 1UL << NTP_DISCARD ) ///< see ::NTP_DISCARD +#define NTP_MSK_REFCLOCKS ( 1UL << NTP_REFCLOCKS ) ///< see ::NTP_REFCLOCKS +#define NTP_MSK_STATISTICS ( 1UL << NTP_STATISTICS ) ///< see ::NTP_STATISTICS; if set, ::NTP_STATS_GLB_INFO can be queried +#define NTP_MSK_MISCELLANEOUS ( 1UL << NTP_MISCELLANEOUS ) ///< see ::NTP_MISCELLANEOUS +#define NTP_MSK_TRUSTED_KEYS ( 1UL << NTP_TRUSTED_KEYS ) ///< see ::NTP_TRUSTED_KEYS +#define NTP_MSK_FIXED_REFCLOCKS ( 1UL << NTP_FIXED_REFCLOCKS ) ///< see ::NTP_FIXED_REFCLOCKS + + +/** @} anchor NTP_FLAG_MASKS */ + + + +/** + * @brief Global configuration settings of an NTP device (client/server) + * + * This structure should be sent to an NTP device to configure global settings + */ +typedef struct +{ + uint8_t ntp_role; ///< one of the supported NTP roles, see ::NTP_ROLES + uint8_t num_symm_keys; ///< number of configured symm keys + uint8_t num_trusted_keys; ///< number of activated symm keys + uint8_t reserved_1; ///< reserved, currently 0 + + uint32_t reserved_2; ///< reserved, currently 0 + uint32_t reserved_3; ///< reserved, currently 0 + + uint32_t flags; ///< NTP flags, see @ref NTP_FLAG_MASKS + +} NTP_GLB_SETTINGS; + +#define _mbg_swab_ntp_glb_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + +/** + * @brief Global configuration info of an NTP device (client/server) + * + * This structure can be used to determine possible configurations of an NTP device + */ +typedef struct +{ + NTP_GLB_SETTINGS settings; ///< current configuration settings + + uint8_t max_symm_keys; ///< number of available symm keys that can be generated, see ::NTP_SYMM_KEY_INFO_IDX + uint8_t max_trusted_keys; ///< number of available trusted keys, see ::NTP_TRUSTED_KEY_INFO_IDX + + uint16_t reserved_2; ///< reserved, currently 0 + uint32_t reserved_3; ///< reserved, currently 0 + + uint32_t supp_ntp_roles; ///< supported NTP roles, see ::NTP_ROLE_MASKS + uint32_t supp_flags; ///< supported NTP flags, see @ref NTP_FLAG_MASKS + +} NTP_GLB_INFO; + +#define _mbg_swab_ntp_glb_info( _p ) \ +do \ +{ \ + _mbg_swab_ntp_glb_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_ntp_roles ); \ + _mbg_swab32( &(_p)->supp_flags ); \ +} while ( 0 ) + + +#if defined( _PRELIMINARY_CODE ) + +/** + * @brief Enumeration of supported NTP restriction types/keywords + * + * Used with ::NTP_RESTR::type + * + * @see https://www.eecis.udel.edu/~mills/ntp/html/accopt.html#restrict + * @see ::NTP_RESTR_TYPE_MSKS + */ +enum NTP_RESTR_TYPES +{ + NTP_RESTR_TYPE_DEFAULT, + NTP_RESTR_TYPE_SOURCE, + NTP_RESTR_TYPE_ADDRESS, + N_NTP_RESTR_TYPES +}; + + + +/** + * @brief Bit masks associated with ::NTP_RESTR_TYPES + * + * Used with ::NTP_RESTR_LIMITS::supp_types + * + * @see ::NTP_RESTR_TYPES + */ +enum NTP_RESTR_TYPE_MSKS +{ + NTP_RESTR_TYPE_MSK_DEFAULT = ( 1UL << NTP_RESTR_TYPE_DEFAULT ), ///< see ::NTP_RESTR_TYPE_DEFAULT + NTP_RESTR_TYPE_MSK_SOURCE = ( 1UL << NTP_RESTR_TYPE_SOURCE ), ///< see ::NTP_RESTR_TYPE_SOURCE + NTP_RESTR_TYPE_MSK_ADDRESS = ( 1UL << NTP_RESTR_TYPE_ADDRESS ) ///< see ::NTP_RESTR_TYPE_ADDRESS +}; + + + +/** + * @brief Enumeration of supported NTP restriction flags + * + * Used to define ::NTP_RESTR_FLAG_MSKS + * + * @see https://www.eecis.udel.edu/~mills/ntp/html/accopt.html#restrict + * @see ::NTP_RESTR_FLAG_MSKS + */ +enum NTP_RESTR_FLAGS +{ + NTP_RESTR_FLAG_FLAKE, + NTP_RESTR_FLAG_IGNORE, + NTP_RESTR_FLAG_KOD, + NTP_RESTR_FLAG_LIMITED, + NTP_RESTR_FLAG_LOWPRIOTRAP, + NTP_RESTR_FLAG_MSSNTP, + NTP_RESTR_FLAG_NOMODIFY, + NTP_RESTR_FLAG_NOQUERY, + NTP_RESTR_FLAG_NOPEER, + NTP_RESTR_FLAG_NOSERVE, + NTP_RESTR_FLAG_NOTRAP, + NTP_RESTR_FLAG_NOTRUST, + NTP_RESTR_FLAG_NTPPORT, + NTP_RESTR_FLAG_VERSION, + NTP_RESTR_FLAG_IPV4, ///< This default restriction only applies to IPv4 + NTP_RESTR_FLAG_IPV6, ///< This default restriction only applies to IPv6 + N_NTP_RESTR_FLAGS +}; + + + +/** + * @brief Flag masks associated with ::NTP_RESTR_FLAGS + * + * Used with ::NTP_RESTR::flags and ::NTP_RESTR_LIMITS::supp_flags + * + * @see ::NTP_RESTR_FLAGS + */ +enum NTP_RESTR_FLAG_MSKS +{ + NTP_RESTR_FLAG_MSK_FLAKE = ( 1UL << NTP_RESTR_FLAG_FLAKE ), ///< see ::NTP_RESTR_FLAG_FLAKE + NTP_RESTR_FLAG_MSK_IGNORE = ( 1UL << NTP_RESTR_FLAG_IGNORE ), ///< see ::NTP_RESTR_FLAG_IGNORE + NTP_RESTR_FLAG_MSK_KOD = ( 1UL << NTP_RESTR_FLAG_KOD ), ///< see ::NTP_RESTR_FLAG_KOD + NTP_RESTR_FLAG_MSK_LIMITED = ( 1UL << NTP_RESTR_FLAG_LIMITED ), ///< see ::NTP_RESTR_FLAG_LIMITED + NTP_RESTR_FLAG_MSK_LOWPRIOTRAP = ( 1UL << NTP_RESTR_FLAG_LOWPRIOTRAP ),///< see ::NTP_RESTR_FLAG_LOWPRIOTRAP + NTP_RESTR_FLAG_MSK_MSSNTP = ( 1UL << NTP_RESTR_FLAG_MSSNTP ), ///< see ::NTP_RESTR_FLAG_MSSNTP + NTP_RESTR_FLAG_MSK_NOMODIFY = ( 1UL << NTP_RESTR_FLAG_NOMODIFY ), ///< see ::NTP_RESTR_FLAG_NOMODIFY + NTP_RESTR_FLAG_MSK_NOQUERY = ( 1UL << NTP_RESTR_FLAG_NOQUERY ), ///< see ::NTP_RESTR_FLAG_NOQUERY + NTP_RESTR_FLAG_MSK_NOPEER = ( 1UL << NTP_RESTR_FLAG_NOPEER ), ///< see ::NTP_RESTR_FLAG_NOPEER + NTP_RESTR_FLAG_MSK_NOSERVE = ( 1UL << NTP_RESTR_FLAG_NOSERVE ), ///< see ::NTP_RESTR_FLAG_NOSERVE + NTP_RESTR_FLAG_MSK_NOTRAP = ( 1UL << NTP_RESTR_FLAG_NOTRAP ), ///< see ::NTP_RESTR_FLAG_NOTRAP + NTP_RESTR_FLAG_MSK_NOTRUST = ( 1UL << NTP_RESTR_FLAG_NOTRUST ), ///< see ::NTP_RESTR_FLAG_NOTRUST + NTP_RESTR_FLAG_MSK_NTPPORT = ( 1UL << NTP_RESTR_FLAG_NTPPORT ), ///< see ::NTP_RESTR_FLAG_NTPPORT + NTP_RESTR_FLAG_MSK_VERSION = ( 1UL << NTP_RESTR_FLAG_VERSION ), ///< see ::NTP_RESTR_FLAG_VERSION + NTP_RESTR_FLAG_MSK_IPV4 = ( 1UL << NTP_RESTR_FLAG_IPV4 ), ///< see ::NTP_RESTR_FLAG_IPV4 + NTP_RESTR_FLAG_MSK_IPV6 = ( 1UL << NTP_RESTR_FLAG_IPV6 ) ///< see ::NTP_RESTR_FLAG_IPV6 +}; + + + +/** + * @brief General NTP restriction limits to be read from a device + * + * Used to query from a device how many NTP restrictions are supported + * by the device, then index 0..::NTP_RESTR_LIMITS::cur_restrs-1 + * restriction records can be read from a device. A maximum of + * ::NTP_RESTR_LIMITS::max_restrs can be configured at all. + */ +typedef struct +{ + uint16_t max_restrs; ///< Number of maximum supported restrictions + uint16_t cur_restrs; ///< Number of currently configured restrictions + uint32_t supp_types; ///< Supported restriction types, see ::NTP_RESTR_TYPE_MSKS + uint32_t supp_flags; ///< Supported restriction flags, see ::NTP_RESTR_FLAG_MSKS + uint32_t reserved; ///< Future use + +} NTP_RESTR_LIMITS; + +#define _mbg_swab_ntp_restr_limits( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->max_restrs ); \ + _mbg_swab16( &(_p)->cur_restrs ); \ + _mbg_swab32( &(_p)->supp_types ); \ + _mbg_swab32( &(_p)->supp_flags ); \ + _mbg_swab32( &(_p)->reserved ); \ +} while ( 0 ) + +/** + * @brief NTP restriction + * + * Structure contains all flags and information needed for a valid NTP restriction + * as described at ntp.org's manual page. + */ +typedef struct +{ + uint8_t type; ///< Restriction type, see ::NTP_RESTR_TYPES + uint8_t reserved_1; ///< Future use + uint16_t reserved_2; ///< Future use + uint32_t flags; ///< Restriction flags, see ::NTP_RESTR_FLAG_MSKS + + MBG_HOSTNAME addr; ///< used if ::NTP_RESTR::type == ::NTP_RESTR_TYPE_ADDRESS + ///< can contain a hostname, or an IPv4 or IPv6 address + ///< with or without CIDR extension (eg. 172.16.0.0/16). +} NTP_RESTR; + +#define _mbg_swab_ntp_restr( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab_ntp_restr_discard( &(_p)->u.discard ); \ +} while ( 0 ) + + + +/** + * @brief NTP restriction, plus index + * + * @see ::NTP_RESTR + */ +typedef struct +{ + uint32_t idx; + NTP_RESTR restr; + +} NTP_RESTR_IDX; + +#define _mbg_swab_ntp_restr_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_ntp_restr( &(_p)->restr ); \ +} while ( 0 ) + + + +/** + * @brief General NTP "discard" rate limiting limits to be read from a device + * + * Used to query from a device what range of values is supported + * for the NTP "discard" rate limiting configuration. + */ +typedef struct +{ + uint8_t avg_min; ///< Minimum value for avg + uint8_t avg_max; ///< Maximum value for avg + uint8_t min_min; ///< Minimum value for min + uint8_t min_max; ///< Maximum value for min + uint16_t monitor_min; ///< Maximum value for min + uint16_t monitor_max; ///< Maximum value for min + + uint32_t reserved; ///< Future use + +} NTP_DISCARD_LIMITS; + +#define _mbg_swab_ntp_discard_limits( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->monitor_min ); \ + _mbg_swab16( &(_p)->monitor_max ); \ + _mbg_swab32( &(_p)->reserved ); \ +} while ( 0 ) + + + +/** + * @brief NTP "discard" rate limiting settings as described at ntp.org's manual + */ +typedef struct +{ + uint8_t avg; ///< Specify the minimum average interpacket spacing in log2 s. + uint8_t min; ///< Specify the minimum interpacket spacing (guard time) in seconds. + uint16_t monitor; ///< ### TODO Which is the unit of this field? + uint32_t reserved; ///< Possible future use + +} NTP_DISCARD_SETTINGS; + +#define _mbg_swab_ntp_discard_settings( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->monitor ); \ + _mbg_swab32( &(_p)->reserved ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of supported refclock types + * + * Used with ::NTP_REFCLK_CFG_SETTINGS::type + * + * @see https://www.eecis.udel.edu/~mills/ntp/html/refclock.html + * @see ::NTP_REFCLK_TYPE_MSKS + */ +enum NTP_REFCLK_TYPES +{ + NTP_REFCLK_TYPE_LOCAL, ///< NTP local clock + NTP_REFCLK_TYPE_TRUETIME, ///< NTP Truetime driver + NTP_REFCLK_TYPE_PARSE, ///< NTP parse driver + NTP_REFCLK_TYPE_NMEA, ///< NTP NMEA driver + NTP_REFCLK_TYPE_PPS, ///< NTP atom driver (standalone PPS) + NTP_REFCLK_TYPE_SHM, ///< NTP shared memory driver + N_NTP_REFCLK_TYPES +}; + + + +/** + * @brief Bit masks associated with ::NTP_REFCLK_TYPES + * + * Used with ::NTP_REFCLK_CFG_INFO::supp_refclk_types + * + * @see ::NTP_REFCLK_TYPES + */ +enum NTP_REFCLK_TYPE_MSKS +{ + NTP_REFCLK_TYPE_MSK_LOCAL = ( 1UL << NTP_REFCLK_TYPE_LOCAL ), ///< see ::NTP_REFCLK_TYPE_LOCAL + NTP_REFCLK_TYPE_MSK_TRUETIME = ( 1UL << NTP_REFCLK_TYPE_TRUETIME ), ///< see ::NTP_REFCLK_TYPE_TRUETIME + NTP_REFCLK_TYPE_MSK_PARSE = ( 1UL << NTP_REFCLK_TYPE_PARSE ), ///< see ::NTP_REFCLK_TYPE_PARSE + NTP_REFCLK_TYPE_MSK_NMEA = ( 1UL << NTP_REFCLK_TYPE_NMEA ), ///< see ::NTP_REFCLK_TYPE_NMEA + NTP_REFCLK_TYPE_MSK_PPS = ( 1UL << NTP_REFCLK_TYPE_PPS ), ///< see ::NTP_REFCLK_TYPE_PPS + NTP_REFCLK_TYPE_MSK_SHM = ( 1UL << NTP_REFCLK_TYPE_SHM ) ///< see ::NTP_REFCLK_TYPE_SHM +}; + + + + + +/** + * @brief Numbers related to the "fudge" flags used with ntpd's refclock interface + * + * Used with ::NTP_REFCLK_CFG_SETTINGS::drv_flags_enable + * and ::NTP_REFCLK_CFG_SETTINGS::drv_flags_value + * + * The refclock interface provided by ntpd supports a number of flags + * (flag1..flag4) which can be "fudged" in ntp.conf to control specific + * features of a particular refclock driver, e.g.: + * "fudge 127.127.8.0 flag1 1" + * + * Which feature is controlled by which flag depends on the refclock + * driver type, so usually each flag has a different meaning for + * different refclock types. + * + * There are different cases to be distinguished: + * + * - if a flag is not specified at all in ntp.conf then + * the controlled feature is enabled or disabled + * according to the driver's default settings + * + * - if a flag is specified as '0' or '1' in ntp.conf then + * the controlled feature is enabled or disabled + * according to the flag's setting. + * + * Thus, the bit mask in ::NTP_REFCLK_CFG_SETTINGS::drv_flags_enable + * controls if the associated fudge flag should be specified in ntp.conf, + * and if it is specified then the associated bit in + * ::NTP_REFCLK_CFG_SETTINGS::drv_flags_value controls if the fudge flag + * is set to 0 or 1. + * + * @anchor NTP_FUDGE_FLAG_NUMBERS @{ */ + +#define NTP_MIN_REFCLOCK_FUDGE_FLAG 1 ///< minimum refclock fudge flag number, associated with bit 0 +#define N_NTP_REFCLOCK_FUDGE_FLAGS 4 ///< the number of supported fudge flags + +/** @} anchor NTP_FUDGE_FLAG_NUMBERS */ + + + +/** + * @brief NTP refclock specific settings + * + * Used to configure a NTP refclock. + */ +typedef struct +{ + uint8_t type; ///< See ::NTP_REFCLK_TYPES + uint8_t instance; ///< Refclock instance of the specified type. Usually up to 4 instances of the same type are supported by ntpd. + uint8_t mode; ///< Driver specific "mode" ::FIXME Flag to enable "mode"? + int8_t stratum; ///< Stratum number to be fudged; -1 if unspecified and thus default is to be used + + int8_t refid[4]; ///< Reference id used by driver ::FIXME Flag to enable "refid"? + + uint8_t minpoll; ///< Minimum polling interval, [log2 seconds], 0 if unused/unspecified + uint8_t maxpoll; ///< Maximum polling interval, [log2 seconds], 0 if unused/unspecified + uint8_t reserved_1; ///< Reserved for future use + uint8_t reserved_2; ///< Future use + + NANO_TIME_64 time1; ///< Driver specific + NANO_TIME_64 time2; ///< Driver specific + + uint16_t drv_flags_enable; ///< Enable/disable driver specific flags, see @ref NTP_FUDGE_FLAG_NUMBERS + uint16_t drv_flags_value; ///< 0 or 1, if (drv_flags_enable & x) == 1, see @ref NTP_FUDGE_FLAG_NUMBERS + + uint32_t flags; ///< See @ref NTP_FLAG_MASKS. Only flags specified in ::FIXME can be used here. + + uint32_t reserved_3; ///< Future use + +} NTP_REFCLK_CFG_SETTINGS; + +#define _mbg_swab_ntp_refclk_cfg_settings( _p ) \ +do \ +{ \ + _mbg_swab_nano_time_64( &(_p)->time1 ); \ + _mbg_swab_nano_time_64( &(_p)->time2 ); \ + _mbg_swab16( &(_p)->drv_flags_enable ); \ + _mbg_swab16( &(_p)->drv_flags_value ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief NTP refclock settings index + * + * @see ::NTP_REFCLK_CFG_SETTINGS + */ +typedef struct +{ + uint32_t idx; + NTP_REFCLK_CFG_SETTINGS settings; ///< See ::NTP_REFCLK_CFG_SETTINGS + +} NTP_REFCLK_CFG_SETTINGS_IDX; + +#define _mbg_swab_ntp_refclk_cfg_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_ntp_refclk_cfg_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +/** + * @brief NTP refclock configuration and supported refclock types + * + * This structure can be used to set a NTP refclock's configuration + * and get to know its overall supported refclocks. + */ +typedef struct +{ + NTP_REFCLK_CFG_SETTINGS settings; ///< See ::NTP_REFCLK_CFG_SETTINGS + + uint32_t supp_refclk_types; ///< See ::NTP_REFCLK_TYPE_MSKS + +} NTP_REFCLK_CFG_INFO; + +#define _mbg_swab_ntp_refclk_cfg_info( _p ) \ +do \ +{ \ + _mbg_swab_ntp_refclk_cfg_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_refclk_types ); \ +} while ( 0 ) + + + +/** + * @brief NTP refclock info, with index + * + * @see ::NTP_REFCLK_CFG_INFO + */ +typedef struct +{ + uint32_t idx; + NTP_REFCLK_CFG_INFO info; + +} NTP_REFCLK_CFG_INFO_IDX; + +#define _mbg_swab_ntp_refclk_cfg_info_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_ntp_refclk_cfg_info( &(_p)->info ); \ +} while ( 0 ) + + +/** + * @brief Enumeration of NTP supported symmetric key hashing algorithms + * + * @see ::NTP_SYMM_KEY_HASH_MASKS + * + * @note Support of external libraries (e.g.: OpenSSL) may be needed for + * some hashing algorithms. + */ +enum NTP_SYMM_KEY_HASHES +{ + NTP_SYMM_KEY_HASH_MD5, ///< NTP supports MD5 as key hashing algorithm + NTP_SYMM_KEY_HASH_SHA1, ///< NTP supports SHA1 as key hashing algorithm + N_NTP_SYMM_KEY_HASHES +}; + + + +/** + * @brief Flag masks associated with ::NTP_SYMM_KEY_HASHES + * + * @see ::NTP_SYMM_KEY_HASHES + */ +enum NTP_SYMM_KEY_HASH_MASKS +{ + NTP_SYMM_KEY_HASH_MSK_MD5 = ( 1UL << NTP_SYMM_KEY_HASH_MD5 ), ///< see ::NTP_SYMM_KEY_HASH_MD5 + NTP_SYMM_KEY_HASH_MSK_SHA1 = ( 1UL << NTP_SYMM_KEY_HASH_SHA1 ), ///< see ::NTP_SYMM_KEY_HASH_SHA1 +}; + + +/** + * @brief Name strings for defined NTP symm key hashes + * + * @see ::NTP_SYMM_KEY_HASHES + */ +#define NTP_SYMM_KEY_HASHES_STRS \ +{ \ + "MD5", \ + "SHA1" \ +} + + + +/** + * @brief General NTP symmetric key limits to be read from a device + * + * ::NTP_SYMM_KEY_LIMITS::supp_hashes specifies supported hashing algorithms + * to create keys with. See ::NTP_SYMM_KEY_HASH_MASKS. Structure can be queried + * if ::NTP_MSK_SYMM_KEYS is set in ::NTP_GLB_INFO::supp_flags + */ +typedef struct +{ + uint16_t supp_hashes; ///< See ::NTP_SYMM_KEY_HASH_MASKS + uint16_t reserved_1; ///< Future use + uint32_t reserved_2; ///< Future use + uint32_t reserved_3; ///< Future use + uint32_t reserved_4; ///< Future use + +} NTP_SYMM_KEY_LIMITS; + +#define _mbg_swab_ntp_symm_key_limits( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->supp_hashes ); \ +} while ( 0 ) + + + +/// Maximum length of a symmetric key. 128 byte was chosen to be +/// prepared for hash algorithms like SHA256, SH384, up to SHA512. +#define N_NTP_SYMM_KEY_LEN 128 + +/// Maximum number of ip addresses which can be assign to each key in +/// order to limit usage +#define N_NTP_SYMM_KEY_MAX_IP_ADDR 8 + + + +/** + * @brief NTP symmetric key specific settings + * + * This structure is used to configure a symmetric key for NTP. + */ +typedef struct +{ + uint16_t id; ///< Configurable key id (1..65534) + uint8_t hash; ///< See ::NTP_SYMM_KEY_HASHES + uint8_t reserved_1; ///< Future use + + uint16_t reserved_2; ///< Future use + uint8_t num_ip_addr; ///< Number of configured ip addresses + uint8_t reserved_3; ///< Future use + + uint8_t key[N_NTP_SYMM_KEY_LEN]; ///< Hashed phrase, see ::N_NTP_SYMM_KEY_LEN + + MBG_IP_ADDR ip_addr[N_NTP_SYMM_KEY_MAX_IP_ADDR]; ///< Whitelist of ip addresses see ::N_NTP_SYMM_KEY_MAX_IP_ADDR + +} NTP_SYMM_KEY_SETTINGS; + +#define _mbg_swab_ntp_symm_key_settings( _p ) \ +do \ +{ \ + unsigned i; \ + \ + _mbg_swab16( &(_p)->id ); \ + \ + for ( i = 0; i < N_NTP_SYMM_KEY_MAX_IP_ADDR; ++i) \ + _mbg_swab_ip_addr( &(_p)->ip_addr[i] ); \ +} while ( 0 ) + + + +/** + * @brief NTP symmetric key settings, with index + * + * @see ::NTP_SYMM_KEY_SETTINGS + */ +typedef struct +{ + uint32_t idx; + NTP_SYMM_KEY_SETTINGS settings; + +} NTP_SYMM_KEY_SETTINGS_IDX; + +#define _mbg_swab_ntp_symm_key_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_ntp_symm_key_settings( &(_p)->settings ); \ +} while ( 0 ) + + +/** + * @brief NTP symmkey info + * + * This structure is used to query a symmetric key for NTP. + */ +typedef struct +{ + NTP_SYMM_KEY_SETTINGS settings; + + uint32_t reserved_1; ///< Future use + uint32_t reserved_2; ///< Future use + uint32_t reserved_3; ///< Future use + uint32_t reserved_4; ///< Future use + +} NTP_SYMM_KEY_INFO; + +#define _mbg_swab_ntp_symm_key_info( _p ) \ +do \ +{ \ + _mbg_swab_ntp_symm_key_settings( &(_p)->settings ); \ +} while ( 0 ) + + +/** + * @brief NTP symm key info, with index + * + * @see ::NTP_SYMM_KEY_INFO + */ +typedef struct +{ + uint32_t idx; + NTP_SYMM_KEY_INFO info; + +} NTP_SYMM_KEY_INFO_IDX; + +#define _mbg_swab_ntp_symm_key_info_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_ntp_symm_key_info( &(_p)->info ); \ +} while ( 0 ) + + +/** + * @brief NTP trusted key settings + * + * This structure is used to configure a trusted symmetric key for NTP. + */ +typedef struct +{ + uint16_t id; ///< Configurable key id (1..65534) + uint16_t reserved_1; ///< Future use + uint32_t reserved_2; ///< Future use + +} NTP_TRUSTED_KEY_SETTINGS; + +#define _mbg_swab_ntp_trusted_key_settings( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->id ); \ +} while ( 0 ) + + +/** + * @brief NTP trusted key settings, with index + * + * @see ::NTP_TRUSTED_KEY_SETTINGS + */ +typedef struct +{ + uint32_t idx; + NTP_TRUSTED_KEY_SETTINGS settings; + +} NTP_TRUSTED_KEY_SETTINGS_IDX; + +#define _mbg_swab_ntp_trusted_key_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_ntp_trusted_key_settings( &(_p)->settings ); \ +} while ( 0 ) + +/** + * @brief NTP trusted key info + * + * This structure is used to query a trusted symmetric key for NTP. + */ +typedef struct +{ + NTP_TRUSTED_KEY_SETTINGS settings; + + uint32_t reserved_1; ///< Future use + uint32_t reserved_2; ///< Future use + uint32_t reserved_3; ///< Future use + uint32_t reserved_4; ///< Future use + +} NTP_TRUSTED_KEY_INFO; + +#define _mbg_swab_ntp_trusted_key_info( _p ) \ +do \ +{ \ + _mbg_swab_ntp_trusted_key_settings( &(_p)->settings ); \ +} while ( 0 ) + + +/** + * @brief NTP trusted key info, with index + * + * @see ::NTP_TRUSTED_KEY_INFO + */ +typedef struct +{ + uint32_t idx; + NTP_TRUSTED_KEY_INFO info; + +} NTP_TRUSTED_KEY_INFO_IDX; + +#define _mbg_swab_ntp_trusted_key_info_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_ntp_trusted_key_info( &(_p)->info ); \ +} while ( 0 ) + + +/** + * @brief Enumeration of NTP supported statistics + * + * @see ::NTP_GLB_STATS_MASKS + */ +enum NTP_GLB_STATS_FLAGS +{ + NTP_GLB_STATS_FLAG_ENABLE, ///< NTP stats can generally be enabled or disabled + NTP_GLB_STATS_FLAG_CLOCKSTATS, ///< NTP supports clockstats + NTP_GLB_STATS_FLAG_CRYPTOSTATS, ///< NTP supports cryptostats + NTP_GLB_STATS_FLAG_LOOPSTATS, ///< NTP supports loopstats + NTP_GLB_STATS_FLAG_PEERSTATS, ///< NTP supports peerstats + NTP_GLB_STATS_FLAG_RAWSTATS, ///< NTP supports rawstats + NTP_GLB_STATS_FLAG_SYSSTATS, ///< NTP supports sysstats + NTP_GLB_STATS_FLAG_FILEGEN, ///< NTP supports sets of files + ///< If flag is set there are structures needed + ///< that are not avail right now. Future use + N_NTP_GLB_STATS_FLAGS +}; + + + +/** + * @brief Flag masks associated with ::NTP_GLB_STATS_FLAGS + * + * @see ::NTP_GLB_STATS_FLAGS + */ +enum NTP_GLB_STATS_MASKS +{ + NTP_GLB_STATS_MSK_ENABLE = ( 1UL << NTP_GLB_STATS_FLAG_ENABLE ), ///< See ::NTP_GLB_STATS_FLAG_ENABLE + NTP_GLB_STATS_MSK_CLOCKSTATS = ( 1UL << NTP_GLB_STATS_FLAG_CLOCKSTATS ), ///< See ::NTP_GLB_STATS_FLAG_CLOCKSTATS + NTP_GLB_STATS_MSK_CRYPTOSTATS = ( 1UL << NTP_GLB_STATS_FLAG_CRYPTOSTATS ), ///< See ::NTP_GLB_STATS_FLAG_CRYPTOSTATS + NTP_GLB_STATS_MSK_LOOPSTATS = ( 1UL << NTP_GLB_STATS_FLAG_LOOPSTATS ), ///< See ::NTP_GLB_STATS_FLAG_LOOPSTATS + NTP_GLB_STATS_MSK_PEERSTATS = ( 1UL << NTP_GLB_STATS_FLAG_PEERSTATS ), ///< See ::NTP_GLB_STATS_FLAG_PEERSTATS + NTP_GLB_STATS_MSK_RAWSTATS = ( 1UL << NTP_GLB_STATS_FLAG_RAWSTATS ), ///< See ::NTP_GLB_STATS_FLAG_RAWSTATS + NTP_GLB_STATS_MSK_SYSSTATS = ( 1UL << NTP_GLB_STATS_FLAG_SYSSTATS ), ///< See ::NTP_GLB_STATS_FLAG_SYSSTATS + NTP_GLB_STATS_MSK_FILEGEN = ( 1UL << NTP_GLB_STATS_FLAG_FILEGEN ) ///< See ::NTP_GLB_STATS_FLAG_FILEGEN +}; + + + +/** + * @brief Global NTP statistics settings to be read from / written to a device + * + * ::NTP_GLB_STATS_MSK_ENABLE is the switch to enable / disable statistics in + * general. In case the bit is set all other bits stand for special statistic + * types that can be enabled or disabled by setting or deleting its specific bit. + */ +typedef struct +{ + uint32_t flags; ///< See ::NTP_GLB_STATS_MASKS + uint32_t reserved_1; ///< Future use + uint32_t reserved_2; ///< Future use + +} NTP_STATS_GLB_SETTINGS; + +#define _mbg_swab_ntp_stats_glb_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ +} while ( 0 ) + + + +/** + * @brief NTP statistics settings + * + * This structure can be used to determine possible NTP statistic options + * and can be queried if ::NTP_MSK_STATISTICS bit is set in ::NTP_GLB_INFO::supp_flags. + */ +typedef struct +{ + NTP_STATS_GLB_SETTINGS settings; ///< See ::NTP_STATS_GLB_SETTINGS + + uint32_t supp_stats; ///< See ::NTP_GLB_STATS_MASKS + uint32_t reserved_1; ///< Future use + uint32_t reserved_2; ///< Future use + uint32_t reserved_3; ///< Future use + +} NTP_STATS_GLB_INFO; + +#define _mbg_swab_ntp_stats_glb_info( _p ) \ +do \ +{ \ + _mbg_swab_ntp_stats_glb_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_stats ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of NTP supported (various) misc options + * + * @see ::NTP_MISC_MSKS + */ +enum NTP_MISC_FLAGS +{ + NTP_MISC_FLAG_DRIFTFILE, ///< NTP supports driftfile + NTP_MISC_FLAG_ORPHAN_MODE, ///< NTP supports orphan mode + NTP_MISC_FLAG_LEAPFILE, ///< NTP supports leapfile + N_NTP_MISC_FLAGS +}; + + + +/** + * @brief Flag masks associated with ::NTP_MISC_FLAGS + * + * @see ::NTP_MISC_FLAGS + */ +enum NTP_MISC_MSKS +{ + NTP_MISC_MSK_DRIFTFILE = ( 1UL << NTP_MISC_FLAG_DRIFTFILE ), ///< See ::NTP_MISC_FLAG_DRIFTFILE + NTP_MISC_MSK_ORPHAN_MODE = ( 1UL << NTP_MISC_FLAG_ORPHAN_MODE ), ///< See ::NTP_MISC_FLAG_ORPHAN_MODE + NTP_MISC_MSK_LEAPFILE = ( 1UL << NTP_MISC_FLAG_LEAPFILE ) ///< See ::NTP_MISC_FLAG_LEAPFILE +}; + + + +/** + * @brief General NTP misc limits to be read from a device + * + * This structure can be used to determine various NTP options + * and can be queried if ::NTP_MSK_MISCELLANEOUS bit is set in ::NTP_GLB_INFO::supp_flags. + */ +typedef struct +{ + uint32_t supp_flags; ///< See ::NTP_MISC_MSKS + uint32_t reserved_1; ///< Future use + uint32_t reserved_2; ///< Future use + +} NTP_MISC_LIMITS; + +#define _mbg_swab_ntp_misc_limits( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->supp_flags ); \ +} while ( 0 ) + + + +/** + * @brief NTP driftfile settings to be read from / written to a device + * + * If ::NTP_MISC_MSK_DRIFTFILE is set in ::NTP_MISC_LIMITS::supp_flags + * ::NTP_MISC_DRIFTFILE_SETTINGS can be read / written. + */ +typedef struct +{ + uint8_t enable; ///< Enable / disable writing a driftfile + uint8_t reserved_1; ///< Future use + uint16_t reserved_2; ///< Future use + +} NTP_MISC_DRIFTFILE_SETTINGS; + +#define _mbg_swab_ntp_misc_driftfile_settings( _p ) \ +do \ +{ \ +} while ( 0 ) + + +/** + * @brief Enumeration of NTP supported (various) misc options + * + * @see ::NTP_ORPHAN_MODE_MSK + */ +enum NTP_ORPHAN_MODE_FLAGS +{ + NTP_ORPHAN_MODE_FLAG_SUPP_DISABLE, ///< Orphan Mode support disabling + + N_NTP_ORPHAN_MODE_FLAGS +}; + + + +/** + * @brief Flag masks associated with ::NTP_ORPHAN_MODE_FLAGS + * + * @see ::NTP_ORPHAN_MODE_FLAGS + */ +enum NTP_ORPHAN_MODE_MSK +{ + NTP_ORPHAN_MODE_MSK_SUPP_DISABLE = ( 1UL << NTP_ORPHAN_MODE_FLAG_SUPP_DISABLE ) ///< See ::NTP_ORPHAN_MODE_FLAG_SUPP_DISABLE +}; + + +/** + * @brief NTP orphan mode settings to be read from / written to a device + * + * If ::NTP_MISC_MSK_ORPHAN_MODE is set in ::NTP_MISC_LIMITS::supp_flags + * ::NTP_MISC_ORPHAN_MODE_SETTINGS can be read / written. + */ +typedef struct +{ + uint8_t enable; ///< Generally enable / disable orphan mode + uint8_t mode; ///< Stratum level when no ref source available + uint16_t reserved_1; ///< Future use + + uint32_t reserved_2; ///< Future use + +} NTP_MISC_ORPHAN_MODE_SETTINGS; + +#define _mbg_swab_ntp_misc_orphan_mode_settings( _p ) \ +do \ +{ \ +} while ( 0 ) + + +/** + * @brief NTP orphan mode info + * + */ +typedef struct +{ + NTP_MISC_ORPHAN_MODE_SETTINGS settings; ///< See ::NTP_MISC_ORPHAN_MODE_SETTINGS + + uint32_t supp_flags; ///< See ::NTP_ORPHAN_MODE_MSK + uint32_t reserved_1; ///< Future use + uint32_t reserved_2; ///< Future use + uint32_t reserved_3; ///< Future use + +} NTP_MISC_ORPHAN_MODE_INFO; + +#define _mbg_swab_ntp_misc_orphan_mode_info( _p ) \ +do \ +{ \ + _mbg_swab_ntp_misc_orphan_mode_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_flags ); \ +} while ( 0 ) + + +/** + * @brief NTP leapfile settings to be read from / written to a device + * + * If ::NTP_MISC_MSK_LEAPFILE is set in ::NTP_MISC_LIMITS::supp_flags + * ::NTP_MISC_LEAPFILE_SETTINGS can be read / written. + */ +typedef struct +{ + uint8_t enable; ///< Generally enable / disable leapfile + uint8_t reserved_1; ///< Stratum level when no ref source available + uint16_t reserved_2; ///< Future use + +} NTP_MISC_LEAPFILE_SETTINGS; + +#define _mbg_swab_ntp_misc_leapfile_settings( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->reserved_2 ); \ +} while ( 0 ) + + +#else // !defined( _PRELIMINARY_CODE ), dummy declarations + + typedef int NTP_RESTR_LIMITS; + typedef int NTP_RESTR; + typedef int NTP_RESTR_IDX; + typedef int NTP_DISCARD_LIMITS; + typedef int NTP_DISCARD_SETTINGS; + typedef int NTP_REFCLK_CFG_SETTINGS; + typedef int NTP_REFCLK_CFG_SETTINGS_IDX; + typedef int NTP_REFCLK_CFG_INFO; + typedef int NTP_REFCLK_CFG_INFO_IDX; + typedef int NTP_SYMM_KEY_LIMITS; + typedef int NTP_SYMM_KEY_SETTINGS; + typedef int NTP_SYMM_KEY_SETTINGS_IDX; + typedef int NTP_SYMM_KEY_INFO; + typedef int NTP_SYMM_KEY_INFO_IDX; + typedef int NTP_TRUSTED_KEY_SETTINGS; + typedef int NTP_TRUSTED_KEY_SETTINGS_IDX; + typedef int NTP_TRUSTED_KEY_INFO; + typedef int NTP_TRUSTED_KEY_INFO_IDX; + typedef int NTP_STATS_GLB_SETTINGS; + typedef int NTP_STATS_GLB_INFO; + typedef int NTP_MISC_LIMITS; + typedef int NTP_MISC_DRIFTFILE_SETTINGS; + typedef int NTP_MISC_ORPHAN_MODE_SETTINGS; + typedef int NTP_MISC_ORPHAN_MODE_INFO; + typedef int NTP_MISC_LEAPFILE_SETTINGS; + +#endif // defined( _PRELIMINARY_CODE ) + + +/** + * @brief Client settings of an NTP device + * + * This structure should be sent to an NTP client to configure client parameters + */ +typedef struct +{ + uint8_t num_peers; ///< number available peers + uint8_t reserved_1; ///< reserved, currently 0 + uint16_t reserved_2; ///< reserved, currently 0 + + uint32_t reserved_3; ///< reserved, currently 0 + + uint32_t flags; ///< NTP flags, see @ref NTP_FLAG_MASKS + +} NTP_CLNT_MODE_SETTINGS; + +#define _mbg_swab_ntp_clnt_mode_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Client settings info of an NTP device + * + * This structure can be used to determine possible NTP client settings and the current configuration + */ +typedef struct +{ + NTP_CLNT_MODE_SETTINGS settings; + + uint8_t n_supp_peers; ///< maximal number of configurable peers + uint8_t n_supp_pref_peers; ///< maximal number of configurable preferred ref sources + uint8_t poll_intv_min; ///< minimal supported NTP polling interval + uint8_t poll_intv_max; ///< maximal supported NTP polling interval + + uint32_t reserved_1; ///< reserved, currently 0 + uint32_t reserved_2; ///< reserved, currently 0 + + uint32_t supp_flags; ///< supported NTP flags, see @ref NTP_FLAG_MASKS + uint32_t supp_peer_flags; ///< supported NTP flags for peers, see @ref NTP_FLAG_MASKS + +} NTP_CLNT_MODE_INFO; + +#define _mbg_swab_ntp_clnt_mode_info( _p ) \ +do \ +{ \ + _mbg_swab_ntp_clnt_mode_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->supp_flags ); \ + _mbg_swab32( &(_p)->supp_peer_flags ); \ +} while ( 0 ) + + + +/** + * @brief General NTP peer settings limits to be read from a device + * + * Used to query from a device how many NTP associations are supported + * by the device, then index 0..::NTP_PEER_LIMITS::n_cur_peers-1 + * peer records can be read from a device. A maximum of + * ::NTP_PEER_LIMITS::n_supp_peers can be configured at all. + */ +typedef struct +{ + uint16_t n_supp_peers; ///< maximum number of configurable peers + uint16_t n_cur_peers; ///< current number of configured peers + + uint8_t poll_intv_min; ///< minimum supported NTP polling interval + uint8_t poll_intv_max; ///< maximum supported NTP polling interval + uint8_t reserved_1; ///< reserved, currently 0 + uint8_t reserved_2; ///< reserved, currently 0 + + uint32_t supp_assoc_types; ///< supported types of NTP associations + uint32_t reserved_3; ///< reserved, currently 0 + + uint32_t supp_flags_server; ///< supported flags for unicast associations + uint32_t supp_flags_peer; ///< supported flags for unicast symmetric-active assocations + uint32_t supp_flags_pool; ///< supported flags for unicast pool associations + uint32_t supp_flags_broadcast; ///< supported flags for broadcast associations + uint32_t supp_flags_multicast; ///< supported flags for multicast associations + uint32_t supp_flags_manycast; ///< supported flags for manycast associations + uint32_t supp_flags_broadcastclient; ///< supported flags for broadcast client associations + uint32_t supp_flags_multicastclient; ///< supported flags for multicast client associations + uint32_t supp_flags_manycastclient; ///< supported flags for manycast client associations + uint32_t reserved_4; ///< reserved, currently 0 + uint32_t reserved_5; ///< reserved, currently 0 + uint32_t reserved_6; ///< reserved, currently 0 + +} NTP_PEER_LIMITS; + +#define _mbg_swab_ntp_peer_limits( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->n_supp_peers ); \ + _mbg_swab16( &(_p)->n_cur_peers ); \ + _mbg_swab32( &(_p)->supp_assoc_types ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ + _mbg_swab32( &(_p)->supp_flags_server ); \ + _mbg_swab32( &(_p)->supp_flags_peer ); \ + _mbg_swab32( &(_p)->supp_flags_pool ); \ + _mbg_swab32( &(_p)->supp_flags_broadcast ); \ + _mbg_swab32( &(_p)->supp_flags_multicast ); \ + _mbg_swab32( &(_p)->supp_flags_manycast ); \ + _mbg_swab32( &(_p)->supp_flags_broadcastclient ); \ + _mbg_swab32( &(_p)->supp_flags_multicastclient ); \ + _mbg_swab32( &(_p)->supp_flags_manycastclient ); \ + _mbg_swab32( &(_p)->reserved_4 ); \ + _mbg_swab32( &(_p)->reserved_5 ); \ + _mbg_swab32( &(_p)->reserved_6 ); \ +} while ( 0 ) + + + +/** + * @brief Peer settings for NTP devices to configure an upload NTP server + * + * This structure should be read from the NTP client device to retrieve the + * current settings and capabilities. The number of supported peers is + * ::NTP_CLNT_MODE_INFO::n_supp_peers. + * + * @note The ::NTP_PEER_SETTINGS_IDX structure should be send back + * to the device to save the configuration. + */ +typedef struct +{ + MBG_HOSTNAME hostname; ///< hostname or IP address of the peer, not used + ///< when the NTP_BROADCASTCLIENT flag is set + + uint8_t min_poll; ///< minimal configurable NTP polling interval + uint8_t max_poll; ///< maximal configurable NTP polling interval + uint8_t ttl; ///< time-to-live to use with broadcast/multicast/manycast + uint8_t reserved_1; ///< reserved, currently 0 + + uint32_t key; ///< ID of the symmetric key used with this association, + ///< this must be in the range 1-65534, 0 = disabled + uint32_t reserved_3; ///< reserved, currently 0 + uint32_t reserved_4; ///< reserved, currently 0 + + uint32_t flags; ///< additional options configured, see @ref NTP_FLAG_MASKS + +} NTP_PEER_SETTINGS; + +#define _mbg_swab_ntp_peer_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->key ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ + _mbg_swab32( &(_p)->reserved_4 ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Peer settings for NTP devices + * + * @see ::NTP_PEER_SETTINGS + */ +typedef struct +{ + uint32_t idx; + NTP_PEER_SETTINGS peer_settings; + +} NTP_PEER_SETTINGS_IDX; + +#define _mbg_swab_ntp_peer_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_ntp_peer_settings( &(_p)->peer_settings ); \ +} while ( 0 ) + + +/** + * @brief Server settings of an NTP device + * + * This structure should be sent to an NTP server to configure server parameters + */ +typedef struct +{ + uint8_t num_refclks; ///< number of available refclks @ref NTP_REFCLK_CFG_INFO + uint8_t reserved_1; ///< reserved, currently 0 + uint16_t reserved_2; ///< reserved, currently 0 + + uint32_t reserved_3; ///< reserved, currently 0 + + uint32_t flags; ///< NTP flags, see @ref NTP_FLAG_MASKS + +} NTP_SRV_MODE_SETTINGS; + +#define _mbg_swab_ntp_srv_mode_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + +/** + * @brief Server settings info of an NTP device + * + * This structure should be used to query an NTP server configuration from a device + */ +typedef struct +{ + NTP_SRV_MODE_SETTINGS settings; + + uint8_t max_refclks; ///< number of supported refclks @ref NTP_REFCLK_CFG_INFO + uint8_t reserved_1; ///< reserved, currently 0 + uint16_t reserved_2; ///< reserved, currently 0 + + uint32_t reserved_3; ///< reserved, currently 0 + + uint32_t supp_flags; ///< supported NTP flags, see @ref NTP_FLAG_MASKS + +} NTP_SRV_MODE_INFO; + +#define _mbg_swab_ntp_srv_mode_info( _p ) \ +do \ +{ \ + _mbg_swab_ntp_srv_mode_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_flags ); \ +} while ( 0 ) + + +/** + * @brief Structure that represents a timestamp in NTP Short Format + * + * Maximal value for seconds is 65535. + * Resolution of fractions is 15 microseconds. + */ +typedef struct +{ + uint16_t seconds; + uint16_t fractions; + +} NTP_SHORT_TSTAMP; + +#define _mbg_swab_ntp_short_tstamp( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->seconds ); \ + _mbg_swab16( &(_p)->fractions ); \ +} + + + +/** + * @brief Structure that represents a timestamp in NTP Timestamp Format + */ +typedef struct +{ + uint32_t seconds; ///< seconds since NTP epoch, see ::NTP_SEC_BIAS + uint32_t fractions; ///< binary fractional part of a second, 0xFFFFFFFF -> 0.9999999... s (resolution 2^-32s =~ 233 ps) + +} NTP_TSTAMP; + +#define _mbg_swab_ntp_tstamp( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->seconds ); \ + _mbg_swab32( &(_p)->fractions ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of known NTP implementations + * + * Used with ::NTP_SYS_STATE::impl_type + */ +enum NTP_IMPL +{ + NTP_IMPL_UNKNOWN = 0, ///< Unknown NTP implementation + NTP_IMPL_NTPD, ///< Network Time Protocol daemon (ntpd) + NTP_IMPL_NTPDATE, ///< NTP client only (ntpdate) + NTP_IMPL_SNTP, ///< Simple Network Time Protocol (sntp) + NTP_IMPL_W32TIME, ///< Windows time service (w32time) + NTP_IMPL_MBGNTP, ///< Meinberg NTP implementation (mbgntp) + N_NTP_IMPLS +}; + +/* + * Default initializers for English leapsecond string names. Initializers + * for multi-language strings can be found in tmonlstr.h. + */ +#define MBG_NTP_IMPL_STR_ENG "Implemetation Type:" + +#define MBG_NTP_IMPL_STR_ENG_UNKNOWN "Unknown NTP implementation" +#define MBG_NTP_IMPL_STR_ENG_NTPD "Network Time Protocol daemon (ntpd)" +#define MBG_NTP_IMPL_STR_ENG_NTPDATE "NTP client only (ntpdate)" +#define MBG_NTP_IMPL_STR_ENG_SNTP "Simple Network Time Protocol (sntp)" +#define MBG_NTP_IMPL_STR_ENG_W32TIME "Windows time service (w32time)" +#define MBG_NTP_IMPL_STR_ENG_MBGNTP "Meinberg NTP implementation (mbgntp)" + + +#define MBG_NTP_IMPL_NAMES_ENG \ +{ \ + MBG_NTP_IMPL_STR_ENG_UNKNOWN, \ + MBG_NTP_IMPL_STR_ENG_NTPD, \ + MBG_NTP_IMPL_STR_ENG_NTPDATE, \ + MBG_NTP_IMPL_STR_ENG_SNTP, \ + MBG_NTP_IMPL_STR_ENG_W32TIME, \ + MBG_NTP_IMPL_STR_ENG_MBGNTP \ +} + + + +/** + * @brief Enumeration of CPU types using NTP + * + * Used with ::NTP_SYS_STATE::cpu_type + */ +enum NTP_CPU_TYPES +{ + NTP_CPU_TYPE_UNKNOWN = 0, + NTP_CPU_TYPE_X86, + NTP_CPU_TYPE_I386, + NTP_CPU_TYPE_I486, + NTP_CPU_TYPE_I586, + NTP_CPU_TYPE_I686, + NTP_CPU_TYPE_X64, + NTP_CPU_TYPE_X86_64, + NTP_CPU_TYPE_AMD64, + NTP_CPU_TYPE_SUN4U, + NTP_CPU_TYPE_ARM, + N_NTP_CPU_TYPES +}; + + + +/** + * @brief Name strings for known CPU types using NTP + * + * @see ::NTP_CPU_TYPES + */ +#define NTP_CPU_TYPES_STRS \ +{ \ + "Unknown", \ + "x86", \ + "i386", \ + "i486", \ + "i586", \ + "i686", \ + "x64", \ + "x86_64", \ + "amd64", \ + "sun4u", \ + "arm" \ +} + + + +/** + * @brief Enumeration of operating systems using NTP + * + * Used with ::NTP_SYS_STATE::system +*/ +enum NTP_SYSTEMS +{ + NTP_SYSTEM_UNKNOWN = 0, + NTP_SYSTEM_NONE, + NTP_SYSTEM_WINDOWS, + NTP_SYSTEM_LINUX, + NTP_SYSTEM_BSD, + NTP_SYSTEM_SOLARIS, + N_NTP_SYSTEMS +}; + + + +/** + * @brief Name strings for operating systens using NTP + * + * @see ::NTP_SYSTEMS + */ +#define NTP_SYSTEMS_STRS \ +{ \ + "Unknown", \ + "No OS", \ + "Windows", \ + "Linux", \ + "BSD", \ + "Solaris" \ +} + + + +/** + * @brief Enumeration of NTP leap indication bits + * + * Used with ::NTP_SYS_STATE::leap_ind + * + */ +enum NTP_LI_BITS +{ + NTP_LEAP_NONE = 0, ///< normal synchronized state + NTP_LEAP_ADD_SEC, ///< insert second after 23:59:59 of the current day + NTP_LEAP_DEL_SEC, ///< delete second 23:59:59 of the current day + NTP_LEAP_ALARM, ///< never synchronized + N_NTP_LI_BITS +}; + + + +/* + * Default initializers for English leapsecond string names. Initializers + * for multi-language strings can be found in tmonlstr.h. + */ +#define MBG_NTP_LEAP_STR_ENG "Leapsecond indication:" + +#define MBG_NTP_LEAP_STR_ENG_NONE "None" +#define MBG_NTP_LEAP_STR_ENG_ADD_SEC "Insert second" +#define MBG_NTP_LEAP_STR_ENG_DEL_SEC "Delete second" +#define MBG_NTP_LEAP_STR_ENG_ALARM "Alarm" + +#define MBG_NTP_LEAP_NAMES_ENG \ +{ \ + MBG_NTP_LEAP_STR_ENG_NONE, \ + MBG_NTP_LEAP_STR_ENG_ADD_SEC, \ + MBG_NTP_LEAP_STR_ENG_DEL_SEC, \ + MBG_NTP_LEAP_STR_ENG_ALARM \ +} + + + +/** + * @brief Enumeration of NTP synchronization source bits + * + * Used with ::NTP_SYS_STATE::sys_sync_src + * + */ +enum NTP_SYNC_SRC_BITS +{ + NTP_SYNC_SRC_UNSPEC = 0, ///< not yet synchronized + NTP_SYNC_SRC_PPS, ///< pulse-per-second signal (Cs, Ru, GPS, etc.) + NTP_SYNC_SRC_LF_RADIO, ///< VLF/LF radio (WWVB, DCF77, etc.) + NTP_SYNC_SRC_HF_RADIO, ///< MF/HF radio (WWV, etc.) + NTP_SYNC_SRC_UHF_RADIO, ///< VHF/UHF radio/satellite (GPS, Galileo, etc.) + NTP_SYNC_SRC_LOCAL, ///< local timecode (IRIG, LOCAL driver, etc.) + NTP_SYNC_SRC_NTP, ///< NTP + NTP_SYNC_SRC_OTHER, ///< other (IEEE 1588, openntp, crony, etc.) + NTP_SYNC_SRC_WRISTWATCH, ///< eyeball and wristwatch + NTP_SYNC_SRC_TELEPHONE, ///< telephone modem (ACTS, PTB, etc.) + N_NTP_SYNC_SRC_BITS +}; + + + +/* + * Default initializers for English sync source string names. Initializers + * for multi-language strings can be found in tmonlstr.h. + */ +#define MBG_NTP_SYNC_SRC_STR_ENG_LABEL "Sync Source:" + +#define MBG_NTP_SYNC_SRC_STR_ENG_UNSPEC "Not yet synchronized" +#define MBG_NTP_SYNC_SRC_STR_ENG_PPS "Pulse per second signal" +#define MBG_NTP_SYNC_SRC_STR_ENG_LF_RADIO "VLF/LF radio" +#define MBG_NTP_SYNC_SRC_STR_ENG_HF_RADIO "MF/HF radio" +#define MBG_NTP_SYNC_SRC_STR_ENG_UHF_RADIO "VHF/UHF radio/satellite" +#define MBG_NTP_SYNC_SRC_STR_ENG_LOCAL "local timecode" +#define MBG_NTP_SYNC_SRC_STR_ENG_NTP "NTP" +#define MBG_NTP_SYNC_SRC_STR_ENG_OTHER "other" +#define MBG_NTP_SYNC_SRC_STR_ENG_WRISTWATCH "eyeball and wristwatch" +#define MBG_NTP_SYNC_SRC_STR_ENG_TELEPHONE "telephone modem" + +#define MBG_NTP_SYNC_SRC_NAMES_ENG \ +{ \ + MBG_NTP_SYNC_SRC_STR_ENG_UNSPEC, \ + MBG_NTP_SYNC_SRC_STR_ENG_PPS, \ + MBG_NTP_SYNC_SRC_STR_ENG_LF_RADIO, \ + MBG_NTP_SYNC_SRC_STR_ENG_HF_RADIO, \ + MBG_NTP_SYNC_SRC_STR_ENG_UHF_RADIO, \ + MBG_NTP_SYNC_SRC_STR_ENG_LOCAL, \ + MBG_NTP_SYNC_SRC_STR_ENG_NTP, \ + MBG_NTP_SYNC_SRC_STR_ENG_OTHER, \ + MBG_NTP_SYNC_SRC_STR_ENG_WRISTWATCH, \ + MBG_NTP_SYNC_SRC_STR_ENG_TELEPHONE \ +} + + + +/** + * @brief Enumeration of NTP system event message bits + * + * Used with ::NTP_SYS_STATE::sys_rec_evt + * + */ +enum NTP_SYS_EVT_BITS +{ + NTP_SYS_EVT_UNSPEC = 0, ///< unspecified NTP event + NTP_SYS_EVT_FREQ_NOT_SET, ///< frequency file not available + NTP_SYS_EVT_FREQ_SET, ///< frequency set from frequency file + NTP_SYS_EVT_SPIKE_DETECT, ///< spike detected + NTP_SYS_EVT_FREQ_MODE, ///< initial frequency training mode + NTP_SYS_EVT_CLOCK_SYNC, ///< clock synchronized + NTP_SYS_EVT_RESTART, ///< program restart + NTP_SYS_EVT_PANIC_STOP, ///< clock error more than 600 s + NTP_SYS_EVT_NO_SYSTEM_PEER, ///< no system peer + NTP_SYS_EVT_LEAP_ARMED, ///< leap second armed from file or autokey + NTP_SYS_EVT_LEAP_DISARMED, ///< leap second disarmed + NTP_SYS_EVT_LEAP_EVENT, ///< leap event + NTP_SYS_EVT_CLOCK_STEP, ///< clock stepped + NTP_SYS_EVT_KERNEL, ///< kernel information message + NTP_SYS_EVT_TAI, ///< leapsecond values update from file + NTP_SYS_EVT_STALE_LS_VALUES, ///< new NIST leapseconds file needed + N_NTP_SYS_EVT_BITS +}; + + + +/* + * Default initializers for English sync source string names. Initializers + * for multi-language strings can be found in tmonlstr.h. + */ +#define MBG_NTP_SYS_EVT_STR_ENG_CNT_LABEL "System Event Counter:" +#define MBG_NTP_SYS_EVT_STR_ENG_MSG_LABEL "System Event Message:" + +#define MBG_NTP_SYS_EVT_STR_ENG_UNSPEC "Unspecified NTP event" +#define MBG_NTP_SYS_EVT_STR_ENG_FREQ_NOT_SET "Frequency file not available" +#define MBG_NTP_SYS_EVT_STR_ENG_FREQ_SET "Frequency set from frequency file" +#define MBG_NTP_SYS_EVT_STR_ENG_SPIKE_DETECT "Spike detected" +#define MBG_NTP_SYS_EVT_STR_ENG_FREQ_MODE "Initial frequency training mode" +#define MBG_NTP_SYS_EVT_STR_ENG_CLOCK_SYNC "Clock synchronized" +#define MBG_NTP_SYS_EVT_STR_ENG_RESTART "Program restart" +#define MBG_NTP_SYS_EVT_STR_ENG_PANIC_STOP "Clock error more than 600 s" +#define MBG_NTP_SYS_EVT_STR_ENG_NO_SYSTEM_PEER "No system peer" +#define MBG_NTP_SYS_EVT_STR_ENG_LEAP_ARMED "Leap second armed from file or autokey" +#define MBG_NTP_SYS_EVT_STR_ENG_LEAP_DISARMED "Leap second disarmed" +#define MBG_NTP_SYS_EVT_STR_ENG_LEAP_EVENT "Leap event" +#define MBG_NTP_SYS_EVT_STR_ENG_CLOCK_STEP "Clock stepped" +#define MBG_NTP_SYS_EVT_STR_ENG_KERNEL "Kernel information message" +#define MBG_NTP_SYS_EVT_STR_ENG_TAI "Leap second values update from file" +#define MBG_NTP_SYS_EVT_STR_ENG_STALE_LS_VALUES "New NIST leapseconds file needed" + + +#define MBG_NTP_SYS_EVT_NAMES_ENG \ +{ \ + MBG_NTP_SYS_EVT_STR_ENG_UNSPEC, \ + MBG_NTP_SYS_EVT_STR_ENG_FREQ_NOT_SET, \ + MBG_NTP_SYS_EVT_STR_ENG_FREQ_SET, \ + MBG_NTP_SYS_EVT_STR_ENG_SPIKE_DETECT, \ + MBG_NTP_SYS_EVT_STR_ENG_FREQ_MODE, \ + MBG_NTP_SYS_EVT_STR_ENG_CLOCK_SYNC, \ + MBG_NTP_SYS_EVT_STR_ENG_RESTART, \ + MBG_NTP_SYS_EVT_STR_ENG_PANIC_STOP, \ + MBG_NTP_SYS_EVT_STR_ENG_NO_SYSTEM_PEER, \ + MBG_NTP_SYS_EVT_STR_ENG_LEAP_ARMED, \ + MBG_NTP_SYS_EVT_STR_ENG_LEAP_DISARMED, \ + MBG_NTP_SYS_EVT_STR_ENG_LEAP_EVENT, \ + MBG_NTP_SYS_EVT_STR_ENG_CLOCK_STEP, \ + MBG_NTP_SYS_EVT_STR_ENG_KERNEL, \ + MBG_NTP_SYS_EVT_STR_ENG_TAI, \ + MBG_NTP_SYS_EVT_STR_ENG_STALE_LS_VALUES \ +} + + + +/** + * @brief Enumeration of supported NTP system state values + * + * @see ::NTP_SYS_STATE_SUPP_FLAG_MASKS + */ +enum NTP_SYS_STATE_SUPP_FLAGS +{ + NTP_SYS_STATE_SUPP_STD = 0, ///< supports standard values of ::NTP_SYS_STATE, all fields except below and reserved + NTP_SYS_STATE_SUPP_EVENTS, ///< supports sys state events (::NTP_SYS_STATE::sys_evt_cnt, ::NTP_SYS_STATE::sys_rec_evt) + NTP_SYS_STATE_SUPP_PRECISION, ///< supports precision indication, see ::NTP_SYS_STATE::precision + NTP_SYS_STATE_SUPP_ROOT_DELAY, ///< supports root delay to syspeer, see ::NTP_SYS_STATE::root_delay + NTP_SYS_STATE_SUPP_ROOT_DISP, ///< supports root dispersion, see ::NTP_SYS_STATE::root_disp + NTP_SYS_STATE_SUPP_FREQ, ///< supports frequency offset, see ::NTP_SYS_STATE::freq + NTP_SYS_STATE_SUPP_SYS_JITTER, ///< supports combined jitter, see ::NTP_SYS_STATE::sys_jitter + NTP_SYS_STATE_SUPP_CLK_JITTER, ///< supports clock jitter, see ::NTP_SYS_STATE::clk_jitter + NTP_SYS_STATE_SUPP_CLK_WANDER, ///< supports clock wander, see ::NTP_SYS_STATE::clk_wander + NTP_SYS_STATE_SUPP_SYS_ASSOC, ///< supports sys assoc ID as sys peer, see ::NTP_SYS_STATE::sys_assoc + N_NTP_SYS_STATE_SUPP_FLAGS +}; + + + +/** + * @brief Flag masks for NTP_SYS_STATE_SUPP_FLAGS + * + * Used with ::NTP_SYS_STATE::supp_flags + * + * @see ::NTP_SYS_STATE_SUPP_FLAGS + */ +enum NTP_SYS_STATE_SUPP_FLAG_MASKS +{ + NTP_SYS_STATE_SUPP_STD_MSK = ( 1UL << NTP_SYS_STATE_SUPP_STD ), ///< see ::NTP_SYS_STATE_SUPP_STD + NTP_SYS_STATE_SUPP_EVENTS_MSK = ( 1UL << NTP_SYS_STATE_SUPP_EVENTS ), ///< see ::NTP_SYS_STATE_SUPP_EVENTS + NTP_SYS_STATE_SUPP_PRECISION_MSK = ( 1UL << NTP_SYS_STATE_SUPP_PRECISION ), ///< see ::NTP_SYS_STATE_SUPP_PRECISION + NTP_SYS_STATE_SUPP_ROOT_DELAY_MSK = ( 1UL << NTP_SYS_STATE_SUPP_ROOT_DELAY ), ///< see ::NTP_SYS_STATE_SUPP_ROOT_DELAY + NTP_SYS_STATE_SUPP_ROOT_DISP_MSK = ( 1UL << NTP_SYS_STATE_SUPP_ROOT_DISP ), ///< see ::NTP_SYS_STATE_SUPP_ROOT_DISP + NTP_SYS_STATE_SUPP_FREQ_MSK = ( 1UL << NTP_SYS_STATE_SUPP_FREQ ), ///< see ::NTP_SYS_STATE_SUPP_FREQ + NTP_SYS_STATE_SUPP_SYS_JITTER_MSK = ( 1UL << NTP_SYS_STATE_SUPP_SYS_JITTER ), ///< see ::NTP_SYS_STATE_SUPP_SYS_JITTER + NTP_SYS_STATE_SUPP_CLK_JITTER_MSK = ( 1UL << NTP_SYS_STATE_SUPP_CLK_JITTER ), ///< see ::NTP_SYS_STATE_SUPP_CLK_JITTER + NTP_SYS_STATE_SUPP_CLK_WANDER_MSK = ( 1UL << NTP_SYS_STATE_SUPP_CLK_WANDER ), ///< see ::NTP_SYS_STATE_SUPP_CLK_WANDER + NTP_SYS_STATE_SUPP_SYS_ASSOC_MSK = ( 1UL << NTP_SYS_STATE_SUPP_SYS_ASSOC ) ///< see ::NTP_SYS_STATE_SUPP_SYS_ASSOC +}; + + + +/** + * @brief Structure that represents the current system status of an NTP device + * + * This structure can be requested from a monitoring program to determine the device system status + */ +typedef struct +{ + uint32_t supp_flags; ///< Supported NTP system state values, see ::NTP_SYS_STATE_SUPP_FLAG_MASKS + + uint8_t leap_ind; ///< Leap indicator, see ::NTP_LI_BITS + uint8_t sys_sync_src; ///< Current synchronization source, see ::NTP_SYNC_SRC_BITS + uint8_t sys_evt_cnt; ///< Number of events, since the last time the event code changed + uint8_t sys_rec_evt; ///< Most recent event message, see ::NTP_SYS_EVT_BITS + + uint8_t impl_type; ///< NTP implementation type, see ::NTP_IMPL + uint8_t major_version; ///< Major version number + uint8_t minor_version; ///< Minor version number + uint8_t micro_version; ///< Micro version number + + uint16_t patch_lvl; ///< Patch level number + uint8_t cpu_type; ///< Processor type, see ::NTP_CPU_TYPES + uint8_t system; ///< Operating system, see ::NTP_SYSTEMS + + uint8_t stratum; ///< Current stratum level of the system + int8_t precision; ///< Precision of the system clock (2^precision) + uint16_t sys_assoc; ///< Association ID of the current system peer, do not use NTP_SYS_STATE::sys_peer if this is supported + + int32_t root_delay; ///< [us] Total roundtrip delay to the system peer + int32_t root_disp; ///< [us] Total dispersion to the system peer + + MBG_IP_ADDR ref_id; ///< Reference ID of the current system peer, see ::MBG_IP_ADDR + + NTP_TSTAMP ref_time; ///< Last time the system time has been adjusted, see ::NTP_TSTAMP + NTP_TSTAMP sys_time; ///< Current system time, see ::NTP_TSTAMP + + uint16_t sys_peer; ///< Index of the current system peer + uint8_t poll; ///< Current polling interval for the system peer (tc) + uint8_t minpoll; ///< Minimal polling interval for the system peer (mintc) + + int64_t offset; ///< [ns] Combined offset to the system peer + + int32_t freq; ///< [ppb] Frequency offset relative to hardware clock + int32_t sys_jitter; ///< [us] Combined jitter of the system + int32_t clk_jitter; ///< [us] Jitter of the clock + int32_t clk_wander; ///< [ppb] Frequency wander of the clock + + uint8_t cfg_counter; ///< Updated (increased) when config changes + uint8_t reserved_1; ///< Reserved, currently always 0 + uint16_t reserved_2; ///< Reserved, currently always 0 + + uint32_t reserved_3; ///< Reserved, currently always 0 + +} NTP_SYS_STATE; + +#define _mbg_swab_ntp_sys_state( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->supp_flags ); \ + \ + _mbg_swab8( &(_p)->leap_ind ); \ + _mbg_swab8( &(_p)->sys_sync_src ); \ + _mbg_swab8( &(_p)->sys_evt_cnt ); \ + _mbg_swab8( &(_p)->sys_rec_evt ); \ + \ + _mbg_swab8( &(_p)->impl_type ); \ + _mbg_swab8( &(_p)->major_version ); \ + _mbg_swab8( &(_p)->minor_version ); \ + _mbg_swab8( &(_p)->micro_version ); \ + \ + _mbg_swab16( &(_p)->patch_lvl ); \ + _mbg_swab8( &(_p)->cpu_type ); \ + _mbg_swab8( &(_p)->system ); \ + \ + _mbg_swab8( &(_p)->stratum ); \ + _mbg_swab8( &(_p)->precision ); \ + _mbg_swab16( &(_p)->sys_assoc ); \ + \ + _mbg_swab32( &(_p)->root_delay ); \ + _mbg_swab32( &(_p)->root_disp ); \ + \ + _mbg_swab_ip_addr( &(_p)->ref_id ); \ + \ + _mbg_swab_ntp_tstamp( &(_p)->ref_time ); \ + _mbg_swab_ntp_tstamp( &(_p)->sys_time ); \ + \ + _mbg_swab16( &(_p)->sys_peer ); \ + _mbg_swab8( &(_p)->poll ); \ + _mbg_swab8( &(_p)->minpoll ); \ + \ + _mbg_swab64( &(_p)->offset ); \ + \ + _mbg_swab32( &(_p)->freq ); \ + _mbg_swab32( &(_p)->sys_jitter ); \ + _mbg_swab32( &(_p)->clk_jitter ); \ + _mbg_swab32( &(_p)->clk_wander ); \ + \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ + \ +} while ( 0 ) + + + +/** + * @brief Enumeration of NTP mode bits + * + * Used with ::NTP_PEER_STATE::host_mode and ::NTP_PEER_STATE::peer_mode + * + */ +enum NTP_MODE_BITS +{ + NTP_MODE_RESERVED = 0, + NTP_MODE_SYMM_ACT, + NTP_MODE_SYMM_PASS, + NTP_MODE_CLIENT, + NTP_MODE_SERVER, + NTP_MODE_BROADCAST, + NTP_MODE_CONTROL, + NTP_MODE_PRIVATE, + N_NTP_MODE_BITS +}; + + + +/* + * Default initializers for English NTP peer mode string names. Initializers + * for multi-language strings can be found in tmonlstr.h. + */ +#define MBG_NTP_MODE_STR_ENG_HOST_LABEL "Host Mode:" +#define MBG_NTP_MODE_STR_ENG_PEER_LABEL "Peer Mode:" + +#define MBG_NTP_PEER_MODE_STR_ENG_RESERVED "Reserved" +#define MBG_NTP_PEER_MODE_STR_ENG_SYMM_ACT "Symm Act" +#define MBG_NTP_PEER_MODE_STR_ENG_SYMM_PASS "Symm Pass" +#define MBG_NTP_PEER_MODE_STR_ENG_CLIENT "Client" +#define MBG_NTP_PEER_MODE_STR_ENG_SERVER "Server" +#define MBG_NTP_PEER_MODE_STR_ENG_BROADCAST "Broadcast" +#define MBG_NTP_PEER_MODE_STR_ENG_CONTROL "Control" +#define MBG_NTP_PEER_MODE_STR_ENG_PRIVATE "Private" + +#define MBG_NTP_MODE_STAT_NAMES_ENG \ +{ \ + MBG_NTP_PEER_MODE_STR_ENG_RESERVED, \ + MBG_NTP_PEER_MODE_STR_ENG_SYMM_ACT, \ + MBG_NTP_PEER_MODE_STR_ENG_SYMM_PASS, \ + MBG_NTP_PEER_MODE_STR_ENG_CLIENT, \ + MBG_NTP_PEER_MODE_STR_ENG_SERVER, \ + MBG_NTP_PEER_MODE_STR_ENG_BROADCAST, \ + MBG_NTP_PEER_MODE_STR_ENG_CONTROL, \ + MBG_NTP_PEER_MODE_STR_ENG_PRIVATE \ +} + + + +/** + * @brief Enumeration of NTP peer reach status + * + * Used with ::NTP_PEER_STATE::peer_reach_stat + */ +enum NTP_REACH_STAT_BITS +{ + NTP_REACH_STAT_UNKNOWN = 0, ///< unknown reach status + NTP_REACH_STAT_NO_LINK, ///< no network connection + NTP_REACH_STAT_DNS_UNREACH, ///< DNS server could not be reached + NTP_REACH_STAT_DNS_UNRESOLVED, ///< DNS name could not be resolved + NTP_REACH_STAT_PEER_UNREACH, ///< peer could not be reached + NTP_REACH_STAT_PEER_NOT_SYNC, ///< peer is not sync (leap alarm, stratum 16) + NTP_REACH_STAT_PEER_BAD_QUALITY, ///< peer has bad quality (dispersion, ...) + NTP_REACH_STAT_OK, ///< reach status is fine + N_NTP_REACH_STAT_BITS +}; + + + +/* + * Default initializers for English reach status string names. Initializers + * for multi-language strings can be found in tmonlstr.h. + */ +#define MBG_NTP_PEER_REACH_STAT_STR_ENG_LABEL "Reach State:" + +#define MBG_NTP_PEER_REACH_STAT_STR_ENG_UNKNOWN "Unknown" +#define MBG_NTP_PEER_REACH_STAT_STR_ENG_NO_LINK "No link" +#define MBG_NTP_PEER_REACH_STAT_STR_ENG_DNS_UNREACH "DNS Server unreached" +#define MBG_NTP_PEER_REACH_STAT_STR_ENG_DNS_UNRESOLVED "DNS name not resolved" +#define MBG_NTP_PEER_REACH_STAT_STR_ENG_PEER_UNREACH "Peer not reached" +#define MBG_NTP_PEER_REACH_STAT_STR_ENG_PEER_NOT_SYNC "Peer not sync" +#define MBG_NTP_PEER_REACH_STAT_STR_ENG_PEER_BAD_QUALITY "Peer has bad quality" +#define MBG_NTP_PEER_REACH_STAT_STR_ENG_OK "Good" + +#define MBG_NTP_PEER_REACH_STAT_NAMES_ENG \ +{ \ + MBG_NTP_PEER_REACH_STAT_STR_ENG_UNKNOWN, \ + MBG_NTP_PEER_REACH_STAT_STR_ENG_NO_LINK, \ + MBG_NTP_PEER_REACH_STAT_STR_ENG_DNS_UNREACH, \ + MBG_NTP_PEER_REACH_STAT_STR_ENG_DNS_UNRESOLVED, \ + MBG_NTP_PEER_REACH_STAT_STR_ENG_PEER_UNREACH, \ + MBG_NTP_PEER_REACH_STAT_STR_ENG_PEER_NOT_SYNC, \ + MBG_NTP_PEER_REACH_STAT_STR_ENG_PEER_BAD_QUALITY, \ + MBG_NTP_PEER_REACH_STAT_STR_ENG_OK \ +} + + + +/** + * @brief Enumeration of NTP peer selection status + * + * Used with ::NTP_PEER_STATE::peer_sel_stat + * + */ +enum NTP_PEER_SEL_STATUS_BITS +{ + NTP_PEER_SEL_REJECT = 0, ///< discarded as not valid (TEST10-TEST13) + NTP_PEER_SEL_FALSETICK, ///< discarded by intersection algorithm + NTP_PEER_SEL_EXCESS, ///< discarded by table overflow (not used) + NTP_PEER_SEL_OUTLYER, ///< discarded by the cluster algorithm + NTP_PEER_SEL_CANDIDATE, ///< included by the combine algorithm + NTP_PEER_SEL_BACKUP, ///< backup (more than tos maxclock sources) + NTP_PEER_SEL_SYS_PEER, ///< system peer + NTP_PEER_SEL_PPS_PEER, ///< PPS peer (when the prefer peer is valid) + N_NTP_PEER_SEL_STATUS_BITS +}; + + + +/* + * Default initializers for English peer select status string names. Initializers + * for multi-language strings can be found in tmonlstr.h. + */ +#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_LABEL "Selected Status:" + +#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_REJECT "Not valid" +#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_FALSETICK "Falsetick" +#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_EXCESS "Excess" +#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_OUTLYER "Outlyer" +#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_CANDIDATE "Candidate" +#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_BACKUP "Backup" +#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_SYS_PEER "System Peer" +#define MBG_NTP_PEER_SEL_STATUS_STR_ENG_PPS_PEER "PPS Peer" + +#define MBG_NTP_PEER_SEL_STATUS_NAMES_ENG \ +{ \ + MBG_NTP_PEER_SEL_STATUS_STR_ENG_REJECT, \ + MBG_NTP_PEER_SEL_STATUS_STR_ENG_FALSETICK, \ + MBG_NTP_PEER_SEL_STATUS_STR_ENG_EXCESS, \ + MBG_NTP_PEER_SEL_STATUS_STR_ENG_OUTLYER, \ + MBG_NTP_PEER_SEL_STATUS_STR_ENG_CANDIDATE, \ + MBG_NTP_PEER_SEL_STATUS_STR_ENG_BACKUP, \ + MBG_NTP_PEER_SEL_STATUS_STR_ENG_SYS_PEER, \ + MBG_NTP_PEER_SEL_STATUS_STR_ENG_PPS_PEER \ +} + + + +/** + * @brief Enumeration of NTP peer status codes + * + * @see ::NTP_PEER_STATUS_FLAG_MASKS + * + */ +enum NTP_PEER_STATUS_FLAGS +{ + NTP_PEER_STATUS_BCST = 0, ///< broadcast association + NTP_PEER_STATUS_REACH, ///< host reachable + NTP_PEER_STATUS_AUTHENB, ///< authentication enabled + NTP_PEER_STATUS_AUTH, ///< authentication ok + NTP_PEER_STATUS_CONFIG, ///< persistent association + N_NTP_PEER_STATUS_FLAGS +}; + + +/** + * @brief Flag masks for NTP_PEER_STATUS_FLAGS + * + * Used with ::NTP_PEER_STATE::peer_status_flags + * + * @see ::NTP_PEER_STATUS_FLAGS + */ +enum NTP_PEER_STATUS_FLAG_MASKS +{ + NTP_PEER_STATUS_BCST_MSK = ( 1UL << NTP_PEER_STATUS_BCST ), ///< see ::NTP_PEER_STATUS_BCST + NTP_PEER_STATUS_REACH_MSK = ( 1UL << NTP_PEER_STATUS_REACH ), ///< see ::NTP_PEER_STATUS_REACH + NTP_PEER_STATUS_AUTHENB_MSK = ( 1UL << NTP_PEER_STATUS_AUTHENB ), ///< see ::NTP_PEER_STATUS_AUTHENB + NTP_PEER_STATUS_AUTH_MSK = ( 1UL << NTP_PEER_STATUS_AUTH ), ///< see ::NTP_PEER_STATUS_AUTH + NTP_PEER_STATUS_CONFIG_MSK = ( 1UL << NTP_PEER_STATUS_CONFIG ), ///< see ::NTP_PEER_STATUS_CONFIG +}; + + +/* + * Default initializers for English peer status string names. Initializers + * for multi-language strings can be found in tmonlstr.h. + */ +#define MBG_NTP_PEER_STATUS_STR_ENG_LABEL "Peer Status:" + +#define MBG_NTP_PEER_STATUS_STR_ENG_BCST "Broadcast association" +#define MBG_NTP_PEER_STATUS_STR_ENG_REACH "Host reachable" +#define MBG_NTP_PEER_STATUS_STR_ENG_AUTHENB "Authentication enabled" +#define MBG_NTP_PEER_STATUS_STR_ENG_CONFIG "Persistant assosiation" + +#define MBG_NTP_PEER_STATUS_NAMES_ENG \ +{ \ + MBG_NTP_PEER_STATUS_STR_ENG_BCST, \ + MBG_NTP_PEER_STATUS_STR_ENG_REACH, \ + MBG_NTP_PEER_STATUS_STR_ENG_REACH, \ + MBG_NTP_PEER_STATUS_STR_ENG_AUTHENB, \ + MBG_NTP_PEER_STATUS_STR_ENG_CONFIG \ +} + + + +/** + * @brief Enumeration of NTP peer event message codes + * + * Used with ::NTP_PEER_STATE::peer_rec_evt + * + */ +enum NTP_PEER_EVT_BITS +{ + NTP_PEER_EVT_UNSPEC = 0, ///< unspecified NTP event + NTP_PEER_EVT_MOBILIZE, ///< association mobilized + NTP_PEER_EVT_DEMOBILIZE, ///< association demobilized + NTP_PEER_EVT_UNREACHABLE, ///< server unreachable + NTP_PEER_EVT_REACHABLE, ///< server reachable + NTP_PEER_EVT_RESTART, ///< association restart + NTP_PEER_EVT_NO_REPLY, ///< no server found (ntpdate mode) + NTP_PEER_EVT_RATE_EXCEEDED, ///< rate exceeded (kiss code RATE) + NTP_PEER_EVT_ACCESS_DENIED, ///< access denied (kiss code DENY) + NTP_PEER_EVT_LEAP_ARMED, ///< leap armed from server LI code + NTP_PEER_EVT_SYS_PEER, ///< become system peer + NTP_PEER_EVT_CLOCK_EVENT, ///< see clock status word + NTP_PEER_EVT_BAD_AUTH, ///< authentication failure + NTP_PEER_EVT_POPCORN, ///< popcorn spike suppressor + NTP_PEER_EVT_INTERLEAVE_MODE, ///< entering interleave mode + NTP_PEER_EVT_INTERLEAVE_ERROR, ///< interleave error (recovered) + N_NTP_PEER_EVT_BITS +}; + + + +/* + * Default initializers for English event message codes. Initializers + * for multi-language strings can be found in tmonlstr.h. + */ +#define MBG_NTP_PEER_EVT_STR_ENG_CNT_LABEL "Peer Event Counter:" +#define MBG_NTP_PEER_EVT_STR_ENG_MSG_LABEL "Peer Event Message:" + +#define MBG_NTP_PEER_EVT_STR_ENG_UNSPEC "Unspecified NTP event" +#define MBG_NTP_PEER_EVT_STR_ENG_MOBILIZE "Association mobilized" +#define MBG_NTP_PEER_EVT_STR_ENG_DEMOBILIZE "Association demobilized" +#define MBG_NTP_PEER_EVT_STR_ENG_UNREACHABLE "Server unreachable" +#define MBG_NTP_PEER_EVT_STR_ENG_REACHABLE "Server reachable" +#define MBG_NTP_PEER_EVT_STR_ENG_RESTART "Association restart" +#define MBG_NTP_PEER_EVT_STR_ENG_NO_REPLY "No server found" +#define MBG_NTP_PEER_EVT_STR_ENG_RATE_EXCEEDED "Rate exceeded" +#define MBG_NTP_PEER_EVT_STR_ENG_ACCESS_DENIED "Access denied" +#define MBG_NTP_PEER_EVT_STR_ENG_LEAP_ARMED "Leap second armed from LI code" +#define MBG_NTP_PEER_EVT_STR_ENG_SYS_PEER "Become system Peer" +#define MBG_NTP_PEER_EVT_STR_ENG_CLOCK_EVENT "Clock event" +#define MBG_NTP_PEER_EVT_STR_ENG_BAD_AUTH "Authentication failure" +#define MBG_NTP_PEER_EVT_STR_ENG_POPCORN "Popcorn Spike suspressor" +#define MBG_NTP_PEER_EVT_STR_ENG_INTERLEAVE_MODE "Entering Interleave mode" +#define MBG_NTP_PEER_EVT_STR_ENG_INTERLEAVE_ERROR "Interleave error" + + +#define MBG_NTP_PEER_EVT_NAMES_ENG \ +{ \ + MBG_NTP_PEER_EVT_STR_ENG_UNSPEC, \ + MBG_NTP_PEER_EVT_STR_ENG_MOBILIZE, \ + MBG_NTP_PEER_EVT_STR_ENG_DEMOBILIZE, \ + MBG_NTP_PEER_EVT_STR_ENG_UNREACHABLE, \ + MBG_NTP_PEER_EVT_STR_ENG_REACHABLE, \ + MBG_NTP_PEER_EVT_STR_ENG_RESTART, \ + MBG_NTP_PEER_EVT_STR_ENG_NO_REPLY, \ + MBG_NTP_PEER_EVT_STR_ENG_RATE_EXCEEDED, \ + MBG_NTP_PEER_EVT_STR_ENG_ACCESS_DENIED, \ + MBG_NTP_PEER_EVT_STR_ENG_LEAP_ARMED, \ + MBG_NTP_PEER_EVT_STR_ENG_SYS_PEER, \ + MBG_NTP_PEER_EVT_STR_ENG_CLOCK_EVENT, \ + MBG_NTP_PEER_EVT_STR_ENG_BAD_AUTH, \ + MBG_NTP_PEER_EVT_STR_ENG_POPCORN, \ + MBG_NTP_PEER_EVT_STR_ENG_INTERLEAVE_MODE, \ + MBG_NTP_PEER_EVT_STR_ENG_INTERLEAVE_ERROR \ +} + + +/** + * @brief Enumeration of NTP flash status bit codes + * + * @see ::NTP_FLASH_STAT_FLAG_MASKS + * + */ +enum NTP_FLASH_STAT_FLAGS +{ + NTP_FLASH_STAT_PKT_DUP = 0, ///< duplicate packet + NTP_FLASH_STAT_PKT_BOGUS, ///< bogus packet + NTP_FLASH_STAT_PKT_UNSYNC, ///< server not synchronized + NTP_FLASH_STAT_PKT_DENIED, ///< access denied + NTP_FLASH_STAT_PKT_AUTH, ///< authentication failure + NTP_FLASH_STAT_PKT_STRATUM, ///< invalid leap or stratum + NTP_FLASH_STAT_PKT_HEADER, ///< header distance exceeded + NTP_FLASH_STAT_PKT_AUTOKEY, ///< Autokey sequence error + NTP_FLASH_STAT_PKT_CRYPTO, ///< Autokey protocol error + NTP_FLASH_STAT_PEER_STRATUM, ///< invalid header or stratum + NTP_FLASH_STAT_PEER_DIST, ///< distance threshold exceeded + NTP_FLASH_STAT_PEER_LOOP, ///< synchronization loop + NTP_FLASH_STAT_PEER_UNREACH, ///< unreachable or nonselect + N_NTP_FLASH_STAT_FLAGS +}; + + + +/** + * @brief Flag masks for ::NTP_FLASH_STAT_FLAGS + * + * Used with ::NTP_PEER_STATE::flash_stat_flags + * + * @see ::NTP_FLASH_STAT_FLAGS + */ +enum NTP_FLASH_STAT_FLAG_MASKS +{ + NTP_FLASH_STAT_PKT_DUP_MSK = ( 1UL << NTP_FLASH_STAT_PKT_DUP ), ///< see ::NTP_FLASH_STAT_PKT_DUP + NTP_FLASH_STAT_PKT_BOGUS_MSK = ( 1UL << NTP_FLASH_STAT_PKT_BOGUS ), ///< see ::NTP_FLASH_STAT_PKT_BOGUS + NTP_FLASH_STAT_PKT_UNSYNC_MSK = ( 1UL << NTP_FLASH_STAT_PKT_UNSYNC ), ///< see ::NTP_FLASH_STAT_PKT_UNSYNC + NTP_FLASH_STAT_PKT_DENIED_MSK = ( 1UL << NTP_FLASH_STAT_PKT_DENIED ), ///< see ::NTP_FLASH_STAT_PKT_DENIED + NTP_FLASH_STAT_PKT_AUTH_MSK = ( 1UL << NTP_FLASH_STAT_PKT_AUTH ), ///< see ::NTP_FLASH_STAT_PKT_AUTH + NTP_FLASH_STAT_PKT_STRATUM_MSK = ( 1UL << NTP_FLASH_STAT_PKT_STRATUM ), ///< see ::NTP_FLASH_STAT_PKT_STRATUM + NTP_FLASH_STAT_PKT_HEADER_MSK = ( 1UL << NTP_FLASH_STAT_PKT_HEADER ), ///< see ::NTP_FLASH_STAT_PKT_HEADER + NTP_FLASH_STAT_PKT_AUTOKEY_MSK = ( 1UL << NTP_FLASH_STAT_PKT_AUTOKEY ), ///< see ::NTP_FLASH_STAT_PKT_AUTOKEY + NTP_FLASH_STAT_PKT_CRYPTO_MSK = ( 1UL << NTP_FLASH_STAT_PKT_CRYPTO ), ///< see ::NTP_FLASH_STAT_PKT_CRYPTO + NTP_FLASH_STAT_PEER_STRATUM_MSK = ( 1UL << NTP_FLASH_STAT_PEER_STRATUM ), ///< see ::NTP_FLASH_STAT_PEER_STRATUM + NTP_FLASH_STAT_PEER_DIST_MSK = ( 1UL << NTP_FLASH_STAT_PEER_DIST ), ///< see ::NTP_FLASH_STAT_PEER_DIST + NTP_FLASH_STAT_PEER_LOOP_MSK = ( 1UL << NTP_FLASH_STAT_PEER_LOOP ), ///< see ::NTP_FLASH_STAT_PEER_LOOP + NTP_FLASH_STAT_PEER_UNREACH_MSK = ( 1UL << NTP_FLASH_STAT_PEER_UNREACH ), ///< see ::NTP_FLASH_STAT_PEER_UNREACH +}; - double sqrt_A; /* Square Root of semi-major Axis [sqrt(m)] */ - double e; /* Eccentricity [---] */ - double M0; /* +- Mean Anomaly at Ref. Time [rad] */ - double omega; /* +- Argument of Perigee [rad] */ - double OMEGA0; /* +- Longit. of Asc. Node of orbit plane [rad] */ - double OMEGADOT; /* +- Rate of Right Ascension [rad/sec] */ - double deltai; /* +- [rad] */ - double af0; /* +- Clock Correction Coefficient 0 [sec] */ - double af1; /* +- Clock Correction Coefficient 1 [sec/sec] */ -} ALM; + +/* + * Default initializers for English ntp flash state mask. Initializers + * for multi-language strings can be found in tmonlstr.h. + */ +#define MBG_NTP_FLASH_STR_ENG_LABEL "Flash Status:" + +#define MBG_NTP_FLASH_STR_ENG_PKT_DUP "Duplicate packet" +#define MBG_NTP_FLASH_STR_ENG_PKT_BOGUS "Bogus packet" +#define MBG_NTP_FLASH_STR_ENG_PKT_UNSYNC "Server not synchronized" +#define MBG_NTP_FLASH_STR_ENG_PKT_DENIED "Access denied" +#define MBG_NTP_FLASH_STR_ENG_PKT_AUTH "Authentication failure" +#define MBG_NTP_FLASH_STR_ENG_PKT_STRATUM "Invalid leap or stratum" +#define MBG_NTP_FLASH_STR_ENG_PKT_HEADER "Header distance exceeded" +#define MBG_NTP_FLASH_STR_ENG_PKT_AUTOKEY "Autokey sequence error" +#define MBG_NTP_FLASH_STR_ENG_PKT_CRYPTO "Autokey protocol error" +#define MBG_NTP_FLASH_STR_ENG_PEER_STRATUM "Invalid header or stratum" +#define MBG_NTP_FLASH_STR_ENG_PEER_DIST "Distance threshold exceeded" +#define MBG_NTP_FLASH_STR_ENG_PEER_LOOP "Synchronization loop" +#define MBG_NTP_FLASH_STR_ENG_PEER_UNREACH "Unreachable or nonselect" + + +#define MBG_NTP_FLASH_NAMES_ENG \ +{ \ + MBG_NTP_FLASH_STR_ENG_PKT_DUP, \ + MBG_NTP_FLASH_STR_ENG_PKT_BOGUS, \ + MBG_NTP_FLASH_STR_ENG_PKT_UNSYNC, \ + MBG_NTP_FLASH_STR_ENG_PKT_DENIED, \ + MBG_NTP_FLASH_STR_ENG_PKT_AUTH, \ + MBG_NTP_FLASH_STR_ENG_PKT_STRATUM, \ + MBG_NTP_FLASH_STR_ENG_PKT_HEADER, \ + MBG_NTP_FLASH_STR_ENG_PKT_AUTOKEY, \ + MBG_NTP_FLASH_STR_ENG_PKT_CRYPTO, \ + MBG_NTP_FLASH_STR_ENG_PEER_STRATUM, \ + MBG_NTP_FLASH_STR_ENG_PEER_DIST, \ + MBG_NTP_FLASH_STR_ENG_PEER_LOOP, \ + MBG_NTP_FLASH_STR_ENG_PEER_UNREACH \ +} + + + +/** + * @brief Enumeration of supported NTP peer state values + * + * @see ::NTP_PEER_STATE_SUPP_FLAG_MASKS + */ +enum NTP_PEER_STATE_SUPP_FLAGS +{ + NTP_PEER_STATE_SUPP_STD, ///< supports standard values of ::NTP_PEER_STATE, all fields except below and reserved + NTP_PEER_STATE_SUPP_ASS_ID, ///< supports association ID, see ::NTP_PEER_STATE::ass_id + NTP_PEER_STATE_SUPP_EVENTS, ///< supports peer state events (NTP_PEER_STATE::peer_evt_cnt, NTP_PEER_STATE::peer_rec_evt) + NTP_PEER_STATE_SUPP_REACH_STAT, ///< supports peer reach status, see ::NTP_PEER_STATE::peer_reach_stat + NTP_PEER_STATE_SUPP_PRECISION, ///< supports precision indication, see ::NTP_PEER_STATE::precision + NTP_PEER_STATE_SUPP_ROOT_DELAY, ///< supports root delay to syspeer, see ::NTP_PEER_STATE::root_delay + NTP_PEER_STATE_SUPP_ROOT_DISP, ///< supports root dispersion, see ::NTP_PEER_STATE::root_disp + NTP_PEER_STATE_SUPP_HEADWAY, ///< supports headway, see ::NTP_PEER_STATE::headway + NTP_PEER_STATE_SUPP_FLASH_STAT, ///< supports flash status word, see ::NTP_PEER_STATE::flash_stat_flags + NTP_PEER_STATE_SUPP_KEY_ID, ///< supports symmetric key id, see ::NTP_PEER_STATE::key_id + NTP_PEER_STATE_SUPP_DISP, ///< supports filter dispersion, see ::NTP_PEER_STATE::disp + NTP_PEER_STATE_SUPP_JITTER, ///< supports filter jitter, see ::NTP_PEER_STATE::jitter + NTP_PEER_STATE_SUPP_XLEAVE, ///< supports interleave delay, see ::NTP_PEER_STATE::xleave + N_NTP_PEER_STATE_SUPP_FLAGS +}; + + +/** + * @brief Flag masks for NTP_PEER_STATE_SUPP_FLAGS + * + * Used with ::NTP_PEER_STATE::supp_flags + * + * @see ::NTP_PEER_STATE_SUPP_FLAGS + */ +enum NTP_PEER_STATE_SUPP_FLAG_MASKS +{ + NTP_PEER_STATE_SUPP_STD_MSK = ( 1UL << NTP_PEER_STATE_SUPP_STD ), ///< see ::NTP_PEER_STATE_SUPP_STD + NTP_PEER_STATE_SUPP_ASS_ID_MSK = ( 1UL << NTP_PEER_STATE_SUPP_ASS_ID ), ///< see ::NTP_PEER_STATE_SUPP_ASS_ID + NTP_PEER_STATE_SUPP_EVENTS_MSK = ( 1UL << NTP_PEER_STATE_SUPP_EVENTS ), ///< see ::NTP_PEER_STATE_SUPP_EVENTS + NTP_PEER_STATE_SUPP_REACH_STAT_MSK = ( 1UL << NTP_PEER_STATE_SUPP_REACH_STAT ), ///< see ::NTP_PEER_STATE_SUPP_REACH_STAT + NTP_PEER_STATE_SUPP_PRECISION_MSK = ( 1UL << NTP_PEER_STATE_SUPP_PRECISION ), ///< see ::NTP_PEER_STATE_SUPP_PRECISION + NTP_PEER_STATE_SUPP_ROOT_DELAY_MSK = ( 1UL << NTP_PEER_STATE_SUPP_ROOT_DELAY ), ///< see ::NTP_PEER_STATE_SUPP_ROOT_DELAY + NTP_PEER_STATE_SUPP_ROOT_DISP_MSK = ( 1UL << NTP_PEER_STATE_SUPP_ROOT_DISP ), ///< see ::NTP_PEER_STATE_SUPP_ROOT_DISP + NTP_PEER_STATE_SUPP_HEADWAY_MSK = ( 1UL << NTP_PEER_STATE_SUPP_HEADWAY ), ///< see ::NTP_PEER_STATE_SUPP_HEADWAY + NTP_PEER_STATE_SUPP_FLASH_STAT_MSK = ( 1UL << NTP_PEER_STATE_SUPP_FLASH_STAT ), ///< see ::NTP_PEER_STATE_SUPP_FLASH_STAT + NTP_PEER_STATE_SUPP_KEY_ID_MSK = ( 1UL << NTP_PEER_STATE_SUPP_KEY_ID ), ///< see ::NTP_PEER_STATE_SUPP_KEY_ID + NTP_PEER_STATE_SUPP_DISP_MSK = ( 1UL << NTP_PEER_STATE_SUPP_DISP ), ///< see ::NTP_PEER_STATE_SUPP_DISP + NTP_PEER_STATE_SUPP_JITTER_MSK = ( 1UL << NTP_PEER_STATE_SUPP_JITTER ), ///< see ::NTP_PEER_STATE_SUPP_JITTER + NTP_PEER_STATE_SUPP_XLEAVE_MSK = ( 1UL << NTP_PEER_STATE_SUPP_XLEAVE ), ///< see ::NTP_PEER_STATE_SUPP_XLEAVE +}; + + + +/** + * @brief Structure that represents the status of an NTP peer + * + * This structure should be requested via ::NTP_PEER_STATE_IDX + * + * @see ::NTP_PEER_STATE_IDX + */ +typedef struct +{ + uint32_t supp_flags; ///< Supported NTP peer state values, see ::NTP_PEER_STATE_SUPP_FLAG_MASKS + + uint16_t ass_id; ///< Association ID of the peer + uint16_t peer_status_flags; ///< Peer status flags, see ::NTP_PEER_STATUS_FLAG_MASKS + + uint8_t leap_ind; ///< Leap indicator, see ::NTP_LI_BITS + uint8_t peer_sel_stat; ///< Current selection status of the peer, see ::NTP_PEER_SEL_STATUS_BITS + uint8_t peer_evt_cnt; ///< Number of events, since the last time the event code changed + uint8_t peer_rec_evt; ///< Most recent event message, see ::NTP_PEER_EVT_BITS + + uint8_t peer_reach_stat; ///< Current reach status of the peer, see ::NTP_REACH_STAT_BITS + uint8_t reserved_1; ///< Reserved, currently always 0 + uint16_t reserved_2; ///< Reserved, currently always 0 + + MBG_IP_ADDR_PORT src_addr; ///< Source address of the NTP peer, see ::MBG_IP_ADDR_PORT + MBG_IP_ADDR_PORT dst_addr; ///< Destination address of the NTP peer, see ::MBG_IP_ADDR_PORT + + uint8_t stratum; ///< Current stratum level of the NTP peer + int8_t precision; ///< Precision of the peer clock (2^precision) + uint16_t reserved_3; ///< Reserved, currently always 0 + + int32_t root_delay; ///< [us] Total roundtrip delay to the system peer of the NTP peer + int32_t root_disp; ///< [us] Total dispersion to the system peer of the NTP peer + + MBG_IP_ADDR ref_id; ///< Reference ID of the NTP peer, see ::MBG_IP_ADDR + + NTP_TSTAMP ref_time; ///< Last time the NTP peers time has been adjusted, see ::NTP_TSTAMP + NTP_TSTAMP rec_time; ///< Current system time of the NTP peer, see ::NTP_TSTAMP + + uint8_t reach; ///< Shift register for the last 8 polling intervals + uint8_t reserved_4; ///< Reserved, currently always 0 + uint16_t unreach; ///< Counter for the number of unsuccessful polling intervals + + uint8_t host_mode; ///< NTP mode of the requesting host, see ::NTP_MODE_BITS + uint8_t peer_mode; ///< NTP mode of the peer, see ::NTP_MODE_BITS + uint8_t host_poll; ///< Host NTP polling interval + uint8_t peer_poll; ///< Peer NTP polling interval + + uint8_t headway; ///< Indicator for the KoD packet, TODO: further investigation + uint8_t reserved_5; ///< Reserved, currently always 0 + uint16_t flash_stat_flags; ///< Flash status flags, see ::NTP_FLASH_STAT_FLAG_MASKS + + uint16_t key_id; ///< ID of symmetric authentication key + uint16_t reserved_6; ///< Reserved, currently always 0 + + int64_t offset; ///< [ns] filter offset to this NTP peer + int64_t delay; ///< [ns] filter delay to this NTP peer + + int32_t disp; ///< [us] filter dispersion of the NTP peer + int32_t jitter; ///< [us] filter jitter of the NTP peer + + uint32_t xleave; ///< [ns] interleave delay of the NTP peer + + uint8_t n_filter_values; ///< Number of filter values available, currently always 0 + uint8_t reserved_7; ///< Reserved, currently always 0 + uint16_t reserved_8; ///< Reserved, currently always 0 + + uint32_t reserved_9; ///< Reserved, currently always 0 + +} NTP_PEER_STATE, NTP_REFCLK_STATE; + + + +#define _mbg_swab_ntp_peer_state( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->supp_flags ); \ + \ + _mbg_swab16( &(_p)->ass_id ); \ + _mbg_swab16( &(_p)->peer_status_flags ); \ + \ + _mbg_swab8( &(_p)->leap_ind ); \ + _mbg_swab8( &(_p)->peer_sel_stat ); \ + _mbg_swab8( &(_p)->peer_evt_cnt ); \ + _mbg_swab8( &(_p)->peer_rec_evt ); \ + \ + _mbg_swab8( &(_p)->peer_reach_stat ); \ + _mbg_swab8( &(_p)->reserved_1 ); \ + _mbg_swab16( &(_p)->reserved_2 ); \ + \ + _mbg_swab_ip_addr_port( &(_p)->src_addr ); \ + _mbg_swab_ip_addr_port( &(_p)->dst_addr ); \ + \ + _mbg_swab8( &(_p)->stratum ); \ + _mbg_swab8( &(_p)->precision ); \ + _mbg_swab16( &(_p)->reserved_3 ); \ + \ + _mbg_swab32( &(_p)->root_delay ); \ + _mbg_swab32( &(_p)->root_disp ); \ + \ + _mbg_swab_ip_addr( &(_p)->ref_id ); \ + \ + _mbg_swab_ntp_tstamp( &(_p)->ref_time ); \ + _mbg_swab_ntp_tstamp( &(_p)->rec_time ); \ + \ + _mbg_swab8( &(_p)->reach ); \ + _mbg_swab8( &(_p)->reserved_4 ); \ + _mbg_swab16( &(_p)->unreach ); \ + \ + _mbg_swab8( &(_p)->host_mode ); \ + _mbg_swab8( &(_p)->peer_mode ); \ + _mbg_swab8( &(_p)->host_poll ); \ + _mbg_swab8( &(_p)->peer_poll ); \ + \ + _mbg_swab8( &(_p)->headway ); \ + _mbg_swab8( &(_p)->reserved_5 ); \ + _mbg_swab16( &(_p)->flash_stat_flags ); \ + \ + _mbg_swab16( &(_p)->key_id ); \ + _mbg_swab16( &(_p)->reserved_6 ); \ + \ + _mbg_swab64( &(_p)->offset ); \ + _mbg_swab64( &(_p)->delay ); \ + \ + _mbg_swab32( &(_p)->disp ); \ + _mbg_swab32( &(_p)->jitter ); \ + \ + _mbg_swab32( &(_p)->xleave ); \ + \ + _mbg_swab8( &(_p)->n_filter_values ); \ + _mbg_swab8( &(_p)->reserved_7 ); \ + _mbg_swab16( &(_p)->reserved_8 ); \ + \ + _mbg_swab32( &(_p)->reserved_9 ); \ + \ +} while ( 0 ) + +#define _mbg_swab_ntp_refclk_state ( _p ) _mbg_swab_ntp_peer_state( _p ) + + +/** + * @brief Structure that contains an index value and the NTP peer state + * + * This structure can be requested by a monitoring program to observe the status of configured NTP peers + * + * @see ::NTP_PEER_STATE + */ +typedef struct +{ + uint32_t idx; ///< The index of the observed NTP peer + NTP_PEER_STATE peer_state; ///< Peer state, see ::NTP_PEER_STATE + +} NTP_PEER_STATE_IDX, NTP_REFCLK_STATE_IDX; + + +#define _mbg_swab_ntp_peer_state_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_ntp_peer_state( &(_p)->peer_state ); \ +} while ( 0 ) + + +#define _mbg_swab_ntp_refclk_state_idx( _p ) _mbg_swab_ntp_peer_state_idx( _p ) + + +/** @} defgroup group_ntp */ + + + +/** + * @defgroup group_lno Definitions used with LNO devices + * + * @{ */ + +#define MAX_LNO_OUTPUT 4 + +/** + * @brief LNO state + */ +typedef struct +{ + uint16_t sine_lvl[MAX_LNO_OUTPUT]; ///< signal levels at the outputs + + uint16_t max_sine_lvl; ///< max level of an output, e.g. 1024 + uint8_t n_outputs; ///< actual number of outputs [0..::MAX_LNO_OUTPUT-1] + uint8_t out_enb_state; ///< e.g. bit 0 is set if corresponding output 0 is enabled, etc. + + uint16_t reserved_0; ///< reserved, currently always 0 + uint16_t flags; ///< status flags, see ::LNO_STATE_FLAG_BITS + +} LNO_STATE; + +#define _mbg_swab_lno_state( _p ) \ +do \ +{ \ + int i; \ + \ + for ( i = 0; i < MAX_LNO_OUTPUT; i++ ) \ + _mbg_swab16( &(_p)->sine_lvl[i] ); \ + \ + _mbg_swab_16( &(_p)->max_sine_lvl ); \ + _mbg_swab_16( &(_p)->reserved_0 ); \ + _mbg_swab_16( &(_p)->flags ); \ +} while ( 0 ) + + +/** + * @brief Flags used with ::LNO_STATE::flags + */ +enum LNO_STATE_FLAG_BITS +{ + LNO_FLAG_BIT_PLL_LOCKED, ///< PLL is locked + N_LNO_FLAG_BIT ///< number of known bits +}; + +#define LNO_FLAG_PLL_LOCKED ( 1UL << LNO_FLAG_BIT_PLL_LOCKED ) + +/** @} defgroup group_lno */ + + + +/** + * @defgroup group_vst Definitions used with Versatile Storage + * + * Versatile storage is used to store binary data on a device where the storage + * device must not necessarily know about the data structure. It just stores + * a piece of data, and retrieves it on demand. + * + * The structures and associated API calls are only supported if the + * ::GPS_HAS_VST bit is set in ::RECEIVER_INFO::features. + * + * @{ */ + +/** + * @brief Known common VST data types + */ +enum VST_DATA_TYPES +{ + VST_DATA_TYPE_MAC_ADDR, //##++++++++++++ This is just an example. More to be added. + N_VST_DATA_TYPES +}; + + +/** + * @brief + */ +typedef struct +{ + uint16_t data_type; ///< data type identifier, see ::VST_DATA_TYPES for common types + uint16_t idx; ///< Index for several sets of the same type + uint16_t data_len; ///< length of the data set appended to the header + uint16_t reserved; ///< reserved, currently always 0 + +} VST_HEADER; + +#define _mbg_swab_vst_header( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->data_type ); \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab16( &(_p)->data_len ); \ + _mbg_swab16( &(_p)->reserved ); \ +} while ( 0 ) + +/** @} defgroup group_vst */ + + + +/** + * @defgroup group_shs Definitions used with SHS devices + * + * An SHS (Secure Hybrid System) device compares the times from 2 sources + * and eventually sets an alarm (warning and/or error) flag if the difference + * between the 2 time sources exceeds a configurable limit. + * + * These structures and associated definitions are used to query the SHS + * capabilities, configure the SHS device according to its capabilities, + * and query the SHS status. + * + * The structures and associated API calls are only supported if the + * ::GPS_HAS_SHS bit is set in ::RECEIVER_INFO::features. + * + * The ::SHS_INFO structure can be read to retrieve the capabilities and + * current settings of the device. The ::SHS_SETTINGS structure can then + * be set up according to the capabilities, and be written back to configure + * the device. + * + * If ::SHS_SETTINGS::err_limit and/or ::SHS_SETTINGS::warn_limit are + * not 0 then the SHS device checks if the time difference between the + * 2 clocks exceeds these limits and sets ::SHS_STATUS::shs_state + * as appropriate. + * + * If indicated by ::SHS_INFO::supp_flags the SHS device can also take + * certain actions if the time difference exceeds the error limit. + * If this happens then the same flags are set in ::SHS_STATUS::flags + * to indicate the action has been taken. + * + * @{ */ + +/** + * @brief Current configuration of an SHS controller + * + * @see ::SHS_INFO + * @see ::SHS_STATUS + */ +typedef struct +{ + NANO_TIME err_limit; ///< time difference limit above which an error is indicated + NANO_TIME warn_limit; ///< time difference limit above which a warning is indicated + uint32_t reserved; ///< reserved, currently always 0 + uint32_t flags; ///< see ::SHS_FLAG_MASKS + +} SHS_SETTINGS; + +#define _mbg_swab_shs_settings( _p ) \ +do \ +{ \ + _mbg_swab_nano_time( &(_p)->err_limit ); \ + _mbg_swab_nano_time( &(_p)->warn_limit ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Current SHS settings and general SHS capabilities + * + * @see ::SHS_SETTINGS + * @see ::SHS_STATUS + */ +typedef struct +{ + SHS_SETTINGS settings; ///< current configuration settings + NANO_TIME max_limit; ///< if not 0, the max. allowed value for ::SHS_SETTINGS::err_limit and ::SHS_SETTINGS::warn_limit + uint32_t reserved; ///< reserved, currently always 0 + uint32_t supp_flags; ///< indicates which flags are supported for ::SHS_SETTINGS::flags, see ::SHS_FLAG_MASKS + +} SHS_INFO; + +#define _mbg_swab_shs_info( _p ) \ +do \ +{ \ + _mbg_swab_shs_settings( &(_p)->settings ); \ + _mbg_swab_nano_time( &(_p)->max_limit ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Current SHS status + */ +typedef struct +{ + NANO_TIME time_diff; ///< current time difference between the 2 clocks + TM_STATUS_EXT clk_status_1; ///< status of first clock + TM_STATUS_EXT clk_status_2; ///< status of second clock + uint8_t shs_state; ///< see ::SHS_STATES + uint8_t reserved_1; ///< reserved, currently always 0 + uint16_t reserved_2; ///< reserved, currently always 0 + uint32_t flags; ///< see ::SHS_FLAG_MASKS + +} SHS_STATUS; + +#define _mbg_swab_shs_status( _p ) \ +do \ +{ \ + _mbg_swab_nano_time( &(_p)->time_diff ); \ + _mbg_swab32( &(_p)->clk_status_1 ); \ + _mbg_swab32( &(_p)->clk_status_2 ); \ + _mbg_swab16( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief SHS configuration flag bits + * + * Codes used with ::SHS_STATUS::shs_state + */ +enum SHS_STATES +{ + SHS_STATE_DISABLED, ///< time difference not checked, eventually no limits configured + SHS_STATE_OK, ///< time difference OK, below warning limit + SHS_STATE_WARNING, ///< time difference exceeds warning limit + SHS_STATE_ERROR, ///< time difference exceeds error limit + SHS_STATE_FATAL, ///< one or both time sources disconnected + N_SHS_STATES +}; + + + +/** + * @brief SHS flag bits + * + * @see ::SHS_FLAG_MASKS + */ +enum SHS_FLAG_BITS +{ + SHS_FLAG_BIT_DISB_SERIAL, ///< disable serial output in state ::SHS_STATE_ERROR + SHS_FLAG_BIT_DISB_PPS, ///< disable PPS output in state ::SHS_STATE_ERROR + SHS_FLAG_BIT_DISB_10MHZ, ///< disable 10 MHz output in state ::SHS_STATE_ERROR + N_SHS_FLAG_BITS +}; + + +/** + * @brief SHS flag masks + * + * With ::SHS_INFO::supp_flags these flags indicate what is supported + * by the SHS controller, e.g. what action can be taken automatically. + * Each bit set in ::SHS_INFO::supp_flags can be set by a configuration + * tool in ::SHS_SETTINGS::flags to enable the associated feature. + * If a corresponding bit is set in ::SHS_STATUS::flags this means the + * associated feature has been enabled, e.g. an action has been taken. + * + * @see ::SHS_FLAG_BITS + */ +enum SHS_FLAG_MASKS +{ + SHS_FLAG_DISB_SERIAL = ( 1UL << SHS_FLAG_BIT_DISB_SERIAL ), ///< see ::SHS_FLAG_BIT_DISB_SERIAL + SHS_FLAG_DISB_PPS = ( 1UL << SHS_FLAG_BIT_DISB_PPS ), ///< see ::SHS_FLAG_BIT_DISB_PPS + SHS_FLAG_DISB_10MHZ = ( 1UL << SHS_FLAG_BIT_DISB_10MHZ ) ///< see ::SHS_FLAG_BIT_DISB_10MHZ +}; + +/** @} defgroup group_shs */ + + + +/** + * @defgroup group_xbp eXtended Binary Protocol definitions + * + * @note These structures are only supported if ::GPS_HAS_XBP is set + * in ::RECEIVER_INFO::features. + * + * @{ */ + +/** + * @brief An XBP port specifier + * + * Each controller can provide up to 255 ports with numbers 0..254. + * XBP port number ::XBP_PORT_RESERVED is reserved to mark unused ports. + */ +typedef uint8_t XBP_PORT; + + +/** + * @brief An identifier used to mark an XBP port unused + */ +#define XBP_PORT_RESERVED ( (XBP_PORT) -1 ) + + +/** + * @brief Maximum XBP bus/controller cascading level + * + * Should be 7 so the total size of ::XBP_ADDR is 8 bytes. + */ +#define MAX_XBP_CASC_LVL 7 + + +/** + * @brief An XBP address specifier + * + * A generic scheme to address devices connected to cascaded controllers. + */ +typedef struct +{ + uint8_t hop_count; ///< Used as index to the addr array + XBP_PORT addr[MAX_XBP_CASC_LVL]; ///< An array of port numbers on cascaded controllers + +} XBP_ADDR; + +#define _mbg_swab_xbp_addr( _p ) _nop_macro_fnc() // only single bytes + + + +/** + * @brief A structure used to report XBP features and limits + */ +typedef struct +{ + uint32_t features; ///< Mask of XBP features, see ::XBP_FEAT_MASKS + uint32_t flags; ///< XBP flags, currently not used + uint32_t reserved_0; ///< reserved, currently not used + uint32_t reserved_1; ///< reserved, currently not used + uint32_t reserved_2; ///< reserved, currently not used + uint32_t reserved_3; ///< reserved, currently not used + +} XBP_LIMITS; + +#define _mbg_swab_xbp_limits( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->features ); \ + _mbg_swab32( &(_p)->flags ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of bits used to define ::XBP_FEAT_MASKS + */ +enum XBP_FEAT_BITS +{ + XBP_FEAT_BIT_NODES, ///< Supports ::XBP_NODE_LIMITS and associated structures + N_XBP_FEAT_BITS +}; + + +/** + * @brief XBP feature masks used with ::XBP_LIMITS::features + * + * @see ::XBP_FEAT_BITS + */ +enum XBP_FEAT_MASKS +{ + XBP_FEAT_MASK_NODES = ( 1UL << XBP_FEAT_BIT_NODES ) ///< See ::XBP_FEAT_BIT_NODES +}; + + + +/** + * @brief Information on available XBP nodes + * + * Only supported if ::XBP_FEAT_MASK_NODES is set in ::XBP_LIMITS::features. + */ +typedef struct +{ + uint32_t node_count; ///< Number of XBP nodes available in the system + uint32_t reserved_0; ///< Currently reserved, always 0 + uint32_t reserved_1; ///< Currently reserved, always 0 + // TODO: do we need additional fields here? + +} XBP_NODE_LIMITS; + +#define _mbg_swab_xbp_node_limits( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->node_count ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ +} while ( 0 ) + + + +/** + * @brief Possible states of an XBP device + * + * Used with ::XBP_NODE_INFO::state. + */ +enum XBP_DEVICE_STATES +{ + XBP_DEVICE_STATE_UNKNOWN, + XBP_DEVICE_STATE_NOT_AVAILABLE, + XBP_DEVICE_STATE_INITIALIZING, + XBP_DEVICE_STATE_AVAILABLE, + XBP_DEVICE_STATE_DISCONNECTED, + N_XBP_DEVICE_STATES +}; + + + +/** + * @brief Information on a specific XBP node + * + * Only supported if ::XBP_FEAT_MASK_NODES is set in ::XBP_LIMITS::features. + * The number of instances supported by a device is specified + * in ::XBP_NODE_LIMITS::node_count. + */ +typedef struct +{ + XBP_ADDR addr; ///< The address of the specific node + + /// ::RECEIVER_INFO of the device connected to this node. + /// If no device is available then ::RECEIVER_INFO::model_code + /// is set to ::GPS_MODEL_UNKNOWN (== 0). + RECEIVER_INFO ri; + + uint8_t state; ///< The device state, see ::XBP_DEVICE_STATES + uint8_t reserved; ///< Currently reserved, always 0 + uint32_t flags; ///< Currently reserved, always 0 + +} XBP_NODE_INFO; + +#define _mbg_swab_xbp_node_info( _p ) \ +do \ +{ \ + _mbg_swab_xbp_addr( &(_p)->addr ); \ + _mbg_swab_receiver_info( &(_p)->ri ); \ + _mbg_swab8( &(_p)->state ); \ + _mbg_swab8( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Information on an XBP node with specific index + * + * Only supported if ::XBP_FEAT_MASK_NODES is set in ::XBP_LIMITS::features. + */ +typedef struct +{ + uint32_t idx; ///< node index, 0..::XBP_NODE_LIMITS::node_count-1 + XBP_NODE_INFO node_info; ///< ::RECEIVER_INFO of the device behind this node + +} XBP_NODE_INFO_IDX; + +#define _mbg_swab_xbp_node_info_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_xbp_node_info( &(_p)->node_info ); \ +} while ( 0 ) + + +/** @} defgroup group_xbp */ + + + +/** + * @defgroup group_tlv_api Meinberg TLV API definitions + * + * @note These structures and definitions are only supported by a device + * if ::MBG_XFEATURE_TLV_API is set in the extended device features. + * + * @{ */ + + +/** + * @brief A data type used to hold a unique ID (UID) for a TLV transaction + */ +typedef uint32_t MBG_TLV_UID; + +#define _mbg_swab_tlv_uid( _p ) \ + _mbg_swab32( _p ) + + + +/** + * @brief A data type to hold one of the ::MBG_TLV_TYPES or ::MBG_TLV_FEAT_TYPES + * + * @see ::MBG_TLV_TYPES + * @see ::MBG_TLV_FEAT_TYPES + */ +typedef uint32_t MBG_TLV_TYPE; + +#define _mbg_swab_tlv_type( _p ) \ + _mbg_swab32( _p ) + + + +/** + * @defgroup group_tlv_feat Meinberg TLV feature definitions + * + * @{ */ + + +/** + * @brief The maximum number of TLV feature types. + * + * Warning: Changing this number breaks API compatibility! + * + * @see ::MBG_TLV_FEAT_TYPES + */ +#define MAX_MBG_TLV_FEAT_TYPES 128 //### TODO Is this sufficient? + + +/** + * @brief Enumeration of known TLV feature types. + * + * TLV feature types are used to specify the content of a binary TLV message + * so that the receiver knows how to interpret the content. + * + * Used with ::MBG_TLV_INFO::supp_tlv_feat and ::MBG_TLV_DATA::type. ### TODO + * + * @see ::MBG_TLV_FEAT_BUFFER + * @see ::MBG_TLV_FEAT_TYPE_NAMES + * @see ::MBG_TLV_TYPES + * @see ::MBG_TLV_TYPE + */ +enum MBG_TLV_FEAT_TYPES +{ + /// Expects two TLV types in order: + /// 1) ::MBG_TLV_TYPE_STR => Firmware version as string + /// 2) ::MBG_TLV_TYPE_FILE => Firmware file as data blob + MBG_TLV_FEAT_TYPE_FW_UPDATE, + + /// If announce message's total bytes are 0, it is a diagnostics file + /// request. If its total bytes are not 0, TLV type ::MBG_TLV_TYPE_FILE + /// is expected and it should contain a file as data blob. + MBG_TLV_FEAT_TYPE_DIAG_FILE, + + /// Only used as action trigger on a remote site, expects no data. + MBG_TLV_FEAT_TYPE_FW_ROLLBACK, + + /// Expects two TLV types in order: + /// 1) ::MBG_TLV_TYPE_STR => Full qualified path including filename on target system + /// 2) ::MBG_TLV_TYPE_FILE => File as data blob + MBG_TLV_FEAT_TYPE_FILE_TRANSFER, + + /// 1) ::MBG_TLV_TYPE_STR => Command line call as string + MBG_TLV_FEAT_TYPE_EXEC_CMD, + + /// 1) ::MBG_TLV_TYPE_FILE => Encrypted license file as data blob + MBG_TLV_FEAT_TYPE_LICENSE_UPGRADE, + + /// 1) ::MBG_TLV_TYPE_BLOB => ::MBG_LICENSE_LIMITS, see @ref group_license_limits + MBG_TLV_FEAT_TYPE_LICENSE_LIMITS, + + /// 1) ::MBG_TLV_TYPE_BLOB => ::MBG_LICENSE_PTPV2_IDX, see @ref group_license_limits + MBG_TLV_FEAT_TYPE_LICENSE_PTPV2_IDX, + + /// 1) ::MBG_TLV_TYPE_BLOB => ::MBG_LICENSE_NTP_IDX, see @ref group_license_limits + MBG_TLV_FEAT_TYPE_LICENSE_NTP_IDX, + + /// Expects two TLV types in order: + /// 1) ::MBG_TLV_TYPE_STR => Full qualified path including filename on target system + MBG_TLV_FEAT_TYPE_FILE_REQUEST, + + /// 1) ::MBG_TLV_TYPE_BLOB => ::MBG_LICENSE_PTPV1_IDX, see @ref group_license_limits + MBG_TLV_FEAT_TYPE_LICENSE_PTPV1_IDX, + + /// 1) ::MBG_TLV_TYPE_BLOB => ::MBG_LICENSE_TIME_MONITOR_IDX, see @ref group_license_limits + MBG_TLV_FEAT_TYPE_LICENSE_TIME_MONITOR_IDX, + + /// 1) ::MBG_TLV_TYPE_BLOB => Unified Firmware Update (UFU) file, see mbg_ufu.h + MBG_TLV_FEAT_TYPE_UFU, + + N_MBG_TLV_FEAT_TYPES + // NOTE If new TLV feature types are appended here then an appropriate + // name string has to be appended to ::MBG_TLV_FEAT_TYPE_NAMES, and care must + // be taken that ::N_MBG_TLV_FEAT_TYPES doesn't exceed ::MAX_MBG_TLV_FEAT_TYPES. +}; + + +/** + * @brief Names of TLV API features + * + * Can be used to initialize a string array of ::N_MBG_TLV_FEAT_TYPES entries, + * so the number of strings must correspond to ::N_MBG_TLV_FEAT_TYPES. + * + * @see ::MBG_TLV_FEAT_TYPES + */ +#define MBG_TLV_FEAT_TYPE_NAMES \ +{ \ + "TLV Firmware Update", \ + "TLV Diagnostics File", \ + "TLV Firmware Rollback", \ + "TLV File Transfer", \ + "TLV Execute Command", \ + "TLV License Upgrade", \ + "TLV License Limits", \ + "TLV License PTPV2", \ + "TLV License NTP", \ + "TLV File Request", \ + "TLV License PTPV1 IDX", \ + "TLV License Time Monitor", \ + "TLV Unified Firmware Update" \ +} + + + +/** + * @brief Array size required to store up to ::MAX_MBG_TLV_FEAT_TYPES bits + * + * The number of bytes required to store up to ::MAX_MBG_TLV_FEAT_TYPES + * feature bits in a byte array. + */ +#define MAX_MBG_TLV_FEAT_BYTES ( MAX_MBG_TLV_FEAT_TYPES / 8 ) + + +/** + * @brief A structure used to store a bit mask of supported TLV context types. + * + * Bit masks for up to ::MAX_MBG_TLV_FEAT_TYPES totally can be stored, + * but only ::N_MBG_TLV_FEAT_TYPES types are currently defined. + * The ::_set_tlv_feat_bit macro should be used by the firmware + * to set a bit mask in the buffer, and the ::check_tlv_feat_supp + * function should be used to implement API calls which test if an + * extended TLV context type is supported. + * + * @see ::_set_tlv_feat_bit + * @see ::check_tlv_feat_supp + */ +typedef struct +{ + uint8_t b[MAX_MBG_TLV_FEAT_BYTES]; + +} MBG_TLV_FEAT_BUFFER; + + + +/** + * @brief Set a TLV context type bit in a ::MBG_TLV_FEAT_BUFFER + * + * Should be used by the firmware only to set one of the ::MBG_TLV_FEAT_TYPES + * bits in an ::MBG_TLV_FEAT_BUFFER after power-up. + * + * @param[in] _tlv_feat_type One of the ::MBG_TLV_FEAT_TYPES + * @param[in] _tlv_feat_buffp Pointer to a ::MBG_TLV_FEAT_BUFFER + */ +#define _set_tlv_feat_bit( _tlv_feat_type, _tlv_feat_buffp ) \ + _set_array_bit( _tlv_feat_type, (_tlv_feat_buffp)->b, MAX_MBG_TLV_FEAT_BYTES ) + + +/** @} defgroup group_tlv_feat */ + + + +/** + * @brief A structure used to query current TLV capabilities + * + * This is only supported by a device if the ::MBG_XFEATURE_TLV_API bit + * is set in the extended device features. + */ +typedef struct +{ + uint32_t reserved; ///< Future use + uint32_t flags; ///< Future use + MBG_TLV_FEAT_BUFFER supp_tlv_feat; ///< A byte array of supported TLV feature bits, see ::MBG_TLV_FEAT_TYPES + +} MBG_TLV_INFO; + +#define _mbg_swab_tlv_info( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Enumeration of known TLV types + * + * Used with ::MBG_TLV_TYPE types, e.g. in ::MBG_TLV_HDR::tlv_type + * or ::MBG_TLV_DATA::type. + * + * @see ::MBG_TLV_FEAT_TYPES + * @see ::MBG_TLV_TYPE + */ +enum MBG_TLV_TYPES +{ + MBG_TLV_TYPE_STR, + MBG_TLV_TYPE_FILE, + MBG_TLV_TYPE_BLOB, ///< In fact, a file is also a blob but + ///< give the child a different name to avoid confusion. + ///< Use this for getting/setting fixed structures! + N_MBG_TLV_TYPES +}; + + + +/** + * @brief General TLV data structure + * + * Structure containing common, additional data required to send + * an announce message for following TLVs. + */ +typedef struct +{ + MBG_TLV_UID uid; ///< Unique ID identifying following TLVs, 0 if empty/not set. + MBG_TLV_TYPE type; ///< One of the ::MBG_TLV_TYPES or ::MBG_TLV_FEAT_TYPES depending on the type of message. + uint32_t total_bytes; ///< Number of all bytes including header(s) that are related to a TLV block transaction. + uint32_t reserved_1; ///< Reserved for future use + +} MBG_TLV_DATA; + +#define _mbg_swab_tlv_data( _p ) \ +do \ +{ \ + _mbg_swab_tlv_uid( &(_p)->uid ); \ + _mbg_swab_tlv_type( &(_p)->type ); \ + _mbg_swab32( &(_p)->total_bytes ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ +} while ( 0 ) + + + +/** + * @brief Structure containing state information while reading TLV data. + */ +typedef struct +{ + MBG_TLV_DATA data; ///< See ::MBG_TLV_DATA + uint32_t read_bytes; ///< Number of bytes read + uint32_t reserved_1; ///< Future use + +} MBG_TLV_RCV_STATE; + + + +/** + * @brief A structure initiating a TLV transfer + * + * ::MBG_TLV_ANNOUNCE should be sent first, before starting a + * TLV transfer, to inform the remote site about following TLVs. + * Following sequence of TLVs is not fixed and implementation + * dependent. + */ +typedef struct +{ + MBG_TLV_DATA data; ///< See ::MBG_TLV_DATA + uint32_t reserved_1; ///< Future use + uint32_t reserved_2; ///< Future use + +} MBG_TLV_ANNOUNCE; + +#define _mbg_swab_tlv_announce( _p ) \ +do \ +{ \ + _mbg_swab_tlv_data( &(_p)->data ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ +} while ( 0 ) + + + +#define MSG_TLV_MAX_VALUE_SIZE 480 + +/** + * @brief TLV header structure containing information on current TLV transaction + */ +typedef struct +{ + MBG_TLV_UID uid; ///< Unique source ID. See ::MBG_TLV_DATA::uid + MBG_TLV_UID tlv_type; ///< "Subtype" identifying current TLV, see ::MBG_TLV_TYPES + uint32_t cur_bytes; ///< Number of bytes in ::MBG_TLV::value + uint32_t trans_bytes; ///< Number of bytes transferred so far related to this TLV type. + uint32_t total_bytes; ///< Number of total bytes (size) of this TLV type without header. + ///< It is fixed and must not be changed during a TLV transaction. + uint32_t reserved_1; ///< Future use + uint32_t reserved_2; ///< Future use + uint32_t reserved_3; ///< Future use + +} MBG_TLV_HDR; + +#define _mbg_swab_tlv_header( _p ) \ +do \ +{ \ + _mbg_swab_tlv_uid( &(_p)->uid ); \ + _mbg_swab_tlv_type( &(_p)->tlv_type ); \ + _mbg_swab32( &(_p)->cur_bytes ); \ + _mbg_swab32( &(_p)->trans_bytes ); \ + _mbg_swab32( &(_p)->total_bytes ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ +} while ( 0 ) + + + +/** + * @brief TLV structure containing information on current TLV transaction and its current data. + */ +typedef struct +{ + MBG_TLV_HDR hdr; ///< See ::MBG_TLV_HDR + uint8_t value[MSG_TLV_MAX_VALUE_SIZE]; ///< See ::MSG_TLV_MAX_VALUE_SIZE + +} MBG_TLV; + +#define _mbg_swab_tlv( _p ) \ +do \ +{ \ + _mbg_swab_tlv_header( &(_p)->hdr ); \ +} while ( 0 ) + +/** @} defgroup group_tlv_api */ + + + +/** + * @defgroup group_gps_nav_data Definitions used with navigational data received from GPS satellites + * + * @note These structures and definitions are only supported by a device + * if ::GPS_MODEL_IS_GPS is set in the @ref GPS_BUILTIN_FEATURE_MASKS + * + * @{ */ + + +/** + * @brief Ephemeris parameters of one specific satellite + * + * Needed to compute the position of a satellite at a given time with + * high precision. Valid for an interval of 4 to 6 hours from start + * of transmission. + */ +typedef struct +{ + CSUM csum; ///< checksum of the remaining bytes + int16_t valid; ///< flag data are valid + + HEALTH health; ///< health indication of transmitting SV [---] + IOD IODC; ///< Issue Of Data, Clock + IOD IODE2; ///< Issue of Data, Ephemeris (Subframe 2) + IOD IODE3; ///< Issue of Data, Ephemeris (Subframe 3) + T_GPS tt; ///< time of transmission + T_GPS t0c; ///< Reference Time Clock [---] + T_GPS t0e; ///< Reference Time Ephemeris [---] + + double sqrt_A; ///< Square Root of semi-major Axis [sqrt(m)] + double e; ///< Eccentricity [---] + double M0; ///< +- Mean Anomaly at Ref. Time [rad] + double omega; ///< +- Argument of Perigee [rad] + double OMEGA0; ///< +- Longit. of Asc. Node of orbit plane [rad] + double OMEGADOT; ///< +- Rate of Right Ascension [rad/sec] + double deltan; ///< +- Mean Motion Diff. from computed value [rad/sec] + double i0; ///< +- Inclination Angle [rad] + double idot; ///< +- Rate of Inclination Angle [rad/sec] + double crc; ///< +- Cosine Corr. Term to Orbit Radius [m] + double crs; ///< +- Sine Corr. Term to Orbit Radius [m] + double cuc; ///< +- Cosine Corr. Term to Arg. of Latitude [rad] + double cus; ///< +- Sine Corr. Term to Arg. of Latitude [rad] + double cic; ///< +- Cosine Corr. Term to Inclination Angle [rad] + double cis; ///< +- Sine Corr. Term to Inclination Angle [rad] + + double af0; ///< +- Clock Correction Coefficient 0 [sec] + double af1; ///< +- Clock Correction Coefficient 1 [sec/sec] + double af2; ///< +- Clock Correction Coefficient 2 [sec/sec^2] + double tgd; ///< +- estimated group delay differential [sec] + + uint16_t URA; ///< predicted User Range Accuracy + + uint8_t L2code; ///< code on L2 channel [---] + uint8_t L2flag; ///< L2 P data flag [---] + +} EPH; + +/** + * @brief Almanac parameters of one specific satellite + * + * A reduced precision set of parameters used to check if a satellite + * is in view at a given time. Valid for an interval of more than 7 days + * from start of transmission. + */ +typedef struct +{ + CSUM csum; ///< checksum of the remaining bytes + int16_t valid; ///< flag data are valid + + HEALTH health; ///< [---] + T_GPS t0a; ///< Reference Time Almanac [sec] + + double sqrt_A; ///< Square Root of semi-major Axis [sqrt(m)] + double e; ///< Eccentricity [---] -/* Summary of configuration and health data of all SVs. */ + double M0; ///< +- Mean Anomaly at Ref. Time [rad] + double omega; ///< +- Argument of Perigee [rad] + double OMEGA0; ///< +- Longit. of Asc. Node of orbit plane [rad] + double OMEGADOT; ///< +- Rate of Right Ascension [rad/sec] + double deltai; ///< +- [rad] + double af0; ///< +- Clock Correction Coefficient 0 [sec] + double af1; ///< +- Clock Correction Coefficient 1 [sec/sec] +} ALM; + + + +/** + * @brief Summary of configuration and health data of all satellites + */ typedef struct { - CSUM csum; /* checksum of the remaining bytes */ - int16_t valid; /* flag data are valid */ + CSUM csum; ///< checksum of the remaining bytes + int16_t valid; ///< flag data are valid - T_GPS tot_51; /* time of transmission, page 51 */ - T_GPS tot_63; /* time of transmission, page 63 */ - T_GPS t0a; /* complete reference time almanac */ + T_GPS tot_51; ///< time of transmission, page 51 + T_GPS tot_63; ///< time of transmission, page 63 + T_GPS t0a; ///< complete reference time almanac + + CFG cfg[N_SVNO_GPS]; ///< 4 bit SV configuration code from page 63 + HEALTH health[N_SVNO_GPS]; ///< 6 bit SV health codes from pages 51, 63 - CFG cfg[N_SVNO]; /* SV configuration from page 63 */ - HEALTH health[N_SVNO]; /* SV health from pages 51, 63 */ } CFGH; /** - * @brief GPS UTC correction parameters + * @brief GPS %UTC correction parameters + * + * %UTC correction parameters basically as sent by the GPS satellites. + * + * The csum field is only used by the card's firmware to check the + * consistency of the structure in non-volatile memory. + * + * The field labeled valid indicates if the parameter set is valid, i.e. + * if it contains data received from the satellites. + * + * t0t, A0 and A1 contain fractional correction parameters for the current + * GPS-%UTC time offset in addition to the whole seconds. This is evaluated + * by the receivers' firmware to convert GPS time to %UTC time. + * + * The delta_tls field contains the current full seconds offset between + * GPS time and %UTC, which corresponds to the number of leap seconds inserted + * into the %UTC time scale since GPS was put into operation in January 1980. + * + * delta_tlfs holds the number of "future" leap seconds, i.e. the %UTC offset + * after the next leap second event defined by WNlsf and DNt. + * + * The fields WNlsf and DNt specify the GPS week number and the day number + * in that week for the end of which a leap second has been scheduled. + * + * @note: The satellites transmit WNlsf only as a signed 8 bit value, so it + * can only define a point in time which is +/- 127 weeks off the current time. + * The firmware tries to expand this based on the current week number, but + * the result is ambiguous if the leap second occurs or occurred more + * than 127 weeks in the future or past. + * + * So the leap second date should <b>only</b> be evaluated and displayed + * in a user interface if the fields delta_tls and delta_tlsf have + * different values, in which case there is indeed a leap second announcement + * inside the +/- 127 week range. */ typedef struct { - CSUM csum; /**< Checksum of the remaining bytes */ - int16_t valid; /**< Flag indicating UTC parameters are valid */ + CSUM csum; ///< Checksum of the remaining bytes + int16_t valid; ///< Flag indicating %UTC parameters are valid - T_GPS t0t; /**< Reference Time UTC Parameters [wn|sec] */ - double A0; /**< +- Clock Correction Coefficient 0 [sec] */ - double A1; /**< +- Clock Correction Coefficient 1 [sec/sec] */ + T_GPS t0t; ///< Reference Time %UTC Parameters [wn|sec] + double A0; ///< +- Clock Correction Coefficient 0 [sec] + double A1; ///< +- Clock Correction Coefficient 1 [sec/sec] + + uint16_t WNlsf; ///< Week number of nearest leap second + int16_t DNt; ///< The day number at the end of which a leap second occurs + int8_t delta_tls; ///< Current %UTC offset to GPS system time [sec] + int8_t delta_tlsf; ///< Future %UTC offset to GPS system time after next leap second transition [sec] - uint16_t WNlsf; /**< Week number of nearest leap second */ - int16_t DNt; /**< The day number at the end of which a leap second occurs */ - int8_t delta_tls; /**< Current UTC offset to GPS system time [sec] */ - int8_t delta_tlsf; /**< Future UTC offset to GPS system time after next leap second transition [sec] */ } UTC; #define _mbg_swab_utc_parm( _p ) \ +do \ { \ _mbg_swab_csum( &(_p)->csum ); \ _mbg_swab16( &(_p)->valid ); \ @@ -5027,42 +18181,48 @@ typedef struct _mbg_swab_double( &(_p)->A1 ); \ _mbg_swab16( &(_p)->WNlsf ); \ _mbg_swab16( &(_p)->DNt ); \ -} - +} while ( 0 ) -/* Ionospheric correction parameters */ +/** + * @brief Ionospheric correction parameters + */ typedef struct { - CSUM csum; /* checksum of the remaining bytes */ - int16_t valid; /* flag data are valid */ + CSUM csum; ///< checksum of the remaining bytes + int16_t valid; ///< flag data are valid - double alpha_0; /* Ionosph. Corr. Coeff. Alpha 0 [sec] */ - double alpha_1; /* Ionosph. Corr. Coeff. Alpha 1 [sec/deg] */ - double alpha_2; /* Ionosph. Corr. Coeff. Alpha 2 [sec/deg^2] */ - double alpha_3; /* Ionosph. Corr. Coeff. Alpha 3 [sec/deg^3] */ + double alpha_0; ///< Ionosph. Corr. Coeff. Alpha 0 [sec] + double alpha_1; ///< Ionosph. Corr. Coeff. Alpha 1 [sec/deg] + double alpha_2; ///< Ionosph. Corr. Coeff. Alpha 2 [sec/deg^2] + double alpha_3; ///< Ionosph. Corr. Coeff. Alpha 3 [sec/deg^3] - double beta_0; /* Ionosph. Corr. Coeff. Beta 0 [sec] */ - double beta_1; /* Ionosph. Corr. Coeff. Beta 1 [sec/deg] */ - double beta_2; /* Ionosph. Corr. Coeff. Beta 2 [sec/deg^2] */ - double beta_3; /* Ionosph. Corr. Coeff. Beta 3 [sec/deg^3] */ -} IONO; + double beta_0; ///< Ionosph. Corr. Coeff. Beta 0 [sec] + double beta_1; ///< Ionosph. Corr. Coeff. Beta 1 [sec/deg] + double beta_2; ///< Ionosph. Corr. Coeff. Beta 2 [sec/deg^2] + double beta_3; ///< Ionosph. Corr. Coeff. Beta 3 [sec/deg^3] +} IONO; -/* GPS ASCII message */ +/** + * @brief GPS ASCII message + */ typedef struct { - CSUM csum; /* checksum of the remaining bytes */ - int16_t valid; /* flag data are valid */ - char s[23]; /* 22 chars GPS ASCII message plus trailing zero */ + CSUM csum; ///< checksum of the remaining bytes */ + int16_t valid; ///< flag data are valid + char s[23]; ///< 22 chars GPS ASCII message plus trailing zero + } ASCII_MSG; +/** @} defgroup group_gps_nav_data */ -enum + +enum GPS_PLATFORMS { GPS_PLATFORM_PORTABLE, GPS_PLATFORM_FIXED, @@ -5092,11 +18252,12 @@ enum -enum +enum TIME_MODES { TIME_MODE_DISABLED, TIME_MODE_SURVEY_IN, - TIME_MODE_FIXED + TIME_MODE_FIXED, + N_TIME_MODES }; @@ -5110,15 +18271,17 @@ typedef struct int32_t fixedPosY; // cm int32_t fixedPosZ; // cm uint32_t fixedPosVar; // cm - uint32_t flags; // currently 0 - uint32_t reserved; // currently 0 + uint32_t flags; // currently 0 + uint32_t reserved; // currently 0 + } NAV_TIME_MODE_SETTINGS; + /** - Navigation Engine settings to set configuration - parameters of a dynamic platform model. -*/ + * Navigation Engine settings to set configuration + * parameters of a dynamic platform model. + */ typedef struct { uint8_t dynamic_platform; @@ -5130,9 +18293,2900 @@ typedef struct uint32_t flags; // currently 0 uint32_t reserved; // currently 0 NAV_TIME_MODE_SETTINGS nav_time_mode_settings; + } NAV_ENGINE_SETTINGS; + +/** + * @defgroup group_led_api Meinberg LED API definitions + * + * @note These structures and definitions are only supported by a device + * if ::MBG_XFEATURE_LED_API is set in the extended device features. + * + * @{ */ + + +/** + * @brief General LED info to be read from a device + * + * Used to query from a device how many LEDs are supported + * by the device, then index 0..::MBG_LED_LIMITS::num_leds-1 + * ::MBG_LED_INFO_IDX or ::MBG_LED_SETTINGS_IDX structures + * can be read from or written to the device. + * + * @see ::MBG_LED_SETTINGS_IDX + * @see ::MBG_LED_INFO_IDX + */ +typedef struct +{ + uint8_t num_leds; ///< Number of supported LEDs, see ::MBG_LED_SETTINGS_IDX::idx and ::MBG_LED_INFO_IDX::idx + uint8_t reserved_0; ///< Currently reserved, unused, always 0 + uint16_t reserved_1; ///< Currently reserved, unused, always 0 + uint32_t reserved_2; ///< Currently reserved, unused, always 0 + +} MBG_LED_LIMITS; + +#define _mbg_swab_mbg_led_limits( _p ) \ +do \ +{ \ + _mbg_swab8( &(_p)->num_leds ); \ + _mbg_swab8( &(_p)->reserved_0 ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ +} while ( 0 ) + + + +/** + * @brief Possible modes of LEDs + * + * Used with ::MBG_LED_SETTINGS::mode + * + * @see ::MBG_LED_MODE_MASKS + */ +enum MBG_LED_MODES +{ + MBG_LED_MODE_OFF, + MBG_LED_MODE_ON, + MBG_LED_MODE_FLASH, + MBG_LED_MODE_FLASH_5S, + N_MBG_LED_MODES +}; + + + +/** + * @brief Bit masks associated with LED modes + * + * Used with ::MBG_LED_INFO::supp_modes + * + * @see ::MBG_LED_MODES + */ +enum MBG_LED_MODE_MASKS +{ + MBG_LED_MODE_MASK_OFF = ( 1UL << MBG_LED_MODE_OFF ), ///< see ::MBG_LED_MODE_OFF + MBG_LED_MODE_MASK_ON = ( 1UL << MBG_LED_MODE_ON ), ///< see ::MBG_LED_MODE_ON + MBG_LED_MODE_MASK_FLASH = ( 1UL << MBG_LED_MODE_FLASH ), ///< see ::MBG_LED_MODE_FLASH + MBG_LED_MODE_MASK_FLASH_5S = ( 1UL << MBG_LED_MODE_FLASH_5S ) ///< see ::MBG_LED_MODE_FLASH_5S +}; + + +/** + * @brief Names of LED modes + * + * Can be used to initialize a string array of ::N_MBG_LED_MODES entries, + * so the number of strings must correspond to ::N_MBG_LED_MODES. + * + * @see ::MBG_LED_MODES + * @see ::MBG_LED_MODE_MASKS + */ +#define MBG_LED_MODE_STRS \ +{ \ + "Off", \ + "On", \ + "Flash", \ + "Flash 5s" \ +} + + + +/** + * @brief Possible colors of LEDs + * + * Used with ::MBG_LED_SETTINGS::color + * + * @see ::MBG_LED_COLOR_MASKS + */ +enum MBG_LED_COLORS +{ + MBG_LED_COLOR_GREEN, + MBG_LED_COLOR_RED, + MBG_LED_COLOR_YELLOW, + MBG_LED_COLOR_BLUE, + N_MBG_LED_COLORS +}; + + + +/** + * @brief Bit masks of possible LED colors + * + * Used with ::MBG_LED_INFO::supp_colors + * + * @see ::MBG_LED_COLORS + */ +enum MBG_LED_COLOR_MASKS +{ + MBG_LED_COLOR_MASK_GREEN = ( 1UL << MBG_LED_COLOR_GREEN ), ///< see ::MBG_LED_COLOR_GREEN + MBG_LED_COLOR_MASK_RED = ( 1UL << MBG_LED_COLOR_RED ), ///< see ::MBG_LED_COLOR_RED + MBG_LED_COLOR_MASK_YELLOW = ( 1UL << MBG_LED_COLOR_YELLOW ), ///< see ::MBG_LED_COLOR_YELLOW + MBG_LED_COLOR_MASK_BLUE = ( 1UL << MBG_LED_COLOR_BLUE ) ///< see ::MBG_LED_COLOR_BLUE +}; + + + +/** + * @brief Names of LED colors + * + * Can be used to initialize a string array of ::N_MBG_LED_COLORS entries, + * so the number of strings must correspond to ::N_MBG_LED_COLORS. + * + * @see ::MBG_LED_COLORS + * @see ::MBG_LED_COLOR_MASKS + */ +#define MBG_LED_COLOR_STRS \ +{ \ + "Green", \ + "Red", \ + "Yellow", \ + "Blue" \ +} + + + +/** + * @brief Configuration settings for a single LED + * + * @see ::MBG_LED_SETTINGS_IDX + */ +typedef struct +{ + uint8_t mode; ///< LED mode, see ::MBG_LED_MODES + uint8_t color; ///< LED color, see ::MBG_LED_COLORS + uint16_t reserved; ///< Currently reserved, unused, always 0 + +} MBG_LED_SETTINGS; + +#define _mbg_swab_mbg_led_settings( _p ) \ +do \ +{ \ + _mbg_swab8( &(_p)->mode ); \ + _mbg_swab8( &(_p)->color ); \ + _mbg_swab16( &(_p)->reserved ); \ +} while ( 0 ) + + + +/** + * @brief Configuration settings for a single LED, plus index + * + * @see ::MBG_LED_SETTINGS + * @see ::MBG_LED_LIMITS + */ +typedef struct +{ + uint16_t idx; ///< 0..::MBG_LED_LIMITS::num_leds-1 + MBG_LED_SETTINGS settings; ///< LED settings + +} MBG_LED_SETTINGS_IDX; + +#define _mbg_swab_mbg_led_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_mbg_led_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +/** + * @brief Current settings and general capabilities of an LED + * + * This structure should be read from the device to retrieve the + * current settings of an LED plus its capabilities, e.g. the + * supported modes, colors, etc. + * + * @see ::MBG_LED_INFO_IDX + */ +typedef struct +{ + MBG_LED_SETTINGS settings; ///< Current LED settings + uint32_t supp_modes; ///< Supported modes, see ::MBG_LED_MODE_MASKS + uint32_t supp_colors; ///< Supported colors, see ::MBG_LED_COLOR_MASKS + uint32_t reserved; ///< Currently reserved, unused, always 0 + uint32_t flags; ///< Currently reserved, unused, always 0 + +} MBG_LED_INFO; + +#define _mbg_swab_mbg_led_info( _p ) \ +do \ +{ \ + _mbg_swab_mbg_led_settings( &(_p)->settings ); \ + _mbg_swab32( &(_p)->supp_modes ); \ + _mbg_swab32( &(_p)->supp_colors ); \ + _mbg_swab32( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Current settings and general capabilities of an LED, plus index + * + * @see ::MBG_LED_INFO + * @see ::MBG_LED_LIMITS + */ +typedef struct +{ + uint16_t idx; ///< 0..::MBG_LED_LIMITS::num_leds-1 + MBG_LED_INFO info; ///< LED info + +} MBG_LED_INFO_IDX; + +#define _mbg_swab_mbg_led_info_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_mbg_led_info( &(_p)->info ); \ +} while ( 0 ) + +/** @} defgroup group_led_api */ + + + +/** + * @defgroup group_lne_api Definitions specific to LNE devices + * + * @note These structures and definitions are only supported by a device + * if ::MBG_XFEATURE_LNE_API is set in the extended device features. + * + * @{ */ + + +/** + * @brief General info to be read from an LNE device + * + * Used to query from a device e.g. how many LNE ports are provided + * by the device, then index 0..::MBG_LNE_LIMITS::num_ports-1 + * ::MBG_LNE_PORT_INFO_IDX or ::MBG_LNE_PORT_SETTINGS_IDX structures + * can be read from or written to the device. + * + * @see ::MBG_LNE_PORT_SETTINGS_IDX + * @see ::MBG_LNE_PORT_INFO_IDX + */ +typedef struct +{ + uint8_t num_ports; ///< Number of supported ports, see ::MBG_LNE_PORT_SETTINGS_IDX::idx and ::MBG_LNE_PORT_INFO_IDX::idx + uint8_t reserved_0; ///< Currently reserved, unused, always 0 + uint16_t reserved_1; ///< Currently reserved, unused, always 0 + uint32_t features; // ### TODO Mask of supported features, see ::MBG_LNE_FEAT_MASKS + ///< Currently reserved, unused, always 0 + uint32_t reserved_2; ///< Currently reserved, unused, always 0 + +} MBG_LNE_LIMITS; + +#define _mbg_swab_mbg_lne_limits( _p ) \ +do \ +{ \ + _mbg_swab8( &(_p)->num_ports ); \ + _mbg_swab8( &(_p)->reserved_0 ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->features ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ +} while ( 0 ) + + + +#if 0 //### TODO //################# + +/** + * @brief LNE feature bits + * + * Used to define ::MBG_LNE_FEAT_MASKS + * + * @see ::MBG_LNE_FEAT_MASKS + */ +enum MBG_LNE_FEAT_BITS +{ + MBG_LNE_FEAT_BIT_SWITCH_PWR, ///< Power switching off all LNE ports at once supported, see ::MBG_LNE_PWR_STATE + N_MBG_LNE_FEAT_BITS +}; + + + +/** + * @brief LNE feature bit masks + * + * Used with ::MBG_LNE_LIMITS::features + * + * @see ::MBG_LNE_FEAT_BITS + */ +enum MBG_LNE_FEAT_MASKS +{ + MBG_LNE_FEAT_MASK_SWITCH_PWR = ( 1UL << MBG_LNE_FEAT_BIT_SWITCH_PWR ) ///< see ::MBG_LNE_FEAT_BIT_SWITCH_PWR +}; + +#endif + + + +/** + * @brief Configuration settings for a single LNE port + * + * @see ::MBG_LNE_PORT_SETTINGS_IDX + */ +typedef struct +{ + uint32_t reserved_0; ///< currently reserved, unused, always 0 + uint32_t reserved_1; ///< currently reserved, unused, always 0 + uint32_t reserved_2; ///< currently reserved, unused, always 0 + uint32_t flags; ///< currently reserved, unused, always 0 + +} MBG_LNE_PORT_SETTINGS; + +#define _mbg_swab_mbg_lne_port_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Configuration settings for a single LNE port, plus index + * + * @see ::MBG_LNE_PORT_SETTINGS + * @see ::MBG_LNE_LIMITS + */ +typedef struct +{ + uint16_t idx; ///< 0..::MBG_LNE_LIMITS::num_ports-1 + MBG_LNE_PORT_SETTINGS settings; ///< LNE settings + +} MBG_LNE_PORT_SETTINGS_IDX; + +#define _mbg_swab_mbg_lne_port_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_mbg_lne_port_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +/** + * @brief Current settings and general capabilities of an LNE port + * + * This structure should be read from the device to retrieve the + * current settings of an LNE port plus its capabilities, ### e.g. the + * supported modes, colors, etc. + * + * @see ::MBG_LNE_PORT_INFO_IDX + */ +typedef struct +{ + MBG_LNE_PORT_SETTINGS settings; ///< Current LNE port settings + MBG_MAC_ADDR mac_addr; ///< The MAC address assigned to this port + uint32_t reserved_0; ///< currently reserved, unused, always 0 + uint32_t reserved_1; ///< currently reserved, unused, always 0 + uint32_t reserved_2; ///< currently reserved, unused, always 0 + uint32_t flags; ///< see ::LNE_PORT_FLAG_MASKS + +} MBG_LNE_PORT_INFO; + +#define _mbg_swab_mbg_lne_port_info( _p ) \ +do \ +{ \ + _mbg_swab_mbg_lne_port_settings( &(_p)->settings ); \ + _mbg_swab_mbg_mac_addr( &(_p)->mac_addr ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Current settings and general capabilities of an LNE port, plus index + * + * @see ::MBG_LNE_PORT_INFO + * @see ::MBG_LNE_LIMITS + */ +typedef struct +{ + uint16_t idx; ///< 0..::MBG_LED_LIMITS::num_leds-1 + MBG_LNE_PORT_INFO info; ///< LNE port info + +} MBG_LNE_PORT_INFO_IDX; + +#define _mbg_swab_mbg_lne_port_info_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_mbg_lne_port_info( &(_p)->info ); \ +} while ( 0 ) + + + +/** + * @brief LNE port flag bits + * + * Used to define ::LNE_PORT_FLAG_MASKS + * + * @see ::LNE_PORT_FLAG_MASKS + */ +enum LNE_PORT_FLAG_BITS +{ + LNE_PORT_FLAG_BIT_IS_SFP, + N_LNE_PORT_FLAG_BITS +}; + + + +/** + * @brief LNE port flag bit masks + * + * Used with ::MBG_LNE_PORT_INFO::flags + * + * @see ::LNE_PORT_FLAG_BITS + */ +enum LNE_PORT_FLAG_MASKS +{ + LNE_PORT_FLAG_MASK_IS_SFP = ( 1UL << LNE_PORT_FLAG_BIT_IS_SFP ) ///< see ::LNE_PORT_FLAG_BIT_IS_SFP +}; + + +/** @} defgroup group_lne_api */ + + + +/** + * @defgroup group_pwr_ctl_api Definitions for power control API + * + * @note These structures and definitions are only supported by a device + * if ::MBG_XFEATURE_PWR_CTL_API is set in the extended device features. + * + * @{ */ + + +/** + * @brief Device power states + * + * Used with ::MBG_PWR_CTL::state. + */ +enum MBG_PWR_STATES +{ + MBG_PWR_STATE_OFF, + MBG_PWR_STATE_ON, + N_MBG_PWR_STATES +}; + + + +/** + * @brief Device power control + * + * Used to change or retrieve a device's power state + */ +typedef struct +{ + uint8_t state; ///< see ::MBG_PWR_STATES + uint8_t reserved_0; ///< Currently reserved, unused, always 0 + uint16_t reserved_1; ///< Currently reserved, unused, always 0 + +} MBG_PWR_CTL; + +#define _mbg_swab_mbg_pwr_ctl( _p ) \ +do \ +{ \ + _mbg_swab8( &(_p)->state ); \ + _mbg_swab8( &(_p)->reserved_0 ); \ + _mbg_swab16( &(_p)->reserved_1 ); \ +} while ( 0 ) + +/** @} defgroup group_pwr_ctl_api */ + + + + +/** + * @defgroup group_ext_sys_info Extended system information + * + * @note This structure and its definitions are only supported by a device + * if ::MBG_XFEATURE_EXT_SYS_INFO is set in the extended device features. + * + * @{ */ + + +/** + * @brief Bits used to define ::MBG_EXT_SYS_INFO_MSKS + * + * @see ::MBG_EXT_SYS_INFO_MSKS + */ +enum MBG_EXT_SYS_INFO_BITS +{ + MBG_EXT_SYS_INFO_BIT_SW_REV, + MBG_EXT_SYS_INFO_BIT_HW_REV, + MBG_EXT_SYS_INFO_BIT_OS_REV, + MBG_EXT_SYS_INFO_BIT_FPGA_REV, + MBG_EXT_SYS_INFO_BIT_CORE_MOD_REV, + N_MBG_EXT_SYS_INFO_BITS +}; + + + +/** + * @brief Bit masks of supported revision numbers + * + * Used with ::MBG_EXT_SYS_INFO::supp_members + * + * @see ::MBG_EXT_SYS_INFO_BITS + */ +enum MBG_EXT_SYS_INFO_MSKS +{ + MBG_EXT_SYS_INFO_MSK_SW_REV = ( 1UL << MBG_EXT_SYS_INFO_BIT_SW_REV ), ///< see ::MBG_EXT_SYS_INFO_BIT_SW_REV + MBG_EXT_SYS_INFO_MSK_HW_REV = ( 1UL << MBG_EXT_SYS_INFO_BIT_HW_REV ), ///< see ::MBG_EXT_SYS_INFO_BIT_HW_REV + MBG_EXT_SYS_INFO_MSK_OS_REV = ( 1UL << MBG_EXT_SYS_INFO_BIT_OS_REV ), ///< see ::MBG_EXT_SYS_INFO_BIT_OS_REV + MBG_EXT_SYS_INFO_MSK_FPGA_REV = ( 1UL << MBG_EXT_SYS_INFO_BIT_FPGA_REV ), ///< see ::MBG_EXT_SYS_INFO_BIT_FPGA_REV + MBG_EXT_SYS_INFO_MSK_CORE_MOD_REV = ( 1UL << MBG_EXT_SYS_INFO_BIT_CORE_MOD_REV ) ///< see ::MBG_EXT_SYS_INFO_BIT_CORE_MOD_REV +}; + + +enum MBG_EXT_SYS_INFO_PROC_TYPES +{ + MBG_EXT_SYS_INFO_PROC_TYPE_NONE, + MBG_EXT_SYS_INFO_PROC_TYPE_CORTEX_A9, + MBG_EXT_SYS_INFO_PROC_TYPE_CORTEX_SAM3u, + MBG_EXT_SYS_INFO_PROC_TYPE_CORTEX_SAM3s, + MBG_EXT_SYS_INFO_PROC_TYPE_CORTEX_STM32F4, + N_MBG_EXT_SYS_INFO_PROC_TYPES +}; + +#define MBG_EXT_SYS_INFO_PROC_STRS \ +{ \ + "None", \ + "Cortex A9", \ + "Cortex SAM3u", \ + "Cortex SAM3s", \ + "Cortex STM32F4" \ +} + +enum MBG_EXT_SYS_INFO_FPGA_TYPES +{ + MBG_EXT_SYS_INFO_FPGA_TYPE_NONE, + MBG_EXT_SYS_INFO_FPGA_TYPE_CYCLONE5_SOC, ///< System on chip + MBG_EXT_SYS_INFO_FPGA_TYPE_CYCLONE5, ///< Stand alone FPGA + MBG_EXT_SYS_INFO_FPGA_TYPE_CYCLONE4GX15, + MBG_EXT_SYS_INFO_FPGA_TYPE_CYLCONE4CE22, + N_MBG_EXT_SYS_INFO_FPGA_TYPES +}; + +#define MBG_EXT_SYS_INFO_FPGA_STRS \ +{ \ + "None", \ + "Cyclone5 SoC", \ + "Cyclone5", \ + "Cyclone4GX15", \ + "Cyclone4CE22" \ +} + +enum MBG_EXT_SYS_INFO_CORE_MOD_TYPES +{ + MBG_EXT_SYS_INFO_CORE_MOD_TYPE_NONE, + MBG_EXT_SYS_INFO_CORE_MOD_TYPE_UBX_LEA_M8F, ///< u-blox GNSS module without Galileo support + MBG_EXT_SYS_INFO_CORE_MOD_TYPE_UBX_LEA_M8T, ///< u-blox GNSS module with Galileo support + N_MBG_EXT_SYS_INFO_CORE_MOD_TYPES +}; + +#define MBG_EXT_SYS_INFO_CORE_MOD_STRS \ +{ \ + "None", \ + "u-blox LEA-M8F", \ + "u-blox LEA-M8T" \ +} + +typedef struct +{ + uint32_t supp_members; ///< ::MBG_EXT_SYS_INFO_MSKS + + uint32_t sw_rev; + uint32_t hw_rev; + uint32_t os_rev; + uint32_t fpga_rev; + + uint16_t proc_type; ///< See ::MBG_EXT_SYS_INFO_PROC_TYPES + uint16_t fpga_type; ///< See ::MBG_EXT_SYS_INFO_FPGA_TYPES + uint16_t core_mod_type; ///< See ::MBG_EXT_SYS_INFO_CORE_MOD_TYPES + uint16_t reserved; + + uint32_t core_mod_rev; + + /* Reserved for future use, currently 0 */ + uint32_t reserved_rev_3; + uint32_t reserved_rev_4; + uint32_t reserved_rev_5; + uint32_t reserved_rev_6; + uint32_t reserved_rev_7; + uint32_t reserved_rev_8; + uint32_t reserved_rev_9; + uint32_t reserved_rev_10; + uint32_t reserved_rev_11; + +} MBG_EXT_SYS_INFO; + +#define _mbg_swab_ext_sys_info( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->supp_members ); \ + _mbg_swab32( &(_p)->sw_rev ); \ + _mbg_swab32( &(_p)->hw_rev ); \ + _mbg_swab32( &(_p)->os_rev ); \ + _mbg_swab32( &(_p)->fpga_rev ); \ + _mbg_swab16( &(_p)->proc_type ); \ + _mbg_swab16( &(_p)->fpga_type ); \ + _mbg_swab16( &(_p)->core_mod_type ); \ + _mbg_swab16( &(_p)->reserved ); \ + _mbg_swab32( &(_p)->core_mod_rev ); \ +} while ( 0 ) + + +#define _mbg_encode_revision( _major, _minor, _patch ) \ + ( ( (_major) << 24) | ( (_minor) << 16 ) | (_patch) ) + + +#define _mbg_decode_revision( _rev, _major, _minor, _patch ) \ +{ \ + (_major) = ( (_rev) >> 24 ) & 0xff; \ + (_minor) = ( (_rev) >> 16 ) & 0xff; \ + (_patch) = (_rev) & 0xffff; \ +} + + +/** @} defgroup group_ext_sys_info */ + + +/** + * @defgroup group_license_limits License information + * + * @note This is probably obsolete. + * + * @{ */ + + +#define MBG_MAX_LICENSES 32 + + +/** + * @brief General license information to be read from a device + * + * Used to query from a device how many and which different license types + * are supported. If a special type is supported (licenses[MBG_LICENSE_BASE_TYPES] > 0), its + * license specific information can be queried from 0..licenses[MBG_LICENSE_BASE_TYPES]-1 via + * its license specific [...]_IDX structures and TLV API command codes. + * See ::MBG_XFEATURE_TLV_API and ::MBG_TLV_FEAT_TYPES. + */ +typedef struct +{ + uint8_t licenses[MBG_MAX_LICENSES]; ///< To get the number of supported licenses + ///< of a specific type you need to access the array + ///< with the specififc license index defined at ::MBG_LICENSE_BASE_TYPES. +} MBG_LICENSE_LIMITS; + + +enum MBG_LICENSE_BASE_TYPES +{ + MBG_LICENSE_BASE_TYPE_PTPV2, + MBG_LICENSE_BASE_TYPE_NTP, + MBG_LICENSE_BASE_TYPE_PTPV1, + MBG_LICENSE_BASE_TYPE_TIME_MONITOR, + N_MBG_LICENSE_BASE_TYPES +}; + + +/** + * @brief Bits used to define ::MBG_LICENSE_BASE_MSKS + * + * @see ::MBG_LICENSE_BASE_MSKS + */ +enum MBG_LICENSE_BASE_FLAGS +{ + MBG_LICENSE_BASE_FLAG_SUPP_UPGRADE, ///< License supports upgrading / modifying + N_MBG_LICENSE_BASE_FLAGS +}; + + +/** + * @brief Bit masks of common supported base license flags + * + * Used with ::MBG_LICENSE_BASE::supp_flags + * + * @see ::MBG_LICENSE_BASE_FLAGS + */ +enum MBG_LICENSE_BASE_MSKS +{ + MBG_LICENSE_BASE_MSK_SUPP_UPGRADE = ( 1UL << MBG_LICENSE_BASE_FLAG_SUPP_UPGRADE ) ///< See ::MBG_LICENSE_BASE_FLAG_SUPP_UPGRADE +}; + + +/** + * @brief Common license information + * + * Should be part of each individual license type. + */ +typedef struct +{ + uint8_t type; ///< See ::MBG_LICENSE_BASE_TYPES + uint8_t reserved_1; ///< Reserved for future use, currently 0 + uint16_t reserved_2; ///< Reserved for future use, currently 0 + uint32_t supp_flags; ///< See ::MBG_LICENSE_BASE_MSKS + uint32_t reserved_3; ///< Reserved for future use, currently 0 + uint32_t reserved_4; ///< Reserved for future use, currently 0 + +} MBG_LICENSE_BASE; + +#define _mbg_swab_license_base( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->supp_flags ); \ +} while ( 0 ) + + +/** + * @brief Bits used to define ::MBG_LICENSE_PTPV2_MEMBER_MSKS + * + * @see ::MBG_LICENSE_PTPV2_MEMBER_MSKS + */ +enum MBG_LICENSE_PTPV2_MEMBERS +{ + MBG_LICENSE_PTPV2_MEMBER_MAX_UCLIENTS, + MBG_LICENSE_PTPV2_MEMBER_MAX_MTRANS, + N_MBG_LICENSE_PTPV2_MEMBERS +}; + + +/** + * @brief Bit masks of PTPV2 license specific members + * + * Used with ::MBG_LICENSE_PTPV2::supp_members + * + * @see ::MBG_LICENSE_PTPV2_MEMBERS + */ +enum MBG_LICENSE_PTPV2_MEMBER_MSKS +{ + MBG_LICENSE_PTPV2_MEMBER_MSK_MAX_UCLIENTS = ( 1UL << MBG_LICENSE_PTPV2_MEMBER_MAX_UCLIENTS ), ///< See ::MBG_LICENSE_PTPV2_MEMBER_MAX_UCLIENTS + MBG_LICENSE_PTPV2_MEMBER_MSK_MAX_MTRANS = ( 1UL << MBG_LICENSE_PTPV2_MEMBER_MAX_MTRANS ) ///< See ::MBG_LICENSE_PTPV2_MEMBER_MAX_MTRANS +}; + + +/** + * @brief PTPV2 specific license information + * + */ +typedef struct +{ + MBG_LICENSE_BASE base; ///< See ::MBG_LICENSE_BASE + uint32_t supp_members; ///< See ::MBG_LICENSE_PTPV2_MEMBER_MSKS + uint32_t reserved_1; ///< Reserved for future use, currently 0 + uint16_t max_uclients; ///< Maximal number of supported unicast clients. + uint16_t reserved_2; ///< Reserved for future use, currently 0 + uint32_t max_mtrans; ///< Maximal number of supported multicast transactions per second. + uint32_t reserved_3; ///< Reserved for future use, currently 0 + uint32_t reserved_4; ///< Reserved for future use, currently 0 + uint32_t reserved_5; ///< Reserved for future use, currently 0 + uint32_t reserved_6; ///< Reserved for future use, currently 0 + +} MBG_LICENSE_PTPV2; + +#define _mbg_swab_license_ptpv2( _p ) \ +do \ +{ \ + _mbg_swab_license_base( &(_p)->base ); \ + _mbg_swab32( &(_p)->supp_members ); \ + _mbg_swab16( &(_p)->max_uclients ); \ + _mbg_swab32( &(_p)->max_mtrans ); \ +} while ( 0 ) + + +typedef struct +{ + uint32_t idx; + MBG_LICENSE_PTPV2 license; + +} MBG_LICENSE_PTPV2_IDX; + +#define _mbg_swab_license_ptpv2_idx( _p ) \ +do \ +{ \ + _mbg_swab_license_ptpv2( &(_p)->license ); \ + _mbg_swab32( &(_p)->idx ); \ +} while ( 0 ) + + +/** + * @brief Bits used to define ::MBG_LICENSE_NTP_MEMBER_MSKS + * + * @see ::MBG_LICENSE_NTP_MEMBER_MSKS + */ +enum MBG_LICENSE_NTP_MEMBERS +{ + MBG_LICENSE_NTP_MEMBER_MAX_RPS, + N_MBG_LICENSE_NTP_MEMBERS +}; + + +/** + * @brief Bit masks of NTP license specific members + * + * Used with ::MBG_LICENSE_NTP::supp_members + * + * @see ::MBG_LICENSE_PTPV2_MEMBERS + */ +enum MBG_LICENSE_NTP_MEMBER_MSKS +{ + MBG_LICENSE_NTP_MEMBER_MSK_MAX_RPS = ( 1UL << MBG_LICENSE_NTP_MEMBER_MAX_RPS ) ///< See ::MBG_LICENSE_NTP_MEMBER_MAX_RPS +}; + + +/** + * @brief NTP specific license information + */ +typedef struct +{ + MBG_LICENSE_BASE base; ///< See ::MBG_LICENSE_BASE + uint32_t supp_members; ///< See ::MBG_LICENSE_NTP_MEMBER_MSKS + uint32_t max_rps; ///< Maximum number of supported NTP requests per second + uint32_t reserved_1; ///< Reserved for future use, currently 0 + uint32_t reserved_2; ///< Reserved for future use, currently 0 + uint32_t reserved_3; ///< Reserved for future use, currently 0 + uint32_t reserved_4; ///< Reserved for future use, currently 0 + uint32_t reserved_5; ///< Reserved for future use, currently 0 + uint32_t reserved_6; ///< Reserved for future use, currently 0 + +} MBG_LICENSE_NTP; + +#define _mbg_swab_license_ntp( _p ) \ +do \ +{ \ + _mbg_swab_license_base( &(_p)->base ); \ + _mbg_swab32( &(_p)->supp_members ); \ + _mbg_swab32( &(_p)->max_rps ); \ +} while ( 0 ) + + + +typedef struct +{ + uint32_t idx; + MBG_LICENSE_NTP license; + +} MBG_LICENSE_NTP_IDX; + +#define _mbg_swab_license_ntp_idx( _p ) \ +do \ +{ \ + _mbg_swab_license_ntp( &(_p)->license ); \ + _mbg_swab32( &(_p)->idx ); \ +} while ( 0 ) + +/** + * @brief Bits used to define ::MBG_LICENSE_PTPV1_MEMBER_MSKS + * + * @see ::MBG_LICENSE_PTPV1_MEMBER_MSKS + */ +enum MBG_LICENSE_PTPV1_MEMBERS +{ + MBG_LICENSE_PTPV1_MEMBER_MAX_RPS, + N_MBG_LICENSE_PTPV1_MEMBERS +}; + + +/** + * @brief Bit masks of PTPV1 license specific members + * + * Used with ::MBG_LICENSE_PTPV1::supp_members + * + * @see ::MBG_LICENSE_PTPV2_MEMBERS + */ +enum MBG_LICENSE_PTPV1_MEMBER_MSKS +{ + MBG_LICENSE_PTPV1_MEMBER_MSK_MAX_RPS = ( 1UL << MBG_LICENSE_PTPV1_MEMBER_MAX_RPS ) ///< See ::MBG_LICENSE_PTPV1_MEMBER_MAX_RPS +}; + + +/** + * @brief NTP specific license information + */ +typedef struct +{ + MBG_LICENSE_BASE base; ///< See ::MBG_LICENSE_BASE + uint32_t supp_members; ///< See ::MBG_LICENSE_PTPV1_MEMBER_MSKS + uint32_t max_rps; ///< Maximum number of supported PTPv1 delay requests per second + uint32_t reserved_1; ///< Reserved for future use, currently 0 + uint32_t reserved_2; ///< Reserved for future use, currently 0 + uint32_t reserved_3; ///< Reserved for future use, currently 0 + uint32_t reserved_4; ///< Reserved for future use, currently 0 + uint32_t reserved_5; ///< Reserved for future use, currently 0 + uint32_t reserved_6; ///< Reserved for future use, currently 0 + +} MBG_LICENSE_PTPV1; + +#define _mbg_swab_license_ptpv1( _p ) \ +do \ +{ \ + _mbg_swab_license_base( &(_p)->base ); \ + _mbg_swab32( &(_p)->supp_members ); \ + _mbg_swab32( &(_p)->max_rps ); \ +} while ( 0 ) + + +typedef struct +{ + uint32_t idx; + MBG_LICENSE_PTPV1 license; + +} MBG_LICENSE_PTPV1_IDX; + +#define _mbg_swab_license_ptpv1_idx( _p ) \ +do \ +{ \ + _mbg_swab_license_ptpv1( &(_p)->license ); \ + _mbg_swab32( &(_p)->idx ); \ +} while ( 0 ) + +/** + * @brief Bits used to define ::MBG_LICENSE_TIME_MONITOR_MEMBER_MSKS + * + * @see ::MBG_LICENSE_TIME_MONITOR_MEMBER_MSKS + */ +enum MBG_LICENSE_TIME_MONITOR_MEMBERS +{ + MBG_LICENSE_TIME_MONITOR_MEMBER_MAX_PTPV2_CLIENTS, + MBG_LICENSE_TIME_MONITOR_MEMBER_MAX_NTP_CLIENTS, + N_MBG_LICENSE_TIME_MONITOR_MEMBERS +}; + + +/** + * @brief Bit masks of Time Monitor license specific members + * + * Used with ::MBG_LICENSE_TIME_MONITOR::supp_members + * + * @see ::MBG_LICENSE_TIME_MONITOR_MEMBERS + */ +enum MBG_LICENSE_TIME_MONITOR_MEMBER_MSKS +{ + MBG_LICENSE_TIME_MONITOR_MEMBER_MSK_MAX_PTPV2_CLIENTS = ( 1UL << MBG_LICENSE_TIME_MONITOR_MEMBER_MAX_PTPV2_CLIENTS ), ///< See ::MBG_LICENSE_TIME_MONITOR_MEMBER_MAX_PTPV2_CLIENTS + MBG_LICENSE_TIME_MONITOR_MEMBER_MSK_MAX_NTP_CLIENTS = ( 1UL << MBG_LICENSE_TIME_MONITOR_MEMBER_MAX_NTP_CLIENTS ) ///< See ::MBG_LICENSE_TIME_MONITOR_MEMBER_MAX_NTP_CLIENTS +}; + + +/** + * @brief Time Monitor specific license information + * + */ +typedef struct +{ + MBG_LICENSE_BASE base; ///< See ::MBG_LICENSE_BASE + uint32_t supp_members; ///< See ::MBG_LICENSE_TIME_MONITOR_MEMBER_MSKS + uint32_t reserved_1; ///< Reserved for future use, currently 0 + uint16_t max_ptpv2_clients; ///< Maximum number of supported PTPv2 clients to be monitored + uint16_t max_ntp_clients; ///< Maximum number of supported NTP clients to be monitored + uint32_t reserved_2; ///< Reserved for future use, currently 0 + uint32_t reserved_3; ///< Reserved for future use, currently 0 + uint32_t reserved_4; ///< Reserved for future use, currently 0 + uint32_t reserved_5; ///< Reserved for future use, currently 0 + uint32_t reserved_6; ///< Reserved for future use, currently 0 + +} MBG_LICENSE_TIME_MONITOR; + +#define _mbg_swab_license_time_monitor( _p ) \ +do \ +{ \ + _mbg_swab_license_base( &(_p)->base ); \ + _mbg_swab32( &(_p)->supp_members ); \ + _mbg_swab16( &(_p)->max_ptpv2_clients ); \ + _mbg_swab16( &(_p)->max_ntp_clients ); \ +} while ( 0 ) + + +typedef struct +{ + uint32_t idx; + MBG_LICENSE_TIME_MONITOR license; + +} MBG_LICENSE_TIME_MONITOR_IDX; + +#define _mbg_swab_license_time_monitor_idx( _p ) \ +do \ +{ \ + _mbg_swab_license_time_monitor( &(_p)->license ); \ + _mbg_swab32( &(_p)->idx ); \ +} while ( 0 ) + +/** @} defgroup group_license_limits */ + + + +/** + * @defgroup group_clk_res_info Clock resolution info + * + * @note This structure and its definitions are only supported by a device + * if ::MBG_XFEATURE_CLK_RES_INFO is set in the extended device features. + * + * @{ */ + +/** + * @brief Clock resolution information + * + * @see @ref group_clk_res_info + */ +typedef struct +{ + uint32_t base_clk; ///< Base clock of the internal time base [MHz] + uint32_t num_clk_phase; ///< Number of multi-phase clock signals + uint32_t reserved_9; + uint32_t reserved_8; + uint32_t reserved_7; + uint32_t reserved_6; + uint32_t reserved_5; + uint32_t reserved_4; + uint32_t reserved_3; + uint32_t reserved_2; + uint32_t reserved_1; + uint32_t reserved_0; + +} MBG_CLK_RES_INFO; + +#define _mbg_swab_mbg_clk_res_info( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->base_clk ); \ + _mbg_swab32( &(_p)->num_clk_phase ); \ + _mbg_swab32( &(_p)->reserved_9 ); \ + _mbg_swab32( &(_p)->reserved_8 ); \ + _mbg_swab32( &(_p)->reserved_7 ); \ + _mbg_swab32( &(_p)->reserved_6 ); \ + _mbg_swab32( &(_p)->reserved_5 ); \ + _mbg_swab32( &(_p)->reserved_4 ); \ + _mbg_swab32( &(_p)->reserved_3 ); \ + _mbg_swab32( &(_p)->reserved_2 ); \ + _mbg_swab32( &(_p)->reserved_1 ); \ + _mbg_swab32( &(_p)->reserved_0 ); \ +} while ( 0 ) + +/** @} defgroup group_clk_res_info */ + + + +/** + * @brief Type of upcoming transaction sequence + * + * Used in combination with ::GPS_BEGIN_TRANSACTION and ::GPS_END_TRANSACTION + * to announce which type of transaction is going to be started. Thus the receiver + * can prepare for following actions. + */ +enum MBG_TRANSACTION_TYPES +{ + MBG_TRANSACTION_TYPE_NONE, + /* ### TODO FIXME + * Network transaction requires at least and as first command: + * - ::GPS_NET_GLB_CFG (::MBG_NET_GLB_CFG_INFO) + * Depending on ::MBG_NET_GLB_CFG_INFO::glb_settings and its num_[...] + * members there are a couple of index commands which should be handled in any order: + * - ::GPS_NET_DNS_SRVR (::MBG_IP_ADDR_IDX) + * - ::GPS_NET_DNS_SRCH_DOM (::MBG_NET_NAME_IDX) + * - ::GPS_NET_INTF_LINK_IDX (::MBG_NET_INTF_LINK_INFO_IDX) + * - ::GPS_NET_INTF_ADDR_IDX (::MBG_NET_INTF_ADDR_INFO_IDX) + * - ::GPS_NET_INTF_ROUTE_IDX (::MBG_NET_INTF_ROUTE_INFO_IDX) + */ + MBG_TRANSACTION_TYPE_NETWORK, + MBG_TRANSACTION_TYPE_PTP, + /* + * Commands in any order if supp. by ::MBG_SNMP_GLB_INFO::max_[...] + * and ::MBG_SNMP_GLB_INFO::supp_versions + * + * Should be used within ::MBG_TRANSACTION_TYPE_MONITORING but may also be + * used stand-alone. + * + * - ::GPS_SNMP_GLB_SETTINGS + * - ::GPS_SNMP_V12_SETTINGS_IDX + * - ::GPS_SNMP_V12_TRAP_SETTINGS_IDX + * - ::GPS_SNMP_V3_SETTINGS_IDX + * - ::GPS_SNMP_V3_TRAP_SETTINGS_IDX + */ + MBG_TRANSACTION_TYPE_MONITORING_SNMP, + /* + * NTP transaction requires at least and as first command: + * ::GPS_NTP_GLB_CFG + * Commands in any order if supp. by ::MBG_NTP_GLB_INFO + * and ::MBG_SNMP_GLB_INFO::supp_versions + * + * - ::GPS_NTP_REFCLK_CFG + * - ::GPS_NTP_MISC_LIMITS + * - ::GPS_NTP_MISC_ORPHAN_MODE + * - ::GPS_NTP_SYMM_KEY_LIMITS + * - ::GPS_NTP_SYMM_KEY_CFG + * - ::GPS_NTP_TRUSTED_KEY_CFG + * - ::GPS_NTP_CLNT_MODE_CFG + * - ::GPS_NTP_SRV_MODE_CFG + * - ::GPS_NTP_PEER_SETTINGS_IDX + * - ::GPS_NTP_SYS_STATE + * - ::GPS_NTP_PEER_STATE_IDX + */ + MBG_TRANSACTION_TYPE_NTP, + /* + * IO Port transaction used to read or write ALL_IO_PORT_INFO + * Commands related to this transaction: + * + * - ::GPS_IO_PORT_LIMITS + * - ::GPS_IO_PORT_SETTINGS_IDX + * - ::GPS_IO_PORT_INFO_IDX + * - ::GPS_IO_PORT_TYPE_INFO_IDX + * - ::GPS_IO_PORT_STATUS_IDX + */ + MBG_TRANSACTION_TYPE_IO_PORT, + /* + * Commands in any order if ::MBG_XFEATURE_MONITORING is set in + * ::MBG_XFEATURE_BUFFER. + * + * Transactions ::MBG_TRANSACTION_TYPE_MONITORING_SNMP and + * ::MBG_TRANSACTION_TYPE_EVENTS may also be opened within + * ::MBG_TRANSACTION_TYPE_MONITORING transaction. + * + * - ::GPS_MONITORING_LIMITS + * - ::GPS_MONITORING_STATUS + */ + MBG_TRANSACTION_TYPE_MONITORING, + /* + * Commands in any order if ::MBG_XFEATURE_MONITORING is set in + * ::MBG_XFEATURE_BUFFER. + * + * Should be used within ::MBG_TRANSACTION_TYPE_MONITORING but may also be + * used stand-alone. + * + * - ::GPS_EVENT_IDX + * - ::GPS_EVENT_STAT_IDX + */ + MBG_TRANSACTION_TYPE_EVENTS, + + MAX_MBG_TRANSACTION_TYPES +}; + + +#define MBG_TRANSACTION_MSK_SET 0x8000 +#define _mbg_is_set_transaction( _type ) ( ( _type ) & MBG_TRANSACTION_MSK_SET ) +#define _mbg_transaction_type_set( _type ) ( ( _type ) |= MBG_TRANSACTION_MSK_SET ) + + +/** + * @defgroup group_io_ports IO Port API + * + * @note This structure and its definitions are only supported by a device + * if ::MBG_XFEATURE_IO_PORTS is set in the extended device features. + * + * @{ */ + +/** + * @brief IO Port types + * + * Used with ::MBG_IO_PORT_TYPE_INFO::port_type and ::MBG_IO_PORT_SETTINGS::port_type + */ +enum MBG_IO_PORT_TYPES +{ + MBG_IO_PORT_TYPE_PPS, + MBG_IO_PORT_TYPE_10MHz, + MBG_IO_PORT_TYPE_2048KHz, + MBG_IO_PORT_TYPE_GPIO, + MBG_IO_PORT_TYPE_ETHERNET, + MBG_IO_PORT_TYPE_TERMINAL, + MBG_IO_PORT_TYPE_MULTI, + MBG_IO_PORT_TYPE_POUT, + N_MBG_IO_PORT_TYPES +}; + +/** + * @brief Port type to be used for an undefined/unassigned port + * + * Only use this for ::MBG_IO_PORT_SETTINGS::port_type + * if ::MBG_IO_PORT_SETTINGS::op_mode is ::MBG_IO_PORT_OP_MODE_NONE + */ +#define MBG_IO_PORT_TYPE_NONE ( (uint16_t) -1 ) + + +/** + * @brief Strings descriptions for ::MBG_IO_PORT_TYPES + * + * Can be used to initialize a string array of ::N_MBG_IO_PORT_TYPES entries, + * so the number of strings must correspond to ::N_MBG_IO_PORT_TYPES. + * + * @see ::MBG_IO_PORT_TYPES + */ +#define MBG_IO_PORT_TYPE_STRS \ +{ \ + "PPS", \ + "10 MHz", \ + "2048 KHz", \ + "GPIO", \ + "Ethernet", \ + "Terminal", \ + "Multi", \ + "Prog. Output" \ +} + + +/** + * @brief Port directions (input or output) + * + * @see ::MBG_IO_PORT_DIR_MSKS + */ +enum MBG_IO_PORT_DIRS +{ + MBG_IO_PORT_DIR_NONE = -1, ///< Only use this for ::MBG_IO_PORT_SETTINGS::direction if ::MBG_IO_PORT_SETTINGS::op_mode is ::MBG_IO_PORT_OP_MODE_NONE + MBG_IO_PORT_DIR_IN, ///< Port is input like PPS In + MBG_IO_PORT_DIR_OUT, ///< Port is output like 10Mhz + MBG_IO_PORT_DIR_IN_OUT, ///< Port can be in- & output in parallel like network port + N_MBG_IO_PORT_DIRS +}; + + +/** + * @brief Strings descriptions for ::MBG_IO_PORT_DIRS + * + * Can be used to initialize a string array of ::N_MBG_IO_PORT_DIRS entries, + * so the number of strings must correspond to ::N_MBG_IO_PORT_DIRS. + * + * @see ::MBG_IO_PORT_DIRS + */ +#define MBG_IO_PORT_DIR_STRS \ +{ \ + "Input", \ + "Output", \ + "Input/Output" \ +} + + +/** + * @brief Bit masks of Meinberg I/O port directions + * + * Used with ::MBG_IO_PORT_TYPE_INFO::supp_dirs + * + * @see ::MBG_IO_PORT_DIRS + */ +enum MBG_IO_PORT_DIR_MSKS +{ + MBG_IO_PORT_MSK_DIR_IN = ( 1UL << MBG_IO_PORT_DIR_IN ), ///< See ::MBG_IO_PORT_DIR_IN + MBG_IO_PORT_MSK_DIR_OUT = ( 1UL << MBG_IO_PORT_DIR_OUT ), ///< See ::MBG_IO_PORT_DIR_OUT + MBG_IO_PORT_MSK_DIR_IN_OUT = ( 1UL << MBG_IO_PORT_DIR_IN_OUT ) ///< See ::MBG_IO_PORT_DIR_IN_OUT +}; + + +/** + * @brief Port type sources + * + * Configurable sources for an I/O port type + * + * @see ::MBG_IO_PORT_SRC_MSKS + */ +enum MBG_IO_PORT_SRCS +{ + MBG_IO_PORT_SRC_NONE = -1, ///< Only use this for ::MBG_IO_PORT_SETTINGS::source if ::MBG_IO_PORT_SETTINGS::op_mode is ::MBG_IO_PORT_OP_MODE_NONE + MBG_IO_PORT_SRC_STATIC, ///< Static, not configurable + MBG_IO_PORT_SRC_LOCAL, ///< Locally generated, e.g. on (carrier) board + MBG_IO_PORT_SRC_ASSOC_CLOCK, ///< Fixed (wired) clock from back plane (e.g. refclock 1 in M500 IMS) + MBG_IO_PORT_SRC_ACTIVE_CLOCK, ///< Switched clock from back plane (e.g. selected by RSC) + MBG_IO_PORT_SRC_CLK1, ///< Clock 1 fixed (CPU board only) + MBG_IO_PORT_SRC_CLK2, ///< Clock 2 fixed (CPU board only) + MBG_IO_PORT_SRC_ARC, ///< Any rate converter + MBG_IO_PORT_SRC_OSC, ///< Oscillator + MBG_IO_PORT_SRC_SYNCE, ///< SyncE + N_MBG_IO_PORT_SRCS +}; + + +/** + * @brief Strings descriptions for ::MBG_IO_PORT_SRCS + * + * Can be used to initialize a string array of ::N_MBG_IO_PORT_SRCS entries, + * so the number of strings must correspond to ::N_MBG_IO_PORT_SRCS. + * + * @see ::MBG_IO_PORT_SRCS + */ +#define MBG_IO_PORT_SRC_STRS \ +{ \ + "Static", \ + "Locally generated", \ + "Associated clock", \ + "Active clock", \ + "Clock 1 fixed", \ + "Clock 2 fixed", \ + "Any rate converter", \ + "Oscillator", \ + "SyncE" \ +} + + +/** + * @brief Bit masks of Meinberg I/O port attitudes + * + * Used with ::MBG_IO_PORT_TYPE_INFO::supp_srcs + * + * @see ::MBG_IO_PORT_SRCS + */ +enum MBG_IO_PORT_SRC_MSKS +{ + MBG_IO_PORT_SRC_MSK_STATIC = (1UL << MBG_IO_PORT_SRC_STATIC), ///< See ::MBG_IO_PORT_SRC_STATIC + MBG_IO_PORT_SRC_MSK_LOCAL = (1UL << MBG_IO_PORT_SRC_LOCAL), ///< See ::MBG_IO_PORT_SRC_LOCAL + MBG_IO_PORT_SRC_MSK_ASSOC_CLOCK = (1UL << MBG_IO_PORT_SRC_ASSOC_CLOCK), ///< See ::MBG_IO_PORT_SRC_ASSOC_CLOCK + MBG_IO_PORT_SRC_MSK_ACTIVE_CLOCK = (1UL << MBG_IO_PORT_SRC_ACTIVE_CLOCK), ///< See ::MBG_IO_PORT_SRC_ACTIVE_CLOCK + MBG_IO_PORT_SRC_MSK_CLK1 = (1UL << MBG_IO_PORT_SRC_CLK1), ///< See ::MBG_IO_PORT_SRC_CLK1 + MBG_IO_PORT_SRC_MSK_CLK2 = (1UL << MBG_IO_PORT_SRC_CLK2), ///< See ::MBG_IO_PORT_SRC_CLK2 + MBG_IO_PORT_SRC_MSK_ARC = (1UL << MBG_IO_PORT_SRC_ARC), ///< See ::MBG_IO_PORT_SRC_ARC + MBG_IO_PORT_SRC_MSK_OSC = (1UL << MBG_IO_PORT_SRC_OSC), ///< See ::MBG_IO_PORT_SRC_OSC + MBG_IO_PORT_SRC_MSK_SYNCE = (1UL << MBG_IO_PORT_SRC_SYNCE) ///< See ::MBG_IO_PORT_SRC_SYNCE +}; + + +/** + * @brief Port connector types + * + * Used with ::MBG_IO_PORT_INFO::conn_type + * + */ +enum MBG_IO_PORT_CONN_TYPES +{ + MBG_IO_PORT_CONN_TYPE_SMA, + MBG_IO_PORT_CONN_TYPE_BNC, + MBG_IO_PORT_CONN_TYPE_DSUB25, + MBG_IO_PORT_CONN_TYPE_RJ45, + MBG_IO_PORT_CONN_TYPE_SFP, + MBG_IO_PORT_CONN_TYPE_USB_MICRO_B, + MBG_IO_PORT_CONN_TYPE_USB_A, + MBG_IO_PORT_CONN_TYPE_USB_B, + MBG_IO_PORT_CONN_TYPE_SMA_ANT, + MBG_IO_PORT_CONN_TYPE_RJ45_ETH, + MBG_IO_PORT_CONN_TYPE_2_PIN_DFK, + MBG_IO_PORT_CONN_TYPE_3_PIN_DFK, + MBG_IO_PORT_CONN_TYPE_16_PIN_DFK, + MBG_IO_PORT_CONN_TYPE_BNC_ISO, + MBG_IO_PORT_CONN_TYPE_DSUB9, + MBG_IO_PORT_CONN_TYPE_FIBRE_ST, + MBG_IO_PORT_CONN_TYPE_XHE_SPI, + N_MBG_IO_PORT_CONN_TYPES +}; + + +/** + * @brief Strings descriptions for ::MBG_IO_PORT_CONN_TYPES + * + * Can be used to initialize a string array of ::N_MBG_IO_PORT_CONN_TYPES entries, + * so the number of strings must correspond to ::N_MBG_IO_PORT_CONN_TYPES. + * + * @see ::MBG_IO_PORT_CONN_TYPES + */ +#define MBG_IO_PORT_CONN_TYPE_STRS \ +{ \ + "SMA", \ + "BNC", \ + "D-Sub 25", \ + "RJ45", \ + "SFP", \ + "USB Micro B", \ + "USB A", \ + "USB B", \ + "SMA Antenna", \ + "RJ45 Ethernet", \ + "DFK 2-Pin", \ + "DFK 3-Pin", \ + "DFK 16-Pin", \ + "BNC isolated", \ + "D-Sub 9", \ + "Fibre ST", \ + "XHE SPI" \ +} + + +/** + * @brief Position of a port on a card + * + * Used with ::MBG_IO_PORT_INFO::position + * + */ +enum MBG_IO_PORT_POS +{ + MBG_IO_PORT_POS_FRONT_COL_1, ///> Connector column 1, front + MBG_IO_PORT_POS_REAR_COL_1, ///> Connector column 1, rear + MBG_IO_PORT_POS_FRONT_COL_2, ///> Connector column 2, front + MBG_IO_PORT_POS_REAR_COL_2, ///> Connector column 2, rear + MBG_IO_PORT_POS_FRONT_COL_3, ///> Connector column 3, front + MBG_IO_PORT_POS_REAR_COL_3, ///> Connector column 3, rear + MBG_IO_PORT_POS_FRONT_COL_4, ///> Connector column 4, front + MBG_IO_PORT_POS_REAR_COL_4, ///> Connector column 4, rear + N_MBG_IO_PORT_POS +}; + + +/** + * @brief Bit masks of Meinberg I/O port attitudes + * + * Used with ::MBG_IO_PORT_TYPE_INFO::supp_srcs + * + * @see ::MBG_IO_PORT_POS + */ +enum MBG_IO_PORT_POS_MSKS +{ + MBG_IO_PORT_POS_MSK_FRONT_COL_1 = (1UL << MBG_IO_PORT_POS_FRONT_COL_1), ///< See ::MBG_IO_PORT_POS_FRONT_COL_1 + MBG_IO_PORT_POS_MSK_REAR_COL_1 = (1UL << MBG_IO_PORT_POS_REAR_COL_1), ///< See ::MBG_IO_PORT_POS_REAR_COL_1 + MBG_IO_PORT_POS_MSK_FRONT_COL_2 = (1UL << MBG_IO_PORT_POS_FRONT_COL_2), ///< See ::MBG_IO_PORT_POS_FRONT_COL_2 + MBG_IO_PORT_POS_MSK_REAR_COL_2 = (1UL << MBG_IO_PORT_POS_REAR_COL_2), ///< See ::MBG_IO_PORT_POS_REAR_COL_2 + MBG_IO_PORT_POS_MSK_FRONT_COL_3 = (1UL << MBG_IO_PORT_POS_FRONT_COL_3), ///< See ::MBG_IO_PORT_POS_FRONT_COL_3 + MBG_IO_PORT_POS_MSK_REAR_COL_3 = (1UL << MBG_IO_PORT_POS_REAR_COL_3), ///< See ::MBG_IO_PORT_POS_REAR_COL_3 + MBG_IO_PORT_POS_MSK_FRONT_COL_4 = (1UL << MBG_IO_PORT_POS_FRONT_COL_4), ///< See ::MBG_IO_PORT_POS_FRONT_COL_4 + MBG_IO_PORT_POS_MSK_REAR_COL_4 = (1UL << MBG_IO_PORT_POS_REAR_COL_4) ///< See ::MBG_IO_PORT_POS_REAR_COL_4 +}; + + +/** + * @brief IO Port Limits + * + * @see @ref group_io_ports + * @see ::MBG_IO_PORT_SETTINGS + * @see ::MBG_IO_PORT_SETTINGS_U + * @see ::MBG_IO_PORT_SETTINGS_IDX + * @see ::MBG_IO_PORT_INFO + * @see ::MBG_IO_PORT_INFO_IDX + * @see ::MBG_IO_PORT_TYPE_INFO + * @see ::MBG_IO_PORT_TYPE_INFO_IDX + * @see ::MBG_IO_PORT_STATUS + * @see ::MBG_IO_PORT_STATUS_IDX + */ +typedef struct +{ + uint8_t num_ports; + uint8_t reserved_1[3]; ///< Reserved, currently 0 + uint32_t supp_positions; ///< Determines the size of the card (i.e. 2 rows, front/rear) See ::MBG_IO_PORT_POS_MSKS + uint32_t reserved_2[10]; ///< Reserved, currently 0 + +} MBG_IO_PORT_LIMITS; + +#define _mbg_swab_io_port_limits( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->supp_positions ); \ +} while ( 0 ) + + + +/** + * @brief Port Operation Bits + * + * Used with ::MBG_IO_PORT_SETTINGS::op_mode + * + * For now, there is a per port operation mode setting which + * is quite equal to ::ENABLE_FLAGS. + * + * @see ::MBG_IO_PORT_OP_MODE_MSKS + */ +enum MBG_IO_PORT_OP_MODE_BITS +{ + MBG_IO_PORT_OP_MODE_NONE = -1, ///< Current mode cannot be determined + MBG_IO_PORT_OP_MODE_DISABLED, ///< Disabled port + MBG_IO_PORT_OP_MODE_ALWAYS, ///< Always enable port + MBG_IO_PORT_OP_MODE_IF_SYNC_ONLY, ///< Enable port if sync only + MBG_IO_PORT_OP_MODE_AFTER_SYNC, ///< Always enable port after being sync once + N_MBG_IO_PORT_OP_MODE_BITS +}; + + +/** + * @brief Strings descriptions for ::MBG_IO_PORT_OP_MODE_BITS + * + * Can be used to initialize a string array of ::N_MBG_IO_PORT_OP_MODE_BITS entries, + * so the number of strings must correspond to ::N_MBG_IO_PORT_OP_MODE_BITS. + * + * @see ::MBG_IO_PORT_OP_MODE_BITS + */ +#define MBG_IO_PORT_OP_MODE_STRS \ +{ \ + "Disabled", \ + "Always enabled", \ + "If sync only", \ + "Always after sync" \ +} + + + +/** + * @brief Masks for ::MBG_IO_PORT_OP_MODE_BITS + * + * Used with ::MBG_IO_PORT_INFO::supp_op_modes + * + * @see ::MBG_IO_PORT_OP_MODE_BITS + */ +enum MBG_IO_PORT_OP_MODE_MSKS +{ + MBG_IO_PORT_OP_MODE_MSK_DISABLED = (1UL << MBG_IO_PORT_OP_MODE_DISABLED), ///< See ::MBG_IO_PORT_OP_MODE_DISABLED + MBG_IO_PORT_OP_MODE_MSK_ALWAYS = (1UL << MBG_IO_PORT_OP_MODE_ALWAYS), ///< See ::MBG_IO_PORT_OP_MODE_ALWAYS + MBG_IO_PORT_OP_MODE_MSK_IF_SYNC_ONLY = (1UL << MBG_IO_PORT_OP_MODE_IF_SYNC_ONLY), ///< See ::MBG_IO_PORT_OP_MODE_IF_SYNC_ONLY + MBG_IO_PORT_OP_MODE_MSK_AFTER_SYNC = (1UL << MBG_IO_PORT_OP_MODE_AFTER_SYNC) ///< See ::MBG_IO_PORT_OP_MODE_AFTER_SYNC +}; + + +/** + * @brief Physical or logical group role bits + * + * Used with ::MBG_IO_PORT_STATUS::phys_grp_role, ::MBG_IO_PORT_STATUS::log_grp_role + * + * @see ::MBG_IO_PORT_GRP_ROLE_MSKS + */ +enum MBG_IO_PORT_GRP_ROLE_BITS +{ + MBG_IO_PORT_GRP_ROLE_NONE, ///< No group role, only possible if port is not assigned to any group + MBG_IO_PORT_GRP_ROLE_MASTER, ///< Master port in group, i.e. configurable port of LIU + MBG_IO_PORT_GRP_ROLE_SLAVE, ///< Slave port in group, i.e. non-configurable port of LIU + MBG_IO_PORT_GRP_ROLE_PASSIVE, ///< Passive port in group, i.e. passive port of network group (i.e. SFP or RJ45) + N_MBG_IO_PORT_GRP_ROLE_BITS +}; + + +/** + * @brief Strings descriptions for ::MBG_IO_PORT_GRP_ROLE_BITS + * + * Can be used to initialize a string array of ::N_MBG_IO_PORT_GRP_ROLE_BITS entries, + * so the number of strings must correspond to ::N_MBG_IO_PORT_GRP_ROLE_BITS. + * + * @see ::MBG_IO_PORT_GRP_ROLE_BITS + */ +#define MBG_IO_PORT_GRP_ROLE_STRS \ +{ \ + "None", \ + "Master", \ + "Slave", \ + "Passive" \ +} + + +/** + * @brief Masks for ::MBG_IO_PORT_GRP_ROLE_BITS + * + * Used with ::MBG_IO_PORT_INFO::supp_phys_grp_roles + * + * @see ::MBG_IO_PORT_GRP_ROLE_BITS + */ +enum MBG_IO_PORT_GRP_ROLE_MSKS +{ + MBG_IO_PORT_GRP_ROLE_MSK_NONE = (1UL << MBG_IO_PORT_GRP_ROLE_NONE), ///< See ::MBG_IO_PORT_GRP_ROLE_NONE + MBG_IO_PORT_GRP_ROLE_MSK_MASTER = (1UL << MBG_IO_PORT_GRP_ROLE_MASTER), ///< See ::MBG_IO_PORT_GRP_ROLE_MASTER + MBG_IO_PORT_GRP_ROLE_MSK_SLAVE = (1UL << MBG_IO_PORT_GRP_ROLE_SLAVE), ///< See ::MBG_IO_PORT_GRP_ROLE_SLAVE + MBG_IO_PORT_GRP_ROLE_MSK_PASSIVE = (1UL << MBG_IO_PORT_GRP_ROLE_PASSIVE) ///< See ::MBG_IO_PORT_GRP_ROLE_PASSIVE +}; + + +/** + * @brief IO Port Settings Union + * + * @see @ref group_io_ports + * @see ::MBG_IO_PORT_SETTINGS + * @see ::MBG_IO_PORT_LIMITS + * @see ::MBG_IO_PORT_SETTINGS_IDX + * @see ::MBG_IO_PORT_INFO + * @see ::MBG_IO_PORT_INFO_IDX + * @see ::MBG_IO_PORT_TYPE_INFO + * @see ::MBG_IO_PORT_TYPE_INFO_IDX + * @see ::MBG_IO_PORT_STATUS + * @see ::MBG_IO_PORT_STATUS_IDX + */ +typedef union +{ + MBG_GPIO_SETTINGS gpio_settings; + POUT_SETTINGS pout_settings; + +} MBG_IO_PORT_SETTINGS_U; + +#define _mbg_swab_io_port_settings_u( _type, _p, _recv ) \ +do \ +{ \ + switch ( (_type) ) \ + { \ + case MBG_IO_PORT_TYPE_GPIO: \ + _mbg_swab_mbg_gpio_settings( &(_p)->gpio_settings, (_recv) ); \ + break; \ + \ + case MBG_IO_PORT_TYPE_POUT: \ + if ( _recv ) \ + _mbg_swab_pout_settings_on_get( &(_p)->pout_settings ); \ + else _mbg_swab_pout_settings_on_set( &(_p)->pout_settings ); \ + break; \ + \ + default: break; \ + } \ +} while ( 0 ) + + +#define MBG_IO_PORT_SETTINGS_MIN_SIZE 32 + + +/** + * @brief IO Port Settings + * + * @see @ref group_io_ports + * @see ::MBG_IO_PORT_SETTINGS_U + * @see ::MBG_IO_PORT_LIMITS + * @see ::MBG_IO_PORT_SETTINGS_IDX + * @see ::MBG_IO_PORT_INFO + * @see ::MBG_IO_PORT_INFO_IDX + * @see ::MBG_IO_PORT_TYPE_INFO + * @see ::MBG_IO_PORT_TYPE_INFO_IDX + * @see ::MBG_IO_PORT_STATUS + * @see ::MBG_IO_PORT_STATUS_IDX + */ +typedef struct +{ + uint16_t port_type; ///< ::MBG_IO_PORT_TYPES + uint8_t direction; ///< ::MBG_IO_PORT_DIRS + uint8_t source; ///< ::MBG_IO_PORT_SRCS + uint8_t op_mode; ///< ::MBG_IO_PORT_OP_MODE_BITS + uint8_t reserved_1[3]; ///< Future use and padding, currently 0 + uint32_t reserved_2[6]; ///< Future use and padding, currently 0 + + /* + * Struct members above represent minimum amount of data to be sent. + * See ::MBG_IO_PORT_SETTINGS_MIN_SIZE + */ + + MBG_IO_PORT_SETTINGS_U data; ///< Data union for settings' type + +} MBG_IO_PORT_SETTINGS; + +#define _mbg_swab_io_port_settings( _p, _recv ) \ +do \ +{ \ + uint16_t t = (_p)->port_type; \ + if ( (_recv) ) \ + _mbg_swab16( &t ); \ + _mbg_swab16( &(_p)->port_type ); \ + _mbg_swab_io_port_settings_u( t, &(_p)->data, (_recv) ); \ +} while ( 0 ) + + + + +/** + * @brief IO Port Settings Index + * + * @see @ref group_io_ports + * @see ::MBG_IO_PORT_SETTINGS_U + * @see ::MBG_IO_PORT_LIMITS + * @see ::MBG_IO_PORT_SETTINGS + * @see ::MBG_IO_PORT_INFO + * @see ::MBG_IO_PORT_INFO_IDX + * @see ::MBG_IO_PORT_TYPE_INFO + * @see ::MBG_IO_PORT_TYPE_INFO_IDX + * @see ::MBG_IO_PORT_STATUS + * @see ::MBG_IO_PORT_STATUS_IDX + * + * Indexes from 0..::MBG_IO_PORT_LIMITS::num_ports - 1 are used + * to set ::MBG_IO_PORT_SETTINGS wrapped in ::MBG_IO_PORT_SETTINGS_IDX. + */ +typedef struct +{ + uint32_t idx; + MBG_IO_PORT_SETTINGS settings; + +} MBG_IO_PORT_SETTINGS_IDX; + +#define _mbg_swab_io_port_settings_idx( _p, _recv ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_io_port_settings( &(_p)->settings, (_recv) ); \ +} while ( 0 ) + + +#define MBG_IO_PORT_SETTINGS_IDX_MIN_SIZE (MBG_IO_PORT_SETTINGS_MIN_SIZE + sizeof( uint32_t )) + + +#define MBG_IO_PORT_SETTINGS_IDX_SIZES \ +{ \ + MBG_IO_PORT_SETTINGS_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_PPS */ \ + MBG_IO_PORT_SETTINGS_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_10MHz */ \ + MBG_IO_PORT_SETTINGS_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_2048KHz */ \ + MBG_IO_PORT_SETTINGS_IDX_MIN_SIZE + sizeof( MBG_GPIO_SETTINGS ), /* MBG_IO_PORT_TYPE_GPIO */ \ + MBG_IO_PORT_SETTINGS_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_ETHERNET */ \ + MBG_IO_PORT_SETTINGS_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_TERMINAL */ \ + MBG_IO_PORT_SETTINGS_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_MULTI */ \ + MBG_IO_PORT_SETTINGS_IDX_MIN_SIZE + sizeof( POUT_SETTINGS ) /* MBG_IO_PORT_TYPE_POUT */ \ +} + + +#define MBG_NO_PHYS_GROUP 0xFF +#define MBG_NO_LOG_GROUP 0xFF + +/** + * @brief IO Port Info + * + * @see @ref group_io_ports + * @see ::MBG_IO_PORT_SETTINGS_U + * @see ::MBG_IO_PORT_LIMITS + * @see ::MBG_IO_PORT_SETTINGS + * @see ::MBG_IO_PORT_SETTINGS_IDX + * @see ::MBG_IO_PORT_INFO_IDX + * @see ::MBG_IO_PORT_TYPE_INFO + * @see ::MBG_IO_PORT_TYPE_INFO_IDX + * @see ::MBG_IO_PORT_STATUS + * @see ::MBG_IO_PORT_STATUS_IDX + */ +typedef struct +{ + uint8_t num_types; ///< See ::MBG_IO_PORT_TYPE_INFO + uint8_t conn_type; ///< See ::MBG_IO_PORT_CONN_TYPES + uint8_t position; ///< See ::MBG_IO_PORT_POS + uint8_t reserved_1; ///< Future use and padding, currently 0 + uint16_t supp_op_modes; ///< See ::MBG_IO_PORT_OP_MODE_MSKS + uint16_t supp_phys_grp_roles; ///< Supported roles in ::MBG_IO_PORT_STATUS::phys_grp_role, see ::MBG_IO_PORT_GRP_ROLE_MSKS + uint8_t phys_grp; ///< Physical group number (i.e. SFP/RJ45 on HPS100), or ::MBG_NO_PHYS_GROUP + uint8_t reserved_2[3]; ///< Future use and padding, currently 0 + uint32_t reserved_3[8]; ///< Future use and padding, currently 0 + char rel_str[16]; ///< Indicates internal relation, i.e. "lan0", "fpga0" or "/dev/ttyS0" + MBG_IO_PORT_SETTINGS settings; ///< See ::MBG_IO_PORT_SETTINGS + +} MBG_IO_PORT_INFO; + +#define _mbg_port_has_phys_group( _p ) ( ( _p )->phys_grp != MBG_NO_PHYS_GROUP ) + +#define _mbg_swab_io_port_info( _p, _recv ) \ +do \ +{ \ + _mbg_swab16( &(_p)->supp_op_modes ); \ + _mbg_swab16( &(_p)->supp_phys_grp_roles ); \ + _mbg_swab_io_port_settings( &(_p)->settings, (_recv) ); \ +} while ( 0 ) + + + +#define MBG_IO_PORT_INFO_MIN_SIZE ( 60 + MBG_IO_PORT_SETTINGS_MIN_SIZE ) + + +/** + * @brief IO Port Info Index + * + * @see @ref group_io_ports + * @see ::MBG_IO_PORT_SETTINGS_U + * @see ::MBG_IO_PORT_LIMITS + * @see ::MBG_IO_PORT_SETTINGS + * @see ::MBG_IO_PORT_SETTINGS_IDX + * @see ::MBG_IO_PORT_INFO + * @see ::MBG_IO_PORT_TYPE_INFO_U + * @see ::MBG_IO_PORT_TYPE_INFO + * @see ::MBG_IO_PORT_TYPE_INFO_IDX + * @see ::MBG_IO_PORT_STATUS + * @see ::MBG_IO_PORT_STATUS_IDX + * + * Indexes from 0..::MBG_IO_PORT_LIMITS::num_ports - 1 are used + * to query ::MBG_IO_PORT_INFO wrapped in ::MBG_IO_PORT_INFO_IDX. + */ +typedef struct +{ + uint32_t idx; + MBG_IO_PORT_INFO info; + +} MBG_IO_PORT_INFO_IDX; + +#define _mbg_swab_io_port_info_idx( _p, _recv ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_io_port_info( &(_p)->info, (_recv) ); \ +} while ( 0 ) + + + +#define MBG_IO_PORT_INFO_IDX_MIN_SIZE (MBG_IO_PORT_INFO_MIN_SIZE + sizeof( uint32_t )) + + +#define MBG_IO_PORT_INFO_IDX_SIZES \ +{ \ + MBG_IO_PORT_INFO_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_PPS */ \ + MBG_IO_PORT_INFO_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_10MHz */ \ + MBG_IO_PORT_INFO_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_2048KHz */ \ + MBG_IO_PORT_INFO_IDX_MIN_SIZE + sizeof( MBG_GPIO_SETTINGS ), /* MBG_IO_PORT_TYPE_GPIO */ \ + MBG_IO_PORT_INFO_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_ETHERNET */ \ + MBG_IO_PORT_INFO_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_TERMINAL */ \ + MBG_IO_PORT_INFO_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_MULTI */ \ + MBG_IO_PORT_INFO_IDX_MIN_SIZE + sizeof( POUT_SETTINGS ) /* MBG_IO_PORT_TYPE_POUT */ \ +} + + +/** + * @brief IO Port Type Info Union + * + * @see @ref group_io_ports + * @see ::MBG_IO_PORT_SETTINGS_U + * @see ::MBG_IO_PORT_LIMITS + * @see ::MBG_IO_PORT_SETTINGS + * @see ::MBG_IO_PORT_SETTINGS_IDX + * @see ::MBG_IO_PORT_INFO + * @see ::MBG_IO_PORT_INFO_IDX + * @see ::MBG_IO_PORT_TYPE_INFO + * @see ::MBG_IO_PORT_TYPE_INFO_IDX + * @see ::MBG_IO_PORT_STATUS + * @see ::MBG_IO_PORT_STATUS_IDX + */ +typedef union +{ + MBG_GPIO_LIMITS gpio_limits; + POUT_INFO pout_info; + +} MBG_IO_PORT_TYPE_INFO_U; + +#define _mbg_swab_io_port_type_info_u( _type, _p, _recv ) \ +do \ +{ \ + switch ( (_type) ) \ + { \ + case MBG_IO_PORT_TYPE_GPIO: \ + _mbg_swab_mbg_gpio_limits( &(_p)->gpio_limits, (_recv) ); \ + break; \ + \ + case MBG_IO_PORT_TYPE_POUT: \ + _mbg_swab_pout_info_on_get( &(_p)->pout_info ); \ + break; \ + \ + default: break; \ + } \ +} while ( 0 ) + + + +#define MBG_IO_PORT_TYPE_INFO_MIN_SIZE 32 + + +/** + * @brief IO Port Type Info + * + * @see @ref group_io_ports + * @see ::MBG_IO_PORT_SETTINGS_U + * @see ::MBG_IO_PORT_LIMITS + * @see ::MBG_IO_PORT_SETTINGS + * @see ::MBG_IO_PORT_SETTINGS_IDX + * @see ::MBG_IO_PORT_INFO_IDX + * @see ::MBG_IO_PORT_TYPE_INFO_U + * @see ::MBG_IO_PORT_TYPE_INFO_IDX + * @see ::MBG_IO_PORT_STATUS + * @see ::MBG_IO_PORT_STATUS_IDX + */ +typedef struct +{ + uint16_t port_type; ///< See ::MBG_IO_PORT_TYPES + uint16_t reserved_1; ///< Future use and padding, currently 0 + uint8_t supp_dirs; ///< See ::MBG_IO_PORT_DIR_MSKS + uint8_t reserved_2[3]; ///< Future use and padding, currently 0 + uint32_t supp_srcs; ///< See ::MBG_IO_PORT_SRC_MSKS + uint32_t reserved_3[5]; ///< Future use and padding, currently 0 + + /* + * Struct members above represent minimum amount of data to be sent. + * See ::MBG_IO_PORT_TYPE_INFO_MIN_SIZE + */ + + MBG_IO_PORT_TYPE_INFO_U data; ///< Port type specific data + +} MBG_IO_PORT_TYPE_INFO; + +#define _mbg_swab_io_port_type_info( _p, _recv ) \ +do \ +{ \ + uint16_t t = (_p)->port_type; \ + if ( (_recv) ) \ + _mbg_swab16( &t ); \ + _mbg_swab16( &(_p)->port_type ); \ + _mbg_swab_io_port_type_info_u( t, &(_p)->data, (_recv) ); \ + _mbg_swab32( &(_p)->supp_srcs ); \ +} while ( 0 ) + + +#define MBG_IO_PORT_TYPE_INFO_IDX_MIN_SIZE (MBG_IO_PORT_TYPE_INFO_MIN_SIZE + 2 * sizeof( uint32_t )) + + +#define MBG_IO_PORT_TYPE_INFO_IDX_SIZES \ +{ \ + MBG_IO_PORT_TYPE_INFO_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_PPS */ \ + MBG_IO_PORT_TYPE_INFO_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_10MHz */ \ + MBG_IO_PORT_TYPE_INFO_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_2048KHz */ \ + MBG_IO_PORT_TYPE_INFO_IDX_MIN_SIZE + sizeof( MBG_GPIO_LIMITS ), /* MBG_IO_PORT_TYPE_GPIO */ \ + MBG_IO_PORT_TYPE_INFO_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_ETHERNET */ \ + MBG_IO_PORT_TYPE_INFO_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_TERMINAL */ \ + MBG_IO_PORT_TYPE_INFO_IDX_MIN_SIZE, /* MBG_IO_PORT_TYPE_MULTI */ \ + MBG_IO_PORT_TYPE_INFO_IDX_MIN_SIZE + sizeof( POUT_INFO ) /* MBG_IO_PORT_TYPE_POUT */ \ +} + + +/** + * @brief IO Port Type Info Index + * + * @see @ref group_io_ports + * @see ::MBG_IO_PORT_SETTINGS_U + * @see ::MBG_IO_PORT_LIMITS + * @see ::MBG_IO_PORT_SETTINGS + * @see ::MBG_IO_PORT_SETTINGS_IDX + * @see ::MBG_IO_PORT_TYPE_INFO + * @see ::MBG_IO_PORT_TYPE_INFO_U + * @see ::MBG_IO_PORT_STATUS + * @see ::MBG_IO_PORT_STATUS_IDX + * + * Indexes from 0..::MBG_IO_PORT_INFO::num_types - 1 are used + * to query ::MBG_IO_PORT_TYPE_INFO wrapped in ::MBG_IO_PORT_TYPE_INFO_IDX. + * + */ +typedef struct +{ + uint32_t port_idx; + uint32_t port_type_idx; + MBG_IO_PORT_TYPE_INFO info; + +} MBG_IO_PORT_TYPE_INFO_IDX; + +#define _mbg_swab_io_port_type_info_idx( _p, _recv ) \ +do \ +{ \ + _mbg_swab32( &(_p)->port_idx ); \ + _mbg_swab32( &(_p)->port_type_idx ); \ + _mbg_swab_io_port_type_info( &(_p)->info, (_recv) ); \ +} while ( 0 ) + + + +#define MAX_IO_PORT_STATUS_BITS 64 + + +/** + * @brief Port Type Status Bits + * + */ +enum MBG_IO_PORT_STATUS_BITS +{ + MBG_IO_PORT_STATUS_BIT_DISABLED, ///< See ::MBG_IO_PORT_OP_MODE_DISABLED. Other bits should be 0 in this case + MBG_IO_PORT_STATUS_BIT_CARRIER_DETECTED, ///< Port has physical carrier connection (e.g. BNC cable in BPE's case) + MBG_IO_PORT_STATUS_BIT_INPUT_SIGNAL_NEVER_AVAIL, ///< Input signal has NEVER been avail + MBG_IO_PORT_STATUS_BIT_INPUT_SIGNAL_AVAIL, ///< Input signal is avail right now + MBG_IO_PORT_STATUS_BIT_INPUT_SIGNAL_LOST, ///< Input signal is currently not avail, but has been avail before + MBG_IO_PORT_STATUS_BIT_SHORT_CIRCUIT, ///< Short circuit + N_MBG_IO_PORT_STATUS_BITS +}; + + +/** + * @brief Strings descriptions for ::MBG_IO_PORT_STATUS_BITS + * + * Can be used to initialize a string array of ::N_MBG_IO_PORT_STATUS_BITS entries, + * so the number of strings must correspond to ::N_MBG_IO_PORT_STATUS_BITS. + * + * @see ::MBG_IO_PORT_STATUS_BITS + */ +#define MBG_IO_PORT_STATUS_STRS \ +{ \ + "Disabled", \ + "Carrier detected", \ + "Input signal has never been avail", \ + "Input signal is avail", \ + "Input signal is currently lost", \ + "Short circuit" \ +} + + +/** + * @brief Array size required to store all status bits + * + * The number of bytes required to store up to ::MAX_IO_PORT_STATUS_BITS + * feature bits in a byte array. + */ +#define MAX_IO_PORT_STATUS_BYTES ( MAX_IO_PORT_STATUS_BITS / 8 ) + + +/** + * @brief A structure used to store port status bits + * + * Up to ::MAX_IO_PORT_STATUS_BITS totally can be stored, but only + * ::N_MBG_IO_PORT_STATUS_BITS are currently defined. + * + * The ::_set_io_port_status_bit macro should be used by the firmware + * to set a status bit in the buffer, and the ::check_feat_supp_byte_array + * to check if a bit is set + * + * @see ::_set_io_port_status_bit + * @see ::check_feat_supp_byte_array + */ +typedef struct +{ + uint8_t b[MAX_IO_PORT_STATUS_BYTES]; + +} MBG_IO_PORT_STATUS_BUFFER; + +#define _mbg_swab_io_port_status_buffer( _p ) \ + _nop_macro_fnc() + + + +/** + * @brief Set an port status bit in a ::MBG_IO_PORT_STATUS_BUFFER + * + * Should be used by the firmware only to set one of the ::N_MBG_IO_PORT_STATUS_BITS + * in an ::MBG_IO_PORT_STATUS_BUFFER after power-up. + * + * @param[in] _status_bit One of the ::MBG_IO_PORT_STATUS_BITS + * @param[in] _status_buffp Pointer to an ::MBG_IO_PORT_STATUS_BUFFER + */ +#define _set_io_port_status_bit( _status_bit, _status_buffp ) \ + _set_array_bit( _status_bit, (_status_buffp)->b, MAX_IO_PORT_STATUS_BYTES ) + + +/** + * @brief IO Port Type Status + * + * @see @ref group_io_ports + * @see ::MBG_IO_PORT_SETTINGS_U + * @see ::MBG_IO_PORT_LIMITS + * @see ::MBG_IO_PORT_SETTINGS + * @see ::MBG_IO_PORT_SETTINGS_IDX + * @see ::MBG_IO_PORT_TYPE_INFO + * @see ::MBG_IO_PORT_TYPE_INFO_U + * @see ::MBG_IO_PORT_TYPE_INFO_IDX + * @see ::MBG_IO_PORT_STATUS_IDX + * + */ +typedef struct +{ + MBG_IO_PORT_STATUS_BUFFER supp_stati; ///< Supported ::MBG_IO_PORT_STATUS_BITS in ::MBG_IO_PORT_STATUS_BUFFER + MBG_IO_PORT_STATUS_BUFFER status; ///< See ::MBG_IO_PORT_STATUS_BUFFER + + uint8_t cfg_counter; ///< Updated (increased) when config changes + uint8_t phys_grp_role; ///< Physical group role state, see ::MBG_IO_PORT_GRP_ROLE_BITS + uint8_t log_grp; ///< Logical group number (i.e. bond0), or ::MBG_NO_LOG_GROUP + uint8_t log_grp_role; ///< Logical group role (i.e. bond master, bond slave), see ::MBG_IO_PORT_GRP_ROLE_BITS + + uint32_t reserved_2[4]; ///< Future use, currently 0 + +} MBG_IO_PORT_STATUS; + +#define _mbg_port_has_log_group( _p ) ( ( _p )->log_grp != MBG_NO_LOG_GROUP ) + +#define _mbg_swab_io_port_status( _p ) \ +do \ +{ \ + _mbg_swab_io_port_status_buffer( &(_p)->supp_stati ); \ + _mbg_swab_io_port_status_buffer( &(_p)->status ); \ +} while ( 0 ) + + + +/** + * @brief IO Port Type Status + * + * @see @ref group_io_ports + * @see ::MBG_IO_PORT_SETTINGS_U + * @see ::MBG_IO_PORT_LIMITS + * @see ::MBG_IO_PORT_SETTINGS + * @see ::MBG_IO_PORT_SETTINGS_IDX + * @see ::MBG_IO_PORT_TYPE_INFO + * @see ::MBG_IO_PORT_TYPE_INFO_U + * @see ::MBG_IO_PORT_TYPE_INFO_IDX + * @see ::MBG_IO_PORT_STATUS + * + * Indexes from 0..::MBG_IO_PORT_INFO::num_types - 1 are used + * to query ::MBG_IO_PORT_TYPE_INFO wrapped in ::MBG_IO_PORT_TYPE_INFO_IDX. + * + */ +typedef struct +{ + uint32_t idx; + MBG_IO_PORT_STATUS status; + +} MBG_IO_PORT_STATUS_IDX; + +#define _mbg_swab_io_port_status_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_io_port_status( &(_p)->status ); \ +} while ( 0 ) + + +/** @} defgroup group_io_ports */ + + + +/** + * @defgroup group_monitoring Monitoring / notification + * + * @note This structure and its definitions are only supported by a device + * if ::MBG_XFEATURE_MONITORING is set in the extended device features. + * + * TODO: Add proper Doxygen documentation + * + * @{ */ + + +#define MBG_MONITORING_STR_SIZE 32 + +enum MBG_MONITORING_TYPES +{ + MBG_MONITORING_TYPE_SNMP, + MBG_MONITORING_TYPE_EMAIL, + MBG_MONITORING_TYPE_SYSLOG, + N_MBG_MONITORING_TYPES +}; + +#define MBG_MONITORING_TYPE_STRS \ +{ \ + "SNMP", \ + "Email", \ + "Syslog" \ +} + +enum MBG_MONITORING_TYPE_MSKS +{ + MBG_MONITORING_TYPE_MSK_SNMP = (1UL << MBG_MONITORING_TYPE_SNMP), + MBG_MONITORING_TYPE_MSK_EMAIL = (1UL << MBG_MONITORING_TYPE_EMAIL), + MBG_MONITORING_TYPE_MSK_SYSLOG = (1UL << MBG_MONITORING_TYPE_SYSLOG) +}; + + + +typedef struct +{ + uint16_t supp_types; ///< See ::MBG_MONITORING_TYPE_MSKS + uint16_t supp_num_events; ///< Supported number of events. See ::MBG_EVENT_TYPES + uint32_t reserved_2[3]; + +} MBG_MONITORING_LIMITS; + +#define _mbg_swab_monitoring_limits( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->supp_types ); \ + _mbg_swab16( &(_p)->supp_num_events ); \ +} while ( 0 ) + + + +/* If ::MBG_MONITORING_TYPE_MSK_SNMP is set in ::MBG_MONITORING_LIMITS::supp_types */ + +enum MBG_SNMP_VERSIONS +{ + MBG_SNMP_VERSION_V1, + MBG_SNMP_VERSION_V2c, + MBG_SNMP_VERSION_V3, + N_MBG_SNMP_VERSIONS +}; + +#define MBG_SNMP_VERSION_STRS \ +{ \ + "Version 1", \ + "Version 2c", \ + "Version 3" \ +} + +enum MBG_SNMP_VERSION_MSKS +{ + MBG_SNMP_VERSION_MSK_V1 = (1UL << MBG_SNMP_VERSION_V1), + MBG_SNMP_VERSION_MSK_V2c = (1UL << MBG_SNMP_VERSION_V2c), + MBG_SNMP_VERSION_MSK_V3 = (1UL << MBG_SNMP_VERSION_V3) +}; + + + +typedef struct +{ + uint8_t num_v12_settings; ///< Number of configured v1/v2 settings, see ::MBG_SNMP_V12_INFO_IDX + uint8_t num_v3_settings; ///< Number of configured v1/v2 trap receivers, see ::MBG_SNMP_V12_TRAP_INFO_IDX + uint8_t num_v12_trap_receivers; ///< Number of configured v3 settings, see ::MBG_SNMP_V3_INFO_IDX + uint8_t num_v3_trap_receivers; ///< Number of configured v3 trap receivers, see ::MBG_SNMP_V3_TRAP_INFO_IDX + uint16_t listening_port; ///< snmpd listening port, 161 by default + uint16_t reserved_1; + uint32_t reserved_2[3]; + char location[MBG_MONITORING_STR_SIZE]; + char contact[MBG_MONITORING_STR_SIZE]; + char name[MBG_MONITORING_STR_SIZE]; + char reserved_3[MBG_MONITORING_STR_SIZE]; ///< Future use + char reserved_4[MBG_MONITORING_STR_SIZE]; ///< Future use + +} MBG_SNMP_GLB_SETTINGS; + +#define _mbg_swab_snmp_glb_settings( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->listening_port ); \ +} while ( 0 ) + + + +typedef struct +{ + MBG_SNMP_GLB_SETTINGS settings; + uint8_t supp_versions; ///< See ::MBG_SNMP_VERSION_MSKS + uint8_t max_v12_settings; ///< Only valid if ::MBG_SNMP_GLB_INFO::supp_versions contains ::MBG_SNMP_VERSION_MSK_V1 or ::MBG_SNMP_VERSION_MSK_V2c + uint8_t max_v3_settings; ///< Only valid if ::MBG_SNMP_GLB_INFO::supp_versions contains ::MBG_SNMP_VERSION_MSK_V3 + uint8_t max_v12_trap_receivers; ///< Only valid if ::MBG_SNMP_GLB_INFO::supp_versions contains ::MBG_SNMP_VERSION_MSK_V1 or ::MBG_SNMP_VERSION_MSK_V2c + uint8_t max_v3_trap_receivers; ///< Only valid if ::MBG_SNMP_GLB_INFO::supp_versions contains ::MBG_SNMP_VERSION_MSK_V3 + uint8_t reserved_1[3]; + uint32_t reserved_2[2]; + +} MBG_SNMP_GLB_INFO; + +#define _mbg_swab_snmp_glb_info( _p ) \ +do \ +{ \ + _mbg_swab_snmp_glb_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +enum MBG_SNMP_ACCESS_TYPES +{ + MBG_SNMP_ACCESS_TYPE_RO, + MBG_SNMP_ACCESS_TYPE_RW, + N_MBG_SNMP_ACCESS_TYPES +}; + + +#define MBG_SNMP_ACCESS_TYPE_STRS \ +{ \ + "Read-only", \ + "Read-write" \ +} + + + +typedef struct +{ + uint8_t version; ///< See ::MBG_SNMP_VERSIONS + uint8_t access_type; ///< See ::MBG_SNMP_ACCESS_TYPES, ignore in trap settings + uint8_t reserved_1[2]; + uint32_t reserved_2[3]; + char community[MBG_MONITORING_STR_SIZE]; + +} MBG_SNMP_V12_SETTINGS; + +#define _mbg_swab_snmp_v12_settings( _p ) \ +do \ +{ \ +} while ( 0 ) + + + +typedef struct +{ + uint32_t idx; + MBG_SNMP_V12_SETTINGS settings; + +} MBG_SNMP_V12_SETTINGS_IDX; + +#define _mbg_swab_snmp_v12_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_snmp_v12_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +typedef struct +{ + MBG_SNMP_V12_SETTINGS settings; + uint32_t reserved_1[4]; + +} MBG_SNMP_V12_INFO; + +#define _mbg_swab_snmp_v12_info( _p ) \ +do \ +{ \ + _mbg_swab_snmp_v12_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +typedef struct +{ + uint32_t idx; + MBG_SNMP_V12_INFO info; + +} MBG_SNMP_V12_INFO_IDX; + +#define _mbg_swab_snmp_v12_info_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_snmp_v12_info( &(_p)->info ); \ +} while ( 0 ) + + + +typedef struct +{ + uint8_t timeout; ///< In seconds + uint8_t retries; + uint16_t reserved_1; + uint32_t reserved_2[3]; + char reserved_3[MBG_MONITORING_STR_SIZE]; ///< Future use + char reserved_4[MBG_MONITORING_STR_SIZE]; ///< Future use + MBG_SNMP_V12_SETTINGS v12_settings; + MBG_HOSTNAME receiver_addr; + uint16_t dest_port; ///< receiver destination port, 162 by default + uint16_t reserved_5; + +} MBG_SNMP_V12_TRAP_SETTINGS; + +#define _mbg_swab_snmp_v12_trap_settings( _p ) \ +do \ +{ \ + _mbg_swab_snmp_v12_settings( &(_p)->v12_settings ); \ + _mbg_swab16( &(_p)->dest_port ); \ +} while ( 0 ) + + + +typedef struct +{ + uint32_t idx; + MBG_SNMP_V12_TRAP_SETTINGS settings; + +} MBG_SNMP_V12_TRAP_SETTINGS_IDX; + +#define _mbg_swab_snmp_v12_trap_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_snmp_v12_trap_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +typedef struct +{ + MBG_SNMP_V12_TRAP_SETTINGS settings; + uint32_t reserved_1[4]; + +} MBG_SNMP_V12_TRAP_INFO; + +#define _mbg_swab_snmp_v12_trap_info( _p ) \ +do \ +{ \ + _mbg_swab_snmp_v12_trap_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +typedef struct +{ + uint32_t idx; + MBG_SNMP_V12_TRAP_INFO info; + +} MBG_SNMP_V12_TRAP_INFO_IDX; + +#define _mbg_swab_snmp_v12_trap_info_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_snmp_v12_trap_info( &(_p)->info ); \ +} while ( 0 ) + + + +enum MBG_SNMP_V3_SEC_LEVELS +{ + MBG_SNMP_V3_SEC_LEVEL_NO_AUTH_NO_PRIV, + MBG_SNMP_V3_SEC_LEVEL_AUTH_NO_PRIV, + MBG_SNMP_V3_SEC_LEVEL_AUTH_PRIV, + N_MBG_SNMP_V3_SEC_LEVELS +}; + +#define MBG_SNMP_V3_SEC_LEVEL_STRS \ +{ \ + "No auth no priv", \ + "Auth no priv", \ + "Auth priv" \ +} + + +enum MBG_SNMP_V3_AUTH_PROTOCOLS +{ + MBG_SNMP_V3_AUTH_PROTOCOL_NONE, + MBG_SNMP_V3_AUTH_PROTOCOL_MD5, + MBG_SNMP_V3_AUTH_PROTOCOL_SHA, + N_MBG_SNMP_V3_AUTH_PROTOCOLS +}; + +#define MBG_SNMP_V3_AUTH_PROTOCOL_STRS \ +{ \ + "None", \ + "MD5", \ + "SHA" \ +} + + +enum MBG_SNMP_V3_PRIV_PROTOCOLS +{ + MBG_SNMP_V3_PRIV_PROTOCOL_NONE, + MBG_SNMP_V3_PRIV_PROTOCOL_DES, + MBG_SNMP_V3_PRIV_PROTOCOL_AES, + N_MBG_SNMP_V3_PRIV_PROTOCOLS +}; + + +#define MBG_SNMP_V3_PRIV_PROTOCOL_STRS \ +{ \ + "None", \ + "DES", \ + "AES" \ +} + + + +typedef struct +{ + uint8_t access_type; ///< See ::MBG_SNMP_ACCESS_TYPES, ignore in trap settings + uint8_t sec_level; ///< See ::MBG_SNMP_V3_SEC_LEVELS + uint8_t auth_protocol; ///< See ::MBG_SNMP_V3_AUTH_PROTOCOLS if ::MBG_SNMP_V3_SETTINGS::sec_level + ///< is ::MBG_SNMP_V3_SEC_LEVEL_AUTH_NO_PRIV or ::MBG_SNMP_V3_SEC_LEVEL_AUTH_PRIV + uint8_t priv_protocol; ///< See ::MBG_SNMP_V3_PRIV_PROTOCOLS if ::MBG_SNMP_V3_SETTINGS::sec_level + ///< is ::MBG_SNMP_V3_SEC_LEVEL_AUTH_PRIV + uint32_t reserved_1[3]; + char user_name[MBG_MONITORING_STR_SIZE]; ///< User name used for authentication, always required. + char auth_passwd[MBG_MONITORING_STR_SIZE]; ///< Password associated with ::MBG_SNMP_V3_SETTINGS::user_name, if ::MBG_SNMP_V3_SETTINGS::auth_protocol + ///< is ::MBG_SNMP_V3_SEC_LEVEL_AUTH_NO_PRIV or ::MBG_SNMP_V3_SEC_LEVEL_AUTH_PRIV + char sec_engine_id[MBG_MONITORING_STR_SIZE]; ///< Mandatory + char context_engine_id[MBG_MONITORING_STR_SIZE]; ///< Ignore + char context_name[MBG_MONITORING_STR_SIZE]; ///< Ignore + char reserved_2[MBG_MONITORING_STR_SIZE]; ///< Future use + char reserved_3[MBG_MONITORING_STR_SIZE]; ///< Future use + char priv_passwd[MBG_MONITORING_STR_SIZE]; ///< Encryption passwd if ::MBG_SNMP_V3_SETTINGS::auth_protocol is ::MBG_SNMP_V3_SEC_LEVEL_AUTH_PRIV + uint32_t boots; ///< Number of system/deamon restarts -> Ignore + uint32_t time; ///< Timeticks since last "boots" event -> Ignore + uint32_t reserved_4[2]; + +} MBG_SNMP_V3_SETTINGS; + +#define _mbg_swab_snmp_v3_settings( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->boots ); \ + _mbg_swab32( &(_p)->time ); \ +} while ( 0 ) + + + +typedef struct +{ + uint32_t idx; + MBG_SNMP_V3_SETTINGS settings; + +} MBG_SNMP_V3_SETTINGS_IDX; + +#define _mbg_swab_snmp_v3_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_snmp_v3_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +typedef struct +{ + MBG_SNMP_V3_SETTINGS settings; + uint32_t reserved_1[4]; + +} MBG_SNMP_V3_INFO; + +#define _mbg_swab_snmp_v3_info( _p ) \ +do \ +{ \ + _mbg_swab_snmp_v3_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +typedef struct +{ + uint32_t idx; + MBG_SNMP_V3_INFO info; + +} MBG_SNMP_V3_INFO_IDX; + +#define _mbg_swab_snmp_v3_info_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_snmp_v3_info( &(_p)->info ); \ +} while ( 0 ) + + + +typedef struct +{ + uint8_t timeout; ///< In seconds + uint8_t retries; + uint8_t reserved_1[2]; + uint32_t reserved_2[3]; + MBG_SNMP_V3_SETTINGS v3_settings; + MBG_HOSTNAME receiver_addr; + uint16_t dest_port; ///< receiver destination port, 162 by default + uint16_t reserved_3; + +} MBG_SNMP_V3_TRAP_SETTINGS; + +#define _mbg_swab_snmp_v3_trap_settings( _p ) \ +do \ +{ \ + _mbg_swab_snmp_v3_settings( &(_p)->v3_settings ); \ + _mbg_swab16( &(_p)->dest_port ); \ +} while ( 0 ) + + + +typedef struct +{ + uint32_t idx; + MBG_SNMP_V3_TRAP_SETTINGS settings; + +} MBG_SNMP_V3_TRAP_SETTINGS_IDX; + +#define _mbg_swab_snmp_v3_trap_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_snmp_v3_trap_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +typedef struct +{ + MBG_SNMP_V3_TRAP_SETTINGS settings; + uint32_t reserved_1[4]; + +} MBG_SNMP_V3_TRAP_INFO; + +#define _mbg_swab_snmp_v3_trap_info( _p ) \ +do \ +{ \ + _mbg_swab_snmp_v3_trap_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +typedef struct +{ + uint32_t idx; + MBG_SNMP_V3_TRAP_INFO info; + +} MBG_SNMP_V3_TRAP_INFO_IDX; + +#define _mbg_swab_snmp_v3_trap_info_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_snmp_v3_trap_info( &(_p)->info ); \ +} while ( 0 ) + + + +enum MBG_EVENT_TYPES +{ + MBG_EVENT_TYPE_NTP_STATE, + MBG_EVENT_TYPE_HEARTBEAT, + N_MBG_EVENT_TYPES +}; + +#define MBG_EVENT_TYPE_STRS \ +{ \ + "NTP state", \ + "Heartbeat" \ +} + +enum MBG_EVENT_SEVERITIES +{ + MBG_EVENT_SEVERITY_INFO, + MBG_EVENT_SEVERITY_WARNING, + MBG_EVENT_SEVERITY_ERROR, + MBG_EVENT_SEVERITY_CRITICAL, + N_MBG_EVENT_SEVERITIES +}; + +#define MBG_EVENT_SEVERITY_STRS \ +{ \ + "Info", \ + "Warning", \ + "Error", \ + "Critical" \ +} + +enum MBG_EVENT_SEVERITY_MSKS +{ + MBG_EVENT_SEVERITY_MSK_INFO = (1UL << MBG_EVENT_SEVERITY_INFO), + MBG_EVENT_SEVERITY_MSK_WARNING = (1UL << MBG_EVENT_SEVERITY_WARNING), + MBG_EVENT_SEVERITY_MSK_ERROR = (1UL << MBG_EVENT_SEVERITY_ERROR), + MBG_EVENT_SEVERITY_MSK_CRITICAL = (1UL << MBG_EVENT_SEVERITY_CRITICAL) +}; + +typedef struct +{ + uint8_t severity; ///< See ::MBG_EVENT_SEVERITIES + uint8_t reserved_1; + uint16_t triggers; ///< See ::MBG_MONITORING_TYPE_MSKS if set in ::MBG_MONITORING_LIMITS::supp_types + uint16_t interval; ///< [s], only if ::MBG_EVENT_SUPP_FLAG_INTERVAL is set in ::MBG_EVENT_INFO::supp_flags, else 0. + uint16_t reserved_2; + uint32_t reserved_3[6]; + +} MBG_EVENT_SETTINGS; + +#define _mbg_swab_event_settings( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->triggers ); \ + _mbg_swab16( &(_p)->interval ); \ +} while ( 0 ) + + + +/** + * @brief Structure for monitoring event settings + * + * @see ::MBG_EVENT_INFO_IDX + */ +typedef struct +{ + uint32_t idx; + MBG_EVENT_SETTINGS settings; + +} MBG_EVENT_SETTINGS_IDX; + +#define _mbg_swab_event_settings_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_event_settings( &(_p)->settings ); \ +} while ( 0 ) + + + +enum MBG_EVENT_SUPP_FLAGS +{ + MBG_EVENT_SUPP_FLAG_INTERVAL, ///< Event can be sent cyclically + N_MBG_EVENT_SUPP_FLAGS +}; + + +enum MBG_EVENT_SUPP_FLAG_MSKS +{ + MBG_EVENT_SUPP_FLAG_MSK_INTERVAL = ( 1UL << MBG_EVENT_SUPP_FLAG_INTERVAL ) +}; + + + +enum MBG_EVENT_FLAGS +{ + MBG_EVENT_FLAG_NOT_AVAIL, ///< Event is currently not available, i.e. card in slot has been removed + N_MBG_EVENT_FLAGS +}; + + +enum MBG_EVENT_FLAG_MSKS +{ + MBG_EVENT_FLAG_MSK_NOT_AVAIL = ( 1UL << MBG_EVENT_FLAG_NOT_AVAIL ) +}; + +#define MBG_OWN_EVENT_CHASSIS 0xFF +#define MBG_OWN_EVENT_SLOT 0xFF +#define MBG_INV_EVENT_PORT 0xFF + + + +typedef struct +{ + MBG_EVENT_SETTINGS settings; + uint16_t type; ///< See ::MBG_EVENT_TYPES + uint8_t chassis_idx; ///< Index of the associated IMS chassis + uint8_t slot_idx; ///< Index of the associated IMS slot + uint8_t port_idx; ///< Index of the associated IO port + uint8_t reserved_1; ///< Reserved, currently 0 + uint16_t reserved_2; ///< Reserved, currently 0 + + uint16_t supp_severities; ///< See ::MBG_EVENT_SEVERITY_MSKS + uint16_t supp_flags; ///< See ::MBG_EVENT_SUPP_FLAG_MSKS + uint16_t supp_triggers; ///< See ::MBG_MONITORING_TYPE_MSKS + uint16_t flags; ///< See ::MBG_EVENT_FLAG_MSKS + + uint32_t reserved_3[4]; + +} MBG_EVENT_INFO; + +#define _mbg_swab_event_info( _p ) \ +do \ +{ \ + _mbg_swab_event_settings( &(_p)->settings ); \ + _mbg_swab16( &(_p)->type ); \ + _mbg_swab16( &(_p)->supp_severities ); \ + _mbg_swab16( &(_p)->supp_flags ); \ + _mbg_swab16( &(_p)->supp_triggers ); \ + _mbg_swab16( &(_p)->flags ); \ +} while ( 0 ) + + + +/** + * @brief Structure for monitoring event info + * + * @note idx represents the event type, see ::MBG_EVENT_TYPES + * Before requesting the struct, its availability should be checked + * in ::MBG_MONITORING_LIMITS::supp_num_events. + * + * @see ::MBG_EVENT_TYPES + * @see ::MBG_MONITORING_LIMITS + */ +typedef struct +{ + uint32_t idx; + MBG_EVENT_INFO info; + +} MBG_EVENT_INFO_IDX; + +#define _mbg_swab_event_info_idx( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->idx ); \ + _mbg_swab_event_info( &(_p)->info ); \ +} while ( 0 ) + + + +typedef struct +{ + uint8_t snmp_cfg_counter; ///< Updated (increased) when SNMP config changes + uint8_t email_cfg_counter; ///< Updated (increased) when Email config changes + uint8_t syslog_cfg_counter; ///< Updated (increased) when Syslog config changes + uint8_t event_cfg_counter; ///< Updated (increased) when event config changes + uint32_t reserved_2[3]; + +} MBG_MONITORING_STATUS; + +#define _mbg_swab_monitoring_status( _p ) \ +do \ +{ \ +} while ( 0 ) + + + +enum MBG_EVENT_STATUS_FLAGS +{ + MBG_EVENT_STATUS_FLAG_ACTIVE, ///< Event is currently active + N_MBG_EVENT_STATUS_FLAGS +}; + + +enum MBG_EVENT_STATUS_FLAG_MSKS +{ + MBG_EVENT_STATUS_FLAG_MSK_ACTIVE = (1UL << MBG_EVENT_STATUS_FLAG_ACTIVE) +}; + + + +typedef struct +{ + uint16_t flags; ///< See ::MBG_EVENT_STATUS_FLAGS + uint16_t reserved_1; + uint32_t last_triggered; ///< Unix timestamp when this event has been triggered + uint32_t reserved_2[6]; + +} MBG_EVENT_STATUS; + +#define _mbg_swab_event_status( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->flags ); \ + _mbg_swab32( &(_p)->last_triggered ); \ +} while ( 0 ) + + + +typedef struct +{ + uint16_t idx; + MBG_EVENT_STATUS status; + +} MBG_EVENT_STATUS_IDX; + +#define _mbg_swab_event_status_idx( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->idx ); \ + _mbg_swab_event_status( &(_p)->status ); \ +} while ( 0 ) + +/** @} defgroup group_monitoring */ + + +/** + * @defgroup group_usb_lock USB locks + * + * @note This structure and its definitions are only supported by a device + * if ::MBG_XFEATURE_USB_LOCK is set in the extended device features. + * Feature can electrically disconnect an USB slave device from + * the USB host bus. It cannot be reset via software, it's a one way action only. + * + * TODO: Add proper Doxygen documentation + * + * @{ */ + + +enum MBG_USB_LOCK_FLAGS +{ + MBG_USB_LOCK_FLAG_ACTIVE, ///< USB connection is interrupted + N_MBG_USB_LOCK_FLAGS +}; + + +enum MBG_USB_LOCK_FLAG_MSKS +{ + MBG_USB_LOCK_FLAG_MSK_ACTIVE = (1UL << MBG_USB_LOCK_FLAG_ACTIVE) ///< See ::MBG_USB_LOCK_FLAG_ACTIVE +}; + + +typedef struct +{ + uint8_t flags; ///< ::MBG_USB_LOCK_FLAG_MSKS + uint8_t reserved_1[3]; + uint32_t reserved_2[3]; + +} MBG_USB_LOCK_SETTINGS; + +#define _mbg_swab_usb_lock_settings( _p ) do {} while ( 0 ) + + +typedef struct +{ + MBG_USB_LOCK_SETTINGS settings; + uint8_t supp_flags; ///< ::MBG_USB_LOCK_FLAG_MSKS + uint8_t reserved_1[3]; + uint32_t reserved_2[3]; + +} MBG_USB_LOCK_INFO; + +#define _mbg_swab_usb_lock_info( _p ) \ +do \ +{ \ + _mbg_swab_usb_lock_settings( _p ); \ +} while ( 0 ) + + +typedef struct +{ + uint8_t flags; ///< ::MBG_USB_LOCK_FLAG_MSKS + uint8_t reserved_1[3]; + uint32_t reserved_2[3]; + +} MBG_USB_LOCK_STATUS; + +#define _mbg_swab_usb_lock_status( _p ) do {} while ( 0 ) + + +/** @} defgroup group_usb_lock */ + + #if defined( _USING_BYTE_ALIGNMENT ) #pragma pack() // set default alignment #undef _USING_BYTE_ALIGNMENT diff --git a/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.c b/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.c index f493af9..48cefc1 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.c +++ b/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: gpsutils.c 1.4.1.3 2010/07/15 13:33:43 martin TEST $ + * $Id: gpsutils.c 1.10 2017/07/05 13:57:06 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,12 +10,22 @@ * * ----------------------------------------------------------------------- * $Log: gpsutils.c $ - * Revision 1.4.1.3 2010/07/15 13:33:43 martin + * Revision 1.10 2017/07/05 13:57:06 martin + * Use save string functions from str_util.c. + * Quieted some compiler warninges. + * Added doxygen comments. + * Revision 1.9 2013/01/30 16:10:08 martin + * Exclude some code from compiling by default, and + * thus don't require pcpslstr.h by default. + * Revision 1.8 2012/10/15 14:27:05Z martin + * Exclude sprint_fixed_freq() from build except for Borland C / Windows. + * Revision 1.7 2010/07/15 09:32:09 martin * Use DEG character definition from pcpslstr.h. - * Revision 1.4.1.2 2004/11/09 14:42:36Z martin - * Use C99 fixed-size types in swap_double(). - * Revision 1.4.1.1 2003/05/16 08:36:27 MARTIN - * Fixed sprint_dms() to work correctly under QNX. + * Revision 1.6 2004/12/28 11:21:26Z martin + * Omit trap if fixed_freq is 0. + * Use C99 fixed-size data types were required. + * Revision 1.5 2003/02/04 09:20:04Z MARTIN + * New functions sprint_alt(), sprint_fixed_freq(). * Revision 1.4 2003/01/31 13:45:19 MARTIN * sprint_pos_geo() returns N/A if position not valid. * Revision 1.3 2002/12/12 16:07:04 martin @@ -32,26 +42,71 @@ #include <gpsutils.h> #undef _GPSUTILS -#include <pcpslstr.h> +#if defined( USE_SPRINTF ) + #error USE_SPRINTF was obsoleted by USE_SNPRINTF. Please update project settings. +#endif + +#if !defined( USE_SNPRINTF ) + #define USE_SNPRINTF 0 +#endif + +#if !defined( _USE_GPSUTILS_FULL ) + #if defined( MBG_TGT_WIN32 ) && defined( __BORLANDC__ ) + #define _USE_GPSUTILS_FULL 1 + #else + #define _USE_GPSUTILS_FULL 0 + #endif +#endif + +#if USE_SNPRINTF + #include <str_util.h> + + #define DEG "deg" +#endif + +#if _USE_GPSUTILS_FULL + #include <str_util.h> + #include <math.h> +#endif #include <stdio.h> #include <string.h> +#if USE_SNPRINTF || _USE_GPSUTILS_FULL + +static const char str_na[] = "N/A"; + +#endif -#define _eos( _s ) ( &(_s)[strlen( _s )] ) /*HDR*/ -void swap_double( double *d ) +/** + * @brief Swap the bytes of a single variable of type "double" + * + * The memory layout of a "double" on Meinberg bus level devices + * and computers usually differs. This function can be used to + * fix this and is usually called from inside API functions, + * if required. + * + * @param[in,out] p Pointer to a "double" to be swapped + * + * @see ::swap_eph_doubles + * @see ::swap_alm_doubles + * @see ::swap_utc_doubles + * @see ::swap_iono_doubles + * @see ::swap_pos_doubles + */ +void swap_double( double *p ) { uint16_t *wp1; uint16_t *wp2; uint16_t w; int i; - wp1 = (uint16_t *) d; - wp2 = ( (uint16_t *) d ) + 3; + wp1 = (uint16_t *) p; + wp2 = ( (uint16_t *) p ) + 3; for ( i = 0; i < 2; i++ ) { @@ -62,133 +117,370 @@ void swap_double( double *d ) wp2--; } -} /* swap_double */ +} // swap_double /*HDR*/ -void swap_eph_doubles( EPH *ephp ) +/** + * @brief Swap the "double" fields in an ::EPH structure + * + * See comments for ::swap_double + * + * @param[in,out] p Pointer to an ::EPH structure to be converted + * + * @see ::swap_double + * @see ::swap_alm_doubles + * @see ::swap_utc_doubles + * @see ::swap_iono_doubles + * @see ::swap_pos_doubles + */ +void swap_eph_doubles( EPH *p ) { - swap_double( &ephp->sqrt_A ); - swap_double( &ephp->e ); - swap_double( &ephp->M0 ); - swap_double( &ephp->omega ); - swap_double( &ephp->i0 ); - swap_double( &ephp->OMEGA0 ); - swap_double( &ephp->OMEGADOT ); - - swap_double( &ephp->deltan ); - swap_double( &ephp->idot ); - - swap_double( &ephp->crc ); - swap_double( &ephp->crs ); - swap_double( &ephp->cuc ); - swap_double( &ephp->cus ); - swap_double( &ephp->cic ); - swap_double( &ephp->cis ); - - swap_double( &ephp->af0 ); - swap_double( &ephp->af1 ); - swap_double( &ephp->af2 ); - - swap_double( &ephp->tgd ); + swap_double( &p->sqrt_A ); + swap_double( &p->e ); + swap_double( &p->M0 ); + swap_double( &p->omega ); + swap_double( &p->i0 ); + swap_double( &p->OMEGA0 ); + swap_double( &p->OMEGADOT ); + + swap_double( &p->deltan ); + swap_double( &p->idot ); + + swap_double( &p->crc ); + swap_double( &p->crs ); + swap_double( &p->cuc ); + swap_double( &p->cus ); + swap_double( &p->cic ); + swap_double( &p->cis ); + + swap_double( &p->af0 ); + swap_double( &p->af1 ); + swap_double( &p->af2 ); + + swap_double( &p->tgd ); } /* swap_eph_doubles */ /*HDR*/ -void swap_alm_doubles( ALM *almp ) +/** + * @brief Swap the "double" fields in an ::ALM structure + * + * See comments for ::swap_double + * + * @param[in,out] p Pointer to an ::ALM structure to be converted + * + * @see ::swap_double + * @see ::swap_eph_doubles + * @see ::swap_utc_doubles + * @see ::swap_iono_doubles + * @see ::swap_pos_doubles + */ +void swap_alm_doubles( ALM *p ) { - swap_double( &almp->sqrt_A ); - swap_double( &almp->e ); - swap_double( &almp->deltai ); - swap_double( &almp->OMEGA0 ); - swap_double( &almp->OMEGADOT ); - swap_double( &almp->omega ); - swap_double( &almp->M0 ); - swap_double( &almp->af0 ); - swap_double( &almp->af1 ); + swap_double( &p->sqrt_A ); + swap_double( &p->e ); + swap_double( &p->deltai ); + swap_double( &p->OMEGA0 ); + swap_double( &p->OMEGADOT ); + swap_double( &p->omega ); + swap_double( &p->M0 ); + swap_double( &p->af0 ); + swap_double( &p->af1 ); } /* swap_alm_doubles */ /*HDR*/ -void swap_utc_doubles( UTC *utcp ) +/** + * @brief Swap the "double" fields in a ::UTC structure + * + * See comments for ::swap_double + * + * @param[in,out] p Pointer to a ::UTC structure to be converted + * + * @see ::swap_double + * @see ::swap_eph_doubles + * @see ::swap_alm_doubles + * @see ::swap_iono_doubles + * @see ::swap_pos_doubles + */ +void swap_utc_doubles( UTC *p ) { - swap_double( &utcp->A0 ); - swap_double( &utcp->A1 ); + swap_double( &p->A0 ); + swap_double( &p->A1 ); } /* swap_utc_doubles */ /*HDR*/ -void swap_iono_doubles( IONO *ionop ) +/** + * @brief Swap the "double" fields in a ::IONO structure + * + * See comments for ::swap_double + * + * @param[in,out] p Pointer to a ::IONO structure to be converted + * + * @see ::swap_double + * @see ::swap_eph_doubles + * @see ::swap_alm_doubles + * @see ::swap_utc_doubles + * @see ::swap_pos_doubles + */ +void swap_iono_doubles( IONO *p ) { - swap_double( &ionop->alpha_0 ); - swap_double( &ionop->alpha_1 ); - swap_double( &ionop->alpha_2 ); - swap_double( &ionop->alpha_3 ); + swap_double( &p->alpha_0 ); + swap_double( &p->alpha_1 ); + swap_double( &p->alpha_2 ); + swap_double( &p->alpha_3 ); - swap_double( &ionop->beta_0 ); - swap_double( &ionop->beta_1 ); - swap_double( &ionop->beta_2 ); - swap_double( &ionop->beta_3 ); + swap_double( &p->beta_0 ); + swap_double( &p->beta_1 ); + swap_double( &p->beta_2 ); + swap_double( &p->beta_3 ); } /* swap_iono_doubles */ /*HDR*/ -void swap_pos_doubles( POS *posp ) +/** + * @brief Swap the "double" fields in a ::POS structure + * + * See comments for ::swap_double + * + * @param[in,out] p Pointer to a ::POS structure to be converted + * + * @see ::swap_double + * @see ::swap_eph_doubles + * @see ::swap_alm_doubles + * @see ::swap_utc_doubles + * @see ::swap_iono_doubles + */ +void swap_pos_doubles( POS *p ) { int i; for ( i = 0; i < N_XYZ; i++ ) - swap_double( &posp->xyz[i] ); + swap_double( &p->xyz[i] ); for ( i = 0; i < N_LLA; i++ ) - swap_double( &posp->lla[i] ); + swap_double( &p->lla[i] ); - swap_double( &posp->longitude.sec ); - swap_double( &posp->latitude.sec ); + swap_double( &p->longitude.sec ); + swap_double( &p->latitude.sec ); } /* swap_pos_doubles */ +#if USE_SNPRINTF + /*HDR*/ -void sprint_dms( char *s, DMS *pdms, int prec ) +/** + * @brief Print the ::DMS part of a geo position into a string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p Pointer to a ::DMS structure to be printed + * @param[in] prec Precision, i.e. number of fractions of the seconds + * + * @return Length of the string in the buffer + * + * @see snprint_dms + * @see snprint_alt + * @see snprint_pos_geo + * @see snprint_fixed_freq + */ +size_t snprint_dms( char *s, size_t max_len, const DMS *p, int prec ) { - sprintf( s, "%c %i" DEG "%02i'%02.*f\"", - pdms->prefix, - pdms->deg, - pdms->min, - prec, - pdms->sec - ); + size_t n = snprintf_safe( s, max_len, "%c %i" DEG "%02i'%02.*f\"", + p->prefix, p->deg, p->min, + prec, p->sec ); + + return n; -} /* sprint_dms */ +} // snprint_dms /*HDR*/ -void sprint_pos_geo( char *s, POS *ppos, const char *sep, int prec ) +/** + * @brief Print the altitude part of a geo position into a string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] alt The altitude value to be printed, in [m] + * + * @return Length of the string in the buffer + * + * @see snprint_dms + * @see snprint_pos_geo + * @see snprint_fixed_freq + */ +size_t snprint_alt( char *s, size_t max_len, double alt ) +{ + size_t n = snprintf_safe( s, max_len, "%.0fm", alt ); + + return n; + +} // snprint_alt + + + +/*HDR*/ +/** + * @brief Print a geo position in ::POS format into a string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p Pointer to a ::POS structure to be printed + * @param[in] sep Separator character for the ::DMS part + * @param[in] prec Precision, i.e. number of fractions of the seconds of the ::DMS part + * + * @return Length of the string in the buffer + * + * @see snprint_dms + * @see snprint_alt + * @see snprint_fixed_freq + */ +size_t snprint_pos_geo( char *s, size_t max_len, const POS *p, char sep, int prec ) { - if ( ppos->lla[LON] && ppos->lla[LAT] && ppos->lla[ALT] ) + size_t n = 0; + + if ( p->lla[LON] && p->lla[LAT] && p->lla[ALT] ) + { + n += snprint_dms( &s[n], max_len - n, &p->latitude, prec ); + n += snprintf_safe( &s[n], max_len - n, "%c", sep ); + n += snprint_dms( &s[n], max_len - n, &p->longitude, prec ); + n += snprintf_safe( &s[n], max_len - n, "%c", sep ); + n += snprint_alt( &s[n], max_len - n, p->lla[ALT] ); + } + else + n = sn_cpy_str_safe( s, max_len, str_na ); + + return n; + +} // snprint_pos_geo + +#endif // USE_SNPRINTF + + + +#if _USE_GPSUTILS_FULL + +/*HDR*/ +/** + * @brief Print a formatted ::FIXED_FREQ_INFO into a string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p_ff Pointer to a ::FIXED_FREQ_INFO structure to be printed + * + * @return Length of the string in the buffer + * + * @see snprint_dms + * @see snprint_alt + * @see snprint_pos_geo + */ +size_t snprint_fixed_freq( char *s, size_t max_len, FIXED_FREQ_INFO *p_ff ) +{ + double freq; + int range; + ushort unit; + ushort format; + size_t n = 0; + + // Before re-calculating frequency, range is the base 10 exponent + // to the frequency value which is represented in kHz. + // After calculating range from real frequency, range is represented + // as follows: + // range display format divisor format index calculation + // -3 100mHz 1.000 [/1e-3] -3 % 3 = -3 + 3 = 0 % 3 = 0 + // -2 100mHz 10.00 [/1e-3] -2 % 3 = -2 + 3 = 1 % 3 = 1 + // -1 100mHz 100.0 [/1e-3] -1 % 3 = -1 + 3 = 2 % 3 = 2 + // 0 1Hz 1.000 [/1e0] 0 % 3 = 0 + 3 = 3 % 3 = 0 + // 1 10Hz 10.00 [/1e0] 1 % 3 = 1 + 3 = 1 % 3 = 1 + // 2 100Hz 100.0 [/1e0] 2 % 3 = 2 + 3 = 2 % 3 = 2 + // 3 1kHz 1.000 [/1e3] 3 % 3 = 0 + 3 = 3 % 3 = 0 + // 4 10kHz 10.00 [/1e3] 4 % 3 = 1 + 3 = 4 % 3 = 1 + // 5 100kHz 100.0 [/1e3] 5 % 3 = 2 + 3 = 5 % 3 = 2 + // 6 1MHz 1.000 [/1e6] 6 % 3 = 0 + 3 = 3 % 3 = 0 + // 7 10MHz 10.00 [/1e6] 7 % 3 = 1 + 3 = 4 % 3 = 1 + // 8 100MHz 100.0 [/1e6] 8 % 3 = 2 + 3 = 5 % 3 = 2 + + // format string for fp output + static const char *fmt_str[] = + { + "%4.3lf%s", + "%4.2lf%s", + "%4.1lf%s", + }; + + // Unit index and divisor are calculated as follows: + // range unit index calculation divisor calculation + // -3 mHz ( int )( ( -3 + 3 ) / 3 ) = 0 + // -2 mHz ( int )( ( -2 + 3 ) / 3 ) = 0 + // -1 mHz ( int )( ( -1 + 3 ) / 3 ) = 0 / 10e-3 = 10e( 3 * 0 - 3 ) + // 0 Hz ( int )( ( 0 + 3 ) / 3 ) = 1 + // 1 Hz ( int )( ( 1 + 3 ) / 3 ) = 1 + // 2 Hz ( int )( ( 2 + 3 ) / 3 ) = 1 / 1e0 = 10e( 3 * 1 - 3 ) + // 3 kHz ( int )( ( 3 + 3 ) / 3 ) = 2 + // 4 kHz ( int )( ( 4 + 3 ) / 3 ) = 2 + // 5 kHz ( int )( ( 5 + 3 ) / 3 ) = 2 / 10e3 = 10e( 3 * 2 - 3 ) + // 6 MHz ( int )( ( 6 + 3 ) / 3 ) = 3 + // 7 MHz ( int )( ( 7 + 3 ) / 3 ) = 3 + // 8 MHz ( int )( ( 8 + 3 ) / 3 ) = 3 / 10e6 =10e( 3 * 3 - 3 ) + + // unit string + static const char *unit_str[] = + { + "mHz", + "Hz", + "kHz", + "MHz" + }; + + + if ( p_ff->khz_val ) { - sprint_dms( s, &ppos->latitude, prec ); - strcat( s, sep ); - sprint_dms( _eos( s ), &ppos->longitude, prec ); - strcat( s, sep ); - sprintf( _eos( s ), "%.0fm", ppos->lla[ALT] ); + // calculate frequency in Hz + freq = ( double ) p_ff->khz_val * pow( 10, ( p_ff->range + 3 ) ); + + // calculate decimal exponent + range = ( ( int ) log10( freq ) ); + + // check whether range is in the allowed range + // if so display frequency in broken format + if ( ( range >= -3 ) && ( range <= 8 ) ) + { + // calculate format index ( see above ) + format = ( ( ( range % 3 ) + 3 ) % 3 ); + + // calculate unit index + unit = ( ushort )( range + 3 ) / 3; + + // calculate display value + freq = freq / pow( 10, ( ( 3 * unit ) - 3 ) ); + n = snprintf_safe( s, max_len, fmt_str[format], freq, unit_str[unit] ); + } + else + { + // out of range display fequency in Hz + n = snprintf_safe( s, max_len, "%fHz", freq ); + } } else - strcpy( s, "N/A" ); + n = sn_cpy_str_safe( s, max_len, str_na ); -} /* sprint_pos_geo */ + return n; +} // snprint_fixed_freq +#endif // _USE_GPSUTILS_FULL diff --git a/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.h b/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.h index 8716adf..fd25e3e 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/gpsutils.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: gpsutils.h 1.4.1.2 2010/07/15 09:19:04 martin REL_M $ + * $Id: gpsutils.h 1.8 2017/07/05 13:58:25 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,10 +10,15 @@ * * ----------------------------------------------------------------------- * $Log: gpsutils.h $ - * Revision 1.4.1.2 2010/07/15 09:19:04 martin + * Revision 1.8 2017/07/05 13:58:25 martin + * Include stddef.h. + * Updated function prototypes. + * Revision 1.7 2010/07/15 09:32:09 martin * Use DEG character definition from pcpslstr.h. - * Revision 1.4.1.1 2003/05/15 09:40:25Z martin - * Changed degree string/char for QNX. + * Revision 1.6 2005/02/18 10:32:33Z martin + * Check more predefined macros to determine if compiling for Windows. + * Revision 1.5 2003/02/04 09:18:48Z MARTIN + * Updated function prototypes. * Revision 1.4 2002/12/12 16:08:11 martin * Definitions for degree character. * Requires mbggeo.h. @@ -32,6 +37,8 @@ #include <mbggeo.h> +#include <stddef.h> + #ifdef _GPSUTILS #define _ext @@ -43,26 +50,174 @@ /* Start of header body */ - -/* function prototypes: */ - #ifdef __cplusplus extern "C" { #endif + + /* ----- function prototypes begin ----- */ /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ - void swap_double( double *d ) ; - void swap_eph_doubles( EPH *ephp ) ; - void swap_alm_doubles( ALM *almp ) ; - void swap_utc_doubles( UTC *utcp ) ; - void swap_iono_doubles( IONO *ionop ) ; - void swap_pos_doubles( POS *posp ) ; - void sprint_dms( char *s, DMS *pdms, int prec ) ; - void sprint_pos_geo( char *s, POS *ppos, const char *sep, int prec ) ; + /** + * @brief Swap the bytes of a single variable of type "double" + * + * The memory layout of a "double" on Meinberg bus level devices + * and computers usually differs. This function can be used to + * fix this and is usually called from inside API functions, + * if required. + * + * @param[in,out] p Pointer to a "double" to be swapped + * + * @see ::swap_eph_doubles + * @see ::swap_alm_doubles + * @see ::swap_utc_doubles + * @see ::swap_iono_doubles + * @see ::swap_pos_doubles + */ + void swap_double( double *p ) ; + + /** + * @brief Swap the "double" fields in an ::EPH structure + * + * See comments for ::swap_double + * + * @param[in,out] p Pointer to an ::EPH structure to be converted + * + * @see ::swap_double + * @see ::swap_alm_doubles + * @see ::swap_utc_doubles + * @see ::swap_iono_doubles + * @see ::swap_pos_doubles + */ + void swap_eph_doubles( EPH *p ) ; + + /** + * @brief Swap the "double" fields in an ::ALM structure + * + * See comments for ::swap_double + * + * @param[in,out] p Pointer to an ::ALM structure to be converted + * + * @see ::swap_double + * @see ::swap_eph_doubles + * @see ::swap_utc_doubles + * @see ::swap_iono_doubles + * @see ::swap_pos_doubles + */ + void swap_alm_doubles( ALM *p ) ; + + /** + * @brief Swap the "double" fields in a ::UTC structure + * + * See comments for ::swap_double + * + * @param[in,out] p Pointer to a ::UTC structure to be converted + * + * @see ::swap_double + * @see ::swap_eph_doubles + * @see ::swap_alm_doubles + * @see ::swap_iono_doubles + * @see ::swap_pos_doubles + */ + void swap_utc_doubles( UTC *p ) ; + + /** + * @brief Swap the "double" fields in a ::IONO structure + * + * See comments for ::swap_double + * + * @param[in,out] p Pointer to a ::IONO structure to be converted + * + * @see ::swap_double + * @see ::swap_eph_doubles + * @see ::swap_alm_doubles + * @see ::swap_utc_doubles + * @see ::swap_pos_doubles + */ + void swap_iono_doubles( IONO *p ) ; + + /** + * @brief Swap the "double" fields in a ::POS structure + * + * See comments for ::swap_double + * + * @param[in,out] p Pointer to a ::POS structure to be converted + * + * @see ::swap_double + * @see ::swap_eph_doubles + * @see ::swap_alm_doubles + * @see ::swap_utc_doubles + * @see ::swap_iono_doubles + */ + void swap_pos_doubles( POS *p ) ; + + /** + * @brief Print the ::DMS part of a geo position into a string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p Pointer to a ::DMS structure to be printed + * @param[in] prec Precision, i.e. number of fractions of the seconds + * + * @return Length of the string in the buffer + * + * @see snprint_dms + * @see snprint_alt + * @see snprint_pos_geo + * @see snprint_fixed_freq + */ + size_t snprint_dms( char *s, size_t max_len, const DMS *p, int prec ) ; + + /** + * @brief Print the altitude part of a geo position into a string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] alt The altitude value to be printed, in [m] + * + * @return Length of the string in the buffer + * + * @see snprint_dms + * @see snprint_pos_geo + * @see snprint_fixed_freq + */ + size_t snprint_alt( char *s, size_t max_len, double alt ) ; + + /** + * @brief Print a geo position in ::POS format into a string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p Pointer to a ::POS structure to be printed + * @param[in] sep Separator character for the ::DMS part + * @param[in] prec Precision, i.e. number of fractions of the seconds of the ::DMS part + * + * @return Length of the string in the buffer + * + * @see snprint_dms + * @see snprint_alt + * @see snprint_fixed_freq + */ + size_t snprint_pos_geo( char *s, size_t max_len, const POS *p, char sep, int prec ) ; + + /** + * @brief Print a formatted ::FIXED_FREQ_INFO into a string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p_ff Pointer to a ::FIXED_FREQ_INFO structure to be printed + * + * @return Length of the string in the buffer + * + * @see snprint_dms + * @see snprint_alt + * @see snprint_pos_geo + */ + size_t snprint_fixed_freq( char *s, size_t max_len, FIXED_FREQ_INFO *p_ff ) ; + /* ----- function prototypes end ----- */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/identdec.h b/src/external/bsd/meinberg/dist/mbglib/common/identdec.h index 6054ec7..2eff9fc 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/identdec.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/identdec.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: identdec.h 1.1 2002/02/19 13:46:19 MARTIN REL_M $ + * $Id: identdec.h 1.2 2017/05/10 15:21:36 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,8 @@ * * ----------------------------------------------------------------------- * $Log: identdec.h $ + * Revision 1.2 2017/05/10 15:21:36 martin + * Tiny cleanup. * Revision 1.1 2002/02/19 13:46:19 MARTIN * Initial revision * @@ -34,16 +36,11 @@ /* Start of header body */ - - - - -/* function prototypes: */ - #ifdef __cplusplus extern "C" { #endif + /* ----- function prototypes begin ----- */ /* This section was generated automatically */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/lan_util.c b/src/external/bsd/meinberg/dist/mbglib/common/lan_util.c index 03734c4..5fc9de1 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/lan_util.c +++ b/src/external/bsd/meinberg/dist/mbglib/common/lan_util.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: lan_util.c 1.1.1.3 2011/06/21 15:23:30 martin TRASH $ + * $Id: lan_util.c 1.12 2017/07/05 14:07:56 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,12 +10,54 @@ * * ----------------------------------------------------------------------- * $Log: lan_util.c $ - * Revision 1.1.1.3 2011/06/21 15:23:30 martin - * Fixed build under DOS. - * Revision 1.1.1.2 2011/04/20 16:08:55Z martin - * Revision 1.1.1.1 2011/03/04 10:33:22 martin - * Implemented dummy snprintf() function for environments - * which don't provide this. + * Revision 1.12 2017/07/05 14:07:56 martin + * IPv6 support functions added by hannes. + * Function snprint_ip4_cidr_mask() fixed by hannes. It now behaves + * as expected and appends the CIDR mask bits to the IP address now. + * Mostly use safe string functions from str_util.c. + * New function snprint_ptp_clock_id(). + * Compiler warnings due to uninitialized vars quieted by thomas-b. + * Renamed check_octets_not_all_zero() to octets_are_all_zero(), + * which returns a bool now. + * Renamed check_mac_addr_not_all_zero() to mac_addr_all_zero(), + * which returns a bool now. + * Removed get_port_mac_addr_check(). + * Removed definitions of old MBG_LU_... return codes, and + * only use standard MBG_RETURN_CODES instead. + * Fixed macro definition syntax to quiet clang compiler warnings. + * Let get_port_ip4_settings() check port link even if it + * returns an error (changed by daniel). + * Check for MBG_TGT_POSIX instead of MBG_TGT_UNIX. + * Doxygen comments. + * Revision 1.11 2015/04/01 14:31:14 hannes + * Fix: cidr_str_to_ip4_addr_and_net_mask: Defaults correctly to + * netmask 0.0.0.0 (/0) for no CIDR extension in cidr_str. + * Revision 1.10 2014/10/17 12:45:48 martin + * Let str_to_ip4_addr() return 0 if an empty string has been passed. + * Revision 1.9 2014/09/24 08:31:00 martin + * Exclude get_ip4_gateway() from build if USE_MBG_TSU is defined. + * Fixed some compiler warnings. + * Added and modified some comments. + * Revision 1.8 2013/10/02 07:19:13 martin + * New function get_port_intf_idx. + * Fixed naming.of local netlink support functions. + * Revision 1.7 2013/05/22 16:49:42 martin + * Fixed some return codes. + * Revision 1.6 2013/03/19 10:24:51 martin + * Fixed bugs in get_ip4_gateway(): A skipped routing entry was + * taken as default route, and thus a wrong default route 0.0.0.0 + * could be returned erraneously. Also, malloc() was used without + * checking the result. + * Added conditional debug code. + * Revision 1.5 2013/02/19 15:13:10 martin + * Added some new functions. + * Updated doxygen comments. + * Revision 1.4 2012/11/02 09:16:57 martin + * Fixed build under Windows. + * Revision 1.3 2012/10/02 18:23:28Z martin + * Removed obsolete code to avoid compiler warning. + * Revision 1.2 2012/03/09 08:49:19 martin + * Added some commonly used functions. * Revision 1.1 2011/03/04 10:01:32Z martin * Initial revision. * @@ -25,61 +67,932 @@ #include <lan_util.h> #undef _LAN_UTIL +#include <words.h> +#include <str_util.h> +#include <mbgerror.h> + #include <stdio.h> +#include <string.h> +#include <ctype.h> +#if defined( MBG_TGT_POSIX ) -#if defined( __BORLANDC__ ) \ - && ( __BORLANDC__ <= 0x410 ) // BC3.1 defines 0x410 ! + #if defined( MBG_TGT_LINUX ) + #include <linux/types.h> -#include <stdarg.h> + // Some older versions of linux/types.h don't define u8..u64 + // for user space applications. However, if they do they also + // define BITS_PER_LONG, so we use this symbol to figure out + // if we need to define u8..u64 by ourselves. + #if !defined( BITS_PER_LONG ) + typedef uint8_t u8; + typedef uint16_t u16; + typedef uint32_t u32; + typedef uint64_t u64; + #endif -static /*HDR*/ -int snprintf( char *s, size_t max_len, const char *fmt, ... ) + #include <linux/sockios.h> + #include <linux/ethtool.h> + #include <linux/rtnetlink.h> + #endif + + #include <unistd.h> + #include <syslog.h> + #include <sys/ioctl.h> + #include <arpa/inet.h> + #include <netinet/in.h> + +#else + + // dummy codes, the functions will report an error ... + #define SIOCGIFADDR 0 + #define SIOCGIFNETMASK 0 + #define SIOCGIFBRDADDR 0 + + #if defined( MBG_TGT_WIN32 ) + #define snprintf _snprintf + #endif + +#endif + + +#if !defined( DEBUG_NETLINK ) + #if ( 0 && defined( DEBUG ) && defined( MBG_TGT_LINUX ) ) + #define DEBUG_NETLINK 1 + #else + #define DEBUG_NETLINK 0 + #endif +#endif + + +#if DEBUG_NETLINK + // we need a function to output debugging information + #if !defined STANDALONE + #include <ptp2_cnf.h> // for mbglog() from the ARM PTP projects + #else + // to be provided by the application + extern __attribute__( ( format( printf, 2, 3 ) ) ) void mbglog( int priority, const char *fmt, ... ); + #endif +#endif // DEBUG_NETLINK + + + +// Maximum size of an IPv4 address string in dotted quad format, +// including a terminating 0, and thus the required minimum size +// for a buffer to take such a string. i.e. "aaa.bbb.ccc.ddd\0". +#define MAX_IP4_ADDR_STR_SIZE 16 + + +#if defined( MBG_TGT_LINUX ) + +struct route_info +{ + struct in_addr dstAddr; + struct in_addr srcAddr; + struct in_addr gateWay; + char ifName[IF_NAMESIZE]; +}; + +#endif + + + +/*HDR*/ +/** + * @brief Count the number of sequential bits in an IPv4 net mask + * + * Counting starts from MSB, i.e. for 0xC0 and 0xC1 the results + * are both 2 since only the 2 MSBs are sequentially set. + * + * @param[in] p_mask The IPv4 net mask to be evaluated + * + * @return The number of sequential MSB bits set in *p_mask + * + * @see ::ip4_net_mask_from_cidr + */ +int get_ip4_net_mask_bits( const IP4_ADDR *p_mask ) +{ + IP4_ADDR msb_mask = IP4_MSB_MASK; + int i; + + for ( i = 0; i < MAX_IP4_BITS; i++ ) + { + if ( ( *p_mask & msb_mask ) == 0 ) + break; + + msb_mask >>= 1; + } + + return i; + +} // get_ip4_net_mask_bits + + + +/*HDR*/ +/** + * @brief Print an IPv4 address to a dotted quad formatted string + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p_addr The IPv4 address to be evaluated + * @param[in] info An optional string which is prepended to the string, or NULL + * + * @return The overall number of characters printed to the string + * + * @see ::snprint_ip4_cidr_addr + * @see ::str_to_ip4_addr + * @see ::cidr_str_to_ip4_addr_and_net_mask + */ +size_t snprint_ip4_addr( char *s, size_t max_len, const IP4_ADDR *p_addr, const char *info ) { - int n; - va_list arg_list; + size_t n = 0; + ulong ul = *p_addr; - va_start( arg_list, fmt ); - n = vsprintf( s, fmt, arg_list ); - va_end( arg_list ); + if ( info ) + n += snprintf_safe( s, max_len, "%s", info ); + // Don't use byte pointers here since this is not safe + // for both little and big endian targets. + n += snprintf_safe( &s[n], max_len - n, "%u.%u.%u.%u", + BYTE_3( ul ), BYTE_2( ul ), + BYTE_1( ul ), BYTE_0( ul ) + ); return n; -} // snprintf +} // snprint_ip4_addr -#endif + + +/*HDR*/ +/** + * @brief Print an IPv4 address plus net mask in CIDR notation to a string + * + * The printed CIDR string is something like "172.16.3.250/24" + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p_addr The IPv4 address to be evaluated + * @param[in] p_mask The associated IPv4 net mask + * @param[in] info An optional string which is prepended to the string, or NULL + * + * @return The overall number of characters printed to the string + * + * @see ::snprint_ip4_addr + * @see ::str_to_ip4_addr + * @see ::cidr_str_to_ip4_addr_and_net_mask + */ +size_t snprint_ip4_cidr_addr( char *s, size_t max_len, const IP4_ADDR *p_addr, + const IP4_ADDR *p_mask, const char *info ) +{ + int cidr_mask_bits; + size_t n = snprint_ip4_addr( s, max_len, p_addr, info ); + + cidr_mask_bits = get_ip4_net_mask_bits( p_mask ); + + if ( ( cidr_mask_bits >= MIN_IP4_CIDR_NETMASK_BITS ) && + ( cidr_mask_bits <= MAX_IP4_CIDR_NETMASK_BITS ) ) + n += snprintf_safe( &s[n], max_len - n, "/%i", cidr_mask_bits ); + + return n; + +} // snprint_ip4_cidr_addr /*HDR*/ /** - * @brief Print a MAC ID or similar array of octets to a string. + * @brief Convert a string to an ::IP4_ADDR + * + * If output parameter is specified as NULL then this function + * can be used to check if the IPv4 address string is formally correct. * - * @param s The string buffer into which to print - * @param max_len Maximum length of the string, i.e. size of the buffer - * @param octets An array of octets - * @param num_octets The number of octets to be printed from the array - * @param sep The separator printed between the bytes, or 0 - * @param info An optional string which is prepended to the output, or NULL + * @param[out] p_addr Pointer to an ::IP4_ADDR variable to be filled, or NULL + * @param[in] s An IPv4 address string to be converted + * + * @return A number >= 0 (::MBG_SUCCESS) according to the number of characters evaluated + * from the input string, or one of the @ref MBG_ERROR_CODES on error, + * specifically ::MBG_ERR_PARM_FMT if an invalid number or character was found in the string. + * + * @see ::snprint_ip4_addr + * @see ::snprint_ip4_cidr_addr + * @see ::cidr_str_to_ip4_addr_and_net_mask + */ +int str_to_ip4_addr( IP4_ADDR *p_addr, const char *s ) +{ + IP4_ADDR tmp_ip4_addr = 0; + const char *cp = s; + int i; + + if ( strlen( s ) ) + { + for ( i = 0; ; ) + { + unsigned long ul = strtoul( (char *) cp, (char **) &cp, 10 ); + + if ( ul > 0xFFUL ) // invalid number + return MBG_ERR_PARM_FMT; + + tmp_ip4_addr |= ul << ( 8 * (3 - i) ); + + if ( ++i >= 4 ) + break; // done + + if ( *cp != '.' ) + return MBG_ERR_PARM_FMT; // invalid string format, dot expected + + cp++; // skip dot + } + } + + if ( p_addr ) + *p_addr = tmp_ip4_addr; + + // success: return the number of evaluated chars + return (int) ( cp - s ); + +} // str_to_ip4_addr + + + +/*HDR*/ +/** + * @brief Convert a string in CIDR notation to an ::IP4_ADDR and net mask + * + * If output parameters are specified as NULL then this function + * can be used to check if the CIDR string is formally correct. + * + * @param[out] p_addr Pointer to an ::IP4_ADDR variable to be filled with + * the IPv4 address, or NULL + * @param[out] p_mask Pointer to an ::IP4_ADDR variable to be filled with + * the IPv4 net mask, or NULL + * @param[in] cidr_str The string to be converted, in CIDR format, e.g. "172.16.3.250/24" + * + * @return A number >= 0 (::MBG_SUCCESS) according to the number of characters evaluated + * from the input string, or one of the @ref MBG_ERROR_CODES on error, + * specifically ::MBG_ERR_PARM_FMT if an invalid number or character was found in the string. + * + * @see ::snprint_ip4_addr + * @see ::snprint_ip4_cidr_addr + * @see ::str_to_ip4_addr + */ +int cidr_str_to_ip4_addr_and_net_mask( IP4_ADDR *p_addr, IP4_ADDR *p_mask, + const char *cidr_str ) +{ + IP4_ADDR mask; + long cidr_mask_bits; + const char *cp; + int l; + int rc = str_to_ip4_addr( p_addr, cidr_str ); + + if ( mbg_rc_is_error( rc ) ) + return rc; + + + l = (int) strlen( cidr_str ); + + if ( l < rc ) // input string too short + return MBG_ERR_PARM_FMT; + + + cp = &cidr_str[rc]; + + if ( *cp == 0 ) // end of string + { + // The string has no CIDR extension, so + // assume "/0", i.e. host mask 0.0.0.0; + mask = (IP4_ADDR) 0; + goto done; + } + + + if ( *cp != '/' ) + return MBG_ERR_PARM_FMT; + + + cp++; + cidr_mask_bits = strtol( (char *) cp, (char **) &cp, 10 ); + + if ( ( cidr_mask_bits < MIN_IP4_CIDR_NETMASK_BITS ) || + ( cidr_mask_bits > MAX_IP4_CIDR_NETMASK_BITS ) ) + return MBG_ERR_RANGE; + + + mask = ip4_net_mask_from_cidr( (int) cidr_mask_bits ); + +done: + if ( p_mask ) + *p_mask = mask; + + // success: return the number of evaluated chars + return (int) ( cp - cidr_str ); + +} // cidr_str_to_ip4_addr_and_net_mask + + + +/*HDR*/ +/** + * @brief Count the number of sequential bits in an IPv6 net mask + * + * Counting starts from MSB, i.e. for 0xC0 and 0xC1 the results + * are both 2 since only the 2 MSBs are sequentially set. + * + * @param[in] p_mask The IPv6 net mask to be evaluated + * + * @return The number of sequential MSB bits set in *p_mask + * + * @see ::ip6_net_mask_from_cidr + */ +int get_ip6_net_mask_bits( const IP6_ADDR *p_mask ) +{ + int i; + int cnt = 0; + uint8_t msb_mask = IP6_MSB_MASK; + + for ( i = IP6_ADDR_BYTES - 1 ; i >= 0; i-- ) + { + if ( p_mask->b[i] == 0xff ) + cnt += 8; + else + { + for ( ; cnt < MAX_IP6_CIDR_NETMASK_BITS; cnt++ ) + { + if ( ( p_mask->b[i] & msb_mask ) == 0 ) + break; + + msb_mask >>= 1; + } + break; + } + } + + return cnt; + +} // get_ip6_net_mask_bits + + + +/*HDR*/ +/** + * @brief Print an IPv6 address in optimized format to a string + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p_addr The IPv6 address to be evaluated + * @param[in] info An optional string which is prepended to the string, or NULL * * @return The overall number of characters printed to the string + * + * @see ::snprint_ip6_cidr_addr + * @see ::snprint_ip6_cidr_mask_addr + * @see ::str_to_ip6_addr + * @see ::cidr_str_to_ip6_addr_and_cidr_bits + * @see ::cidr_str_to_ip6_addr_and_net_mask */ -int snprint_octets( char *s, size_t max_len, const uint8_t *octets, - int num_octets, char sep, const char *info ) +size_t snprint_ip6_addr( char *s, size_t max_len, const IP6_ADDR *p_addr, const char *info ) { - int n = 0; + // Copied from inet_ntop.c, and reversed byte order + + IP6_ADDR_STR tmp; + char *tp; + #define NUM_WORDS ( (int) ( sizeof( IP6_ADDR_STR ) / sizeof( uint16_t ) ) ) + uint16_t words[NUM_WORDS] = { 0 }; int i; + size_t n = 0; + struct + { + int base; + int len; + } best = { 0 }, cur = { 0 }; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in p_addr->b[] for :: shorthanding. + */ + for ( i = IP6_ADDR_BYTES - 1; i >= 0; i-- ) + words[(IP6_ADDR_BYTES - 1 - i) / 2] |= (p_addr->b[i] << ((1 - ((IP6_ADDR_BYTES - 1 - i) % 2)) << 3)); + + best.base = -1; + cur.base = -1; + + for ( i = 0; i < NUM_WORDS; i++ ) + { + if ( words[i] == 0 ) + { + if ( cur.base == -1 ) + cur.base = i, cur.len = 1; + else + cur.len++; + } + else + { + if ( cur.base != -1 ) + { + if ( best.base == -1 || cur.len > best.len ) + best = cur; + + cur.base = -1; + } + } + } + + if ( cur.base != -1 ) + { + if ( best.base == -1 || cur.len > best.len ) + best = cur; + } + + if ( best.base != -1 && best.len < 2 ) + best.base = -1; + + // Format the result. + + tp = tmp; + + for ( i = 0; i < NUM_WORDS; i++ ) + { + /* Are we inside the best run of 0x00's? */ + if ( best.base != -1 && i >= best.base && i < ( best.base + best.len ) ) + { + if (i == best.base) + *tp++ = ':'; + + continue; + } + + /* Are we following an initial run of 0x00s or any real hex? */ + if ( i != 0 ) + *tp++ = ':'; + + /* Is this address an encapsulated IPv4? */ + if ( i == 6 && best.base == 0 && ( best.len == 6 || ( best.len == 5 && words[5] == 0xffff ) ) ) + return MBG_ERR_INV_PARM; // we don't support encapsulated IPv4 + + sprintf( tp, "%x", words[i] ); + tp += strlen( tp ); + } + + /* Was it a trailing run of 0x00's? */ + if ( best.base != -1 && ( best.base + best.len ) == NUM_WORDS ) + *tp++ = ':'; + + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ( ( tp - tmp ) > (int) max_len ) + return MBG_ERR_OVERFLOW; if ( info ) - n += snprintf( s, max_len, "%s", info ); + n += snprintf_safe( s, max_len, "%s", info ); + + n += snprintf_safe( &s[n], max_len - n, "%s", tmp ); + + return n; + + #undef NUM_WORDS + +} // snprint_ip6_addr + + + +/*HDR*/ +/** + * @brief Print an IPv6 address plus net mask to string in CIDR notation + * + * The printed CIDR string is something like "2001:0DB8:0:CD30:EF45::/64" + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p_addr The IPv6 address to be evaluated + * @param[in] p_mask The associated IPv6 net mask + * @param[in] info An optional string which is prepended to the string, or NULL + * + * @return The overall number of characters printed to the string + * + * @see ::snprint_ip6_addr + * @see ::snprint_ip6_cidr_mask_addr + * @see ::str_to_ip6_addr + * @see ::cidr_str_to_ip6_addr_and_cidr_bits + * @see ::cidr_str_to_ip6_addr_and_net_mask + */ +size_t snprint_ip6_cidr_addr( char *s, size_t max_len, const IP6_ADDR *p_addr, + const IP6_ADDR *p_mask, const char *info ) +{ + size_t n = snprint_ip6_addr( s, max_len, p_addr, info ); + + int cidr_mask_bits = get_ip6_net_mask_bits( p_mask ); + + if ( ( cidr_mask_bits >= MIN_IP6_CIDR_NETMASK_BITS ) && + ( cidr_mask_bits <= MAX_IP6_CIDR_NETMASK_BITS ) ) + n += snprintf_safe( &s[n], max_len - n, "/%i", cidr_mask_bits ); + + return n; + +} // snprint_ip6_cidr_addr + + + +/*HDR*/ +/** + * @brief Print an IPv6 address plus number of net mask bits to string in CIDR notation + * + * The printed CIDR string is something like "2001:0DB8:0:CD30:EF45::/64" + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p_addr The IPv6 address to be evaluated + * @param[in] cidr_mask_bits The CIDR number of bits specifying the IPv6 net mask + * @param[in] info An optional string which is prepended to the string, or NULL + * + * @return The overall number of characters printed to the string + * + * @see ::snprint_ip6_addr + * @see ::snprint_ip6_cidr_addr + * @see ::str_to_ip6_addr + * @see ::cidr_str_to_ip6_addr_and_cidr_bits + * @see ::cidr_str_to_ip6_addr_and_net_mask + */ +size_t snprint_ip6_cidr_mask_addr( char *s, size_t max_len, const IP6_ADDR *p_addr, + const int cidr_mask_bits, const char* info ) +{ + size_t n; + IP6_ADDR mask; + + ip6_net_mask_from_cidr( &mask, cidr_mask_bits ); + + n = snprint_ip6_addr( s, max_len, p_addr, info ); + + if ( ( cidr_mask_bits >= MIN_IP6_CIDR_NETMASK_BITS ) && + ( cidr_mask_bits <= MAX_IP6_CIDR_NETMASK_BITS ) ) + n += snprintf_safe( &s[n], max_len - n, "/%i", cidr_mask_bits ); + + return n; + +} // snprint_ip6_cidr_mask_addr + + + +/*HDR*/ +/** + * @brief Convert a string to an ::IP6_ADDR + * + * If the output parameter is specified as NULL then this function + * can be used to check if the string is formally correct. + * + * On success ::IP6_ADDR variable contains the IPv6 address + * in little endian byte order. + * + * @param[out] p_addr Pointer to the ::IP6_ADDR variable, or NULL + * @param[in] s A string containing an IPv6 address + * + * @return A number >= 0 (::MBG_SUCCESS) according to the number of characters evaluated + * from the input string, or one of the @ref MBG_ERROR_CODES on error, + * specifically ::MBG_ERR_PARM_FMT if an invalid number or character was found in the string. + * + * @see ::snprint_ip6_addr + * @see ::snprint_ip6_cidr_addr + * @see ::snprint_ip6_cidr_mask_addr + * @see ::str_to_ip6_addr + * @see ::cidr_str_to_ip6_addr_and_cidr_bits + * @see ::cidr_str_to_ip6_addr_and_net_mask + */ +int str_to_ip6_addr( IP6_ADDR *p_addr, const char *s ) +{ + // copied from inet_pton.c and reversed byte order + IP6_ADDR tmp = { { 0 } }; + static const char xdigits[] = "0123456789abcdef"; + uint8_t *tp; + uint8_t *startp; + uint8_t *colonp; + int ch; + int saw_xdigit; + int read_cnt = 0; + unsigned int val; + + if ( p_addr ) + memset( p_addr, 0, sizeof( *p_addr ) ); // set IP address to :: + + startp = tmp.b - 1; + tp = startp + sizeof( tmp ); + + colonp = NULL; + + /* Leading :: requires some special handling. */ + if ( *s == ':' ) + { + read_cnt++; + + if ( *++s != ':' ) + return MBG_ERR_PARM_FMT; + } + + saw_xdigit = 0; + val = 0; + + while ( ( ch = tolower( *s++ ) ) != '\0' ) + { + const char *pch; + + read_cnt++; + + pch = strchr( xdigits, ch ); + + if ( pch != NULL ) + { + val <<= 4; + val |= ( pch - xdigits ); + + if ( val > 0xffff ) //### TODO signed? unsigned? + return MBG_ERR_PARM_FMT; + + saw_xdigit = 1; + continue; + } + + if ( ch == ':' ) + { + if ( !saw_xdigit ) + { + if ( colonp ) + return MBG_ERR_PARM_FMT; + + colonp = tp; + continue; + + } + else + if ( *s == '\0' ) + return MBG_ERR_PARM_FMT; + + if ( tp - sizeof( uint16_t ) < startp ) + return MBG_ERR_PARM_FMT; + + *tp-- = (uint8_t) ( val >> 8 ) & 0xff; + *tp-- = (uint8_t) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + + if ( ch == '/' ) // cidr notation. we reached the end + { + read_cnt--; + break; + } + + return MBG_ERR_PARM_FMT; + } + + if ( saw_xdigit ) + { + if ( tp - sizeof( uint16_t ) < startp ) + return MBG_ERR_PARM_FMT; + + *tp-- = (uint8_t) (val >> 8) & 0xff; + *tp-- = (uint8_t) val & 0xff; + } + + if ( colonp != NULL ) + { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const size_t n = colonp - tp; + size_t i; + + if ( tp == startp ) + return MBG_ERR_PARM_FMT; + + for ( i = 0; i <= n; i++ ) + { + startp[i] = colonp[i - n]; + colonp[i - n] = 0; + } + + tp = startp; + } + + if ( tp != startp ) + return MBG_ERR_PARM_FMT; + + if ( p_addr ) + *p_addr = tmp; + + return read_cnt; + +} // str_to_ip6_addr + + + +/*HDR*/ +/** + * @brief Convert a string in CIDR notation to an ::IP6_ADDR and net mask + * + * If output parameters are specified as NULL then this function + * can be used to check if the CIDR string is formally correct. + * + * @param[out] p_addr Pointer to an ::IP6_ADDR variable to be filled up + * with the IPv6 address, or NULL + * @param[out] p_mask Pointer to an ::IP6_ADDR variable to be filled up + with the net mask bits, or NULL + * @param[in] cidr_str The string to be converted, in CIDR format, e.g. "2001:0DB8:0:CD30::/64" + * + * @return A number >= 0 (::MBG_SUCCESS) according to the number of characters evaluated + * from the input string, or one of the @ref MBG_ERROR_CODES on error, + * specifically ::MBG_ERR_PARM_FMT if an invalid number or character was found in the string. + * + * @see ::snprint_ip4_addr + * @see ::snprint_ip4_cidr_addr + * @see ::str_to_ip4_addr + */ +int cidr_str_to_ip6_addr_and_net_mask( IP6_ADDR *p_addr, IP6_ADDR *p_mask, const char *cidr_str ) +{ + int mask = 0; + int rc = cidr_str_to_ip6_addr_and_cidr_bits( p_addr, &mask, cidr_str ); + + if ( mbg_rc_is_error( rc ) ) + return rc; + + if ( p_mask ) + ip6_net_mask_from_cidr( p_mask, mask ); + + return rc; + +} // cidr_str_to_ip6_addr_and_net_mask + + + +/*HDR*/ +/** + * @brief Convert a string in CIDR notation to an ::IP6_ADDR and net mask bits + * + * If output parameters are specified as NULL then this function + * can be used to check if the CIDR string is formally correct. + * + * @param[out] p_addr Pointer to an ::IP6_ADDR variable for the IPv6 address, or NULL + * @param[out] p_cidr Pointer to an int variable for the net mask bits, or NULL + * @param[in] cidr_str The string to be converted, in CIDR format, e.g. "2001:0DB8:0:CD30::/64" + * + * @return A number >= 0 (::MBG_SUCCESS) according to the number of characters evaluated + * from the input string, or one of the @ref MBG_ERROR_CODES on error, + * specifically ::MBG_ERR_PARM_FMT if an invalid number or character was found in the string. + * + * @see ::snprint_ip6_addr + * @see ::snprint_ip6_cidr_addr + * @see ::str_to_ip6_addr + */ +int cidr_str_to_ip6_addr_and_cidr_bits( IP6_ADDR *p_addr, int *p_cidr, + const char *cidr_str ) +{ + long cidr_mask_bits; + const char *cp; + ssize_t l; + int rc = str_to_ip6_addr( p_addr, cidr_str ); + + if ( mbg_rc_is_error( rc ) ) + return rc; + + l = strlen( cidr_str ); + + if ( l < rc ) // input string too short + return MBG_ERR_PARM_FMT; + + cp = &cidr_str[rc]; + + if ( *cp == 0 ) // end of string + { + // The string has no CIDR extension, so + // assume "/0", i.e. host mask :: + cidr_mask_bits = 0; + goto done; + } + + if ( *cp != '/' ) + return MBG_ERR_PARM_FMT; + + cp++; + cidr_mask_bits = strtol( (char *) cp, (char **) &cp, 10 ); + + if ( ( cidr_mask_bits < MIN_IP6_CIDR_NETMASK_BITS ) || + ( cidr_mask_bits > MAX_IP6_CIDR_NETMASK_BITS ) ) + return MBG_ERR_RANGE; + +done: + if ( p_cidr ) + *p_cidr = (int) cidr_mask_bits; + + // success: return the number of evaluated chars + return (int) ( cp - cidr_str ); + +} // cidr_str_to_ip6_addr_and_cidr_bits + + + +/*HDR*/ +/** + * @brief Compute an IPv6 net mask according to the number of CIDR netmask bits + * + * E.g. the 64 bits mentioned in "2001:0DB8:0:CD30::/64" result in 2^64, + * corresponding to FFFF:FFFF:FFFF:FFFF:: in IPv6 notation. + * + * @param[out] p_mask Pointer to an ::IP6_ADDR variable for the IPv6 netmask + * @param[in] netmask_bits Number of netmask bits from CIDR notation + * + * @see ::get_ip6_net_mask_bits + */ +void ip6_net_mask_from_cidr( IP6_ADDR *p_mask, int netmask_bits ) +{ + int i = 0; + + if ( p_mask ) + { + memset( p_mask, 0, sizeof( *p_mask ) ); + + if ( netmask_bits < 0 ) + netmask_bits = 0; + else + if ( netmask_bits >= IP6_ADDR_BITS ) + netmask_bits = IP6_ADDR_BITS; + + for ( i = IP6_ADDR_BYTES - 1; i >= 0; i-- ) + { + if ( netmask_bits > 8 ) + { + p_mask->b[i] = 0xff; + netmask_bits -= 8; + } + else + { + p_mask->b[i] = (0xff << ( 8 - netmask_bits ) ) & 0xff; + netmask_bits = 0; + } + } + } + +} // ip6_net_mask_from_cidr + + + +/*HDR*/ +/** + * @brief Determine the network part of an IPv6 address based on the net mask + * + * E.g. IP "2001:0DB8:0:CD30::", net mask "FFFF:FFFF::" yields network part "2001:0DB8::". + * + * @param[out] p_net_part The extracted network part of the IPv6 address + * @param[in] p_addr The IPv6 address to be evaluated + * @param[in] p_mask The associated IPv6 net mask + */ +void ip6_net_part_from_addr( IP6_ADDR *p_net_part, const IP6_ADDR *p_addr, + const IP6_ADDR *p_mask ) +{ + int i; + + for ( i = IP6_ADDR_BYTES; i-- > 0; ) + p_net_part->b[i] = p_addr->b[i] & p_mask->b[i]; + +} // ip6_net_part_from_addr + + + +/*HDR*/ +/** + * @brief Print a MAC ID or similar array of octets to a string + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Maximum length of the string, i.e. size of the buffer + * @param[in] octets An array of octets + * @param[in] num_octets The number of octets to be printed from the array + * @param[in] sep The separator printed between the bytes, or 0 + * @param[in] info An optional string which is prepended to the output, or NULL + * + * @return The overall number of characters printed to the string + * + * @see ::snprint_mac_addr + * @see ::str_to_octets + * @see ::octets_are_all_zero + */ +size_t snprint_octets( char *s, size_t max_len, const uint8_t *octets, + int num_octets, char sep, const char *info ) +{ + size_t n = 0; + int i; + + if ( info ) + n += snprintf_safe( s, max_len, "%s", info ); for ( i = 0; i < num_octets; i++ ) { if ( i && sep ) - n += snprintf( &s[n], max_len - n, "%c", sep ); + n += snprintf_safe( &s[n], max_len - n, "%c", sep ); - n += snprintf( &s[n], max_len - n, "%02X", octets[i] ); + n += snprintf_safe( &s[n], max_len - n, "%02X", octets[i] ); } return n; @@ -90,13 +1003,61 @@ int snprint_octets( char *s, size_t max_len, const uint8_t *octets, /*HDR*/ /** - * @brief Set a MAC ID or a similar array of bytes from a string. + * @brief Print a ::PTP_CLOCK_ID to a string + * + * @todo Eventually this function should be moved to a different module. + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Maximum length of the string, i.e. size of the buffer + * @param[in] p The ::PTP_CLOCK_ID to be printed * - * @param octets An array of octets to be set up - * @param num_octets The number of octets which can be stored - * @param s The string to be converted + * @return The overall number of characters printed to the string * - * @return The overall number of octets decoded from the string + * @see ::snprint_octets + */ +size_t snprint_ptp_clock_id( char *s, size_t max_len, const PTP_CLOCK_ID *p ) +{ + return snprint_octets( s, max_len, p->b, sizeof( *p ), ':', NULL ); + +} // snprint_ptp_clock_id + + + +/*HDR*/ +/** + * @brief Print a MAC address to a string + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Maximum length of the string, i.e. size of the buffer + * @param[in] p_mac_addr The MAC address to be printed + * + * @return The overall number of characters printed to the string + * + * @see ::snprint_octets + * @see ::str_to_octets + * @see ::octets_are_all_zero + */ +size_t snprint_mac_addr( char *s, size_t max_len, const MBG_MAC_ADDR *p_mac_addr ) +{ + return snprint_octets( s, max_len, p_mac_addr->b, sizeof( *p_mac_addr ), MAC_SEP_CHAR, NULL ); + +} // snprint_mac_addr + + + +/*HDR*/ +/** + * @brief Set a MAC ID or a similar array of octets from a string + * + * @param[out] octets An array of octets to be set up + * @param[in] num_octets The number of octets which can be stored + * @param[in] s The string to be converted + * + * @return The overall number of octets decoded from the string + * + * @see ::snprint_octets + * @see ::snprint_mac_addr + * @see ::octets_are_all_zero */ int str_to_octets( uint8_t *octets, int num_octets, const char *s ) { @@ -126,74 +1087,838 @@ int str_to_octets( uint8_t *octets, int num_octets, const char *s ) /*HDR*/ /** - * @brief Print an IPv4 address to a dotted quad format string. + * @brief Check if an array of octets is all zero * - * @param s The string buffer into which to print - * @param max_len Maximum length of the string, i.e. size of the buffer - * @param addr The IPv4 address - * @param info An optional string which is prepended to the string, or NULL + * @param[in] octets Pointer to the array of octets + * @param[in] num_octets Number of octets * - * @return The overall number of characters printed to the string + * @return true if all bytes are 0, else false + * + * @see ::snprint_octets + * @see ::snprint_mac_addr + * @see ::str_to_octets */ -int snprint_ip4_addr( char *s, size_t max_len, const IP4_ADDR *addr, const char *info ) +bool octets_are_all_zero( const uint8_t *octets, int num_octets ) { - int n = 0; + int i; - if ( info ) - n += snprintf( s, max_len, "%s", info ); + // check if any of the bytes is != 0 + for ( i = 0; i < num_octets; i++ ) + if ( octets[i] != 0 ) + break; - n += snprintf( &s[n], max_len - n, "%i.%i.%i.%i", - BYTE_OF( *addr, 3 ), - BYTE_OF( *addr, 2 ), - BYTE_OF( *addr, 1 ), - BYTE_OF( *addr, 0 ) - ); - return n; + return i == num_octets; // true if *all* bytes are 0 -} // snprint_ip4_addr +} // octets_are_all_zero /*HDR*/ /** - * @brief Convert a string to an IP4_ADDR. + * @brief Check if a MAC address is all zero * - * @param p Pointer to the IP4_ADDR variable, or NULL, in which case this - * function can be used to check if the string is formally correct. - * @param s The string to be converted + * @param[in] p_addr Pointer to a MAC address to be checked * - * @return >= 0 on success, number of characters evaluated from the input string - * -1 if invalid number found in string - * -2 if separator is not a dot '.' + * @return true if all bytes of the MAC address are 0, else false + * + * @see ::octets_are_all_zero */ -int str_to_ip4_addr( IP4_ADDR *p, const char *s ) +bool mac_addr_is_all_zero( const MBG_MAC_ADDR *p_addr ) { - IP4_ADDR tmp_ip4_addr = 0; - char *cp; + return octets_are_all_zero( p_addr->b, sizeof( p_addr->b ) ); + +} // mac_addr_is_all_zero + + + +#if defined( MBG_TGT_POSIX ) + +/*HDR*/ +/** + * @brief Do a SIOCGxxx IOCTL call to read specific information from a LAN interface + * + * @param[in] if_name Name of the interface + * @param[in] ioctl_code One of the predefined system SIOCGxxx IOCTL codes + * @param[out] p_ifreq Pointer to a request buffer + * + * @return One of the @ref MBG_RETURN_CODES + */ +int do_siocg_ioctl( const char *if_name, int ioctl_code, struct ifreq *p_ifreq ) +{ + int sock_fd; + int rc; + + if ( strlen( if_name ) > ( IFNAMSIZ - 1 ) ) + return MBG_ERR_PARM_FMT; + + sock_fd = socket( AF_INET, SOCK_DGRAM, 0 ); //### TODO: or AF_INET6/PF_INET6 for IPv6 + + if ( sock_fd == -1 ) // failed to open socket + return mbg_get_last_socket_error( "failed to open socket in do_siocg_ioctl" ); + + strncpy_safe( p_ifreq->ifr_name, if_name, sizeof( p_ifreq->ifr_name ) ); + + rc = ioctl( sock_fd, ioctl_code, p_ifreq ); + + if ( rc == -1 ) // ioctl failed, errno has been set appropriately + rc = mbg_get_last_socket_error( "ioctl failed in do_siocg_ioctl" ); + else + rc = MBG_SUCCESS; + + close( sock_fd ); + + return rc; + +} // do_siocg_ioctl + +#endif // defined( MBG_TGT_POSIX ) + + + +/*HDR*/ +/** + * @brief Retrieve the index of a specific network interface + * + * @param[in] if_name Name of the interface + * @param[out] p_intf_idx Pointer to a variable to be filled up + * + * @return One of the @ref MBG_RETURN_CODES. + * On error, *p_intf_idx is set to -1. + */ +int get_port_intf_idx( const char *if_name, int *p_intf_idx ) +{ + int rc = MBG_ERR_NOT_SUPP_ON_OS; + + #if defined( MBG_TGT_LINUX ) + struct ifreq ifr = { { { 0 } } }; + + rc = do_siocg_ioctl( if_name, SIOCGIFINDEX, &ifr ); + + if ( mbg_rc_is_success( rc ) ) + { + *p_intf_idx = ifr.ifr_ifindex; + return rc; + } + #endif + + // we get here on error only + *p_intf_idx = -1; + + return rc; + +} // get_port_intf_idx + + + +/*HDR*/ +/** + * @brief Retrieve the MAC address of a network interface + * + * @param[in] if_name Name of the interface + * @param[out] p_mac_addr Pointer to the MAC address buffer to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * On error, the MAC address is set to all 0 + */ +int get_port_mac_addr( const char *if_name, MBG_MAC_ADDR *p_mac_addr ) +{ + int rc = MBG_ERR_NOT_SUPP_ON_OS; + + #if defined( MBG_TGT_LINUX ) + struct ifreq ifr = { { { 0 } } }; + + rc = do_siocg_ioctl( if_name, SIOCGIFHWADDR, &ifr ); + + if ( mbg_rc_is_success( rc ) ) + { + memcpy( p_mac_addr, ifr.ifr_hwaddr.sa_data, sizeof( *p_mac_addr ) ); + return rc; + } + #endif + + // we get here on error only + memset( p_mac_addr, 0, sizeof( *p_mac_addr ) ); + + return rc; + +} // get_port_mac_addr + + + +/*HDR*/ +/** + * @brief Check the link state of a network interface + * + * @param[in] if_name Name of the interface + * + * @return 1 if link detected on port, + * 0 if no link detected on port, + * one of the @ref MBG_ERROR_CODES in case of an error + */ +int check_port_link( const char *if_name ) +{ + int rc = MBG_ERR_NOT_SUPP_ON_OS; + + #if defined( MBG_TGT_LINUX ) + struct ifreq ifr = { { { 0 } } }; + struct ethtool_value edata = { 0 }; + + edata.cmd = ETHTOOL_GLINK; // defined in ethtool.h + ifr.ifr_data = (caddr_t) &edata; + + rc = do_siocg_ioctl( if_name, SIOCETHTOOL, &ifr ); + + if ( mbg_rc_is_success( rc ) ) + rc = ( edata.data == 0 ) ? 0 : 1; + #endif + + return rc; + +} // check_port_link + + + +static /*HDR*/ +/** + * @brief Retrieve some IPv4 address-like info from a network interface + * + * @param[in] if_name Name of the interface + * @param[out] p_addr Pointer to address field to be filled up + * @param[in] sigioc_code The IOCTL code associated with the address + * + * @return One of the @ref MBG_RETURN_CODES + * On error, *p_addr is set to all 0. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr + * @see ::get_port_ip4_broad_addr_str + */ +int get_specific_port_ip4_addr( const char *if_name, IP4_ADDR *p_addr, int sigioc_code ) +{ + int rc = MBG_ERR_NOT_SUPP_ON_OS; + + #if defined( MBG_TGT_LINUX ) + struct ifreq ifr = { { { 0 } } }; + + rc = do_siocg_ioctl( if_name, sigioc_code, &ifr ); + + if ( mbg_rc_is_success( rc ) ) + { + *p_addr = ntohl( ( (struct sockaddr_in *) &ifr.ifr_addr )->sin_addr.s_addr ); + return rc; + } + #endif + + // we get here on error only + *p_addr = 0; // make empty address + + return rc; + +} // get_specific_port_ip4_addr + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 address of a network interface + * + * @param[in] if_name Name of the interface + * @param[out] p_addr Pointer to address field to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * On error, *p_addr is set to all 0. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr + * @see ::get_port_ip4_broad_addr_str + * @see ::get_specific_port_ip4_addr + */ +int get_port_ip4_addr( const char *if_name, IP4_ADDR *p_addr ) +{ + return get_specific_port_ip4_addr( if_name, p_addr, SIOCGIFADDR ); + +} // get_port_ip4_addr + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 net mask of a network interface + * + * @param[in] if_name Name of the interface + * @param[out] p_addr Pointer to address field to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * On error, *p_addr is set to all 0. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr + * @see ::get_port_ip4_broad_addr_str + * @see ::get_specific_port_ip4_addr + */ +int get_port_ip4_netmask( const char *if_name, IP4_ADDR *p_addr ) +{ + return get_specific_port_ip4_addr( if_name, p_addr, SIOCGIFNETMASK ); + +} // get_port_ip4_netmask + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 broadcast address of a network interface + * + * @param[in] if_name Name of the interface + * @param[out] p_addr Pointer to address field to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * On error, *p_addr is set to all 0. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr_str + * @see ::get_specific_port_ip4_addr + */ +int get_port_ip4_broad_addr( const char *if_name, IP4_ADDR *p_addr ) +{ + return get_specific_port_ip4_addr( if_name, p_addr, SIOCGIFBRDADDR ); + +} // get_port_ip4_broad_addr + + + +#if defined( MBG_TGT_LINUX ) + +static /*HDR*/ +/** + * @brief Read a requested message from the netlink socket + * + * @return Message length (>= 0) on success, or of the @ref MBG_ERROR_CODES + */ +int nl_read( int sock_fd, char *buf_ptr, size_t buf_size, int seq_num, int pid ) +{ + struct nlmsghdr *nl_hdr; + int read_len = 0; + int msg_len = 0; + + do + { + // receive response from the kernel, can be several chunks + if ( ( read_len = recv( sock_fd, buf_ptr, buf_size - msg_len, 0 ) ) == -1 ) + { + int rc = mbg_get_last_socket_error( NULL ); + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Failed to receive netlink packet: %s", + __func__, mbg_strerror( rc ) ); + #endif + return rc; + } + + nl_hdr = (struct nlmsghdr *) buf_ptr; + + // check if the header is valid + if ( ( NLMSG_OK( nl_hdr, read_len ) == 0 ) || ( nl_hdr->nlmsg_type == NLMSG_ERROR ) ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Invalid header in received netlink packet", + __func__ ); + #endif + return MBG_ERR_DATA_FMT; + } + + // check if the its the last message + if ( nl_hdr->nlmsg_type == NLMSG_DONE ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Reached last message in received packet", + __func__ ); + #endif + break; + } + + // move the pointer to buffer appropriately + buf_ptr += read_len; + msg_len += read_len; + + // check if its a multi part message + if ( ( nl_hdr->nlmsg_flags & NLM_F_MULTI ) == 0 ) + { + // return if it's not a multi part message + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Received packet is not a multi part message", + __func__ ); + #endif + break; + } + + } while ( ( nl_hdr->nlmsg_seq != seq_num ) || ( nl_hdr->nlmsg_pid != pid ) ); + + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Received packet has len %i", + __func__, msg_len ); + #endif + + return msg_len; + +} // nl_read + + + +#if DEBUG_NETLINK + +static /*HDR*/ +void nl_log_bytes( const char *fnc, const char *info, const void *p, int n_bytes ) +{ + char ws[80]; + size_t n = 0; int i; - for ( i = 0, cp = (char *) s; ; ) + for ( i = 0; i < n_bytes; i++ ) + n += snprintf_safe( &ws[n], sizeof( ws ) - n, " %i", BYTE_OF( * (uint8_t *) p, i ) ); + + mbglog( LOG_INFO, "%s: attibute %s, copying %i bytes:%s", + fnc, info, n_bytes, ws ); + +} // nl_log_bytes + +#endif + + + +static /*HDR*/ +int nl_parse_routes( struct nlmsghdr *nl_hdr, struct route_info *rt_info ) +{ + // parse the route info returned + struct rtmsg *rt_msg; + struct rtattr *rt_attr; + int rt_len; + + rt_msg = (struct rtmsg *) NLMSG_DATA( nl_hdr ); + + // If the route is not for AF_INET then return. + // This could be also IPv6 routes. + if ( rt_msg->rtm_family != AF_INET ) //##++ TODO: PF_INET6 for IPv6 + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Route is not AF_INET (%li), but %li", + __func__, (long) AF_INET, (long) rt_msg->rtm_family ); + #endif + return -1; + } + + // If the route does not belong to main routing table then return. + if ( rt_msg->rtm_table != RT_TABLE_MAIN ) { - unsigned long ul = strtoul( cp, &cp, 10 ); + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Route does not belong to main table (%li), but %li", + __func__, (long) RT_TABLE_MAIN, (long) rt_msg->rtm_table ); + #endif + return -1; + } - if ( ul > 255 ) // invalid number - return -1; - tmp_ip4_addr |= ul << ( 8 * (3 - i) ); + // get the rtattr field + rt_attr = (struct rtattr *) RTM_RTA( rt_msg ); + rt_len = RTM_PAYLOAD( nl_hdr ); + + for ( ; RTA_OK( rt_attr, rt_len ); rt_attr = RTA_NEXT( rt_attr, rt_len ) ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "rt_attr at %p, %i bytes left", rt_attr, rt_len ); + #endif - if ( ++i >= 4 ) - break; // done + switch ( rt_attr->rta_type ) + { + case RTA_OIF: + if_indextoname( *(int *)RTA_DATA( rt_attr ), rt_info->ifName ); + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: attibute RTA_OIF, IF name: %s", + __func__, rt_info->ifName ); + #endif + break; - if ( *cp != '.' ) - return -2; // invalid string format, dot expected + case RTA_GATEWAY: + memcpy( &rt_info->gateWay, RTA_DATA( rt_attr ), sizeof( rt_info->gateWay ) ); + #if DEBUG_NETLINK + nl_log_bytes( __func__, "RTA_GATEWAY", &rt_info->gateWay, sizeof( rt_info->gateWay ) ); + #endif + break; - cp++; // skip dot + case RTA_PREFSRC: + memcpy( &rt_info->srcAddr , RTA_DATA( rt_attr ), sizeof( rt_info->srcAddr ) ); + #if DEBUG_NETLINK + nl_log_bytes( __func__, "RTA_PREFSRC", &rt_info->srcAddr, sizeof( rt_info->srcAddr ) ); + #endif + break; + + case RTA_DST: + memcpy( &rt_info->dstAddr, RTA_DATA( rt_attr ), sizeof( rt_info->dstAddr ) ); + #if DEBUG_NETLINK + nl_log_bytes( __func__, "RTA_DST", &rt_info->dstAddr, sizeof( rt_info->dstAddr ) ); + #endif + break; + + #if DEBUG_NETLINK + case RTA_TABLE: + { + // The RTA_TABLE attribute was added to the kernel source in 2006 to support + // more than 255 routing tables. Originally the number of the routing table + // to which an entry belongs had been passed only in struct rtmsg::rtm_table, + // which is only 8 bits wide and should still hold the 8 LSBs of the full + // routing table number for compatibility, so this should still work for the + // standard routing tables, including the main table we are inspecting here. + // + // Whether this can be compiled in depends on the version of linux/rtnetlink.h + // used by the compiler. Unfortunately RTA_TABLE is part of an enum, so you + // can't simply use #ifdef RTA_TABLE to include this code conditionally. + uint32_t rta_table; + memcpy( &rta_table, RTA_DATA( rt_attr ), sizeof( rta_table ) ); + mbglog( LOG_ERR, "%s: attibute RTA_TABLE %i (%i)", + __func__, rta_table, rt_msg->rtm_table ); + } + break; + + default: + mbglog( LOG_ERR, "%s: Found unknown route type %li", + __func__, (long) rt_attr->rta_type ); + #endif + } } - if ( p ) - *p = tmp_ip4_addr; + return 0; - return cp - (char *) s; // success +} // nl_parse_routes + +#endif // defined( MBG_TGT_LINUX ) + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 gateway (default route) + * + * @param[out] p_addr Pointer to address field to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * On error, *p_addr is set to all 0. + */ +int get_ip4_gateway( IP4_ADDR *p_addr ) +{ + int rc = MBG_ERR_NOT_SUPP_ON_OS; + +#if defined( MBG_TGT_LINUX ) + struct nlmsghdr *nlmsg; + struct route_info route_info; + char msg_buf[8192]; // pretty large buffer, why 8192 ? + int sock_fd; + int len; + int msg_seq = 0; + int idx; + + // create socket + if ( ( sock_fd = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE ) ) == -1 ) + { + rc = mbg_get_last_socket_error( NULL ); + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Failed to create netlink socket: %s", + __func__, mbg_strerror( rc ) ); + #endif + goto out; + } + + + // initialize buffer with request message + memset( msg_buf, 0, sizeof( msg_buf ) ); + + // point the header and the msg structure pointers into the buffer + nlmsg = (struct nlmsghdr *) msg_buf; + + // fill in the nlmsg header + nlmsg->nlmsg_len = NLMSG_LENGTH( sizeof( struct rtmsg ) ); // length of message + nlmsg->nlmsg_type = RTM_GETROUTE; // get the routes from kernel routing table + + nlmsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // the message is a request for dump + nlmsg->nlmsg_seq = msg_seq++; // sequence of the message packet + nlmsg->nlmsg_pid = getpid(); // PID of process sending the request + + // send the request + if ( send( sock_fd, nlmsg, nlmsg->nlmsg_len, 0 ) == -1 ) + { + rc = mbg_get_last_socket_error( NULL ); + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Failed to write to netlink socket: %s", + __func__, mbg_strerror( rc ) ); + #endif + goto out; + } + + // read the response + if ( ( len = nl_read( sock_fd, msg_buf, sizeof( msg_buf ), msg_seq, getpid() ) ) < 0 ) + { + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Failed to read from netlink socket", + __func__ ); + #endif + rc = len; + goto out; + } + + #if DEBUG_NETLINK + mbglog( LOG_ERR, "%s: Read %i bytes from netlink socket", __func__, len ); + #endif + + // parse and print the response + for ( idx = 0; NLMSG_OK( nlmsg, len ); nlmsg = NLMSG_NEXT( nlmsg, len ), idx++ ) + { + memset( &route_info, 0, sizeof( route_info ) ); + + #if DEBUG_NETLINK + mbglog( LOG_ERR, "\nnl_msg at %p, %i bytes left", nlmsg, len ); + #endif + + + if ( nl_parse_routes( nlmsg, &route_info ) < 0 ) + continue; // don't check route_info if it has not been set up + + #if DEBUG_NETLINK + { + char ws[100]; + int l = sizeof( ws ); + int n = 0; + + // inet_ntoa() uses a static buffer which is overwritten on every call + //##++ TODO: rather than inet_ntoa use inet_ntop which can also handle IPv6 + n += snprintf_safe( &ws[n], l - n, "src %s", (char *) inet_ntoa( route_info.srcAddr ) ); + n += snprintf_safe( &ws[n], l - n, ", dst %s", (char *) inet_ntoa( route_info.dstAddr ) ); + n += snprintf_safe( &ws[n], l - n, ", gw %s", (char *) inet_ntoa( route_info.gateWay ) ); + + mbglog( LOG_ERR, "%s: route %i: %s, if \"%s\"", + __func__, idx, ws, route_info.ifName ); + } + #endif + + // check if default IPv4 gateway + //##++ TODO: rather than inet_ntoa use inet_ntop which can also handle IPv6 + if ( strstr( (char *) inet_ntoa( route_info.dstAddr ), "0.0.0.0" ) ) + { + *p_addr = ntohl( route_info.gateWay.s_addr ); + rc = MBG_SUCCESS; + // Actually we could stop searching now. However, in case of debug + // we'll continue to examine the rest of the routing message. + #if DEBUG_NETLINK + //##++ TODO: rather than inet_ntoa use inet_ntop which can also handle IPv6 + mbglog( LOG_ERR, "%s: Default gateway found: %s", + __func__, (char *) inet_ntoa( route_info.gateWay ) ); + #else + break; + #endif + } + } + +out: + if ( sock_fd >= 0 ) + close( sock_fd ); + +#endif // defined( MBG_TGT_LINUX ) + + if ( mbg_rc_is_error( rc ) ) + *p_addr = 0; + + return rc; + +} // get_ip4_gateway + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 address of a network interface as string + * + * @param[in] if_name Name of the interface + * @param[out] p_addr_buf Pointer to the string buffer to be filled up + * @param[in] buf_size size of the string buffer + * + * @return One of the @ref MBG_RETURN_CODES + * On error, a string according to "0.0.0.0" is generated. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr + * @see ::get_port_ip4_broad_addr_str + * @see ::get_specific_port_ip4_addr + */ +int get_port_ip4_addr_str( const char *if_name, char *p_addr_buf, int buf_size ) +{ + IP4_ADDR addr; + + int rc = get_port_ip4_addr( if_name, &addr ); + + snprint_ip4_addr( p_addr_buf, buf_size, &addr, NULL ); + + return rc; + +} // get_port_ip4_addr_str + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 net mask of a network interface as string + * + * @param[in] if_name Name of the interface + * @param[out] p_addr_buf Pointer to the string buffer to be filled up + * @param[in] buf_size size of the string buffer + * + * @return One of the @ref MBG_RETURN_CODES + * On error, a string according to "0.0.0.0" is generated. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_broad_addr + * @see ::get_port_ip4_broad_addr_str + * @see ::get_specific_port_ip4_addr + */ +int get_port_ip4_netmask_str( const char *if_name, char *p_addr_buf, int buf_size ) +{ + IP4_ADDR addr; + + int rc = get_port_ip4_netmask( if_name, &addr ); + + snprint_ip4_addr( p_addr_buf, buf_size, &addr, NULL ); + + return rc; + +} // get_port_ip4_netmask_str + + + +/*HDR*/ +/** + * @brief Retrieve the IPv4 broadcast address of a network interface as string + * + * @param[in] if_name Name of the interface + * @param[out] p_addr_buf Pointer to the string buffer to be filled up + * @param[in] buf_size size of the string buffer + * + * @return One of the @ref MBG_RETURN_CODES + * On error, a string according to "0.0.0.0" is generated. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr + * @see ::get_specific_port_ip4_addr + */ +int get_port_ip4_broad_addr_str( const char *if_name, char *p_addr_buf, int buf_size ) +{ + IP4_ADDR addr; + + int rc = get_port_ip4_broad_addr( if_name, &addr ); + + snprint_ip4_addr( p_addr_buf, buf_size, &addr, NULL ); + + return rc; + +} // get_port_ip4_broad_addr_str + + + +/*HDR*/ +/** + * @brief Retrieve the current IPv4 settings of a network interface + * + * @param[in] if_name Name of the interface + * @param[out] p Pointer to a IP4_SETTINGS structure to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr + * @see ::get_port_ip4_broad_addr_str + * @see ::get_specific_port_ip4_addr + */ +int get_port_ip4_settings( const char *if_name, IP4_SETTINGS *p ) +{ + int link_up; + int rc; + + memset( p, 0, sizeof( *p ) ); + + rc = get_port_ip4_addr( if_name, &p->ip_addr ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + + rc = get_port_ip4_netmask( if_name, &p->netmask ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + + rc = get_port_ip4_broad_addr( if_name, &p->broad_addr ); + + if ( mbg_rc_is_error( rc ) ) + goto out; + + +#ifndef USE_MBG_TSU + rc = get_ip4_gateway( &p->gateway ); + + if ( mbg_rc_is_error( rc ) ) + goto out; +#endif + +#if 0 //### TODO + // We could also try to check VLAN and DHCP settings here, + // but as of now, this is specific to an application. + + // ##++++ The VLAN and DHCP status info collected below + // just return what has been configured previously by this program, + // however, it does not reflect any changes which have been made + // manually, e.g. via the command line. + if ( vlan_enabled ) + { + p->flags |= IP4_MSK_VLAN; + p->vlan_cfg = vlan_cfg; + } + + if ( dhcp_enabled ) + p->flags |= IP4_MSK_DHCP; +#endif + +out: + + // Check linkup independent from success of getting IP4 parameters + link_up = check_port_link( if_name ); + + if ( link_up ) + p->flags |= IP4_MSK_LINK; + + return rc; + +} // get_port_ip4_settings -} // str_to_ip4_addr diff --git a/src/external/bsd/meinberg/dist/mbglib/common/lan_util.h b/src/external/bsd/meinberg/dist/mbglib/common/lan_util.h index 2092760..27d49a3 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/lan_util.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/lan_util.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: lan_util.h 1.1.1.2 2011/06/22 07:47:48 martin TRASH $ + * $Id: lan_util.h 1.7 2017/07/05 14:10:58 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,9 +10,23 @@ * * ----------------------------------------------------------------------- * $Log: lan_util.h $ - * Revision 1.1.1.2 2011/06/22 07:47:48 martin - * Cleaned up handling of pragma pack(). - * Revision 1.1.1.1 2011/04/20 16:09:02 martin + * Revision 1.7 2017/07/05 14:10:58 martin + * Some definitions used with IPv6 added by hannes. + * Removed definitions of old MBG_LU_... return codes. + * Standard MBG_RETURN_CODES are now used instead. + * Updated function prototypes. + * Revision 1.6 2014/09/24 08:32:58 martin + * Fixed a POSIX header file dependency. + * Revision 1.5 2013/10/02 07:20:36 martin + * Updated function prototypes. + * Revision 1.4 2013/02/19 15:15:53 martin + * Added some inline functions. + * Redefined return codes as named enum. + * Updated function prototypes. + * Revision 1.3 2012/10/02 18:24:29 martin + * Added some macros to simpliy conversion to string. + * Revision 1.2 2012/03/09 08:51:44 martin + * Updated function prototypes. * Revision 1.1 2011/03/04 10:01:32 martin * Initial revision. * @@ -24,10 +38,33 @@ /* Other headers to be included */ -#include <gpsdefs.h> +#include <mbg_tgt.h> +#include <gpsdefs.h> // for some Meinberg data structures #include <stdlib.h> +#if defined( MBG_TGT_POSIX ) + #include <sys/types.h> + #include <sys/socket.h> + #include <net/if.h> + #include <ifaddrs.h> // *must* be included *after* net/if.h +#else + // A dummy declaration to prevent from warnings due to usage + // of this type with function prototypes. + struct ifreq + { + int dummy; + }; +#endif + + +#if defined( IFHWADDRLEN ) // usually defined in net/if.h + #if ( IFHWADDRLEN != 6 ) + #error Warning: IFHWADDRLEN is not 6! + #endif +#endif + + #ifdef _LAN_UTIL #define _ext @@ -44,6 +81,10 @@ #define _USING_BYTE_ALIGNMENT #endif +#ifdef __cplusplus +extern "C" { +#endif + #if !defined( MAC_SEP_CHAR ) #define MAC_SEP_CHAR ':' // character used to separate octets of a MAC ID @@ -54,12 +95,111 @@ #endif +#define MAX_IP4_BITS ( 8 * (int) sizeof( IP4_ADDR ) ) + +#define IP4_MSB_MASK ( 1UL << ( MAX_IP4_BITS - 1 ) ) + +#define MIN_IP4_CIDR_NETMASK_BITS 0 +#define MAX_IP4_CIDR_NETMASK_BITS MAX_IP4_BITS + + +#define IP6_MSB_MASK ( 1UL << ( 8 - 1 ) ) + +#define MIN_IP6_CIDR_NETMASK_BITS 0 +#define MAX_IP6_CIDR_NETMASK_BITS IP6_ADDR_BITS + + + +/** + * @brief Compute an IP4 net mask according to the number of CIDR netmask bits + * + * E.g. the 24 bits mentioned in "172.16.3.250/24" result in 0xFFFFFF00, + * corresponding to 255.255.255.0 in dotted quad notation. + * + * @param netmask_bits Number of netmask bits from CIDR notation + * + * @return The IPv4 net mask + * + * @see get_ip4_net_mask_bits() + */ +static __mbg_inline +IP4_ADDR ip4_net_mask_from_cidr( int netmask_bits ) +{ + return (IP4_ADDR) ~( ( 1UL << ( MAX_IP4_BITS - netmask_bits ) ) - 1 ); + +} // ip4_net_mask_from_cidr + + + +/** + * @brief Determine the broadcast address for an IP4 address plus net mask + * + * E.g. IP 0xAC1003FA, net mask 0xFFFFFF00 yields broadcast addr 0xAC1003FF. + * In dotted quad notation, IP 172.16.3.250 with net mask 255.255.255.0 + * result in broadcast address 172.16.3.255. + * + * @param p_addr The full IP4 address + * @param p_mask The IP4 net mask + * + * @return The determined IP4 broadcast address + */ +static __mbg_inline +IP4_ADDR ip4_broad_addr_from_addr( const IP4_ADDR *p_addr, const IP4_ADDR *p_mask ) +{ + return *p_addr | ~(*p_mask); + +} // ip4_broad_addr_from_addr + + + +/** + * @brief Determine the network part of an IP4 address based on the net mask + * + * E.g. IP 0xAC1003FA, net mask 0xFFFFFF00 yields network part 0xAC100300. + * In dotted quad notation, IP 172.16.3.250 with net mask 255.255.255.0 + * results in network part 172.16.3.0. + * + * @param p_addr The full IP4 address + * @param p_mask The IP4 net mask + * + * @return The network part of the IP4 address + */ +static __mbg_inline +IP4_ADDR ip4_net_part_from_addr( const IP4_ADDR *p_addr, const IP4_ADDR *p_mask ) +{ + return *p_addr & *p_mask; + +} // ip4_net_part_from_addr + + + +/** + * @brief Check if two IP4 addresses have the same network part. + * + * @param p_addr1 The first IP4 address to check + * @param p_addr2 The second IP4 address to check + * @param p_mask The IP4 net mask + * + * @return true, if the network parts are matching + */ +static __mbg_inline +int ip4_net_part_matches( const IP4_ADDR *p_addr1, const IP4_ADDR *p_addr2, + const IP4_ADDR *p_mask ) +{ + return ip4_net_part_from_addr( p_addr1, p_mask ) + == ip4_net_part_from_addr( p_addr2, p_mask ); + +} // ip4_net_part_matches + + + +#define _ip4_addr_to_str( _s, _a ) \ + snprint_ip4_addr( _s, sizeof( _s ), _a, NULL ) + +#define _mac_addr_to_str( _s, _a ) \ + snprint_mac_addr( _s, sizeof( _s ), _a ) -/* function prototypes: */ -#ifdef __cplusplus -extern "C" { -#endif /* ----- function prototypes begin ----- */ @@ -67,54 +207,536 @@ extern "C" { /* by MAKEHDR, do not remove the comments. */ /** - * @brief Print a MAC ID or similar array of octets to a string. + * @brief Count the number of sequential bits in an IPv4 net mask + * + * Counting starts from MSB, i.e. for 0xC0 and 0xC1 the results + * are both 2 since only the 2 MSBs are sequentially set. + * + * @param[in] p_mask The IPv4 net mask to be evaluated * - * @param s The string buffer into which to print - * @param max_len Maximum length of the string, i.e. size of the buffer - * @param octets An array of octets - * @param num_octets The number of octets to be printed from the array - * @param sep The separator printed between the bytes, or 0 - * @param info An optional string which is prepended to the output, or NULL + * @return The number of sequential MSB bits set in *p_mask + * + * @see ::ip4_net_mask_from_cidr + */ + int get_ip4_net_mask_bits( const IP4_ADDR *p_mask ) ; + + /** + * @brief Print an IPv4 address to a dotted quad formatted string + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p_addr The IPv4 address to be evaluated + * @param[in] info An optional string which is prepended to the string, or NULL * * @return The overall number of characters printed to the string + * + * @see ::snprint_ip4_cidr_addr + * @see ::str_to_ip4_addr + * @see ::cidr_str_to_ip4_addr_and_net_mask */ - int snprint_octets( char *s, size_t max_len, const uint8_t *octets, int num_octets, char sep, const char *info ) ; + size_t snprint_ip4_addr( char *s, size_t max_len, const IP4_ADDR *p_addr, const char *info ) ; /** - * @brief Set a MAC ID or a similar array of bytes from a string. + * @brief Print an IPv4 address plus net mask in CIDR notation to a string + * + * The printed CIDR string is something like "172.16.3.250/24" * - * @param octets An array of octets to be set up - * @param num_octets The number of octets which can be stored - * @param s The string to be converted + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p_addr The IPv4 address to be evaluated + * @param[in] p_mask The associated IPv4 net mask + * @param[in] info An optional string which is prepended to the string, or NULL * - * @return The overall number of octets decoded from the string + * @return The overall number of characters printed to the string + * + * @see ::snprint_ip4_addr + * @see ::str_to_ip4_addr + * @see ::cidr_str_to_ip4_addr_and_net_mask */ - int str_to_octets( uint8_t *octets, int num_octets, const char *s ) ; + size_t snprint_ip4_cidr_addr( char *s, size_t max_len, const IP4_ADDR *p_addr, const IP4_ADDR *p_mask, const char *info ) ; + + /** + * @brief Convert a string to an ::IP4_ADDR + * + * If output parameter is specified as NULL then this function + * can be used to check if the IPv4 address string is formally correct. + * + * @param[out] p_addr Pointer to an ::IP4_ADDR variable to be filled, or NULL + * @param[in] s An IPv4 address string to be converted + * + * @return A number >= 0 (::MBG_SUCCESS) according to the number of characters evaluated + * from the input string, or one of the @ref MBG_ERROR_CODES on error, + * specifically ::MBG_ERR_PARM_FMT if an invalid number or character was found in the string. + * + * @see ::snprint_ip4_addr + * @see ::snprint_ip4_cidr_addr + * @see ::cidr_str_to_ip4_addr_and_net_mask + */ + int str_to_ip4_addr( IP4_ADDR *p_addr, const char *s ) ; + + /** + * @brief Convert a string in CIDR notation to an ::IP4_ADDR and net mask + * + * If output parameters are specified as NULL then this function + * can be used to check if the CIDR string is formally correct. + * + * @param[out] p_addr Pointer to an ::IP4_ADDR variable to be filled with + * the IPv4 address, or NULL + * @param[out] p_mask Pointer to an ::IP4_ADDR variable to be filled with + * the IPv4 net mask, or NULL + * @param[in] cidr_str The string to be converted, in CIDR format, e.g. "172.16.3.250/24" + * + * @return A number >= 0 (::MBG_SUCCESS) according to the number of characters evaluated + * from the input string, or one of the @ref MBG_ERROR_CODES on error, + * specifically ::MBG_ERR_PARM_FMT if an invalid number or character was found in the string. + * + * @see ::snprint_ip4_addr + * @see ::snprint_ip4_cidr_addr + * @see ::str_to_ip4_addr + */ + int cidr_str_to_ip4_addr_and_net_mask( IP4_ADDR *p_addr, IP4_ADDR *p_mask, const char *cidr_str ) ; /** - * @brief Print an IPv4 address to a dotted quad format string. + * @brief Count the number of sequential bits in an IPv6 net mask + * + * Counting starts from MSB, i.e. for 0xC0 and 0xC1 the results + * are both 2 since only the 2 MSBs are sequentially set. + * + * @param[in] p_mask The IPv6 net mask to be evaluated * - * @param s The string buffer into which to print - * @param max_len Maximum length of the string, i.e. size of the buffer - * @param addr The IPv4 address - * @param info An optional string which is prepended to the string, or NULL + * @return The number of sequential MSB bits set in *p_mask + * + * @see ::ip6_net_mask_from_cidr + */ + int get_ip6_net_mask_bits( const IP6_ADDR *p_mask ) ; + + /** + * @brief Print an IPv6 address in optimized format to a string + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p_addr The IPv6 address to be evaluated + * @param[in] info An optional string which is prepended to the string, or NULL * * @return The overall number of characters printed to the string + * + * @see ::snprint_ip6_cidr_addr + * @see ::snprint_ip6_cidr_mask_addr + * @see ::str_to_ip6_addr + * @see ::cidr_str_to_ip6_addr_and_cidr_bits + * @see ::cidr_str_to_ip6_addr_and_net_mask + */ + size_t snprint_ip6_addr( char *s, size_t max_len, const IP6_ADDR *p_addr, const char *info ) ; + + /** + * @brief Print an IPv6 address plus net mask to string in CIDR notation + * + * The printed CIDR string is something like "2001:0DB8:0:CD30:EF45::/64" + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p_addr The IPv6 address to be evaluated + * @param[in] p_mask The associated IPv6 net mask + * @param[in] info An optional string which is prepended to the string, or NULL + * + * @return The overall number of characters printed to the string + * + * @see ::snprint_ip6_addr + * @see ::snprint_ip6_cidr_mask_addr + * @see ::str_to_ip6_addr + * @see ::cidr_str_to_ip6_addr_and_cidr_bits + * @see ::cidr_str_to_ip6_addr_and_net_mask + */ + size_t snprint_ip6_cidr_addr( char *s, size_t max_len, const IP6_ADDR *p_addr, const IP6_ADDR *p_mask, const char *info ) ; + + /** + * @brief Print an IPv6 address plus number of net mask bits to string in CIDR notation + * + * The printed CIDR string is something like "2001:0DB8:0:CD30:EF45::/64" + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] p_addr The IPv6 address to be evaluated + * @param[in] cidr_mask_bits The CIDR number of bits specifying the IPv6 net mask + * @param[in] info An optional string which is prepended to the string, or NULL + * + * @return The overall number of characters printed to the string + * + * @see ::snprint_ip6_addr + * @see ::snprint_ip6_cidr_addr + * @see ::str_to_ip6_addr + * @see ::cidr_str_to_ip6_addr_and_cidr_bits + * @see ::cidr_str_to_ip6_addr_and_net_mask + */ + size_t snprint_ip6_cidr_mask_addr( char *s, size_t max_len, const IP6_ADDR *p_addr, const int cidr_mask_bits, const char* info ) ; + + /** + * @brief Convert a string to an ::IP6_ADDR + * + * If the output parameter is specified as NULL then this function + * can be used to check if the string is formally correct. + * + * On success ::IP6_ADDR variable contains the IPv6 address + * in little endian byte order. + * + * @param[out] p_addr Pointer to the ::IP6_ADDR variable, or NULL + * @param[in] s A string containing an IPv6 address + * + * @return A number >= 0 (::MBG_SUCCESS) according to the number of characters evaluated + * from the input string, or one of the @ref MBG_ERROR_CODES on error, + * specifically ::MBG_ERR_PARM_FMT if an invalid number or character was found in the string. + * + * @see ::snprint_ip6_addr + * @see ::snprint_ip6_cidr_addr + * @see ::snprint_ip6_cidr_mask_addr + * @see ::str_to_ip6_addr + * @see ::cidr_str_to_ip6_addr_and_cidr_bits + * @see ::cidr_str_to_ip6_addr_and_net_mask + */ + int str_to_ip6_addr( IP6_ADDR *p_addr, const char *s ) ; + + /** + * @brief Convert a string in CIDR notation to an ::IP6_ADDR and net mask + * + * If output parameters are specified as NULL then this function + * can be used to check if the CIDR string is formally correct. + * + * @param[out] p_addr Pointer to an ::IP6_ADDR variable to be filled up + * with the IPv6 address, or NULL + * @param[out] p_mask Pointer to an ::IP6_ADDR variable to be filled up + with the net mask bits, or NULL + * @param[in] cidr_str The string to be converted, in CIDR format, e.g. "2001:0DB8:0:CD30::/64" + * + * @return A number >= 0 (::MBG_SUCCESS) according to the number of characters evaluated + * from the input string, or one of the @ref MBG_ERROR_CODES on error, + * specifically ::MBG_ERR_PARM_FMT if an invalid number or character was found in the string. + * + * @see ::snprint_ip4_addr + * @see ::snprint_ip4_cidr_addr + * @see ::str_to_ip4_addr + */ + int cidr_str_to_ip6_addr_and_net_mask( IP6_ADDR *p_addr, IP6_ADDR *p_mask, const char *cidr_str ) ; + + /** + * @brief Convert a string in CIDR notation to an ::IP6_ADDR and net mask bits + * + * If output parameters are specified as NULL then this function + * can be used to check if the CIDR string is formally correct. + * + * @param[out] p_addr Pointer to an ::IP6_ADDR variable for the IPv6 address, or NULL + * @param[out] p_cidr Pointer to an int variable for the net mask bits, or NULL + * @param[in] cidr_str The string to be converted, in CIDR format, e.g. "2001:0DB8:0:CD30::/64" + * + * @return A number >= 0 (::MBG_SUCCESS) according to the number of characters evaluated + * from the input string, or one of the @ref MBG_ERROR_CODES on error, + * specifically ::MBG_ERR_PARM_FMT if an invalid number or character was found in the string. + * + * @see ::snprint_ip6_addr + * @see ::snprint_ip6_cidr_addr + * @see ::str_to_ip6_addr + */ + int cidr_str_to_ip6_addr_and_cidr_bits( IP6_ADDR *p_addr, int *p_cidr, const char *cidr_str ) ; + + /** + * @brief Compute an IPv6 net mask according to the number of CIDR netmask bits + * + * E.g. the 64 bits mentioned in "2001:0DB8:0:CD30::/64" result in 2^64, + * corresponding to FFFF:FFFF:FFFF:FFFF:: in IPv6 notation. + * + * @param[out] p_mask Pointer to an ::IP6_ADDR variable for the IPv6 netmask + * @param[in] netmask_bits Number of netmask bits from CIDR notation + * + * @see ::get_ip6_net_mask_bits + */ + void ip6_net_mask_from_cidr( IP6_ADDR *p_mask, int netmask_bits ) ; + + /** + * @brief Determine the network part of an IPv6 address based on the net mask + * + * E.g. IP "2001:0DB8:0:CD30::", net mask "FFFF:FFFF::" yields network part "2001:0DB8::". + * + * @param[out] p_net_part The extracted network part of the IPv6 address + * @param[in] p_addr The IPv6 address to be evaluated + * @param[in] p_mask The associated IPv6 net mask + */ + void ip6_net_part_from_addr( IP6_ADDR *p_net_part, const IP6_ADDR *p_addr, const IP6_ADDR *p_mask ) ; + + /** + * @brief Print a MAC ID or similar array of octets to a string + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Maximum length of the string, i.e. size of the buffer + * @param[in] octets An array of octets + * @param[in] num_octets The number of octets to be printed from the array + * @param[in] sep The separator printed between the bytes, or 0 + * @param[in] info An optional string which is prepended to the output, or NULL + * + * @return The overall number of characters printed to the string + * + * @see ::snprint_mac_addr + * @see ::str_to_octets + * @see ::octets_are_all_zero + */ + size_t snprint_octets( char *s, size_t max_len, const uint8_t *octets, int num_octets, char sep, const char *info ) ; + + /** + * @brief Print a ::PTP_CLOCK_ID to a string + * + * @todo Eventually this function should be moved to a different module. + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Maximum length of the string, i.e. size of the buffer + * @param[in] p The ::PTP_CLOCK_ID to be printed + * + * @return The overall number of characters printed to the string + * + * @see ::snprint_octets + */ + size_t snprint_ptp_clock_id( char *s, size_t max_len, const PTP_CLOCK_ID *p ) ; + + /** + * @brief Print a MAC address to a string + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Maximum length of the string, i.e. size of the buffer + * @param[in] p_mac_addr The MAC address to be printed + * + * @return The overall number of characters printed to the string + * + * @see ::snprint_octets + * @see ::str_to_octets + * @see ::octets_are_all_zero + */ + size_t snprint_mac_addr( char *s, size_t max_len, const MBG_MAC_ADDR *p_mac_addr ) ; + + /** + * @brief Set a MAC ID or a similar array of octets from a string + * + * @param[out] octets An array of octets to be set up + * @param[in] num_octets The number of octets which can be stored + * @param[in] s The string to be converted + * + * @return The overall number of octets decoded from the string + * + * @see ::snprint_octets + * @see ::snprint_mac_addr + * @see ::octets_are_all_zero + */ + int str_to_octets( uint8_t *octets, int num_octets, const char *s ) ; + + /** + * @brief Check if an array of octets is all zero + * + * @param[in] octets Pointer to the array of octets + * @param[in] num_octets Number of octets + * + * @return true if all bytes are 0, else false + * + * @see ::snprint_octets + * @see ::snprint_mac_addr + * @see ::str_to_octets */ - int snprint_ip4_addr( char *s, size_t max_len, const IP4_ADDR *addr, const char *info ) ; + bool octets_are_all_zero( const uint8_t *octets, int num_octets ) ; /** - * @brief Convert a string to an IP4_ADDR. + * @brief Check if a MAC address is all zero + * + * @param[in] p_addr Pointer to a MAC address to be checked + * + * @return true if all bytes of the MAC address are 0, else false + * + * @see ::octets_are_all_zero + */ + bool mac_addr_is_all_zero( const MBG_MAC_ADDR *p_addr ) ; + + /** + * @brief Do a SIOCGxxx IOCTL call to read specific information from a LAN interface + * + * @param[in] if_name Name of the interface + * @param[in] ioctl_code One of the predefined system SIOCGxxx IOCTL codes + * @param[out] p_ifreq Pointer to a request buffer + * + * @return One of the @ref MBG_RETURN_CODES + */ + int do_siocg_ioctl( const char *if_name, int ioctl_code, struct ifreq *p_ifreq ) ; + + /** + * @brief Retrieve the index of a specific network interface + * + * @param[in] if_name Name of the interface + * @param[out] p_intf_idx Pointer to a variable to be filled up + * + * @return One of the @ref MBG_RETURN_CODES. + * On error, *p_intf_idx is set to -1. + */ + int get_port_intf_idx( const char *if_name, int *p_intf_idx ) ; + + /** + * @brief Retrieve the MAC address of a network interface + * + * @param[in] if_name Name of the interface + * @param[out] p_mac_addr Pointer to the MAC address buffer to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * On error, the MAC address is set to all 0 + */ + int get_port_mac_addr( const char *if_name, MBG_MAC_ADDR *p_mac_addr ) ; + + /** + * @brief Check the link state of a network interface + * + * @param[in] if_name Name of the interface + * + * @return 1 if link detected on port, + * 0 if no link detected on port, + * one of the @ref MBG_ERROR_CODES in case of an error + */ + int check_port_link( const char *if_name ) ; + + /** + * @brief Retrieve the IPv4 address of a network interface + * + * @param[in] if_name Name of the interface + * @param[out] p_addr Pointer to address field to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * On error, *p_addr is set to all 0. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr + * @see ::get_port_ip4_broad_addr_str + * @see ::get_specific_port_ip4_addr + */ + int get_port_ip4_addr( const char *if_name, IP4_ADDR *p_addr ) ; + + /** + * @brief Retrieve the IPv4 net mask of a network interface + * + * @param[in] if_name Name of the interface + * @param[out] p_addr Pointer to address field to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * On error, *p_addr is set to all 0. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr + * @see ::get_port_ip4_broad_addr_str + * @see ::get_specific_port_ip4_addr + */ + int get_port_ip4_netmask( const char *if_name, IP4_ADDR *p_addr ) ; + + /** + * @brief Retrieve the IPv4 broadcast address of a network interface + * + * @param[in] if_name Name of the interface + * @param[out] p_addr Pointer to address field to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * On error, *p_addr is set to all 0. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr_str + * @see ::get_specific_port_ip4_addr + */ + int get_port_ip4_broad_addr( const char *if_name, IP4_ADDR *p_addr ) ; + + /** + * @brief Retrieve the IPv4 gateway (default route) + * + * @param[out] p_addr Pointer to address field to be filled up + * + * @return One of the @ref MBG_RETURN_CODES + * On error, *p_addr is set to all 0. + */ + int get_ip4_gateway( IP4_ADDR *p_addr ) ; + + /** + * @brief Retrieve the IPv4 address of a network interface as string + * + * @param[in] if_name Name of the interface + * @param[out] p_addr_buf Pointer to the string buffer to be filled up + * @param[in] buf_size size of the string buffer + * + * @return One of the @ref MBG_RETURN_CODES + * On error, a string according to "0.0.0.0" is generated. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr + * @see ::get_port_ip4_broad_addr_str + * @see ::get_specific_port_ip4_addr + */ + int get_port_ip4_addr_str( const char *if_name, char *p_addr_buf, int buf_size ) ; + + /** + * @brief Retrieve the IPv4 net mask of a network interface as string + * + * @param[in] if_name Name of the interface + * @param[out] p_addr_buf Pointer to the string buffer to be filled up + * @param[in] buf_size size of the string buffer + * + * @return One of the @ref MBG_RETURN_CODES + * On error, a string according to "0.0.0.0" is generated. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_broad_addr + * @see ::get_port_ip4_broad_addr_str + * @see ::get_specific_port_ip4_addr + */ + int get_port_ip4_netmask_str( const char *if_name, char *p_addr_buf, int buf_size ) ; + + /** + * @brief Retrieve the IPv4 broadcast address of a network interface as string + * + * @param[in] if_name Name of the interface + * @param[out] p_addr_buf Pointer to the string buffer to be filled up + * @param[in] buf_size size of the string buffer + * + * @return One of the @ref MBG_RETURN_CODES + * On error, a string according to "0.0.0.0" is generated. + * + * @see ::get_port_ip4_settings + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr + * @see ::get_specific_port_ip4_addr + */ + int get_port_ip4_broad_addr_str( const char *if_name, char *p_addr_buf, int buf_size ) ; + + /** + * @brief Retrieve the current IPv4 settings of a network interface + * + * @param[in] if_name Name of the interface + * @param[out] p Pointer to a IP4_SETTINGS structure to be filled up * - * @param p Pointer to the IP4_ADDR variable, or NULL, in which case this - * function can be used to check if the string is formally correct. - * @param s The string to be converted + * @return One of the @ref MBG_RETURN_CODES * - * @return >= 0 on success, number of characters evaluated from the input string - * -1 if invalid number found in string - * -2 if separator is not a dot '.' + * @see ::get_port_ip4_addr + * @see ::get_port_ip4_addr_str + * @see ::get_port_ip4_netmask + * @see ::get_port_ip4_netmask_str + * @see ::get_port_ip4_broad_addr + * @see ::get_port_ip4_broad_addr_str + * @see ::get_specific_port_ip4_addr */ - int str_to_ip4_addr( IP4_ADDR *p, const char *s ) ; + int get_port_ip4_settings( const char *if_name, IP4_SETTINGS *p ) ; /* ----- function prototypes end ----- */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/macioctl.h b/src/external/bsd/meinberg/dist/mbglib/common/macioctl.h index e3c0fbe..3cb0dff 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/macioctl.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/macioctl.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: macioctl.h 1.33.1.25 2011/07/20 15:48:22 martin TRASH $ + * $Id: macioctl.h 1.38 2017/07/05 14:20:58 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,67 +11,58 @@ * * ----------------------------------------------------------------------- * $Log: macioctl.h $ - * Revision 1.33.1.25 2011/07/20 15:48:22 martin + * Revision 1.38 2017/07/05 14:20:58 martin + * Support GNSS, GPIO and xmulti_ref stuff. + * Support new way to check if a feature is supported. + * Attribute always_inline is now in __mbg_inline. + * Fixed macro definition syntax to avoid clang compiler warnings. + * Account for frac_sec_from_bin() obsoleted by bin_frac_32_to_dec_frac(). + * IOCTL debugging code. + * Removed trailing spaces. + * Revision 1.37 2014/05/19 15:57:25 martin + * Fixed grammar in a comment. + * Revision 1.36 2013/09/26 07:54:22 martin + * Support GNSS API. + * Revision 1.35 2013/04/11 13:46:05 martin + * Account for modified spinlock handling under Windows. + * Revision 1.34 2012/10/02 18:29:49Z martin + * Account for some renamed library symbols. + * Account for renamed structures. + * Support on-board event logs. + * Support debug status. + * Made inline functions static. + * Include cfg_hlp.h. + * Always read receiver info directly from the device. * Conditionally use older IOCTL request buffer structures. - * Revision 1.33.1.24 2011/07/19 12:52:05 martin - * Revision 1.33.1.23 2011/07/14 14:53:58 martin * Modified generic IOCTL handling such that for calls requiring variable sizes * a fixed request block containing input and output buffer pointers and sizes is * passed down to the kernel driver. This simplifies implementation under *BSD * and also works for other target systems. - * Revision 1.33.1.22 2011/07/06 11:19:19 martin * Support reading CORR_INFO, and reading/writing TR_DISTANCE. - * Revision 1.33.1.21 2011/06/29 10:51:16 martin * Support IOCTL_DEV_HAS_PZF. - * Revision 1.33.1.20 2011/05/18 10:08:13 martin - * Re-ordered IOCTL evaluation to match ioctl_get_required_privilege() - * which also makes sure calls requiring lowest latency are handled first. - * Revision 1.33.1.19 2011/05/17 16:05:06 martin * Use a single union type buffer instead of a large number of local * variables in ioctl_switch(). * The accumulated size of all local variables required much stack * space which led to problems under Windows. - * Revision 1.33.1.18 2011/05/17 09:37:31 martin * Support PTP unicast configuration. * Account for some IOCTL codes renamed to follow common naming conventions. - * Revision 1.33.1.17 2011/04/12 15:28:54 martin * Use common mutex primitives from mbgmutex.h. - * Revision 1.33.1.16 2011/03/31 10:57:00 martin - * Revision 1.33.1.15 2011/03/31 07:32:09 martin - * This version is the same as 1.33.1.12. - * Revision 1.33.1.14 2011/03/31 07:16:34 martin * Changes by Frank Kardel: Don't require copyin/copyout under NetBSD. - * Revision 1.33.1.13 2011/03/23 16:50:30 martin * Support NetBSD beside FreeBSD. - * Revision 1.33.1.12 2011/03/21 16:25:23 martin * Account for modified _pcpc_kfree(). - * Revision 1.33.1.11 2011/03/02 09:59:50 daniel - * Bug fix: Use PCPS_TIME_STAMP with + * Bug fix: Use PCPS_TIME_STAMP with * IOCTL_GET_FAST_HR_TIMESTAMP as output size. - * Revision 1.33.1.10 2011/02/15 14:50:39Z martin - * In a call to retrieve RECEIVER_INFO don't read from device - * but just copy the field from the device info structure. - * Revision 1.33.1.9 2011/02/15 11:08:33 daniel - * Preliminary support for PTP unicast - * Revision 1.33.1.8 2011/02/09 17:08:27Z martin * Specify I/O range number when calling port I/O macros * so they can be used for different ranges under BSD. - * Revision 1.33.1.7 2011/01/26 16:37:55 martin * Modified inline declarations for gcc. - * Revision 1.33.1.6 2011/01/24 17:08:40 martin * Fixed build under FreeBSD. - * Revision 1.33.1.5 2010/11/09 10:57:33 martin * Added _sem_inc_safe_no_irp() macro (Windows only). - * Revision 1.33.1.4 2010/07/16 08:31:32Z martin - * Revision 1.33.1.3 2010/07/15 15:47:07 martin - * Revision 1.33.1.2 2010/07/14 14:48:52 martin * Simplified code and renamed some inline functions. - * Revision 1.33.1.1 2010/03/03 15:11:51 martin * Fixed macro. * Revision 1.33 2009/12/21 16:22:55 martin * Moved code reading memory mapped timestamps to inline functions. * Revision 1.32 2009/12/15 15:34:57 daniel - * Support reading the raw IRIG data bits for firmware versions + * Support reading the raw IRIG data bits for firmware versions * which support this feature. * Revision 1.31 2009/11/04 14:58:52Z martin * Conditionally exclude port status query from build. @@ -105,7 +96,7 @@ * Revision 1.23 2008/12/11 10:30:38Z martin * _pcps_get_cycles() is now called inside the low level routines * immediately when the command byte is written. - * Mutex for hardware access is now acquired/released in _pcps_sem_inc() + * Mutex for hardware access is now acquired/released in _pcps_sem_inc() * and _pcps_sem_dec(), so other IOCTLs which don't access the card * can be run in parallel. * Moved definitions of _pcps_sem_inc(), _pcps_sem_dec(), and @@ -114,14 +105,14 @@ * with certain PEX cards which have IRQs enabled). * Use _pcps_sem_inc_safe() macro to check if access is safe and * inhibit access if this is not the case. - * Consistenly use pcps_drvr_name instead of mbgclock_name + * Consistenly use pcps_drvr_name instead of mbgclock_name * for debug messages. * Don't return error for unmap_mm...() under Linux. * Account for ASIC_FEATURES being coded as flags, and account * for new symbol PCI_ASIC_HAS_MM_IO. * Handle new IOCTLs IOCTL_HAS_PCI_ASIC_FEATURES, IOCTL_HAS_PCI_ASIC_VERSION, - * IOCTL_DEV_IS_MSF, IOCTL_DEV_IS_LWR, IOCTL_DEV_IS_WWVB, - * IOCTL_GET_IRQ_STAT_INFO, IOCTL_GET_CYCLES_FREQUENCY, + * IOCTL_DEV_IS_MSF, IOCTL_DEV_IS_LWR, IOCTL_DEV_IS_WWVB, + * IOCTL_GET_IRQ_STAT_INFO, IOCTL_GET_CYCLES_FREQUENCY, * IOCTL_HAS_FAST_HR_TIMESTAMP, and IOCTL_GET_FAST_HR_TIMESTAMP. * Support mapped I/O resources. * Revision 1.22 2008/01/17 09:28:49 daniel @@ -153,17 +144,17 @@ * Revision 1.14 2004/12/09 11:03:36Z martin * Support configuration of on-board frequency synthesizer. * Revision 1.13 2004/11/09 12:47:19Z martin - * Use new macro _pcps_ddev_has_gps_data() to check whether GPS large + * Use new macro _pcps_ddev_has_gps_data() to check whether GPS large * data I/O is supported. * Changes due to renamed symbols, IRIG RX/TX. - * Modifications were required in order to be able to configure IRIG + * Modifications were required in order to be able to configure IRIG * settings of cards which provide both IRIG input and output. - * GPS169PCI cards with IRIG output and early firmware versions - * used the same codes to configure the IRIG output as the TCR - * cards use to configure the IRIG input. Those codes are now + * GPS169PCI cards with IRIG output and early firmware versions + * used the same codes to configure the IRIG output as the TCR + * cards use to configure the IRIG input. Those codes are now * exclusively used to configure the IRIG input. A workaround - * has been included for those GPS169PCI cards, because otherwise - * the IRIG configuration would not work properly after a driver + * has been included for those GPS169PCI cards, because otherwise + * the IRIG configuration would not work properly after a driver * update, without also doing a firmware update. * Show debug msg if GPS169PCI workaround for IRIG cfg in effect. * Use more specific data types than generic types. @@ -196,7 +187,7 @@ * Support almost all IOCTL codes. * Support for Win32. * Revision 1.3 2001/11/30 09:52:47Z martin - * Added support for event_time which, however, requires + * Added support for event_time which, however, requires * a custom GPS firmware. * Revision 1.2 2001/09/14 12:01:17 martin * Decode PCPS_IOCTL_SET_GPS_CMD. @@ -208,8 +199,9 @@ #ifndef _MACIOCTL_H #define _MACIOCTL_H -#include <pcpsdrvr.h> #include <mbgioctl.h> +#include <cfg_hlp.h> +#include <pcpsdrvr.h> #include <pci_asic.h> #include <mbgddmsg.h> @@ -387,7 +379,7 @@ typedef struct rc = _pcps_read_var( _pddev, _cmd, iob._fld ); \ _pcps_sem_dec( _pddev ); \ \ - if ( rc != MBG_SUCCESS ) \ + if ( mbg_rc_is_error( rc ) ) \ goto err_access; \ \ _iob_to_pout_var( iob._fld, _pout ); \ @@ -405,7 +397,7 @@ typedef struct rc = _pcps_write_var( _pddev, _cmd, iob._fld ); \ _pcps_sem_dec( _pddev ); \ \ - if ( rc != MBG_SUCCESS ) \ + if ( mbg_rc_is_error( rc ) ) \ goto err_access; \ } @@ -418,7 +410,7 @@ typedef struct rc = _pcps_write_byte( _pddev, _cmd ); \ _pcps_sem_dec( _pddev ); \ \ - if ( rc != MBG_SUCCESS ) \ + if ( mbg_rc_is_error( rc ) ) \ goto err_access; \ } @@ -435,7 +427,7 @@ typedef struct rc = pcps_read_gps( _pddev, _cmd, (uchar FAR *) &iob._fld, _size ); \ _pcps_sem_dec( _pddev ); \ \ - if ( rc != MBG_SUCCESS ) \ + if ( mbg_rc_is_error( rc ) ) \ goto err_access; \ \ _iob_to_pout( &iob._fld, _pout, _size ); \ @@ -454,7 +446,7 @@ typedef struct rc = _pcps_read_gps_var( _pddev, _cmd, iob._fld ); \ _pcps_sem_dec( _pddev ); \ \ - if ( rc != MBG_SUCCESS ) \ + if ( mbg_rc_is_error( rc ) ) \ goto err_access; \ \ _iob_to_pout_var( iob._fld, _pout ); \ @@ -475,7 +467,7 @@ typedef struct rc = _pcps_write_gps_var( _pddev, _cmd, iob._fld ); \ _pcps_sem_dec( _pddev ); \ \ - if ( rc != MBG_SUCCESS ) \ + if ( mbg_rc_is_error( rc ) ) \ goto err_access; \ } @@ -550,9 +542,14 @@ typedef struct -#define TEST_MM_ACCESS_TIME ( 0 && defined( MBG_TGT_LINUX ) ) -#define TEST_MM_ACCESS_64 0 -#define TEST_FRAC_ONLY 0 +#if ( 0 && defined( MBG_TGT_LINUX ) ) + #define TEST_MM_ACCESS_TIME 1 +#else + #define TEST_MM_ACCESS_TIME 0 +#endif + +#define TEST_MM_ACCESS_64 0 +#define TEST_FRAC_ONLY 0 #if TEST_MM_ACCESS_TIME #include <pcpsutil.h> @@ -583,6 +580,7 @@ typedef union ANT_INFO ant_info; ENABLE_FLAGS enable_flags; STAT_INFO stat_info; + RECEIVER_INFO receiver_info; GPS_CMD gps_cmd; IDENT ident; POS pos; @@ -592,11 +590,11 @@ typedef union PORT_SETTINGS_IDX port_settings_idx; SYNTH synth; SYNTH_STATE synth_state; - ALL_POUT_INFO all_pout_info; + ALL_POUT_INFO_IDX all_pout_info_idx; POUT_SETTINGS_IDX pout_settings_idx; - ALL_STR_TYPE_INFO all_str_type_info; - ALL_PORT_INFO all_port_info; - ALL_PTP_UC_MASTER_INFO all_ptp_uc_master_info; + ALL_STR_TYPE_INFO_IDX all_str_type_info_idx; + ALL_PORT_INFO_IDX all_port_info_idx; + ALL_PTP_UC_MASTER_INFO_IDX all_ptp_uc_master_info_idx; MBG_TIME_SCALE_INFO mbg_time_scale_info; MBG_TIME_SCALE_SETTINGS mbg_time_scale_settings; UTC utc; @@ -620,6 +618,22 @@ typedef union MBG_TIME_INFO_TSTAMP mbg_time_info_tstamp; CORR_INFO corr_info; TR_DISTANCE tr_distance; + MBG_DEBUG_STATUS debug_status; + MBG_NUM_EVT_LOG_ENTRIES num_evt_log_entries; + MBG_EVT_LOG_ENTRY evt_log_entry; + MBG_GNSS_MODE_SETTINGS gnss_mode_settings; + MBG_GNSS_MODE_INFO gnss_mode_info; + ALL_GNSS_SAT_INFO_IDX all_gnss_sat_info_idx; + MBG_GPIO_CFG_LIMITS mbg_gpio_cfg_limits; + ALL_GPIO_INFO_IDX all_gpio_info_idx; + ALL_GPIO_STATUS_IDX all_gpio_status_idx; + MBG_GPIO_SETTINGS_IDX mbg_gpio_settings_idx; + XMULTI_REF_INSTANCES xmulti_ref_instances; + ALL_XMULTI_REF_STATUS_IDX all_xmulti_ref_status_idx; + ALL_XMULTI_REF_INFO_IDX all_xmulti_ref_info_idx; + XMULTI_REF_SETTINGS_IDX xmulti_ref_settings_idx; + XMR_HOLDOVER_STATUS xmr_holdover_status; + IOCTL_DEV_FEAT_REQ dev_feat_req; PCPS_MAPPED_MEM mapped_mem; @@ -637,11 +651,11 @@ typedef union #if defined( __GNUC__ ) // Avoid "no previous prototype" with some gcc versions. -__mbg_inline -void swap_tstamp( PCPS_TIME_STAMP *p_ts ) __attribute__((always_inline)); +static __mbg_inline +void swap_tstamp( PCPS_TIME_STAMP *p_ts ); #endif -__mbg_inline +static __mbg_inline void swap_tstamp( PCPS_TIME_STAMP *p_ts ) { uint32_t tmp = p_ts->sec; @@ -654,14 +668,18 @@ void swap_tstamp( PCPS_TIME_STAMP *p_ts ) #if defined( __GNUC__ ) // Avoid "no previous prototype" with some gcc versions. -__mbg_inline -void do_get_fast_hr_timestamp_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP *p_ts ) __attribute__((always_inline)); +static __mbg_inline +void do_get_fast_hr_timestamp_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP *p_ts ); #endif -__mbg_inline +static __mbg_inline void do_get_fast_hr_timestamp_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP *p_ts ) { + #if defined( MBG_TGT_WIN32 ) + KIRQL OldIrql; + #endif + #if TEST_MM_ACCESS_64 volatile uint64_t *p = (volatile uint64_t *) pddev->mm_tstamp_addr; #else @@ -727,7 +745,7 @@ void do_get_fast_hr_timestamp_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP *p_ts ) #if TEST_MM_ACCESS_TIME delta_frac = (long) ( tmp.frac - p_ts->frac ); - delta_ns = (unsigned) frac_sec_from_bin( delta_frac, 1000000000UL ); + delta_ns = (unsigned) bin_frac_32_to_dec_frac( delta_frac, NSECS_PER_SEC ); printk( KERN_INFO "MM tstamp dev %04X: %li/%li cyc (%lu kHz)" " %08lX.%08lX->%08lX.%08lX: %li (%u.%03u us)" @@ -750,13 +768,17 @@ void do_get_fast_hr_timestamp_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP *p_ts ) #if defined( __GNUC__ ) // Avoid "no previous prototype" with some gcc versions. -__mbg_inline -void do_get_fast_hr_timestamp_cycles_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP_CYCLES *p_ts_cyc ) __attribute__((always_inline)); +static __mbg_inline +void do_get_fast_hr_timestamp_cycles_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP_CYCLES *p_ts_cyc ); #endif -__mbg_inline +static __mbg_inline void do_get_fast_hr_timestamp_cycles_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP_CYCLES *p_ts_cyc ) { + #if defined( MBG_TGT_WIN32 ) + KIRQL OldIrql; + #endif + volatile uint32_t *p = (volatile uint32_t *) pddev->mm_tstamp_addr; _mbg_spin_lock_acquire( &pddev->mm_lock ); @@ -768,36 +790,41 @@ void do_get_fast_hr_timestamp_cycles_safe( PCPS_DDEV *pddev, PCPS_TIME_STAMP_CYC } // do_get_fast_hr_timestamp_cycles_safe + #if defined( __GNUC__ ) // Avoid "no previous prototype" with some gcc versions. -__mbg_inline +static __mbg_inline int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, #if defined( MBG_TGT_WIN32 ) IRP *pIrp, int *ret_size, uint16_t pout_size, #endif - void *pin, void *pout ) __attribute__((always_inline)); + void *pin, void *pout ); #endif /** - * @brief Decode an handle IOCTL commands. + * @brief Decode and handle IOCTL commands * - * This function is called from the OS dependent IOCTL handlers. + * This function is called from the OS-specific IOCTL handlers, so eventually + * the calling function needs to translate the Meinberg return codes to appropriate + * OS-specific return codes. * - * @param pddev Pointer to the device structure - * @param ioctl_code The IOCTL code to be handled + * @param[in] pddev Pointer to the device structure + * @param[in] ioctl_code The IOCTL code to be handled + */ #if defined( MBG_TGT_WIN32 ) - * @param pIrp The IRP associated to the IOCTL call - * @param ret_size The number of bytes to be returned - * @param pout_size The size of the output buffer +/** + * @param[in] pIrp The IRP associated with the IOCTL call + * @param[in] ret_size The number of bytes to be returned + * @param[in] pout_size The size of the output buffer + */ #endif - * @param pin The input buffer - * @param pout The output buffer + /** + * @param[in] pin The input buffer + * @param[in] pout The output buffer * - * @return MBG_SUCCESS or one of the Meinberg error codes which need to be translated - * by the calling function to the OS dependent error code. - * @return -1 for unknown IOCTL codes + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES */ -__mbg_inline +static __mbg_inline int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, #if defined( MBG_TGT_WIN32 ) IRP *pIrp, int *ret_size, uint16_t pout_size, @@ -854,7 +881,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, iob.pcps_hr_time_cycles.cycles = pddev->acc_cycles; _pcps_sem_dec( pddev ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto err_access; _iob_to_pout_var( iob.pcps_hr_time_cycles, pout ); @@ -883,7 +910,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, mbg_get_pc_cycles( &iob.pcps_time_cycles.cycles ); _pcps_sem_dec( pddev ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto err_access; _iob_to_pout_var( iob.pcps_time_cycles, pout ); @@ -932,7 +959,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, iob.mbg_time_info_hrt.ref_hr_time_cycles.cycles = pddev->acc_cycles; _pcps_sem_dec( pddev ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto err_access; _iob_to_pout_var( iob.mbg_time_info_hrt, pout ); @@ -997,9 +1024,12 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, case IOCTL_GET_GPS_RECEIVER_INFO: - _io_chk_cond( _pcps_ddev_has_receiver_info( pddev ) ); - // Just return the saved RECEIVER_INFO ... - _iob_to_pout_var( pddev->ri, pout ); + // Always read the receiver info directly from the device. Never + // just return a previous copy which has been read earlier since + // something may just have been changed by a configuration API call. + _io_read_gps_var_chk( pddev, PC_GPS_RECEIVER_INFO, + receiver_info, pout, + _pcps_ddev_has_receiver_info( pddev ) ); break; @@ -1066,6 +1096,39 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, break; + case IOCTL_GET_DEBUG_STATUS: + _io_read_var_chk( pddev, PCPS_GET_DEBUG_STATUS, debug_status, + pout, _pcps_ddev_has_debug_status( pddev ) ); + break; + + + case IOCTL_GET_NUM_EVT_LOG_ENTRIES: + _io_read_var_chk( pddev, PCPS_NUM_EVT_LOG_ENTRIES, num_evt_log_entries, + pout, _pcps_ddev_has_evt_log( pddev ) ); + break; + + + case IOCTL_GET_FIRST_EVT_LOG_ENTRY: + _io_read_var_chk( pddev, PCPS_FIRST_EVT_LOG_ENTRY, evt_log_entry, + pout, _pcps_ddev_has_evt_log( pddev ) ); + break; + + + case IOCTL_GET_NEXT_EVT_LOG_ENTRY: + _io_read_var_chk( pddev, PCPS_NEXT_EVT_LOG_ENTRY, evt_log_entry, + pout, _pcps_ddev_has_evt_log( pddev ) ); + break; + + + #if _MBG_SUPP_VAR_ACC_SIZE // otherwise generic IOCTL functions are used instead + case IOCTL_GET_ALL_GNSS_SAT_INFO: + _io_read_gps_chk( pddev, PC_GPS_ALL_GNSS_SAT_INFO, all_gnss_sat_info_idx, pout, + pout_size, _pcps_ddev_is_gnss( pddev ) ); + break; + #endif + + + // Commands returning device capabilities and features case IOCTL_DEV_IS_GPS: @@ -1093,6 +1156,11 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, break; + case IOCTL_DEV_IS_GNSS: + _report_cond( _pcps_ddev_is_gnss( pddev ), pout ); + break; + + case IOCTL_DEV_IS_IRIG_RX: _report_cond( _pcps_ddev_is_irig_rx( pddev ), pout ); break; @@ -1273,6 +1341,36 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, break; + case IOCTL_DEV_HAS_DEBUG_STATUS: + _report_cond( _pcps_ddev_has_debug_status( pddev ), pout ); + break; + + + case IOCTL_DEV_HAS_EVT_LOG: + _report_cond( _pcps_ddev_has_evt_log( pddev ), pout ); + break; + + + case IOCTL_DEV_HAS_GPIO: + _report_cond( _pcps_ddev_has_gpio( pddev ), pout ); + break; + + + case IOCTL_DEV_HAS_XMR: + _report_cond( _pcps_ddev_has_xmr( pddev ), pout ); + break; + + case IOCTL_CHK_DEV_FEAT: + _iob_from_pin_var( iob.dev_feat_req, pin ); + rc = pcps_chk_dev_feat( pddev, iob.dev_feat_req.feat_req_type, iob.dev_feat_req.feat_num ); + #if 0 + _mbgddmsg_4( MBG_DBG_INFO, "%s: chk_dev_feat %i:%i returned %i", + pcps_driver_name, iob.dev_feat_req.feat_req_type, + iob.dev_feat_req.feat_num, rc ); + #endif + break; + + // The next codes are somewhat special since they change something // on the board but do not affect basic operation @@ -1289,6 +1387,12 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, break; + case IOCTL_CLR_EVT_LOG: + _io_write_cmd_chk( pddev, PCPS_CLR_EVT_LOG, _pcps_ddev_has_evt_log( pddev ) ); + break; + + + // Status information which may not be available for everybody case IOCTL_GET_GPS_POS: @@ -1296,6 +1400,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, break; + // Codes reading device configuration case IOCTL_GET_PCPS_SERIAL: @@ -1431,6 +1536,116 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, break; + case IOCTL_PCPS_GENERIC_READ: + #if USE_IOCTL_GENERIC_REQ + _iob_from_pin_var( iob.req, pin ); + p_buff_out = _pcps_kmalloc( iob.req.out_sz ); + + if ( p_buff_out == NULL ) + { + _mbgddmsg_4( MBG_DBG_INFO, "%s: unable to alloc %lu bytes for %s, cmd: %02lX", + pcps_driver_name, (ulong) iob.req.out_sz, + "IOCTL_PCPS_GENERIC_READ", (ulong) iob.req.info ); + goto err_no_mem; + } + + _pcps_sem_inc_safe( pddev ); + rc = _pcps_read( pddev, (uint8_t) iob.req.info, p_buff_out, + (uint8_t) iob.req.out_sz ); + _pcps_sem_dec( pddev ); + + if ( rc == MBG_SUCCESS ) + _frc_iob_to_pout( p_buff_out, iob.req.out_p, iob.req.out_sz ); + + _pcps_kfree( p_buff_out, iob.req.out_sz ); + + if ( mbg_rc_is_error( rc ) ) + goto err_access; + + #else + + _iob_from_pin_var( iob.ctl, pin ); + buffer_size = sizeof( iob.ctl ) + iob.ctl.data_size_out; + p_buff = _pcps_kmalloc( buffer_size ); + + if ( p_buff == NULL ) + goto err_no_mem; + + _pcps_sem_inc_safe( pddev ); + rc = _pcps_read( pddev, (uint8_t) iob.ctl.info, p_buff->data, + (uint8_t) iob.ctl.data_size_out ); + _pcps_sem_dec( pddev ); + + if ( rc == MBG_SUCCESS ) + { + p_buff->ctl = iob.ctl; + _iob_to_pout( p_buff, pout, buffer_size ); //##+++++++ need to check this !! + } + + _pcps_kfree( p_buff, buffer_size ); + + if ( mbg_rc_is_error( rc ) ) + goto err_access; + + #endif + break; + + + case IOCTL_PCPS_GENERIC_READ_GPS: + #if USE_IOCTL_GENERIC_REQ + _iob_from_pin_var( iob.req, pin ); + p_buff_out = _pcps_kmalloc( iob.req.out_sz ); + + if ( p_buff_out == NULL ) + { + _mbgddmsg_4( MBG_DBG_INFO, "%s: unable to alloc %lu bytes for %s, GPS cmd: %02lX", + pcps_driver_name, (ulong) iob.req.out_sz, + "IOCTL_PCPS_GENERIC_READ_GPS", (ulong) iob.req.info ); + goto err_no_mem; + } + + _pcps_sem_inc_safe( pddev ); + rc = pcps_read_gps( pddev, (uint8_t) iob.req.info, p_buff_out, + (uint16_t) iob.req.out_sz ); + _pcps_sem_dec( pddev ); + + if ( rc == MBG_SUCCESS ) + _frc_iob_to_pout( p_buff_out, iob.req.out_p, iob.req.out_sz ); + + _pcps_kfree( p_buff_out, iob.req.out_sz ); + + if ( mbg_rc_is_error( rc ) ) + goto err_access; + + #else + + _iob_from_pin_var( iob.ctl, pin ); + buffer_size = sizeof( iob.ctl ) + iob.ctl.data_size_out; + p_buff = _pcps_kmalloc( buffer_size ); + + if ( p_buff == NULL ) + goto err_no_mem; + + _pcps_sem_inc_safe( pddev ); + rc = pcps_read_gps( pddev, (uint8_t) iob.ctl.info, p_buff->data, + (uint16_t) iob.ctl.data_size_out ); + _pcps_sem_dec( pddev ); + + if ( rc == MBG_SUCCESS ) + { + p_buff->ctl = iob.ctl; + _iob_to_pout( p_buff, pout, buffer_size ); //##+++++++ need to check this !! + } + + _pcps_kfree( p_buff, buffer_size ); + + if ( mbg_rc_is_error( rc ) ) + goto err_access; + + #endif + break; + + #if _MBG_SUPP_VAR_ACC_SIZE // These codes are only supported on target systems where a variable size of @@ -1438,31 +1653,77 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, // generic IOCTL functions are used instead. case IOCTL_GET_GPS_ALL_STR_TYPE_INFO: - _io_read_gps_chk( pddev, PC_GPS_ALL_STR_TYPE_INFO, all_str_type_info, pout, + _io_read_gps_chk( pddev, PC_GPS_ALL_STR_TYPE_INFO, all_str_type_info_idx, pout, pout_size, _pcps_ddev_has_receiver_info( pddev ) ); break; case IOCTL_GET_GPS_ALL_PORT_INFO: - _io_read_gps_chk( pddev, PC_GPS_ALL_PORT_INFO, all_port_info, pout, + _io_read_gps_chk( pddev, PC_GPS_ALL_PORT_INFO, all_port_info_idx, pout, pout_size, _pcps_ddev_has_receiver_info( pddev ) ); break; case IOCTL_GET_GPS_ALL_POUT_INFO: - _io_read_gps_chk( pddev, PC_GPS_ALL_POUT_INFO, all_pout_info, pout, + _io_read_gps_chk( pddev, PC_GPS_ALL_POUT_INFO, all_pout_info_idx, pout, pout_size, _pcps_ddev_has_receiver_info( pddev ) ); break; case IOCTL_GET_ALL_PTP_UC_MASTER_INFO: - _io_read_gps_chk( pddev, PC_GPS_ALL_PTP_UC_MASTER_INFO, all_ptp_uc_master_info, + _io_read_gps_chk( pddev, PC_GPS_ALL_PTP_UC_MASTER_INFO, all_ptp_uc_master_info_idx, pout, pout_size, _pcps_ddev_has_ptp_unicast( pddev ) ); break; + + case IOCTL_GET_ALL_GPIO_INFO: + _io_read_gps_chk( pddev, PC_GPS_ALL_GPIO_INFO, all_gpio_info_idx, + pout, pout_size, _pcps_ddev_has_gpio( pddev ) ); + break; + + + case IOCTL_GET_ALL_GPIO_STATUS: + _io_read_gps_var_chk( pddev, PC_GPS_ALL_GPIO_STATUS, all_gpio_status_idx, + pout, _pcps_ddev_has_gpio( pddev ) ); //##++++++++++++++++++++++++ condition?? + break; + + + case IOCTL_GET_ALL_XMR_STATUS: + _io_read_gps_chk( pddev, PC_GPS_ALL_XMR_STATUS, all_xmulti_ref_status_idx, + pout, pout_size, _pcps_ddev_has_xmr( pddev ) ); + break; + + + case IOCTL_GET_ALL_XMR_INFO: + _io_read_gps_chk( pddev, PC_GPS_ALL_XMR_INFO, all_xmulti_ref_info_idx, + pout, pout_size, _pcps_ddev_has_xmr( pddev ) ); + break; + #endif // _MBG_SUPP_VAR_ACC_SIZE + case IOCTL_GET_GNSS_MODE_INFO: + _io_read_gps_var_chk( pddev, PC_GPS_GNSS_MODE, gnss_mode_info, + pout, _pcps_ddev_is_gnss( pddev ) ); + break; + + case IOCTL_GET_GPIO_CFG_LIMITS: + _io_read_gps_var_chk( pddev, PC_GPS_GPIO_CFG_LIMITS, mbg_gpio_cfg_limits, + pout, _pcps_ddev_has_gpio( pddev ) ); + break; + + case IOCTL_GET_XMR_INSTANCES: + _io_read_gps_var_chk( pddev, PC_GPS_XMR_INSTANCES, xmulti_ref_instances, + pout, _pcps_ddev_has_xmr( pddev ) ); + break; + + case IOCTL_GET_XMR_HOLDOVER_STATUS: + _io_read_gps_var_chk( pddev, PC_GPS_XMR_HOLDOVER_STATUS, xmr_holdover_status, + pout, _pcps_ddev_has_xmr( pddev ) ); + break; + + + // Codes writing device configuration case IOCTL_SET_PCPS_SERIAL: @@ -1582,6 +1843,19 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, break; + case IOCTL_SET_GNSS_MODE_SETTINGS: + _io_write_gps_var_chk( pddev, PC_GPS_GNSS_MODE, gnss_mode_settings, pin, + _pcps_ddev_is_gnss( pddev ) ); + break; + + + case IOCTL_SET_GPIO_SETTINGS_IDX: + _io_write_var_chk( pddev, PC_GPS_GPIO_SETTINGS_IDX, mbg_gpio_settings_idx, + pin, _pcps_ddev_has_gpio( pddev ) ); + break; + + + // Operations which may severely affect system operation case IOCTL_SET_PCPS_TIME: @@ -1622,62 +1896,13 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, break; - // Generic read/write operations which can do anything - - case IOCTL_PCPS_GENERIC_READ: - #if USE_IOCTL_GENERIC_REQ - _iob_from_pin_var( iob.req, pin ); - p_buff_out = _pcps_kmalloc( iob.req.out_sz ); - - if ( p_buff_out == NULL ) - { - _mbgddmsg_4( MBG_DBG_INFO, "%s: unable to alloc %lu bytes for %s, cmd: %02lX", - pcps_driver_name, (ulong) iob.req.out_sz, - "IOCTL_PCPS_GENERIC_READ", (ulong) iob.req.info ); - goto err_no_mem; - } - - _pcps_sem_inc_safe( pddev ); - rc = _pcps_read( pddev, (uint8_t) iob.req.info, p_buff_out, - (uint8_t) iob.req.out_sz ); - _pcps_sem_dec( pddev ); - - if ( rc == MBG_SUCCESS ) - _frc_iob_to_pout( p_buff_out, iob.req.out_p, iob.req.out_sz ); - - _pcps_kfree( p_buff_out, iob.req.out_sz ); - - if ( rc != MBG_SUCCESS ) - goto err_access; - - #else - - _iob_from_pin_var( iob.ctl, pin ); - buffer_size = sizeof( iob.ctl ) + iob.ctl.data_size_out; - p_buff = _pcps_kmalloc( buffer_size ); - - if ( p_buff == NULL ) - goto err_no_mem; - - _pcps_sem_inc_safe( pddev ); - rc = _pcps_read( pddev, (uint8_t) iob.ctl.info, p_buff->data, - (uint8_t) iob.ctl.data_size_out ); - _pcps_sem_dec( pddev ); - - if ( rc == MBG_SUCCESS ) - { - p_buff->ctl = iob.ctl; - _iob_to_pout( p_buff, pout, buffer_size ); //##+++++++ need to check this !! - } + case IOCTL_SET_XMR_SETTINGS_IDX: + _io_write_gps_var( pddev, PC_GPS_XMR_SETTINGS_IDX, xmulti_ref_settings_idx, pin ); + break; - _pcps_kfree( p_buff, buffer_size ); - if ( rc != MBG_SUCCESS ) - goto err_access; - - #endif - break; + // Generic read/write operations which can do anything case IOCTL_PCPS_GENERIC_WRITE: #if USE_IOCTL_GENERIC_REQ @@ -1692,7 +1917,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, goto err_no_mem; } - _frc_iob_from_pin( p_buff_in, pin, iob.req.in_sz ); + _frc_iob_from_pin( p_buff_in, iob.req.in_p, iob.req.in_sz ); _pcps_sem_inc_safe( pddev ); rc = pcps_write( pddev, (uint8_t) iob.req.info, p_buff_in, @@ -1701,7 +1926,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, _pcps_kfree( p_buff_in, iob.req.in_sz ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto err_access; #else @@ -1722,62 +1947,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, _pcps_kfree( p_buff, buffer_size ); - if ( rc != MBG_SUCCESS ) - goto err_access; - - #endif - break; - - - case IOCTL_PCPS_GENERIC_READ_GPS: - #if USE_IOCTL_GENERIC_REQ - _iob_from_pin_var( iob.req, pin ); - p_buff_out = _pcps_kmalloc( iob.req.out_sz ); - - if ( p_buff_out == NULL ) - { - _mbgddmsg_4( MBG_DBG_INFO, "%s: unable to alloc %lu bytes for %s, GPS cmd: %02lX", - pcps_driver_name, (ulong) iob.req.out_sz, - "IOCTL_PCPS_GENERIC_READ_GPS", (ulong) iob.req.info ); - goto err_no_mem; - } - - _pcps_sem_inc_safe( pddev ); - rc = pcps_read_gps( pddev, (uint8_t) iob.req.info, p_buff_out, - (uint16_t) iob.req.out_sz ); - _pcps_sem_dec( pddev ); - - if ( rc == MBG_SUCCESS ) - _frc_iob_to_pout( p_buff_out, iob.req.out_p, iob.req.out_sz ); - - _pcps_kfree( p_buff_out, iob.req.out_sz ); - - if ( rc != MBG_SUCCESS ) - goto err_access; - - #else - - _iob_from_pin_var( iob.ctl, pin ); - buffer_size = sizeof( iob.ctl ) + iob.ctl.data_size_out; - p_buff = _pcps_kmalloc( buffer_size ); - - if ( p_buff == NULL ) - goto err_no_mem; - - _pcps_sem_inc_safe( pddev ); - rc = pcps_read_gps( pddev, (uint8_t) iob.ctl.info, p_buff->data, - (uint16_t) iob.ctl.data_size_out ); - _pcps_sem_dec( pddev ); - - if ( rc == MBG_SUCCESS ) - { - p_buff->ctl = iob.ctl; - _iob_to_pout( p_buff, pout, buffer_size ); //##+++++++ need to check this !! - } - - _pcps_kfree( p_buff, buffer_size ); - - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto err_access; #endif @@ -1797,7 +1967,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, goto err_no_mem; } - _frc_iob_from_pin( p_buff_in, pin, iob.req.in_sz ); + _frc_iob_from_pin( p_buff_in, iob.req.in_p, iob.req.in_sz ); _pcps_sem_inc_safe( pddev ); rc = pcps_write_gps( pddev, (uint8_t) iob.req.info, p_buff_in, @@ -1806,7 +1976,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, _pcps_kfree( p_buff_in, iob.req.in_sz ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto err_access; #else @@ -1827,7 +1997,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, _pcps_kfree( p_buff, buffer_size ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto err_access; #endif @@ -1851,7 +2021,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, goto err_no_mem; } - _frc_iob_from_pin( p_buff_in, pin, iob.req.in_sz ); + _frc_iob_from_pin( p_buff_in, iob.req.in_p, iob.req.in_sz ); } else { @@ -1895,7 +2065,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, if ( p_buff_out ) _pcps_kfree( p_buff_out, iob.req.out_sz ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto err_access; #else @@ -1927,7 +2097,7 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, _pcps_kfree( p_buff, buffer_size ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto err_access; #endif @@ -1991,28 +2161,39 @@ int ioctl_switch( PCPS_DDEV *pddev, unsigned int ioctl_code, #endif // USE_DEBUG_PORT - default: + default: // Unknown IOCTL code goto err_inval; } + // We get here in case of success. return rc; err_inval: + // We get here if the IOCTL code is inappropriate + // for this target / OS. + // POSIX return code would probably be -ENODEV. return MBG_ERR_INV_DEV_REQUEST; err_support: + // We get here if the IOCTL code is inappropriate + // for this device. + // POSIX return code would be -ENOTTY. return MBG_ERR_NOT_SUPP_BY_DEV; err_no_mem: + // We get here if we were unable to allocate memory. + // POSIX return code would be -ENOMEM. return MBG_ERR_NO_MEM; err_busy_unsafe: return MBG_ERR_IRQ_UNSAFE; err_access: - return rc; // return the rc from the low level routine - + // We get here if device access failed. + // POSIX return code would probably be -EIO. + // Return the rc from the low level routine. + return rc; #if defined( USE_COPY_KERNEL_USER ) diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbg_arch.h b/src/external/bsd/meinberg/dist/mbglib/common/mbg_arch.h index ebfe035..a08ec76 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbg_arch.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbg_arch.h @@ -1,20 +1,28 @@ /************************************************************************** * - * $Id: mbg_arch.h 1.3.1.4 2011/06/27 16:12:59 martin TRASH $ + * $Id: mbg_arch.h 1.6 2017/01/27 09:03:16 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * * Description: * Definitions to support different computer hardware architectures. * + * For a good summary of predefined macros which can be used to determine + * the build environment, the target environment, and architecture, see: + * http://sourceforge.net/p/predef/wiki/Home/ + * * ----------------------------------------------------------------------- * $Log: mbg_arch.h $ - * Revision 1.3.1.4 2011/06/27 16:12:59 martin - * Revision 1.3.1.3 2011/04/12 12:55:28 martin - * Include words.h. - * Revision 1.3.1.2 2011/02/09 15:46:48 martin - * Revision 1.3.1.1 2011/02/09 15:26:58 martin + * Revision 1.6 2017/01/27 09:03:16 martin + * Added macros _mbg_swab8() and _mbg_swab64(). + * Fixed macro syntax. + * Modified _swab_dummy() to avoid compiler warnings due to unused variables. + * Revision 1.5 2014/03/11 16:01:55 martin + * Added a comment. + * Revision 1.4 2012/10/02 18:32:00 martin + * Include words.h and, conditionally, stdlib.h. + * Use generic preprocessor symbol MBG_TGT_KERNEL. * Revision 1.3 2009/06/12 13:12:37Z martin * Fixed compiler warning. * Revision 1.2 2009/03/19 15:14:15 martin @@ -66,7 +74,7 @@ // to access unaligned data. #if !defined( _mbg_put_unaligned ) - #define _mbg_put_unaligned( _v, _p ) ((void)( *(_p) = (_v) )) + #define _mbg_put_unaligned( _v, _p ) do { ((void)( *(_p) = (_v) )); } while ( 0 ) #endif #if !defined( _mbg_get_unaligned ) @@ -119,8 +127,9 @@ -// swap a double type variable bytewise e.g. to convert the endianess - +/** + * @brief Swap a 'double' type variable bytewise e.g. to convert the endianess + */ static __mbg_inline void mbg_swab_double( double *p ) { @@ -143,22 +152,27 @@ void mbg_swab_double( double *p ) #if defined( MBG_ARCH_BIG_ENDIAN ) - #define _mbg_swab16( _p ) *(_p) = __swab16( *(_p) ) - #define _mbg_swab32( _p ) *(_p) = __swab32( *(_p) ) + #define _mbg_swab8( _p ) _nop_macro_fnc() // always a dummy, but for completeness ... + #define _mbg_swab16( _p ) do { *(_p) = __swab16( *(_p) ); } while ( 0 ) + #define _mbg_swab32( _p ) do { *(_p) = __swab32( *(_p) ); } while ( 0 ) + #define _mbg_swab64( _p ) do { *(_p) = __swab64( *(_p) ); } while ( 0 ) #define _mbg_swab_double( _p ) mbg_swab_double( _p ) #define _mbg_swab_doubles( _p, _n ) \ + do \ { \ int i; \ for ( i = 0; i < (_n); i++ ) \ _mbg_swab_double( &_p[i] ); \ - } + } while ( 0 ) #else + #define _mbg_swab8( _p ) _nop_macro_fnc() #define _mbg_swab16( _p ) _nop_macro_fnc() #define _mbg_swab32( _p ) _nop_macro_fnc() + #define _mbg_swab64( _p ) _nop_macro_fnc() #define _mbg_swab_double( _p ) _nop_macro_fnc() @@ -166,4 +180,16 @@ void mbg_swab_double( double *p ) #endif + + + +/** + * @brief A placeholder for yet missing _mbg_swab_..() macros + * + * We don't just use the _nop_macro_fnc() macros here to avoid + * compiler warnings 'unused variable'. + */ +#define _mbg_swab_dummy( _x ) do { (void) _x; } while ( 0 ) + + #endif /* _MBG_ARCH_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbg_cof.h b/src/external/bsd/meinberg/dist/mbglib/common/mbg_cof.h new file mode 100755 index 0000000..ced7988 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbg_cof.h @@ -0,0 +1,83 @@ + +/************************************************************************** + * + * $Id: mbg_cof.h 1.2 2017/07/05 14:25:12 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Container macros (see Linux Kernel) + * + * ----------------------------------------------------------------------- + * $Log: mbg_cof.h $ + * Revision 1.2 2017/07/05 14:25:12 martin + * Reformatted code to conform to standard header file format. + * Changes tfor improved cross-platform compatibility. + * Revision 1.1 2015/09/09 10:42:27 martin + * Initial revision by philipp. + * + **************************************************************************/ + +#ifndef _MBG_COF_H +#define _MBG_COF_H + +/* Other headers to be included */ + +#include <mbg_tgt.h> + +#if !defined( MBG_TGT_KERNEL ) + #include <stddef.h> // for offsetof() +#endif + + +#ifdef _MBG_COF + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined( MBG_TGT_POSIX ) + + // A special construct supported by gcc/clang and and implemented + // e.g. in the Linux kernel, which is said to be very type-safe: + #define mbg_container_of( _ptr, _type, _member ) ({ \ + const typeof( ((_type *)0)->_member ) *__mptr = (_ptr); \ + (_type *)((char *)__mptr - offsetof(_type,_member));}) + +#else + + // A different implementation in ANSI C, which supports type-checking anyway: + #define mbg_container_of( _ptr, _type, _member ) \ + ( (_type *)( (char *)(1 ? (_ptr) : &((_type *)0)->_member) - offsetof( _type, _member ))) + +#endif + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + +/* (no header definitions found) */ + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _MBG_COF_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbg_tgt.h b/src/external/bsd/meinberg/dist/mbglib/common/mbg_tgt.h index a2eaaa2..2a63b1a 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbg_tgt.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbg_tgt.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbg_tgt.h 1.22.2.13 2011/06/22 07:51:03 martin TRASH $ + * $Id: mbg_tgt.h 1.36 2017/07/04 12:35:11 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,29 +11,121 @@ * * ----------------------------------------------------------------------- * $Log: mbg_tgt.h $ - * Revision 1.22.2.13 2011/06/22 07:51:03 martin + * Revision 1.36 2017/07/04 12:35:11 martin + * Fixed build for Windows kernel space. + * Don't define ssize_t if HAVE_SSIZE_T is already defined. + * Added definition for _NO_MBG_API. + * Fixed missing 'bool' type for old Linux kernels. + * Fixed missing 'struct timespec' for DOS. + * Evaluate preprocessor symbol KERNEL_HAS_BOOL to avoid + * compiler errors due to duplicate definitions in specific + * Linux kernels patched by the distro maintainers. + * Provide ssize_t for C++Builder 5. + * Improved Visual Studio version checking. + * New define MBG_TGT_HAS_NODE_NAME. + * Revision 1.35 2016/08/05 12:21:34 martin + * Conditionally define a macro _DEPRECATED_BY which can be used to + * tag functions as deprecated, so compilers can emit appropriate warnings. + * New symbol MBG_TGT_HAS_ABS64. + * Moved some compatibility definitions from gpsserio.h here. + * Define ssize_t for Windows, if required. + * Conditionally provided struct timespec for Windows. + * Added compatible 64 bit type print format specifiers. + * Include inttypes.h for all targets providing also stdint.h. + * Added some MSVC version code information. + * Fixes for FreeBSD. + * Fixed some spelling. + * Tmp workaround for 2.6.32-5-sparc64. + * Proper fix required. + * Revision 1.34.1.26 2016/08/05 10:38:10 martin + * Revision 1.34.1.25 2016/08/04 14:51:25Z martin + * Moved some compatibility definitions from gpsserio.h to mbg_tgt.h. + * Revision 1.34.1.24 2016/08/02 13:10:58 martin + * Define ssize_t for Windows, if required. + * Revision 1.34.1.23 2016/07/18 14:41:27Z martin + * New symbol MBG_TGT_HAS_ABS64. + * Revision 1.34.1.22 2016/07/14 09:00:58Z martin + * Conditionally provided struct timespec for Windows. + * Revision 1.34.1.21 2016/07/07 10:01:28Z martin + * Modified inclusion of Windows header files. + * Revision 1.34.1.20 2016/06/06 12:59:03 thomas-b + * Include all necessary Windows headers in the needed sequence + * Revision 1.34.1.19 2016/04/26 14:53:06 martin + * Revision 1.34.1.18 2016/04/26 13:31:08Z martin + * Added compatible 64 bit type print format specifiers. + * Revision 1.34.1.17 2016/04/25 14:46:20Z martin + * Include inttypes.h for all targets providing also stdint.h. + * Revision 1.34.1.16 2016/03/02 12:26:15 martin + * *** empty log message *** + * Revision 1.34.1.15 2016/02/26 09:12:11 paul + * Revision 1.34.1.14 2015/12/10 12:34:14Z martin + * *** empty log message *** + * Revision 1.34.1.13 2015/12/01 14:55:52 martin + * Revision 1.34.1.12 2015/12/01 14:54:08Z martin + * *** empty log message *** + * Revision 1.34.1.11 2015/12/01 14:52:20 martin + * *** empty log message *** + * Revision 1.34.1.10 2015/12/01 14:43:44 martin + * *** empty log message *** + * Revision 1.34.1.9 2015/12/01 13:55:09 martin + * Conditionally define a macro _DEPRECATED_BY which can be used to + * tag functions as deprecated, so compilers can emit appropriate warnings. + * Revision 1.34.1.8 2015/10/28 13:45:25 martin + * Added some MSVC version code information. + * Revision 1.34.1.7 2015/10/19 09:34:56 martin + * Fixed some spelling. + * Revision 1.34.1.6 2015/10/15 12:49:10 marvin + * Revision 1.34.1.5 2015/10/08 08:55:16Z martin + * Revision 1.34.1.4 2015/10/05 15:07:23Z marvin + * Unicode support. + * Revision 1.34.1.3 2015/09/21 08:58:27Z martin + * *** empty log message *** + * Revision 1.34.1.2 2015/09/18 14:53:25 martin + * Fixes for FreeBSD. + * Revision 1.34.1.1 2015/04/07 15:40:59 martin + * Tmp workaround for 2.6.32-5-sparc64. + * Proper fix required. + * Revision 1.34 2015/03/03 13:32:49 martin + * Provide __func__ for MS Visual Studio. + * Revision 1.33 2015/03/02 11:27:59Z martin + * Windows only: + * Define _CRT_SECURE_NO_WARNINGS to quiet compiler warnings. + * Define WIN32_LEAN_AND_MEAN only if it hasn't been defined before. + * Revision 1.32 2014/06/24 09:21:44 martin + * Update for newer C++Builder versions. + * Revision 1.31 2014/05/27 10:23:33 martin + * Finer control of which types are required for or already + * available on particular target systems. + * First definitions to support SunOS/Solaris. + * Revision 1.30 2014/04/01 12:55:58 martin + * Define MBG_TGT_WIN32 also for MS resource compiler. + * New target MBG_TGT_POSIX. + * Always include winsock2.h and windows.h for MBG_TGT_WIN32. + * Always include unistd.h for MBG_TGT_POSIX. + * Define empty __attribute__ macro for non-gcc environments. + * Revision 1.29 2013/02/01 14:50:46 martin + * Fixed a typo which caused an error under Borland CBuilder 5. + * Revision 1.28 2012/12/12 10:03:16Z martin + * Fix for Borland C 3.1. + * Revision 1.27 2012/11/29 12:03:14Z martin + * Moved definition of _no_macro_fnc() to words.h. + * Revision 1.26 2012/11/02 09:01:47Z martin + * Merged some stuff depending on the build environment here + * and cleaned up. + * Revision 1.25 2012/04/04 07:17:18 martin + * Treat QNX Neutrino as Unix target. + * Revision 1.24 2011/08/23 10:21:23 martin + * New symbol _NO_MBG_API_ATTR which can be used with functions + * which are going to be exported by a DLL, but actually aren't, yet. + * Revision 1.23 2011/08/19 10:47:00 martin + * Don't include stddef.h. + * Distinguish between different gcc target platforms. + * Initial support for IA64 platform. + * Support wchar_t for BSD. * Defined _NO_USE_PACK_INTF for Sparc and IA64. - * Revision 1.22.2.12 2011/04/12 15:36:00 martin - * Revision 1.22.2.11 2011/03/22 10:25:26Z martin * Fixed typo in comment. - * Revision 1.22.2.10 2011/02/09 15:46:48 martin - * Revision 1.22.2.9 2011/02/09 15:27:10 martin - * Revision 1.22.2.8 2011/02/04 10:15:54Z martin - * Revision 1.22.2.7 2011/02/01 17:11:54 martin - * Revision 1.22.2.6 2011/01/27 16:16:28 martin - * Support wchar_t for BSD. - * Revision 1.22.2.5 2011/01/24 17:08:40 martin - * Fixed build under FreeBSD. - * Revision 1.22.2.4 2010/12/14 11:04:02 martin - * Revision 1.22.2.3 2010/05/25 14:42:32Z martin - * Don't use MM I/O on IA64 platform. - * Revision 1.22.2.2 2010/05/21 13:09:35 martin - * Initial support for IA64 platform. - * Revision 1.22.2.1 2010/04/22 09:35:56 martin - * Distinguish between different gcc target platforms. * Revision 1.22 2009/10/01 08:20:50 martin * Fixed inline code support with different BC versions. - * Revision 1.1 2009/11/20 12:24:05 philipp * Revision 1.21 2009/09/01 10:34:23Z martin * Don't define __mbg_inline for CVI and undefined targets. * Revision 1.20 2009/08/18 15:14:26 martin @@ -60,9 +152,9 @@ * Recognize DOS target under Watcom compilers. * Flag Watcom C always supports wchar_t. * Revision 1.12 2008/01/17 09:38:50Z daniel - * Added macros to determine whether C language extensions + * Added macros to determine whether C language extensions * (e.g. C94, C99) are supported by the target environment. - * Added macro to check whether wchar_t and friends are + * Added macro to check whether wchar_t and friends are * supported, and some compatibility stuff. * Revision 1.11 2007/10/31 16:58:03 martin * Fixed __mbg_inline for Borland C (DOS). @@ -71,7 +163,7 @@ * Added MBG_PORT_HANDLE type for serial ports. * Added macros for unified inline code syntax. * Revision 1.9 2006/12/08 12:45:54Z martin - * Under Windows include ntddk.h rather than windows.h + * Under Windows include ntddk.h rather than windows.h * if building kernel driver . * Revision 1.8 2006/10/25 12:20:45Z martin * Initial support for FreeBSD, NetBSD, and OpenBSD. @@ -88,7 +180,7 @@ * Revision 1.3 2003/04/09 13:37:20Z martin * Added definition for _MBG_API. * Revision 1.2 2003/02/24 16:08:45Z martin - * Don't setup for Win32 PNP if explicitely configured non-PNP. + * Don't setup for Win32 PNP if explicitly configured non-PNP. * Revision 1.1 2002/02/19 13:46:20Z MARTIN * Initial revision * @@ -109,11 +201,21 @@ /* Start of header body */ -#if defined( _CVI ) || defined( _CVI_ ) +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined( _CVI_ ) - #define MBG_TGT_WIN32 #define MBG_TGT_CVI + #if defined( _NI_mswin_ ) + #define MBG_TGT_WIN32 + #else + #error Unsupported CVI target platform. + #endif + #elif defined( _WIN32_WINNT ) // MS platform SDK @@ -123,7 +225,7 @@ #if ( _WIN32_WINNT >= 0x0500 ) // Win2k and above #if !defined( MBG_TGT_WIN32_NON_PNP ) - // only if not explicitely disabled + // only if not explicitly disabled #define MBG_TGT_WIN32_PNP #endif #endif @@ -149,6 +251,11 @@ // MS Visual C++ #define MBG_TGT_WIN32 +#elif defined( RC_INVOKED ) + + //MS resource compiler + #define MBG_TGT_WIN32 + #elif defined( __WINDOWS_386__ ) // Watcom C/C++ for target Win32 @@ -189,6 +296,17 @@ // GCC for target OpenBSD #define MBG_TGT_OPENBSD +#elif defined( __sun ) // Oracle Solaris or other SunOS derived operating system + + // __SUNPRO_C Oracle Solaris Studio C compiler, __SUNPRO_C value is the version number + // __SUNPRO_CC Oracle Solaris Studio C++ compiler, __SUNPRO_CC value is the version number + // __sparc generate code for SPARC (R) architecture (32-bit or 64-bit) + // __sparcv9 generate code for 64-bit SPARC architecture + // __i386 generate code for 32-bit x86 architecture + // __amd64 generate code for 64-bit x64 architecture + + #define MBG_TGT_SUNOS + #elif defined( __QNX__ ) // any compiler for target QNX @@ -212,13 +330,48 @@ #endif -// Some definitions which depend on the type of compiler ... -#if defined( __GNUC__ ) - #define __mbg_inline __inline__ +#if defined( MBG_TGT_FREEBSD ) \ + || defined( MBG_TGT_NETBSD ) \ + || defined( MBG_TGT_OPENBSD ) + #define MBG_TGT_BSD + + #if defined( _KERNEL ) + #define MBG_TGT_KERNEL + #endif + +#endif + +#if defined( MBG_TGT_LINUX ) \ + || defined( MBG_TGT_BSD ) \ + || defined( MBG_TGT_QNX_NTO ) \ + || defined( MBG_TGT_SUNOS ) + + #define MBG_TGT_POSIX + #define MBG_TGT_UNIX +#endif + +#if defined( MBG_TGT_WIN32 ) + + #define _CRT_SECURE_NO_WARNINGS 1 + +#endif + + +// Some definitions depending on the build environment ... - #define MBG_TGT_HAS_WCHAR_T 1 +#if defined( __GNUC__ ) || defined( __clang__ ) + + #if defined( __clang__ ) + #define _CLANG_VERSION ( __clang_major__ * 10000 \ + + __clang_minor__ * 100 \ + + __clang_patchlevel__ ) + #endif // defined( __clang__ ) + + #define _GCC_VERSION ( __GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__ ) #if defined( __i386__ ) @@ -249,19 +402,301 @@ #endif + #if defined( MBG_TGT_LINUX ) + + #if defined( MBG_TGT_KERNEL ) + + #include <linux/types.h> + #include <linux/version.h> + + #if ( LINUX_VERSION_CODE <= KERNEL_VERSION( 2, 6, 4 ) ) || \ + ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 4 ) ) // must be true for 2.6.32-5-sparc64 + #define _ULONG_DEFINED 1 + #define _USHORT_DEFINED 1 + #define _UINT_DEFINED 1 + #endif + + // The 'bool' type is supported by the vanilla Linux kernel 2.6.19 and later. + // However, looks like at least the RedHat folks have backported this to 2.6.18, + // so KERNEL_HAS_BOOL can be defined to avoid a compiler error due to + // duplicate definition. + #if ( ( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 19 ) ) && !defined( KERNEL_HAS_BOOL ) ) + typedef _Bool bool; + #define bool bool + #endif + + // 'true' and 'false' are also defined by newer kernel versions + // as enum in linux/stddef.h, but may not be defined by + // older kernels. + + #else + + #include <stdint.h> + #include <inttypes.h> + #include <stdbool.h> + + #if defined( __u_char_defined ) + #define _ULONG_DEFINED 1 + #define _USHORT_DEFINED 1 + #define _UINT_DEFINED 1 + #endif + + #endif + + #define MBG_TGT_HAS_DEV_FN 1 + + #elif defined( MBG_TGT_BSD ) + + #if defined( MBG_TGT_KERNEL ) + #include <sys/types.h> + #else + #include <stdint.h> + #include <inttypes.h> + #include <stdbool.h> + #endif + + #define MBG_TGT_HAS_DEV_FN 1 + + #elif defined( MBG_TGT_QNX_NTO ) // QNX 6.x (Neutrino) + + #include <unistd.h> + #include <stdint.h> + #include <inttypes.h> + #include <stdbool.h> + + #else + + #include <stdint.h> + #include <inttypes.h> + #include <stdbool.h> + + #endif + + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + + #define MBG_TGT_HAS_WCHAR_T 1 + + + #if defined( __clang__ ) + #define _DEPRECATED_BY( _s ) __attribute__((deprecated("use \"" _s "\" instead"))) // works with clang 3.4.1 + #elif ( _GCC_VERSION > 40500 ) // gcc 4.5.0 and newer + #define _DEPRECATED_BY( _s ) __attribute__((deprecated("use \"" _s "\" instead"))) + #elif ( _GCC_VERSION > 30100 ) // gcc 3.1 and newer + #define _DEPRECATED_BY( _s ) __attribute__((deprecated)) + #else + // Not supported at all, use empty default definiton below. + #endif + + #if ( _GCC_VERSION > 30100 ) // gcc 3.1 and newer + #define __mbg_inline __inline__ __attribute__((always_inline)) + #else + // Not supported at all, use empty default definiton below. + #define __mbg_inline __inline__ + #endif + #elif defined( _MSC_VER ) + // Known predifined MS compiler version codes: + // 1910: MSVC++ 15.0 (Visual Studio 2017) + // 1900: MSVC++ 14.0 (Visual Studio 2015) + // 1800: MSVC++ 12.0 (Visual Studio 2013) + // 1700: MSVC++ 11.0 (Visual Studio 2012) + // 1600: MSVC++ 10.0 (Visual Studio 2010) + // 1500: MSVC++ 9.0 (Visual Studio 2008) + // 1400: MSVC++ 8.0 (Visual Studio 2005, Windows Server 2003 SP1 DDK - AMD64) + // 1310: MSVC++ 7.1 (Visual Studio .NET 2003, Windows Server 2003 DDK) + // 1300: MSVC++ 7.0 (Visual Studio .NET 2002, Windows XP SP1 DDK) + // 1200: MSVC++ 6.0 + // 1100: MSVC++ 5.0 + + // Enable this to get compile-time messages on the compiler version + #if 0 + #if ( _MSC_VER >= 1910 ) + #error >= 1910: MSVC++ 15.0 (Visual Studio 2017), or later + #elif ( _MSC_VER >= 1900 ) + #error 1900: MSVC++ 14.0 (Visual Studio 2015) + #elif ( _MSC_VER >= 1800 ) + #error 1800: MSVC++ 12.0 (Visual Studio 2013) + #elif ( _MSC_VER >= 1700 ) + #error 1700: MSVC++ 11.0 (Visual Studio 2012) + #elif ( _MSC_VER >= 1600 ) + #error 1600: MSVC++ 10.0 (Visual Studio 2010) + #elif ( _MSC_VER >= 1500 ) + #error 1500: MSVC++ 9.0 (Visual Studio 2008) + #elif ( _MSC_VER >= 1400 ) + #error STRINGIFY( _MSC_VER ) MSVC++ 8.0 (Visual Studio 2005, Windows Server 2003 SP1 DDK - AMD64) + #elif ( _MSC_VER >= 1310 ) + #error 1310: MSVC++ 7.1 (Visual Studio .NET 2003, Windows Server 2003 DDK) + #elif ( _MSC_VER >= 1300 ) + #error 1300: MSVC++ 7.0 (Visual Studio .NET 2002, Windows XP SP1 DDK) + #elif ( _MSC_VER >= 1200 ) + #error 1200: MSVC++ 6.0 + #elif ( _MSC_VER >= 1100 ) + #error 1100: MSVC++ 5.0 + #else + #error <1100: Older than MSVC 4 + #endif + #endif + + // "struct timespec" is supported only since VS2015 + // If it is then also the symbol TIME_UTC should be defined. + // Functions to read the current time as struct timespec + // are timespec_get() and friends, which are also only provided + // by VS2015 and later. + // As of VS2015, only TIME_UTC is supported to read + // the UTC system time, there is no equivalent for + // the POSIX CLOCK_MONOTONIC. However, QPC can be used + // to get monotonic time stamps and intervals. + #if ( _MSC_VER < 1900 ) + #if !defined( HAVE_STRUCT_TIMESPEC ) + #define MBG_TGT_MISSING_STRUCT_TIMESPEC 1 + #endif + #endif + + #if ( _MSC_VER >= 1600 ) + #include <stdint.h> + #include <inttypes.h> + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #else + #define MBG_TGT_HAS_INT_8_16_32 1 + #define MBG_PRE64_PREFIX "I64" + #endif + + #if !defined( __cplusplus ) + // no bool support anyway + #define MBG_TGT_MISSING_BOOL_TYPE 1 + #endif + + #define MBG_TGT_HAS_WCHAR_T 1 + #define __mbg_inline __forceinline - #define MBG_TGT_HAS_WCHAR_T 1 + // At least up to VS2008 the C99 builtin symbol __func__ + // is not supported. Some VS versions support __FUNCTION__ + // instead, but at least VC6 doesn't support this, either. + // of the current function instead. + #if ( _MSC_VER >= 1300 ) + #define __func__ __FUNCTION__ + #else + #define __func__ "func_???" + #endif + + // The "deprecated" attribute should be supported since Visual Studio 2005, + // but doesn't seem to be supported by the compiler shipped with the + // "Windows Server 2003 SP1 DDK", which is used to build kernel drivers + // and defines the same _MSC_VER number as VS2005. For now we assume + // that this is supported by compilers shipped with newer SDKs. + #if ( ( _MSC_VER >= 1500 ) || \ + ( ( _MSC_VER >= 1400 ) && !defined( _KDD_ ) ) ) + #define _DEPRECATED_BY( _s ) __declspec(deprecated("deprecated, use \"" _s "\"")) + #endif + + // availability of _abs64() + #if ( _MSC_VER >= 1310 ) + // This is supported at least since Visual Studio 2008 + // and Windows Server 2003 SP1 DDK. + #define MBG_TGT_HAS_ABS64 1 + #endif + + #if !defined ( HAVE_SSIZE_T ) -#elif defined( _CVI ) || defined( _CVI_ ) + // ssize_t support + #if ( _MSC_VER >= 1500 ) + // ssize_t may not be defined, but SSIZE_T is + #include <basetsd.h> + typedef SSIZE_T ssize_t; + #else + // At least VC6 hasn't SIZE_T, either, but size_t + // is typedef'ed as unsigned int, so we just typedef + // the signed variant here. + typedef int ssize_t; + #endif + + #define HAVE_SSIZE_T 1 - // Inline code is not supported. + #endif // !defined ( HAVE_SSIZE_T ) - #define MBG_TGT_HAS_WCHAR_T 0 +#elif defined( _CVI_ ) -#elif defined( __BORLANDC__ ) + // 1000 for CVI v10.0 (CVI 2010) + // 911 for CVI v9.1.1 (CVI 2009 SP1) + // 910 for CVI v9.1 (CVI 2009) + // 310 for CVI v3.1 + // 301 for CVI v3.0.1 + // 1 for CVI v3.0 + + #if ( _CVI_ >= 910 ) + // LabWindows/CVI 2009 is the first version providing stdint.h. + #include <stdint.h> + #include <inttypes.h> + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #else + #define USE_LONG_FOR_INT32 1 + #endif + + // As of LabWindows/CVI 2010, stdbool.h is still missing. + #define MBG_TGT_MISSING_BOOL_TYPE 1 + + #define MBG_TGT_HAS_WCHAR_T 0 + + // Inline code is not supported, though the inline keyword + // is silently accepted since CVI v9.0 + +#elif defined( __BORLANDC__ ) // or __CODEGEARC__ in newer versions + + // 0x0200 Borland C/C++ 2.0 + // 0x0400 Borland C/C++ 3.0 + // 0x0410 Borland C/C++ 3.1 + // 0x0550 Borland C/C++ 5.5 (C++Builder 5.0) + + // Next codes are in addition defined as __CODEGEARC__ + // See http://docwiki.embarcadero.com + + // 0x0570 for Borland Developer Studio 2006 (BDS 2006) + // 0x0590 for C++Builder 2007 + // 0x0591 for update 1 to C++Builder 2007 + // 0x0592 for RAD Studio 2007 + // 0x0593 for the December update to RAD Studio 2007 + // 0x0610 for C++Builder 2009 and for C++Builder 2009 Update 1 + // 0x0620 for C++Builder 2010 and for C++Builder 2010 Update 1 + // 0x0621 for C++Builder 2010 Update 2 + // 0x0630 for C++Builder XE + // 0x0631 for C++Builder XE Update 1 + // 0x0640 for C++Builder XE2 + // 0x0650 for C++Builder XE3 + + #if ( __BORLANDC__ >= 0x630 ) + // C++Builder XE starts to provide stdbool.h + #include <stdint.h> + #include <inttypes.h> + #include <stdbool.h> + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #elif ( __BORLANDC__ >= 0x570 ) + // BDS/Borland C++ Builder 2006 starts to provide at least stdint.h + #include <stdint.h> + #include <inttypes.h> + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #if !defined( __cplusplus ) + #define MBG_TGT_MISSING_BOOL_TYPE 1 + #endif + #elif ( __BORLANDC__ >= 0x0550 ) + #define MBG_TGT_HAS_INT_8_16_32 1 + #define MBG_PRE64_PREFIX "I64" + #if !defined( __cplusplus ) + #define MBG_TGT_MISSING_BOOL_TYPE 1 + #endif + #else // e.g. BC 3.1 or earlier + #if ( __BORLANDC__ <= 0x410 ) + #define MBG_TGT_MISSING_64_BIT_TYPES 1 + #define MBG_TGT_MISSING_BOOL_TYPE 1 + #define USE_LONG_FOR_INT32 1 + #define MBG_TGT_MISSING_STRUCT_TIMESPEC 1 + + typedef int ssize_t; + #endif + #endif + + #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) #if defined( __cplusplus ) #define __mbg_inline inline // standard C++ syntax @@ -271,41 +706,71 @@ #define __mbg_inline // up to BC3.1 not supported for C #endif - #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + #if !defined ( HAVE_SSIZE_T ) + typedef int ssize_t; // required at least for C++ Builder 5 + #define HAVE_SSIZE_T 1 + #endif #elif defined( __WATCOMC__ ) - #define __mbg_inline _inline + // 1050 v10.5 + // 1100 v11.0 + // 1200 Open Watcom C++ v1.0 + // 1230 Open Watcom C++ v1.3 + // 1270 Open Watcom C++ v1.7 - #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + #if defined( MBG_TGT_QNX ) // QNX 4.x -#endif + #include <sys/types.h> + #define MBG_TGT_MISSING_64_BIT_TYPES 1 + #elif ( __WATCOMC__ > 1230 ) // Open Watcom C 1.3 and above -#if defined( MBG_TGT_FREEBSD ) \ - || defined( MBG_TGT_NETBSD ) \ - || defined( MBG_TGT_OPENBSD ) - #define MBG_TGT_BSD + #include <stdint.h> + #include <inttypes.h> + + #elif !defined( __WATCOM_INT64__ ) // Watcom C 11 + + #define MBG_TGT_MISSING_64_BIT_TYPES 1 - #if defined( _KERNEL ) - #define MBG_TGT_KERNEL #endif + #define MBG_TGT_HAS_WCHAR_T defined( MBG_TGT_WIN32 ) + + #define __mbg_inline _inline + #endif -#if defined( MBG_TGT_LINUX ) \ - || defined( MBG_TGT_BSD ) \ - || defined( MBG_TGT_QNX_NTO ) - #define MBG_TGT_UNIX + +// If the build environment doesn't provide a inttypes.h file +// with print format specifiers for 64 bit fixed size types +// then MBG_PRE64_PREFIX should be defined which is used +// to define our own C99 compatible format specifiers. +// Eventually, similar definitions are required for 32, 16, +// and 8 bit fixed size types. +#if defined( MBG_PRE64_PREFIX ) + #define PRIi64 MBG_PRE64_PREFIX "i" + #define PRId64 MBG_PRE64_PREFIX "d" + #define PRIo64 MBG_PRE64_PREFIX "o" + #define PRIu64 MBG_PRE64_PREFIX "u" + #define PRIx64 MBG_PRE64_PREFIX "x" + #define PRIX64 MBG_PRE64_PREFIX "X" +#endif + +#if !defined( __GNUC__ ) && !defined( __attribute__ ) + #define __attribute__( _x ) #endif +#if !defined( _DEPRECATED_BY ) + #define _DEPRECATED_BY( _s ) // empty definition +#endif #if defined( MBG_TGT_WIN32 ) #if defined( _AMD64_ ) - // This is used for AMD64 architecture and for + // This is used for AMD64 architecture and for // Intel XEON CPUs with 64 bit extension. #define MBG_TGT_WIN32_PNP_X64 #define WIN32_FLAVOR "x64" @@ -317,9 +782,23 @@ #if defined( _KDD_ ) #define MBG_TGT_KERNEL #include <ntddk.h> + + #define _MBG_API #else // This must not be used for kernel drivers. + + // Prevent inclusion of obsolete winsock.h in windows.h + #if !defined( WIN32_LEAN_AND_MEAN ) + #define WIN32_LEAN_AND_MEAN 1 + #endif + #if !defined( _WINSOCKAPI_ ) + #define _WINSOCKAPI_ + #endif + #include <windows.h> + #include <winsock2.h> + #include <ws2tcpip.h> + typedef HANDLE MBG_HANDLE; #define MBG_INVALID_HANDLE INVALID_HANDLE_VALUE @@ -340,9 +819,15 @@ typedef DWORD DWORD_PTR; #endif - #endif + // socklen_t support + #if ( _MSC_VER < 1500 ) + // At least VS2008 has a socklen_t type + typedef int socklen_t; + #endif + + #define _MBG_API WINAPI - #define _MBG_API WINAPI + #endif #if defined( MBG_LIB_EXPORT ) #define _MBG_API_ATTR __declspec( dllexport ) @@ -350,7 +835,11 @@ #define _MBG_API_ATTR __declspec( dllimport ) #endif -#elif defined( MBG_TGT_UNIX ) +#elif defined( MBG_TGT_POSIX ) + + #if !defined( MBG_TGT_KERNEL ) + #include <unistd.h> + #endif typedef int MBG_HANDLE; typedef int MBG_PORT_HANDLE; @@ -367,6 +856,44 @@ #endif +/** + * @brief A socket file descriptor type + */ +#if defined( MBG_TGT_WIN32 ) + #if !defined( MBG_TGT_KERNEL ) // we don't need this in kernel space + // usually evaluates to UINT_PTR, which in turn evaluates + // to (unsigned int), or (unsigned __int64). + typedef SOCKET MBG_SOCK_FD; + #endif +#elif defined( MBG_TGT_POSIX ) + typedef int MBG_SOCK_FD; //### TODO + //### TODO typedef int SOCKET; +#endif + + + +/** + * @brief A value to mark an ::MBG_SOCK_FD as invalid + */ +#if defined( MBG_TGT_WIN32 ) + #define MBG_INVALID_SOCK_FD INVALID_SOCKET // usually evaluates to (SOCKET)(~0) since SOCKET is unsigned +#elif defined( MBG_TGT_POSIX ) + #define MBG_INVALID_SOCK_FD -1 +#endif + + + +/** + * @brief The return code of socket functions in case of error + */ +#if defined( MBG_TGT_WIN32 ) + #define MBG_SOCKET_ERR_RETVAL SOCKET_ERROR // usually evaluates to -1 +#elif defined( MBG_TGT_POSIX ) + #define MBG_SOCKET_ERR_RETVAL -1 +#endif + + + #if !defined( _MBG_API ) #define _MBG_API #endif @@ -375,6 +902,14 @@ #define _MBG_API_ATTR #endif +#if !defined( _NO_MBG_API ) + #define _NO_MBG_API +#endif + +#if !defined( _NO_MBG_API_ATTR ) + #define _NO_MBG_API_ATTR +#endif + #if !defined( MBG_INVALID_PORT_HANDLE ) #define MBG_INVALID_PORT_HANDLE MBG_INVALID_HANDLE #endif @@ -383,11 +918,22 @@ #define MBG_USE_MM_IO_FOR_PCI 0 #endif - -#if !defined( _nop_macro_fnc ) - #define _nop_macro_fnc() do {} while (0) +#if !defined( MBG_TGT_HAS_DEV_FN ) + #define MBG_TGT_HAS_DEV_FN 0 #endif +#if defined( MBG_TGT_MISSING_STRUCT_TIMESPEC ) + +#include <time.h> + + struct timespec + { + time_t tv_sec; + long tv_nsec; + }; + +#endif // defined( MBG_TGT_MISSING_STRUCT_TIMESPEC ) + // The macros below are defined in order to be able to check if // certain C language extensions are available on the target system: @@ -422,17 +968,6 @@ -/* End of header body */ - -#undef _ext - - -/* function prototypes: */ - -#ifdef __cplusplus -extern "C" { -#endif - /* ----- function prototypes begin ----- */ /* This section was generated automatically */ @@ -446,6 +981,8 @@ extern "C" { } #endif +/* End of header body */ -#endif /* _MBG_TGT_H */ +#undef _ext +#endif /* _MBG_TGT_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgddmsg.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgddmsg.h index 3f9a367..4517d7b 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbgddmsg.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgddmsg.h @@ -1,19 +1,25 @@ /************************************************************************** * - * $Id: mbgddmsg.h 1.9.1.1 2011/03/29 13:55:19 martin TRASH $ + * $Id: mbgddmsg.h 1.11 2017/07/05 14:31:23 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * * Description: - * Print or remove debug messages by redefinitions. + * Definitions and function prototypes to deal with messages + * generated by kernel mode drivers. Some type of messages are + * always generated, others are only generated ibn DEBUG builds + * and are defined void in release builds. * * ----------------------------------------------------------------------- * $Log: mbgddmsg.h $ - * Revision 1.9.1.1 2011/03/29 13:55:19 martin - * Also enable debug msgs if MBG_DEBUG is defined. - * Revision 1.9 2011/01/26 18:13:49 martin + * Revision 1.11 2017/07/05 14:31:23 martin + * Added _mbg_kdd_msg...() macros. + * Code cleanup. + * Updated function prototypes. + * Revision 1.10 2012/10/02 18:33:21Z martin * Support for *BSD. + * Also enable debug msgs if MBG_DEBUG is defined. * Revision 1.8 2009/04/22 09:54:55 martin * Include mbg_tgt.h also if building without DEBUG. * Revision 1.7 2009/03/19 15:22:54 martin @@ -38,104 +44,193 @@ #define _MBGDDMSG_H +/* Other headers to be included */ + #include <mbg_tgt.h> -#if defined( DEBUG ) || ( defined( DBG ) && DBG ) || defined( MBG_DEBUG ) +#if defined( MBG_TGT_NETWARE ) + #include <conio.h> +#elif defined( MBG_TGT_OS2 ) + #include <iprintf.h> +#elif defined( MBG_TGT_WIN32 ) + #include <ntddk.h> +#elif defined( MBG_TGT_LINUX ) + #include <linux/module.h> + #include <linux/version.h> +#elif defined( MBG_TGT_BSD ) + // nothing to include +#else // MBG_TGT_QNX, MBG_TGT_DOS, ... + //##+++++++++++++ + #include <stdio.h> +#endif -enum -{ - MBG_DBG_ERR, - MBG_DBG_WARN, - MBG_DBG_INFO, - MBG_DBG_DETAIL, - MBG_DBG_INIT_DEV, - MBG_DEBUG_SEM, - MBG_DBG_IRQ, - N_MBG_DBG_LVL -}; -extern int debug; +#ifdef _MBGDDMSG + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + +#ifdef __cplusplus +extern "C" { +#endif -#define _chk_lvl( _lvl ) ( (_lvl) < debug ) #if defined( MBG_TGT_NETWARE ) - #include <conio.h> #define _printf ConsolePrintf #define _hd #define _tl "\n" #elif defined( MBG_TGT_OS2 ) - #include <iprintf.h> #define _printf iprintf #define _hd #define _tl "\n" #elif defined( MBG_TGT_WIN32 ) - #include <ntddk.h> - #define _printf DbgPrint + #define _printf mbg_kdd_msg #define _hd - #define _tl "\n" + #define _tl + #define USE_MBG_KDD_MSG 1 #elif defined( MBG_TGT_LINUX ) - // #include <printk.h> - #define _printf printk - #define _hd KERN_INFO - #define _tl "\n" + #if ( LINUX_VERSION_CODE < KERNEL_VERSION( 2, 6, 8 ) ) + // vprintk not supported by the kernel + #define _printf printk + #define _hd KERN_INFO + #define _tl "\n" + #else + #define _printf mbg_kdd_msg + #define _hd KERN_NOTICE + #define _tl "\n" + #define USE_MBG_KDD_MSG 1 + #endif #elif defined( MBG_TGT_BSD ) #define _printf printf #define _hd #define _tl "\n" #else // MBG_TGT_QNX, MBG_TGT_DOS, ... - #include <stdio.h> #define _printf printf #define _hd #define _tl "\n" #endif -#define _mbgddmsg_0( _lvl, _fmt ) \ -do { \ - if ( _chk_lvl( _lvl ) ) \ - { _printf( _hd _fmt _tl ); } \ +#if !defined( USE_MBG_KDD_MSG ) + #define USE_MBG_KDD_MSG 0 +#endif + + +#define _mbg_kdd_msg_0( _fmt ) \ +do { \ + _printf( _hd _fmt _tl ); \ +} while ( 0 ) + +#define _mbg_kdd_msg_1( _fmt, _p1 ) \ +do { \ + _printf( _hd _fmt _tl, (_p1) ); \ +} while ( 0 ) + +#define _mbg_kdd_msg_2( _fmt, _p1, _p2 ) \ +do { \ + _printf( _hd _fmt _tl, (_p1), (_p2) ); \ +} while ( 0 ) + +#define _mbg_kdd_msg_3( _fmt, _p1, _p2, _p3 ) \ +do { \ + _printf( _hd _fmt _tl, (_p1), (_p2), (_p3) ); \ +} while ( 0 ) + +#define _mbg_kdd_msg_4( _fmt, _p1, _p2, _p3, _p4 ) \ +do { \ + _printf( _hd _fmt _tl, (_p1), (_p2), (_p3), (_p4) ); \ +} while ( 0 ) + +#define _mbg_kdd_msg_5( _fmt, _p1, _p2, _p3, _p4, _p5 ) \ +do { \ + _printf( _hd _fmt _tl, (_p1), (_p2), (_p3), (_p4), (_p5) ); \ +} while ( 0 ) + +#define _mbg_kdd_msg_6( _fmt, _p1, _p2, _p3, _p4, _p5, _p6 ) \ +do { \ + _printf( _hd _fmt _tl, (_p1), (_p2), (_p3), (_p4), (_p5), (_p6) ); \ +} while ( 0 ) + +#define _mbg_kdd_msg_7( _fmt, _p1, _p2, _p3, _p4, _p5, _p6, _p7 ) \ +do { \ + _printf( _hd _fmt _tl, (_p1), (_p2), (_p3), (_p4), (_p5), (_p6), (_p7) ); \ } while ( 0 ) -#define _mbgddmsg_1( _lvl, _fmt, _p1 ) \ + + +#if defined( DEBUG ) || ( defined( DBG ) && DBG ) || defined( MBG_DEBUG ) + +enum +{ + MBG_DBG_ERR, + MBG_DBG_WARN, + MBG_DBG_INFO, + MBG_DBG_DETAIL, + MBG_DBG_INIT_DEV, + MBG_DEBUG_SEM, + MBG_DBG_IRQ, + N_MBG_DBG_LVL +}; + + +#define _chk_lvl( _lvl ) ( (_lvl) < debug ) + +#define _mbgddmsg_0( _lvl, _fmt ) \ do { \ if ( _chk_lvl( _lvl ) ) \ - { _printf( _hd _fmt _tl, (_p1) ); } \ + { _mbg_kdd_msg_0( _fmt ); } \ } while ( 0 ) -#define _mbgddmsg_2( _lvl, _fmt, _p1, _p2 ) \ +#define _mbgddmsg_1( _lvl, _fmt, _p1 ) \ do { \ if ( _chk_lvl( _lvl ) ) \ - { _printf( _hd _fmt _tl, (_p1), (_p2) ); } \ + { _mbg_kdd_msg_1( _fmt, (_p1) ); } \ } while ( 0 ) -#define _mbgddmsg_3( _lvl, _fmt, _p1, _p2, _p3 ) \ +#define _mbgddmsg_2( _lvl, _fmt, _p1, _p2 ) \ do { \ if ( _chk_lvl( _lvl ) ) \ - { _printf( _hd _fmt _tl, (_p1), (_p2), (_p3) ); } \ + { _mbg_kdd_msg_2( _fmt, (_p1), (_p2) ); } \ } while ( 0 ) -#define _mbgddmsg_4( _lvl, _fmt, _p1, _p2, _p3, _p4 ) \ +#define _mbgddmsg_3( _lvl, _fmt, _p1, _p2, _p3 ) \ do { \ if ( _chk_lvl( _lvl ) ) \ - { _printf( _hd _fmt _tl, (_p1), (_p2), (_p3), (_p4) ); } \ + { _mbg_kdd_msg_3( _fmt, (_p1), (_p2), (_p3) ); } \ } while ( 0 ) -#define _mbgddmsg_5( _lvl, _fmt, _p1, _p2, _p3, _p4, _p5 ) \ +#define _mbgddmsg_4( _lvl, _fmt, _p1, _p2, _p3, _p4 ) \ do { \ if ( _chk_lvl( _lvl ) ) \ - { _printf( _hd _fmt _tl, (_p1), (_p2), (_p3), (_p4), (_p5) ); } \ + { _mbg_kdd_msg_4( _fmt, (_p1), (_p2), (_p3), (_p4) ); } \ } while ( 0 ) -#define _mbgddmsg_6( _lvl, _fmt, _p1, _p2, _p3, _p4, _p5, _p6 ) \ +#define _mbgddmsg_5( _lvl, _fmt, _p1, _p2, _p3, _p4, _p5 ) \ do { \ if ( _chk_lvl( _lvl ) ) \ - { _printf( _hd _fmt _tl, (_p1), (_p2), (_p3), (_p4), (_p5), (_p6) ); } \ + { _mbg_kdd_msg_5( _fmt, (_p1), (_p2), (_p3), (_p4), (_p5) ); } \ } while ( 0 ) -#define _mbgddmsg_7( _lvl, _fmt, _p1, _p2, _p3, _p4, _p5, _p6, _p7 ) \ +#define _mbgddmsg_6( _lvl, _fmt, _p1, _p2, _p3, _p4, _p5, _p6 ) \ do { \ if ( _chk_lvl( _lvl ) ) \ - { _printf( _hd _fmt _tl, (_p1), (_p2), (_p3), (_p4), (_p5), (_p6), (_p7) ); } \ + { _mbg_kdd_msg_6( _fmt, (_p1), (_p2), (_p3), (_p4), (_p5), (_p6) ); } \ +} while ( 0 ) + +#define _mbgddmsg_7( _lvl, _fmt, _p1, _p2, _p3, _p4, _p5, _p6, _p7 ) \ +do { \ + if ( _chk_lvl( _lvl ) ) \ + { _mbg_kdd_msg_7( _fmt, (_p1), (_p2), (_p3), (_p4), (_p5), (_p6), (_p7) ); } \ } while ( 0 ) #else @@ -151,4 +246,30 @@ do { #endif + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + __attribute__( ( format( printf, 1, 2 ) ) ) void mbg_kdd_msg( const char *fmt, ... ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + + +#undef _ext +#undef _DO_INIT + #endif /* _MBGDDMSG_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.c b/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.c index fb04f1d..a789add 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.c +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgdevio.c 1.35.1.25 2011/07/20 15:50:51 martin TRASH $ + * $Id: mbgdevio.c 1.39 2017/07/05 15:02:47 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,60 +10,81 @@ * * ----------------------------------------------------------------------- * $Log: mbgdevio.c $ - * Revision 1.35.1.25 2011/07/20 15:50:51 martin + * Revision 1.39 2017/07/05 15:02:47 martin + * Lots of new API functions provided by thomas-b, philipp, and martin. + * Fixed a potential buffer overflow in mbg_open_device_by_name(). + * Fixed a bug where XYZ and LLA were not written properly + * under target systems not using a kernel driver. + * Proper return codes from thread functions. + * PCPS_DEV * parameter for mbg_setup_receiver_info may now be NULL. + * New set of functions to determine if a specific feature is supported. + * The functions are named mbg_chk_dev_...(), are combined in a group + * mbgdevio_chk_supp_fncs, and replace and deprecate a set of older + * functions named mbg_chk_dev_(), which are collected in a group + * mbgdevio_chk_supp_fncs_deprecated. The new functions are much easier + * to be handled, and return a single, distinct return code which clearly + * tells if a feature is not supported, or an error occurred while trying + * to find this out. + * Older defines N_SUPP_DEV, PCPS_MAX_DDEVS, and MBG_MAX_DEVICES + * have been obsoleted by new defines N_SUPP_DEV_BUS, N_SUPP_DEV_EXT, + * and N_SUPP_DEV_TOTAL. + * Defined many macros in a safer way, and replaced some macros + * by inline functions. + * Improved doxygen comments. + * Revision 1.38 2013/11/08 15:04:54 martin + * Fixes for big endian targets. + * Revision 1.37 2013/09/26 08:54:22 martin + * Support GNSS API. + * Support mbg_open_device_by_name() on Unix. + * Updated doxygen comments. + * Revision 1.36 2012/10/02 18:37:09Z martin + * There are some g++ versions which fail to compile source code using + * the macros provided by Linux to define IOCTL codes. If only the API + * functions are called by an application then the IOCTL codes aren't + * required anyway, so we just avoid inclusion of mbgioctl.h in + * general and but include it when this module is built. + * Updated doxygen comments. + * New functions mbg_get_all_irig_rx_info() and + * mbg_save_all_irig_rx_settings(). + * Account for renamed macros. + * Support on-board event logs. + * New functions mbg_dev_has_debug_status() and + * mbg_get_debug_status(). + * Added a workaround to make mbgmon (BC) build under Windows. + * In mbg_get_serial_settings() return an error if the number of provided + * serial ports or supported string types exceeds the numbers supported + * by the driver. + * Moved mbg_get_serial_settings() and mbg_save_serial_settings() + * to an extra file. These functions expect parameters the sizes of + * which might change in future API versions, which would make + * functions exported by shared libraries incompatible across versions. + * Made functions mbg_get_gps_all_port_info() and + * mbg_get_gps_all_str_type_info() non-static so they are now exported + * by the shared libraries built from this module. + * Include cfg_hlp.h. * Conditionally use older IOCTL request buffer structures. * Moved some macros etc. to the .h file. - * Modified some macros. - * Revision 1.35.1.24 2011/07/14 14:54:00 martin * Modified generic IOCTL handling such that for calls requiring variable sizes * a fixed request block containing input and output buffer pointers and sizes is * passed down to the kernel driver. This simplifies implementation under *BSD * and also works for other target systems. - * Revision 1.35.1.23 2011/07/08 10:11:00 martin - * Fixes for DOS. - * Revision 1.35.1.22 2011/07/06 11:19:20Z martin * Support reading CORR_INFO, and reading/writing TR_DISTANCE. - * Revision 1.35.1.21 2011/06/29 11:09:55 martin * Added mbg_dev_has_pzf() function. - * Revision 1.35.1.20 2011/06/27 13:02:50 martin - * Use O_RDWR flag when opening a device. - * Revision 1.35.1.19 2011/06/24 11:13:36 martin - * Revision 1.35.1.18 2011/06/22 10:05:45 martin * Support PTP unicast configuration. * Account for some IOCTL codes renamed to follow common naming conventions. - * Revision 1.35.1.17 2011/04/12 12:56:20 martin * Renamed mutex stuff to critical sections. - * Revision 1.35.1.16 2011/03/31 13:18:46 martin - * Coding style. - * Revision 1.35.1.15 2011/02/16 10:15:13 martin - * Revision 1.35.1.14 2011/02/15 14:24:55Z martin - * Revision 1.35.1.13 2011/02/15 11:21:47 daniel * Added API calls to support PTP unicast. - * Revision 1.35.1.12 2011/02/09 17:08:28Z martin * Specify I/O range number when calling port I/O macros * so they can be used for different ranges under BSD. - * Revision 1.35.1.11 2011/02/01 15:08:08 martin - * Revision 1.35.1.10 2011/01/28 09:33:21 martin * Modifications to support FreeBSD. - * Revision 1.35.1.9 2010/12/14 11:23:47 martin * Moved definition of MBG_HW_NAME to the header file. - * Revision 1.35.1.8 2010/12/14 10:56:33Z martin - * Revision 1.35.1.7 2010/08/18 13:43:20 martin - * Revision 1.35.1.6 2010/08/11 13:48:52 martin - * Cleaned up comments. - * Revision 1.35.1.5 2010/08/11 12:43:51 martin - * Revision 1.35.1.4 2010/05/21 13:10:37 martin - * Fixed platforms where cycles are not supported. - * Revision 1.35.1.3 2010/04/26 14:46:41 martin * Compute PC cycles frequency under Linux if cpu_tick is not set by the kernel. - * Revision 1.35.1.2 2010/02/09 14:05:38 stefan - * Fixed a bug that kept the function mbg_open_device_by_name in a loop under certain conditions. - * Revision 1.35.1.1 2010/02/05 11:49:26 martin + * Fixed a bug that kept the function mbg_open_device_by_name in a loop under certain conditions. * Made xhrt leap second check an inline function. * Revision 1.35 2010/01/12 13:40:25 martin * Fixed a typo in mbg_dev_has_raw_irig_data(). * Revision 1.34 2009/12/15 15:34:58Z daniel - * Support reading the raw IRIG data bits for firmware versions + * Support reading the raw IRIG data bits for firmware versions * which support this feature. * Revision 1.33 2009/09/29 15:08:40Z martin * Support retrieving time discipline info. @@ -75,7 +96,7 @@ * Revision 1.30 2009/06/19 12:19:41Z martin * Support reading raw IRIG time. * Revision 1.29 2009/06/08 18:23:22 daniel - * Added PTP configuration functions and PTP state functions, but + * Added PTP configuration functions and PTP state functions, but * they are still excluded from build. * Added calls to support simple LAN interface configuration. * Revision 1.28 2009/03/19 15:30:04 martin @@ -91,30 +112,30 @@ * Account for renamed IOCTL codes. * Revision 1.27 2008/12/17 10:37:37 martin * Fixed a bug in mbg_open_device_by_name() with sel. mode MBG_MATCH_ANY. - * Support variable read buffer sizes under Linux, so + * Support variable read buffer sizes under Linux, so * mbg_get_all_port_info() and mbg_get_all_str_type_info() * can now be used under Linux. * Support PC cycles under Linux via inline rdtsc call. * Use predefined constants to convert fractions. - * New API calls mbg_get_fast_hr_timestamp_cycles(), and + * New API calls mbg_get_fast_hr_timestamp_cycles(), and * mbg_get_fast_hr_timestamp_comp() which take memory mapped HR time stamps - * in kernel space, and mbg_dev_has_fast_hr_timestamp() to check whether + * in kernel space, and mbg_dev_has_fast_hr_timestamp() to check whether * this is supported by a device. * Removed mm_*() functions since these are obsolete now. - * Support extrapolated HR time (xhrt) for Windows and Linux - * by providing a function mbg_xhrt_poll_thread_create() which + * Support extrapolated HR time (xhrt) for Windows and Linux + * by providing a function mbg_xhrt_poll_thread_create() which * starts a poll thread for a specific device which to read * HR time plus associated cycles in regular intervals. * Added functions mbg_get_process_affinity(), mbg_set_process_affinity(), - * and mbg_set_current_process_affinity_to_cpu(), and mbg_create_thread() + * and mbg_set_current_process_affinity_to_cpu(), and mbg_create_thread() * and mbg_set_thread_affinity() to control the extrapolation feature. * Use new preprocessor symbol MBGDEVIO_HAVE_THREAD_AFFINITY. * Added new functions mbg_get_xhrt_time_as_pcps_hr_time() and - * mbg_get_xhrt_time_as_filetime() (Windows only) to retrieve + * mbg_get_xhrt_time_as_filetime() (Windows only) to retrieve * fast extrapolated timestamps. - * Added function mbg_get_xhrt_cycles_frequency() to retrieve the + * Added function mbg_get_xhrt_cycles_frequency() to retrieve the * cycles counter frequency computed by the polling thread. - * Added function mbg_get_default_cycles_frequency_from_dev(), + * Added function mbg_get_default_cycles_frequency_from_dev(), * and mbg_get_default_cycles_frequency() (Windows only). * Moved mbg_open_device..() functions upwards. * Made device_info_list common. @@ -126,7 +147,7 @@ * Account Linux for device names renamed from /dev/mbgclk to /dev/mbgclock. * Support bigendian target platforms. * Revision 1.26 2008/02/26 16:54:21 martin - * New/changed functions for memory mapped access which are + * New/changed functions for memory mapped access which are * currently excluded from build. * Changed separator for device names from ' ' to '_'. * Added new type MBG_HW_NAME. @@ -141,10 +162,10 @@ * Revision 1.23 2008/01/30 10:32:35Z daniel * Renamed mapped memory funtions. * Revision 1.22 2008/01/25 15:27:42Z daniel - * Fixed a bug in mbg_get_hr_time_comp() where an overflow + * Fixed a bug in mbg_get_hr_time_comp() where an overflow * of the fractions was handled with wrong sign. * Revision 1.21 2008/01/17 15:49:59Z daniel - * Added functions mbg_find_devices_with_hw_id() and + * Added functions mbg_find_devices_with_hw_id() and * mbg_free_devics_list() to work with Linux Win32 OSs. * Added Doxygen compliant comments for API functions. * Support for mapped memory I/O under linux and windows. @@ -181,27 +202,27 @@ * Unified macros for Win32 and Linux. * Fixed warning under Win32 using type cast. * Revision 1.15 2005/01/31 16:44:21Z martin - * Added function mbg_get_hr_time_comp() which returns HR time stamp + * Added function mbg_get_hr_time_comp() which returns HR time stamp * which has latency compensated. * Revision 1.14 2005/01/14 10:22:23Z martin * Added functions which query device features. * Revision 1.13 2004/12/09 11:23:59Z martin * Support configuration of on-board frequency synthesizer. * Revision 1.12 2004/11/09 14:11:07Z martin - * Modifications were required in order to be able to configure IRIG + * Modifications were required in order to be able to configure IRIG * settings of cards which provide both IRIG input and output. - * Renamed functions mbg_get_irig_info() and mbg_set_irig_settings() - * to mbg_get_irig_rx_info() and mbg_set_irig_rx_settings() + * Renamed functions mbg_get_irig_info() and mbg_set_irig_settings() + * to mbg_get_irig_rx_info() and mbg_set_irig_rx_settings() * New functions mbg_get_irig_tx_info() and mbg_set_irig_tx_settings(). * All API functions now use well defined parameter types instead of * generic types. Some new types have been defined therefore. * Added a workaround for GPS169PCI cards with early firmware versions - * which used the same codes to configure the IRIG output as the TCR - * cards use to configure the IRIG input. Those codes are now + * which used the same codes to configure the IRIG output as the TCR + * cards use to configure the IRIG input. Those codes are now * exclusively used to configure the IRIG input. The workaround - * has been included in order to let GPS169PCI cards work properly + * has been included in order to let GPS169PCI cards work properly * after a driver update, without requiring a firmware update. - * The macro _pcps_ddev_requires_irig_workaround() is used to check + * The macro _pcps_ddev_requires_irig_workaround() is used to check * if the workaround is required. * Renamed function mbg_get_gps_stat() to mbg_get_gps_bvar_stat(). * Revision 1.11 2004/08/17 11:13:45Z martin @@ -224,7 +245,7 @@ * New functions mbgdevio_get_version() and mbgdevio_check_version(). * New functions for generic read/write access. * New functions mbg_get_pcps_tzdl() and mbg_set_pcps_tzdl(). - * Fixed a bug passing the wrong command code to a + * Fixed a bug passing the wrong command code to a * direct access target in mbg_get_sync_time(). * Return driver info for direct access targets. * Include pcpsdrvr.h and pcps_dos.h, if applicable. @@ -242,15 +263,15 @@ * Extended macro calls for direct access targets. * Updated macros for Linux. * Revision 1.5 2003/04/15 19:35:25Z martin - * New functions mbg_setup_receiver_info(), + * New functions mbg_setup_receiver_info(), * mbg_get_serial_settings(), mbg_save_serial_settings(). * Revision 1.4 2003/04/09 16:07:16Z martin * New API functions mostly complete. * Use renamed IOCTL codes from mbgioctl.h. - * Added DllEntry function foe Win32. + * Added DllEntry function for Win32. * Made MBG_Device_count and MBG_Device_Path local. * Revision 1.3 2003/01/24 13:44:40Z martin - * Fixed get_ref_time_from_driver_at_sec_change() to be used + * Fixed get_ref_time_from_driver_at_sec_change() to be used * with old kernel drivers. * Revision 1.2 2002/09/06 11:04:01Z martin * Some old API functions have been replaced by new ones @@ -266,20 +287,24 @@ #include <mbgdevio.h> #undef _MBGDEVIO -#include <parmpcps.h> -#include <parmgps.h> +#include <mbgutil.h> #include <gpsutils.h> #include <mbgerror.h> +#include <cfg_hlp.h> +#include <str_util.h> #if defined( MBG_TGT_DOS_PM ) #include <mbg_dpmi.h> #endif -#if !defined( MBG_USE_KERNEL_DRIVER ) +#if defined( MBG_USE_KERNEL_DRIVER ) + + #include <mbgioctl.h> + +#else #include <pcpsdrvr.h> #include <pci_asic.h> - #include <stdio.h> static PCPS_DRVR_INFO drvr_info = { MBGDEVIO_VERSION, 0, "MBGDEVIO direct" }; @@ -287,18 +312,6 @@ -#define MAX_INFO_LEN 260 - -typedef struct -{ - MBG_HW_NAME hw_name; - char model_name[PCPS_CLOCK_NAME_SZ]; - PCPS_SN_STR serial_number; - char hardware_id[MAX_INFO_LEN]; // OS dependent hardware_id to identify and open the device -} MBG_DEVICE_INFO; - - - // target specific code for different environments #if defined( MBG_TGT_WIN32 ) @@ -306,20 +319,22 @@ typedef struct #include <mbgsvctl.h> #include <mbgnames.h> #include <pci_asic.h> - #include <mbgutil.h> //##++ + #include <mbgutil.h> #include <timecnv.h> #include <pcpsutil.h> #include <tchar.h> #include <stdio.h> -#elif defined( MBG_TGT_UNIX ) +#elif defined( MBG_TGT_POSIX ) && !defined( MBG_TGT_QNX_NTO ) #include <unistd.h> #include <stdlib.h> #include <string.h> - #include <stdio.h> // sprintf() - #include <sys/mman.h> + + #if defined( DEBUG ) + #include <stdio.h> // printf() debug output + #endif #else // other target OSs which access the hardware directly @@ -343,12 +358,6 @@ typedef struct #define _pcps_write_gps_var_safe _pcps_write_gps_var #endif - #define _mbgdevio_chk_cond( _cond ) \ - { \ - if ( !(_cond) ) \ - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV ); \ - } - #endif // end of target specific code @@ -371,122 +380,2771 @@ typedef struct #define _mbgdevio_read_chk( _dh, _cmd, _ioctl, _p, _sz, _cond ) \ +do \ { \ _mbgdevio_chk_cond( _cond ); \ rc = _do_mbgdevio_read( _dh, _cmd, _ioctl, _p, _sz ); \ -} +} while ( 0 ) #define _mbgdevio_read_var_chk( _dh, _cmd, _ioctl, _p, _cond ) \ +do \ { \ _mbgdevio_chk_cond( _cond ); \ rc = _mbgdevio_read_var( _dh, _cmd, _ioctl, _p ); \ -} +} while ( 0 ) #define _mbgdevio_write_var_chk( _dh, _cmd, _ioctl, _p, _cond ) \ +do \ { \ _mbgdevio_chk_cond( _cond ); \ rc = _mbgdevio_write_var( _dh, _cmd, _ioctl, _p ); \ -} +} while ( 0 ) #define _mbgdevio_write_cmd_chk( _dh, _cmd, _ioctl, _cond ) \ +do \ { \ _mbgdevio_chk_cond( _cond ); \ rc = _mbgdevio_write_cmd( _dh, _cmd, _ioctl ); \ -} +} while ( 0 ) #define _mbgdevio_read_gps_chk( _dh, _cmd, _ioctl, _p, _sz, _cond ) \ +do \ { \ _mbgdevio_chk_cond( _cond ); \ rc = _do_mbgdevio_read_gps( _dh, _cmd, _ioctl, _p, _sz ); \ -} +} while ( 0 ) #define _mbgdevio_read_gps_var_chk( _dh, _cmd, _ioctl, _p, _cond ) \ +do \ { \ _mbgdevio_chk_cond( _cond ); \ rc = _mbgdevio_read_gps_var( _dh, _cmd, _ioctl, _p ); \ -} +} while ( 0 ) #define _mbgdevio_write_gps_var_chk( _dh, _cmd, _ioctl, _p, _cond ) \ +do \ { \ _mbgdevio_chk_cond( _cond ); \ rc = _mbgdevio_write_gps_var( _dh, _cmd, _ioctl, _p ); \ -} +} while ( 0 ) #if defined( _MBGIOCTL_H ) - #define _mbgdevio_query_cond( _dh, _cond, _ioctl, _p ) \ - { \ - _mbgdevio_vars(); \ - rc = _mbgdevio_read_var( _dh, -1, _ioctl, _p ); \ - return _mbgdevio_ret_val; \ - } - #define _mbgdevio_query_ri_cond _mbgdevio_query_cond + #define _mbgdevio_old_query_cond( _dh, _cond, _ioctl, _p ) \ + MBGDEVIO_RET_VAL rc; \ + rc = _mbgdevio_read_var( _dh, -1, _ioctl, _p ); \ + return _mbgdevio_cnv_ret_val( rc ) + + #define _mbgdevio_old_query_ri_cond _mbgdevio_old_query_cond + #else - #define _mbgdevio_query_cond( _dh, _cond, _ioctl, _p ) \ - { \ - *p = _cond( _dh ); \ - return MBG_SUCCESS; \ + + #define _mbgdevio_old_query_cond( _dh, _cond, _ioctl, _p ) \ + *p = _cond( _dh ); \ + return MBG_SUCCESS + + #define _mbgdevio_old_query_ri_cond( _dh, _cond, _ioctl, _p ) \ + *p = _cond( _ri_addr( _dh ) ); \ + return MBG_SUCCESS + +#endif + + + +#if defined( _MBGIOCTL_H ) + +static +int do_ioctl_chk_dev_feat( MBG_DEV_HANDLE dh, uint32_t feat_req_type, uint32_t feat_num ) +{ + MBGDEVIO_RET_VAL rc; + IOCTL_DEV_FEAT_REQ req; + req.feat_req_type = feat_req_type; + req.feat_num = feat_num; + rc = _do_mbg_ioctl( dh, IOCTL_CHK_DEV_FEAT, + &req, sizeof( req ), 0 ); + return _mbgdevio_cnv_ret_val( rc ); + +} // do_ioctl_chk_dev_feat + +#endif // defined( _MBGIOCTL_H ) + + + +static __mbg_inline +/** + * @brief Generic function to determine if a specific feature is supported + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] feat_type One of the defined ::DEV_FEAT_REQ_TYPES. + * @param[in] feat_num A feature number with range and meaning depending on the value of feat_type. + * + * @return ::MBG_SUCCESS if the requested feature is supported, see @ref mbgdevio_chk_supp_fncs + * + * @ingroup mbgdevio_chk_supp_fncs + * @see @ref mbgdevio_chk_supp_fncs + * @see ::mbgdevio_chk_dev_feat_deprecated (which is deprecated) + */ +int mbgdevio_chk_dev_feat( MBG_DEV_HANDLE dh, uint32_t feat_type, uint32_t feat_num ) +{ + #if defined( _MBGIOCTL_H ) + + // Use an IOCTL call to retrieve the information + // from the kernel driver. + return do_ioctl_chk_dev_feat( dh, feat_type, feat_num ); + #else + // This target doesn't use a kernel driver, so we retrieve + // the information directly from the device info structure. + return pcps_chk_dev_feat( dh, feat_type, feat_num ); + #endif + +} // mbgdevio_chk_dev_feat + + + +static __mbg_inline +/** + * @brief Deprecated generic function to determine if a specific feature is supported + * + * @deprecated This function is deprecated, use ::mbgdevio_chk_dev_feat preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] feat_type One of the defined ::DEV_FEAT_REQ_TYPES. + * @param[in] feat_num A feature number with range and meaning depending on the value of feat_type. + * @param[out] p Pointer to an int which is updated if the API call succeeds, i.e ::MBG_SUCCESS is returned + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS if feature request could be executed without error + * and *p was updated accordingly, see @ref mbgdevio_chk_supp_fncs_deprecated + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see @ref mbgdevio_chk_supp_fncs_deprecated + * @see ::mbgdevio_chk_dev_feat which should be used preferably + */ +int mbgdevio_chk_dev_feat_deprecated( MBG_DEV_HANDLE dh, uint32_t feat_type, uint32_t feat_num, int *p ) +{ + // Emulate the behavior of old feature-check functions. + int rc = mbgdevio_chk_dev_feat( dh, feat_type, feat_num ); + + // If we could definitely determine if the requested feature + // is supported or not then we accordingly update the integer + // variable the address of which has been passed by the caller, + // and return MBG_SUCCESS since we could determine the information + // successfully. + if ( mbg_rc_is_success( rc ) || ( rc == MBG_ERR_NOT_SUPP_BY_DEV ) ) + { + *p = mbg_rc_is_success( rc ); + return MBG_SUCCESS; } - #define _mbgdevio_query_ri_cond( _dh, _cond, _ioctl, _p ) \ - { \ - *p = _cond( &(_dh)->ri ); \ - return MBG_SUCCESS; \ + // If we get here then there was some error when we tried to + // determine the requested information, e.g. an IOCTL error + // when accessing the kernel driver, so we return the associated + // error code. + return rc; + +} // mbgdevio_chk_dev_feat_deprecated + + + +#if defined( _MBGIOCTL_H ) + + #define _mbgdevio_new_query_condx( _dh, _cond, _ioctl ) \ + { \ + MBGDEVIO_RET_VAL rc; \ + int _flag = 0; \ + rc = _mbgdevio_read_var( _dh, -1, _ioctl, &_flag ); \ + \ + if ( rc == MBG_SUCCESS ) /* no IOCTL error */ \ + if ( _flag == 0 ) /* if returned value is 0 */ \ + rc = MBG_ERR_NOT_SUPP_BY_DEV; /* not supp. */ \ + \ + /* success or IOCTL error */ \ + return _mbgdevio_cnv_ret_val( rc ); \ } + +#else + + #define _mbgdevio_new_query_condx( _dh, _cond, _ioctl ) \ + return _cond( _dh ) ? MBG_SUCCESS : MBG_ERR_NOT_SUPP_BY_DEV + #endif +// ### FIXME +#define _mbgdevio_new_query_cond _mbgdevio_new_query_condx + + static MBG_PC_CYCLES_FREQUENCY pc_cycles_frequency; -static MBG_DEVICE_INFO device_info_list[MBG_MAX_DEVICES]; -#if defined( MBG_TGT_WIN32 ) +/*HDR*/ +/** + * @brief Get the version number of the precompiled DLL/shared object library + * + * If this library is used as a DLL/shared object library then the version + * number can be checked to see if the header files which are actually used + * to build an application are compatible with the header files which have + * been used to build the library, and thus the API function are called + * in the correct way. + * + * @return The version number + * + * @see ::mbgdevio_check_version + * @see ::MBGDEVIO_VERSION defined in mbgdevio.h + */ +_MBG_API_ATTR int _MBG_API mbgdevio_get_version( void ) +{ + return MBGDEVIO_VERSION; + +} // mbgdevio_get_version + -// We don't move this as inline function to mbgdevio.h for now -// since this function calls mbgsvctl_log_mbgdevio_error() which -// is defined in mbgsvctl.h, and including mbgsvc.h from within -// mbgdevio.h results in DLL import/export mismatches. /*HDR*/ -MBGDEVIO_RET_VAL do_mbg_ioctl( MBG_DEV_HANDLE dh, int ioctl_code, - const void *in_p, int in_sz, void *out_p, int out_sz ) +/** + * @brief Check if the DLL/shared library is compatible with a given version + * + * If this library is used as a DLL/shared object library then the version + * number can be checked to see if the header files which are actually used + * to build an application are compatible with the header files which have + * been used to build the library, and thus the API functions are called + * in the correct way. + * + * @param[in] header_version Version number to be checked, should be ::MBGDEVIO_VERSION + * from the mbgdevio.h file version used to build the application + * + * @return ::MBG_SUCCESS if compatible, else ::MBG_ERR_LIB_NOT_COMPATIBLE + * + * @see ::mbgdevio_get_version + * @see ::MBGDEVIO_VERSION defined in mbgdevio.h + */ +_MBG_API_ATTR int _MBG_API mbgdevio_check_version( int header_version ) { - DWORD ReturnedLength; + if ( header_version >= MBGDEVIO_COMPAT_VERSION ) + return MBG_SUCCESS; + + return MBG_ERR_LIB_NOT_COMPATIBLE; + +} // mbgdevio_check_version + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::RECEIVER_INFO structure and related calls. + * + * Very old devices may not provide a ::RECEIVER_INFO structure. + * The ::mbg_setup_receiver_info call should be used preferably to set up + * a ::RECEIVER_INFO for a device. That function uses this call to determine + * whether a ::RECEIVER_INFO can be read directly from a device, or sets up + * a default structure using default values depending on the device type. + * + * @note This function should be preferred over ::mbg_dev_has_receiver_info, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_setup_receiver_info + * @see ::mbg_get_gps_receiver_info + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_receiver_info( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_PCPS, PCPS_BIT_HAS_RECEIVER_INFO ); + +} // mbg_chk_dev_has_receiver_info + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_receiver_info; - if ( !DeviceIoControl( dh, ioctl_code, - (LPVOID) in_p, in_sz, out_p, out_sz, - &ReturnedLength, - NULL - ) ) - { - DWORD rc = GetLastError(); - // do not report a USB device timeout error - if ( rc != _mbg_err_to_os( MBG_ERR_USB_ACCESS ) ) - mbgsvctl_log_mbgdevio_error( ioctl_code, rc ); +/*HDR*/ +/** + * @brief Check if a device supports large configuration data structures. + * + * Such structures have been introduced with the first Meinberg GPS receivers. + * Mostly all configuration structures are large data structures, and mostly all + * current devices support this, but some old devices may not. + * + * @note This function should be preferred over ::mbg_dev_has_gps_data, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_gps_data( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_PCPS, PCPS_BIT_HAS_GPS_DATA_16 ); + +} // mbg_chk_dev_has_gps_data + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_gps_data; + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_generic_io API call. + * + * <b>Warning</b>: This call is for debugging purposes and internal use only! + * + * @note This function should be preferred over ::mbg_dev_has_generic_io, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_generic_io + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_generic_io( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_PCPS, PCPS_BIT_HAS_GENERIC_IO ); + +} // mbg_chk_dev_has_generic_io + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_generic_io; + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_get_asic_version API call. + * + * If ::mbg_get_asic_version is supported, or not, depends on + * the bus interface chip assembled on the device. + * + * @note This function should be preferred over ::mbg_dev_has_asic_version, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_asic_version + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_asic_version( MBG_DEV_HANDLE dh ) +{ + // TODO return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_PCPS, ... ); + _mbgdevio_new_query_condx( dh, _pcps_ddev_has_asic_version, IOCTL_DEV_HAS_PCI_ASIC_VERSION ); + +} // mbg_chk_dev_has_asic_version + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_asic_version; + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_get_asic_features call. + * + * If ::mbg_get_asic_features is supported, or not, depends on + * the bus interface chip assembled on the device. + * + * @note This function should be preferred over ::mbg_dev_has_asic_features, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_asic_features + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_asic_features( MBG_DEV_HANDLE dh ) +{ + // TODO return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_PCPS, ... ); + _mbgdevio_new_query_condx( dh, _pcps_ddev_has_asic_features, IOCTL_DEV_HAS_PCI_ASIC_FEATURES ); + +} // mbg_chk_dev_has_asic_features + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_asic_features; + + + +/*HDR*/ +/** + * @brief Check if a device provides eXtended Multi Ref (XMR) inputs. + * + * Devices providing XMR inputs can receive or decode different timing + * signals in parallel, and the supported sources can be prioritized. + * + * @note This function should be preferred over ::mbg_dev_has_xmr, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_xmr_instances + * @see ::mbg_get_gps_all_xmr_status + * @see ::mbg_get_gps_all_xmr_info + * @see ::mbg_set_gps_xmr_settings_idx + * @see ::mbg_get_xmr_holdover_status + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_xmr( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_RI, GPS_HAS_XMULTI_REF ); + +} // mbg_chk_dev_has_xmr + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_xmr; + + + +static /*HDR*/ +/** + * @brief Check if device is a specific bus type + * + * This function checks if the bus flags associated with + * the device match the requested flags. This can be used e.g. + * to distinguish if a device is a PCI or USB device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] bus_flag_mask The bus flags to be tested, see @ref PCPS_BUS_FLAG_MASKS + * + * @return ::MBG_SUCCESS if the bus flags match, else ::MBG_ERR_NOT_SUPP_BY_DEV + * + * @see @ref PCPS_BUS_FLAG_MASKS + */ +int chk_bus_flags( MBG_DEV_HANDLE dh, int bus_flag_mask ) +{ + PCPS_DEV dev_info; + + int rc = mbg_get_device_info( dh, &dev_info ); + + if ( mbg_rc_is_error( rc ) ) return rc; - } - return MBG_SUCCESS; + return ( dev_info.type.bus_flags & bus_flag_mask ) ? MBG_SUCCESS : MBG_ERR_NOT_SUPP_BY_DEV; + +} // chk_bus_flags + + + +/*HDR*/ +/** + * @brief Check if the device is connected via the ISA bus + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the device is connected via the ISA bus, + * else ::MBG_ERR_NOT_SUPP_BY_DEV + * + * @ingroup mbgdevio_chk_supp_fncs + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_isa( MBG_DEV_HANDLE dh ) +{ + return chk_bus_flags( dh, PCPS_BUS_ISA ); + +} // mbg_chk_dev_is_isa + +MBG_CHK_SUPP_FNC mbg_chk_dev_is_isa; + + + +/*HDR*/ +/** + * @brief Check if the device is connected via the MCA bus + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the device is connected via the MCA bus, + * else ::MBG_ERR_NOT_SUPP_BY_DEV + * + * @ingroup mbgdevio_chk_supp_fncs + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_mca( MBG_DEV_HANDLE dh ) +{ + return chk_bus_flags( dh, PCPS_BUS_MCA ); + +} // mbg_chk_dev_is_mca + +MBG_CHK_SUPP_FNC mbg_chk_dev_is_mca; + + + +/*HDR*/ +/** + * @brief Check if the device is connected via the PCI bus + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the device is connected via the PCI bus, + * else ::MBG_ERR_NOT_SUPP_BY_DEV + * + * @ingroup mbgdevio_chk_supp_fncs + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_pci( MBG_DEV_HANDLE dh ) +{ + return chk_bus_flags( dh, PCPS_BUS_PCI ); +} // mbg_chk_dev_is_pci + +MBG_CHK_SUPP_FNC mbg_chk_dev_is_pci; + + + +/*HDR*/ +/** + * @brief Check if the device is connected via the PCI Express bus + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the device is connected via the PCI Express bus, + * else ::MBG_ERR_NOT_SUPP_BY_DEV + * + * @ingroup mbgdevio_chk_supp_fncs + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_pci_express( MBG_DEV_HANDLE dh ) +{ + PCPS_DEV dev_info; + + int rc = mbg_get_device_info( dh, &dev_info ); + + if ( mbg_rc_is_error( rc ) ) + return rc; + + // TODO Move this to the kernel driver + if ( ( dev_info.type.bus_flags == PCPS_BUS_PCI_MBGPEX ) || + ( dev_info.type.bus_flags == PCPS_BUS_PCI_PEX8311 ) ) + return MBG_SUCCESS; + + return MBG_ERR_NOT_SUPP_BY_DEV; + +} // mbg_chk_dev_is_pci_express + +MBG_CHK_SUPP_FNC mbg_chk_dev_is_pci_express; + + + +/*HDR*/ +/** + * @brief Check if the device is connected via the USB bus + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the device is connected via the USB bus, + * else ::MBG_ERR_NOT_SUPP_BY_DEV + * + * @ingroup mbgdevio_chk_supp_fncs + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_usb( MBG_DEV_HANDLE dh ) +{ + return chk_bus_flags( dh, PCPS_BUS_USB ); + +} // mbg_chk_dev_is_usb + +MBG_CHK_SUPP_FNC mbg_chk_dev_is_usb; + + + +/*HDR*/ +/** + * @brief Check if a device supports GNSS configuration + * + * This is usually the case if a device supports reception of + * different satellite systems, e.g. GPS, Glonass, Galileo, etc. + * + * @note This function should be preferred over ::mbg_dev_is_gnss, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_gps_gnss_mode_info + * @see ::mbg_set_gps_gnss_mode_settings + * @see ::mbg_get_gps_all_gnss_sat_info + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_gnss( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_PCPS, PCPS_BIT_IS_GNSS ); + +} // mbg_chk_dev_is_gnss + +MBG_CHK_SUPP_FNC mbg_chk_dev_is_gnss; + + + +/*HDR*/ +/** + * @brief Check if a device is a GPS receiver + * + * The function also returns ::MBG_SUCCESS for GNSS receivers + * which can track GPS satellites beside other GNSS systems. + * + * @note This function should be preferred over ::mbg_dev_is_gps, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_gps( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_REF_TYPE, PCPS_REF_GPS ); + +} // mbg_chk_dev_is_gps + +MBG_CHK_SUPP_FNC mbg_chk_dev_is_gps; + + + +/*HDR*/ +/** + * @brief Check if a device is a DCF77 receiver. + * + * Beside standard DCF77 receivers which receive the legacy AM signal + * there are also PZF receivers which can decode the pseudo-random phase + * modulation and thus yield a higher accuracy. See ::mbg_chk_dev_has_pzf. + * + * @note This function should be preferred over ::mbg_dev_is_dcf, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_has_pzf + * @see ::mbg_chk_dev_is_lwr + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_dcf( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_REF_TYPE, PCPS_REF_DCF ); + +} // mbg_chk_dev_is_dcf + +MBG_CHK_SUPP_FNC mbg_chk_dev_is_dcf; + + + +/*HDR*/ +/** + * @brief Check if a device supports demodulation of the DCF77 PZF code + * + * Beside the enhanced PZF correlation receivers which decode the DCF77's + * pseudo-random phase modulation to yield a better accuracy there are also + * legacy DCF77 receivers which just decode the standard AM signal. + * See ::mbg_chk_dev_is_dcf. + * + * @note This function should be preferred over ::mbg_dev_has_pzf, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_has_corr_info + * @see ::mbg_chk_dev_has_tr_distance + * @see ::mbg_chk_dev_is_dcf + * @see ::mbg_chk_dev_is_lwr + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_pzf( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_condx( dh, _pcps_ddev_has_pzf, IOCTL_DEV_HAS_PZF ); + +} // mbg_chk_dev_has_pzf + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_pzf; + + + +/*HDR*/ +/** + * @brief Check if a device is a MSF receiver + * + * @note This function should be preferred over ::mbg_dev_is_msf, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_is_lwr + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_msf( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_REF_TYPE, PCPS_REF_MSF ); + +} // mbg_chk_dev_is_msf + +MBG_CHK_SUPP_FNC mbg_chk_dev_is_msf; + + + +/*HDR*/ +/** + * @brief Check if a device is a WWVB receiver + * + * @note This function should be preferred over ::mbg_dev_is_wwvb, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_is_lwr + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_wwvb( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_REF_TYPE, PCPS_REF_WWVB ); + +} // _pcps_ddev_is_wwvb + +MBG_CHK_SUPP_FNC _pcps_ddev_is_wwvb; + + + +/*HDR*/ +/** + * @brief Check if a device is a JJY receiver. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_is_lwr + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_jjy( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_REF_TYPE, PCPS_REF_JJY ); + +} // _pcps_ddev_is_jjy + +MBG_CHK_SUPP_FNC _pcps_ddev_is_jjy; + + + +/*HDR*/ +/** + * @brief Check if a device is any long wave signal receiver + * + * Long wave receivers include e.g. DCF77, MSF, WWVB, or JJY. + * + * @note This function should be preferred over ::mbg_dev_is_lwr, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_is_dcf + * @see ::mbg_chk_dev_is_msf + * @see ::mbg_chk_dev_is_wwvb + * @see ::mbg_chk_dev_is_jjy + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_lwr( MBG_DEV_HANDLE dh ) +{ + // TODO Combine to single call + return mbg_rc_is_success( mbg_chk_dev_is_dcf( dh ) ) || + mbg_rc_is_success( mbg_chk_dev_is_msf( dh ) ) || + mbg_rc_is_success( mbg_chk_dev_is_wwvb( dh ) ) || + mbg_rc_is_success( mbg_chk_dev_is_jjy( dh ) ); + +} // mbg_chk_dev_is_lwr + +MBG_CHK_SUPP_FNC mbg_chk_dev_is_lwr; + + + +/*HDR*/ +/** + * @brief Check if a device provides a configurable IRIG input. + * + * @note This function should be preferred over ::mbg_dev_is_irig_rx, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_irig_rx_info + * @see ::mbg_set_irig_rx_settings + * @see ::mbg_chk_dev_has_irig_tx + * @see ::mbg_chk_dev_has_irig +*/ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_is_tcr( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_REF_TYPE, PCPS_REF_IRIG ); + +} // mbg_chk_dev_is_tcr + +MBG_CHK_SUPP_FNC mbg_chk_dev_is_tcr; + + + +/*HDR*/ +/** + * @brief Check if a device supports simple LAN interface API calls + * + * @note This function should be preferred over ::mbg_dev_has_lan_intf, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_lan_if_info + * @see ::mbg_get_ip4_state + * @see ::mbg_get_ip4_settings + * @see ::mbg_set_ip4_settings + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_lan_intf( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_PCPS, PCPS_BIT_HAS_LAN_INTF ); + +} // mbg_chk_dev_has_lan_intf + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_lan_intf; + + + +/*HDR*/ +/** + * @brief Check if a device supports PTP configuration/status calls + * + * @note This function should be preferred over ::mbg_dev_has_ptp, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_state + * @see ::mbg_get_ptp_cfg_info + * @see ::mbg_set_ptp_cfg_settings + * @see ::mbg_chk_dev_has_ptp_unicast + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_ptp( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_PCPS, PCPS_BIT_HAS_PTP ); + +} // mbg_chk_dev_has_ptp + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_ptp; + + + +/*HDR*/ +/** + * @brief Check if a device supports PTP unicast feature/configuration + * + * Not all devices which support PTP do also support PTP Unicast. This API + * call checks if PTP Unicast is supported in addition to the standard + * PTP multicast. + * + * @note This function should be preferred over ::mbg_dev_has_ptp_unicast, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_uc_master_cfg_limits + * @see ::mbg_get_all_ptp_uc_master_info + * @see ::mbg_set_ptp_uc_master_settings_idx + * @see ::mbg_get_ptp_state + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_ptp_unicast( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_RI, GPS_HAS_PTP_UNICAST ); + +} // mbg_chk_dev_has_ptp_unicast + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_ptp_unicast; + + + +/*HDR*/ +/** + * @brief Check if a device supports the mbg_get_hr_time... functions + * + * @note This function should be preferred over ::mbg_dev_has_hr_time, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_hr_time + * @see ::mbg_get_hr_time_cycles + * @see ::mbg_get_hr_time_comp + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_hr_time( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_PCPS, PCPS_BIT_HAS_HR_TIME ); + +} // mbg_chk_dev_has_hr_time + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_hr_time; + + + +/*HDR*/ +/** + * @brief Check if a device supports the mbg_get_fast_hr_timestamp... calls + * + * @note This function should be preferred over ::mbg_dev_has_fast_hr_timestamp, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_fast_hr_timestamp_cycles + * @see ::mbg_get_fast_hr_timestamp_comp + * @see ::mbg_get_fast_hr_timestamp + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_fast_hr_timestamp( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_PCPS, PCPS_BIT_HAS_FAST_HR_TSTAMP ); + +} // mbg_chk_dev_has_fast_hr_timestamp + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_fast_hr_timestamp; + + + +/*HDR*/ +/** + * @brief Check if a device supports configurable time scales. + * + * By default the devices return %UTC and/or local time. However, some cards + * can be configured to return raw GPS time or TAI instead. + * + * @note This function should be preferred over ::mbg_dev_has_time_scale, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_time_scale_info + * @see ::mbg_set_time_scale_settings + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_time_scale( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_time_scale, IOCTL_DEV_HAS_GPS_TIME_SCALE ); + +} // mbg_chk_dev_has_time_scale + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_time_scale; + + + +/*HDR*/ +/* (Intentionally excluded from Doxygen) + * @brief Check if a device supports setting an event time + * + * This feature is only supported by some special custom firmware + * to preset a %UTC time at which the clock is to generate an output signal. + * + * @note This function should be preferred over ::mbg_dev_has_event_time, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_set_event_time + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_event_time( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_event_time, IOCTL_DEV_HAS_EVENT_TIME ); + +} // mbg_chk_dev_has_event_time + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_event_time; + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_get_ucap_entries and ::mbg_get_ucap_event calls + * + * If the device doesn't support this but is a GPS card then the card provides + * a time capture FIFO buffer and the obsolete ::mbg_get_gps_ucap call can be used + * to retrieve entries from the FIFO buffer. + * + * @note This function should be preferred over ::mbg_dev_has_ucap, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_ucap_entries + * @see ::mbg_get_ucap_event + * @see ::mbg_clr_ucap_buff + * @see ::mbg_get_gps_ucap + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_ucap( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_ucap, IOCTL_DEV_HAS_UCAP ); + +} // mbg_chk_dev_has_ucap + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_ucap; + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_clr_ucap_buff call + * + * The ::mbg_clr_ucap_buff call can be used to clear a device's on-board + * time capture FIFO buffer, but the call may not be supported by some + * older GPS devices. + * + * @note This function should be preferred over ::mbg_dev_can_clr_ucap_buff, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_clr_ucap_buff + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_can_clr_ucap_buff( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_can_clr_ucap_buff, IOCTL_DEV_CAN_CLR_UCAP_BUFF ); + +} // mbg_chk_dev_can_clr_ucap_buff + +MBG_CHK_SUPP_FNC mbg_chk_dev_can_clr_ucap_buff; + + + +/*HDR*/ +/** + * @brief Check if a device supports timezone configuration using the ::TZDL structure + * + * @note This function should be preferred over ::mbg_dev_has_tzdl, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_gps_tzdl + * @see ::mbg_set_gps_tzdl + * @see ::mbg_chk_dev_has_tz + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_tzdl( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_tzdl, IOCTL_DEV_HAS_TZDL ); + +} // mbg_chk_dev_has_tzdl + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_tzdl; + + + +/*HDR*/ +/** + * @brief Check if a device supports timezone configuration using the ::PCPS_TZDL structure + * + * @note This function should be preferred over ::mbg_dev_has_pcps_tzdl, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_pcps_tzdl + * @see ::mbg_set_pcps_tzdl + * @see ::mbg_chk_dev_has_tz + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_pcps_tzdl( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_pcps_tzdl, IOCTL_DEV_HAS_PCPS_TZDL ); + +} // mbg_chk_dev_has_pcps_tzdl + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_pcps_tzdl; + + + +/*HDR*/ +/** + * @brief Check if a device supports timezone configuration using the ::PCPS_TZCODE type. + * + * @note This function should be preferred over ::mbg_dev_has_tzcode, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_tzcode + * @see ::mbg_set_tzcode + * @see ::mbg_chk_dev_has_tz + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_tzcode( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_tzcode, IOCTL_DEV_HAS_TZCODE ); + +} // mbg_chk_dev_has_tzcode + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_tzcode; + + + +/*HDR*/ +/** + * @brief Check if a device supports any kind of timezone configuration. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @note This function should be preferred over ::mbg_dev_has_tz, + * which has been deprecated. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_has_tzdl + * @see ::mbg_chk_dev_has_pcps_tzdl + * @see ::mbg_chk_dev_has_tzcode + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_tz( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_tz, IOCTL_DEV_HAS_TZ ); + +} // mbg_chk_dev_has_tz + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_tz; + + + +/*HDR*/ +/** + * @brief Check if a device provides either an IRIG input or output. + * + * @note This function should be preferred over ::mbg_dev_has_irig, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_is_tcr + * @see ::mbg_chk_dev_has_irig_tx + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_irig( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_irig, IOCTL_DEV_HAS_IRIG ); + +} // mbg_chk_dev_has_irig + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_irig; + + + +/*HDR*/ +/** + * @brief Check if a device provides a configurable IRIG output. + * + * @note This function should be preferred over ::mbg_dev_has_irig, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_irig_tx_info + * @see ::mbg_set_irig_tx_settings + * @see ::mbg_chk_dev_is_tcr + * @see ::mbg_chk_dev_has_irig + * @see @ref group_icode + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_irig_tx( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_irig_tx, IOCTL_DEV_HAS_IRIG_TX ); + +} // mbg_chk_dev_has_irig_tx + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_irig_tx; + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_get_irig_ctrl_bits call + * + * @note This function should be preferred over ::mbg_dev_has_irig_ctrl_bits, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_irig_ctrl_bits + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_irig_ctrl_bits( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_irig_ctrl_bits, IOCTL_DEV_HAS_IRIG_CTRL_BITS ); + +} // mbg_chk_dev_has_irig_ctrl_bits + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_irig_ctrl_bits; + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_get_raw_irig_data call + * + * @note This function should be preferred over ::mbg_dev_has_raw_irig_data, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_raw_irig_data + * @see ::mbg_get_raw_irig_data_on_sec_change + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_raw_irig_data( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_PCPS, PCPS_BIT_HAS_RAW_IRIG_DATA ); + +} // mbg_chk_dev_has_raw_irig_data + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_raw_irig_data; + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_get_irig_time call + * + * @note This function should be preferred over ::mbg_dev_has_irig_time, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_irig_time + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_irig_time( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_irig_time, IOCTL_DEV_HAS_IRIG_TIME ); + +} // mbg_chk_dev_has_irig_time + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_irig_time; + + + +/*HDR*/ +/** + * @brief Check if a device provides the level of its inputs signal + * + * This is useful to display the signal level of e.g. an IRIG or similar + * time code, or a long wave signal. + * + * @note This function should be preferred over ::mbg_dev_has_signal, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_signal( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_signal, IOCTL_DEV_HAS_SIGNAL ); + +} // mbg_chk_dev_has_signal + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_signal; + + + +/*HDR*/ +/** + * @brief Check if a device provides a modulation signal + * + * Modulation signals are e.g. the second marks provided by a long wave receiver. + * + * @note This function should be preferred over ::mbg_dev_has_mod, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_mod( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_mod, IOCTL_DEV_HAS_MOD ); + +} // mbg_chk_dev_has_mod + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_mod; + + + +/*HDR*/ +/* (Intentionally excluded from Doxygen) + * @brief Check if a device supports higher baud rates than usual + * + * Check if a device provides a serial output that supports + * higher baud rates than older cards, i.e. ::DEFAULT_BAUD_RATES_DCF_HS + * rather than ::DEFAULT_BAUD_RATES_DCF. + * + * The call ::mbg_get_serial_settings takes care of this, so applications + * which use that call as suggested don't need to use this call directly. + * + * @note This function should be preferred over ::mbg_dev_has_serial_hs, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_serial_settings + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_serial_hs( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_serial_hs, IOCTL_DEV_HAS_SERIAL_HS ); + +} // mbg_chk_dev_has_serial_hs + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_serial_hs; + + + +/*HDR*/ +/** + * @brief Check if a device provides a programmable frequency synthesizer + * + * @note This function should be preferred over ::mbg_dev_has_synth, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_synth + * @see ::mbg_set_synth + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_synth( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_synth, IOCTL_DEV_HAS_SYNTH ); + +} // mbg_chk_dev_has_synth + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_synth; + + + +/*HDR*/ +/** + * @brief Check if a device provides GPIO signal inputs and/or outputs + * + * @note This function should be preferred over ::mbg_dev_has_gpio, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_gpio_cfg_limits + * @see ::mbg_get_gps_all_gpio_info + * @see ::mbg_set_gps_gpio_settings_idx + * @see ::mbg_get_gps_all_gpio_status + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_gpio( MBG_DEV_HANDLE dh ) +{ + return mbgdevio_chk_dev_feat( dh, DEV_FEAT_REQ_TYPE_RI, GPS_HAS_GPIO ); + +} // mbg_chk_dev_has_gpio + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_gpio; + + + +/*HDR*/ +/** + * @brief Check if a device supports configuration of antenna cable length + * + * @note This function should be preferred over ::mbg_dev_has_cab_len, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_gps_ant_cable_len + * @see ::mbg_set_gps_ant_cable_len + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_cab_len( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_cab_len, IOCTL_DEV_HAS_CAB_LEN ); + +} // mbg_chk_dev_has_cab_len + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_cab_len; + + + +/*HDR*/ +/** + * @brief Check if a device provides a configurable ref time offset + * + * This may be required to convert the received time to %UTC, if the input + * signal doesn't specify this (e.g. with most IRIG code formats). + * + * @note This function should be preferred over ::mbg_dev_has_ref_offs, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_ref_offs + * @see ::mbg_set_ref_offs + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_ref_offs( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_ref_offs, IOCTL_DEV_HAS_REF_OFFS ); + +} // mbg_chk_dev_has_ref_offs + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_ref_offs; + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::MBG_OPT_INFO/::MBG_OPT_SETTINGS. + * + * These structures contain optional settings, controlled by flags. + * See ::MBG_OPT_SETTINGS and associated definitions. + * + * @note This function should be preferred over ::mbg_dev_has_opt_flags, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_opt_info + * @see ::mbg_set_opt_settings + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_opt_flags( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_opt_flags, IOCTL_DEV_HAS_OPT_FLAGS ); + +} // mbg_chk_dev_has_opt_flags + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_opt_flags; + + + +/*HDR*/ +/** + * @brief Check if a device support reading/writing of UTC parameters. + * + * This API call checks if a device supports reading/writing a GPS %UTC + * parameter set via the PC bus. Reading/writing these parameters via the + * serial port using the Meinberg binary data protocol is supported by all + * Meinberg GPS and GNSS devices. + * + * The %UTC parameter set is usually received from the satellites' broadcasts + * and contains the current time offset between GPS time and UTC, plus information + * on a pending leap second event. + * + * It may be useful to overwrite them to do some tests, or for applications + * where a card is freewheeling. + * + * @note This function should be preferred over ::mbg_dev_has_utc_parm, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_utc_parm + * @see ::mbg_set_utc_parm + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_utc_parm( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_utc_parm, IOCTL_DEV_HAS_GPS_UTC_PARM ); + +} // mbg_chk_dev_has_utc_parm + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_utc_parm; + + + +/*HDR*/ +/** + * @brief Check if a device supports reading correlation info + * + * The PZF phase modulation decoded by DCF77 PZF receivers is decoded + * using a correlation approach, and optionally there's an API call + * supported which can be used to retrieve the correlation value + * and thus determine the quality of the input signal. + * + * @note This function should be preferred over ::mbg_dev_has_corr_info, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_has_pzf + * @see ::mbg_get_corr_info + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_corr_info( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_corr_info, IOCTL_DEV_HAS_CORR_INFO ); + +} // mbg_chk_dev_has_corr_info + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_corr_info; + + + +/*HDR*/ +/** + * @brief Check if a device supports configurable distance from transmitter + * + * The distance from transmitter parameter is used to compensate + * the RF propagation delay, mostly with long wave receivers. + * + * @note This function should be preferred over ::mbg_dev_has_tr_distance, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_has_pzf + * @see ::mbg_get_tr_distance + * @see ::mbg_set_tr_distance + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_tr_distance( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_tr_distance, IOCTL_DEV_HAS_TR_DISTANCE ); + +} // mbg_chk_dev_has_tr_distance + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_tr_distance; + + + +/*HDR*/ +/** + * @brief Check if a device provides a debug status word to be read + * + * @note This function should be preferred over ::mbg_dev_has_debug_status, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_debug_status + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_debug_status( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_debug_status, IOCTL_DEV_HAS_DEBUG_STATUS ); + +} // mbg_chk_dev_has_debug_status + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_debug_status; + + + +/*HDR*/ +/** + * @brief Check if a device provides an on-board event log + * + * @note This function should be preferred over ::mbg_dev_has_evt_log, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_clr_evt_log + * @see ::mbg_get_num_evt_log_entries + * @see ::mbg_get_first_evt_log_entry + * @see ::mbg_get_next_evt_log_entry + */ +_MBG_API_ATTR int _MBG_API mbg_chk_dev_has_evt_log( MBG_DEV_HANDLE dh ) +{ + _mbgdevio_new_query_cond( dh, _pcps_ddev_has_evt_log, IOCTL_DEV_HAS_EVT_LOG ); + +} // mbg_chk_dev_has_evt_log + +MBG_CHK_SUPP_FNC mbg_chk_dev_has_evt_log; + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::RECEIVER_INFO structure and related calls + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_receiver_info preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_receiver_info + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_receiver_info" ) _MBG_API mbg_dev_has_receiver_info( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_receiver_info, IOCTL_DEV_HAS_RECEIVER_INFO, p ); + +} // mbg_dev_has_receiver_info + + + +/*HDR*/ +/** + * @brief Check if a device supports large configuration data structures + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_gps_data preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_gps_data + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_gps_data" ) _MBG_API mbg_dev_has_gps_data( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_gps_data, IOCTL_DEV_HAS_GPS_DATA, p ); + +} // mbg_dev_has_gps_data + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_generic_io API call + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_generic_io preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_generic_io + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_generic_io" ) _MBG_API mbg_dev_has_generic_io( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_generic_io, IOCTL_DEV_HAS_GENERIC_IO, p ); + +} // mbg_dev_has_generic_io + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_get_asic_version call + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_asic_version preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_asic_version + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_asic_version" ) _MBG_API mbg_dev_has_asic_version( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_asic_version, IOCTL_DEV_HAS_PCI_ASIC_VERSION, p ); + +} // mbg_dev_has_asic_version + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_get_asic_features call. + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_asic_features preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_asic_features + * @see ::mbg_get_asic_features + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_asic_features" ) _MBG_API mbg_dev_has_asic_features( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_asic_features, IOCTL_DEV_HAS_PCI_ASIC_FEATURES, p ); + +} // mbg_dev_has_asic_features + + + +/*HDR*/ +/** + * @brief Check if a device provides extended multi ref (XMR) inputs. + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_xmr preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_xmr + * @see @ref group_multi_ref_ext + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_xmr" ) _MBG_API mbg_dev_has_xmr( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_ri_cond( dh, _pcps_has_ri_xmr, IOCTL_DEV_HAS_XMR, p ); + +} // mbg_dev_has_xmr + + + +/*HDR*/ +/** + * @brief Check if a device supports GNSS configuration + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_gnss preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_gnss + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_gnss" ) _MBG_API mbg_dev_is_gnss( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_is_gnss, IOCTL_DEV_IS_GNSS, p ); + +} // mbg_dev_is_gnss + + + +/*HDR*/ +/** + * @brief Check if a device is a GPS receiver + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_gps preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_gps + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_gps" ) _MBG_API mbg_dev_is_gps( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_is_gps, IOCTL_DEV_IS_GPS, p ); + +} // mbg_dev_is_gps + + + +/*HDR*/ +/** + * @brief Check if a device is a DCF77 receiver + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_dcf preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_dcf + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_dcf" ) _MBG_API mbg_dev_is_dcf( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_is_dcf, IOCTL_DEV_IS_DCF, p ); + +} // mbg_dev_is_dcf + + + +/*HDR*/ +/** + * @brief Check if a device supports demodulation of the DCF77 PZF code + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_pzf preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_pzf + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_pzf" ) _MBG_API mbg_dev_has_pzf( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_pzf, IOCTL_DEV_HAS_PZF, p ); + +} // mbg_dev_has_pzf + + + +/*HDR*/ +/** + * @brief Check if a device is a MSF receiver + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_msf preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_msf + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_msf" ) _MBG_API mbg_dev_is_msf( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_is_msf, IOCTL_DEV_IS_MSF, p ); + +} // mbg_dev_is_msf + + + +/*HDR*/ +/** + * @brief Check if a device is a WWVB receiver + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_wwvb preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_wwvb + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_wwvb" ) _MBG_API mbg_dev_is_wwvb( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_is_wwvb, IOCTL_DEV_IS_WWVB, p ); + +} // mbg_dev_is_wwvb + + + +/*HDR*/ +/** + * @brief Check if a device is any long wave signal receiver + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_lwr preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_lwr + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_lwr" ) _MBG_API mbg_dev_is_lwr( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_is_lwr, IOCTL_DEV_IS_LWR, p ); + +} // mbg_dev_is_lwr + + + +/*HDR*/ +/** + * @brief Check if a device provides a configurable IRIG input. + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_tcr preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_tcr + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_tcr" ) _MBG_API mbg_dev_is_irig_rx( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_is_irig_rx, IOCTL_DEV_IS_IRIG_RX, p ); + +} // mbg_dev_is_irig_rx + + + +/*HDR*/ +/** + * @brief Check if a device supports simple LAN interface API calls + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_lan_intf preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_lan_intf + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_lan_intf" ) _MBG_API mbg_dev_has_lan_intf( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_lan_intf, IOCTL_DEV_HAS_LAN_INTF, p ); + +} // mbg_dev_has_lan_intf + + + +/*HDR*/ +/** + * @brief Check if a device supports PTP configuration/status calls + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_ptp preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_ptp + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_ptp" ) _MBG_API mbg_dev_has_ptp( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_ptp, IOCTL_DEV_HAS_PTP, p ); + +} // mbg_dev_has_ptp + + + +/*HDR*/ +/** + * @brief Check if a device supports PTP unicast feature/configuration + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_ptp_unicast preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_ptp_unicast + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_ptp_unicast" ) _MBG_API mbg_dev_has_ptp_unicast( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_ri_cond( dh, _pcps_has_ri_ptp_unicast, IOCTL_DEV_HAS_PTP_UNICAST, p ); + +} // mbg_dev_has_ptp_unicast + + + +/*HDR*/ +/** + * @brief Check if a device supports the HR_TIME functions + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_hr_time preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_hr_time + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_hr_time" ) _MBG_API mbg_dev_has_hr_time( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_hr_time, IOCTL_DEV_HAS_HR_TIME, p ); + +} // mbg_dev_has_hr_time + + + +/*HDR*/ +/** + * @brief Check if a device supports the mbg_get_fast_hr_timestamp_...() calls + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_fast_hr_timestamp preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_fast_hr_timestamp + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_fast_hr_timestamp" ) _MBG_API mbg_dev_has_fast_hr_timestamp( MBG_DEV_HANDLE dh, int *p ) +{ + return mbgdevio_chk_dev_feat_deprecated( dh, DEV_FEAT_REQ_TYPE_PCPS, PCPS_BIT_HAS_FAST_HR_TSTAMP, p ); + +} // mbg_dev_has_fast_hr_timestamp + + + +/*HDR*/ +/** + * @brief Check if a device supports configurable time scales + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_time_scale preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_time_scale + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_time_scale" ) _MBG_API mbg_dev_has_time_scale( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_time_scale, IOCTL_DEV_HAS_GPS_TIME_SCALE, p ); + +} // mbg_dev_has_time_scale + + + +/*HDR*/ +/** + * @brief Check if a device supports setting an event time + * + * @note This is only supported by some customized devices + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_event_time preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_event_time + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_event_time" ) _MBG_API mbg_dev_has_event_time( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_event_time, IOCTL_DEV_HAS_EVENT_TIME, p ); + +} // mbg_dev_has_event_time + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_get_ucap_entries and ::mbg_get_ucap_event calls + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_ucap preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_ucap + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_ucap" ) _MBG_API mbg_dev_has_ucap( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_ucap, IOCTL_DEV_HAS_UCAP, p ); + +} // mbg_dev_has_ucap + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_clr_ucap_buff call + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_can_clr_ucap_buff preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_can_clr_ucap_buff + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_can_clr_ucap_buff" ) _MBG_API mbg_dev_can_clr_ucap_buff( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_can_clr_ucap_buff, IOCTL_DEV_CAN_CLR_UCAP_BUFF, p ); + +} // mbg_dev_can_clr_ucap_buff + + + +/*HDR*/ +/** + * @brief Check if a device supports timezone configuration using the ::TZDL structure + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_tzdl preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_tzdl + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_tzdl" ) _MBG_API mbg_dev_has_tzdl( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_tzdl, IOCTL_DEV_HAS_TZDL, p ); + +} // mbg_dev_has_tzdl + + + +/*HDR*/ +/** + * @brief Check if a device supports timezone configuration using the ::PCPS_TZDL structure + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_pcps_tzdl preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_pcps_tzdl + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_pcps_tzdl" ) _MBG_API mbg_dev_has_pcps_tzdl( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_pcps_tzdl, IOCTL_DEV_HAS_PCPS_TZDL, p ); + +} // mbg_dev_has_pcps_tzdl + + + +/*HDR*/ +/** + * @brief Check if a device supports timezone configuration using the ::PCPS_TZCODE type + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_tzcode preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_tzcode + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_tzcode" ) _MBG_API mbg_dev_has_tzcode( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_tzcode, IOCTL_DEV_HAS_TZCODE, p ); + +} // mbg_dev_has_tzcode + + + +/*HDR*/ +/** + * @brief Check if a device supports any kind of timezone configuration + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_tz preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_tz + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_tz" ) _MBG_API mbg_dev_has_tz( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_tz, IOCTL_DEV_HAS_TZ, p ); + +} // mbg_dev_has_tz + + + +/*HDR*/ +/** + * @brief Check if a device provides either an IRIG input or output + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_irig preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_irig + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_irig" ) _MBG_API mbg_dev_has_irig( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_irig, IOCTL_DEV_HAS_IRIG, p ); + +} // mbg_dev_has_irig + + + +/*HDR*/ +/** + * @brief Check if a device provides a configurable IRIG output + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_irig_tx preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_irig_tx + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_irig_tx" ) _MBG_API mbg_dev_has_irig_tx( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_irig_tx, IOCTL_DEV_HAS_IRIG_TX, p ); + +} // mbg_dev_has_irig_tx + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_get_irig_ctrl_bits call + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_irig_ctrl_bits preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_irig_ctrl_bits + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_irig_ctrl_bits" ) _MBG_API mbg_dev_has_irig_ctrl_bits( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_irig_ctrl_bits, IOCTL_DEV_HAS_IRIG_CTRL_BITS, p ); + +} // mbg_dev_has_irig_ctrl_bits + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_get_raw_irig_data call + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_raw_irig_data preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_raw_irig_data + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_raw_irig_data" ) _MBG_API mbg_dev_has_raw_irig_data( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_raw_irig_data, IOCTL_DEV_HAS_RAW_IRIG_DATA, p ); + +} // mbg_dev_has_raw_irig_data + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::mbg_get_irig_time call + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_irig_time preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_irig_time + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_irig_time" ) _MBG_API mbg_dev_has_irig_time( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_irig_time, IOCTL_DEV_HAS_IRIG_TIME, p ); + +} // mbg_dev_has_irig_time -} // do_mbg_ioctl -#endif // defined( MBG_TGT_WIN32 ) +/*HDR*/ +/** + * @brief Check if a device provides the level of its inputs signal + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_signal preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_signal + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_signal" ) _MBG_API mbg_dev_has_signal( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_signal, IOCTL_DEV_HAS_SIGNAL, p ); + +} // mbg_dev_has_signal + + + +/*HDR*/ +/** + * @brief Check if a device provides a modulation signal + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_mod preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_mod + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_mod" ) _MBG_API mbg_dev_has_mod( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_mod, IOCTL_DEV_HAS_MOD, p ); + +} // mbg_dev_has_mod + + + +/*HDR*/ +/* (Intentionally excluded from Doxygen) + * @brief Check if a device supports higher baud rates than usual + * + * Check if a device provides a serial output that supports + * higher baud rates than older cards, i.e. ::DEFAULT_BAUD_RATES_DCF_HS + * rather than ::DEFAULT_BAUD_RATES_DCF. + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_serial_hs preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_serial_hs + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_serial_hs" ) _MBG_API mbg_dev_has_serial_hs( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_serial_hs, IOCTL_DEV_HAS_SERIAL_HS, p ); + +} // mbg_dev_has_serial_hs -static /*HDR*/ //##++ make this public ? + +/*HDR*/ +/** + * @brief Check if a device provides a programmable frequency synthesizer + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_synth preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_synth + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_synth" ) _MBG_API mbg_dev_has_synth( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_synth, IOCTL_DEV_HAS_SYNTH, p ); + +} // mbg_dev_has_synth + + + +/*HDR*/ +/** + * @brief Check if a device provides GPIO signal inputs and/or outputs + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_gpio preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_gpio + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_gpio" ) _MBG_API mbg_dev_has_gpio( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_ri_cond( dh, _pcps_has_ri_gpio, IOCTL_DEV_HAS_GPIO, p ); + +} // mbg_dev_has_gpio + + + +/*HDR*/ +/** + * @brief Check if a device supports configuration of antenna cable length + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_cab_len preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_cab_len + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_cab_len" ) _MBG_API mbg_dev_has_cab_len( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_cab_len, IOCTL_DEV_HAS_CAB_LEN, p ); + +} // mbg_dev_has_cab_len + + + +/*HDR*/ +/** + * @brief Check if a device provides a configurable ref time offset + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_ref_offs preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_ref_offs + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_ref_offs" ) _MBG_API mbg_dev_has_ref_offs( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_ref_offs, IOCTL_DEV_HAS_REF_OFFS, p ); + +} // mbg_dev_has_ref_offs + + + +/*HDR*/ +/** + * @brief Check if a device supports the ::MBG_OPT_INFO/::MBG_OPT_SETTINGS + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_opt_flags preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_opt_flags + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_opt_flags" ) _MBG_API mbg_dev_has_opt_flags( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_opt_flags, IOCTL_DEV_HAS_OPT_FLAGS, p ); + +} // mbg_dev_has_opt_flags + + + +/*HDR*/ +/** + * @brief Check if a device support reading/writing of ::UTC parameters + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_utc_parm preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_utc_parm + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_utc_parm" ) _MBG_API mbg_dev_has_utc_parm( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_utc_parm, IOCTL_DEV_HAS_GPS_UTC_PARM, p ); + +} // mbg_dev_has_utc_parm + + + +/*HDR*/ +/** + * @brief Check if a device supports reading correlation info + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_corr_info preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_corr_info + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_corr_info" ) _MBG_API mbg_dev_has_corr_info( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_corr_info, IOCTL_DEV_HAS_CORR_INFO, p ); + +} // mbg_dev_has_corr_info + + + +/*HDR*/ +/** + * @brief Check if a device supports configurable distance from transmitter + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_tr_distance preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_tr_distance + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_tr_distance" ) _MBG_API mbg_dev_has_tr_distance( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_tr_distance, IOCTL_DEV_HAS_TR_DISTANCE, p ); + +} // mbg_dev_has_tr_distance + + + +/*HDR*/ +/** + * @brief Check if a device provides a debug status word to be read + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_debug_status preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_debug_status + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_debug_status" ) _MBG_API mbg_dev_has_debug_status( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_debug_status, IOCTL_DEV_HAS_DEBUG_STATUS, p ); + +} // mbg_dev_has_debug_status + + + +/*HDR*/ +/** + * @brief Check if a device provides an on-board event log. + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_evt_log preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_evt_log + */ +_MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_evt_log" ) _MBG_API mbg_dev_has_evt_log( MBG_DEV_HANDLE dh, int *p ) +{ + _mbgdevio_old_query_cond( dh, _pcps_ddev_has_evt_log, IOCTL_DEV_HAS_EVT_LOG, p ); + +} // mbg_dev_has_evt_log + + + +static /*HDR*/ +/** + * @brief Update a ::PCPS_TIME_STAMP to compensate the latency of an API call + * + * @param[in,out] ts The timestamp to be updated + * @param[in] p_cyc_ts Cycles value taken when the function was called + * @param[in] p_cyc_ontime Cycles value taken when access to the device was made + * @param[in] p_cyc_freq Cycles frequency determined by the application, depending on the type of cycles counter + * @param[out] hns_latency Optional pointer to a variable to receive the computed latency, or NULL + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ int mbg_comp_hr_latency( PCPS_TIME_STAMP *ts, const MBG_PC_CYCLES *p_cyc_ts, const MBG_PC_CYCLES *p_cyc_ontime, const MBG_PC_CYCLES_FREQUENCY *p_cyc_freq, int32_t *hns_latency ) { - #if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX ) + #if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_POSIX ) int64_t cyc_latency; int64_t frac_latency; @@ -505,28 +3163,28 @@ int mbg_comp_hr_latency( PCPS_TIME_STAMP *ts, ); #endif - // Account for cycles counter overflow. This is - // supposed to happen once every 2^^63 units of the - // cycles counter frequency, i.e. about every - // 97 years on a system with 3 GHz clock. + // Account for cycles counter overflow. If the CPU's TSC is used + // this is supposed to happen once every 2^^63 units of the + // cycles counter frequency, i.e. about every 97 years on a system + // with 3 GHz clock. if ( cyc_latency < 0 ) { cyc_latency += ( (uint64_t) -1 ) >> 1; #if DEBUG && defined( MBG_TGT_LINUX ) - printf( "->%lli (%llX)", + printf( "->%lli (%llX)", (unsigned long long) cyc_latency, (unsigned long long) ( ( (uint64_t) -1 ) >> 1 ) ); #endif } - // convert latency to binary fractions of seconds, + // Convert latency to binary fractions of seconds, // i.e. units of 2^^-32. frac_latency = (*p_cyc_freq) ? ( cyc_latency * ( ( (int64_t) 1 ) << 32 ) / *p_cyc_freq ) : 0; - // compute the compensated fractional part of the HR time stamp - // and account for borrows from the sec field + // Compute the compensated fractional part of the HR time stamp + // and account for borrows from the sec field. comp_frac = ts->frac - frac_latency; ts->frac = (uint32_t) comp_frac; // yields 32 LSBs ts->sec += (uint32_t) ( comp_frac >> 32 ); // yields 32 MSBs @@ -568,7 +3226,7 @@ int mbg_comp_hr_latency( PCPS_TIME_STAMP *ts, #else // This is currently not supported by the target environment. - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS ); + return MBG_ERR_NOT_SUPP_ON_OS; #endif @@ -578,202 +3236,202 @@ int mbg_comp_hr_latency( PCPS_TIME_STAMP *ts, /*HDR*/ /** - Get the version number of the compiled mbgdevio library. - If the mbgdevio library is built as a DLL/shared object then - the version number of the compiled library may differ from - the version number of the import library and header files - which have been used to build an application. - - @return The version number - - @see ::MBGDEVIO_VERSION defined in mbgdevio.h. - */ -_MBG_API_ATTR int _MBG_API mbgdevio_get_version( void ) + * @brief Create a device file name according to an index number + * + * Create a system-specific device file name string, e.g. "/dev/mbgclock0" + * under Linux and similar systems, which can be used with the + * open() call on systems which support this. + * + * Under Windows a hardware ID string is used, so a Windows-specific function + * is called to retrieve the string + * + * @param[out] s Pointer to the output buffer. + * @param[in] max_len Size of the output buffer. + * @param[in] dev_idx The device index number. + * + * @see mbg_svc_get_device_path under Windows + */ +_MBG_API_ATTR int _MBG_API mbg_dev_fn_from_dev_idx( char *s, int max_len, int dev_idx ) { + size_t n = 0; - return MBGDEVIO_VERSION; - -} // mbgdevio_get_version - - - -/*HDR*/ -/** - Check if the version of the compiled mbgdevio library is compatible - with a certain version which is passed as parameter. - - @param header_version Version number to be checked, should be ::MBGDEVIO_VERSION - defined in mbgdevio.h. - - @return ::MBG_SUCCESS if compatible, ::MBG_ERR_LIB_NOT_COMPATIBLE if not. - - @see ::MBGDEVIO_VERSION defined in mbgdevio.h. - */ -_MBG_API_ATTR int _MBG_API mbgdevio_check_version( int header_version ) -{ - if ( header_version >= MBGDEVIO_COMPAT_VERSION ) - return MBG_SUCCESS; + #if MBG_TGT_HAS_DEV_FN + n = snprintf_safe( s, max_len, mbg_dev_fn_fmt, dev_idx ); + #elif defined( MBG_TGT_WIN32 ) + n = sn_cpy_str_safe( s, max_len, mbg_svc_get_device_path( dev_idx ) ); + #else + n = snprintf_safe( s, max_len, "index #%i", dev_idx ); + #endif - return _mbg_err_to_os( MBG_ERR_LIB_NOT_COMPATIBLE ); + return _int_from_size_t( n ); -} // mbgdevio_check_version +} // mbg_dev_fn_from_dev_idx /*HDR*/ /** - Open a device by index, starting from 0. - This function is <b>out of date</b>, mbg_open_device_by_name() - should be used instead. - - See the <b>note</b> for mbg_find_device() for details. - - @param device_index Index of the device, use 0 for the first device. - */ -_MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device( unsigned int device_index ) + * @brief Open a device by index number + * + * For details and similar functions see @ref mbgdevio_open_fncs. + * + * @param[in] dev_idx Device index number, starting from 0. + * + * @return A valid device handle on success, else ::MBG_INVALID_DEV_HANDLE + * + * @ingroup mbgdevio_open_fncs + * @see ::mbg_close_device + * @see @ref mbgdevio_open_fncs + */ +MBG_DEV_HANDLE _MBG_API mbg_open_device( int dev_idx ) { -#if defined( MBG_TGT_WIN32 ) - - const char *device_path; - HANDLE dh; - - device_path = mbg_svc_get_device_path( device_index ); - - if ( device_path == NULL ) + if ( dev_idx < 0 ) goto fail; - - dh = CreateFile( - device_path, // file name - GENERIC_READ | GENERIC_WRITE, // access mode - 0, // share mode - NULL, // security descriptor - OPEN_EXISTING, // how to create - 0, // file attributes - NULL // handle to template file - ); - - if ( INVALID_HANDLE_VALUE == dh ) + #if defined( MBG_TGT_WIN32 ) { - #if 0 //##++ - printf( "mbg_open_device: CreateFile failed for index %i\n", device_index ); - #endif + const char *device_path = mbg_svc_get_device_path( dev_idx ); - goto fail; + return mbg_open_device_by_dev_fn( device_path ); } + #elif MBG_TGT_HAS_DEV_FN + { + MBG_DEV_FN dev_fn; - return dh; - -fail: - return MBG_INVALID_DEV_HANDLE; - -#elif defined( MBG_TGT_UNIX ) - - MBG_DEV_HANDLE dh; - char dev_fn[50]; - - if ( device_index > MBG_MAX_DEVICES ) - device_index = MBG_MAX_DEVICES; - - sprintf( dev_fn, "/dev/mbgclock%d", device_index ); //##++ - - dh = open( dev_fn, O_RDWR ); + mbg_dev_fn_from_dev_idx( dev_fn, sizeof( dev_fn ), dev_idx ); - return ( dh < 0 ) ? MBG_INVALID_DEV_HANDLE : dh; + return mbg_open_device_by_dev_fn( dev_fn ); + } + #else -#else + #if defined( _PCPSDRVR_H ) + if ( dev_idx < n_ddevs ) + return &pcps_ddev[dev_idx]; + #endif - return ( device_index < n_ddevs ) ? &pcps_ddev[device_index] : NULL; + // intentionally fall-through to "fail" + #endif -#endif +fail: + errno = ENODEV; // No such device + return MBG_INVALID_DEV_HANDLE; } // mbg_open_device -static /*HDR*/ -/* (Intentionally excluded from Doxygen) - Return a handle to a device specified by a given hardware_id. - The format the hardware_id depends on the operating system, so - this function is used only internally to detect devices for - which a unique name of the format MBG_HW_NAME is generated, - which is in turn used with the public API functions. - */ -MBG_DEV_HANDLE _MBG_API mbg_open_device_by_hw_id( const char* hw_id ) +/*HDR*/ +/** + * @brief Open a device specified by a device file name + * + * The format the device file name depends on the operating system. + * see ::MBG_DEV_FN. + * + * For details and similar functions see @ref mbgdevio_open_fncs. + * + * @param[in] dev_fn The device file name + * + * @return A valid device handle on success, else ::MBG_INVALID_DEV_HANDLE + * + * @ingroup mbgdevio_open_fncs + * @see ::mbg_close_device + * @see @ref mbgdevio_open_fncs + * @see ::MBG_DEV_FN + */ +_MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device_by_dev_fn( const char *dev_fn ) { #if defined( MBG_TGT_WIN32 ) - HANDLE dh; - int ret = 0; - BOOL usb = FALSE; - - if ( hw_id == NULL ) - goto fail; + if ( dev_fn == NULL ) + { + SetLastError( ERROR_INVALID_PARAMETER ); // TODO Is this error code appropriate? + return MBG_INVALID_DEV_HANDLE; + } - dh = CreateFile( - hw_id, // file name + return CreateFileA( + dev_fn, // file name GENERIC_READ | GENERIC_WRITE, // access mode 0, // share mode NULL, // security descriptor OPEN_EXISTING, // how to create - strstr(hw_id,"usb") ? FILE_FLAG_OVERLAPPED : 0, // file attributes + strstr( dev_fn, "usb" ) ? FILE_FLAG_OVERLAPPED : 0, // file attributes NULL // handle to template file ); - if ( INVALID_HANDLE_VALUE == dh ) - goto fail; - - return dh; +#elif defined( MBG_TGT_POSIX ) && !defined( MBG_TGT_QNX_NTO ) -fail: - return MBG_INVALID_DEV_HANDLE; - -#elif defined ( MBG_TGT_UNIX ) - - MBG_DEV_HANDLE dh = -1; - - if ( strlen( hw_id ) > 0 ) - dh = open( hw_id, O_RDWR ); + if ( dev_fn == NULL ) + { + errno = EFAULT; // Bad address, invalid pointer + return MBG_INVALID_DEV_HANDLE; + } - return ( dh < 0 ) ? MBG_INVALID_DEV_HANDLE : dh; + return open( dev_fn, O_RDWR ); #else + errno = ( dev_fn == NULL ) ? EFAULT : ENODEV; return MBG_INVALID_DEV_HANDLE; #endif -} // mbg_open_device_by_hw_id +} // mbg_open_device_by_dev_fn + /*HDR*/ /** - Get the number of supported devices installed on the computer. - This function is <b>out of date</b>, mbg_find_devices_with_names() - should be used instead. + * @brief Open a device specified by a device file name + * + * @deprecated This function is deprecated, use + * ::mbg_open_device_by_dev_fn preferably. + * + * The format the device file name depends on the operating system. + * see ::MBG_DEV_FN. + * + * For details and similar functions see @ref mbgdevio_open_fncs. + * + * @param[in] dev_fn The device file name, see ::MBG_DEV_FN + * + * @return A valid device handle on success, else ::MBG_INVALID_DEV_HANDLE + * + * @ingroup mbgdevio_open_fncs + * @see ::mbg_close_device + * @see @ref mbgdevio_open_fncs + * @see ::MBG_DEV_FN + */ +_MBG_API_ATTR MBG_DEV_HANDLE _DEPRECATED_BY( "mbg_open_device_by_dev_fn" ) _MBG_API mbg_open_device_by_hw_id( const char *dev_fn ) +{ + return mbg_open_device_by_dev_fn( dev_fn ); - <b>Note:</b> This function is out of date since it may not work - correctly for Meinberg devices which are disconnected and reconnected - while the system is running (e.g. USB devices). However, the function - will be kept for compatibility reasons and works correctly if all - Meinberg devices are connected at system boot and are not disconnected - and reconnected during operation +} // mbg_open_device_by_hw_id - @return The number of devices found. - @see mbg_find_devices_with_names() - */ + +/*HDR*/ +/** + * @brief Get the number of devices installed on the computer + * + * The function ::mbg_find_devices_with_names should eventually + * be used preferafly. See @ref mbgdevio_open_fncs. + * + * @return The number of devices found + * + * @see ::mbg_find_devices_with_names + * @see ::mbg_open_device + * @see @ref mbgdevio_open_fncs + */ _MBG_API_ATTR int _MBG_API mbg_find_devices( void ) { #if defined( _PCPSDRVR_H ) #if defined( MBG_TGT_QNX_NTO ) // Since this program accessed the hardware directly - // I/O privileges must be assigned to the thread. + // I/O privileges have to be assigned to the thread. if ( ThreadCtl( _NTO_TCTL_IO, NULL ) == -1 ) { - perror( "Fatal error" ); + fprintf( stderr, "** ThreadCtl() failed to request I/O privileges: %s\n\n", strerror( errno ) ); exit( 1 ); } #endif @@ -784,11 +3442,11 @@ _MBG_API_ATTR int _MBG_API mbg_find_devices( void ) pcps_detect_any_tsr(); prv_busy = pcps_tsr_set_busy_flag( 1 ); - pcps_detect_clocks( pcps_isa_ports, NULL ); + pcps_detect_devices( pcps_isa_ports, NULL ); pcps_tsr_set_busy_flag( prv_busy ); } #else - pcps_detect_clocks( pcps_isa_ports, NULL ); + pcps_detect_devices( pcps_isa_ports, NULL ); #endif return n_ddevs; @@ -797,13 +3455,13 @@ _MBG_API_ATTR int _MBG_API mbg_find_devices( void ) return mbg_svc_find_devices(); -#elif defined ( MBG_TGT_UNIX ) + #elif defined( MBG_TGT_POSIX ) MBG_DEV_HANDLE dh; int i = 0; int n = 0; - while( i < MBG_MAX_DEVICES ) + while ( i < N_SUPP_DEV_BUS ) { dh = mbg_open_device( i ); @@ -824,457 +3482,573 @@ _MBG_API_ATTR int _MBG_API mbg_find_devices( void ) -#if defined( MBG_TGT_WIN32 ) || defined ( MBG_TGT_UNIX ) +#if MBG_TGT_HAS_DEV_FN +/** + * @brief Free a list of device names that has been allocated before + * + * This function should be called to free a list that has been + * allocated by ::setup_dev_fn_list. + * + * @param[out] list Pointer to a list to be allocated and + * + * @see ::setup_dev_fn_list + * @see ::setup_dev_details_from_dev_fn + */ static /*HDR*/ -int mbg_find_devices_with_hw_id( MBG_DEVICE_LIST ** list, int max_devs ) +void free_dev_fn_list( MBG_DEV_FN_LIST_ENTRY *list ) { - #if defined ( MBG_TGT_WIN32 ) - - return mbg_svc_find_devices_with_hw_id( list, max_devs ); - - #elif defined ( MBG_TGT_UNIX ) - - MBG_DEVICE_LIST *ListBegin; - int n = 0; - int i = 0; - - (*list) = (MBG_DEVICE_LIST *) malloc( sizeof( **list ) ); - memset( *list, 0, sizeof( **list ) ); - - ListBegin = (*list); - - for (;;) + #if defined( MBG_TGT_WIN32 ) + mbg_svc_free_device_list( list ); // TODO + #else + while ( list ) { - char dev_name[100]; - MBG_DEV_HANDLE dh; - - sprintf( dev_name, "/dev/mbgclock%d", i ); + MBG_DEV_FN_LIST_ENTRY *next; - dh = mbg_open_device_by_hw_id( dev_name ); - - if ( dh != MBG_INVALID_HANDLE ) + if ( list->dev_fn_ptr ) { - mbg_close_device( &dh ); - - (*list)->device_path = (char *) malloc( strlen( dev_name ) + 1 ); - strcpy( (*list)->device_path, dev_name ); - - (*list)->next = (MBG_DEVICE_LIST *) malloc( sizeof( **list ) ); - (*list) = (*list)->next; - - memset( *list, 0, sizeof( **list ) ); - n++; + free( list->dev_fn_ptr ); + list->dev_fn_ptr = NULL; } - if ( ++i >= MBG_MAX_DEVICES ) - break; + next = list->next; + free( list ); + list = next; } + #endif - if ( n > 0 ) - *list = ListBegin; - else - { - free( *list ); - *list = NULL; - } +} // free_dev_fn_list - return n; +#endif // MBG_TGT_HAS_DEV_FN - #else - return 0; - - #endif -} -#endif +#if MBG_TGT_HAS_DEV_FN +static /*HDR*/ +/** + * @brief Allocate and fill a list of device file names + * + * The function ::setup_dev_details_from_dev_fn can be called + * to get the model name / serial number ID associated with + * the device file name. + * + * The function ::free_dev_fn_list should be called when the + * returned list has been evaliuated and isn't needed anymore. + * + * @param[out] p_list Pointer to a list to be allocated and + * set up, set to NULL if no devices were found. + * @param[in] max_devs Max. number of devices to be added to the list. + * + * @return The number of devices found + * + * @see ::free_dev_fn_list + * @see ::setup_dev_details_from_dev_fn + */ +int setup_dev_fn_list( MBG_DEV_FN_LIST_ENTRY **p_list, int max_devs ) +{ + // The way to retrieve a list of devices currently present + // in the system depends on the operating system. + #if defined( MBG_TGT_WIN32 ) -#if defined ( MBG_TGT_WIN32 ) || defined ( MBG_TGT_UNIX ) + return mbg_svc_find_devices_with_hw_id( p_list, max_devs ); -static /*HDR*/ -void _MBG_API mbg_free_device_list( MBG_DEVICE_LIST *devices ) -{ + #elif defined( MBG_TGT_POSIX ) - #if defined ( MBG_TGT_WIN32 ) - mbg_svc_free_device_list( devices ); - #else - int i = 0; - MBG_DEVICE_LIST *Next = NULL; + MBG_DEV_FN_LIST_ENTRY *list_head = NULL; + MBG_DEV_FN_LIST_ENTRY *pos = NULL; + int n_dev_fn = 0; + int i; - while ( i < MBG_MAX_DEVICES) + for ( i = 0; i < max_devs; i++ ) { - if ( devices ) + MBG_DEV_FN dev_fn; + MBG_DEV_HANDLE dh; + + mbg_dev_fn_from_dev_idx( dev_fn, sizeof( dev_fn ), i ); + dh = mbg_open_device_by_dev_fn( dev_fn ); + + if ( dh != MBG_INVALID_DEV_HANDLE ) { - if ( devices->device_path ) - { - free( devices->device_path ); - devices->device_path = NULL; - } + size_t sz = strlen( dev_fn ) + 1; // including terminating 0 - if ( devices->next ) + if ( list_head == NULL ) // first turn { - Next = devices->next; - free(devices); - devices = Next; + list_head = (MBG_DEV_FN_LIST_ENTRY *) calloc( 1, sizeof( *list_head ) ); + pos = list_head; } else { - if ( devices ) - { - free( devices ); - devices = NULL; - } - break; + pos->next = (MBG_DEV_FN_LIST_ENTRY *) calloc( 1, sizeof( *pos ) ); + pos = pos->next; } - } - else - break; - i++; + if ( pos == NULL ) + goto out_free; + + pos->dev_fn_ptr = (char *) calloc( 1, sz ); + + if ( pos->dev_fn_ptr == NULL ) + goto out_free; + + strncpy_safe( pos->dev_fn_ptr, dev_fn, sz ); + n_dev_fn++; + + mbg_close_device( &dh ); + } } + if ( n_dev_fn ) + goto out; + + +out_free: + free_dev_fn_list( list_head ); + list_head = NULL; + n_dev_fn = 0; + +out: + *p_list = list_head; // Return the list + return n_dev_fn; + + #else + + *p_list = NULL; + return 0; + #endif -} -#endif +} // setup_dev_fn_list + +#endif // MBG_TGT_HAS_DEV_FN -#if ( defined( MBG_TGT_WIN32 ) || defined ( MBG_TGT_UNIX ) ) +#if MBG_TGT_HAS_DEV_FN static /*HDR*/ -void get_hw_name_from_hw_id( MBG_DEVICE_INFO *dev_info ) +/** + * @brief Open a device, retrieve the ::PCPS_DEV info, then close it + * + * @param[out] p Pointer to a ::PCPS_DEV to be filled. + * @param[in] dev_fn The device file name of the device to be used. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ +int get_dev_info_for_dev_fn( PCPS_DEV *p, const char *dev_fn ) { MBG_DEV_HANDLE dh; - PCPS_DEV pdev; + int rc; - dh = MBG_INVALID_HANDLE; - memset( &pdev, 0, sizeof( pdev ) ); + memset( p, 0, sizeof( *p ) ); - // Default initializers - strcpy( dev_info->model_name, "N/A" ); - strcpy( dev_info->serial_number, "N/A" ); - strcpy( dev_info->hw_name, "N/A" ); + // Try to retrieve device information. + dh = mbg_open_device_by_dev_fn( dev_fn ); - dh = mbg_open_device_by_hw_id( dev_info->hardware_id ); + if ( dh == MBG_INVALID_DEV_HANDLE ) + return mbg_get_last_error( NULL ); - if ( dh != MBG_INVALID_HANDLE ) - { - if ( mbg_get_device_info( dh, &pdev ) == MBG_SUCCESS ) - { - strcpy( dev_info->model_name, _pcps_type_name( &pdev ) ); - strcpy( dev_info->serial_number, _pcps_sernum( &pdev ) ); - sprintf( dev_info->hw_name, "%s_%s", _pcps_type_name( &pdev ), _pcps_sernum( &pdev ) ); - } + rc = mbg_get_device_info( dh, p ); - mbg_close_device( &dh ); - } + mbg_close_device( &dh ); -} // get_hw_name_from_hw_id + return rc; -#endif +} // get_dev_info_for_dev_fn +#endif // MBG_TGT_HAS_DEV_FN -/*HDR*/ + +#if MBG_TGT_HAS_DEV_FN + +static /*HDR*/ /** - Return the number of supported devices installed on the system and - set up a list of unique names of those devices. + * @brief Create a string with a unique device name + * + * The device name is composed of the device's type name and + * its serial number which is appended after an underscore '_'. + * So the string buffer is typically an ::MBG_DEV_NAME. + * + * @param[out] s Pointer to the output buffer for the string. + * @param[in] max_len Size of the output buffer. + * @param[in] p_dev Pointer to a ::PCPS_DEV structure providing the required information. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::MBG_DEV_NAME + */ +int snprint_dev_name( char *s, size_t max_len, const PCPS_DEV *p_dev ) +{ + size_t n = snprintf_safe( s, max_len, "%s_%s", + _pcps_type_name( p_dev ), _pcps_sernum( p_dev ) ); + return _int_from_size_t( n ); - This function should be used preferably instead of mbg_find_devices(). +} // snprint_dev_name - @param device_list Pointer to a linked list of type ::MBG_DEVICENAME_LIST - with device names. The list will be allocated by this - function and has to be freed after usage by calling - mbg_free_device_name_list(). - @param max_devices Maximum number of devices the function should look for - (can not exceed ::MBG_MAX_DEVICES). +#endif // MBG_TGT_HAS_DEV_FN - @return Number of present devices - @see ::MBG_HW_NAME for the format of the unique names - @see mbg_free_device_name_list() - @see mbg_find_devices() - */ -_MBG_API_ATTR int _MBG_API mbg_find_devices_with_names( MBG_DEVICENAME_LIST **device_list, - int max_devices ) + +static /*HDR*/ +/** + * @brief Lookup a specific device in an array of ::PCPS_DEV structures + * + * Look for a matching name, if a type name is specified, and for + * a matching serial number if that is also given. + * + * @param[in] dev_array The array of ::PCPS_DEV structures to be searched. + * @param[in] n_dev The number of entries in @p dev_array. + * @param[in] type_name An optional type name to search for, may be NULL. + * @param[in] sernum An optional serial number to search for, may be NULL. + * + * @return An index value >= 0 on success, or -1 if no entry was found + * + * @see ::lookup_dev_idx_ex + */ +int lookup_dev_idx( const PCPS_DEV *dev_array, int n_dev, + const char *type_name, const char *sernum ) { -#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX ) + int i; - MBG_DEVICE_LIST *hardware_list = NULL; - MBG_DEVICE_LIST *hardware_list_begin = NULL; - MBG_DEVICENAME_LIST *ListBegin = NULL; - MBG_DEVICE_INFO dev_info; + for ( i = 0; i < n_dev; i++ ) + { + const PCPS_DEV *p_dev = &dev_array[i]; - int n_devices = 0; - int i = 0; + if ( type_name && strcmp( _pcps_type_name( p_dev ), type_name ) ) + continue; // Type name given, but doesn't match. - n_devices = mbg_find_devices_with_hw_id( &hardware_list, max_devices ); + if ( sernum && strcmp( _pcps_sernum( p_dev ), sernum ) ) + continue; // Serial number given, but doesn't match. - hardware_list_begin = hardware_list; + return i; // Matching device found. + } - if ( n_devices ) - { - *device_list = (MBG_DEVICENAME_LIST *) malloc( sizeof( MBG_DEVICENAME_LIST ) ); - (*device_list)->next = NULL; + return -1; // No matching device found. - // Save begin of the list - ListBegin = *device_list; +} // lookup_dev_idx - // Loop through the list of hardware_ids and get their readable names - for (;;) - { - if ( hardware_list->device_path && i++ < MBG_MAX_DEVICES ) - { - strcpy( dev_info.hardware_id, hardware_list->device_path ); - get_hw_name_from_hw_id( &dev_info ); - strcpy( (*device_list)->device_name, dev_info.hw_name ); +static /*HDR*/ +/** + * @brief Lookup a specific device in an array, depending on a match code + * + * The function first looks for an exact match of type name + * and serial number, then for a matching type name only, if + * @p selection_mode allows, and if no matching devic model + * can be found at all, returns the index of the first device + * found, if an appropriate @p selection_mode has been specified. + * + * @param[in] dev_array The array of ::PCPS_DEV structures to be searched. + * @param[in] n_dev The number of entries in @p dev_array. + * @param[in] type_name An optional type name to search for, may be NULL. + * @param[in] sernum An optional serial number to search for, may be NULL. + * @param[in] selection_mode One of the ::MBG_MATCH_MODES. + * + * @return An index value >= 0 on success, or -1 if no entry was found + * + * @see ::lookup_dev_idx + * @see ::MBG_MATCH_MODES + */ +int lookup_dev_idx_ex( const PCPS_DEV *dev_array, int n_dev, + const char *type_name, const char *sernum, + int selection_mode ) +{ + int dev_idx = -1; - if ( hardware_list->next ) - { - hardware_list = hardware_list->next; - (*device_list)->next = (MBG_DEVICENAME_LIST *) malloc( sizeof( MBG_DEVICENAME_LIST ) ); - (*device_list) = (*device_list)->next; - (*device_list)->next = NULL; - } - else - break; - } - else - break; - } + if ( n_dev == 0 ) // no devices available + goto out; - *device_list = ListBegin; - } + dev_idx = lookup_dev_idx( dev_array, n_dev, type_name, sernum ); - if ( hardware_list_begin ) - mbg_free_device_list( hardware_list_begin ); + if ( dev_idx >= 0 ) + goto out; - return n_devices; -#else + // The requested combination of a clock model name and + // serial number was not found. If an exact match was + // requested then we're done anyway. + if ( selection_mode == MBG_MATCH_EXACTLY ) + goto out; - return 0; -#endif + // Look for device with matching name only, ignoring + // the serial number. + dev_idx = lookup_dev_idx( dev_array, n_dev, type_name, NULL ); -} // mbg_find_devices_with_names + if ( dev_idx >= 0 ) + goto out; + + + // As a last resort select the first device that + // has been found, if the selection mode allows. + if ( selection_mode == MBG_MATCH_ANY ) + dev_idx = 0; + +out: + return dev_idx; + +} // lookup_dev_idx_ex /*HDR*/ /** - Free the memory of the ::MBG_DEVICENAME_LIST that has been allocated before - by mbg_find_devices_with_names(). + * @brief Allocate memory and set up a list of installed and supported devices + * + * Allocate and fill a list with the names of Meinberg devices currently + * present in the system. + * + * This can be used e.g. to populate a device selection dialog + * in a configuration program. + * + * When the list is not used anymore it can be freed by calling + * ::mbg_free_device_name_list. + * + * @param[in] p_list Pointer to a linked list to be allocated. + * @param[in] max_devices Maximum number of devices to be searched for + * (must not exceed ::N_SUPP_DEV_BUS). + * + * @return The number of present devices + * + * @see ::mbg_free_device_name_list + * @see ::mbg_find_devices + * @see ::MBG_DEV_NAME + */ +_MBG_API_ATTR int _MBG_API mbg_find_devices_with_names( MBG_DEV_NAME_LIST_ENTRY **p_list, + int max_devices ) +{ +#if MBG_TGT_HAS_DEV_FN - @param *list Linked list of type ::MBG_DEVICENAME_LIST + MBG_DEV_FN_LIST_ENTRY *dev_fn_list_head = NULL; + MBG_DEV_FN_LIST_ENTRY *dev_fn_pos = NULL; - @see mbg_find_devices_with_names() - */ -_MBG_API_ATTR void _MBG_API mbg_free_device_name_list( MBG_DEVICENAME_LIST *list) -{ -#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX ) + MBG_DEV_NAME_LIST_ENTRY *list_head = NULL; + MBG_DEV_NAME_LIST_ENTRY *pos = NULL; - MBG_DEVICENAME_LIST *Next = NULL; - int i = 0; + int n_dev_fn = 0; + int n_dev_name = 0; - // Deallocate members of linked list - while ( i < MBG_MAX_DEVICES ) - { - if ( list ) - { - Next = list->next; + // First set up a list of device names, the format of which + // depends on the OS. + n_dev_fn = setup_dev_fn_list( &dev_fn_list_head, max_devices ); - free( list ); - list = NULL; + // Now iterate through the device *file name* list + // and set up a *device name* list. + for ( dev_fn_pos = dev_fn_list_head; dev_fn_pos; dev_fn_pos = dev_fn_pos->next ) + { + PCPS_DEV dev; + int rc; - if ( Next ) - list = Next->next; - else - break; + if ( list_head == NULL ) // first turn + { + list_head = (MBG_DEV_NAME_LIST_ENTRY *) calloc( 1, sizeof( *list_head ) ); + pos = list_head; } else + { + pos->next = (MBG_DEV_NAME_LIST_ENTRY *) calloc( 1, sizeof( *pos ) ); + pos = pos->next; + } + + if ( pos == NULL ) // failed to allocate memory + { + mbg_free_device_name_list( list_head ); // free this list + list_head = NULL; + n_dev_name = 0; break; + } + + // Get device details for the device. + rc = get_dev_info_for_dev_fn( &dev, dev_fn_pos->dev_fn_ptr ); + + if ( mbg_rc_is_success( rc ) ) + snprint_dev_name( pos->dev_name, sizeof( pos->dev_name ), + &dev ); - i++; + if ( ++n_dev_name > n_dev_fn ) // This should never happen + break; } -#endif + // Free the device name list which we don't need anymore + free_dev_fn_list( dev_fn_list_head ); -} // mbg_free_device_list + *p_list = list_head; // Return the list + return n_dev_name; +#else -/*HDR*/ -/** - Return a handle to a device with a certain unique name. - The names of the devices that are installed on the system can be retrieved by - the function mbg_find_devices_with_names(). + *p_list = NULL; + return 0; - This function should be used preferably instead of mbg_open_device(). +#endif - @param hw_name String with the unique name of the device to be opened - @param selection_mode One of the enum values of ::MBG_MATCH_MODE +} // mbg_find_devices_with_names - @return On success, the function returns a handle to the device, otherwise ::MBG_INVALID_DEV_HANDLE - @see ::MBG_HW_NAME for the format of the unique names. - @see ::MBG_MATCH_MODE - @see mbg_find_devices_with_names() - */ -_MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device_by_name( const char* hw_name, int selection_mode ) //##++++ -{ -#if ( defined( MBG_TGT_WIN32 ) || defined ( MBG_TGT_UNIX ) ) +/*HDR*/ +/** + * @brief Free the memory allocated for a list of ::MBG_DEV_NAME_LIST_ENTRY entries. + * + * The list may have been set up and allocated before + * by ::mbg_find_devices_with_names. + * + * @param[in,out] list Linked list of ::MBG_DEV_NAME_LIST_ENTRY entries. + * + * @see ::mbg_find_devices_with_names + */ +_MBG_API_ATTR void _MBG_API mbg_free_device_name_list( MBG_DEV_NAME_LIST_ENTRY *list ) +{ + while ( list ) + { + MBG_DEV_NAME_LIST_ENTRY *next = list->next; - MBG_DEV_HANDLE dh; + free( list ); + list = next; + } - MBG_DEVICE_LIST *devices = NULL; - MBG_DEVICE_LIST *ListBegin = NULL; - char hw_id[MAX_INFO_LEN]; - char tmp_model_name[PCPS_CLOCK_NAME_SZ]; - PCPS_SN_STR tmp_sn; - int n_devices = 0; - int i = 0; - int j = 0; +} // mbg_free_device_name_list - hw_id[0] = '\0'; - memset( tmp_model_name, 0, sizeof( tmp_model_name) ); - memset( device_info_list, 0, sizeof( device_info_list ) ); - memset( tmp_sn, 0, sizeof( tmp_sn ) ); - // separate hw_name into clock model and serial number - if ( hw_name && ( strlen( hw_name ) > 0 ) ) +/*HDR*/ +/** + * @brief Return a handle to a device with a particular device name + * + * See ::MBG_DEV_NAME for the possible formats of a device name. + * + * For details and similar functions see @ref mbgdevio_open_fncs. + * + * @param[in] srch_name String with the ::MBG_DEV_NAME of a device to be opened + * @param[in] selection_mode One of the ::MBG_MATCH_MODES + * + * @return A valid device handle on success, else ::MBG_INVALID_DEV_HANDLE + * + * @ingroup mbgdevio_open_fncs + * @see ::mbg_close_device + * @see @ref mbgdevio_open_fncs + * @see ::MBG_DEV_NAME + * @see ::MBG_MATCH_MODES + */ +_MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device_by_name( const char *srch_name, int selection_mode ) +{ + PCPS_DEV dev_array[N_SUPP_DEV_BUS] = { { { 0 } } }; + PCPS_CLOCK_NAME type_name = { 0 }; + PCPS_SN_STR sernum = { 0 }; + size_t srch_name_len = 0; + size_t i = 0; + const char *cp; + char c; + int dev_idx = -1; + + if ( srch_name ) + srch_name_len = strlen( srch_name ); + + if ( srch_name_len ) { - // clock model - for ( i = 0; ( i < PCPS_CLOCK_NAME_SZ ) && ( hw_name[i] != '_' ) && ( (unsigned int) i < strlen( hw_name ) ); i++ ) - tmp_model_name[i] = hw_name[i]; - - tmp_model_name[i] = 0; - i++; + // clock model name + cp = srch_name; + i = 0; - // serial number - if ( ( unsigned int ) i < strlen( hw_name ) ) + for (;;) { - j = 0; + c = *cp++; - while( ( unsigned int ) i < strlen(hw_name) && j < PCPS_SN_SIZE ) - { - tmp_sn[j] = hw_name[i]; - j++; - i++; - } - tmp_sn[j] = '\0'; - } - } - else - goto fail; + if ( c == 0 ) // end of string + break; - i = 0; + if ( c == '_' ) // separator before S/N + break; + + type_name[i] = ( c >= 'a' && c <= 'z' ) ? ( c - 0x20 ) : c; - // get OS-dependent hardware_id strings for devices that are present on the system - n_devices = mbg_find_devices_with_hw_id( &devices, MBG_MAX_DEVICES ); + if ( ++i >= ( sizeof( type_name ) - 1 ) ) + break; + } - ListBegin = devices; + type_name[i] = 0; // terminate string - if ( n_devices ) - { - for (;;) + if ( c == '_' ) { - if ( devices->device_path && i < MBG_MAX_DEVICES ) - { - strncpy( device_info_list[i].hardware_id, devices->device_path, MAX_INFO_LEN ); + // Serial number + i = 0; - // get readable hw_name for the device - get_hw_name_from_hw_id( &device_info_list[i] ); + for (;;) + { + c = *cp++; - if ( hw_name && device_info_list[i].hw_name && strcmp( device_info_list[i].hw_name, hw_name ) == 0 ) //##+++++ - { - // The requested device was found - strcpy( hw_id, device_info_list[i].hardware_id ); + if ( c == 0 ) // end of string break; - } - else if ( devices->next ) - devices = devices->next; - else + + if ( c < '0' || c > '9' ) // not a digit break; - } - else - break; - i++; - } - // If the requested CLOCK_MODEL/SN combination was not found, - // decide what to do depending on the selection mode - if ( ( hw_id[0] == '\0' ) && ( selection_mode != MBG_MATCH_EXACTLY ) ) - { - for ( j = 0; j <= i; j++ ) - { - // Search for the same clock model - if ( ( tmp_model_name[0] != '\0' ) && strcmp( device_info_list[j].model_name, tmp_model_name ) == 0 ) - { - strcpy( hw_id, device_info_list[j].hardware_id ); + sernum[i] = c; + + if ( ++i >= ( sizeof( sernum ) - 1 ) ) break; - } } - // Finally select the first device found on the system, if the clock model was not found - if ( ( selection_mode == MBG_MATCH_ANY ) && ( hw_id[0] == '\0' ) ) - strcpy( hw_id, device_info_list[0].hardware_id ); + sernum[i] = 0; // terminate string } } - mbg_free_device_list( ListBegin ); - -#endif + #if MBG_TGT_HAS_DEV_FN + { + MBG_DEV_FN dev_fn_array[N_SUPP_DEV_BUS] = { { 0 } }; + MBG_DEV_FN_LIST_ENTRY *list_head = NULL; -#if defined ( MBG_TGT_WIN32 ) + // Set up a temporary list with file names of devices + // that are currently present in the system. + int n_devices = setup_dev_fn_list( &list_head, N_SUPP_DEV_BUS ); - if ( hw_id[0] == '\0' ) - goto fail; - - dh = CreateFile( - hw_id, // file name - GENERIC_READ | GENERIC_WRITE, // access mode - 0, // share mode - NULL, // security descriptor - OPEN_EXISTING, // how to create - strstr(hw_id,"usb") ? FILE_FLAG_OVERLAPPED : 0, // file attributes - NULL // handle to template file - ); + if ( n_devices ) + { + MBG_DEV_FN_LIST_ENTRY *pos; - if ( INVALID_HANDLE_VALUE == dh ) - goto fail; + for ( i = 0, pos = list_head; pos && pos->dev_fn_ptr; pos = pos->next ) + { + int rc = get_dev_info_for_dev_fn( &dev_array[i], pos->dev_fn_ptr ); - return dh; + if ( mbg_rc_is_success( rc ) ) + { + // Save the associated device file name. + sn_cpy_str_safe( dev_fn_array[i], sizeof( dev_fn_array[i] ), pos->dev_fn_ptr ); + i++; + } + } -fail: - return MBG_INVALID_DEV_HANDLE; + dev_idx = lookup_dev_idx_ex( dev_array, i, type_name, sernum, selection_mode ); + } -#elif defined ( MBG_TGT_UNIX ) + free_dev_fn_list( list_head ); - if ( hw_id[0] != '\0' ) - dh = open( hw_id, O_RDWR ); - else - goto fail; + // We even try to open the device if no match was found. + // This causes an "invalid device handle" value to be + // returned, and sets an appropriate "last error" code. + return mbg_open_device_by_dev_fn( ( dev_idx >= 0 ) ? dev_fn_array[dev_idx] : "" ); + } + #else + #if defined( _PCPSDRVR_H ) + mbg_find_devices(); - return ( dh < 0 ) ? MBG_INVALID_DEV_HANDLE : dh; + for ( i = 0; i < n_ddevs; i++ ) + dev_array[i] = pcps_ddev[i].dev; -fail: - return MBG_INVALID_DEV_HANDLE; + dev_idx = lookup_dev_idx_ex( dev_array, i, type_name, sernum, selection_mode ); -#else + if ( dev_idx >= 0 ) + return mbg_open_device( dev_idx ); + #endif - //return ( device_index < n_ddevs ) ? &pcps_ddev[device_index] : NULL; - return MBG_INVALID_DEV_HANDLE; + errno = ENODEV; + return MBG_INVALID_DEV_HANDLE; -#endif + #endif } // mbg_open_device_by_name @@ -1282,18 +4056,19 @@ fail: /*HDR*/ /** - Close a handle to a device and set the handle value to ::MBG_INVALID_DEV_HANDLE. - If required, unmap mapped memory. - - @param dev_handle Handle to a Meinberg device. - */ + * @brief Close a device handle and set the handle value to ::MBG_INVALID_DEV_HANDLE + * + * @param[in,out] dev_handle Pointer to a Meinberg device handle + * + * @see @ref mbgdevio_open_fncs + */ _MBG_API_ATTR void _MBG_API mbg_close_device( MBG_DEV_HANDLE *dev_handle ) { if ( *dev_handle != MBG_INVALID_DEV_HANDLE && *dev_handle != 0 ) //##++++ dev_handle NULL/0 ??? { #if defined( MBG_TGT_WIN32 ) CloseHandle( *dev_handle ); - #elif defined( MBG_TGT_UNIX ) + #elif defined( MBG_TGT_POSIX ) && !defined( MBG_TGT_QNX_NTO ) close( *dev_handle ); #endif } @@ -1306,24 +4081,21 @@ _MBG_API_ATTR void _MBG_API mbg_close_device( MBG_DEV_HANDLE *dev_handle ) /*HDR*/ /** - Return a ::PCPS_DRVR_INFO structure that provides information - about the kernel device driver. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_DRVR_INFO structure which is filled up. - - @return ::MBG_SUCCESS or error code returned by device I/O control function - */ + * @brief Read information about the driver handling a given device + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p A ::PCPS_DRVR_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ _MBG_API_ATTR int _MBG_API mbg_get_drvr_info( MBG_DEV_HANDLE dh, PCPS_DRVR_INFO *p ) { #if defined( _MBGIOCTL_H ) - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, -1, IOCTL_GET_PCPS_DRVR_INFO, p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); #else - #if defined( __BORLANDC__ ) - dh; // avoid warnings "never used" - #endif + (void) dh; // avoid warning "never used" drvr_info.n_devs = n_ddevs; *p = drvr_info; return MBG_SUCCESS; @@ -1335,20 +4107,20 @@ _MBG_API_ATTR int _MBG_API mbg_get_drvr_info( MBG_DEV_HANDLE dh, PCPS_DRVR_INFO /*HDR*/ /** - Return a ::PCPS_DEV structure that provides detailed information about the device. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_DEV structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function - */ + * @brief Read detailed device information + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] *p A ::PCPS_DEV structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ _MBG_API_ATTR int _MBG_API mbg_get_device_info( MBG_DEV_HANDLE dh, PCPS_DEV *p ) { #if defined( _MBGIOCTL_H ) - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, -1, IOCTL_GET_PCPS_DEV, p ); // Endianess is converted inside the kernel driver, if necessary. - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); #else *p = dh->dev; return MBG_SUCCESS; @@ -1360,22 +4132,26 @@ _MBG_API_ATTR int _MBG_API mbg_get_device_info( MBG_DEV_HANDLE dh, PCPS_DEV *p ) /*HDR*/ /** - Return the current state of the on-board::PCPS_STATUS_PORT. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_STATUS_PORT value to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function - - @see \ref group_status_port "bitmask" - */ + * @brief Read the current state of the on-board ::PCPS_STATUS_PORT + * + * This function is useful to read the device's status port which + * also includes the ::PCPS_ST_MOD bit reflecting the time code + * modulation of long wave receivers. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p A ::PCPS_STATUS_PORT value to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see @ref group_status_port "bitmask" //### TODO check syntax + */ _MBG_API_ATTR int _MBG_API mbg_get_status_port( MBG_DEV_HANDLE dh, PCPS_STATUS_PORT *p ) { #if defined( _MBGIOCTL_H ) - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, -1, IOCTL_GET_PCPS_STATUS_PORT, p ); // No endianess conversion required. - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); #else *p = _pcps_ddev_read_status_port( dh ); // No endianess conversion required. @@ -1388,33 +4164,33 @@ _MBG_API_ATTR int _MBG_API mbg_get_status_port( MBG_DEV_HANDLE dh, PCPS_STATUS_P /*HDR*/ /* (Intentionally excluded from Doxygen) - Generic read function which writes a command code to the device - and reads a number of replied data to a generic buffer. - - <b>Warning</b>: This is for debugging purposes only! - The specialized API calls should be used preferably. - A specific device may not support any command code. - - @param dh Valid handle to a Meinberg device - @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device - @param *p Pointer to a buffer to be filled up - @param size Size of the buffer *p - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_generic_write() - @see mbg_generic_read_gps() - @see mbg_generic_write_gps() - @see mbg_generic_io() - */ + * Generic read function which writes a command code to a device + * and reads a number of replied data to a generic buffer. + * + * <b>Warning</b>: This is for debugging purposes only! + * The specialized API calls should be used preferably. + * Not all devices support each of the ::PC_GPS_COMMANDS. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] cmd Can be any @ref PCPS_CMD_CODES "command code" supported by the device + * @param[out] p Pointer to a buffer to be filled up + * @param[in] size Size of the output buffer + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_generic_write + * @see ::mbg_generic_read_gps + * @see ::mbg_generic_write_gps + * @see ::mbg_generic_io + */ _MBG_API_ATTR int _MBG_API mbg_generic_read( MBG_DEV_HANDLE dh, int cmd, void *p, int size ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_gen_read( dh, cmd, p, size ); - // No type information available, so endianess must be + // No type information available, so endianess has to be // converted by the caller, if required. - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_generic_read @@ -1422,36 +4198,36 @@ _MBG_API_ATTR int _MBG_API mbg_generic_read( MBG_DEV_HANDLE dh, int cmd, /*HDR*/ /* (Intentionally excluded from Doxygen) - Generic read function which writes a GPS command code to the device - and reads a number of replied data to a generic buffer. - The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data() - check whether this call is supported by a specific card. - - <b>Warning</b>: This is for debugging purposes only! - The specialized API calls should be used preferably. - A specific device may not support any GPS command code. - - @param dh Valid handle to a Meinberg device - @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device. - @param *p Pointer to a buffer to be filled up - @param size Size of the buffer *p - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_gps_data() - @see mbg_generic_write_gps() - @see mbg_generic_read() - @see mbg_generic_write() - @see mbg_generic_io() - */ + * Generic read function which writes a GPS command code to a device + * and reads a number of data bytes back into a generic buffer. + * The function ::mbg_chk_dev_has_gps_data can be used to check + * whether this call is supported by a device. + * + * <b>Warning</b>: This is for debugging purposes only! + * The specialized API calls should be used preferably. + * Not all devices support each of the ::PC_GPS_COMMANDS. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] cmd One of the ::PCPS_CMD_CODES supported by the device. + * @param[out] p Pointer to a buffer to be filled up + * @param[in] size Size of the buffer, has to match the expected data size associated with cmd + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_gps_data + * @see ::mbg_generic_write_gps + * @see ::mbg_generic_read + * @see ::mbg_generic_write + * @see ::mbg_generic_io + */ _MBG_API_ATTR int _MBG_API mbg_generic_read_gps( MBG_DEV_HANDLE dh, int cmd, void *p, int size ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_gen_read_gps( dh, cmd, p, size ); - // No type information available, so endianess must be + // No type information available, so endianess has to be // converted by the caller, if required. - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_generic_read_gps @@ -1459,33 +4235,33 @@ _MBG_API_ATTR int _MBG_API mbg_generic_read_gps( MBG_DEV_HANDLE dh, int cmd, /*HDR*/ /* (Intentionally excluded from Doxygen) - Generic write function which writes a command code plus an - associated number of data bytes to the device. - - <b>Warning</b>: This is for debugging purposes only! - The specialized API calls should be used preferably. - A specific device may not support any command code. - - @param dh Valid handle to a Meinberg device - @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device. - @param *p Pointer to a buffer to be written - @param size Size of the buffer *p - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_generic_read() - @see mbg_generic_read_gps() - @see mbg_generic_write_gps() - @see mbg_generic_io() - */ + * Generic write function which writes a command code plus an + * associated number of data bytes to a device. + * + * <b>Warning</b>: This is for debugging purposes only! + * The specialized API calls should be used preferably. + * Not all devices support each of the ::PC_GPS_COMMANDS. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] cmd One of the ::PCPS_CMD_CODES supported by the device. + * @param[in] p Pointer to a buffer of data to be written + * @param[in] size Size of the buffer, has to match the expected data size associated with cmd + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_generic_read + * @see ::mbg_generic_read_gps + * @see ::mbg_generic_write_gps + * @see ::mbg_generic_io + */ _MBG_API_ATTR int _MBG_API mbg_generic_write( MBG_DEV_HANDLE dh, int cmd, const void *p, int size ) { - _mbgdevio_vars(); - // No type information available, so endianess must be + MBGDEVIO_RET_VAL rc; + // No type information available, so endianess has to be // converted by the caller, if required. rc = _mbgdevio_gen_write( dh, cmd, p, size ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_generic_write @@ -1493,36 +4269,36 @@ _MBG_API_ATTR int _MBG_API mbg_generic_write( MBG_DEV_HANDLE dh, int cmd, /*HDR*/ /* (Intentionally excluded from Doxygen) - Generic write function which writes a GPS command code plus an - associated number of data bytes to the device. - The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data() - check whether this call is supported by a specific card. - - <b>Warning</b>: This is for debugging purposes only! - The specialized API calls should be used preferably. - A specific device may not support any GPS command code. - - @param dh Valid handle to a Meinberg device - @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device. - @param *p Pointer to a buffer to be written - @param size Size of the buffer *p - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_gps_data() - @see mbg_generic_read_gps() - @see mbg_generic_read() - @see mbg_generic_write() - @see mbg_generic_io() - */ + * Generic write function which writes a GPS command code plus an + * associated number of data bytes to a device. + * The function ::mbg_chk_dev_has_gps_data can be used to check + * whether this call is supported by a device. + * + * <b>Warning</b>: This is for debugging purposes only! + * The specialized API calls should be used preferably. + * Not all devices support each of the ::PC_GPS_COMMANDS. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] cmd One of the ::PCPS_CMD_CODES supported by the device. + * @param[in] p Pointer to a buffer of data to be written + * @param[in] size Size of the buffer, has to match the expected data size associated with cmd + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_gps_data + * @see ::mbg_generic_read_gps + * @see ::mbg_generic_read + * @see ::mbg_generic_write + * @see ::mbg_generic_io + */ _MBG_API_ATTR int _MBG_API mbg_generic_write_gps( MBG_DEV_HANDLE dh, int cmd, const void *p, int size ) { - _mbgdevio_vars(); - // No type information available, so endianess must be + MBGDEVIO_RET_VAL rc; + // No type information available, so endianess has to be // converted by the caller, if required. rc = _mbgdevio_gen_write_gps( dh, cmd, p, size ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_generic_write_gps @@ -1530,25 +4306,25 @@ _MBG_API_ATTR int _MBG_API mbg_generic_write_gps( MBG_DEV_HANDLE dh, int cmd, /*HDR*/ /* (Intentionally excluded from Doxygen) - Write and/or read generic data to/from a device. - The macro _pcps_has_generic_io() or the API call mbg_dev_has_generic_io() - check whether this call is supported by a specific card. - - <b>Warning</b>: This call is for debugging purposes and internal use only! - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_generic_io() - @see mbg_generic_read() - @see mbg_generic_write() - @see mbg_generic_read_gps() - @see mbg_generic_write_gps() - */ + * Write and/or read generic data to/from a device. + * The function ::mbg_chk_dev_has_generic_io checks + * whether this call is supported by a device. + * + * <b>Warning</b>: This call is for debugging purposes and internal use only! + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_generic_io + * @see ::mbg_generic_read + * @see ::mbg_generic_write + * @see ::mbg_generic_read_gps + * @see ::mbg_generic_write_gps + */ _MBG_API_ATTR int _MBG_API mbg_generic_io( MBG_DEV_HANDLE dh, int type, const void *in_p, int in_sz, void *out_p, int out_sz ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if !defined( _MBGIOCTL_H ) // The hardware is accessed directly, so we must check @@ -1556,10 +4332,10 @@ _MBG_API_ATTR int _MBG_API mbg_generic_io( MBG_DEV_HANDLE dh, int type, _mbgdevio_chk_cond( _pcps_ddev_has_generic_io( dh ) ); #endif - // No type information available, so endianess must be + // No type information available, so endianess must be // converted by the caller, if required. rc = _mbgdevio_gen_io( dh, type, in_p, in_sz, out_p, out_sz ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_generic_io @@ -1567,29 +4343,32 @@ _MBG_API_ATTR int _MBG_API mbg_generic_io( MBG_DEV_HANDLE dh, int type, /*HDR*/ /** - Read a ::PCPS_TIME structure returning the current date/time/status. - The returned time is local time according to the card's time zone setting, - with a resolution of 10 ms (i.e. 10ths of seconds). - - This call is supported by any device manufactured by Meinberg. However, - for higher accuracy and resolution the mbg_get_hr_time..() group of calls - should be used preferably if supported by the specific device. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_hr_time() - @see mbg_set_time() - @see mbg_get_sync_time() - */ + * @brief Read a ::PCPS_TIME structure returning the current date/time/status + * + * The returned time is local time according to the card's time zone setting, + * with a resolution of 10 ms (i.e. 10ths of seconds) only. + * + * This call is supported by any device manufactured by Meinberg. + * However, for higher accuracy and resolution the @ref mbgdevio_hr_time_fncs or + * the @ref mbgdevio_fast_timestamp_fncs group of calls should be used preferably, + * if supported by the device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_legacy_time_fncs + * @see ::mbg_get_hr_time + * @see ::mbg_set_time + * @see ::mbg_get_sync_time + */ _MBG_API_ATTR int _MBG_API mbg_get_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, PCPS_GIVE_TIME, IOCTL_GET_PCPS_TIME, p ); // No endianess conversion required. - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_time @@ -1597,24 +4376,27 @@ _MBG_API_ATTR int _MBG_API mbg_get_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) /*HDR*/ /** - Set a device's on-board clock manually by passing a ::PCPS_STIME structure - The macro _pcps_can_set_time() checks whether this call - is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_STIME structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_time() - */ + * @brief Set the device's on-board clock to a given date and time. + * + * The macro ::_pcps_can_set_time checks whether + * this call is supported by a device. + * + * @todo Provide an API function replacing ::_pcps_can_set_time. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PCPS_STIME structure to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_time + */ _MBG_API_ATTR int _MBG_API mbg_set_time( MBG_DEV_HANDLE dh, const PCPS_STIME *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; // No endianess conversion required. _mbgdevio_write_var_chk( dh, PCPS_SET_TIME, IOCTL_SET_PCPS_TIME, p, _pcps_ddev_can_set_time( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_time @@ -1622,34 +4404,36 @@ _MBG_API_ATTR int _MBG_API mbg_set_time( MBG_DEV_HANDLE dh, const PCPS_STIME *p /*HDR*/ /** - Read a ::PCPS_TIME structure returning the date/time/status reporting - when the device was synchronized the last time to its time source, - e.g. the DCF77 signal or the GPS satellites. - The macro _pcps_has_sync_time() or the API call mbg_dev_has_sync_time() - check whether this call is supported by a specific card. - - The macro _pcps_has_sync_time() checks whether this call - is supported by a specific card. - - <b>Note:</b> If that information is not available on the board then - the value of the returned ::PCPS_TIME::sec field is set to 0xFF. - The macro _pcps_time_is_read() can be used to check whether the - returned information is valid, or not available. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_time() - */ + * @brief Read the time when the device has last recently synchronized + * + * Fills a ::PCPS_TIME structure with the date/time/status reporting + * when the device was synchronized the last time to its time source, + * e.g. the DCF77 signal, the GPS satellites, or similar. + * + * The macro ::_pcps_has_sync_time checks whether + * this call is supported by a device. + * + * <b>Note:</b> If that information is not available on the board then + * the value of the returned ::PCPS_TIME::sec field is set to 0xFF. + * The macro ::_pcps_time_is_read can be used to check whether the + * returned information is valid, or "not set". + * + * @todo Provide an API function replacing ::_pcps_has_sync_time. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_time + */ _MBG_API_ATTR int _MBG_API mbg_get_sync_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, PCPS_GIVE_SYNC_TIME, IOCTL_GET_PCPS_SYNC_TIME, p, _pcps_ddev_has_sync_time( dh ) ); // No endianess conversion required. - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_sync_time @@ -1657,32 +4441,34 @@ _MBG_API_ATTR int _MBG_API mbg_get_sync_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) /*HDR*/ /** - Wait until the next second change, then return a ::PCPS_TIME - structure similar to mbg_get_time(). - - <b>Note:</b> This API call is supported under Windows only. - The call blocks until the kernel driver detects a second change - reported by the device. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_time() - */ + * @brief Wait until the next second change, then return current time + * + * Returns time in a ::PCPS_TIME structure similar to ::mbg_get_time. + * + * <b>Note:</b> This API call is supported under Windows only. + * The call blocks until the kernel driver detects a second change + * reported by the device. The accuracy of this call is limited + * to a few milliseconds. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_legacy_time_fncs + * @see ::mbg_get_time + */ _MBG_API_ATTR int _MBG_API mbg_get_time_sec_change( MBG_DEV_HANDLE dh, PCPS_TIME *p ) { #if defined( MBG_TGT_WIN32 ) - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, -1, IOCTL_GET_PCPS_TIME_SEC_CHANGE, p ); // No endianess conversion required. - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); #else - #if defined( __BORLANDC__ ) - dh; p; // avoid warnings "never used" - #endif - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS ); + (void) dh; // avoid warning "never used" + (void) p; // avoid warning "never used" + return MBG_ERR_NOT_SUPP_ON_OS; #endif } // mbg_get_time_sec_change @@ -1691,34 +4477,33 @@ _MBG_API_ATTR int _MBG_API mbg_get_time_sec_change( MBG_DEV_HANDLE dh, PCPS_TIME /*HDR*/ /** - Read a ::PCPS_HR_TIME (High Resolution time) structure returning - the current %UTC time (seconds since 1970), %UTC offset, and status. - The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() - check whether this call is supported by a specific card. - - <b>Note:</b> This API call provides a higher accuracy and resolution - than mbg_get_time(). However, it does not account for the latency - which is introduced when accessing the board. - The mbg_get_hr_time_cycles() and mbg_get_hr_time_comp() calls - provides mechanisms to account for and/or compensate the latency. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_hr_time() - @see mbg_get_time() - @see mbg_get_hr_time_cycles() - @see mbg_get_hr_time_comp() - */ + * @brief Read the card's current time with high resolution, including status + * + * Fills up a ::PCPS_HR_TIME (High Resolution time) structure containing + * the current %UTC time (seconds since 1970), %UTC offset, and status. + * + * The API call ::mbg_chk_dev_has_hr_time checks whether + * this call is supported by a device. + * + * For details see @ref ::mbgdevio_hr_time_fncs + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_HR_TIME structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_hr_time_fncs + * @see @ref mbgdevio_hr_time_fncs + * @see @ref mbgdevio_fast_timestamp_fncs + * @see @ref mbgdevio_legacy_time_fncs + */ _MBG_API_ATTR int _MBG_API mbg_get_hr_time( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, PCPS_GIVE_HR_TIME, IOCTL_GET_PCPS_HR_TIME, p, _pcps_ddev_has_hr_time( dh ) ); _mbg_swab_pcps_hr_time( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_hr_time @@ -1726,23 +4511,23 @@ _MBG_API_ATTR int _MBG_API mbg_get_hr_time( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p ) /*HDR*/ /* (Intentionally excluded from Doxygen ) - Write a high resolution time stamp ::PCPS_TIME_STAMP to the clock - to configure a %UTC time when the clock shall generate an event. - The macro _pcps_has_event_time() or the API call mbg_dev_has_event_time() - check whether this call is supported by a specific card. - - <b>Note:</b> This is only supported by some special firmware. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME_STAMP structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_event_time() - */ + * Write a high resolution time stamp ::PCPS_TIME_STAMP to a device + * to configure a %UTC time when the clock shall generate an event. + * The API call ::mbg_chk_dev_has_event_time checks whether + * this call is supported by a device. + * + * <b>Note:</b> This is only supported by some special firmware. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PCPS_TIME_STAMP structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_event_time + */ _MBG_API_ATTR int _MBG_API mbg_set_event_time( MBG_DEV_HANDLE dh, const PCPS_TIME_STAMP *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) PCPS_TIME_STAMP tmp = *p; _mbg_swab_pcps_time_stamp( &tmp ); @@ -1750,7 +4535,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_event_time( MBG_DEV_HANDLE dh, const PCPS_TIM #endif _mbgdevio_write_var_chk( dh, PCPS_SET_EVENT_TIME, IOCTL_SET_PCPS_EVENT_TIME, p, _pcps_ddev_has_event_time( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_event_time @@ -1758,28 +4543,28 @@ _MBG_API_ATTR int _MBG_API mbg_set_event_time( MBG_DEV_HANDLE dh, const PCPS_TIM /*HDR*/ /** - Read the configuration of a device's serial port. - The macro _pcps_has_serial() checks whether this call - is supported by a specific card. - - <b>Note:</b> This function is supported only by a certain class - of devices, so it should not be called directly. The generic - function mbg_get_serial_settings() should be used instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_SERIAL structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see \ref group_cmd_bytes - @see mbg_get_serial_settings() - */ + * @brief Read the serial port configuration from an old type of device + * + * @deprecated Direct usage of this function is deprecated. The generic + * API function ::mbg_get_serial_settings should be used instead + * which fully supports the capabilities of current devices. + * + * The macro ::_pcps_has_serial checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_SERIAL structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_serial_settings + */ _MBG_API_ATTR int _MBG_API mbg_get_serial( MBG_DEV_HANDLE dh, PCPS_SERIAL *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, PCPS_GET_SERIAL, IOCTL_GET_PCPS_SERIAL, p ); // No endianess conversion required. - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_serial @@ -1787,28 +4572,28 @@ _MBG_API_ATTR int _MBG_API mbg_get_serial( MBG_DEV_HANDLE dh, PCPS_SERIAL *p ) /*HDR*/ /** - Write the configuration of a device's serial port. - The macro _pcps_has_serial() checks whether this call - is supported by a specific card. - - <b>Note:</b> This function is supported only by a certain class - of devices, so it should not be called directly. The generic - function mbg_save_serial_settings() should be used instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_SERIAL structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see \ref group_cmd_bytes - @see mbg_save_serial_settings() - */ + * @brief Write the serial port configuration to an old type of device + * + * @deprecated Direct usage of this function is deprecated. The generic + * API function ::mbg_save_serial_settings should be used instead + * which fully supports the capabilities of current devices. + * + * The macro ::_pcps_has_serial checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PCPS_SERIAL structure to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_save_serial_settings + */ _MBG_API_ATTR int _MBG_API mbg_set_serial( MBG_DEV_HANDLE dh, const PCPS_SERIAL *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; // No endianess conversion required. rc = _mbgdevio_write_var( dh, PCPS_SET_SERIAL, IOCTL_SET_PCPS_SERIAL, p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_serial @@ -1816,33 +4601,35 @@ _MBG_API_ATTR int _MBG_API mbg_set_serial( MBG_DEV_HANDLE dh, const PCPS_SERIAL /*HDR*/ /** - Read the card's time zone/daylight saving configuration code. - That tzcode is supported by some simpler cards and only allows only - a very basic configuration. - The macro _pcps_has_tzcode() or the API call mbg_dev_has_tzcode() - check whether this call is supported by a specific card. - Other cards may support the mbg_get_pcps_tzdl() or mbg_get_gps_tzdl() - calls instead which allow for a more detailed configuration of the - time zone and daylight saving settings. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TZCODE structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_tzcode() - @see mbg_set_tzcode() - @see mbg_get_pcps_tzdl() - @see mbg_get_gps_tzdl() - @see \ref group_cmd_bytes - */ + * @brief Read time zone/daylight saving configuration code from a device. + * + * The APIs using ::TZCODE are only supported by some simpler cards + * and allow just a very basic configuration. + * + * The API call ::mbg_chk_dev_has_tzcode checks whether + * this call is supported by a device. + * + * Other devices may support the ::mbg_get_pcps_tzdl or ::mbg_get_gps_tzdl + * calls instead which allow for a more detailed configuration of the + * time zone and daylight saving settings. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TZCODE structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_tzcode + * @see ::mbg_set_tzcode + * @see ::mbg_get_pcps_tzdl + * @see ::mbg_get_gps_tzdl + */ _MBG_API_ATTR int _MBG_API mbg_get_tzcode( MBG_DEV_HANDLE dh, PCPS_TZCODE *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, PCPS_GET_TZCODE, IOCTL_GET_PCPS_TZCODE, p, _pcps_ddev_has_tzcode( dh ) ); // No endianess conversion required. - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_tzcode @@ -1850,33 +4637,35 @@ _MBG_API_ATTR int _MBG_API mbg_get_tzcode( MBG_DEV_HANDLE dh, PCPS_TZCODE *p ) /*HDR*/ /** - Write the card's time zone/daylight saving configuration code. - That tzcode is supported by some simpler cards and only allows only - a very basic configuration. - The macro _pcps_has_tzcode() or the API call mbg_dev_has_tzcode() - check whether this call is supported by a specific card. - Other cards may support the mbg_set_pcps_tzdl() or mbg_set_gps_tzdl() - calls instead which allow for a more detailed configuration of the - time zone and daylight saving settings. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TZCODE structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_tzcode() - @see mbg_get_tzcode() - @see mbg_set_pcps_tzdl() - @see mbg_set_gps_tzdl() - @see \ref group_cmd_bytes - */ + * @brief Write time zone/daylight saving configuration code to a device. + * + * The APIs using ::TZCODE are only supported by some simpler cards + * and allow just a very basic configuration. + * + * The API call ::mbg_chk_dev_has_tzcode checks whether + * this call is supported by a device. + * + * Other devices may support the ::mbg_set_pcps_tzdl or ::mbg_set_gps_tzdl + * calls instead which allow for a more detailed configuration of the + * time zone and daylight saving settings. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PCPS_TZCODE structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_tzcode + * @see ::mbg_get_tzcode + * @see ::mbg_set_pcps_tzdl + * @see ::mbg_set_gps_tzdl + */ _MBG_API_ATTR int _MBG_API mbg_set_tzcode( MBG_DEV_HANDLE dh, const PCPS_TZCODE *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; // No endianess conversion required. _mbgdevio_write_var_chk( dh, PCPS_SET_TZCODE, IOCTL_SET_PCPS_TZCODE, p, _pcps_ddev_has_tzcode( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_tzcode @@ -1884,31 +4673,35 @@ _MBG_API_ATTR int _MBG_API mbg_set_tzcode( MBG_DEV_HANDLE dh, const PCPS_TZCODE /*HDR*/ /** - Read the card's time zone/daylight saving parameters using the - ::PCPS_TZDL structure. - The macro _pcps_has_pcps_tzdl() or the API call mbg_dev_has_pcps_tzdl() - check whether this call is supported by a specific card. - Other cards may support the mbg_get_tzcode() or mbg_get_gps_tzdl() - calls instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TZDL structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_pcps_tzdl() - @see mbg_set_pcps_tzdl() - @see mbg_get_tzcode() - @see mbg_get_gps_tzdl() - @see \ref group_cmd_bytes - */ + * @brief Read time zone/daylight saving parameters from a device. + * + * This function fills up a ::PCPS_TZDL structure which supports a more + * detailed configuration of time zone and daylight saving than the ::TZCODE + * structure. + * + * The API call ::mbg_chk_dev_has_pcps_tzdl checks whether + * this call is supported by a device. + * + * Other devices may support the ::mbg_get_tzcode or ::mbg_get_gps_tzdl + * calls instead. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TZDL structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_pcps_tzdl + * @see ::mbg_set_pcps_tzdl + * @see ::mbg_get_tzcode + * @see ::mbg_get_gps_tzdl + */ _MBG_API_ATTR int _MBG_API mbg_get_pcps_tzdl( MBG_DEV_HANDLE dh, PCPS_TZDL *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, PCPS_GET_PCPS_TZDL, IOCTL_GET_PCPS_TZDL, p, _pcps_ddev_has_pcps_tzdl( dh ) ); _mbg_swab_pcps_tzdl( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_pcps_tzdl @@ -1916,27 +4709,30 @@ _MBG_API_ATTR int _MBG_API mbg_get_pcps_tzdl( MBG_DEV_HANDLE dh, PCPS_TZDL *p ) /*HDR*/ /** - Write the card's time zone/daylight saving parameters using the - ::PCPS_TZDL structure. - The macro _pcps_has_pcps_tzdl() or the API call mbg_dev_has_pcps_tzdl() - check whether this call is supported by a specific card. - Other cards may support the mbg_set_tzcode() or mbg_set_gps_tzdl() - calls instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TZDL structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_pcps_tzdl() - @see mbg_get_pcps_tzdl() - @see mbg_set_tzcode() - @see mbg_set_gps_tzdl() - @see \ref group_cmd_bytes - */ + * @brief Write time zone/daylight saving parameters to a device. + * + * This function passes a ::PCPS_TZDL structure to a device which supports + * a more detailed configuration of time zone and daylight saving than the + * ::TZCODE structure. + * + * The API call ::mbg_chk_dev_has_pcps_tzdl checks whether + * this call is supported by a device. + * Other cards may support the ::mbg_set_tzcode or ::mbg_set_gps_tzdl + * calls instead. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PCPS_TZDL structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_pcps_tzdl + * @see ::mbg_get_pcps_tzdl + * @see ::mbg_set_tzcode + * @see ::mbg_set_gps_tzdl + */ _MBG_API_ATTR int _MBG_API mbg_set_pcps_tzdl( MBG_DEV_HANDLE dh, const PCPS_TZDL *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) PCPS_TZDL tmp = *p; _mbg_swab_pcps_tzdl( &tmp ); @@ -1944,7 +4740,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_pcps_tzdl( MBG_DEV_HANDLE dh, const PCPS_TZDL #endif _mbgdevio_write_var_chk( dh, PCPS_SET_PCPS_TZDL, IOCTL_SET_PCPS_TZDL, p, _pcps_ddev_has_pcps_tzdl( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_pcps_tzdl @@ -1952,27 +4748,30 @@ _MBG_API_ATTR int _MBG_API mbg_set_pcps_tzdl( MBG_DEV_HANDLE dh, const PCPS_TZDL /*HDR*/ /** - Read the reference time offset from %UTC for clocks which can't determine - that offset automatically, e.g. from an IRIG input signal. - The macro _pcps_has_ref_offs() or the API call mbg_dev_has_ref_offs() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_REF_OFFS value to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ref_offs() - @see mbg_set_ref_offs() - @see ::PCPS_GET_REF_OFFS - */ + * @brief Read the %UTC offset configuration of the reference time from a device + * + * This parameter is used to specify the %UTC offset of an incoming + * reference time signal if a kind of time signal e.g. an IRIG input + * signal) does not provide this information. + * + * The API call ::mbg_chk_dev_has_ref_offs checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_REF_OFFS value to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ref_offs + * @see ::mbg_set_ref_offs + */ _MBG_API_ATTR int _MBG_API mbg_get_ref_offs( MBG_DEV_HANDLE dh, MBG_REF_OFFS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, PCPS_GET_REF_OFFS, IOCTL_GET_REF_OFFS, p, _pcps_ddev_has_ref_offs( dh ) ); _mbg_swab_mbg_ref_offs( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_ref_offs @@ -1980,23 +4779,26 @@ _MBG_API_ATTR int _MBG_API mbg_get_ref_offs( MBG_DEV_HANDLE dh, MBG_REF_OFFS *p /*HDR*/ /** - Write the reference time offset from %UTC for clocks which can't determine - that offset automatically, e.g. from an IRIG input signal. - The macro _pcps_has_ref_offs() or the API call mbg_dev_has_ref_offs() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_REF_OFFS value to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ref_offs() - @see mbg_get_ref_offs() - @see ::PCPS_SET_REF_OFFS - */ + * @brief Write the %UTC offset configuration of the reference time to a device. + * + * This parameter is used to specify the %UTC offset of an incoming + * reference time signal if a kind of time signal e.g. an IRIG input + * signal) does not provide this information. + * + * The API call ::mbg_chk_dev_has_ref_offs checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::MBG_REF_OFFS value to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ref_offs + * @see ::mbg_get_ref_offs + */ _MBG_API_ATTR int _MBG_API mbg_set_ref_offs( MBG_DEV_HANDLE dh, const MBG_REF_OFFS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) MBG_REF_OFFS tmp = *p; _mbg_swab_mbg_ref_offs( &tmp ); @@ -2004,7 +4806,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_ref_offs( MBG_DEV_HANDLE dh, const MBG_REF_OF #endif _mbgdevio_write_var_chk( dh, PCPS_SET_REF_OFFS, IOCTL_SET_REF_OFFS, p, _pcps_ddev_has_ref_offs( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_ref_offs @@ -2012,27 +4814,29 @@ _MBG_API_ATTR int _MBG_API mbg_set_ref_offs( MBG_DEV_HANDLE dh, const MBG_REF_OF /*HDR*/ /** - Read a ::MBG_OPT_INFO structure containing optional settings, controlled by flags. - The ::MBG_OPT_INFO structure contains a mask of supported flags plus the current - settings of those flags. - The macro _pcps_has_opt_flags() or the API call mbg_dev_has_opt_flags() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_OPT_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_opt_flags() - @see mbg_set_opt_settings() - */ + * @brief Read a ::MBG_OPT_INFO structure containing optional settings, controlled by flags + * + * The ::MBG_OPT_INFO structure contains a mask of supported flags plus the current + * settings of those flags. + * + * The API call ::mbg_chk_dev_has_opt_flags checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_OPT_INFO structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_opt_flags + * @see ::mbg_set_opt_settings + */ _MBG_API_ATTR int _MBG_API mbg_get_opt_info( MBG_DEV_HANDLE dh, MBG_OPT_INFO *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, PCPS_GET_OPT_INFO, IOCTL_GET_MBG_OPT_INFO, p, _pcps_ddev_has_opt_flags( dh ) ); _mbg_swab_mbg_opt_info( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_opt_info @@ -2040,23 +4844,25 @@ _MBG_API_ATTR int _MBG_API mbg_get_opt_info( MBG_DEV_HANDLE dh, MBG_OPT_INFO *p /*HDR*/ /** - Write a ::MBG_OPT_SETTINGS structure contains optional settings, controlled by flags. - The macro _pcps_has_opt_flags() or the API call mbg_dev_has_opt_flags() - check whether this call is supported by a specific card. - The ::MBG_OPT_INFO structure should be read first to check which of the specified - flags is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_OPT_SETTINGS structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_opt_flags() - @see mbg_get_opt_info() - */ + * @brief Write a ::MBG_OPT_SETTINGS structure containing optional device settings. + * + * The API call ::mbg_chk_dev_has_opt_flags checks whether + * this call is supported by a device. + * + * ::mbg_get_opt_info should be called first to check which of + * the specified flags is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_OPT_SETTINGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_opt_flags + * @see ::mbg_get_opt_info + */ _MBG_API_ATTR int _MBG_API mbg_set_opt_settings( MBG_DEV_HANDLE dh, const MBG_OPT_SETTINGS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) MBG_OPT_SETTINGS tmp = *p; _mbg_swab_mbg_opt_settings( &tmp ); @@ -2065,7 +4871,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_opt_settings( MBG_DEV_HANDLE dh, const MBG_OP _mbgdevio_write_var_chk( dh, PCPS_SET_OPT_SETTINGS, IOCTL_SET_MBG_OPT_SETTINGS, p, _pcps_ddev_has_opt_flags( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_opt_settings @@ -2073,29 +4879,34 @@ _MBG_API_ATTR int _MBG_API mbg_set_opt_settings( MBG_DEV_HANDLE dh, const MBG_OP /*HDR*/ /** - Read an ::IRIG_INFO structure containing the configuration of an IRIG input - plus the possible settings supported by that input. - The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an ::IRIG_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_irig_rx_settings() - @see mbg_dev_is_irig_rx() - @see mbg_dev_has_irig_tx() - @see mbg_dev_has_irig() - @see \ref group_icode - */ + * @brief Read the current IRIG input settings plus capabilities + * + * @deprecated Calling this function directly is deprecated. The function + * ::mbg_get_all_irig_rx_info should be used instead which also reads some + * other associated parameters affecting the behaviour of the IRIG input. + * + * The API call ::mbg_chk_dev_is_tcr checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] *p An ::IRIG_INFO structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_all_irig_rx_info + * @see ::mbg_set_irig_rx_settings + * @see ::mbg_chk_dev_is_tcr + * @see ::mbg_chk_dev_has_irig_tx + * @see ::mbg_chk_dev_has_irig + * @see @ref group_icode + */ _MBG_API_ATTR int _MBG_API mbg_get_irig_rx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, PCPS_GET_IRIG_RX_INFO, IOCTL_GET_PCPS_IRIG_RX_INFO, p, _pcps_ddev_is_irig_rx( dh ) ); _mbg_swab_irig_info( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_irig_rx_info @@ -2103,26 +4914,32 @@ _MBG_API_ATTR int _MBG_API mbg_get_irig_rx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p /*HDR*/ /** - Write an ::IRIG_SETTINGS structure containing the configuration of an IRIG input. - The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx() - check whether this call is supported by a specific card. - The ::IRIG_INFO structure should be read first to determine the possible - settings supported by this card's IRIG input. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::IRIG_SETTINGS structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_irig_rx_info() - @see mbg_dev_is_irig_rx() - @see mbg_dev_has_irig_tx() - @see mbg_dev_has_irig() - @see \ref group_icode - */ + * @brief Write an ::IRIG_SETTINGS structure to a device to configure an IRIG input. + * + * @deprecated Calling this function directly is deprecated. The function + * ::mbg_save_all_irig_rx_settings should be used instead which also writes some + * other associated parameters affecting the behaviour of the IRIG input. + * + * The API call ::mbg_chk_dev_is_tcr checks whether + * this call is supported by a device. + * ::mbg_get_irig_rx_info should be called first to determine + * the possible settings supported by the device's IRIG input. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::IRIG_SETTINGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_save_all_irig_rx_settings + * @see ::mbg_get_irig_rx_info + * @see ::mbg_chk_dev_is_tcr + * @see ::mbg_chk_dev_has_irig_tx + * @see ::mbg_chk_dev_has_irig + * @see @ref group_icode + */ _MBG_API_ATTR int _MBG_API mbg_set_irig_rx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) IRIG_SETTINGS tmp = *p; _mbg_swab_irig_settings( &tmp ); @@ -2131,7 +4948,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_irig_rx_settings( MBG_DEV_HANDLE dh, const IR _mbgdevio_write_var_chk( dh, PCPS_SET_IRIG_RX_SETTINGS, IOCTL_SET_PCPS_IRIG_RX_SETTINGS, p, _pcps_ddev_is_irig_rx( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_irig_rx_settings @@ -2139,95 +4956,162 @@ _MBG_API_ATTR int _MBG_API mbg_set_irig_rx_settings( MBG_DEV_HANDLE dh, const IR /*HDR*/ /** - Check if a specific device supports the mbg_get_irig_ctrl_bits() call. + * @brief Read all IRIG input configuration information from a device + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] pdev Pointer to the device's ::PCPS_DEV structure //### TODO Make this obsolete + * @param[in] p_irig_info Pointer to a ::IRIG_SETTINGS structure to be written + * @param[in] p_ref_offs Pointer to a ::MBG_REF_OFFS structure to be written + * @param[in] p_opt_info Pointer to a ::MBG_OPT_SETTINGS structure to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_save_all_irig_rx_settings + * @see ::mbg_set_irig_rx_settings + * @see ::mbg_set_ref_offs + * @see ::mbg_set_opt_settings + */ +_MBG_API_ATTR int _MBG_API mbg_get_all_irig_rx_info( MBG_DEV_HANDLE dh, + const PCPS_DEV *pdev, + IRIG_INFO *p_irig_info, + MBG_REF_OFFS *p_ref_offs, + MBG_OPT_INFO *p_opt_info ) +{ + int rc; - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + if ( !_pcps_is_irig_rx( pdev ) ) + return MBG_ERR_NOT_SUPP_BY_DEV; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + rc = mbg_get_irig_rx_info( dh, p_irig_info ); - @see mbg_get_irig_ctrl_bits() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_irig_ctrl_bits( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_irig_ctrl_bits, IOCTL_DEV_HAS_IRIG_CTRL_BITS, p ); + if ( mbg_rc_is_success( rc ) && _pcps_has_ref_offs( pdev ) ) + rc = mbg_get_ref_offs( dh, p_ref_offs ); -} // mbg_dev_has_irig_ctrl_bits + if ( mbg_rc_is_success( rc ) && _pcps_has_opt_flags( pdev ) ) + rc = mbg_get_opt_info( dh, p_opt_info ); + + return rc; + +} // mbg_get_all_irig_rx_info /*HDR*/ /** - Read a ::MBG_IRIG_CTRL_BITS type which contains the control function - bits of the latest IRIG input frame. Those bits may carry some - well-known information, as in the IEEE1344 code, but may also contain - some customized information, depending on the IRIG frame type and - the configuration of the IRIG generator. So these bits are returned - as-is and must be interpreted by the application. - The macro _pcps_has_irig_ctrl_bits() or the API call mbg_dev_has_irig_ctrl_bits() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_IRIG_CTRL_BITS type to be filled up + * @brief Write all IRIG input configuration settings to a device. + * + * The API call ::mbg_chk_dev_is_tcr checks whether + * this call is supported by a device. + * ::mbg_get_all_irig_rx_info should be called before to determine + * the possible settings supported by the IRIG input. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] pdev Pointer to the device's ::PCPS_DEV structure //### TODO Make this obsolete + * @param[out] p_irig_settings Pointer to a ::IRIG_SETTINGS structure to be written + * @param[out] p_ref_offs Pointer to a ::MBG_REF_OFFS structure to be written + * @param[out] p_opt_settings Pointer to a ::MBG_OPT_SETTINGS structure to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_all_irig_rx_info + * @see ::mbg_set_irig_rx_settings + * @see ::mbg_set_ref_offs + * @see ::mbg_set_opt_settings + */ +_MBG_API_ATTR int _MBG_API mbg_save_all_irig_rx_settings( MBG_DEV_HANDLE dh, + const PCPS_DEV *pdev, + const IRIG_SETTINGS *p_irig_settings, + const MBG_REF_OFFS *p_ref_offs, + const MBG_OPT_SETTINGS *p_opt_settings ) +{ + int rc; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + if ( !_pcps_is_irig_rx( pdev ) ) + return MBG_ERR_NOT_SUPP_BY_DEV; - @see mbg_dev_has_irig_ctrl_bits() -*/ -_MBG_API_ATTR int _MBG_API mbg_get_irig_ctrl_bits( MBG_DEV_HANDLE dh, - MBG_IRIG_CTRL_BITS *p ) -{ - _mbgdevio_vars(); - rc = _mbgdevio_read_var( dh, PCPS_GET_IRIG_CTRL_BITS, IOCTL_GET_IRIG_CTRL_BITS, p ); - _mbg_swab_irig_ctrl_bits( p ); - return _mbgdevio_ret_val; + rc = mbg_set_irig_rx_settings( dh, p_irig_settings ); -} // mbg_get_irig_ctrl_bits + if ( mbg_rc_is_success( rc ) && _pcps_has_ref_offs( pdev ) ) + rc = mbg_set_ref_offs( dh, p_ref_offs ); + if ( mbg_rc_is_success( rc ) && _pcps_has_opt_flags( pdev ) ) + rc = mbg_set_opt_settings( dh, p_opt_settings ); + return rc; -/*HDR*/ -/** - Check if a specific device supports the mbg_get_raw_irig_data() call. +} // mbg_save_all_irig_rx_settings - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - @return ::MBG_SUCCESS or error code returned by device I/O control function. - @see mbg_get_raw_irig_data() - @see mbg_get_raw_irig_data_on_sec_change() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_raw_irig_data( MBG_DEV_HANDLE dh, int *p ) +/*HDR*/ +/** + * @brief Read the control function bits received from an incoming IRIG signal. + * + * This function fills an ::MBG_IRIG_CTRL_BITS structure with the control function + * bits decoded from the incoming IRIG signal. + * + * The meaning of these bits depends on the type of IRIG code frame format. + * + * In some IRIG formats these bits provide some well-known information which can + * also be evaluated by the device. For example, in IEEE 1344 or IEEE C37.118 code + * the control function bits are used to provide the year number, UTC offset, + * DST status, leap second warning, etc. + * + * For most IRIG code formats, however, these bits are reserved, i.e. not used + * at all, or application defined, depending on the configuration of the IRIG + * generator providing the IRIG signal. + * + * In the latter case the application has to evaluate the received control function + * bits and can use this function to retrieve these bits from the receiver device. + * + * The API call ::mbg_chk_dev_has_irig_ctrl_bits checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_IRIG_CTRL_BITS type to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_irig_ctrl_bits + */ +_MBG_API_ATTR int _MBG_API mbg_get_irig_ctrl_bits( MBG_DEV_HANDLE dh, + MBG_IRIG_CTRL_BITS *p ) { - _mbgdevio_query_cond( dh, _pcps_ddev_has_raw_irig_data, IOCTL_DEV_HAS_RAW_IRIG_DATA, p ); + MBGDEVIO_RET_VAL rc; + rc = _mbgdevio_read_var( dh, PCPS_GET_IRIG_CTRL_BITS, IOCTL_GET_IRIG_CTRL_BITS, p ); + _mbg_swab_irig_ctrl_bits( p ); + return _mbgdevio_cnv_ret_val( rc ); -} // mbg_dev_has_raw_irig_data +} // mbg_get_irig_ctrl_bits /*HDR*/ /** - Read a ::MBG_RAW_IRIG_DATA type which contains all data - bits of the latest IRIG input frame. - The macro _pcps_has_raw_irig_data() or the API call mbg_dev_has_raw_irig_data() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_raw_irig_data() - @see mbg_get_raw_irig_data_on_sec_change() -*/ + * @brief Read raw IRIG data from an IRIG receiver. + * + * This function reads an ::MBG_RAW_IRIG_DATA structure with the raw data bits received + * from the incoming IRIG signal. This enables an application itself to decode the + * information provided by the IRIG signal. + * + * The API call ::mbg_chk_dev_has_raw_irig_data checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_raw_irig_data + * @see ::mbg_get_raw_irig_data_on_sec_change + */ _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data( MBG_DEV_HANDLE dh, MBG_RAW_IRIG_DATA *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, PCPS_GET_RAW_IRIG_DATA, IOCTL_GET_RAW_IRIG_DATA, p ); // No endianess conversion required. - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_raw_irig_data @@ -2235,34 +5119,39 @@ _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data( MBG_DEV_HANDLE dh, /*HDR*/ /** - Read a ::MBG_RAW_IRIG_DATA type just after a second change which contains all data - bits of the latest IRIG input frame. - The macro _pcps_has_raw_irig_data() or the API call mbg_dev_has_raw_irig_data() - check whether this call is supported by a specific card. - - <b>Note:</b> The mbg_get_time_sec_change() function called by this function is - supported under Windows only, so this function can also only be used under Windows. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_raw_irig_data() - @see mbg_get_raw_irig_data() -*/ + * @brief Wait for second changeover then read raw IRIG data from an IRIG receiver. + * + * This function waits until the second of the device's on-board time rolls over, + * and then reads the last recent raw IRIG data from the device. + * + * The API call ::mbg_chk_dev_has_raw_irig_data checks whether + * this call is supported by a device. + * + * <b>Note:</b> The ::mbg_get_time_sec_change function called + * by this function is supported under Windows only, so this function + * can also be used under Windows only. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_raw_irig_data + * @see ::mbg_get_raw_irig_data + * @see ::mbg_get_time_sec_change + */ _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data_on_sec_change( MBG_DEV_HANDLE dh, MBG_RAW_IRIG_DATA *p ) { PCPS_TIME t; - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = mbg_get_time_sec_change( dh, &t ); - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) rc = mbg_get_raw_irig_data( dh, p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_raw_irig_data_on_sec_change @@ -2270,46 +5159,30 @@ _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data_on_sec_change( MBG_DEV_HANDLE d /*HDR*/ /** - Check if a specific device supports the mbg_get_irig_time() call. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_irig_time() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_irig_time( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_irig_time, IOCTL_DEV_HAS_IRIG_TIME, p ); - -} // mbg_dev_has_irig_time - - - -/*HDR*/ -/** - Read a ::PCPS_IRIG_TIME type which returns the raw IRIG day-of-year number - and time decoded from the latest IRIG input frame. If the configured IRIG code - also contains the year number then the year number is also returned, otherwise - the returned year number is 0xFF. - The macro _pcps_has_irig_time() or the API call mbg_dev_has_irig_time() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_IRIG_TIME type to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_irig_time() -*/ + * @brief Read the IRIG time and day-of-year number from an IRIG receiver. + * + * Reads a ::PCPS_IRIG_TIME structure with the raw IRIG day-of-year number + * and time decoded from the latest IRIG input frame. If the configured IRIG code + * also contains the year number then the year number is also returned, otherwise + * the returned year number is 0xFF. + * + * The API call ::mbg_chk_dev_has_irig_time checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_IRIG_TIME type to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_irig_time + */ _MBG_API_ATTR int _MBG_API mbg_get_irig_time( MBG_DEV_HANDLE dh, PCPS_IRIG_TIME *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, PCPS_GIVE_IRIG_TIME, IOCTL_GET_IRIG_TIME, p ); _mbg_swab_pcps_irig_time( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_irig_time @@ -2317,24 +5190,25 @@ _MBG_API_ATTR int _MBG_API mbg_get_irig_time( MBG_DEV_HANDLE dh, /*HDR*/ /** - Clear the card's on-board time capture FIFO buffer. - The macro _pcps_can_clr_ucap_buff() or the API call mbg_dev_can_clr_ucap_buff() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_can_clr_ucap_buff() - @see mbg_get_ucap_entries() - @see mbg_get_ucap_event() - */ + * @brief Clear a device's on-board time capture FIFO buffer. + * + * The API call ::mbg_chk_dev_can_clr_ucap_buff checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_can_clr_ucap_buff + * @see ::mbg_get_ucap_entries + * @see ::mbg_get_ucap_event + */ _MBG_API_ATTR int _MBG_API mbg_clr_ucap_buff( MBG_DEV_HANDLE dh ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_write_cmd_chk( dh, PCPS_CLR_UCAP_BUFF, IOCTL_PCPS_CLR_UCAP_BUFF, _pcps_ddev_can_clr_ucap_buff( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_clr_ucap_buff @@ -2342,28 +5216,32 @@ _MBG_API_ATTR int _MBG_API mbg_clr_ucap_buff( MBG_DEV_HANDLE dh ) /*HDR*/ /** - Read a ::PCPS_UCAP_ENTRIES structure to retrieve the number of saved - user capture events and the maximum capture buffer size. - The macro _pcps_has_ucap() or the API call mbg_dev_has_ucap() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_UCAP_ENTRIES structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ucap() - @see mbg_get_ucap_entries() - @see mbg_get_ucap_event() - */ + * @brief Read information on a device's event capture buffer. + * + * Reads a ::PCPS_UCAP_ENTRIES structure with the number of user capture + * events actually stored in the FIFO buffer, and the maximum number of + * events that can be held by the buffer. + * + * The API call ::mbg_chk_dev_has_ucap checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_UCAP_ENTRIES structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ucap + * @see ::mbg_get_ucap_entries + * @see ::mbg_get_ucap_event + */ _MBG_API_ATTR int _MBG_API mbg_get_ucap_entries( MBG_DEV_HANDLE dh, PCPS_UCAP_ENTRIES *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, PCPS_GIVE_UCAP_ENTRIES, IOCTL_GET_PCPS_UCAP_ENTRIES, p, _pcps_ddev_has_ucap( dh ) ); _mbg_swab_pcps_ucap_entries( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_ucap_entries @@ -2371,35 +5249,38 @@ _MBG_API_ATTR int _MBG_API mbg_get_ucap_entries( MBG_DEV_HANDLE dh, PCPS_UCAP_EN /*HDR*/ /** - Retrieve a single time capture event from the on-board FIFO buffer - using a ::PCPS_HR_TIME structure. The oldest entry of the FIFO is retrieved - and then removed from the FIFO. - If no capture event is available in the FIFO buffer then both the seconds - and the fractions of the returned timestamp are 0. - The macro _pcps_has_ucap() or the API call mbg_dev_has_ucap() - check whether this call is supported by a specific card. - - <b>Note:</b> This call is very much faster than the older mbg_get_gps_ucap() - call which is obsolete but still supported for compatibility with - older cards. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ucap() - @see mbg_get_ucap_entries() - @see mbg_clr_ucap_buff() - */ + * @brief Retrieve a single time capture event from the on-board FIFO buffer + * + * The capture event is returned in a ::PCPS_HR_TIME structure. The oldest entry + * in the FIFO is retrieved and then removed from the FIFO. + * + * If no capture event is available in the FIFO buffer then both the seconds + * and the fractions of the returned timestamp are 0. + * + * The API call ::mbg_chk_dev_has_ucap checks whether + * this call is supported by a device. + * + * <b>Note:</b> This call is very much faster than the older ::mbg_get_gps_ucap + * call which is obsolete but still supported for compatibility with + * older cards. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_HR_TIME structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ucap + * @see ::mbg_get_ucap_entries + * @see ::mbg_clr_ucap_buff + */ _MBG_API_ATTR int _MBG_API mbg_get_ucap_event( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, PCPS_GIVE_UCAP_EVENT, IOCTL_GET_PCPS_UCAP_EVENT, p, _pcps_ddev_has_ucap( dh ) ); _mbg_swab_pcps_hr_time( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_ucap_event @@ -2407,32 +5288,35 @@ _MBG_API_ATTR int _MBG_API mbg_get_ucap_event( MBG_DEV_HANDLE dh, PCPS_HR_TIME * /*HDR*/ /** - Read the card's time zone/daylight saving parameters using the ::TZDL - structure. - The macro _pcps_has_tzdl() or the API call mbg_dev_has_tzdl() - check whether this call is supported by a specific card. - - <b>Note:</b> In spite of the function name this call may also be - supported by non-GPS cards. Other cards may support the mbg_get_tzcode() - or mbg_get_pcps_tzdl() calls instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TZDL structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_tzdl() - @see mbg_set_gps_tzdl() - @see mbg_get_tzcode() - @see mbg_get_pcps_tzdl() - @see \ref group_tzdl - */ + * @brief Read the card's time zone/daylight saving parameters + * + * This function returns the time zone/daylight saving parameters + * in a ::TZDL structure. + * + * The API call ::mbg_chk_dev_has_tzdl checks whether + * this call is supported by a device. + * + * <b>Note:</b> In spite of the function name this call may also be + * supported by non-GPS cards. Other cards may support the ::mbg_get_tzcode + * or ::mbg_get_pcps_tzdl calls instead. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::TZDL structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_tzdl + * @see ::mbg_set_gps_tzdl + * @see ::mbg_get_tzcode + * @see ::mbg_get_pcps_tzdl + * @see @ref group_tzdl + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_tzdl( MBG_DEV_HANDLE dh, TZDL *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_gps_var( dh, PC_GPS_TZDL, IOCTL_GET_GPS_TZDL, p ); _mbg_swab_tzdl( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_tzdl @@ -2440,36 +5324,39 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_tzdl( MBG_DEV_HANDLE dh, TZDL *p ) /*HDR*/ /** - Write the card's time zone/daylight saving parameters using the ::TZDL - structure. - The macro _pcps_has_tzdl() or the API call mbg_dev_has_tzdl() - check whether this call is supported by a specific card. - - <b>Note:</b> In spite of the function name this call may also be - supported by non-GPS cards. Other cards may support the mbg_set_tzcode() - or mbg_set_pcps_tzdl() calls instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TZDL structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_tzdl() - @see mbg_get_gps_tzdl() - @see mbg_set_tzcode() - @see mbg_set_pcps_tzdl() - @see \ref group_tzdl - */ + * @brief Write the card's time zone/daylight saving parameters. + * + * This function writes the time zone/daylight saving parameters + * in a ::TZDL structure to a device. + * + * The API call ::mbg_chk_dev_has_tzdl checks whether + * this call is supported by a device. + * + * <b>Note:</b> In spite of the function name this call may also be + * supported by non-GPS cards. Other cards may support the ::mbg_set_tzcode + * or ::mbg_set_pcps_tzdl calls instead. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::TZDL structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_tzdl + * @see ::mbg_get_gps_tzdl + * @see ::mbg_set_tzcode + * @see ::mbg_set_pcps_tzdl + * @see @ref group_tzdl + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_tzdl( MBG_DEV_HANDLE dh, const TZDL *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) TZDL tmp = *p; _mbg_swab_tzdl( &tmp ); p = &tmp; #endif rc = _mbgdevio_write_gps_var( dh, PC_GPS_TZDL, IOCTL_SET_GPS_TZDL, p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_gps_tzdl @@ -2477,29 +5364,33 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_tzdl( MBG_DEV_HANDLE dh, const TZDL *p ) /*HDR*/ /** - Retrieve the software revision of a GPS receiver. - This call is obsolete but still supported for compatibility - with older GPS cards. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - <b>Note:</b> The function mbg_get_gps_receiver_info() should - be used instead, if supported by the card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::SW_REV structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_is_gps() - @see mbg_get_gps_receiver_info() - */ + * @brief Retrieve the software revision of a GPS receiver + * + * @deprecated This function is deprecated. + * + * This function is deprecated, but still supported + * for compatibility with older GPS cards. Normally + * the software revision is part of the ::RECEIVER_INFO + * structure. See ::mbg_setup_receiver_info which takes + * care of the different options. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::SW_REV structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_setup_receiver_info + * @see ::mbg_chk_dev_is_gps + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_sw_rev( MBG_DEV_HANDLE dh, SW_REV *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_gps_var( dh, PC_GPS_SW_REV, IOCTL_GET_GPS_SW_REV, p ); _mbg_swab_sw_rev( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_sw_rev @@ -2507,23 +5398,37 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_sw_rev( MBG_DEV_HANDLE dh, SW_REV *p ) /*HDR*/ /** - Retrieve the status of the battery buffered GPS variables. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - The GPS receiver stays in cold boot mode until all of the - data sets are valid. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::BVAR_STAT structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ + * @brief Retrieve the status of the battery buffered GPS variables. + * + * GPS receivers require some navigational data set to be available + * to be able to decode position and time accurately. This data set + * is transmitted periodically by the satellites, so it can + * simply be collected if it's not available. + * + * The ::BVAR_STAT type reports which parts of the data set are + * available in the receiver, and which are not. + * + * If the available data set is not complete then the receiver + * stays in COLD BOOT mode until all data have been received + * and thus all data sets are valid. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::BVAR_STAT structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_is_gps + * @see ::BVAR_FLAGS + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_bvar_stat( MBG_DEV_HANDLE dh, BVAR_STAT *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_gps_var( dh, PC_GPS_BVAR_STAT, IOCTL_GET_GPS_BVAR_STAT, p ); _mbg_swab_bvar_stat( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_stat @@ -2531,24 +5436,28 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_bvar_stat( MBG_DEV_HANDLE dh, BVAR_STAT * /*HDR*/ /** - Read the current board time using a ::TTM structure. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - <b>Note:</b> This call is pretty slow, so the mbg_get_hr_time_..() - group of calls should be used preferably. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TTM structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ + * @brief Read the current board time using a ::TTM structure + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * <b>Note:</b> This API call is pretty slow, so ::mbg_get_hr_time or + * ::mbg_get_fast_hr_timestamp or associated calls should be used preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::TTM structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_hr_time + * @see ::mbg_get_fast_hr_timestamp + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_time( MBG_DEV_HANDLE dh, TTM *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_gps_var( dh, PC_GPS_TIME, IOCTL_GET_GPS_TIME, p ); _mbg_swab_ttm( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_time @@ -2556,26 +5465,31 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_time( MBG_DEV_HANDLE dh, TTM *p ) /*HDR*/ /** - Write a ::TTM structure to a GPS receiver in order to set the - on-board date and time. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TTM structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ + * @brief Set the time on a GPS receiver device + * + * Write a ::TTM structure to a GPS receiver in order to set + * the on-board date and time. Date and time must be local time + * according to the device's on-board time zone configuration + * (::TZDL). + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::TTM structure to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_time( MBG_DEV_HANDLE dh, const TTM *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) TTM tmp = *p; _mbg_swab_ttm( &tmp ); p = &tmp; #endif rc = _mbgdevio_write_gps_var( dh, PC_GPS_TIME, IOCTL_SET_GPS_TIME, p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_gps_time @@ -2583,29 +5497,31 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_time( MBG_DEV_HANDLE dh, const TTM *p ) /*HDR*/ /** - Read a ::PORT_PARM structure to retrieve the configuration - of the device's serial ports. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - <b>Note:</b> This function is obsolete since it is only - supported by a certain class of devices and can handle only - up to 2 ports. The generic function mbg_get_serial_settings() - should be used instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PORT_PARM structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_serial_settings() -*/ + * @brief Read a ::PORT_PARM structure with a device's serial port configuration. + * + * @deprecated This function is deprecated, use ::mbg_get_serial_settings preferably. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * <b>Note:</b> This function is deprecated since it is only + * supported by a certain class of devices and can handle only + * up to 2 serial ports. The generic function ::mbg_get_serial_settings + * should be used instead. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PORT_PARM structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_serial_settings + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_port_parm( MBG_DEV_HANDLE dh, PORT_PARM *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_gps_var( dh, PC_GPS_PORT_PARM, IOCTL_GET_GPS_PORT_PARM, p ); _mbg_swab_port_parm( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_port_parm @@ -2613,33 +5529,35 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_port_parm( MBG_DEV_HANDLE dh, PORT_PARM * /*HDR*/ /** - Write a ::PORT_PARM structure to configure the on-board - serial ports. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - <b>Note:</b> This function is obsolete since it is only - supported by a certain class of devices and can handle only - up to 2 ports. The generic function mbg_save_serial_settings() - should be used instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PORT_PARM structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_save_serial_settings() -*/ + * @brief Write a ::PORT_PARM structure to configure the on-board serial ports. + * + * @deprecated This function is deprecated, use ::mbg_save_serial_settings preferably. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * <b>Note:</b> This function is deprecated since it is only + * supported by a certain class of devices and can handle only + * up to 2 ports. The generic function ::mbg_save_serial_settings + * should be used instead. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PORT_PARM structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_save_serial_settings + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_parm( MBG_DEV_HANDLE dh, const PORT_PARM *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) PORT_PARM tmp = *p; _mbg_swab_port_parm( &tmp ); p = &tmp; #endif rc = _mbgdevio_write_gps_var( dh, PC_GPS_PORT_PARM, IOCTL_SET_GPS_PORT_PARM, p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_gps_port_parm @@ -2647,25 +5565,28 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_parm( MBG_DEV_HANDLE dh, const PORT_ /*HDR*/ /** - Read an ::ANT_INFO structure to retrieve status information of the GPS antenna. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - <b>Note:</b> Normally the antenna connection status can also be - determined by evaluation of the ::PCPS_TIME::signal or ::PCPS_HR_TIME::signal - fields. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ANT_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ + * @brief Read an ::ANT_INFO structure to retrieve an extended GPS antenna status. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * <b>Note:</b> Normally the current antenna connection status can also be + * determined by evaluation of the ::PCPS_TIME::signal or ::PCPS_HR_TIME::signal + * fields. The "disconnected" status reported by ::ANT_INFO disappears only if + * the antenna has been reconnected <b>and</b> the receiver has synchronized + * to the GPS satellites again. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::ANT_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_ant_info( MBG_DEV_HANDLE dh, ANT_INFO *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_gps_var( dh, PC_GPS_ANT_INFO, IOCTL_GET_GPS_ANT_INFO, p ); _mbg_swab_ant_info( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_ant_info @@ -2673,30 +5594,31 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_ant_info( MBG_DEV_HANDLE dh, ANT_INFO *p /*HDR*/ /** - Read a time capture event from the on-board FIFO buffer using a ::TTM structure. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - <b>Note:</b> This call is pretty slow and has been obsoleted by - mbg_get_ucap_event() which should be used preferably, if supported - by the card. Anyway, this call is still supported for compatibility - with older cards. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TTM structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_ucap_entries() - @see mbg_get_ucap_event() - @see mbg_clr_ucap_buff() -*/ + * @brief Read a time capture event from the on-board FIFO buffer using a ::TTM structure + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * <b>Note:</b> This call is pretty slow and has been obsoleted by + * ::mbg_get_ucap_event which should be used preferably, if supported + * by the device. Anyway, this call is still supported for compatibility + * with older devices which don't support ::mbg_get_ucap_event. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::TTM structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_ucap_entries + * @see ::mbg_get_ucap_event + * @see ::mbg_clr_ucap_buff + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_ucap( MBG_DEV_HANDLE dh, TTM *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_gps_var( dh, PC_GPS_UCAP, IOCTL_GET_GPS_UCAP, p ); _mbg_swab_ttm( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_ucap @@ -2704,30 +5626,35 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_ucap( MBG_DEV_HANDLE dh, TTM *p ) /*HDR*/ /** - Read an ::ENABLE_FLAGS structure reporting whether certain outputs - shall be enabled immediately after the card's power-up, or only - after the card has synchronized to its input signal. - The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data() - check whether this call is supported by a specific card. - - <b>Note:</b> Not all of the input signals specified for the - ::ENABLE_FLAGS structure can be modified individually. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::ENABLE_FLAGS structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see ::ENABLE_FLAGS - @see mbg_set_gps_enable_flags() -*/ + * @brief Read the ::ENABLE_FLAGS structure controlling when outputs are to be enabled + * + * The ::ENABLE_FLAGS structure controls whether certain signal outputs + * are to be enabled immediately after the device's power-up, or only + * after the device has synchronized to its input signal. + * + * The function ::mbg_chk_dev_has_gps_data can be used to check + * whether this call is supported by a device. + * + * <b>Note:</b> Not all of the input signals specified for the + * ::ENABLE_FLAGS structure can be modified individually. + * See ::ENABLE_FLAGS_CODES. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::ENABLE_FLAGS structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::ENABLE_FLAGS + * @see ::ENABLE_FLAGS_CODES + * @see ::mbg_set_gps_enable_flags + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_enable_flags( MBG_DEV_HANDLE dh, ENABLE_FLAGS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_gps_var( dh, PC_GPS_ENABLE_FLAGS, IOCTL_GET_GPS_ENABLE_FLAGS, p ); _mbg_swab_enable_flags( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_enable_flags @@ -2735,27 +5662,32 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_enable_flags( MBG_DEV_HANDLE dh, ENABLE_F /*HDR*/ /** - Write an ENABLE_FLAGS structure to configure whether certain outputs - shall be enabled immediately after the card's power-up, or only - after the card has synchronized to its input signal. - The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data() - check whether this call is supported by a specific card. - - <b>Note:</b> Not all of the input signals specified for the - ENABLE_FLAGS structure can be modified individually. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ENABLE_FLAGS structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see ENABLE_FLAGS - @see mbg_get_gps_enable_flags() -*/ + * @brief Write an ;;ENABLE_FLAGS structure to configure when outputs shall be enabled. + * + * The ::ENABLE_FLAGS structure controls whether certain signal outputs + * are to be enabled immediately after the device's power-up, or only + * after the device has synchronized to its input signal. + * + * The function ::mbg_chk_dev_has_gps_data can be used to check + * whether this call is supported by a device. + * + * <b>Note:</b> Not all of the input signals specified for the + * ::ENABLE_FLAGS structure can be modified individually. + * See ::ENABLE_FLAGS_CODES. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ENABLE_FLAGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::ENABLE_FLAGS + * @see ::ENABLE_FLAGS_CODES + * @see ::mbg_get_gps_enable_flags + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_enable_flags( MBG_DEV_HANDLE dh, const ENABLE_FLAGS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) ENABLE_FLAGS tmp = *p; _mbg_swab_enable_flags( &tmp ); @@ -2763,7 +5695,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_enable_flags( MBG_DEV_HANDLE dh, #endif rc = _mbgdevio_write_gps_var( dh, PC_GPS_ENABLE_FLAGS, IOCTL_SET_GPS_ENABLE_FLAGS, p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_gps_enable_flags @@ -2771,25 +5703,27 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_enable_flags( MBG_DEV_HANDLE dh, /*HDR*/ /** - Read a ::STAT_INFO structure to retrieve the status of the - GPS receiver, including mode of operation and numer of - visible/usable satellites. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::STAT_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see ::STAT_INFO -*/ + * @brief Read the extended GPS receiver status from a device. + * + * The ::STAT_INFO structure reports the status of the GPS receiver, + * including mode of operation and number of visible/usable satellites. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::STAT_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::STAT_INFO + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_stat_info( MBG_DEV_HANDLE dh, STAT_INFO *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_gps_var( dh, PC_GPS_STAT_INFO, IOCTL_GET_GPS_STAT_INFO, p ); _mbg_swab_stat_info( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_stat_info @@ -2797,53 +5731,59 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_stat_info( MBG_DEV_HANDLE dh, STAT_INFO * /*HDR*/ /** - Sends a ::GPS_CMD to a GPS receiver. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::GPS_CMD - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see ::PC_GPS_CMD_BOOT, ::PC_GPS_CMD_INIT_SYS, ::PC_GPS_CMD_INIT_USER, ::PC_GPS_CMD_INIT_DAC -*/ + * @brief Send one of the ::PC_GPS_COMMANDS to a GPS receiver device + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::GPS_CMD + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::PC_GPS_COMMANDS + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_cmd( MBG_DEV_HANDLE dh, const GPS_CMD *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) GPS_CMD tmp = *p; _mbg_swab_gps_cmd( &tmp ); p = &tmp; #endif rc = _mbgdevio_write_gps_var( dh, PC_GPS_CMD, IOCTL_SET_GPS_CMD, p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_gps_cmd /*HDR*/ /** - Read the current GPS receiver position using the ::POS structure - which contains different coordinate formats. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::POS structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_gps_pos_xyz() - @see mbg_set_gps_pos_lla() -*/ + * @brief Read the current geographic position from a GPS device. + * + * The returned ::POS structure contains the current position in + * ECEF (Earth Centered, Earth Fixed) kartesian coordinates, and in + * geographic coordinates with different formats, using the WGS84 + * geographic datum. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::POS structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_gps_pos_xyz + * @see ::mbg_set_gps_pos_lla + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_pos( MBG_DEV_HANDLE dh, POS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_gps_var( dh, PC_GPS_POS, IOCTL_GET_GPS_POS, p ); swap_pos_doubles( p ); _mbg_swab_pos( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_pos @@ -2851,22 +5791,25 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_pos( MBG_DEV_HANDLE dh, POS *p ) /*HDR*/ /** - Preset the GPS receiver position using ::XYZ coordinates - (ECEF: WGS84 "Earth Centered, Earth fixed" kartesian coordinates). - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param p Position in ::XYZ format to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_gps_pos_lla() - @see mbg_get_gps_pos() -*/ + * @brief Set the GPS receiver position using ::XYZ coordinates + * + * The structure ::XYZ must specify the new position in ECEF + * (Earth Centered, Earth Fixed) kartesian coordinates. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Position in ::XYZ format to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_gps_pos_lla + * @see ::mbg_get_gps_pos + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_xyz( MBG_DEV_HANDLE dh, const XYZ p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; XYZ xyz; int i; @@ -2877,8 +5820,11 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_xyz( MBG_DEV_HANDLE dh, const XYZ p ) _mbg_swab_double( &xyz[i] ); } - rc = _mbgdevio_write_gps_var( dh, PC_GPS_POS_XYZ, IOCTL_SET_GPS_POS_XYZ, xyz ); - return _mbgdevio_ret_val; + // _mbgdevio_write_gps_var() would fail here since + // XYZ is an array, not a structure. + rc = _mbgdevio_write_gps( dh, PC_GPS_POS_XYZ, IOCTL_SET_GPS_POS_XYZ, + xyz, sizeof( XYZ ) ); + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_gps_pos_xyz @@ -2886,22 +5832,25 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_xyz( MBG_DEV_HANDLE dh, const XYZ p ) /*HDR*/ /** - Preset the GPS receiver position using ::LLA coordinates - (longitude, latitude, altitude) - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param p Position in ::LLA format to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_gps_pos_xyz() - @see mbg_get_gps_pos() -*/ + * @brief Set the GPS receiver position using ::LLA coordinates + * + * The structure ::LLA must specify the new position as longitude, + * latitude, and altitude, using the WGS84 geographic datum. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Position in ::LLA format to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_gps_pos_xyz + * @see ::mbg_get_gps_pos + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_lla( MBG_DEV_HANDLE dh, const LLA p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; LLA lla; int i; @@ -2912,8 +5861,11 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_lla( MBG_DEV_HANDLE dh, const LLA p ) _mbg_swab_double( &lla[i] ); } - rc = _mbgdevio_write_gps_var( dh, PC_GPS_POS_LLA, IOCTL_SET_GPS_POS_LLA, lla ); - return _mbgdevio_ret_val; + // _mbgdevio_write_gps_var() would fail here since + // LLA is an array, not a structure. + rc = _mbgdevio_write_gps( dh, PC_GPS_POS_LLA, IOCTL_SET_GPS_POS_LLA, lla, sizeof( LLA ) ); + + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_gps_pos_lla @@ -2921,27 +5873,31 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_lla( MBG_DEV_HANDLE dh, const LLA p ) /*HDR*/ /** - Read the configured length of the GPS antenna cable (::ANT_CABLE_LEN). - The cable delay is internally compensated by 5ns per meter cable. - The macro _pcps_has_cab_len() or the API call mbg_dev_has_cab_len() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p ::ANT_CABLE_LEN structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_cab_len() - @see mbg_set_gps_ant_cable_len() -*/ + * @brief Read the configured antenna cable length from a device + * + * The antenna cable length parameter is used by GPS/GNSS receivers + * to compensate the propagation delay of the RF signal over the antenna + * cable, which is about 5 ns/m. + * + * The API call ::mbg_chk_dev_has_cab_len checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an ::ANT_CABLE_LEN structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_cab_len + * @see ::mbg_set_gps_ant_cable_len + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_ant_cable_len( MBG_DEV_HANDLE dh, ANT_CABLE_LEN *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_gps_var_chk( dh, PC_GPS_ANT_CABLE_LEN, IOCTL_GET_GPS_ANT_CABLE_LEN, p, _pcps_ddev_has_cab_len( dh ) ); _mbg_swab_ant_cable_len( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_ant_cable_len @@ -2949,23 +5905,31 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_ant_cable_len( MBG_DEV_HANDLE dh, ANT_CAB /*HDR*/ /** - Write the length of the GPS antenna cable (::ANT_CABLE_LEN). - The cable delay is internally compensated by 5ns per meter cable. - The macro _pcps_has_cab_len() or the API call mbg_dev_has_cab_len() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p ::ANT_CABLE_LEN structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_cab_len() - @see mbg_get_gps_ant_cable_len() -*/ + * @brief Write the GPS antenna cable length configuration to a device. + * + * The antenna cable length parameter is used by GPS/GNSS receivers + * to compensate the propagation delay of the RF signal over the antenna + * cable, which is about 5 ns/m. + * + * The API call ::mbg_chk_dev_has_cab_len checks whether + * this call is supported by a device. + * + * @note Different devices may accept different maximum values, so the + * written value should be re-read using ::mbg_get_gps_ant_cable_len + * to check if the parameter has been accepted. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an ::ANT_CABLE_LEN structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_cab_len + * @see ::mbg_get_gps_ant_cable_len + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_ant_cable_len( MBG_DEV_HANDLE dh, const ANT_CABLE_LEN *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) ANT_CABLE_LEN tmp = *p; _mbg_swab_ant_cable_len( &tmp ); @@ -2974,7 +5938,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_ant_cable_len( MBG_DEV_HANDLE dh, _mbgdevio_write_gps_var_chk( dh, PC_GPS_ANT_CABLE_LEN, IOCTL_SET_GPS_ANT_CABLE_LEN, p, _pcps_ddev_has_cab_len( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_gps_ant_cable_len @@ -2982,30 +5946,32 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_ant_cable_len( MBG_DEV_HANDLE dh, /*HDR*/ /** - Read a ::RECEIVER_INFO structure from a card. - The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info() - check whether this call is supported by a specific card. - - <b>Note:</b> Applications should call mbg_setup_receiver_info() - preferably, which also sets up a basic ::RECEIVER_INFO structure - for card which don't provide that structure by themselves. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::RECEIVER_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_setup_receiver_info() -*/ + * @brief Read the ::RECEIVER_INFO structure from a device + * + * The API call ::mbg_chk_dev_has_receiver_info checks + * whether this call is supported by a device. + * + * <b>Note:</b> Applications should call ::mbg_setup_receiver_info + * preferably, which also sets up a basic ::RECEIVER_INFO structure + * for devices which don't provide that structure by themselves. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::RECEIVER_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_setup_receiver_info + * @see ::mbg_chk_dev_has_receiver_info + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_receiver_info( MBG_DEV_HANDLE dh, RECEIVER_INFO *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_gps_var_chk( dh, PC_GPS_RECEIVER_INFO, IOCTL_GET_GPS_RECEIVER_INFO, p, _pcps_ddev_has_receiver_info( dh ) ); _mbg_swab_receiver_info( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_receiver_info @@ -3013,30 +5979,31 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_receiver_info( MBG_DEV_HANDLE dh, RECEIVE #if !MBGDEVIO_SIMPLE -static /*HDR*/ -/* (Intentionally excluded from Doxygen) - Read a ::STR_TYPE_INFO_IDX array of supported string types. - The function mbg_setup_receiver_info() must have been called before, - and the returned ::RECEIVER_INFO structure passed to this function. - - <b>Note:</b> The function mbg_get_serial_settings() should be used preferably - to get retrieve the cuurrent port settings and configuration options. - - @param dh Valid handle to a Meinberg device. - @param stii Pointer to a an array of string type information to be filled up - @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info() - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_setup_receiver_info() - @see mbg_get_gps_all_port_info() - @see mbg_get_serial_settings() -*/ -int _MBG_API mbg_get_gps_all_str_type_info( MBG_DEV_HANDLE dh, - STR_TYPE_INFO_IDX stii[], - const RECEIVER_INFO *p_ri ) +/*HDR*/ +/** + * @brief Read a ::STR_TYPE_INFO_IDX array of supported string types. + * + * A valid ::RECEIVER_INFO associated with the device + * has to be passed to this function. + * + * <b>Note:</b> The function ::mbg_get_serial_settings should be used preferably + * to get retrieve the current port settings and configuration options. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] stii Pointer to a an array of string type information to be filled up. + * @param[in] p_ri Pointer to the ::RECEIVER_INFO associated with the device //### TODO Make this obsolete + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_serial_settings + * @see ::mbg_get_gps_all_port_info + * @see ::mbg_setup_receiver_info + */ +_MBG_API_ATTR int _MBG_API mbg_get_gps_all_str_type_info( MBG_DEV_HANDLE dh, + STR_TYPE_INFO_IDX stii[], + const RECEIVER_INFO *p_ri ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if _MBG_SUPP_VAR_ACC_SIZE _mbgdevio_read_gps_chk( dh, PC_GPS_ALL_STR_TYPE_INFO, @@ -3051,11 +6018,11 @@ int _MBG_API mbg_get_gps_all_str_type_info( MBG_DEV_HANDLE dh, rc = _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_STR_TYPE_INFO, stii, p_ri->n_str_type * sizeof( stii[0] ) ); else - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV ); + return MBG_ERR_NOT_SUPP_BY_DEV; #endif #if defined( MBG_ARCH_BIG_ENDIAN ) - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) { int i; for ( i = 0; i < p_ri->n_str_type; i++ ) @@ -3066,36 +6033,37 @@ int _MBG_API mbg_get_gps_all_str_type_info( MBG_DEV_HANDLE dh, } #endif - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_all_str_type_info -static /*HDR*/ -/* (Intentionally excluded from Doxygen) - Read a ::PORT_INFO_IDX array of supported serial port configurations. - The function mbg_setup_receiver_info() must have been called before, - and the returned ::RECEIVER_INFO structure passed to this function. - - <b>Note:</b> The function mbg_get_serial_settings() should be used preferably - to get retrieve the cuurrent port settings and configuration options. - - @param dh Valid handle to a Meinberg device. - @param pii Pointer to a an array of port configuration information to be filled up - @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info() - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_setup_receiver_info() - @see mbg_get_gps_all_str_type_info() - @see mbg_get_serial_settings() -*/ -int _MBG_API mbg_get_gps_all_port_info( MBG_DEV_HANDLE dh, - PORT_INFO_IDX pii[], - const RECEIVER_INFO *p_ri ) +/*HDR*/ +/** + * @brief Read a ::PORT_INFO_IDX array of supported serial port configurations. + * + * A valid ::RECEIVER_INFO associated with the device + * has to be passed to this function. + * + * <b>Note:</b> The function ::mbg_get_serial_settings should be used preferably + * to get retrieve the current port settings and configuration options. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] pii Pointer to a an array of port configuration information to be filled up. + * @param[in] p_ri Pointer to the ::RECEIVER_INFO associated with the device //### TODO Make this obsolete + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_serial_settings + * @see ::mbg_get_gps_all_str_type_info + * @see ::mbg_setup_receiver_info + */ +_MBG_API_ATTR int _MBG_API mbg_get_gps_all_port_info( MBG_DEV_HANDLE dh, + PORT_INFO_IDX pii[], + const RECEIVER_INFO *p_ri ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if _MBG_SUPP_VAR_ACC_SIZE _mbgdevio_read_gps_chk( dh, PC_GPS_ALL_PORT_INFO, @@ -3110,11 +6078,11 @@ int _MBG_API mbg_get_gps_all_port_info( MBG_DEV_HANDLE dh, rc = _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_PORT_INFO, pii, p_ri->n_com_ports * sizeof( pii[0] ) ); else - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV ); + return MBG_ERR_NOT_SUPP_BY_DEV; #endif #if defined( MBG_ARCH_BIG_ENDIAN ) - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) { int i; for ( i = 0; i < p_ri->n_com_ports; i++ ) @@ -3125,7 +6093,7 @@ int _MBG_API mbg_get_gps_all_port_info( MBG_DEV_HANDLE dh, } #endif - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_all_port_info @@ -3133,28 +6101,31 @@ int _MBG_API mbg_get_gps_all_port_info( MBG_DEV_HANDLE dh, /*HDR*/ /** - Write the configuration for a single serial port using the ::PORT_SETTINGS_IDX - structure which contains both the ::PORT_SETTINGS and the port index value. - Except for the parameter types, this call is equivalent to mbg_set_gps_port_settings(). - The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info() - check whether this call is supported by a specific card. - - <b>Note:</b> The function mbg_save_serial_settings() should be used preferably - to write new port configuration to the board. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::PORT_SETTINGS_IDX structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_save_serial_settings() - @see mbg_set_gps_port_settings() - @see mbg_dev_has_receiver_info() -*/ + * @brief Write the configuration for a single serial port to a device. + * + * The ::PORT_SETTINGS_IDX structure contains both the ::PORT_SETTINGS + * and the port index value. Except for the parameter types this call is + * equivalent to ::mbg_set_gps_port_settings. + * + * The API call ::mbg_chk_dev_has_receiver_info checks + * whether this call is supported by a device. + * + * <b>Note:</b> The function ::mbg_save_serial_settings should be used preferably + * to write new port configuration to the board. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PORT_SETTINGS_IDX structure to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_save_serial_settings + * @see ::mbg_set_gps_port_settings + * @see ::mbg_chk_dev_has_receiver_info + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings_idx( MBG_DEV_HANDLE dh, const PORT_SETTINGS_IDX *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) PORT_SETTINGS_IDX tmp = *p; _mbg_swab_port_settings_idx( &tmp ); @@ -3163,7 +6134,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings_idx( MBG_DEV_HANDLE dh, _mbgdevio_write_gps_var_chk( dh, PC_GPS_PORT_SETTINGS_IDX, IOCTL_SET_GPS_PORT_SETTINGS_IDX, p, _pcps_ddev_has_receiver_info( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_gps_port_settings_idx @@ -3171,25 +6142,28 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings_idx( MBG_DEV_HANDLE dh, /*HDR*/ /** - Write the configuration for a single serial port using the ::PORT_SETTINGS - structure plus the port index. - Except for the parameter types, this call is equivalent to mbg_set_gps_port_settings_idx(). - The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info() - check whether this call is supported by a specific card. - - <b>Note:</b> The function mbg_save_serial_settings() should be used preferably - to write new port configuration to the board. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::PORT_SETTINGS structure to be filled up - @param idx Index of the serial port to be configured (starting from 0 ). - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_save_serial_settings() - @see mbg_set_gps_port_settings_idx() - @see mbg_dev_has_receiver_info() -*/ + * @brief Write the configuration for a single serial port to a device. + * + * The ::PORT_SETTINGS structure does not contain the port index, so the + * the port index must be given separately. Except for the parameter types + * this call is equivalent to ::mbg_set_gps_port_settings_idx. + * + * The API call ::mbg_chk_dev_has_receiver_info checks + * whether this call is supported by a device. + * + * <b>Note:</b> The function ::mbg_save_serial_settings should be used preferably + * to write new port configuration to the board. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PORT_SETTINGS structure to be written. + * @param[in] idx Index of the serial port to be configured (starting from 0). + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_save_serial_settings + * @see ::mbg_set_gps_port_settings_idx + * @see ::mbg_chk_dev_has_receiver_info + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings( MBG_DEV_HANDLE dh, const PORT_SETTINGS *p, int idx ) { @@ -3209,54 +6183,73 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings( MBG_DEV_HANDLE dh, /*HDR*/ /** - Set up a ::RECEIVER_INFO structure for a device. - If the device supports the ::RECEIVER_INFO structure then the structure - is read from the device, otherwise a structure is set up using - default values depending on the device type. - The function mbg_get_device_info() must have been called before, - and the returned PCPS_DEV structure passed to this function. - - @param dh Valid handle to a Meinberg device. - @param *pdev Pointer to a ::PCPS_DEV structure returned by mbg_get_device_info() - @param *p Pointer to a ::RECEIVER_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_device_info() - @see mbg_dev_has_receiver_info() -*/ + * @brief Set up a ::RECEIVER_INFO structure for a device. + * + * If the device supports the ::RECEIVER_INFO structure then the structure + * is read from the device, otherwise a structure is set up using + * default values depending on the device type. + * + * Optionally, the function ::mbg_get_device_info may have been called + * before, and the returned ::PCPS_DEV structure can be passed to this + * function. + * + * If a NULL pointer is passed instead, the device info is retrieved + * directly from the device, using the device handle. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p_dev Optional pointer to a ::PCPS_DEV structure, may be NULL. + * @param[out] p Pointer to a ::RECEIVER_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_device_info + * @see ::mbg_chk_dev_has_receiver_info + */ _MBG_API_ATTR int _MBG_API mbg_setup_receiver_info( MBG_DEV_HANDLE dh, - const PCPS_DEV *pdev, + const PCPS_DEV *p_dev, RECEIVER_INFO *p ) { + PCPS_DEV dev = { { 0 } }; + int rc; + + if ( p_dev == NULL ) + { + rc = mbg_get_device_info( dh, &dev ); + + if ( mbg_rc_is_error( rc ) ) + return rc; + + p_dev = &dev; + } + // If the clock supports the receiver_info structure then // read it from the clock, otherwise set up some default // values depending on the clock type. - if ( _pcps_has_receiver_info( pdev ) ) + if ( _pcps_has_receiver_info( p_dev ) ) { - int rc = mbg_get_gps_receiver_info( dh, p ); + rc = mbg_get_gps_receiver_info( dh, p ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) return rc; goto check; } - if ( _pcps_is_gps( pdev ) ) + if ( _pcps_is_gps( p_dev ) ) _setup_default_receiver_info_gps( p ); else - _setup_default_receiver_info_dcf( p, pdev ); + _setup_default_receiver_info_dcf( p, p_dev ); check: // Make sure this program supports at least as many ports as // the current clock device. if ( p->n_com_ports > MAX_PARM_PORT ) - return _mbg_err_to_os( MBG_ERR_N_COM_EXCEEDS_SUPP ); + return MBG_ERR_N_COM_EXCEEDS_SUPP; // Make sure this program supports at least as many string types // as the current clock device. if ( p->n_str_type > MAX_PARM_STR_TYPE ) - return _mbg_err_to_os( MBG_ERR_N_STR_EXCEEDS_SUPP ); + return MBG_ERR_N_STR_EXCEEDS_SUPP; return MBG_SUCCESS; @@ -3265,199 +6258,29 @@ check: -#if !MBGDEVIO_SIMPLE - -// The functions below can conditionally be excluded from build -// for simple applications which don't do complex card configuration. -// This reduces the number of modules needed to be linked to the -// application. - /*HDR*/ /** - Read all serial port settings and supported configuration parameters. - - The functions mbg_get_device_info() and mbg_setup_receiver_info() - must have been called before, and the returned ::PCPS_DEV and - ::RECEIVER_INFO structures must be passed to this function. - - The complementary function mbg_save_serial_settings() should be used - to write the modified serial port configuration back to the board. - - @param dh Valid handle to a Meinberg device. - @param *pdev Pointer to a ::PCPS_DEV structure. - @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure to be filled up. - @param *p_ri Pointer to a ::RECEIVER_INFO structure. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_device_info() - @see mbg_setup_receiver_info() - @see mbg_save_serial_settings() -*/ -_MBG_API_ATTR int _MBG_API mbg_get_serial_settings( MBG_DEV_HANDLE dh, - const PCPS_DEV *pdev, - RECEIVER_PORT_CFG *pcfg, - const RECEIVER_INFO *p_ri ) -{ - int rc; - int i; - - memset( pcfg, 0, sizeof( *pcfg ) ); - - if ( _pcps_has_receiver_info( pdev ) ) - { - rc = mbg_get_gps_all_port_info( dh, pcfg->pii, p_ri ); - if ( rc != MBG_SUCCESS ) - goto error; - - rc = mbg_get_gps_all_str_type_info( dh, pcfg->stii, p_ri ); - if ( rc != MBG_SUCCESS ) - goto error; - } - else - { - if ( _pcps_is_gps( pdev ) ) - { - rc = mbg_get_gps_port_parm( dh, &pcfg->tmp_pp ); - if ( rc != MBG_SUCCESS ) - goto error; - - for ( i = 0; i < p_ri->n_com_ports; i++ ) - { - PORT_INFO_IDX *p_pii = &pcfg->pii[i]; - PORT_INFO *p_pi = &p_pii->port_info; - - p_pii->idx = i; - port_settings_from_port_parm( &p_pi->port_settings, - i, &pcfg->tmp_pp, 1 ); - - p_pi->supp_baud_rates = DEFAULT_GPS_BAUD_RATES_C166; - p_pi->supp_framings = DEFAULT_GPS_FRAMINGS_C166; - p_pi->supp_str_types = DEFAULT_SUPP_STR_TYPES_GPS; - } - } - else - if ( _pcps_has_serial ( pdev ) ) // Not all non-GPS clocks have a serial port! - { - PCPS_SERIAL ser_code; - - rc = mbg_get_serial( dh, &ser_code ); - if ( rc != MBG_SUCCESS ) - goto error; - - - port_info_from_pcps_serial( pcfg->pii, ser_code, - _pcps_has_serial_hs( pdev ) ? - DEFAULT_BAUD_RATES_DCF_HS : - DEFAULT_BAUD_RATES_DCF - ); - } - - for ( i = 0; i < p_ri->n_str_type; i++ ) - { - STR_TYPE_INFO_IDX *stip = &pcfg->stii[i]; - stip->idx = i; - stip->str_type_info = default_str_type_info[i]; - } - } - - return MBG_SUCCESS; - - -error: - return rc; - -} // mbg_get_serial_settings - - - -/*HDR*/ -/** - Write the configuration settings for a single serial port to the board. - - Modifications to the serial port configuration should be made only - after mbg_get_serial_settings() had been called to read all serial port - settings and supported configuration parameters. - This function has finally to be called once for every serial port - the configuration of which has been modified. - - As also required by mbg_get_serial_settings(), the functions - mbg_get_device_info() and mbg_setup_receiver_info() must have been - called before, and the returned ::PCPS_DEV and ::RECEIVER_INFO structures - must be passed to this function. - - @param dh Valid handle to a Meinberg device - @param *pdev Pointer to a ::PCPS_DEV structure - @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure - @param port_num Index of the ::serial port to be saved - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_serial_settings() - @see mbg_get_device_info() - @see mbg_setup_receiver_info() -*/ -_MBG_API_ATTR int _MBG_API mbg_save_serial_settings( MBG_DEV_HANDLE dh, - const PCPS_DEV *pdev, - RECEIVER_PORT_CFG *pcfg, - int port_num ) -{ - int rc; - - if ( _pcps_has_receiver_info( pdev ) ) - { - rc = mbg_set_gps_port_settings( dh, &pcfg->pii[port_num].port_info.port_settings, port_num ); - } - else - { - if ( _pcps_is_gps( pdev ) ) - { - port_parm_from_port_settings( &pcfg->tmp_pp, port_num, - &pcfg->pii[port_num].port_info.port_settings, 1 ); - - rc = mbg_set_gps_port_parm( dh, &pcfg->tmp_pp ); - } - else - { - PCPS_SERIAL ser_code; - - pcps_serial_from_port_info( &ser_code, pcfg->pii ); - - rc = mbg_set_serial( dh, &ser_code ); - } - } - - return rc; - -} // mbg_save_serial_settings - -#endif // !MBGDEVIO_SIMPLE - - - -/*HDR*/ -/** - Read the version code of the on-board PCI/PCIe interface ASIC. - The macro _pcps_has_asic_version() or the API call mbg_dev_has_asic_version() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCI_ASIC_VERSION type to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function - - @see mbg_dev_has_asic_version() -*/ + * @brief Read the version code of the on-board PCI/PCIe interface ASIC. + * + * The API call ::mbg_chk_dev_has_asic_version checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCI_ASIC_VERSION type to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_asic_version + */ _MBG_API_ATTR int _MBG_API mbg_get_asic_version( MBG_DEV_HANDLE dh, PCI_ASIC_VERSION *p ) { - #if defined( _MBGIOCTL_H ) - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, -1, IOCTL_GET_PCI_ASIC_VERSION, p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); #else if ( !_pcps_ddev_has_asic_version( dh ) ) - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV ); + return MBG_ERR_NOT_SUPP_BY_DEV; *p = _mbg_inp32_to_cpu( dh, 0, _pcps_ddev_io_base_mapped( dh, 0 ) + offsetof( PCI_ASIC, raw_version ) ); @@ -3471,30 +6294,31 @@ _MBG_API_ATTR int _MBG_API mbg_get_asic_version( MBG_DEV_HANDLE dh, PCI_ASIC_VER /*HDR*/ /** - Read the features of the on-board PCI/PCIe interface ASIC. - The macro _pcps_has_asic_features() or the API call mbg_dev_has_asic_features() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::PCI_ASIC_FEATURES type to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_asic_features() -*/ + * @brief Read the features of the on-board PCI/PCIe interface ASIC + * + * The API call ::mbg_chk_dev_has_asic_features checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCI_ASIC_FEATURES type to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_asic_features + */ _MBG_API_ATTR int _MBG_API mbg_get_asic_features( MBG_DEV_HANDLE dh, PCI_ASIC_FEATURES *p ) { #if defined( _MBGIOCTL_H ) - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, -1, IOCTL_GET_PCI_ASIC_FEATURES, p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); #else if ( !_pcps_ddev_has_asic_features( dh ) ) { *p = 0; - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV ); + return MBG_ERR_NOT_SUPP_BY_DEV; } *p = _mbg_inp32_to_cpu( dh, 0, _pcps_ddev_io_base_mapped( dh, 0 ) @@ -3509,52 +6333,32 @@ _MBG_API_ATTR int _MBG_API mbg_get_asic_features( MBG_DEV_HANDLE dh, /*HDR*/ /** - Check if a specific device supports configurable time scales. - - By default the cards return UTC and/or local time. However, some cards - can be configured to return pure GPS time or TAI instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_time_scale_info() - @see mbg_set_time_scale_settings() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_time_scale( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_time_scale, IOCTL_DEV_HAS_GPS_TIME_SCALE, p ); - -} // mbg_dev_has_time_scale - - - -/*HDR*/ -/** - Read a ::MBG_TIME_SCALE_INFO structure from a card telling which time scales - are supported by a card, and the current settings of the card. - - The macro _pcps_has_time_scale() or the API call mbg_dev_has_time_scale() - check whether this call is supported by a specific card. - See also the notes for mbg_dev_has_time_scale(). - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_TIME_SCALE_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_time_scale_settings() - @see mbg_dev_has_time_scale() -*/ + * @brief Read the current time scale settings and which time scales are supported + * + * The ::MBG_TIME_SCALE_INFO structure tells which time scale settings are supported + * by a device, and which time scale is currently configured. + * + * The API call ::mbg_chk_dev_has_time_scale checks whether + * this call is supported by a device. + * + * See also the notes for ::mbg_chk_dev_has_time_scale. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_TIME_SCALE_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_time_scale_settings + * @see ::mbg_chk_dev_has_time_scale + */ _MBG_API_ATTR int _MBG_API mbg_get_time_scale_info( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_INFO *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_gps_var_chk( dh, PC_GPS_TIME_SCALE, IOCTL_GET_GPS_TIME_SCALE_INFO, p, _pcps_ddev_has_time_scale( dh ) ); _mbg_swab_mbg_time_scale_info( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_time_scale_info @@ -3562,27 +6366,30 @@ _MBG_API_ATTR int _MBG_API mbg_get_time_scale_info( MBG_DEV_HANDLE dh, MBG_TIME_ /*HDR*/ /** - Write a ::MBG_TIME_SCALE_SETTINGS structure to a card which determines - which time scale shall be represented by time stamps read from the card. - - The macro _pcps_has_time_scale() or the API call mbg_dev_has_time_scale() - check whether this call is supported by a specific card. - See also the notes for mbg_dev_has_time_scale(). - - The function mbg_get_time_scale_info() should have been called before - in order to determine which time scales are supported by the card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_TIME_SCALE_SETTINGS structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_time_scale_info() - @see mbg_dev_has_time_scale() -*/ -_MBG_API_ATTR int _MBG_API mbg_set_time_scale_settings( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_SETTINGS *p ) + * @brief Write the time scale configuration to a device + * + * The ::MBG_TIME_SCALE_SETTINGS structure determines which time scale + * is to be used for the time stamps which can be read from a device. + * + * The API call ::mbg_chk_dev_has_time_scale checks whether + * this call is supported by a device. + * + * See also the notes for ::mbg_chk_dev_has_time_scale. + * + * The function ::mbg_get_time_scale_info should have been called before + * in order to determine which time scales are supported by the card. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::MBG_TIME_SCALE_SETTINGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_time_scale_info + * @see ::mbg_chk_dev_has_time_scale + */ +_MBG_API_ATTR int _MBG_API mbg_set_time_scale_settings( MBG_DEV_HANDLE dh, const MBG_TIME_SCALE_SETTINGS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) MBG_TIME_SCALE_SETTINGS tmp = *p; _mbg_swab_mbg_time_scale_settings( &tmp ); @@ -3591,7 +6398,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_time_scale_settings( MBG_DEV_HANDLE dh, MBG_T _mbgdevio_write_gps_var_chk( dh, PC_GPS_TIME_SCALE, IOCTL_SET_GPS_TIME_SCALE_SETTINGS, p, _pcps_ddev_has_time_scale( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_time_scale_settings @@ -3599,59 +6406,31 @@ _MBG_API_ATTR int _MBG_API mbg_set_time_scale_settings( MBG_DEV_HANDLE dh, MBG_T /*HDR*/ /** - Check if a specific device supports reading/writing a GPS UTC parameter - set via the PC bus (reading/writing these parameters via the serial port - is supported by all GPS devices). - - The UTC parameters are normally received from the satellites' broadcasts - and contain the current time offset between GPT time and UTC, plus information - on a pending leap second. - - It may be useful to overwrite them to do some tests, or for applications - where a card is freewheeling. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_utc_parm() - @see mbg_set_utc_parm() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_utc_parm( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_utc_parm, IOCTL_DEV_HAS_GPS_UTC_PARM, p ); - -} // mbg_dev_has_utc_parm - - - -/*HDR*/ -/** - Read a ::UTC structure from a card. - - The macro _pcps_has_utc_parm() or the API call mbg_dev_has_utc_parm() - check whether this call is supported by a specific card. - See also the notes for mbg_dev_has_utc_parm(). - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::UTC structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_utc_parm() - @see mbg_set_utc_parm() -*/ + * @brief Read a ::UTC parameter structure from a device + * + * The API call ::mbg_chk_dev_has_utc_parm checks whether + * this call is supported by a device. + * + * See also the notes for ::mbg_chk_dev_has_utc_parm. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::UTC structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_utc_parm + * @see ::mbg_set_utc_parm + */ _MBG_API_ATTR int _MBG_API mbg_get_utc_parm( MBG_DEV_HANDLE dh, UTC *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_gps_var_chk( dh, PC_GPS_UTC, IOCTL_GET_GPS_UTC_PARM, p, _pcps_ddev_has_utc_parm( dh ) ); _mbg_swab_utc_parm( p ); swap_double( &p->A0 ); swap_double( &p->A1 ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_utc_parm @@ -3659,39 +6438,44 @@ _MBG_API_ATTR int _MBG_API mbg_get_utc_parm( MBG_DEV_HANDLE dh, UTC *p ) /*HDR*/ /** - Write a ::UTC structure to a card. - - This should only be done for testing, or if a card is operated in - freewheeling mode. If the card receives any satellites the settings - written to the board are overwritten by the parameters broadcasted - by the satellites. - - The macro _pcps_has_utc_parm() or the API call mbg_dev_has_utc_parm() - check whether this call is supported by a specific card. - See also the notes for mbg_dev_has_utc_parm(). - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a valid ::UTC structure to be written + * @brief Write a ::UTC parameter structure to a device. + * + * This should only be done for testing, or if a card is operated in + * freewheeling mode. If the receiver is tracking any satellites then the settings + * written to the device are overwritten by the parameters broadcast + * by the satellites. + * + * The API call ::mbg_chk_dev_has_utc_parm checks whether + * this call is supported by a device. + * + * See also the notes for mbg_chk_dev_has_utc_parm. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a valid ::UTC structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_utc_parm + * @see ::mbg_get_utc_parm + */ +_MBG_API_ATTR int _MBG_API mbg_set_utc_parm( MBG_DEV_HANDLE dh, const UTC *p ) +{ + MBGDEVIO_RET_VAL rc; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + // the original parameters need to be modified anyway, so always use a copy + UTC tmp = *p; - @see mbg_dev_has_utc_parm() - @see mbg_get_utc_parm() -*/ -_MBG_API_ATTR int _MBG_API mbg_set_utc_parm( MBG_DEV_HANDLE dh, UTC *p ) -{ - _mbgdevio_vars(); #if defined( MBG_ARCH_BIG_ENDIAN ) - UTC tmp = *p; _mbg_swab_utc_parm( &tmp ); - p = &tmp; #endif - swap_double( &p->A0 ); - swap_double( &p->A1 ); + + swap_double( &tmp.A0 ); + swap_double( &tmp.A1 ); + _mbgdevio_write_gps_var_chk( dh, PC_GPS_UTC, - IOCTL_SET_GPS_UTC_PARM, p, + IOCTL_SET_GPS_UTC_PARM, &tmp, _pcps_ddev_has_utc_parm( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_utc_parm @@ -3699,37 +6483,40 @@ _MBG_API_ATTR int _MBG_API mbg_set_utc_parm( MBG_DEV_HANDLE dh, UTC *p ) /*HDR*/ /** - Read a ::PCPS_TIME_CYCLES structure that contains a ::PCPS_TIME structure - and a PC cycle counter value which can be used to compensate the latency - of the call, i.e. the program execution time until the time stamp has actually - been read from the board. - - This call is supported for any card, similar to mbg_get_time(). However, - the mbg_get_hr_time_cyles() call should be used preferably if supported by - the specific card since that call provides much better accuracy than this one. - - The cycle counter value corresponds to a value returned by QueryPerformanceCounter() - under Windows, and get_cycles() under Linux. On other operating systems the returned - cycles value is always 0. - - Applications should first pick up their own cycle counter value and then call - this function. The difference of the cycle counter values corresponds to the - latency of the call in units of the cycle counter clock frequency, e.g as reported - by QueryPerformanceFrequency() under Windows. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME_CYCLES structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_hr_time_cycles() - @see mbg_get_hr_time_comp() - @see mbg_get_hr_time() - @see mbg_get_time() -*/ + * @brief Read the current time plus the associated PC cycles from a device. + * + * The ::PCPS_TIME_CYCLES structure contains a ::PCPS_TIME structure + * and a PC cycles counter value which can be used to compensate the latency + * of the call, i.e. the program execution time until the time stamp has actually + * been read from the board. + * + * This call is supported for any card, similar to ::mbg_get_time. However, + * the ::mbg_get_hr_time_cycles call should be used preferably if supported by + * the device since that call provides much better accuracy than this one. + * + * The cycles counter value corresponds to a value returned by QueryPerformanceCounter() + * under Windows, and get_cycles() under Linux. On operating systems or targets which don't + * provide a cycles counter the returned cycles value is always 0. + * + * Applications should first pick up their own cycles counter value and then call + * this function. The difference of the cycles counter values corresponds to the + * latency of the call in units of the cycles counter clock frequency, e.g as reported + * by QueryPerformanceFrequency() under Windows. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME_CYCLES structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_legacy_time_fncs + * @see ::mbg_get_hr_time_cycles + * @see ::mbg_get_hr_time_comp + * @see ::mbg_get_hr_time + * @see ::mbg_get_time + */ _MBG_API_ATTR int _MBG_API mbg_get_time_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_CYCLES *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, PCPS_GIVE_TIME, IOCTL_GET_PCPS_TIME_CYCLES, p ); // No endianess conversion required. #if !defined( _MBGIOCTL_H ) @@ -3737,7 +6524,7 @@ _MBG_API_ATTR int _MBG_API mbg_get_time_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_CYC // for PCPS_TIME, read stamp AFTER the call p->cycles = 0; //##++ #endif - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_time_cycles @@ -3745,37 +6532,45 @@ _MBG_API_ATTR int _MBG_API mbg_get_time_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_CYC /*HDR*/ /** - Read a ::PCPS_HR_TIME_CYCLES structure that contains a ::PCPS_HR_TIME structure - and a PC cycle counter value which can be used to compensate the latency - of the call, i.e. the program execution time until the time stamp has actually - been read from the board. - - The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() - check whether this call is supported by a specific card. - - The cycle counter value corresponds to a value returned by QueryPerformanceCounter() - under Windows, and get_cycles() under Linux. On other operating systems the returned - cycles value is always 0. - - Applications should first pick up their own cycle counter value and then call - this function. The difference of the cycle counter values corresponds to the - latency of the call in units of the cycle counter clock frequency, e.g as reported - by QueryPerformanceFrequency() under Windows. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_HR_TIME_CYCLES structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_hr_time_comp() - @see mbg_get_hr_time() - @see mbg_get_time_cycles() - @see mbg_get_time() -*/ + * @brief Read the current high resolution time plus the associated PC cycles from a device. + * + * The returned ::PCPS_HR_TIME_CYCLES structure contains a ::PCPS_HR_TIME + * structure and a PC cycles counter value which can be used to compensate + * the latency of the call, i.e. the program execution time until the time stamp + * has actually been read from the board. + * + * The API call ::mbg_chk_dev_has_hr_time checks whether + * this call is supported by the device. + * + * For details see @ref ::mbgdevio_hr_time_fncs + * + * The cycles counter value corresponds to a value returned by QueryPerformanceCounter() + * under Windows, and get_cycles() under Linux. On operating systems or targets which don't + * provide a cycles counter the returned cycles value is always 0. + * + * Applications should first pick up their own cycles counter value and then call + * this function. The difference of the cycles counter values corresponds to the + * latency of the call in units of the cycles counter clock frequency, e.g as reported + * by QueryPerformanceFrequency() under Windows. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_HR_TIME_CYCLES structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_hr_time_fncs + * @see ::mbg_chk_dev_has_hr_time + * @see ::mbg_get_hr_time + * @see ::mbg_get_hr_time_cycles + * @see ::mbg_get_hr_time_comp + * @see @ref mbgdevio_hr_time_fncs + * @see @ref mbgdevio_fast_timestamp_fncs + * @see @ref mbgdevio_legacy_time_fncs + */ _MBG_API_ATTR int _MBG_API mbg_get_hr_time_cycles( MBG_DEV_HANDLE dh, PCPS_HR_TIME_CYCLES *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if !defined( _MBGIOCTL_H ) // only if not using IOCTLs // for PCPS_HR_TIME, read stamp BEFORE the call @@ -3785,7 +6580,7 @@ _MBG_API_ATTR int _MBG_API mbg_get_hr_time_cycles( MBG_DEV_HANDLE dh, IOCTL_GET_PCPS_HR_TIME_CYCLES, p, _pcps_ddev_has_hr_time( dh ) ); _mbg_swab_pcps_hr_time_cycles( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_hr_time_cycles @@ -3793,34 +6588,42 @@ _MBG_API_ATTR int _MBG_API mbg_get_hr_time_cycles( MBG_DEV_HANDLE dh, /*HDR*/ /** - Read a ::PCPS_HR_TIME structure plus cycle counter value, and correct the - time stamp for the latency of the call as described for mbg_get_hr_time_cycles(), - then return the compensated time stamp and optionally the latency. - - The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() - check whether this call is supported by a specific card. - - The cycle counter value corresponds to a value returned by QueryPerformanceCounter() - under Windows, and get_cycles() under Linux. On other operating systems the returned - cycles value is always 0. - - Applications should first pick up their own cycle counter value and then call - this function. The difference of the cycle counter values corresponds to the - latency of the call in units of the cycle counter clock frequency, e.g as reported - by QueryPerformanceFrequency() under Windows. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up - @param *hns_latency Optional pointer to an int32_t value to return - the latency in 100ns units. Pass NULL if not used. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_hr_time_comp() - @see mbg_get_hr_time() - @see mbg_get_time_cycles() - @see mbg_get_time() -*/ + * @brief Read the current high resolution time, and compensate the call's latency. + * + * Read a ::PCPS_HR_TIME structure plus cycles counter value, and correct the + * time stamp for the latency of the call as described for ::mbg_get_hr_time_cycles, + * then return the compensated time stamp, and optionally the latency. + * + * The API call ::mbg_chk_dev_has_hr_time checks whether + * this call is supported by the device. + * + * For details see @ref ::mbgdevio_hr_time_fncs + * + * The cycles counter value corresponds to a value returned by QueryPerformanceCounter() + * under Windows, and get_cycles() under Linux. On operating systems or targets which don't + * provide a cycles counter the returned cycles value is always 0. + * + * Applications should first pick up their own cycles counter value and then call + * this function. The difference of the cycles counter values corresponds to the + * latency of the call in units of the cycles counter clock frequency, e.g as reported + * by QueryPerformanceFrequency() under Windows. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_HR_TIME structure to be filled up + * @param[out] hns_latency Optional pointer to an int32_t value to return + * the latency in 100ns units, or NULL, if not used. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_hr_time_fncs + * @see ::mbg_chk_dev_has_hr_time + * @see ::mbg_get_hr_time + * @see ::mbg_get_hr_time_cycles + * @see ::mbg_get_hr_time_comp + * @see @ref mbgdevio_hr_time_fncs + * @see @ref mbgdevio_fast_timestamp_fncs + * @see @ref mbgdevio_legacy_time_fncs + */ _MBG_API_ATTR int _MBG_API mbg_get_hr_time_comp( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p, int32_t *hns_latency ) { @@ -3835,7 +6638,7 @@ _MBG_API_ATTR int _MBG_API mbg_get_hr_time_comp( MBG_DEV_HANDLE dh, PCPS_HR_TIME rc = mbg_get_hr_time_cycles( dh, &htc ); - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) { mbg_init_pc_cycles_frequency( dh, &pc_cycles_frequency ); rc = mbg_comp_hr_latency( &htc.t.tstamp, &htc.cycles, &cyc_now, &pc_cycles_frequency, hns_latency ); @@ -3850,25 +6653,28 @@ _MBG_API_ATTR int _MBG_API mbg_get_hr_time_comp( MBG_DEV_HANDLE dh, PCPS_HR_TIME /*HDR*/ /** - Read an ::IRIG_INFO structure containing the configuration of an IRIG output - plus the possible settings supported by that output. - The macro _pcps_has_irig_tx() or the API call mbg_dev_has_irig_tx() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an ::IRIG_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_irig_tx_settings() - @see mbg_dev_has_irig_tx() - @see mbg_dev_is_irig_rx() - @see mbg_dev_has_irig() - @see \ref group_icode -*/ + * @brief Read the current IRIG output settings plus the supported settings. + * + * The returned ::IRIG_INFO structure contains the configuration of an IRIG output + * plus the possible settings supported by that output. + * + * The API call ::mbg_chk_dev_has_irig_tx checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an ::IRIG_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_irig_tx_settings + * @see ::mbg_chk_dev_has_irig_tx + * @see ::mbg_chk_dev_is_tcr + * @see ::mbg_chk_dev_has_irig + * @see @ref group_icode + */ _MBG_API_ATTR int _MBG_API mbg_get_irig_tx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if !defined( _MBGIOCTL_H ) // This is a workaround for GPS169PCIs with early @@ -3888,7 +6694,7 @@ _MBG_API_ATTR int _MBG_API mbg_get_irig_tx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p #undef _PCPS_CMD _mbg_swab_irig_info( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_irig_tx_info @@ -3896,24 +6702,25 @@ _MBG_API_ATTR int _MBG_API mbg_get_irig_tx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p /*HDR*/ /** - Write an ::IRIG_SETTINGS structure containing the configuration of an IRIG output. - The macro _pcps_has_irig_tx() or the API call mbg_dev_has_irig_tx() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an ::IRIG_INFO structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_irig_tx_info() - @see mbg_dev_has_irig_tx() - @see mbg_dev_is_irig_rx() - @see mbg_dev_has_irig() - @see \ref group_icode -*/ + * @brief Write an ::IRIG_SETTINGS structure to a device to configure the IRIG output + * + * The API call ::mbg_chk_dev_has_irig_tx checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to an ::IRIG_INFO structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_irig_tx_info + * @see ::mbg_chk_dev_has_irig_tx + * @see ::mbg_chk_dev_is_tcr + * @see ::mbg_chk_dev_has_irig + * @see @ref group_icode + */ _MBG_API_ATTR int _MBG_API mbg_set_irig_tx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if !defined( _MBGIOCTL_H ) uint8_t pcps_cmd; #endif @@ -3941,7 +6748,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_irig_tx_settings( MBG_DEV_HANDLE dh, const IR p, _pcps_ddev_has_irig_tx( dh ) ); #undef _PCPS_CMD - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_irig_tx_settings @@ -3949,28 +6756,31 @@ _MBG_API_ATTR int _MBG_API mbg_set_irig_tx_settings( MBG_DEV_HANDLE dh, const IR /*HDR*/ /** - Read a ::SYNTH structure containing the configuration of an optional - on-board programmable frequency synthesizer. - The macro _pcps_has_synth() or the API call mbg_dev_has_synth() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::SYNTH structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_synth() - @see mbg_set_synth() - @see mbg_get_synth_state() - @see \ref group_synth -*/ + * @brief Read the current frequency synthesizer settings from a device + * + * Read a ::SYNTH structure containing the configuration of an optional + * on-board programmable frequency synthesizer. + * + * The API call ::mbg_chk_dev_has_synth checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::SYNTH structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_synth + * @see ::mbg_set_synth + * @see ::mbg_get_synth_state + * @see @ref group_synth + */ _MBG_API_ATTR int _MBG_API mbg_get_synth( MBG_DEV_HANDLE dh, SYNTH *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, PCPS_GET_SYNTH, IOCTL_GET_SYNTH, p, _pcps_ddev_has_synth( dh ) ); _mbg_swab_synth( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_synth @@ -3978,32 +6788,35 @@ _MBG_API_ATTR int _MBG_API mbg_get_synth( MBG_DEV_HANDLE dh, SYNTH *p ) /*HDR*/ /** - Write a ::SYNTH structure containing the configuration of an optional - on-board programmable frequency synthesizer. - The macro _pcps_has_synth() or the API call mbg_dev_has_synth() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::SYNTH structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_synth() - @see mbg_get_synth() - @see mbg_get_synth_state() - @see \ref group_synth -*/ + * @brief Write frequency synthesizer configuration settings to a device + * + * Write a ::SYNTH structure containing the configuration of an optional + * on-board programmable frequency synthesizer. + * + * The API call ::mbg_chk_dev_has_synth checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::SYNTH structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_synth + * @see ::mbg_get_synth + * @see ::mbg_get_synth_state + * @see @ref group_synth + */ _MBG_API_ATTR int _MBG_API mbg_set_synth( MBG_DEV_HANDLE dh, const SYNTH *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) SYNTH tmp = *p; _mbg_swab_synth( &tmp ); p = &tmp; #endif - _mbgdevio_write_var_chk( dh, PCPS_SET_SYNTH, IOCTL_SET_SYNTH, + _mbgdevio_write_var_chk( dh, PCPS_SET_SYNTH, IOCTL_SET_SYNTH, p, _pcps_ddev_has_synth( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_synth @@ -4011,28 +6824,28 @@ _MBG_API_ATTR int _MBG_API mbg_set_synth( MBG_DEV_HANDLE dh, const SYNTH *p ) /*HDR*/ /** - Read a ::SYNTH_STATE structure reporting the current state - of an optional on-board programmable frequency synthesizer. - The macro _pcps_has_synth() or the API call mbg_dev_has_synth() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::SYNTH_STATE structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_synth() - @see mbg_get_synth() - @see mbg_set_synth() - @see \ref group_synth -*/ + * @brief Read the current status of the on-board frequency synthesizer + * + * The API call ::mbg_chk_dev_has_synth checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::SYNTH_STATE structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_synth + * @see ::mbg_get_synth + * @see ::mbg_set_synth + * @see @ref group_synth + */ _MBG_API_ATTR int _MBG_API mbg_get_synth_state( MBG_DEV_HANDLE dh, SYNTH_STATE *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, PCPS_GET_SYNTH_STATE, IOCTL_GET_SYNTH_STATE, p, _pcps_ddev_has_synth( dh ) ); _mbg_swab_synth_state( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_synth_state @@ -4040,69 +6853,55 @@ _MBG_API_ATTR int _MBG_API mbg_get_synth_state( MBG_DEV_HANDLE dh, SYNTH_STATE * /*HDR*/ /** - Check if a specific device supports the mbg_get_fast_hr_timestamp_...() calls. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_fast_hr_timestamp_cycles() - @see mbg_get_fast_hr_timestamp_comp() - @see mbg_get_fast_hr_timestamp() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_fast_hr_timestamp( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_fast_hr_timestamp, IOCTL_DEV_HAS_FAST_HR_TIMESTAMP, p ); - -} // mbg_dev_has_fast_hr_timestamp - - - -/*HDR*/ -/** - Read a high resolution ::PCPS_TIME_STAMP_CYCLES structure via memory mapped access. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME_STAMP_CYCLES structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_fast_hr_timestamp() - @see mbg_get_fast_hr_timestamp_comp() - @see mbg_get_fast_hr_timestamp() -*/ + * @brief Read a high resolution ::PCPS_TIME_STAMP_CYCLES structure via memory mapped access. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME_STAMP_CYCLES structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_fast_timestamp_fncs + * @see ::mbg_chk_dev_has_fast_hr_timestamp + * @see ::mbg_get_fast_hr_timestamp_comp + * @see ::mbg_get_fast_hr_timestamp + * @see @ref mbgdevio_fast_timestamp_fncs + */ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP_CYCLES *p ) { #if defined( _MBGIOCTL_H ) - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, -1, IOCTL_GET_FAST_HR_TIMESTAMP_CYCLES, p ); // native endianess, no need to swap bytes - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); #else // This is currently not supported by the target environment. - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS ); + return MBG_ERR_NOT_SUPP_ON_OS; #endif + } // mbg_get_fast_hr_timestamp_cycles /*HDR*/ /** - Read a high resolution ::PCPS_TIME_STAMP via memory mapped access, - and compensate the latency of the time stamp before it is returned. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME_STAMP structure to be filled up - @param *hns_latency Optionally receive the latency in hectonanoseconds - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_fast_hr_timestamp() - @see mbg_get_fast_hr_timestamp_cycles() - @see mbg_get_fast_hr_timestamp() -*/ + * @brief Read a high resolution timestamp and compensate the latency of the call + * + * The retrieved ::PCPS_TIME_STAMP is read from memory mapped registers, + * and timestamp is compensated for the call's latency before it is returned. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME_STAMP structure to be filled up + * @param[out] hns_latency Optionally receives the latency in hectonanoseconds //### TODO Check if hns + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_fast_timestamp_fncs + * @see ::mbg_chk_dev_has_fast_hr_timestamp + * @see ::mbg_get_fast_hr_timestamp_cycles + * @see ::mbg_get_fast_hr_timestamp + * @see @ref mbgdevio_fast_timestamp_fncs + */ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_comp( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP *p, int32_t *hns_latency ) @@ -4118,7 +6917,7 @@ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_comp( MBG_DEV_HANDLE dh, rc = mbg_get_fast_hr_timestamp_cycles( dh, &tc ); - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) { mbg_init_pc_cycles_frequency( dh, &pc_cycles_frequency ); rc = mbg_comp_hr_latency( &tc.tstamp, &tc.cycles, &cyc_now, &pc_cycles_frequency, hns_latency ); @@ -4133,641 +6932,73 @@ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_comp( MBG_DEV_HANDLE dh, /*HDR*/ /** - Read a high resolution ::PCPS_TIME_STAMP structure via memory mapped access. - - This function does not return or evaluate a cycles count, so the latency - of the call can not be determined. However, depending on the timer hardware - used as cycles counter it may take quite some time to read the cycles count - on some hardware architectures, so this call can be used to yield lower - latencies, under the restriction to be unable to determine the exact latency. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME_STAMP structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_fast_hr_timestamp() - @see mbg_get_fast_hr_timestamp_comp() - @see mbg_get_fast_hr_timestamp_cycles() -*/ + * @brief Read a high resolution ::PCPS_TIME_STAMP structure via memory mapped access + * + * This function does not return or evaluate a cycles count, so the latency + * of the call can not be determined. However, depending on the timer hardware + * used as cycles counter it may take quite some time to read the cycles count + * on some hardware architectures, so this call can be used to yield lower + * latencies, under the restriction to be unable to determine the exact latency. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME_STAMP structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_fast_timestamp_fncs + * @see ::mbg_chk_dev_has_fast_hr_timestamp + * @see ::mbg_get_fast_hr_timestamp_comp + * @see ::mbg_get_fast_hr_timestamp_cycles + * @see @ref mbgdevio_fast_timestamp_fncs + */ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP *p ) { #if defined( _MBGIOCTL_H ) - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, -1, IOCTL_GET_FAST_HR_TIMESTAMP, p ); // native endianess, no need to swap bytes - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); #else // This is currently not supported by the target environment. - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS ); + return MBG_ERR_NOT_SUPP_ON_OS; #endif -} // mbg_get_fast_hr_timestamp - - - -/*HDR*/ -/** - Check if a specific device is a GPS receiver. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_is_gps( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_is_gps, IOCTL_DEV_IS_GPS, p ); - -} // mbg_dev_is_gps - - - -/*HDR*/ -/** - Check if a specific device is a DCF77 receiver. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_is_dcf( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_is_dcf, IOCTL_DEV_IS_DCF, p ); - -} // mbg_dev_is_dcf - - - -/*HDR*/ -/** - Check if a specific device is a MSF receiver. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_is_msf( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_is_msf, IOCTL_DEV_IS_MSF, p ); - -} // mbg_dev_is_msf - - - -/*HDR*/ -/** - Check if a specific device is a WWVB receiver. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_is_wwvb( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_is_wwvb, IOCTL_DEV_IS_WWVB, p ); - -} // mbg_dev_is_msf - - - -/*HDR*/ -/** - Check if a specific device is a long wave signal receiver, e.g. DCF77, MSF or WWVB. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_is_lwr( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_is_lwr, IOCTL_DEV_IS_LWR, p ); - -} // mbg_dev_is_lwr - - - -/*HDR*/ -/** - Check if a specific device is an IRIG receiver which supports - configuration of the IRIG input. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_irig_rx_info() - @see mbg_set_irig_rx_settings() - @see mbg_dev_has_irig_tx() - @see mbg_dev_has_irig() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_is_irig_rx( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_is_irig_rx, IOCTL_DEV_IS_IRIG_RX, p ); -} // mbg_dev_is_irig_rx - - - -/*HDR*/ -/** - Check if a specific device supports the HR_TIME functions. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_hr_time() - @see mbg_get_hr_time_cycles() - @see mbg_get_hr_time_comp() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_hr_time( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_hr_time, IOCTL_DEV_HAS_HR_TIME, p ); - -} // mbg_dev_has_hr_time - - - -/*HDR*/ -/** - Check if a specific device supports configuration of antenna cable length. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_gps_ant_cable_len() - @see mbg_set_gps_ant_cable_len() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_cab_len( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_cab_len, IOCTL_DEV_HAS_CAB_LEN, p ); - -} // mbg_dev_has_cab_len - - - -/*HDR*/ -/** - Check if a specific device supports timezone / daylight saving configuration - using the ::TZDL structure. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_gps_tzdl() - @see mbg_set_gps_tzdl() - @see mbg_dev_has_tz() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_tzdl( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_tzdl, IOCTL_DEV_HAS_TZDL, p ); - -} // mbg_dev_has_tzdl - - - -/*HDR*/ -/** - Check if a specific device supports timezone / daylight saving configuration - using the ::PCPS_TZDL structure. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_pcps_tzdl() - @see mbg_set_pcps_tzdl() - @see mbg_dev_has_tz() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_pcps_tzdl( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_pcps_tzdl, IOCTL_DEV_HAS_PCPS_TZDL, p ); - -} // mbg_dev_has_pcps_tzdl - - - -/*HDR*/ -/** - Check if a specific device supports timezone configuration - using the ::PCPS_TZCODE type. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_tzcode() - @see mbg_set_tzcode() - @see mbg_dev_has_tz() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_tzcode( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_tzcode, IOCTL_DEV_HAS_TZCODE, p ); - -} // mbg_dev_has_tzcode - - - -/*HDR*/ -/** - Check if a specific device supports any kind of timezone configuration. - This can be used e.g. to check if a specifig dialog or menu has to - be displayed. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_tzdl() - @see mbg_dev_has_pcps_tzdl() - @see mbg_dev_has_tzcode() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_tz( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_tz, IOCTL_DEV_HAS_TZ, p ); - -} // mbg_dev_has_tz - - - -/*HDR*/ -/* (Intentionally excluded from Doxygen) - Check if a specific device supports setting an event time, i.e. - configure a %UTC time when the clock shall generate an event. - - <b>Note:</b> This is only supported by some special firmware. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_event_time() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_event_time( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_event_time, IOCTL_DEV_HAS_EVENT_TIME, p ); - -} // mbg_dev_has_event_time - - - -/*HDR*/ -/** - Check if a specific device supports the ::RECEIVER_INFO structure and related calls. - Older GPS devices may not support that structure. - - The mbg_get_gps_receiver_info() call uses this call to decide whether a - ::RECEIVER_INFO can be read directly from a device, or whether a default - structure has to be set up using default values depending on the device type. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_gps_receiver_info() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_receiver_info( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_receiver_info, IOCTL_DEV_HAS_RECEIVER_INFO, p ); - -} // mbg_dev_has_receiver_info - - - -/*HDR*/ -/** - Check if a specific device supports the mbg_clr_ucap_buff() call - used to clear a card's on-board time capture FIFO buffer. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_clr_ucap_buff() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_can_clr_ucap_buff( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_can_clr_ucap_buff, IOCTL_DEV_CAN_CLR_UCAP_BUFF, p ); - -} // mbg_dev_can_clr_ucap_buff - - - -/*HDR*/ -/** - Check if a specific device supports the mbg_get_ucap_entries() and - mbg_get_ucap_event() calls. - - If the card does not but it is a GPS card then the card provides - a time capture FIFO buffer and the obsolete mbg_get_gps_ucap() - call can be used to retrieve entries from the FIFO buffer. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_ucap_entries() - @see mbg_get_ucap_event() - @see mbg_clr_ucap_buff() - @see mbg_get_gps_ucap() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_ucap( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_ucap, IOCTL_DEV_HAS_UCAP, p ); - -} // mbg_dev_has_ucap - - - -/*HDR*/ -/** - Check if a specific device provides an IRIG output which can - be configured. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_irig_tx_info() - @see mbg_set_irig_tx_settings() - @see mbg_dev_is_irig_rx() - @see mbg_dev_has_irig() - @see \ref group_icode - -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_irig_tx( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_irig_tx, IOCTL_DEV_HAS_IRIG_TX, p ); - -} // mbg_dev_has_irig_tx - - - -/*HDR*/ -/* (Intentionally excluded from Doxygen) - Check if a specific device provides a serial output supporting - higher baud rates than older cards, i.e. ::DEFAULT_BAUD_RATES_DCF_HS - rather than ::DEFAULT_BAUD_RATES_DCF. - - The mbg_get_serial_settings() takes care of this, so applications - which use that call as suggested won't need to use this call directly. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_serial_settings() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_serial_hs( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_serial_hs, IOCTL_DEV_HAS_SERIAL_HS, p ); - -} // mbg_dev_has_serial_hs - - - -/*HDR*/ -/** - Check if a specific device provides an input signal level value which - may be displayed, e.g. DCF77 or IRIG cards. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_signal( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_signal, IOCTL_DEV_HAS_SIGNAL, p ); - -} // mbg_dev_has_signal - - - -/*HDR*/ -/** - Check if a specific device provides an modulation signal which may be - displayed, e.g. the second marks of a DCF77 AM receiver. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_mod( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_mod, IOCTL_DEV_HAS_MOD, p ); - -} // mbg_dev_has_mod - - - -/*HDR*/ -/** - Check if a specific device provides either an IRIG input or output. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_is_irig_rx() - @see mbg_dev_has_irig_tx() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_irig( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_irig, IOCTL_DEV_HAS_IRIG, p ); - -} // mbg_dev_has_irig - - - -/*HDR*/ -/** - Check if a specific device provides a configurable ref time offset - required to convert the received time to %UTC. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_ref_offs() - @see mbg_set_ref_offs() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_ref_offs( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_ref_offs, IOCTL_DEV_HAS_REF_OFFS, p ); - -} // mbg_dev_has_ref_offs - - - -/*HDR*/ -/** - Check if a specific device supports the ::MBG_OPT_INFO/::MBG_OPT_SETTINGS - structures containing optional settings, controlled by flags. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_opt_info() - @see mbg_set_opt_settings() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_opt_flags( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_opt_flags, IOCTL_DEV_HAS_OPT_FLAGS, p ); - -} // mbg_dev_has_opt_flags - - - -/*HDR*/ -/** - Check if a specific device supports large configuration data structures - as have been introducesde with the GPS receivers. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_gps_data( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_gps_data, IOCTL_DEV_HAS_GPS_DATA, p ); - -} // mbg_dev_has_gps_data - - - -/*HDR*/ -/** - Check if a specific device provides a programmable frequency synthesizer. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_synth() - @see mbg_set_synth() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_synth( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_synth, IOCTL_DEV_HAS_SYNTH, p ); - -} // mbg_dev_has_synth - - - -/*HDR*/ -/* (Intentionally excluded from Doxygen) - Check if a specific device supports the mbg_generic_io() call. - - <b>Warning</b>: That call is for debugging purposes and internal use only! - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_generic_io() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_generic_io( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_generic_io, IOCTL_DEV_HAS_GENERIC_IO, p ); - -} // mbg_dev_has_generic_io - - - -/*HDR*/ -/** - Check if a specific device supports the mbg_get_asic_version() call. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_asic_version() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_asic_version( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_asic_version, IOCTL_DEV_HAS_PCI_ASIC_VERSION, p ); - -} // mbg_dev_has_asic_version - - - -/*HDR*/ -/** - Check if a specific device supports the mbg_get_asic_features() call. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_asic_features() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_asic_features( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_asic_features, IOCTL_DEV_HAS_PCI_ASIC_FEATURES, p ); - -} // mbg_dev_has_asic_features +} // mbg_get_fast_hr_timestamp /*HDR*/ /** - Read a ::POUT_INFO_IDX array of current settings and configuration - options of a card's programmable pulse outputs. - The function mbg_setup_receiver_info() must have been called before, - and the returned ::RECEIVER_INFO structure passed to this function. - The function should only be called if the ::RECEIVER_INFO::n_prg_out - field (i.e. the number of programmable outputs on the board) is not 0. - - The array passed to this function to receive the returned data - must be able to hold at least ::RECEIVER_INFO::n_prg_out elements. - - @param dh Valid handle to a Meinberg device. - @param pii Pointer to a an array of ::POUT_INFO_IDX structures to be filled up - @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info() - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_gps_pout_settings_idx() - @see mbg_set_gps_pout_settings() - @see mbg_setup_receiver_info() -*/ + * @brief Read current configuraton and features provided by the programmable pulse outputs. + * + * Read a ::POUT_INFO_IDX array of current settings and configuration + * options of the device's programmable pulse outputs. + * + * A valid ::RECEIVER_INFO associated with the device + * has to be passed to this function. + * + * The function should only be called if the ::RECEIVER_INFO::n_prg_out + * field (i.e. the number of programmable outputs on the board) is not 0. + * + * The array passed to this function to receive the returned data + * must be able to hold at least ::RECEIVER_INFO::n_prg_out elements. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] pii Pointer to a an array of ::POUT_INFO_IDX structures to be filled up + * @param[in] p_ri Pointer to the ::RECEIVER_INFO associated with the device //### TODO Make this obsolete + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_gps_pout_settings_idx + * @see ::mbg_set_gps_pout_settings + * @see ::mbg_setup_receiver_info + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_all_pout_info( MBG_DEV_HANDLE dh, POUT_INFO_IDX pii[], const RECEIVER_INFO *p_ri ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if _MBG_SUPP_VAR_ACC_SIZE _mbgdevio_read_gps_chk( dh, PC_GPS_ALL_POUT_INFO, @@ -4779,25 +7010,25 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_all_pout_info( MBG_DEV_HANDLE dh, // has been read from a device which really supports it, or // a dummy structure has been setup. if ( p_ri && ( p_ri->model_code != GPS_MODEL_UNKNOWN ) ) - rc = _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_POUT_INFO, pii, + rc = _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_POUT_INFO, pii, p_ri->n_prg_out * sizeof( pii[0] ) ); else - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV ); + return MBG_ERR_NOT_SUPP_BY_DEV; #endif #if defined( MBG_ARCH_BIG_ENDIAN ) - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) { int i; for ( i = 0; i < p_ri->n_prg_out; i++ ) { POUT_INFO_IDX *p = &pii[i]; - _mbg_swab_pout_info_idx( p ); + _mbg_swab_pout_info_idx_on_get( p ); } } #endif - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_gps_all_pout_info @@ -4805,36 +7036,37 @@ _MBG_API_ATTR int _MBG_API mbg_get_gps_all_pout_info( MBG_DEV_HANDLE dh, /*HDR*/ /** - Write the configuration for a single programmable pulse output using - the ::POUT_SETTINGS_IDX structure which contains both the ::POUT_SETTINGS - and the output index value. - Except for the parameter types, this call is equivalent to - mbg_set_gps_pout_settings(). - The function should only be called if the ::RECEIVER_INFO::n_prg_out field - (i.e. the number of programmable outputs on the board) is not 0, and the - output index value must be in the range 0..::RECEIVER_INFO::n_prg_out. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::POUT_SETTINGS_IDX structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_gps_all_pout_info() - @see mbg_set_gps_pout_settings() -*/ + * @brief Write the configuration for a single programmable pulse output + * + * The ::POUT_SETTINGS_IDX structure contains both the ::POUT_SETTINGS + * and the output index value. Except for the parameter types this call + * is equivalent to ::mbg_set_gps_pout_settings. + * + * The function should only be called if the ::RECEIVER_INFO::n_prg_out field + * (i.e. the number of programmable outputs on the board) is not 0, and the + * output index value must be in the range 0..::RECEIVER_INFO::n_prg_out. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::POUT_SETTINGS_IDX structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_gps_all_pout_info + * @see ::mbg_set_gps_pout_settings + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings_idx( MBG_DEV_HANDLE dh, const POUT_SETTINGS_IDX *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) POUT_SETTINGS_IDX tmp = *p; - _mbg_swab_pout_settings_idx( &tmp ); + _mbg_swab_pout_settings_idx_on_set( &tmp ); p = &tmp; #endif _mbgdevio_write_gps_var_chk( dh, PC_GPS_POUT_SETTINGS_IDX, IOCTL_SET_GPS_POUT_SETTINGS_IDX, p, _pcps_ddev_has_receiver_info( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_gps_pout_settings_idx @@ -4842,23 +7074,26 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings_idx( MBG_DEV_HANDLE dh, /*HDR*/ /** - Write the configuration for a single programmable pulse output using - the ::POUT_SETTINGS structure plus the index of the output to be configured. - Except for the parameter types, this call is equivalent to - mbg_set_gps_pout_settings_idx(). - The function should only be called if the ::RECEIVER_INFO::n_prg_out field - (i.e. the number of programmable outputs on the board) is not 0, and the - output index value must be in the range 0..::RECEIVER_INFO::n_prg_out. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::POUT_SETTINGS structure to be written - @param idx Index of the programmable pulse output to be configured (starting from 0 ). - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_gps_all_pout_info() - @see mbg_set_gps_pout_settings_idx() -*/ + * @brief Write the configuration for a single programmable pulse output + * + * The ::POUT_SETTINGS structure does not contain the index of the + * programmable output to be configured, so the index must explicitly + * be passed to this function. Except for the parameter types this call + * is equivalent to ::mbg_set_gps_pout_settings_idx. + * + * The function should only be called if the ::RECEIVER_INFO::n_prg_out field + * (i.e. the number of programmable outputs on the board) is not 0, and the + * output index value must be in the range 0..::RECEIVER_INFO::n_prg_out. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::POUT_SETTINGS structure to be written. + * @param[in] idx Index of the programmable pulse output to be configured (starting from 0 ). + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_gps_all_pout_info + * @see ::mbg_set_gps_pout_settings_idx + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings( MBG_DEV_HANDLE dh, const POUT_SETTINGS *p, int idx ) { @@ -4875,22 +7110,26 @@ _MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings( MBG_DEV_HANDLE dh, /*HDR*/ /** - Read a card's IRQ status information which includes flags indicating - whether IRQs are currently enabled, and whether IRQ support by a card - is possibly unsafe due to the firmware and interface chip version. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_IRQ_STAT_INFO variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - */ + * @brief Read a device's IRQ status information. + * + * IRQ status information includes flags indicating whether IRQs are + * actually enabled, and whether IRQ support by a card is possibly + * unsafe due to the firmware and interface chip version. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_IRQ_STAT_INFO variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see @ref PCPS_IRQ_STAT_INFO_DEFS + */ _MBG_API_ATTR int _MBG_API mbg_get_irq_stat_info( MBG_DEV_HANDLE dh, PCPS_IRQ_STAT_INFO *p ) { #if defined( _MBGIOCTL_H ) - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, -1, IOCTL_GET_IRQ_STAT_INFO, p ); // native endianess, no need to swap bytes - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); #else *p = dh->irq_stat_info; return MBG_SUCCESS; @@ -4902,50 +7141,29 @@ _MBG_API_ATTR int _MBG_API mbg_get_irq_stat_info( MBG_DEV_HANDLE dh, PCPS_IRQ_ST /*HDR*/ /** - Check if a specific device provides simple LAN interface API calls. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_lan_if_info() - @see mbg_get_ip4_state() - @see mbg_get_ip4_settings() - @see mbg_set_ip4_settings() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_lan_intf( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_lan_intf, IOCTL_DEV_HAS_LAN_INTF, p ); - -} // mbg_dev_has_lan_intf - - - -/*HDR*/ -/** - Read LAN interface information from a card which supports this. - The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::LAN_IF_INFO variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_lan_intf() - @see mbg_get_ip4_state() - @see mbg_get_ip4_settings() - @see mbg_set_ip4_settings() - */ + * @brief Read LAN interface information from a device + * + * The API call ::mbg_chk_dev_has_lan_intf checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::LAN_IF_INFO variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_get_ip4_state + * @see ::mbg_get_ip4_settings + * @see ::mbg_set_ip4_settings + */ _MBG_API_ATTR int _MBG_API mbg_get_lan_if_info( MBG_DEV_HANDLE dh, LAN_IF_INFO *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_gps_var_chk( dh, PC_GPS_LAN_IF_INFO, IOCTL_GET_LAN_IF_INFO, p, _pcps_ddev_has_lan_intf( dh ) ); _mbg_swab_lan_if_info( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_lan_if_info @@ -4953,28 +7171,29 @@ _MBG_API_ATTR int _MBG_API mbg_get_lan_if_info( MBG_DEV_HANDLE dh, LAN_IF_INFO * /*HDR*/ /** - Read LAN IPv4 state from a card which supports this. - The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::IP4_SETTINGS variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_lan_intf() - @see mbg_get_lan_if_info() - @see mbg_get_ip4_settings() - @see mbg_set_ip4_settings() - */ + * @brief Read LAN IPv4 state from a device + * + * The API call ::mbg_chk_dev_has_lan_intf checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::IP4_SETTINGS variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_get_lan_if_info + * @see ::mbg_get_ip4_settings + * @see ::mbg_set_ip4_settings + */ _MBG_API_ATTR int _MBG_API mbg_get_ip4_state( MBG_DEV_HANDLE dh, IP4_SETTINGS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_gps_var_chk( dh, PC_GPS_IP4_STATE, IOCTL_GET_IP4_STATE, p, _pcps_ddev_has_lan_intf( dh ) ); _mbg_swab_ip4_settings( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_ip4_state @@ -4982,28 +7201,29 @@ _MBG_API_ATTR int _MBG_API mbg_get_ip4_state( MBG_DEV_HANDLE dh, IP4_SETTINGS *p /*HDR*/ /** - Read LAN IPv4 settings from a card which supports this. - The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::IP4_SETTINGS variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_lan_intf() - @see mbg_get_lan_if_info() - @see mbg_get_ip4_state() - @see mbg_set_ip4_settings() - */ + * @brief Read LAN IPv4 settings from a device. + * + * The API call ::mbg_chk_dev_has_lan_intf checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::IP4_SETTINGS variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_get_lan_if_info + * @see ::mbg_get_ip4_state + * @see ::mbg_set_ip4_settings + */ _MBG_API_ATTR int _MBG_API mbg_get_ip4_settings( MBG_DEV_HANDLE dh, IP4_SETTINGS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_gps_var_chk( dh, PC_GPS_IP4_SETTINGS, IOCTL_GET_IP4_SETTINGS, p, _pcps_ddev_has_lan_intf( dh ) ); _mbg_swab_ip4_settings( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_ip4_settings @@ -5011,23 +7231,24 @@ _MBG_API_ATTR int _MBG_API mbg_get_ip4_settings( MBG_DEV_HANDLE dh, IP4_SETTINGS /*HDR*/ /** - Write LAN IPv4 settings to a card which supports this. - The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p ::IP4_SETTINGS structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_lan_intf() - @see mbg_get_lan_if_info() - @see mbg_get_ip4_settings() -*/ + * @brief Write LAN IPv4 settings to a device + * + * The API call ::mbg_chk_dev_has_lan_intf checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p ::IP4_SETTINGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_get_lan_if_info + * @see ::mbg_get_ip4_settings + */ _MBG_API_ATTR int _MBG_API mbg_set_ip4_settings( MBG_DEV_HANDLE dh, const IP4_SETTINGS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) IP4_SETTINGS tmp = *p; _mbg_swab_ip4_settings( &tmp ); @@ -5036,7 +7257,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_ip4_settings( MBG_DEV_HANDLE dh, _mbgdevio_write_gps_var_chk( dh, PC_GPS_IP4_SETTINGS, IOCTL_SET_IP4_SETTINGS, p, _pcps_ddev_has_lan_intf( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_ip4_settings @@ -5044,70 +7265,30 @@ _MBG_API_ATTR int _MBG_API mbg_set_ip4_settings( MBG_DEV_HANDLE dh, /*HDR*/ /** - Check if a specific device provides PTP configuration/status calls. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_ptp_state() - @see mbg_get_ptp_cfg_info() - @see mbg_set_ptp_cfg_settings() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_ptp( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_cond( dh, _pcps_ddev_has_ptp, IOCTL_DEV_HAS_PTP, p ); - -} // mbg_dev_has_ptp - - - -/*HDR*/ -/** - Check if a specific device provides PTP Unicast feature/configuration. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_ptp_state() - @see mbg_get_ptp_uc_master_cfg_limits() - @see mbg_get_all_ptp_uc_master_info() - @see mbg_set_ptp_unicast_cfg_settings() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_ptp_unicast( MBG_DEV_HANDLE dh, int *p ) -{ - _mbgdevio_query_ri_cond( dh, _pcps_has_ri_ptp_unicast, IOCTL_DEV_HAS_PTP_UNICAST, p ); - -} // mbg_dev_has_ptp_unicast - - - -/*HDR*/ -/** - Read PTP/IEEE1588 status from a card which supports this. - The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PTP_CFG_INFO variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ptp() - @see mbg_get_ptp_cfg_info() - @see mbg_set_ptp_cfg_settings() - */ + * @brief Read PTP/IEEE1588 status from a device + * + * The API call ::mbg_chk_dev_has_ptp checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PTP_STATE variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ptp + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_cfg_info + * @see ::mbg_set_ptp_cfg_settings + * @see ::mbg_chk_dev_has_ptp_unicast + */ _MBG_API_ATTR int _MBG_API mbg_get_ptp_state( MBG_DEV_HANDLE dh, PTP_STATE *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_gps_var_chk( dh, PC_GPS_PTP_STATE, IOCTL_GET_PTP_STATE, p, _pcps_ddev_has_ptp( dh ) ); _mbg_swab_ptp_state( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_ptp_state @@ -5115,27 +7296,30 @@ _MBG_API_ATTR int _MBG_API mbg_get_ptp_state( MBG_DEV_HANDLE dh, PTP_STATE *p ) /*HDR*/ /** - Read PTP/IEEE1588 config info and current settings from a card which supports this. - The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PTP_CFG_INFO variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ptp() - @see mbg_get_ptp_state() - @see mbg_set_ptp_cfg_settings() - */ + * @brief Read PTP/IEEE1588 config info and current settings from a device + * + * The API call ::mbg_chk_dev_has_ptp checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PTP_CFG_INFO variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ptp + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_state + * @see ::mbg_set_ptp_cfg_settings + * @see ::mbg_chk_dev_has_ptp_unicast + */ _MBG_API_ATTR int _MBG_API mbg_get_ptp_cfg_info( MBG_DEV_HANDLE dh, PTP_CFG_INFO *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_gps_var_chk( dh, PC_GPS_PTP_CFG, IOCTL_GET_PTP_CFG_INFO, p, _pcps_ddev_has_ptp( dh ) ); _mbg_swab_ptp_cfg_info( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_ptp_cfg_info @@ -5143,23 +7327,26 @@ _MBG_API_ATTR int _MBG_API mbg_get_ptp_cfg_info( MBG_DEV_HANDLE dh, PTP_CFG_INFO /*HDR*/ /** - Write PTP/IEEE1588 configuration settings to a card which supports this. - The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p ::PTP_CFG_SETTINGS structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ptp() - @see mbg_get_ptp_state() - @see mbg_get_ptp_cfg_info() -*/ + * @brief Write PTP/IEEE1588 configuration settings to a device. + * + * The API call ::mbg_chk_dev_has_ptp checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p ::PTP_CFG_SETTINGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ptp + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_state + * @see ::mbg_get_ptp_cfg_info + * @see ::mbg_chk_dev_has_ptp_unicast + */ _MBG_API_ATTR int _MBG_API mbg_set_ptp_cfg_settings( MBG_DEV_HANDLE dh, const PTP_CFG_SETTINGS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) PTP_CFG_SETTINGS tmp = *p; _mbg_swab_ptp_cfg_settings( &tmp ); @@ -5168,7 +7355,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_ptp_cfg_settings( MBG_DEV_HANDLE dh, _mbgdevio_write_gps_var_chk( dh, PC_GPS_PTP_CFG, IOCTL_SET_PTP_CFG_SETTINGS, p, _pcps_ddev_has_ptp( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_ptp_cfg_settings @@ -5176,26 +7363,31 @@ _MBG_API_ATTR int _MBG_API mbg_set_ptp_cfg_settings( MBG_DEV_HANDLE dh, /*HDR*/ /** - Read PTP/IEEE1588 unicast config info and current settings from a card which supports this. - The macro _pcps_has_ri_ptp_unicast() or the API call mbg_dev_has_ptp_unicast() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PTP_UNICAST_CFG_INFO variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ptp_unicast() - @see mbg_set_ptp_unicast_cfg_settings() - */ + * @brief Read PTP/IEEE1588 unicast master configuration limits from a device. + * + * The API call ::mbg_chk_dev_has_ptp_unicast checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PTP_UC_MASTER_CFG_LIMITS variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ptp_unicast + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_all_ptp_uc_master_info + * @see ::mbg_set_ptp_uc_master_settings_idx + * @see ::mbg_get_ptp_state + */ _MBG_API_ATTR int _MBG_API mbg_get_ptp_uc_master_cfg_limits( MBG_DEV_HANDLE dh, PTP_UC_MASTER_CFG_LIMITS *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_gps_var_chk( dh, PC_GPS_PTP_UC_MASTER_CFG_LIMITS, IOCTL_PTP_UC_MASTER_CFG_LIMITS, p, - _pcps_has_ri_ptp_unicast( &dh->ri ) ); + _pcps_has_ri_ptp_unicast( _ri_addr( dh ) ) ); + _mbg_swab_ptp_uc_master_cfg_limits( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_ptp_uc_master_cfg_limits @@ -5203,31 +7395,28 @@ _MBG_API_ATTR int _MBG_API mbg_get_ptp_uc_master_cfg_limits( MBG_DEV_HANDLE dh, /*HDR*/ /** - Read a ::IOCTL_SET_PTP_UNICAST_CFG_SETTINGS array of current settings and configuration - options of a card's programmable pulse outputs. - The function mbg_setup_receiver_info() must have been called before, - and the returned ::RECEIVER_INFO structure passed to this function. - The function should only be called if the ::RECEIVER_INFO::n_prg_out - field (i.e. the number of programmable outputs on the board) is not 0. - - The array passed to this function to receive the returned data - must be able to hold at least ::RECEIVER_INFO::n_prg_out elements. - - @param dh Valid handle to a Meinberg device. - @param pii Pointer to a an array of ::PTP_UC_MASTER_INFO_IDX structures to be filled up - @param p_umsl Pointer to a ::PTP_UC_MASTER_CFG_LIMITS structure returned by mbg_get_ptp_uc_master_cfg_limits() - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see //##++++++++++++++++++++++ - @see - @see -*/ + * @brief Read PTP Unicast master settings and configuration options. + * + * The array passed to this function to receive the returned data + * must be able to hold at least ::PTP_UC_MASTER_CFG_LIMITS::n_supp_master elements. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] pii Pointer to a an array of ::PTP_UC_MASTER_INFO_IDX structures to be filled up. + * @param[in] p_umsl Pointer to a ::PTP_UC_MASTER_CFG_LIMITS structure returned by ::mbg_get_ptp_uc_master_cfg_limits + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ptp_unicast + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_uc_master_cfg_limits + * @see ::mbg_set_ptp_uc_master_settings_idx + * @see ::mbg_get_ptp_state + */ _MBG_API_ATTR int _MBG_API mbg_get_all_ptp_uc_master_info( MBG_DEV_HANDLE dh, - PTP_UC_MASTER_INFO_IDX pii[], - const PTP_UC_MASTER_CFG_LIMITS *p_umsl ) + PTP_UC_MASTER_INFO_IDX pii[], + const PTP_UC_MASTER_CFG_LIMITS *p_umsl ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if _MBG_SUPP_VAR_ACC_SIZE _mbgdevio_read_gps_chk( dh, PC_GPS_ALL_PTP_UC_MASTER_INFO, @@ -5239,11 +7428,11 @@ _MBG_API_ATTR int _MBG_API mbg_get_all_ptp_uc_master_info( MBG_DEV_HANDLE dh, rc = _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_PTP_UC_MASTER_INFO, pii, p_umsl->n_supp_master * sizeof( pii[0] ) ); else - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV ); + return MBG_ERR_NOT_SUPP_BY_DEV; #endif #if defined( MBG_ARCH_BIG_ENDIAN ) - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) { int i; for ( i = 0; i < p_umsl->n_supp_master; i++ ) @@ -5254,7 +7443,7 @@ _MBG_API_ATTR int _MBG_API mbg_get_all_ptp_uc_master_info( MBG_DEV_HANDLE dh, } #endif - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_get_all_ptp_uc_master_info @@ -5262,24 +7451,26 @@ _MBG_API_ATTR int _MBG_API mbg_get_all_ptp_uc_master_info( MBG_DEV_HANDLE dh, /*HDR*/ /** - Write PTP/IEEE1588 unicast configuration settings to a card which supports this. - The macro _pcps_has_ri_ptp_unicast() or the API call mbg_dev_has_ptp_unicast() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p ::PTP_UNICAST_CFG_SETTINGS structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ptp_unicast() - @see mbg_get_ptp_state() - @see mbg_get_ptp_cfg_info() - @see mbg_get_ptp_unicast_cfg_info() -*/ + * @brief Write PTP/IEEE1588 unicast configuration settings to a device + * + * The API call ::mbg_chk_dev_has_ptp_unicast checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p ::PTP_UC_MASTER_SETTINGS_IDX structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ptp_unicast + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_uc_master_cfg_limits + * @see ::mbg_get_all_ptp_uc_master_info + * @see ::mbg_get_ptp_state + */ _MBG_API_ATTR int _MBG_API mbg_set_ptp_uc_master_settings_idx( MBG_DEV_HANDLE dh, const PTP_UC_MASTER_SETTINGS_IDX *p ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; #if defined( MBG_ARCH_BIG_ENDIAN ) PTP_UC_MASTER_SETTINGS_IDX tmp = *p; _mbg_swab_ptp_uc_master_settings_idx( &tmp ); @@ -5288,7 +7479,7 @@ _MBG_API_ATTR int _MBG_API mbg_set_ptp_uc_master_settings_idx( MBG_DEV_HANDLE dh _mbgdevio_write_gps_var_chk( dh, PC_GPS_PTP_UC_MASTER_SETTINGS_IDX, IOCTL_SET_PTP_UC_MASTER_SETTINGS_IDX, p, _pcps_ddev_has_ptp_unicast( dh ) ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbg_set_ptp_uc_master_settings_idx @@ -5296,39 +7487,40 @@ _MBG_API_ATTR int _MBG_API mbg_set_ptp_uc_master_settings_idx( MBG_DEV_HANDLE dh /*HDR*/ /** - Read system time and card time from the kernel driver. The kernel - driver reads the current system time plus a HR time structure from - a card immediately after each other. The returned info structure also - contains some cycles counts to be able to determine the execution times - required to read those time stamps. - - The advantage of this call compared to mbg_get_time_info_tstamp() is - that this call also returns the card's status. On the other hand, reading - the HR time from the card may block e.g. if another application accesses - the board. - - This call makes a mbg_get_hr_time_cycles() call internally so the macro - _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() can be - used to check whether this call is supported with a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_TIME_INFO_HRT variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_hr_time() - @see mbg_get_time_info_tstamp() - */ + * @brief Read both system time and associated device time from the kernel driver + * + * The kernel driver reads the current system time plus a HR time structure + * from a card immediately after each other. The returned info structure also + * contains some cycles counts to be able to determine the execution times + * required to read those time stamps. + * + * The advantage of this call compared to ::mbg_get_time_info_tstamp is + * that this call also returns the card's status. On the other hand, reading + * the HR time from the card may block e.g. if another application accesses + * the board. + * + * This call makes a ::mbg_get_hr_time_cycles call internally so the API call + * ::mbg_chk_dev_has_hr_time can be used to check whether this call is supported + * by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_TIME_INFO_HRT structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_hr_time + * @see ::mbg_get_time_info_tstamp + */ _MBG_API_ATTR int _MBG_API mbg_get_time_info_hrt( MBG_DEV_HANDLE dh, MBG_TIME_INFO_HRT *p ) { #if defined( _MBGIOCTL_H ) - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, -1, IOCTL_GET_TIME_INFO_HRT, p, _pcps_ddev_has_hr_time( dh ) ); _mbg_swab_mbg_time_info_hrt( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); #else - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS ); + return MBG_ERR_NOT_SUPP_ON_OS; #endif } // mbg_get_time_info_hrt @@ -5337,29 +7529,31 @@ _MBG_API_ATTR int _MBG_API mbg_get_time_info_hrt( MBG_DEV_HANDLE dh, MBG_TIME_IN /*HDR*/ /** - This call is similar to mbg_get_time_info_hrt() except that a - mbg_get_fast_hr_timestamp_cycles() call is made internally, so the macro - _pcps_has_fast_hr_timestamp() or the API call mbg_dev_has_fast_hr_timestamp() - can be used to check whether this call is supported with a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_TIME_INFO_TSTAMP variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_fast_hr_timestamp() - @see mbg_get_time_info_hrt() - */ + * @brief Read both system time and associated device timestamp from the kernel driver + * + * This call is similar to ::mbg_get_time_info_hrt except that a + * ::mbg_get_fast_hr_timestamp_cycles call is made internally, so + * the API call ::mbg_chk_dev_has_fast_hr_timestamp can be used to check whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_TIME_INFO_TSTAMP structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_fast_hr_timestamp + * @see ::mbg_get_time_info_hrt + */ _MBG_API_ATTR int _MBG_API mbg_get_time_info_tstamp( MBG_DEV_HANDLE dh, MBG_TIME_INFO_TSTAMP *p ) { #if defined( _MBGIOCTL_H ) - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; _mbgdevio_read_var_chk( dh, -1, IOCTL_GET_TIME_INFO_TSTAMP, p, _pcps_ddev_has_fast_hr_timestamp( dh ) ); _mbg_swab_mbg_time_info_tstamp( p ); - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); #else - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS ); + return MBG_ERR_NOT_SUPP_ON_OS; #endif } // mbg_get_time_info_tstamp @@ -5368,236 +7562,881 @@ _MBG_API_ATTR int _MBG_API mbg_get_time_info_tstamp( MBG_DEV_HANDLE dh, MBG_TIME /*HDR*/ /** - Check if a specific device supports demodulation of the DCF77 PZF code. + * @brief Read PZF correlation info from a device + * + * The API call ::mbg_chk_dev_has_corr_info checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::CORR_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_pzf + * @see ::mbg_chk_dev_has_corr_info + */ +_MBG_API_ATTR int _MBG_API mbg_get_corr_info( MBG_DEV_HANDLE dh, CORR_INFO *p ) +{ + MBGDEVIO_RET_VAL rc; + _mbgdevio_read_var_chk( dh, PCPS_GET_CORR_INFO, + IOCTL_GET_CORR_INFO, p, + _pcps_ddev_has_corr_info( dh ) ); + _mbg_swab_corr_info( p ); + return _mbgdevio_cnv_ret_val( rc ); - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. +} // mbg_get_corr_info - @return ::MBG_SUCCESS or error code returned by device I/O control function. - @see mbg_dev_has_corr_info() - @see mbg_dev_has_tr_distance() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_pzf( MBG_DEV_HANDLE dh, int *p ) + +/*HDR*/ +/** + * @brief Read configurable "distance from transmitter" parameter from a device + * + * The distance from transmitter parameter is used to compensate + * the RF propagation delay, mostly with long wave receivers. + * + * The API call ::mbg_chk_dev_has_tr_distance checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::TR_DISTANCE variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_pzf + * @see ::mbg_chk_dev_has_tr_distance + * @see ::mbg_set_tr_distance + */ +_MBG_API_ATTR int _MBG_API mbg_get_tr_distance( MBG_DEV_HANDLE dh, TR_DISTANCE *p ) { - _mbgdevio_query_cond( dh, _pcps_ddev_has_pzf, IOCTL_DEV_HAS_PZF, p ); + MBGDEVIO_RET_VAL rc; + _mbgdevio_read_var_chk( dh, PCPS_GET_TR_DISTANCE, + IOCTL_GET_TR_DISTANCE, p, + _pcps_ddev_has_tr_distance( dh ) ); + _mbg_swab_tr_distance( p ); + return _mbgdevio_cnv_ret_val( rc ); -} // mbg_dev_has_pzf +} // mbg_get_tr_distance /*HDR*/ /** - Check if a specific device supports reading correlation info. + * @brief Write configurable "distance from transmitter" parameter to a device. + * + * The distance from transmitter parameter is used to compensate + * the RF propagation delay, mostly with long wave receivers. + * + * The API call ::mbg_chk_dev_has_tr_distance checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::TR_DISTANCE variable to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_pzf + * @see ::mbg_chk_dev_has_tr_distance + * @see ::mbg_get_tr_distance + */ +_MBG_API_ATTR int _MBG_API mbg_set_tr_distance( MBG_DEV_HANDLE dh, const TR_DISTANCE *p ) +{ + MBGDEVIO_RET_VAL rc; + #if defined( MBG_ARCH_BIG_ENDIAN ) + TR_DISTANCE tmp = *p; + _mbg_swab_tr_distance( &tmp ); + p = &tmp; + #endif + _mbgdevio_write_var_chk( dh, PCPS_SET_TR_DISTANCE, IOCTL_SET_TR_DISTANCE, + p, _pcps_ddev_has_tr_distance( dh ) ); + return _mbgdevio_cnv_ret_val( rc ); - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. +} // mbg_set_tr_distance - @return ::MBG_SUCCESS or error code returned by device I/O control function. - @see mbg_dev_has_pzf() - @see mbg_get_corr_info() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_corr_info( MBG_DEV_HANDLE dh, int *p ) + +/*HDR*/ +/** + * @brief Read a debug status word from a device + * + * This is mainly supported by IRIG timecode receiver cards, and the status + * word is intended to provide more detailed information why a card might not + * synchronize to the incoming timecode signal. + * + * See ::MBG_DEBUG_STATUS and related definitions for details. + * + * The API call ::mbg_chk_dev_has_debug_status checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_DEBUG_STATUS variable to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_debug_status + */ +_MBG_API_ATTR int _MBG_API mbg_get_debug_status( MBG_DEV_HANDLE dh, MBG_DEBUG_STATUS *p ) { - _mbgdevio_query_cond( dh, _pcps_ddev_has_corr_info, IOCTL_DEV_HAS_CORR_INFO, p ); + MBGDEVIO_RET_VAL rc; + _mbgdevio_read_var_chk( dh, PCPS_GET_DEBUG_STATUS, + IOCTL_GET_DEBUG_STATUS, p, + _pcps_ddev_has_debug_status( dh ) ); + _mbg_swab_debug_status( p ); + return _mbgdevio_cnv_ret_val( rc ); -} // mbg_dev_has_corr_info +} // mbg_get_debug_status /*HDR*/ /** - Check if a specific device supports configurable distance from transmitter - used to compensate RF propagation delay. + * @brief Clear the device's on-board event log + * + * The API call ::mbg_chk_dev_has_evt_log checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_evt_log + * @see ::mbg_get_num_evt_log_entries + * @see ::mbg_get_first_evt_log_entry + * @see ::mbg_get_next_evt_log_entry + */ +_MBG_API_ATTR int _MBG_API mbg_clr_evt_log( MBG_DEV_HANDLE dh ) +{ + MBGDEVIO_RET_VAL rc; + _mbgdevio_write_cmd_chk( dh, PCPS_CLR_EVT_LOG, IOCTL_CLR_EVT_LOG, + _pcps_ddev_has_evt_log( dh ) ); + return _mbgdevio_cnv_ret_val( rc ); - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. +} // mbg_clr_evt_log - @return ::MBG_SUCCESS or error code returned by device I/O control function. - @see mbg_dev_has_pzf() - @see mbg_get_tr_distance() - @see mbg_set_tr_distance() -*/ -_MBG_API_ATTR int _MBG_API mbg_dev_has_tr_distance( MBG_DEV_HANDLE dh, int *p ) + +/*HDR*/ +/** + * @brief Read details about a device's on-board event log buffer + * + * The returned ::MBG_NUM_EVT_LOG_ENTRIES structure tells how many + * event log entries can be saved on the board, and how many entries + * actually have been saved. + * + * The API call ::mbg_chk_dev_has_evt_log checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_NUM_EVT_LOG_ENTRIES variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_evt_log + * @see ::mbg_clr_evt_log + * @see ::mbg_get_first_evt_log_entry + * @see ::mbg_get_next_evt_log_entry + */ +_MBG_API_ATTR int _MBG_API mbg_get_num_evt_log_entries( MBG_DEV_HANDLE dh, MBG_NUM_EVT_LOG_ENTRIES *p ) { - _mbgdevio_query_cond( dh, _pcps_ddev_has_tr_distance, IOCTL_DEV_HAS_TR_DISTANCE, p ); + MBGDEVIO_RET_VAL rc; + _mbgdevio_read_var_chk( dh, PCPS_NUM_EVT_LOG_ENTRIES, + IOCTL_GET_NUM_EVT_LOG_ENTRIES, p, + _pcps_ddev_has_evt_log( dh ) ); + _mbg_swab_mbg_num_evt_log_entries( p ); + return _mbgdevio_cnv_ret_val( rc ); -} // mbg_dev_has_tr_distance +} // mbg_get_num_evt_log_entries /*HDR*/ /** - Read PZF correlation info from a card which supports this. - The macro _pcps_has_corr_info() or the API call mbg_dev_has_corr_info() - check whether this call is supported by a specific card. + * @brief Read the first (oldest) event log entry from a device + * + * @note Subsequent reads should be made using ::mbg_get_next_evt_log_entry. + * + * The API call ::mbg_chk_dev_has_evt_log checks whether + * this call is supported by a device. + * + * If no (more) event log entry is available on the device then + * the returned MBG_EVT_LOG_ENTRY::code is MBG_EVT_ID_NONE. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_EVT_LOG_ENTRY variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_evt_log + * @see ::mbg_clr_evt_log + * @see ::mbg_get_num_evt_log_entries + * @see ::mbg_get_next_evt_log_entry + */ +_MBG_API_ATTR int _MBG_API mbg_get_first_evt_log_entry( MBG_DEV_HANDLE dh, MBG_EVT_LOG_ENTRY *p ) +{ + MBGDEVIO_RET_VAL rc; + _mbgdevio_read_var_chk( dh, PCPS_FIRST_EVT_LOG_ENTRY, + IOCTL_GET_FIRST_EVT_LOG_ENTRY, p, + _pcps_ddev_has_evt_log( dh ) ); + _mbg_swab_mbg_evt_log_entry( p ); + return _mbgdevio_cnv_ret_val( rc ); - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::CORR_INFO variable to be filled up +} // mbg_get_first_evt_log_entry - @return ::MBG_SUCCESS or error code returned by device I/O control function. - @see mbg_dev_has_pzf() - @see mbg_dev_has_corr_info() - */ -_MBG_API_ATTR int _MBG_API mbg_get_corr_info( MBG_DEV_HANDLE dh, CORR_INFO *p ) + +/*HDR*/ +/** + * @brief Read the next event log entry from a device + * + * @note The first read should be made using ::mbg_get_first_evt_log_entry + * to set the on-board read index to the oldest entry. + * + * The API call ::mbg_chk_dev_has_evt_log checks whether + * this call is supported by a device. + * + * If no (more) event log entry is available on the device then + * the returned MBG_EVT_LOG_ENTRY::code is MBG_EVT_ID_NONE. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_EVT_LOG_ENTRY variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_evt_log + * @see ::mbg_clr_evt_log + * @see ::mbg_get_num_evt_log_entries + * @see ::mbg_get_first_evt_log_entry + */ +_MBG_API_ATTR int _MBG_API mbg_get_next_evt_log_entry( MBG_DEV_HANDLE dh, MBG_EVT_LOG_ENTRY *p ) { - _mbgdevio_vars(); - _mbgdevio_read_var_chk( dh, PCPS_GET_CORR_INFO, - IOCTL_GET_CORR_INFO, p, - _pcps_ddev_has_corr_info( dh ) ); - _mbg_swab_corr_info( p ); - return _mbgdevio_ret_val; + MBGDEVIO_RET_VAL rc; + _mbgdevio_read_var_chk( dh, PCPS_NEXT_EVT_LOG_ENTRY, + IOCTL_GET_NEXT_EVT_LOG_ENTRY, p, + _pcps_ddev_has_evt_log( dh ) ); + _mbg_swab_mbg_evt_log_entry( p ); + return _mbgdevio_cnv_ret_val( rc ); -} // mbg_get_corr_info +} // mbg_get_next_evt_log_entry /*HDR*/ /** - Read configurable "distance from transmitter" parameter from a card - which supports this. The parameter is used to compensate the RF signal - propagation delay. - The macro _pcps_has_tr_distance() or the API call mbg_dev_has_tr_distance() - check whether this call is supported by a specific card. + * @brief Read the current GNSS mode info including current settings + * + * The ::MBG_GNSS_MODE_INFO structure tells which GNSS systems are supported + * by a device, and also includes the settings currently in effect. + * + * The API call ::mbg_chk_dev_is_gnss can be used to check whether + * this call is supported by a device. + * + * See also the notes for ::mbg_chk_dev_is_gnss. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p_mi Pointer to a ::MBG_GNSS_MODE_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_gps_gnss_mode_settings + * @see ::mbg_get_gps_all_gnss_sat_info + * @see ::mbg_chk_dev_is_gnss + */ +_MBG_API_ATTR int _MBG_API mbg_get_gps_gnss_mode_info( MBG_DEV_HANDLE dh, MBG_GNSS_MODE_INFO *p_mi ) +{ + MBGDEVIO_RET_VAL rc; + _mbgdevio_read_gps_var_chk( dh, PC_GPS_GNSS_MODE, + IOCTL_GET_GNSS_MODE_INFO, p_mi, + _pcps_ddev_is_gnss( dh ) ); + _mbg_swab_mbg_gnss_mode_info( p_mi ); + return _mbgdevio_cnv_ret_val( rc ); - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TR_DISTANCE variable to be filled up +} // mbg_get_gps_gnss_mode_info - @return ::MBG_SUCCESS or error code returned by device I/O control function. - @see mbg_dev_has_pzf() - @see mbg_dev_has_tr_distance() - @see mbg_set_tr_distance() - */ -_MBG_API_ATTR int _MBG_API mbg_get_tr_distance( MBG_DEV_HANDLE dh, TR_DISTANCE *p ) + +/*HDR*/ +/** + * @brief Write the GNSS mode configuration to a device + * + * The ::MBG_GNSS_MODE_SETTINGS structure determines the GNSS settings + * for a device, e.g. which satellite systems have to be used. + * + * The function ::mbg_get_gps_gnss_mode_info should have been called before + * to determine which GNSS settings are supported by the device. + * + * The API call ::mbg_chk_dev_is_gnss can be used to check whether + * this call is supported by a device. + * + * See also the notes for ::mbg_chk_dev_is_gnss. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p_ms Pointer to a ::MBG_GNSS_MODE_SETTINGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_gps_gnss_mode_info + * @see ::mbg_get_gps_all_gnss_sat_info + * @see ::mbg_chk_dev_is_gnss + */ +_MBG_API_ATTR int _MBG_API mbg_set_gps_gnss_mode_settings( MBG_DEV_HANDLE dh, + const MBG_GNSS_MODE_SETTINGS *p_ms ) +{ + MBGDEVIO_RET_VAL rc; + #if defined( MBG_ARCH_BIG_ENDIAN ) + MBG_GNSS_MODE_SETTINGS tmp = *p_ms; + _mbg_swab_mbg_gnss_mode_settings( &tmp ); + p_ms = &tmp; + #endif + _mbgdevio_write_gps_var_chk( dh, PC_GPS_GNSS_MODE, + IOCTL_SET_GNSS_MODE_SETTINGS, p_ms, + _pcps_ddev_is_gnss( dh ) ); + return _mbgdevio_cnv_ret_val( rc ); + +} // mbg_set_gps_gnss_mode_settings + + + +/*HDR*/ +/** + * @brief Read a ::GNSS_SAT_INFO_IDX array of satellite status information + * + * The function ::mbg_get_gps_gnss_mode_info must have been called before, + * and the returned ::MBG_GNSS_MODE_INFO structure be passed to this function. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] gsii Pointer to a an array of satellite info structures to be filled up. + * @param[in] p_mi Pointer to a ::MBG_GNSS_MODE_INFO structure returned by ::mbg_get_gps_gnss_mode_info. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_gps_gnss_mode_info + * @see ::mbg_set_gps_gnss_mode_settings + * @see ::mbg_chk_dev_is_gnss + */ +_MBG_API_ATTR int _MBG_API mbg_get_gps_all_gnss_sat_info( MBG_DEV_HANDLE dh, + GNSS_SAT_INFO_IDX gsii[], + const MBG_GNSS_MODE_INFO *p_mi ) { - _mbgdevio_vars(); - _mbgdevio_read_var_chk( dh, PCPS_GET_TR_DISTANCE, - IOCTL_GET_TR_DISTANCE, p, - _pcps_ddev_has_tr_distance( dh ) ); - _mbg_swab_tr_distance( p ); - return _mbgdevio_ret_val; + MBGDEVIO_RET_VAL rc; -} // mbg_get_tr_distance + int n_supp = num_bits_set( p_mi->supp_gnss_types ); + + #if _MBG_SUPP_VAR_ACC_SIZE + _mbgdevio_read_gps_chk( dh, PC_GPS_ALL_GNSS_SAT_INFO, + IOCTL_GET_ALL_GNSS_SAT_INFO, gsii, + n_supp * sizeof( gsii[0] ), + _pcps_ddev_is_gnss( dh ) ); + #else + rc = _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_GNSS_SAT_INFO, gsii, + n_supp * sizeof( gsii[0] ) ); + #endif + + #if defined( MBG_ARCH_BIG_ENDIAN ) + if ( mbg_rc_is_success( rc ) ) + { + int i; + for ( i = 0; i < n_supp; i++ ) + { + GNSS_SAT_INFO_IDX *p = &gsii[i]; + _mbg_swab_gnss_sat_info_idx( p ); + } + } + #endif + + return _mbgdevio_cnv_ret_val( rc ); + +} // mbg_get_gps_all_gnss_sat_info /*HDR*/ /** - Write configurable "distance from transmitter" parameter to a card - which supports this. The parameter is used to compensate the RF signal - propagation delay. - The macro _pcps_has_tr_distance() or the API call mbg_dev_has_tr_distance() - check whether this call is supported by a specific card. + * @brief Read common GPIO configuration limits + * + * The API call ::mbg_chk_dev_has_gpio checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p A ::MBG_GPIO_CFG_LIMITS structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_gpio + * @see ::mbg_get_gpio_cfg_limits + * @see ::mbg_get_gps_all_gpio_info + * @see ::mbg_set_gps_gpio_settings_idx + * @see ::mbg_get_gps_all_gpio_status + */ +_MBG_API_ATTR int _MBG_API mbg_get_gpio_cfg_limits( MBG_DEV_HANDLE dh, MBG_GPIO_CFG_LIMITS *p ) +{ + MBGDEVIO_RET_VAL rc; + _mbgdevio_read_gps_var_chk( dh, PC_GPS_GPIO_CFG_LIMITS, + IOCTL_GET_GPIO_CFG_LIMITS, p, + _pcps_ddev_has_gpio( dh ) ); + _mbg_swab_mbg_gpio_cfg_limits( p ); - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TR_DISTANCE variable to be written + return _mbgdevio_cnv_ret_val( rc ); - @return ::MBG_SUCCESS or error code returned by device I/O control function. +} // mbg_get_gpio_cfg_limits - @see mbg_dev_has_pzf() - @see mbg_dev_has_tr_distance() - @see mbg_get_tr_distance() - */ -_MBG_API_ATTR int _MBG_API mbg_set_tr_distance( MBG_DEV_HANDLE dh, const TR_DISTANCE *p ) + + +/*HDR*/ +/** + * @brief Get all GPIO settings and capabilities. + * + * The API call ::mbg_chk_dev_has_gpio checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] gii An array of ::MBG_GPIO_STATUS_IDX structures to be filled up. + * @param[in] p_gcl Pointer to a ::MBG_GPIO_CFG_LIMITS structure read before. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_gpio + * @see ::mbg_get_gpio_cfg_limits + * @see ::mbg_get_gps_all_gpio_info + * @see ::mbg_set_gps_gpio_settings_idx + * @see ::mbg_get_gps_all_gpio_status + */ +_MBG_API_ATTR int _MBG_API mbg_get_gps_all_gpio_info( MBG_DEV_HANDLE dh, + MBG_GPIO_INFO_IDX gii[], + const MBG_GPIO_CFG_LIMITS *p_gcl ) { - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; + + uint32_t n_supp = p_gcl->num_io; + + #if _MBG_SUPP_VAR_ACC_SIZE + _mbgdevio_read_gps_chk( dh, PC_GPS_ALL_GPIO_INFO, + IOCTL_GET_ALL_GPIO_INFO, gii, + n_supp * sizeof( gii[0] ), + _pcps_ddev_has_gpio( dh ) ); + #else + rc = _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_GPIO_INFO, gii, + n_supp * sizeof( gii[0] ) ); + #endif + #if defined( MBG_ARCH_BIG_ENDIAN ) - TR_DISTANCE tmp = *p; - _mbg_swab_tr_distance( &tmp ); + if ( mbg_rc_is_success( rc ) ) + { + int i; + for ( i = 0; i < n_supp; i++ ) + { + MBG_GPIO_INFO_IDX *p = &gii[i]; + _mbg_swab_mbg_gpio_info_idx( p, 1 ); + } + } + #endif + + return _mbgdevio_cnv_ret_val( rc ); + +} // mbg_get_gps_all_gpio_info + + + +/*HDR*/ +/** + * @brief Write the configuration for a single GPIO port to a device + * + * The ::MBG_GPIO_SETTINGS_IDX structure contains both the ::MBG_GPIO_SETTINGS + * and the port index value. + * + * The API call ::mbg_chk_dev_has_gpio checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_GPIO_SETTINGS_IDX structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_gpio + * @see ::mbg_get_gpio_cfg_limits + * @see ::mbg_get_gps_all_gpio_info + * @see ::mbg_set_gps_gpio_settings_idx + * @see ::mbg_get_gps_all_gpio_status + */ +_MBG_API_ATTR int _MBG_API mbg_set_gps_gpio_settings_idx( MBG_DEV_HANDLE dh, + const MBG_GPIO_SETTINGS_IDX *p ) +{ + MBGDEVIO_RET_VAL rc; + #if defined( MBG_ARCH_BIG_ENDIAN ) + MBG_GPIO_SETTINGS_IDX tmp = *p; + _mbg_swab_mbg_gpio_settings_idx( &tmp, 1 ); p = &tmp; #endif - _mbgdevio_write_var_chk( dh, PCPS_SET_TR_DISTANCE, IOCTL_SET_TR_DISTANCE, - p, _pcps_ddev_has_tr_distance( dh ) ); - return _mbgdevio_ret_val; + _mbgdevio_write_gps_var_chk( dh, PC_GPS_GPIO_SETTINGS_IDX, + IOCTL_SET_GPIO_SETTINGS_IDX, p, + _pcps_ddev_has_gpio( dh ) ); + return _mbgdevio_cnv_ret_val( rc ); -} // mbg_set_tr_distance +} // mbg_set_gps_gpio_settings_idx /*HDR*/ /** - Read the CPU affinity of a process, i.e. on which of the available - CPUs the process can be executed. + * @brief Read the status of all GPIO signal ports + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] gsi An array of ::MBG_GPIO_STATUS_IDX structures to be filled up. + * @param[in] p_gcl Pointer to a ::MBG_GPIO_CFG_LIMITS structure read before. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_gpio + * @see ::mbg_get_gpio_cfg_limits + * @see ::mbg_get_gps_all_gpio_info + * @see ::mbg_set_gps_gpio_settings_idx + */ +_MBG_API_ATTR int _MBG_API mbg_get_gps_all_gpio_status( MBG_DEV_HANDLE dh, + MBG_GPIO_STATUS_IDX gsi[], + const MBG_GPIO_CFG_LIMITS *p_gcl ) +{ + MBGDEVIO_RET_VAL rc; - @param pid The process ID. - @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. + uint32_t n_supp; - @return ::MBG_SUCCESS or error code returned by the system call. + if ( !( p_gcl->flags & MBG_GPIO_CFG_LIMIT_FLAG_MASK_STATUS_SUPP ) ) + return MBG_ERR_NOT_SUPP_BY_DEV; - @see mbg_set_process_affinity() - @see mbg_set_current_process_affinity_to_cpu() - */ -_MBG_API_ATTR int _MBG_API mbg_get_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p ) + n_supp = p_gcl->num_io; + + #if _MBG_SUPP_VAR_ACC_SIZE + _mbgdevio_read_gps_chk( dh, PC_GPS_ALL_GPIO_STATUS, + IOCTL_GET_ALL_GPIO_STATUS, gsi, + n_supp * sizeof( gsi[0] ), + _pcps_ddev_has_gpio( dh ) ); + #else + rc = _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_GPIO_STATUS, gsi, + n_supp * sizeof( gsi[0] ) ); + #endif + + #if defined( MBG_ARCH_BIG_ENDIAN ) + if ( mbg_rc_is_success( rc ) ) + { + int i; + for ( i = 0; i < n_supp; i++ ) + { + MBG_GPIO_STATUS_IDX *p = &gsi[i]; + _mbg_swab_mbg_gpio_status_idx( p ); + } + } + #endif + + return _mbgdevio_cnv_ret_val( rc ); + +} // mbg_get_gps_all_gpio_status + + + +/*HDR*/ +/** + * @brief Read ::XMULTI_REF_INSTANCES + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p A ::XMULTI_REF_INSTANCES structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_xmr + * @see ::mbg_get_gps_all_xmr_status + * @see ::mbg_get_gps_all_xmr_info + * @see ::mbg_set_gps_xmr_settings_idx + * @see ::mbg_get_xmr_holdover_status + */ +_MBG_API_ATTR int _MBG_API mbg_get_xmr_instances( MBG_DEV_HANDLE dh, XMULTI_REF_INSTANCES *p ) { - #if defined( MBG_TGT_LINUX ) + MBGDEVIO_RET_VAL rc; + _mbgdevio_read_gps_var_chk( dh, PC_GPS_XMR_INSTANCES, + IOCTL_GET_XMR_INSTANCES, p, + _pcps_ddev_has_xmr( dh ) ); + _mbg_swab_xmulti_ref_instances( p ); + return _mbgdevio_cnv_ret_val( rc ); - return sched_getaffinity( pid, sizeof( *p ), p ); +} // mbg_get_xmr_instances - #elif defined( MBG_TGT_WIN32 ) - MBG_CPU_SET system_affinity_mask = 0; - return GetProcessAffinityMask( pid, p, &system_affinity_mask ) ? 0 : -1; +/*HDR*/ +/** + * @brief Read the status of all XMR sources + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] xmrsi An array of ::XMULTI_REF_STATUS_IDX structures to be filled up. + * @param[in] p_xmri Pointer to a ::XMULTI_REF_INSTANCES structure read before. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_xmr + * @see ::mbg_get_xmr_instances + * @see ::mbg_get_gps_all_xmr_info + * @see ::mbg_set_gps_xmr_settings_idx + * @see ::mbg_get_xmr_holdover_status + */ +_MBG_API_ATTR int _MBG_API mbg_get_gps_all_xmr_status( MBG_DEV_HANDLE dh, + XMULTI_REF_STATUS_IDX xmrsi[], + const XMULTI_REF_INSTANCES *p_xmri ) +{ + MBGDEVIO_RET_VAL rc; + + int n_supp = p_xmri->n_xmr_settings; + #if _MBG_SUPP_VAR_ACC_SIZE + _mbgdevio_read_gps_chk( dh, PC_GPS_ALL_XMR_STATUS, + IOCTL_GET_ALL_XMR_STATUS, xmrsi, + n_supp * sizeof( xmrsi[0] ), + _pcps_ddev_has_xmr( dh ) ); #else + rc = _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_XMR_STATUS, xmrsi, + n_supp * sizeof( xmrsi[0] ) ); + #endif + + #if defined( MBG_ARCH_BIG_ENDIAN ) + if ( mbg_rc_is_success( rc ) ) + { + int i; + for ( i = 0; i < n_supp; i++ ) + { + XMULTI_REF_STATUS_IDX *p = &xmrsi[i]; + _mbg_swab_xmulti_ref_status_idx( p ); + } + } + #endif + + return _mbgdevio_cnv_ret_val( rc ); + +} // mbg_get_gps_all_xmr_status + + + +/*HDR*/ +/** + * @brief Read all XMR settings and capabilities + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] xmrii An array of ::XMULTI_REF_INFO_IDX structures to be filled up. + * @param[in] p_xmri Pointer to a ::XMULTI_REF_INSTANCES structure read before. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_xmr + * @see ::mbg_get_xmr_instances + * @see ::mbg_get_gps_all_xmr_status + * @see ::mbg_set_gps_xmr_settings_idx + * @see ::mbg_get_xmr_holdover_status + */ +_MBG_API_ATTR int _MBG_API mbg_get_gps_all_xmr_info( MBG_DEV_HANDLE dh, + XMULTI_REF_INFO_IDX xmrii[], + const XMULTI_REF_INSTANCES *p_xmri ) +{ + MBGDEVIO_RET_VAL rc; - return -1; + int n_supp = p_xmri->n_xmr_settings; + #if _MBG_SUPP_VAR_ACC_SIZE + _mbgdevio_read_gps_chk( dh, PC_GPS_ALL_XMR_INFO, + IOCTL_GET_ALL_XMR_INFO, xmrii, + n_supp * sizeof( xmrii[0] ), + _pcps_ddev_has_xmr( dh ) ); + #else + rc = _mbgdevio_gen_read_gps( dh, PC_GPS_ALL_XMR_INFO, xmrii, + n_supp * sizeof( xmrii[0] ) ); #endif -} // mbg_get_process_affinity + #if defined( MBG_ARCH_BIG_ENDIAN ) + if ( mbg_rc_is_success( rc ) ) + { + int i; + for ( i = 0; i < n_supp; i++ ) + { + XMULTI_REF_INFO_IDX *p = &xmrii[i]; + _mbg_swab_xmulti_ref_info_idx( p ); + } + } + #endif + + return _mbgdevio_cnv_ret_val( rc ); + +} // mbg_get_gps_all_xmr_info /*HDR*/ /** - Set the CPU affinity of a process, i.e. on which of the available - CPUs the process is allowed to be executed. + * @brief Write a single XMR setting to a device + * + * The ::XMULTI_REF_SETTINGS_IDX structure contains both the ::XMULTI_REF_SETTINGS + * and the index value. + * + * The API call ::mbg_chk_dev_has_xmr checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::XMULTI_REF_SETTINGS_IDX structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_xmr + * @see ::mbg_get_xmr_instances + * @see ::mbg_get_gps_all_xmr_status + * @see ::mbg_get_gps_all_xmr_info + * @see ::mbg_get_xmr_holdover_status + */ +_MBG_API_ATTR int _MBG_API mbg_set_gps_xmr_settings_idx( MBG_DEV_HANDLE dh, + const XMULTI_REF_SETTINGS_IDX *p ) +{ + MBGDEVIO_RET_VAL rc; + #if defined( MBG_ARCH_BIG_ENDIAN ) + XMULTI_REF_SETTINGS_IDX tmp = *p; + _mbg_swab_xmulti_ref_settings_idx( &tmp ); + p = &tmp; + #endif + _mbgdevio_write_gps_var_chk( dh, PC_GPS_XMR_SETTINGS_IDX, + IOCTL_SET_XMR_SETTINGS_IDX, p, + _pcps_ddev_has_xmr( dh ) ); + return _mbgdevio_cnv_ret_val( rc ); - @param pid The process ID. - @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. +} // mbg_set_gps_xmr_settings_idx - @return ::MBG_SUCCESS or error code returned by the system call. - @see mbg_get_process_affinity() - @see mbg_set_current_process_affinity_to_cpu() - */ -_MBG_API_ATTR int _MBG_API mbg_set_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p ) + +/*HDR*/ +/** + * @brief Read the current XMR holdover interval from a device + * + * The API call ::mbg_chk_dev_has_xmr checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::XMR_HOLDOVER_INTV structure to be filled up. + * @param[in] p_xmri Pointer to a ::XMULTI_REF_INSTANCES structure read before. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_xmr + * @see ::mbg_get_xmr_instances + * @see ::mbg_get_gps_all_xmr_status + * @see ::mbg_get_gps_all_xmr_info + * @see ::mbg_set_gps_xmr_settings_idx + */ +_MBG_API_ATTR int _MBG_API mbg_get_xmr_holdover_status( MBG_DEV_HANDLE dh, XMR_HOLDOVER_STATUS *p, + const XMULTI_REF_INSTANCES *p_xmri ) { - #if defined( MBG_TGT_LINUX ) + MBGDEVIO_RET_VAL rc; + + if ( !( p_xmri->flags & XMRIF_MSK_HOLDOVER_STATUS_SUPP ) ) + return MBG_ERR_NOT_SUPP_BY_DEV; + + _mbgdevio_read_gps_var_chk( dh, PC_GPS_XMR_HOLDOVER_STATUS, + IOCTL_GET_XMR_HOLDOVER_STATUS, p, + _pcps_ddev_has_xmr( dh ) ); + _mbg_swab_xmr_holdover_status( p ); - return sched_setaffinity( pid, sizeof( *p ), p ); + return _mbgdevio_cnv_ret_val( rc ); + +} // mbg_get_xmr_holdover_status + + + +/*HDR*/ +/** + * @brief Read the CPU affinity of a process + * + * This means on which of the available CPUs or CPU cores + * a process may be executed. + * + * @param[in] pid The process ID. + * @param[out] p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_process_affinity + * @see ::mbg_set_current_process_affinity_to_cpu + */ +_MBG_API_ATTR int _MBG_API mbg_get_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p ) +{ + #if defined( MBG_TGT_LINUX ) // TODO Eventually generally for POSIX? + + if ( sched_getaffinity( pid, sizeof( *p ), p ) == 0 ) // success + return MBG_SUCCESS; + + return mbg_get_last_error( NULL ); #elif defined( MBG_TGT_WIN32 ) - return SetProcessAffinityMask( pid, *p ) ? 0 : -1; + MBG_CPU_SET system_affinity_mask = 0; + + if ( GetProcessAffinityMask( pid, p, &system_affinity_mask ) ) + return MBG_SUCCESS; + + return mbg_get_last_error( NULL ); #else - return -1; + return MBG_ERR_NOT_SUPP_ON_OS; #endif -} // mbg_set_process_affinity +} // mbg_get_process_affinity /*HDR*/ /** - Set the CPU affinity of a process for a single CPU only, i.e. the process - may only be executed on that single CPU. + * @brief Set the CPU affinity of a process. + * + * This determines on which of the available CPUs + * or CPU cores the process is allowed to be executed. + * + * @param[in] pid The process ID. + * @param[out] p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_process_affinity + * @see ::mbg_set_current_process_affinity_to_cpu + */ +_MBG_API_ATTR int _MBG_API mbg_set_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p ) +{ + #if defined( MBG_TGT_LINUX ) // TODO Eventually generally for POSIX? + + if ( sched_setaffinity( pid, sizeof( *p ), p ) == 0 ) + return MBG_SUCCESS; + + return mbg_get_last_error( NULL ); + + #elif defined( MBG_TGT_WIN32 ) + + if ( SetProcessAffinityMask( pid, *p ) ) + return MBG_SUCCESS; + + return mbg_get_last_error( NULL ); + + #else - @param cpu_num The number of the CPU. + return MBG_ERR_NOT_SUPP_ON_OS; + + #endif + +} // mbg_set_process_affinity - @return ::MBG_SUCCESS or error code returned by the system call. - @see mbg_get_process_affinity() - @see mbg_set_process_affinity() - */ + +/*HDR*/ +/** + * @brief Set the CPU affinity of a process for a single CPU only + * + * This means the process may only be executed on that single CPU. + * + * @param[in] cpu_num The number of the CPU. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_process_affinity + * @see ::mbg_set_process_affinity + */ _MBG_API_ATTR int _MBG_API mbg_set_current_process_affinity_to_cpu( int cpu_num ) { MBG_CPU_SET cpu_set; @@ -5615,25 +8454,29 @@ _MBG_API_ATTR int _MBG_API mbg_set_current_process_affinity_to_cpu( int cpu_num /*HDR*/ /** - Create a new execution thread for the current process. - This function is only implemented for targets which support threads. - - @param p_ti Pointer to a ::MBG_THREAD_INFO structure to be filled up. - @param fnc The name of the thread function to be started. - @param arg A generic argument passed to the thread function. - - @return ::MBG_SUCCESS or error code returned by the system call. - - @see mbg_thread_stop() - @see mbg_thread_sleep_interruptible() - @see mbg_thread_set_affinity() - */ + * @brief Create a new execution thread for the current process. + * + * This function is only implemented for targets that support threads. + * + * @param[in] p_ti Pointer to a ::MBG_THREAD_INFO structure to be filled up. + * @param[in] fnc The name of the thread function to be started. + * @param[in] arg A generic argument passed to the thread function. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_thread_stop + * @see ::mbg_thread_sleep_interruptible + * @see ::mbg_thread_set_affinity + */ _MBG_API_ATTR int _MBG_API mbg_thread_create( MBG_THREAD_INFO *p_ti, - MBG_THREAD_FNC_RET_VAL (MBG_THREAD_FNC_ATTR *fnc)(void *), void *arg ) + MBG_THREAD_FNC fnc, void *arg ) { - #if defined( MBG_TGT_LINUX ) + #if defined( MBG_TGT_LINUX ) // TODO Eventually generally for POSIX? + + if ( pthread_create( &p_ti->thread_id, NULL, fnc, arg ) == 0 ) + return MBG_SUCCESS; - return pthread_create( &p_ti->thread_id, NULL, fnc, arg ); + return mbg_get_last_error( NULL ); #elif defined( MBG_TGT_WIN32 ) @@ -5650,19 +8493,19 @@ _MBG_API_ATTR int _MBG_API mbg_thread_create( MBG_THREAD_INFO *p_ti, if ( h == NULL ) { CloseHandle( p_ti->exit_request ); - goto fail; + goto fail; } p_ti->thread_id = h; - return 0; + return MBG_SUCCESS; fail: - return GetLastError(); + return mbg_get_last_error( NULL ); #else - return -1; + return MBG_ERR_NOT_SUPP_ON_OS; #endif @@ -5672,25 +8515,30 @@ fail: /*HDR*/ /** - Stop a thread which has been created by mbg_thread_create(). Wait - until the thread has finished and release all resources. - This function is only implemented for targets which support threads. - - @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. - - @return ::MBG_SUCCESS or error code returned by the system call. - - @see mbg_thread_create() - @see mbg_thread_sleep_interruptible() - @see mbg_thread_set_affinity() - */ + * @brief Stop a thread which has been created by ::mbg_thread_create. + * + * Wait until the thread has finished and release all resources. + * + * This function is only implemented for targets that support threads. + * + * @param[in,out] p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_thread_create + * @see ::mbg_thread_sleep_interruptible + * @see ::mbg_thread_set_affinity + */ _MBG_API_ATTR int _MBG_API mbg_thread_stop( MBG_THREAD_INFO *p_ti ) { - #if defined( MBG_TGT_LINUX ) + #if defined( MBG_TGT_LINUX ) // TODO Eventually generally for POSIX? pthread_cancel( p_ti->thread_id ); - return pthread_join( p_ti->thread_id, NULL ); + if ( pthread_join( p_ti->thread_id, NULL ) == 0 ) + return MBG_SUCCESS; + + return mbg_get_last_error( NULL ); #elif defined( MBG_TGT_WIN32 ) @@ -5703,14 +8551,14 @@ _MBG_API_ATTR int _MBG_API mbg_thread_stop( MBG_THREAD_INFO *p_ti ) CloseHandle( p_ti->thread_id ); p_ti->thread_id = NULL; - return 0; + return MBG_SUCCESS; } - return GetLastError(); + return mbg_get_last_error( NULL ); #else - return -1; + return MBG_ERR_NOT_SUPP_ON_OS; #endif @@ -5720,26 +8568,32 @@ _MBG_API_ATTR int _MBG_API mbg_thread_stop( MBG_THREAD_INFO *p_ti ) /*HDR*/ /** - Let the current thread sleep for a certain interval unless a signal is - received indicating the thread should terminate. - This function is only implemented for targets which support threads. - - @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. - @param sleep_ms The number of milliseconds to sleep - @return 0 if the sleep interval has expired normally - 1 if a signal to terminate has been received - <0 if an error has occurred - - @see mbg_thread_create() - @see mbg_thread_stop() - @see mbg_thread_set_affinity() - */ + * @brief Let the current thread sleep for a certain interval + * + * The sleep is interrupted if a signal is received indicating + * the thread should terminate. + * + * This function is only implemented for targets that support threads. + * + * @param[in,out] p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. + * @param[in] sleep_ms The number of milliseconds to sleep + * + * @return MBG_SUCCESS if the sleep interval has expired normally, + * MBG_ERR_INTR if a signal to terminate has been received, + * or one of the other @ref MBG_ERROR_CODES + * + * @see ::mbg_thread_create + * @see ::mbg_thread_stop + * @see ::mbg_thread_set_affinity + */ _MBG_API_ATTR int _MBG_API mbg_thread_sleep_interruptible( MBG_THREAD_INFO *p_ti, ulong sleep_ms ) { - #if defined( MBG_TGT_LINUX ) + #if defined( MBG_TGT_LINUX ) // TODO Eventually generally for POSIX? - usleep( sleep_ms * 1000 ); - return 0; + if ( usleep( sleep_ms * 1000 ) == 0 ) + return MBG_SUCCESS; + + return mbg_get_last_error( NULL ); #elif defined( MBG_TGT_WIN32 ) @@ -5748,17 +8602,17 @@ _MBG_API_ATTR int _MBG_API mbg_thread_sleep_interruptible( MBG_THREAD_INFO *p_ti switch ( dw ) { case WAIT_OBJECT_0: // has been interrupted to terminate - return 1; + return MBG_ERR_INTR; case WAIT_TIMEOUT: // sleep interval expired without interruption - return 0; + return MBG_SUCCESS; } - return -1; + return mbg_get_last_error( NULL ); #else - return -1; + return MBG_ERR_NOT_SUPP_ON_OS; #endif @@ -5770,34 +8624,43 @@ _MBG_API_ATTR int _MBG_API mbg_thread_sleep_interruptible( MBG_THREAD_INFO *p_ti /*HDR*/ /** - Set the CPU affinity of a single thread, i.e. on which of the available - CPUs the thread is allowed to be executed. - This function is only implemented for targets which support thread affinity. - - @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. - @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. - - @return ::MBG_SUCCESS or error code returned by the system call. - - @see mbg_thread_create() - @see mbg_thread_stop() - @see mbg_thread_sleep_interruptible() - */ + * @brief Set the CPU affinity of a single thread + * + * This determines on which of the available CPUs the thread + * is allowed to be executed. + * + * This function is only implemented for targets that support thread affinity. + * + * @param[in,out] p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. + * @param[in] p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_thread_create + * @see ::mbg_thread_stop + * @see ::mbg_thread_sleep_interruptible + */ _MBG_API_ATTR int _MBG_API mbg_thread_set_affinity( MBG_THREAD_INFO *p_ti, MBG_CPU_SET *p ) { - #if defined( MBG_TGT_LINUX ) + #if defined( MBG_TGT_LINUX ) // TODO Eventually generally for POSIX? + + if ( pthread_setaffinity_np( tid, sizeof( *p ), p ) == 0 ) + return MBG_SUCCESS; - return pthread_setaffinity_np( tid, sizeof( *p ), p ); + return mbg_get_last_error( NULL ); #elif defined( MBG_TGT_WIN32 ) MBG_CPU_SET prv_thread_affinity = SetThreadAffinityMask( p_ti->thread_id, *p ); - return prv_thread_affinity ? 0 : -1; + if ( prv_thread_affinity ) + return MBG_SUCCESS; + + return mbg_get_last_error( NULL ); #else - return -1; + return MBG_ERR_NOT_SUPP_ON_OS; #endif @@ -5809,29 +8672,32 @@ _MBG_API_ATTR int _MBG_API mbg_thread_set_affinity( MBG_THREAD_INFO *p_ti, MBG_C static /*HDR*/ /** - A thread function which implements polling of a device at a regular interval. - At each polling a high resolution time stamp and an associated cycles count - are saved which can be used to retrieve extrapolated time stamps using the - cycles counter. The thread also computes the frequency of the system's cycles - counter. - On systems where the cycles counter is implemented by a CPU's time stamp - counter (TSC) it maybe required to set the thread or process affinity to a - single CPU to get reliable cycles counts. In this case also care should be - taken that the CPU's clock frequency is not stepped up and down e.g. due - to power saving mechanisms (e.g. Intel SpeedStep, or AMD Cool'n'Quiet). - Otherwise time interpolation may be messed up. - This function is only implemented for targets which support threads. - - @param *p_void Pointer to a ::MBG_POLL_THREAD_INFO structure. - - @return ::MBG_SUCCESS or nothing, depending on the taget system. - - @see mbg_xhrt_poll_thread_create() - @see mbg_xhrt_poll_thread_stop() - @see mbg_get_xhrt_time_as_pcps_hr_time() - @see mbg_get_xhrt_time_as_filetime() - @see mbg_get_xhrt_cycles_frequency() - */ + * @brief A thread function implementing polling of a device at regular intervals. + * + * At each polling a high resolution time stamp and an associated cycles count + * are saved which can be used to retrieve extrapolated time stamps using the + * cycles counter. The thread also computes the frequency of the system's cycles + * counter. + * + * On systems where the cycles counter is implemented by a CPU's time stamp + * counter (TSC) it may be required to set the thread or process affinity to a + * single CPU to get reliable cycles counts. In this case also care should be + * taken that the CPU's clock frequency is not stepped up and down e.g. due + * to power saving mechanisms (e.g. Intel SpeedStep, or AMD Cool'n'Quiet). + * Otherwise time interpolation may be messed up. + * + * This function is only implemented for targets that support threads. + * + * @param[in,out] p_void Pointer to a ::MBG_POLL_THREAD_INFO structure. + * + * @return ::MBG_SUCCESS or nothing, depending on the taget system. + * + * @see ::mbg_xhrt_poll_thread_create + * @see ::mbg_xhrt_poll_thread_stop + * @see ::mbg_get_xhrt_time_as_pcps_hr_time + * @see ::mbg_get_xhrt_time_as_filetime + * @see ::mbg_get_xhrt_cycles_frequency + */ MBG_THREAD_FNC_RET_VAL MBG_THREAD_FNC_ATTR mbg_xhrt_poll_thread_fnc( void *p_void ) { MBG_XHRT_VARS prv_xhrt_vars; @@ -5849,19 +8715,19 @@ MBG_THREAD_FNC_RET_VAL MBG_THREAD_FNC_ATTR mbg_xhrt_poll_thread_fnc( void *p_voi int rc = mbg_get_hr_time_cycles( p->dh, &xhrt_vars.htc ); - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) { xhrt_vars.pcps_hr_tstamp64 = pcps_time_stamp_to_uint64( &xhrt_vars.htc.t.tstamp ); if ( prv_xhrt_vars.pcps_hr_tstamp64 && ( ( xhrt_vars.htc.t.status & PCPS_LS_ENB ) == 0 ) ) - freq = ( mbg_delta_pc_cycles( &xhrt_vars.htc.cycles, &prv_xhrt_vars.htc.cycles ) * PCPS_HRT_BIN_FRAC_SCALE ) + freq = ( mbg_delta_pc_cycles( &xhrt_vars.htc.cycles, &prv_xhrt_vars.htc.cycles ) * MBG_FRAC32_UNITS_PER_SEC ) / ( xhrt_vars.pcps_hr_tstamp64 - prv_xhrt_vars.pcps_hr_tstamp64 ); } _mbg_crit_sect_enter( &p->crit_sect ); - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) { p->vars = xhrt_vars; p->prv_vars = prv_xhrt_vars; @@ -5877,49 +8743,52 @@ MBG_THREAD_FNC_RET_VAL MBG_THREAD_FNC_ATTR mbg_xhrt_poll_thread_fnc( void *p_voi _mbg_crit_sect_leave( &p->crit_sect ); - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) prv_xhrt_vars = xhrt_vars; - if ( mbg_thread_sleep_interruptible( &p_pti->ti, sleep_ms ) ) + if ( mbg_rc_is_error( mbg_thread_sleep_interruptible( &p_pti->ti, sleep_ms ) ) ) break; } - _mbg_thread_exit( 0 ); + _mbg_thread_exit( MBG_SUCCESS ); // TODO or an optional error code? } // mbg_xhrt_poll_thread_fnc +MBG_THREAD_FNC mbg_xhrt_poll_thread_fnc; + /*HDR*/ /** - Set up a ::MBG_POLL_THREAD_INFO structure and start a new thread - which runs the mbg_xhrt_poll_thread_fnc() function. - This function is only implemented for targets which support threads. - - @param *p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure. - @param dh the handle of the device to be polled. - @param freq_hz The initial cycles frequency, if known, in Hz. - @param sleep_ms the sleep interval for the poll thread function in ms. - If this parameter is 0 then the default sleep interval is used. - - @return ::MBG_SUCCESS on success, - ::MBG_ERR_NOT_SUPP_BY_DEV if the device to poll does not support HR time - else the result of mbg_thread_create() - - @see mbg_xhrt_poll_thread_fnc() - @see mbg_xhrt_poll_thread_stop() - @see mbg_get_xhrt_time_as_pcps_hr_time() - @see mbg_get_xhrt_time_as_filetime() - @see mbg_get_xhrt_cycles_frequency() - */ + * @brief Set up a ::MBG_POLL_THREAD_INFO structure and start a new thread + * + * The new thread runs a function which periodically reads + * a time stamp / cycles pair from a device. + * + * This function is only implemented for targets that support threads. + * + * @param[in,out] p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure. + * @param[in] dh the Handle of the device to be polled. + * @param[in] freq_hz The initial cycles frequency, if known, in Hz. + * @param[in] sleep_ms the sleep interval for the poll thread function in ms. + * If this parameter is 0 then the default sleep interval is used. + * + * @return ::MBG_SUCCESS on success, + * ::MBG_ERR_NOT_SUPP_BY_DEV if the device to poll does not support HR time + * else the result of ::mbg_thread_create. + * + * @see ::mbg_xhrt_poll_thread_stop + * @see ::mbg_get_xhrt_time_as_pcps_hr_time + * @see ::mbg_get_xhrt_time_as_filetime + * @see ::mbg_get_xhrt_cycles_frequency + */ _MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_create( MBG_POLL_THREAD_INFO *p_pti, MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY freq_hz, int sleep_ms ) { - int has_hr_time; - int rc = mbg_dev_has_hr_time( dh, &has_hr_time ); + int rc = mbg_chk_dev_has_hr_time( dh ); - if ( ( rc != MBG_SUCCESS ) || !has_hr_time ) - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV ); + if ( mbg_rc_is_error( rc ) ) + return rc; memset( p_pti, 0, sizeof( *p_pti ) ); @@ -5938,24 +8807,24 @@ _MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_create( MBG_POLL_THREAD_INFO *p_ /*HDR*/ /** - Stop a polling thread started by mbg_xhrt_poll_thread_create() - and release all associated resources. - - @param *p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure. - - @return the result of mbg_thread_stop() - - @see mbg_xhrt_poll_thread_fnc() - @see mbg_xhrt_poll_thread_create() - @see mbg_get_xhrt_time_as_pcps_hr_time() - @see mbg_get_xhrt_time_as_filetime() - @see mbg_get_xhrt_cycles_frequency() - */ + * @brief Stop a polling thread started by ::mbg_xhrt_poll_thread_create + * + * This call also releases all associated resources. + * + * @param[in,out] p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure. + * + * @return The result of ::mbg_thread_stop. + * + * @see ::mbg_xhrt_poll_thread_create + * @see ::mbg_get_xhrt_time_as_pcps_hr_time + * @see ::mbg_get_xhrt_time_as_filetime + * @see ::mbg_get_xhrt_cycles_frequency + */ _MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_stop( MBG_POLL_THREAD_INFO *p_pti ) { int rc = mbg_thread_stop( &p_pti->ti ); - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) _mbg_crit_sect_destroy( &p_pti->xhrt_info.crit_sect ); return rc; @@ -5964,8 +8833,33 @@ _MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_stop( MBG_POLL_THREAD_INFO *p_pt -static /*HDR*/ -int mbg_get_xhrt_data( MBG_XHRT_INFO *p, uint64_t *tstamp, MBG_XHRT_VARS *vars ) +static __mbg_inline /*HDR*/ +/** + * @brief Retrieve an extrapolated time stamp + * + * Get the system's current cycles count and compute the current time + * based on last recent time stamp/cycles pair read by the polling thread. + * + * See @ref mbg_xhrt_poll_group for details and limitations. + * + * This function is only implemented for targets that support threads. + * + * @param[in] p Pointer to a ::MBG_XHRT_INFO structure providing data from the polling thread. + * @param[out] p_tstamp Optional pointer to a variable to take the extrapolated time stamp, may be NULL. + * @param[out] p_vars Optional pointer to a ::MBG_XHRT_VARS structure to be filled up, may be NULL. + * + * @return The return code from the API call used by the polling thread + * to read the time from the device, usually ::mbg_get_hr_time_cycles, + * so ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES. + * + * @ingroup mbg_xhrt_poll_group + * @see ::mbg_xhrt_poll_thread_create + * @see ::mbg_xhrt_poll_thread_stop + * @see ::mbg_get_xhrt_time_as_filetime + * @see ::mbg_get_xhrt_cycles_frequency + * @see @ref mbg_xhrt_poll_group + */ +int mbg_get_xhrt_data( MBG_XHRT_INFO *p, uint64_t *p_tstamp, MBG_XHRT_VARS *p_vars ) { MBG_XHRT_VARS xhrt_vars; MBG_PC_CYCLES cyc_now; @@ -5984,15 +8878,15 @@ int mbg_get_xhrt_data( MBG_XHRT_INFO *p, uint64_t *tstamp, MBG_XHRT_VARS *vars ) if ( freq_hz && xhrt_vars.pcps_hr_tstamp64 ) { t_now = xhrt_vars.pcps_hr_tstamp64 + - ( mbg_delta_pc_cycles( &cyc_now, &xhrt_vars.htc.cycles ) * PCPS_HRT_BIN_FRAC_SCALE ) / freq_hz; + ( mbg_delta_pc_cycles( &cyc_now, &xhrt_vars.htc.cycles ) * MBG_FRAC32_UNITS_PER_SEC ) / freq_hz; mbg_chk_tstamp64_leap_sec( &t_now, &xhrt_vars.htc.t.status ); } - if ( tstamp ) - *tstamp = t_now; + if ( p_tstamp ) + *p_tstamp = t_now; - if ( vars ) - *vars = xhrt_vars; + if ( p_vars ) + *p_vars = xhrt_vars; return ioctl_status; @@ -6002,23 +8896,28 @@ int mbg_get_xhrt_data( MBG_XHRT_INFO *p, uint64_t *tstamp, MBG_XHRT_VARS *vars ) /*HDR*/ /** - Retrieve a time stamp in PCPS_HR_TIME format which is extrapolated - using the system's current cycles counter value and a time stamp - plus associated cycles counter value saved by the polling thread. - See mbg_xhrt_poll_thread_fnc() for details and limitations. - This function is only implemented for targets which support threads. - - @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. - @param *p_hrt Pointer to a ::PCPS_HR_TIME structure to be filled up. - - @return MBG_SUCCESS or another return value from the polling thread's IOCTL call. - - @see mbg_xhrt_poll_thread_fnc() - @see mbg_xhrt_poll_thread_create() - @see mbg_xhrt_poll_thread_stop() - @see mbg_get_xhrt_time_as_filetime() - @see mbg_get_xhrt_cycles_frequency() - */ + * @brief Retrieve an extrapolated time stamp in ::PCPS_HR_TIME format + * + * The time stamp is extrapolated using the system's current cycles counter value + * and a time stamp plus associated cycles counter value saved by the polling thread. + * See @ref mbg_xhrt_poll_group for details and limitations. + * + * This function is only implemented for targets that support threads. + * + * @param[in,out] p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. + * @param[out] p_hrt Pointer to a ::PCPS_HR_TIME structure to be filled up. + * + * @return The return code from the API call used by the polling thread + * to read the time from the device, usually ::mbg_get_hr_time_cycles, + * so ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES. + * + * @ingroup mbg_xhrt_poll_group + * @see ::mbg_xhrt_poll_thread_create + * @see ::mbg_xhrt_poll_thread_stop + * @see ::mbg_get_xhrt_time_as_filetime + * @see ::mbg_get_xhrt_cycles_frequency + * @see @ref mbg_xhrt_poll_group + */ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_pcps_hr_time( MBG_XHRT_INFO *p, PCPS_HR_TIME *p_hrt ) { uint64_t tstamp64; @@ -6047,24 +8946,29 @@ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_pcps_hr_time( MBG_XHRT_INFO *p, /*HDR*/ /** - Retrieve a time stamp in FILETIME format which is extrapolated - using the system's current cycles counter value and a time stamp - plus associated cycles counter value saved by the polling thread. - See mbg_xhrt_poll_thread_fnc() for details and limitations. - Since FILETIME is a Windows specific type this function is only - implemented under Windows. - - @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. - @param *p_ft Pointer to a ::FILETIME structure to be filled up. - - @return MBG_SUCCESS or another return value from the polling thread's IOCTL call. - - @see mbg_xhrt_poll_thread_fnc() - @see mbg_xhrt_poll_thread_create() - @see mbg_xhrt_poll_thread_stop() - @see mbg_get_xhrt_time_as_pcps_hr_time() - @see mbg_get_xhrt_cycles_frequency() - */ + * @brief Retrieve an extrapolated time stamp in FILETIME format + * + * The time stamp is extrapolated using the system's current cycles counter value + * and a time stamp plus associated cycles counter value saved by the polling thread. + * See @ref mbg_xhrt_poll_group for details and limitations. + * + * Since FILETIME is a Windows-specific type this function is only + * implemented under Windows. + * + * @param[in,out] p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. + * @param[out] p_ft Pointer to a FILETIME structure to be filled up. + * + * @return The return code from the API call used by the polling thread + * to read the time from the device, usually ::mbg_get_hr_time_cycles, + * so ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES. + * + * @ingroup mbg_xhrt_poll_group + * @see ::mbg_xhrt_poll_thread_create + * @see ::mbg_xhrt_poll_thread_stop + * @see ::mbg_get_xhrt_time_as_pcps_hr_time + * @see ::mbg_get_xhrt_cycles_frequency + * @see @ref mbg_xhrt_poll_group + */ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_filetime( MBG_XHRT_INFO *p, FILETIME *p_ft ) { uint64_t tstamp64; @@ -6087,21 +8991,27 @@ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_filetime( MBG_XHRT_INFO *p, FILE /*HDR*/ /** - Retrieve the frequency of the system's cycles counter as determined - by the device polling thread. - See mbg_xhrt_poll_thread_fnc() for details and limitations. - This function is only implemented for targets which support threads. - - @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. - @param *p_freq_hz Pointer to a ::MBG_PC_CYCLES_FREQUENCY variable in which the frequency is returned. - @return a status code from the polling thread: MBG_SUCCESS or an IOCTL error code. - - @see mbg_xhrt_poll_thread_fnc() - @see mbg_xhrt_poll_thread_create() - @see mbg_xhrt_poll_thread_stop() - @see mbg_get_xhrt_time_as_pcps_hr_time() - @see mbg_get_xhrt_time_as_filetime() - */ + * @brief Retrieve the frequency of the system's cycles counter + * + * The frequency is determined by the device polling thread. + * See @ref mbg_xhrt_poll_group for details and limitations. + * + * This function is only implemented for targets that support threads. + * + * @param[in,out] p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. + * @param[out] p_freq_hz Pointer to a ::MBG_PC_CYCLES_FREQUENCY variable in which the frequency is returned. + * + * @return The return code from the API call used by the polling thread + * to read the time from the device, usually ::mbg_get_hr_time_cycles, + * so ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES. + * + * @ingroup mbg_xhrt_poll_group + * @see ::mbg_xhrt_poll_thread_create + * @see ::mbg_xhrt_poll_thread_stop + * @see ::mbg_get_xhrt_time_as_pcps_hr_time + * @see ::mbg_get_xhrt_time_as_filetime + * @see @ref mbg_xhrt_poll_group + */ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_cycles_frequency( MBG_XHRT_INFO *p, MBG_PC_CYCLES_FREQUENCY *p_freq_hz ) { MBG_PC_CYCLES_FREQUENCY freq_hz; @@ -6125,35 +9035,32 @@ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_cycles_frequency( MBG_XHRT_INFO *p, MBG_ /*HDR*/ /** - Retrieve the default system's cycles counter frequency from the kernel driver. - - @param dh handle of the device to which the IOCTL call is sent. - @param *p Pointer of a ::MBG_PC_CYCLES_FREQUENCY variable to be filled up. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_default_cycles_frequency() - */ + * @brief Retrieve the system's default cycles counter frequency from the kernel driver + * + * This API call can be used on systems which don't provide this information in user space. + * + * @param[in] dh Handle of the device to which the IOCTL call is sent. + * @param[out] p Pointer of a ::MBG_PC_CYCLES_FREQUENCY variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_default_cycles_frequency + */ _MBG_API_ATTR int _MBG_API mbg_get_default_cycles_frequency_from_dev( MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY *p ) { #if defined( _MBGIOCTL_H ) - _mbgdevio_vars(); + MBGDEVIO_RET_VAL rc; rc = _mbgdevio_read_var( dh, -1, IOCTL_GET_CYCLES_FREQUENCY, p ); // native endianess, no need to swap bytes - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) *p = 0; #if defined( MBG_TGT_LINUX ) if ( *p == 0 ) { - int has_hr_time = 0; + rc = mbg_chk_dev_has_hr_time( dh ); - rc = mbg_dev_has_hr_time( dh, &has_hr_time ); - - if ( rc != MBG_SUCCESS ) - goto done; - - if ( has_hr_time ) + if ( mbg_rc_is_success( rc ) ) { PCPS_HR_TIME_CYCLES htc1; PCPS_HR_TIME_CYCLES htc2; @@ -6162,32 +9069,32 @@ _MBG_API_ATTR int _MBG_API mbg_get_default_cycles_frequency_from_dev( MBG_DEV_HA rc = mbg_get_hr_time_cycles( dh, &htc1 ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto done; sleep( 1 ); rc = mbg_get_hr_time_cycles( dh, &htc2 ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto done; // compute cycles frequency from delta htc delta_cycles = mbg_delta_pc_cycles( &htc2.cycles, &htc1.cycles ); delta_t = pcps_time_stamp_to_uint64( &htc2.t.tstamp ) - pcps_time_stamp_to_uint64( &htc1.t.tstamp ); - *p = ( delta_cycles * PCPS_HRT_BIN_FRAC_SCALE ) / delta_t; + *p = ( delta_cycles * MBG_FRAC32_UNITS_PER_SEC ) / delta_t; } } done: #endif - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); #else *p = 0; - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_ON_OS ); + return MBG_ERR_NOT_SUPP_ON_OS; #endif @@ -6197,16 +9104,16 @@ done: /*HDR*/ /** - Retrieve the default system's cycles counter frequency. - - @note This may not be supported on all target platforms, in which case the - returned frequency is 0 and the mbg_get_default_cycles_frequency_from_dev() - call should be used. - - @return the default cycles counter frequency in Hz, or 0 if the value is not available. - - @see mbg_get_default_cycles_frequency_from_dev() -*/ + * @brief Retrieve the system's default cycles counter frequency + * + * @note This may not be supported on all target platforms, in which case the + * returned frequency is 0 and the ::mbg_get_default_cycles_frequency_from_dev + * call should be used instead. + * + * @return the default cycles counter frequency in Hz, or 0 if the value is not available. + * + * @see ::mbg_get_default_cycles_frequency_from_dev + */ _MBG_API_ATTR MBG_PC_CYCLES_FREQUENCY _MBG_API mbg_get_default_cycles_frequency( void ) { #if defined MBG_TGT_WIN32 diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.h index 69cfd5c..440ceda 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgdevio.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgdevio.h 1.39.1.20 2011/07/20 15:52:22 martin TRASH $ + * $Id: mbgdevio.h 1.42 2017/07/05 15:20:32 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,47 +10,50 @@ * * ----------------------------------------------------------------------- * $Log: mbgdevio.h $ - * Revision 1.39.1.20 2011/07/20 15:52:22 martin - * Conditionally use older IOCTL request buffer structures. + * Revision 1.42 2017/07/05 15:20:32 martin + * New MBGDEVIO_VERSION 0x0400, compatibility version unchanged. + * Account for MBG_ERROR_CODES returned by the ioctl functions. + * New type MBG_DEV_FN used for device file names, formerly often + * referred to as 'hardware ID'. + * New type MBG_DEV_NAME used for unique device names, composed of + * device type name and serial number appended after an underscore. + * Renamed and reworked list handling for device lists. + * Use functions from new module timeutil. + * windows.h is now included in mbg_tgt.h. + * Check for MBG_TGT_POSIX instead of MBG_TGT_UNIX. + * Account for PCPS_HRT_BIN_FRAC_SCALE renamed to MBG_FRAC32_UNITS_PER_SEC. + * Fixed macro definition syntax to avoid clang compiler warnings. + * Exclude mbg_chk_tstamp64_leap_sec() for BC builds for now. + * Lots of new doxygen comments and groups. + * Updated function prototypes. + * Revision 1.41 2013/09/26 08:54:54 martin + * Defined thread function type MBG_THREAD_FNC. + * Defined check-if-supported function type MBG_CHK_SUPP_FNC. + * Updated function prototypes. + * Revision 1.40 2012/10/02 18:40:30Z martin + * There are some g++ versions which fail to compile source code using + * the macros provided by Linux to define IOCTL codes. If only the API + * functions are called by an application then the IOCTL codes aren't + * required anyway, so we just avoid inclusion of mbgioctl.h. + * Updated doxygen comments. + * Updated function prototypes. + * Support on-board event logs. + * Fixed a bug which caused a crash when generic I/O calls + * were used under Windows. + * Changes for QNX. + * Workaround to make mbgmon (BC) build under Windows. + * Cleaned up CPU set support under Linux. * Moved some macros here so they can be used by other modules. - * Modified some macros and definitions. - * Revision 1.39.1.19 2011/07/19 15:46:39 martin - * Revision 1.39.1.18 2011/07/06 11:19:24 martin * Support reading CORR_INFO, and reading/writing TR_DISTANCE. - * Revision 1.39.1.17 2011/06/29 11:10:19 martin - * Updated function prototypes. - * Revision 1.39.1.16 2011/06/22 10:16:22 martin * Cleaned up handling of pragma pack(). * Cleaned up inclusion of header files. - * Updated function prototypes. - * Revision 1.39.1.15 2011/04/12 12:57:53 martin * Moved mutex definitions to new mbgmutex.h. * Renamed mutex stuff to critical sections. - * Revision 1.39.1.14 2011/03/31 13:20:55 martin - * Updated function prototypes. - * Revision 1.39.1.13 2011/02/15 14:26:22Z martin - * Revision 1.39.1.12 2011/02/15 11:22:29 daniel * Updated function prototypes to support PTP unicast configuration - * Revision 1.39.1.11 2011/02/02 12:21:39Z martin - * Fixed a type. - * Revision 1.39.1.10 2011/01/28 09:33:45 martin - * Cosmetics. - * Revision 1.39.1.9 2010/12/14 11:23:49 martin - * Moved definition of MBG_HW_NAME to the header file. - * Revision 1.39.1.8 2010/12/14 10:56:35Z martin - * Revision 1.39.1.7 2010/08/11 13:48:53 martin - * Cleaned up comments. - * Revision 1.39.1.6 2010/08/11 12:43:52 martin - * Revision 1.39.1.5 2010/07/15 08:40:57 martin - * Revision 1.39.1.4 2010/01/08 15:04:17Z martin - * Revision 1.39.1.3 2010/01/08 11:24:02Z martin - * Compute and check time of day only if any leap second status bit set. - * Revision 1.39.1.2 2010/01/08 11:13:57Z martin * Made xhrt leap second check an inline function. - * Revision 1.39.1.1 2010/01/07 15:49:37Z martin * Fixed macro to avoid compiler warning. * Revision 1.39 2009/12/15 15:34:59Z daniel - * Support reading the raw IRIG data bits for firmware versions + * Support reading the raw IRIG data bits for firmware versions * which support this feature. * Revision 1.38.1.2 2009/12/10 09:58:53Z daniel * Revision 1.38.1.1 2009/12/10 09:45:29Z daniel @@ -146,11 +149,11 @@ * PC high resolution timer cycles. * Updated function prototypes. * Revision 1.9 2003/06/19 08:50:05Z martin - * Definition of MBGDEVIO_VERSION number to allow DLL + * Definition of MBGDEVIO_VERSION number to allow DLL * API version checking. * Replaced some defines by typedefs. * Renamed USE_DOS_TSR to MBG_USE_DOS_TSR. - * New preprocessor symbol MBG_USE_KERNEL_DRIVER which + * New preprocessor symbol MBG_USE_KERNEL_DRIVER which * is defined only for targets which use IOCTLs. * Don't include pcps_dos.h here. * Updated function prototypes. @@ -188,20 +191,24 @@ #include <mbg_tgt.h> #include <mbg_arch.h> +#include <cfg_hlp.h> +#include <timeutil.h> #include <mbgmutex.h> #include <mbgerror.h> #include <mbggeo.h> #include <pcpsdev.h> #include <pci_asic.h> #include <use_pack.h> + #include <time.h> +#include <stdio.h> +#include <errno.h> -#define MBGDEVIO_VERSION 0x0307 +#define MBGDEVIO_VERSION 0x0400 #define MBGDEVIO_COMPAT_VERSION 0x0210 -#define MBG_MAX_DEVICES 8 #if defined( MBG_TGT_WIN32 ) @@ -218,7 +225,6 @@ #endif #define MBG_USE_KERNEL_DRIVER 1 - #include <windows.h> #define MBGDEVIO_RET_VAL DWORD #define _mbgdevio_cnv_ret_val( _v ) (_v) @@ -239,13 +245,10 @@ #define MBG_USE_KERNEL_DRIVER 1 #include <sys/ioctl.h> #include <fcntl.h> + #include <sched.h> - #if !defined( MBG_ARCH_ARM ) - #include <sched.h> - - #if MBGDEVIO_USE_THREAD_API - #include <pthread.h> - #endif + #if MBGDEVIO_USE_THREAD_API + #include <pthread.h> #endif #elif defined( MBG_TGT_BSD ) @@ -258,6 +261,14 @@ #define MBG_USE_KERNEL_DRIVER 1 +#elif defined( MBG_TGT_QNX_NTO ) + + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> + + #include <pcpsdrvr.h> + #elif defined( MBG_TGT_DOS ) #if !defined( MBG_USE_DOS_TSR ) @@ -283,6 +294,10 @@ #endif +#if defined( MBG_TGT_POSIX ) && !defined( MBG_TGT_QNX_NTO ) + #define MBG_HAS_POSIX_IOCTL 1 +#endif + #if !defined( MBGDEVIO_XHRT_API ) #define MBGDEVIO_XHRT_API 0 #endif @@ -295,8 +310,16 @@ #define MBGDEVIO_HAVE_THREAD_AFFINITY 0 #endif +#if ( 0 && defined( DEBUG ) ) + #define DEBUG_IOCTL 1 +#else + #define DEBUG_IOCTL 0 +#endif + + #ifdef _MBGDEVIO #define _ext + #define _DO_INIT #else #define _ext extern #endif @@ -310,9 +333,13 @@ #endif +#ifdef __cplusplus +extern "C" { +#endif + // If MBGDEVIO_SIMPLE != 0 then some complex configuration // API calls are excluded from build, which would otherwise -// require some additional mbglib modules to be linked +// require some additional mbglib modules to be linked // to the application. #if !defined( MBGDEVIO_SIMPLE ) #define MBGDEVIO_SIMPLE 0 @@ -345,42 +372,65 @@ #endif -#define _mbgdevio_vars() \ - MBGDEVIO_RET_VAL rc +/** + * @brief An string that can take a device file name + * + * The format of the device file name depends on the type of + * operating system. + * + * On Linux and similar systems this is something like + * a regular file name with an index number appended, + * e.g. "/dev/mbgclock0". See ::MBGCLOCK_DEV_FN_BASE. + * + * Under Windows this is a complex string composed of GUIDs, + * bus-specific vendor and device ID numbers, etc., which can't + * easily be handled manually. + */ +typedef char MBG_DEV_FN[260]; // Conforming to MAX_PATH in Windows -#define _mbgdevio_ret_val \ - _mbgdevio_cnv_ret_val( rc ) +#if MBG_TGT_HAS_DEV_FN +#define MBGCLOCK_DEV_FN_BASE "/dev/mbgclock" +#define MBGCLOCK_DEV_FN_FMT MBGCLOCK_DEV_FN_BASE "%i" -/** - The type below is used to store a unique ID for a device which - is made up of the device model name and its serial number, i.e.: - Format: [model_name]_[serial_number], e.g. "GPS170PCI_028210040670" - */ -typedef char MBG_HW_NAME[PCPS_CLOCK_NAME_SZ + PCPS_SN_SIZE + 1]; +_ext const char mbg_dev_fn_base[] +#ifdef _DO_INIT + = MBGCLOCK_DEV_FN_BASE +#endif +; + +_ext const char mbg_dev_fn_fmt[] +#ifdef _DO_INIT + = MBGCLOCK_DEV_FN_FMT +#endif +; + +#endif -#if defined( MBG_TGT_LINUX ) && !defined( MBG_ARCH_ARM ) +// Definitions specific to the target OS + +#if defined( MBG_TGT_LINUX ) #define MBG_PROCESS_ID pid_t #define _mbg_get_current_process() 0 - #define MBG_CPU_SET cpu_set_t - #define MBG_CPU_SET_SIZE CPU_SETSIZE - #define _mbg_cpu_clear( _ps ) CPU_ZERO( (_ps) ) - #define _mbg_cpu_set( _i, _ps ) CPU_SET( (_i), (_ps) ) - #define _mbg_cpu_isset( _i, _ps ) CPU_ISSET( (_i), (_ps) ) + #if defined( __cpu_set_t_defined ) + #define MBG_CPU_SET cpu_set_t + #define MBG_CPU_SET_SIZE CPU_SETSIZE + #define _mbg_cpu_clear( _ps ) CPU_ZERO( (_ps) ) + #define _mbg_cpu_set( _i, _ps ) CPU_SET( (_i), (_ps) ) + #define _mbg_cpu_isset( _i, _ps ) CPU_ISSET( (_i), (_ps) ) + #endif #if MBGDEVIO_USE_THREAD_API - - #define MBG_THREAD_ID pthread_t - #define _mbg_get_current_thread() 0 - #define MBG_THREAD_FNC_ATTR // empty - #define MBG_THREAD_FNC_RET_VAL void * - #define _mbg_thread_exit( _v ) return (void *) (_v) - + #define MBG_THREAD_ID pthread_t + #define _mbg_get_current_thread() 0 + #define MBG_THREAD_FNC_ATTR // empty + #define MBG_THREAD_FNC_RET_VAL void * + #define _mbg_thread_exit( _v ) return (void *) (_v) #endif #elif defined( MBG_TGT_WIN32 ) @@ -401,12 +451,9 @@ typedef char MBG_HW_NAME[PCPS_CLOCK_NAME_SZ + PCPS_SN_SIZE + 1]; #if !defined( MBG_TGT_WIN32 ) - - #define FILETIME int // just a dummy to avoid build errors - + #define FILETIME int // just a dummy to avoid build errors #endif - #if !defined( MBG_PROCESS_ID ) #define MBG_PROCESS_ID int #endif @@ -428,7 +475,7 @@ typedef char MBG_HW_NAME[PCPS_CLOCK_NAME_SZ + PCPS_SN_SIZE + 1]; #endif #if !defined( _mbg_cpu_set ) - #define _mbg_cpu_set( _i, _ps ) ( *(_ps) |= ( 1UL << (_i) ) ) + #define _mbg_cpu_set( _i, _ps ) ( *(_ps) |= ( (MBG_CPU_SET) 1UL << (_i) ) ) #endif #if !defined( _mbg_cpu_isset ) @@ -457,23 +504,57 @@ typedef char MBG_HW_NAME[PCPS_CLOCK_NAME_SZ + PCPS_SN_SIZE + 1]; #endif + +/** + * @brief A generic thread info structure + */ typedef struct { MBG_THREAD_ID thread_id; #if defined( MBG_TGT_WIN32 ) HANDLE exit_request; #endif + } MBG_THREAD_INFO; +/** + * @brief A generic type of a thread function + */ +typedef MBG_THREAD_FNC_RET_VAL MBG_THREAD_FNC_ATTR MBG_THREAD_FNC( void * ); + + + +/** + * @brief A structure holding a time stamp / cycles count pair + * + * This can be used to extrapolate the current time from the current + * system cycles count. + * + * See @ref mbg_xhrt_poll_group for details and limitations. + * + * @see @ref mbg_xhrt_poll_group + */ typedef struct { - PCPS_HR_TIME_CYCLES htc; - uint64_t pcps_hr_tstamp64; + PCPS_HR_TIME_CYCLES htc; ///< Cycles count associated with the time stamp + uint64_t pcps_hr_tstamp64; ///< Time stamp read from a device + } MBG_XHRT_VARS; + +/** + * @brief A status structure provided by the time polling thread function + * + * This can be used to get information from the poll thread function + * and extrapolate the current time from the current system cycles count. + * + * See @ref mbg_xhrt_poll_group for details and limitations. + * + * @see @ref mbg_xhrt_poll_group + */ typedef struct { MBG_XHRT_VARS vars; @@ -483,2734 +564,4868 @@ typedef struct int sleep_ms; MBG_CRIT_SECT crit_sect; MBG_DEV_HANDLE dh; + } MBG_XHRT_INFO; + +/** + * @brief A structure used to control a poll thread function + * + * See @ref mbg_xhrt_poll_group for details and limitations. + * + * @see ::mbg_xhrt_poll_thread_create + * @see ::mbg_xhrt_poll_thread_stop + * @see @ref mbg_xhrt_poll_group + */ typedef struct { MBG_XHRT_INFO xhrt_info; MBG_THREAD_INFO ti; + } MBG_POLL_THREAD_INFO; /** - Match modes to decide how to proceed if a certain - model type with certain serial number can not be found + * @brief Device matching modes + * + * Match modes to determine how to proceed if a device with + * particular model type and serial number has not been detected. */ -enum MBG_MATCH_MODE +enum MBG_MATCH_MODES { - MBG_MATCH_ANY, /**< open the next available device on the system */ - MBG_MATCH_MODEL, /**< open the next available device on the system with the same clock type */ - MBG_MATCH_EXACTLY, /**< force opening exactly the requested device otherwise exit with failure */ - N_MBG_MATCH_MODE /**< number of known modes */ + MBG_MATCH_ANY, ///< use the next device available on the system + MBG_MATCH_MODEL, ///< use the next available device of the same type + MBG_MATCH_EXACTLY, ///< use only exactly the excat matching device, otherwise fail + N_MBG_MATCH_MODES ///< number of known modes }; -typedef struct _MBG_DEVICE_LIST -{ - char *device_path; /**< Hardware ID depending on the calling function */ - struct _MBG_DEVICE_LIST *next; - -} MBG_DEVICE_LIST; - +/** + * @brief An entry for a list of device file names + * + * Applications should consider this type as opaque, + * and must not rely on the type, number, and order of + * the structure members. + */ +typedef struct _MBG_DEV_FN_LIST_ENTRY MBG_DEV_FN_LIST_ENTRY; -typedef struct _MBG_DEVICENAME_LIST +/** + * @brief The structure behind the ::MBG_DEV_FN_LIST_ENTRY type + * + * Applications should consider this structure as opaque, + * and must not rely on the type, number, and order of + * the structure members. + * + * The definition is still in the header file since it + * is still required by some Windows-specific code. + */ +struct _MBG_DEV_FN_LIST_ENTRY { - char device_name[40]; /**< readable name */ - struct _MBG_DEVICENAME_LIST *next; + char *dev_fn_ptr; ///< Address of an OS-specific device file name + ///< that can be used with an OS-specific open call. + MBG_DEV_FN_LIST_ENTRY *next; +}; -} MBG_DEVICENAME_LIST; +/** + * @brief An entry for a list of device names + * + * Applications should consider this type as opaque, + * and must not rely on the type, number, and order of + * the structure members. + * + * @see ::mbg_find_devices_with_names + * @see ::mbg_free_device_name_list + */ +typedef struct _MBG_DEV_NAME_LIST_ENTRY MBG_DEV_NAME_LIST_ENTRY; -/* function prototypes: */ -#ifdef __cplusplus -extern "C" { -#endif +/** + * @brief The structure behind the ::MBG_DEV_NAME_LIST_ENTRY type + * + * Applications should actually consider this structure as opaque, + * and must not rely on the type, number, and order of + * the structure members. + * + * The definition is still in the header file since it is still + * used by some Windows-specific code. + */ +struct _MBG_DEV_NAME_LIST_ENTRY +{ + char dev_name[40]; ///< Readable device name (Should be ::MBG_DEV_NAME, which is smaller, though) + MBG_DEV_NAME_LIST_ENTRY *next; +}; -/* ----- function prototypes begin ----- */ -/* This section was generated automatically */ -/* by MAKEHDR, do not remove the comments. */ - MBGDEVIO_RET_VAL do_mbg_ioctl( MBG_DEV_HANDLE dh, int ioctl_code, const void *in_p, int in_sz, void *out_p, int out_sz ) ; - /** - Get the version number of the compiled mbgdevio library. - If the mbgdevio library is built as a DLL/shared object then - the version number of the compiled library may differ from - the version number of the import library and header files - which have been used to build an application. +/** + * @defgroup mbgdevio_open_fncs API functions that can be used to open a device + * + * Each of these functions can be used to open a device to obtain a valid + * ::MBG_DEV_HANDLE handle which can be used with subsequent API calls to + * access the particular device. + * + * If the device fails to be opened then each of these functions returns + * ::MBG_INVALID_DEV_HANDLE, and an OS-specific "last error" code is set + * accordingly. The caller can then use ::mbg_get_last_error immediately + * to retrieve the OS-specific error code, convert it, and return the + * associated Meinberg-specific error code. See @ref MBG_ERROR_CODES. + * + * Operating systems maintain a list of devices that are currently + * present in a system. The function ::mbg_open_device expects a number + * that is used as an index to this list. If only a single supported device + * is present then index 0 can always be used to open that device. + * + * The function ::mbg_find_devices can be used to retrieve the number of + * devices statically present in the system, and the highest index number + * that can be used is the number of devices - 1. + * + * In a plug-and-play system the device list maintained by the operating + * system may change over time, for example if a USB device is plugged in + * or out during operation. In this case index numbers may change, and may + * not always refer to the same device. + * + * So the function ::mbg_open_device_by_name can be used instead to open + * a specific device identified by model name and optionally serial number. + * See ::MBG_DEV_NAME for the format of such device name. + * + * If a list of unique device names is required e.g. to set up a + * device selection dialog in a GUI application then the function + * ::mbg_find_devices_with_names can be used to allocate and set up + * such a list. When the list has been evaluated and isn't needed + * anymore then ::mbg_free_device_name_list should be called to free + * the allocated memory. + * + * Inside the operating system the device is always identified by a + * device file name which can be used internally with an OS-specific + * "open" function, e.g. "open" on POSIX systems, or ""CreateFile" + * on Windows. + * + * While the device file name is a complex string under Windows, + * under Linux and similar systems this is just a device node name + * like "/dev/mbgclock0" which can easily be used to specify a + * particular device. See ::MBG_DEV_FN. + * + * On such systems the function ::mbg_open_device_by_dev_fn can be used + * to open a device specified by a device file name. + * + * @see ::mbg_open_device + * @see ::mbg_find_devices + * @see ::mbg_open_device_by_name + * @see ::mbg_find_devices_with_names + * @see ::mbg_open_device_by_dev_fn + * @see ::mbg_close_device + */ - @return The version number - @see ::MBGDEVIO_VERSION defined in mbgdevio.h. - */ - _MBG_API_ATTR int _MBG_API mbgdevio_get_version( void ) ; +/** + * @defgroup mbgdevio_hr_time_fncs API functions reading high resolution time, plus status + * + * These functions return a high resolution time, including status flags and + * local time offset according to the time zone configuration on the device. + * + * The API call ::mbg_chk_dev_has_hr_time checks if these functions are supported + * by a device. + * + * Due to the extended information returned to the caller these function + * require interaction with the on-board microcontroller, and thus take + * longer to execute than the @ref mbgdevio_fast_timestamp_fncs. + * + * <b>Note:</b> These API calls provides better accuracy and higher resolution + * than the the standard functions in @ref mbgdevio_legacy_time_fncs. + * + * The ::mbg_get_hr_time function doesn't account for the latency + * which is introduced when accessing the board. + * + * The ::mbg_get_hr_time_cycles and ::mbg_get_hr_time_comp calls + * provide ways to account for and/or compensate the latency. + * + * @see ::mbg_chk_dev_has_hr_time + * @see ::mbg_get_hr_time + * @see ::mbg_get_hr_time_cycles + * @see ::mbg_get_hr_time_comp + * @see @ref mbgdevio_fast_timestamp_fncs + * @see @ref mbgdevio_legacy_time_fncs + */ - /** - Check if the version of the compiled mbgdevio library is compatible - with a certain version which is passed as parameter. - @param header_version Version number to be checked, should be ::MBGDEVIO_VERSION - defined in mbgdevio.h. +/** + * @defgroup mbgdevio_fast_timestamp_fncs Fast API functions reading high resolution timestamps, but no status + * + * These functions are fast, but return only the UTC time. No status flags, + * no time zone offset. The time stamps are read from a latched counter chain + * in the PCI chip set, so this is only supported by cards whose chip set supports this. + * + * @see ::mbg_chk_dev_has_fast_hr_timestamp + * @see ::mbg_get_fast_hr_timestamp + * @see ::mbg_get_fast_hr_timestamp_cycles + * @see ::mbg_get_fast_hr_timestamp_comp + * @see @ref mbgdevio_hr_time_fncs + * @see @ref mbgdevio_legacy_time_fncs + */ - @return ::MBG_SUCCESS if compatible, ::MBG_ERR_LIB_NOT_COMPATIBLE if not. - @see ::MBGDEVIO_VERSION defined in mbgdevio.h. - */ - _MBG_API_ATTR int _MBG_API mbgdevio_check_version( int header_version ) ; +/** + * @defgroup mbgdevio_legacy_time_fncs Legacy API functions to read the time + * + * These functions are supported by all devices, but return time only + * as a ::PCPS_TIME structure, which provides local time according to the + * local time zone configured on the device, and with 10 ms resolution only. + * + * <b>Note:</b> The @ref mbgdevio_hr_time_fncs or @ref mbgdevio_fast_timestamp_fncs + * should be used preferably, if the device supports these. + * + * @see ::mbg_get_time + * @see ::mbg_get_time_cycles + * @see @ref mbgdevio_hr_time_fncs + * @see @ref mbgdevio_fast_timestamp_fncs + */ - /** - Open a device by index, starting from 0. - This function is <b>out of date</b>, mbg_open_device_by_name() - should be used instead. - See the <b>note</b> for mbg_find_device() for details. +/** + * @defgroup mbgdevio_chk_supp_fncs mbgdevio functions used to check if a particular feature is supported + * @ingroup chk_supp_fncs + * + * These functions can be used to check if a device supports a particular feature. + * + * ::MBG_SUCCESS is returned if the requested feature is supported, + * ::MBG_ERR_NOT_SUPP_BY_DEV if the feature is not supported, or one of the other + * @ref MBG_ERROR_CODES is returned if an error occurred when trying to determine + * if the feature is supported, e.g. if the IOCTL call itself failed. + */ - @param device_index Index of the device, use 0 for the first device. - */ - _MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device( unsigned int device_index ) ; - /** - Get the number of supported devices installed on the computer. - This function is <b>out of date</b>, mbg_find_devices_with_names() - should be used instead. +/** + * @defgroup mbgdevio_chk_supp_fncs_deprecated Deprecated mbgdevio functions to check if a particular feature is supported + * @ingroup chk_supp_fncs + * + * @deprecated These functions are deprecated. Use the @ref mbgdevio_chk_supp_fncs preferably. + * + * These are the original functions that were introduced to check if a device supports + * a particular feature. The functions are deprecated, but will be kept for compatibility. + * + * The functions return ::MBG_SUCCESS if the information could be retrieved with out error, + * and an error code otherwise, e.g. if the IOCTL call itself failed. + * + * Only in case of success an integer variable the address of which has to be passed to the + * function is set to 1 or 0 depending on whether the requested feature is supported, or not. + * So the calling application always has to check 2 values after such function had been called. + * + * To make applications simpler the @ref mbgdevio_chk_supp_fncs have been introduced instead, + * which can be used in a much easier way. + * + * @see @ref mbgdevio_chk_supp_fncs + */ - <b>Note:</b> This function is out of date since it may not work - correctly for Meinberg devices which are disconnected and reconnected - while the system is running (e.g. USB devices). However, the function - will be kept for compatibility reasons and works correctly if all - Meinberg devices are connected at system boot and are not disconnected - and reconnected during operation - @return The number of devices found. - @see mbg_find_devices_with_names() - */ - _MBG_API_ATTR int _MBG_API mbg_find_devices( void ) ; +/** + * @defgroup mbg_xhrt_poll_group Extrapolation of high resolution time stamps + * + * ::TODO + */ - /** - Return the number of supported devices installed on the system and - set up a list of unique names of those devices. - This function should be used preferably instead of mbg_find_devices(). - @param device_list Pointer to a linked list of type ::MBG_DEVICENAME_LIST - with device names. The list will be allocated by this - function and has to be freed after usage by calling - mbg_free_device_name_list(). - @param max_devices Maximum number of devices the function should look for - (can not exceed ::MBG_MAX_DEVICES). +/** + * @brief The type of functions to check if a feature is supported + * + * @ingroup mbgdevio_chk_supp_fncs + * @see @ref mbgdevio_chk_supp_fncs + */ +typedef int _MBG_API MBG_CHK_SUPP_FNC( MBG_DEV_HANDLE dh ); - @return Number of present devices - @see ::MBG_HW_NAME for the format of the unique names - @see mbg_free_device_name_list() - @see mbg_find_devices() - */ - _MBG_API_ATTR int _MBG_API mbg_find_devices_with_names( MBG_DEVICENAME_LIST **device_list, int max_devices ) ; - /** - Free the memory of the ::MBG_DEVICENAME_LIST that has been allocated before - by mbg_find_devices_with_names(). - @param *list Linked list of type ::MBG_DEVICENAME_LIST +/* ----- function prototypes begin ----- */ - @see mbg_find_devices_with_names() - */ - _MBG_API_ATTR void _MBG_API mbg_free_device_name_list( MBG_DEVICENAME_LIST *list) ; +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ /** - Return a handle to a device with a certain unique name. - The names of the devices that are installed on the system can be retrieved by - the function mbg_find_devices_with_names(). - - This function should be used preferably instead of mbg_open_device(). + * @brief Get the version number of the precompiled DLL/shared object library + * + * If this library is used as a DLL/shared object library then the version + * number can be checked to see if the header files which are actually used + * to build an application are compatible with the header files which have + * been used to build the library, and thus the API function are called + * in the correct way. + * + * @return The version number + * + * @see ::mbgdevio_check_version + * @see ::MBGDEVIO_VERSION defined in mbgdevio.h + */ + _MBG_API_ATTR int _MBG_API mbgdevio_get_version( void ) ; - @param hw_name String with the unique name of the device to be opened - @param selection_mode One of the enum values of ::MBG_MATCH_MODE + /** + * @brief Check if the DLL/shared library is compatible with a given version + * + * If this library is used as a DLL/shared object library then the version + * number can be checked to see if the header files which are actually used + * to build an application are compatible with the header files which have + * been used to build the library, and thus the API functions are called + * in the correct way. + * + * @param[in] header_version Version number to be checked, should be ::MBGDEVIO_VERSION + * from the mbgdevio.h file version used to build the application + * + * @return ::MBG_SUCCESS if compatible, else ::MBG_ERR_LIB_NOT_COMPATIBLE + * + * @see ::mbgdevio_get_version + * @see ::MBGDEVIO_VERSION defined in mbgdevio.h + */ + _MBG_API_ATTR int _MBG_API mbgdevio_check_version( int header_version ) ; - @return On success, the function returns a handle to the device, otherwise ::MBG_INVALID_DEV_HANDLE + /** + * @brief Check if a device supports the ::RECEIVER_INFO structure and related calls. + * + * Very old devices may not provide a ::RECEIVER_INFO structure. + * The ::mbg_setup_receiver_info call should be used preferably to set up + * a ::RECEIVER_INFO for a device. That function uses this call to determine + * whether a ::RECEIVER_INFO can be read directly from a device, or sets up + * a default structure using default values depending on the device type. + * + * @note This function should be preferred over ::mbg_dev_has_receiver_info, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_setup_receiver_info + * @see ::mbg_get_gps_receiver_info + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_receiver_info( MBG_DEV_HANDLE dh ) ; - @see ::MBG_HW_NAME for the format of the unique names. - @see ::MBG_MATCH_MODE - @see mbg_find_devices_with_names() - */ - _MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device_by_name( const char* hw_name, int selection_mode ) //##++++ -; + /** + * @brief Check if a device supports large configuration data structures. + * + * Such structures have been introduced with the first Meinberg GPS receivers. + * Mostly all configuration structures are large data structures, and mostly all + * current devices support this, but some old devices may not. + * + * @note This function should be preferred over ::mbg_dev_has_gps_data, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_gps_data( MBG_DEV_HANDLE dh ) ; /** - Close a handle to a device and set the handle value to ::MBG_INVALID_DEV_HANDLE. - If required, unmap mapped memory. + * @brief Check if a device supports the ::mbg_generic_io API call. + * + * <b>Warning</b>: This call is for debugging purposes and internal use only! + * + * @note This function should be preferred over ::mbg_dev_has_generic_io, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_generic_io + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_generic_io( MBG_DEV_HANDLE dh ) ; - @param dev_handle Handle to a Meinberg device. - */ - _MBG_API_ATTR void _MBG_API mbg_close_device( MBG_DEV_HANDLE *dev_handle ) ; + /** + * @brief Check if a device supports the ::mbg_get_asic_version API call. + * + * If ::mbg_get_asic_version is supported, or not, depends on + * the bus interface chip assembled on the device. + * + * @note This function should be preferred over ::mbg_dev_has_asic_version, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_asic_version + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_asic_version( MBG_DEV_HANDLE dh ) ; /** - Return a ::PCPS_DRVR_INFO structure that provides information - about the kernel device driver. + * @brief Check if a device supports the ::mbg_get_asic_features call. + * + * If ::mbg_get_asic_features is supported, or not, depends on + * the bus interface chip assembled on the device. + * + * @note This function should be preferred over ::mbg_dev_has_asic_features, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_asic_features + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_asic_features( MBG_DEV_HANDLE dh ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_DRVR_INFO structure which is filled up. + /** + * @brief Check if a device provides eXtended Multi Ref (XMR) inputs. + * + * Devices providing XMR inputs can receive or decode different timing + * signals in parallel, and the supported sources can be prioritized. + * + * @note This function should be preferred over ::mbg_dev_has_xmr, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_xmr_instances + * @see ::mbg_get_gps_all_xmr_status + * @see ::mbg_get_gps_all_xmr_info + * @see ::mbg_set_gps_xmr_settings_idx + * @see ::mbg_get_xmr_holdover_status + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_xmr( MBG_DEV_HANDLE dh ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function - */ - _MBG_API_ATTR int _MBG_API mbg_get_drvr_info( MBG_DEV_HANDLE dh, PCPS_DRVR_INFO *p ) ; + /** + * @brief Check if the device is connected via the ISA bus + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the device is connected via the ISA bus, + * else ::MBG_ERR_NOT_SUPP_BY_DEV + * + * @ingroup mbgdevio_chk_supp_fncs + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_isa( MBG_DEV_HANDLE dh ) ; /** - Return a ::PCPS_DEV structure that provides detailed information about the device. + * @brief Check if the device is connected via the MCA bus + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the device is connected via the MCA bus, + * else ::MBG_ERR_NOT_SUPP_BY_DEV + * + * @ingroup mbgdevio_chk_supp_fncs + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_mca( MBG_DEV_HANDLE dh ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_DEV structure to be filled up + /** + * @brief Check if the device is connected via the PCI bus + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the device is connected via the PCI bus, + * else ::MBG_ERR_NOT_SUPP_BY_DEV + * + * @ingroup mbgdevio_chk_supp_fncs + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_pci( MBG_DEV_HANDLE dh ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function - */ - _MBG_API_ATTR int _MBG_API mbg_get_device_info( MBG_DEV_HANDLE dh, PCPS_DEV *p ) ; + /** + * @brief Check if the device is connected via the PCI Express bus + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the device is connected via the PCI Express bus, + * else ::MBG_ERR_NOT_SUPP_BY_DEV + * + * @ingroup mbgdevio_chk_supp_fncs + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_pci_express( MBG_DEV_HANDLE dh ) ; /** - Return the current state of the on-board::PCPS_STATUS_PORT. + * @brief Check if the device is connected via the USB bus + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the device is connected via the USB bus, + * else ::MBG_ERR_NOT_SUPP_BY_DEV + * + * @ingroup mbgdevio_chk_supp_fncs + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_usb( MBG_DEV_HANDLE dh ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_STATUS_PORT value to be filled up + /** + * @brief Check if a device supports GNSS configuration + * + * This is usually the case if a device supports reception of + * different satellite systems, e.g. GPS, Glonass, Galileo, etc. + * + * @note This function should be preferred over ::mbg_dev_is_gnss, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_gps_gnss_mode_info + * @see ::mbg_set_gps_gnss_mode_settings + * @see ::mbg_get_gps_all_gnss_sat_info + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_gnss( MBG_DEV_HANDLE dh ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function + /** + * @brief Check if a device is a GPS receiver + * + * The function also returns ::MBG_SUCCESS for GNSS receivers + * which can track GPS satellites beside other GNSS systems. + * + * @note This function should be preferred over ::mbg_dev_is_gps, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_gps( MBG_DEV_HANDLE dh ) ; - @see \ref group_status_port "bitmask" - */ - _MBG_API_ATTR int _MBG_API mbg_get_status_port( MBG_DEV_HANDLE dh, PCPS_STATUS_PORT *p ) ; + /** + * @brief Check if a device is a DCF77 receiver. + * + * Beside standard DCF77 receivers which receive the legacy AM signal + * there are also PZF receivers which can decode the pseudo-random phase + * modulation and thus yield a higher accuracy. See ::mbg_chk_dev_has_pzf. + * + * @note This function should be preferred over ::mbg_dev_is_dcf, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_has_pzf + * @see ::mbg_chk_dev_is_lwr + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_dcf( MBG_DEV_HANDLE dh ) ; - /* (Intentionally excluded from Doxygen) - Generic read function which writes a command code to the device - and reads a number of replied data to a generic buffer. + /** + * @brief Check if a device supports demodulation of the DCF77 PZF code + * + * Beside the enhanced PZF correlation receivers which decode the DCF77's + * pseudo-random phase modulation to yield a better accuracy there are also + * legacy DCF77 receivers which just decode the standard AM signal. + * See ::mbg_chk_dev_is_dcf. + * + * @note This function should be preferred over ::mbg_dev_has_pzf, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_has_corr_info + * @see ::mbg_chk_dev_has_tr_distance + * @see ::mbg_chk_dev_is_dcf + * @see ::mbg_chk_dev_is_lwr + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_pzf( MBG_DEV_HANDLE dh ) ; - <b>Warning</b>: This is for debugging purposes only! - The specialized API calls should be used preferably. - A specific device may not support any command code. + /** + * @brief Check if a device is a MSF receiver + * + * @note This function should be preferred over ::mbg_dev_is_msf, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_is_lwr + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_msf( MBG_DEV_HANDLE dh ) ; - @param dh Valid handle to a Meinberg device - @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device - @param *p Pointer to a buffer to be filled up - @param size Size of the buffer *p + /** + * @brief Check if a device is a WWVB receiver + * + * @note This function should be preferred over ::mbg_dev_is_wwvb, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_is_lwr + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_wwvb( MBG_DEV_HANDLE dh ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device is a JJY receiver. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_is_lwr + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_jjy( MBG_DEV_HANDLE dh ) ; - @see mbg_generic_write() - @see mbg_generic_read_gps() - @see mbg_generic_write_gps() - @see mbg_generic_io() - */ - _MBG_API_ATTR int _MBG_API mbg_generic_read( MBG_DEV_HANDLE dh, int cmd, void *p, int size ) ; + /** + * @brief Check if a device is any long wave signal receiver + * + * Long wave receivers include e.g. DCF77, MSF, WWVB, or JJY. + * + * @note This function should be preferred over ::mbg_dev_is_lwr, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_is_dcf + * @see ::mbg_chk_dev_is_msf + * @see ::mbg_chk_dev_is_wwvb + * @see ::mbg_chk_dev_is_jjy + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_lwr( MBG_DEV_HANDLE dh ) ; - /* (Intentionally excluded from Doxygen) - Generic read function which writes a GPS command code to the device - and reads a number of replied data to a generic buffer. - The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data() - check whether this call is supported by a specific card. - - <b>Warning</b>: This is for debugging purposes only! - The specialized API calls should be used preferably. - A specific device may not support any GPS command code. - - @param dh Valid handle to a Meinberg device - @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device. - @param *p Pointer to a buffer to be filled up - @param size Size of the buffer *p - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_gps_data() - @see mbg_generic_write_gps() - @see mbg_generic_read() - @see mbg_generic_write() - @see mbg_generic_io() - */ - _MBG_API_ATTR int _MBG_API mbg_generic_read_gps( MBG_DEV_HANDLE dh, int cmd, void *p, int size ) ; + /** + * @brief Check if a device provides a configurable IRIG input. + * + * @note This function should be preferred over ::mbg_dev_is_irig_rx, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_irig_rx_info + * @see ::mbg_set_irig_rx_settings + * @see ::mbg_chk_dev_has_irig_tx + * @see ::mbg_chk_dev_has_irig +*/ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_is_tcr( MBG_DEV_HANDLE dh ) ; - /* (Intentionally excluded from Doxygen) - Generic write function which writes a command code plus an - associated number of data bytes to the device. + /** + * @brief Check if a device supports simple LAN interface API calls + * + * @note This function should be preferred over ::mbg_dev_has_lan_intf, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_lan_if_info + * @see ::mbg_get_ip4_state + * @see ::mbg_get_ip4_settings + * @see ::mbg_set_ip4_settings + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_lan_intf( MBG_DEV_HANDLE dh ) ; - <b>Warning</b>: This is for debugging purposes only! - The specialized API calls should be used preferably. - A specific device may not support any command code. + /** + * @brief Check if a device supports PTP configuration/status calls + * + * @note This function should be preferred over ::mbg_dev_has_ptp, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_state + * @see ::mbg_get_ptp_cfg_info + * @see ::mbg_set_ptp_cfg_settings + * @see ::mbg_chk_dev_has_ptp_unicast + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_ptp( MBG_DEV_HANDLE dh ) ; - @param dh Valid handle to a Meinberg device - @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device. - @param *p Pointer to a buffer to be written - @param size Size of the buffer *p + /** + * @brief Check if a device supports PTP unicast feature/configuration + * + * Not all devices which support PTP do also support PTP Unicast. This API + * call checks if PTP Unicast is supported in addition to the standard + * PTP multicast. + * + * @note This function should be preferred over ::mbg_dev_has_ptp_unicast, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_uc_master_cfg_limits + * @see ::mbg_get_all_ptp_uc_master_info + * @see ::mbg_set_ptp_uc_master_settings_idx + * @see ::mbg_get_ptp_state + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_ptp_unicast( MBG_DEV_HANDLE dh ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device supports the mbg_get_hr_time... functions + * + * @note This function should be preferred over ::mbg_dev_has_hr_time, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_hr_time + * @see ::mbg_get_hr_time_cycles + * @see ::mbg_get_hr_time_comp + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_hr_time( MBG_DEV_HANDLE dh ) ; - @see mbg_generic_read() - @see mbg_generic_read_gps() - @see mbg_generic_write_gps() - @see mbg_generic_io() - */ - _MBG_API_ATTR int _MBG_API mbg_generic_write( MBG_DEV_HANDLE dh, int cmd, const void *p, int size ) ; + /** + * @brief Check if a device supports the mbg_get_fast_hr_timestamp... calls + * + * @note This function should be preferred over ::mbg_dev_has_fast_hr_timestamp, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_fast_hr_timestamp_cycles + * @see ::mbg_get_fast_hr_timestamp_comp + * @see ::mbg_get_fast_hr_timestamp + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_fast_hr_timestamp( MBG_DEV_HANDLE dh ) ; - /* (Intentionally excluded from Doxygen) - Generic write function which writes a GPS command code plus an - associated number of data bytes to the device. - The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data() - check whether this call is supported by a specific card. - - <b>Warning</b>: This is for debugging purposes only! - The specialized API calls should be used preferably. - A specific device may not support any GPS command code. - - @param dh Valid handle to a Meinberg device - @param cmd Can be any \ref group_cmd_bytes "command byte" supported by the device. - @param *p Pointer to a buffer to be written - @param size Size of the buffer *p - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_gps_data() - @see mbg_generic_read_gps() - @see mbg_generic_read() - @see mbg_generic_write() - @see mbg_generic_io() - */ - _MBG_API_ATTR int _MBG_API mbg_generic_write_gps( MBG_DEV_HANDLE dh, int cmd, const void *p, int size ) ; + /** + * @brief Check if a device supports configurable time scales. + * + * By default the devices return %UTC and/or local time. However, some cards + * can be configured to return raw GPS time or TAI instead. + * + * @note This function should be preferred over ::mbg_dev_has_time_scale, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_time_scale_info + * @see ::mbg_set_time_scale_settings + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_time_scale( MBG_DEV_HANDLE dh ) ; /* (Intentionally excluded from Doxygen) - Write and/or read generic data to/from a device. - The macro _pcps_has_generic_io() or the API call mbg_dev_has_generic_io() - check whether this call is supported by a specific card. + * @brief Check if a device supports setting an event time + * + * This feature is only supported by some special custom firmware + * to preset a %UTC time at which the clock is to generate an output signal. + * + * @note This function should be preferred over ::mbg_dev_has_event_time, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_set_event_time + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_event_time( MBG_DEV_HANDLE dh ) ; - <b>Warning</b>: This call is for debugging purposes and internal use only! + /** + * @brief Check if a device supports the ::mbg_get_ucap_entries and ::mbg_get_ucap_event calls + * + * If the device doesn't support this but is a GPS card then the card provides + * a time capture FIFO buffer and the obsolete ::mbg_get_gps_ucap call can be used + * to retrieve entries from the FIFO buffer. + * + * @note This function should be preferred over ::mbg_dev_has_ucap, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_ucap_entries + * @see ::mbg_get_ucap_event + * @see ::mbg_clr_ucap_buff + * @see ::mbg_get_gps_ucap + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_ucap( MBG_DEV_HANDLE dh ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device supports the ::mbg_clr_ucap_buff call + * + * The ::mbg_clr_ucap_buff call can be used to clear a device's on-board + * time capture FIFO buffer, but the call may not be supported by some + * older GPS devices. + * + * @note This function should be preferred over ::mbg_dev_can_clr_ucap_buff, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_clr_ucap_buff + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_can_clr_ucap_buff( MBG_DEV_HANDLE dh ) ; - @see mbg_dev_has_generic_io() - @see mbg_generic_read() - @see mbg_generic_write() - @see mbg_generic_read_gps() - @see mbg_generic_write_gps() - */ - _MBG_API_ATTR int _MBG_API mbg_generic_io( MBG_DEV_HANDLE dh, int type, const void *in_p, int in_sz, void *out_p, int out_sz ) ; + /** + * @brief Check if a device supports timezone configuration using the ::TZDL structure + * + * @note This function should be preferred over ::mbg_dev_has_tzdl, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_gps_tzdl + * @see ::mbg_set_gps_tzdl + * @see ::mbg_chk_dev_has_tz + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_tzdl( MBG_DEV_HANDLE dh ) ; /** - Read a ::PCPS_TIME structure returning the current date/time/status. - The returned time is local time according to the card's time zone setting, - with a resolution of 10 ms (i.e. 10ths of seconds). + * @brief Check if a device supports timezone configuration using the ::PCPS_TZDL structure + * + * @note This function should be preferred over ::mbg_dev_has_pcps_tzdl, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_pcps_tzdl + * @see ::mbg_set_pcps_tzdl + * @see ::mbg_chk_dev_has_tz + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_pcps_tzdl( MBG_DEV_HANDLE dh ) ; - This call is supported by any device manufactured by Meinberg. However, - for higher accuracy and resolution the mbg_get_hr_time..() group of calls - should be used preferably if supported by the specific device. + /** + * @brief Check if a device supports timezone configuration using the ::PCPS_TZCODE type. + * + * @note This function should be preferred over ::mbg_dev_has_tzcode, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_tzcode + * @see ::mbg_set_tzcode + * @see ::mbg_chk_dev_has_tz + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_tzcode( MBG_DEV_HANDLE dh ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME structure to be filled up + /** + * @brief Check if a device supports any kind of timezone configuration. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @note This function should be preferred over ::mbg_dev_has_tz, + * which has been deprecated. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_has_tzdl + * @see ::mbg_chk_dev_has_pcps_tzdl + * @see ::mbg_chk_dev_has_tzcode + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_tz( MBG_DEV_HANDLE dh ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device provides either an IRIG input or output. + * + * @note This function should be preferred over ::mbg_dev_has_irig, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_is_tcr + * @see ::mbg_chk_dev_has_irig_tx + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_irig( MBG_DEV_HANDLE dh ) ; - @see mbg_get_hr_time() - @see mbg_set_time() - @see mbg_get_sync_time() - */ - _MBG_API_ATTR int _MBG_API mbg_get_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ; + /** + * @brief Check if a device provides a configurable IRIG output. + * + * @note This function should be preferred over ::mbg_dev_has_irig, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_irig_tx_info + * @see ::mbg_set_irig_tx_settings + * @see ::mbg_chk_dev_is_tcr + * @see ::mbg_chk_dev_has_irig + * @see @ref group_icode + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_irig_tx( MBG_DEV_HANDLE dh ) ; /** - Set a device's on-board clock manually by passing a ::PCPS_STIME structure - The macro _pcps_can_set_time() checks whether this call - is supported by a specific card. + * @brief Check if a device supports the ::mbg_get_irig_ctrl_bits call + * + * @note This function should be preferred over ::mbg_dev_has_irig_ctrl_bits, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_irig_ctrl_bits + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_irig_ctrl_bits( MBG_DEV_HANDLE dh ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_STIME structure to be written + /** + * @brief Check if a device supports the ::mbg_get_raw_irig_data call + * + * @note This function should be preferred over ::mbg_dev_has_raw_irig_data, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_raw_irig_data + * @see ::mbg_get_raw_irig_data_on_sec_change + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_raw_irig_data( MBG_DEV_HANDLE dh ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device supports the ::mbg_get_irig_time call + * + * @note This function should be preferred over ::mbg_dev_has_irig_time, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_irig_time + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_irig_time( MBG_DEV_HANDLE dh ) ; - @see mbg_get_time() - */ - _MBG_API_ATTR int _MBG_API mbg_set_time( MBG_DEV_HANDLE dh, const PCPS_STIME *p ) ; + /** + * @brief Check if a device provides the level of its inputs signal + * + * This is useful to display the signal level of e.g. an IRIG or similar + * time code, or a long wave signal. + * + * @note This function should be preferred over ::mbg_dev_has_signal, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_signal( MBG_DEV_HANDLE dh ) ; /** - Read a ::PCPS_TIME structure returning the date/time/status reporting - when the device was synchronized the last time to its time source, - e.g. the DCF77 signal or the GPS satellites. - The macro _pcps_has_sync_time() or the API call mbg_dev_has_sync_time() - check whether this call is supported by a specific card. + * @brief Check if a device provides a modulation signal + * + * Modulation signals are e.g. the second marks provided by a long wave receiver. + * + * @note This function should be preferred over ::mbg_dev_has_mod, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_mod( MBG_DEV_HANDLE dh ) ; - The macro _pcps_has_sync_time() checks whether this call - is supported by a specific card. + /* (Intentionally excluded from Doxygen) + * @brief Check if a device supports higher baud rates than usual + * + * Check if a device provides a serial output that supports + * higher baud rates than older cards, i.e. ::DEFAULT_BAUD_RATES_DCF_HS + * rather than ::DEFAULT_BAUD_RATES_DCF. + * + * The call ::mbg_get_serial_settings takes care of this, so applications + * which use that call as suggested don't need to use this call directly. + * + * @note This function should be preferred over ::mbg_dev_has_serial_hs, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_serial_settings + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_serial_hs( MBG_DEV_HANDLE dh ) ; - <b>Note:</b> If that information is not available on the board then - the value of the returned ::PCPS_TIME::sec field is set to 0xFF. - The macro _pcps_time_is_read() can be used to check whether the - returned information is valid, or not available. + /** + * @brief Check if a device provides a programmable frequency synthesizer + * + * @note This function should be preferred over ::mbg_dev_has_synth, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_synth + * @see ::mbg_set_synth + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_synth( MBG_DEV_HANDLE dh ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME structure to be filled up + /** + * @brief Check if a device provides GPIO signal inputs and/or outputs + * + * @note This function should be preferred over ::mbg_dev_has_gpio, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_gpio_cfg_limits + * @see ::mbg_get_gps_all_gpio_info + * @see ::mbg_set_gps_gpio_settings_idx + * @see ::mbg_get_gps_all_gpio_status + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_gpio( MBG_DEV_HANDLE dh ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device supports configuration of antenna cable length + * + * @note This function should be preferred over ::mbg_dev_has_cab_len, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_gps_ant_cable_len + * @see ::mbg_set_gps_ant_cable_len + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_cab_len( MBG_DEV_HANDLE dh ) ; - @see mbg_get_time() - */ - _MBG_API_ATTR int _MBG_API mbg_get_sync_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ; + /** + * @brief Check if a device provides a configurable ref time offset + * + * This may be required to convert the received time to %UTC, if the input + * signal doesn't specify this (e.g. with most IRIG code formats). + * + * @note This function should be preferred over ::mbg_dev_has_ref_offs, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_ref_offs + * @see ::mbg_set_ref_offs + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_ref_offs( MBG_DEV_HANDLE dh ) ; /** - Wait until the next second change, then return a ::PCPS_TIME - structure similar to mbg_get_time(). + * @brief Check if a device supports the ::MBG_OPT_INFO/::MBG_OPT_SETTINGS. + * + * These structures contain optional settings, controlled by flags. + * See ::MBG_OPT_SETTINGS and associated definitions. + * + * @note This function should be preferred over ::mbg_dev_has_opt_flags, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_opt_info + * @see ::mbg_set_opt_settings + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_opt_flags( MBG_DEV_HANDLE dh ) ; - <b>Note:</b> This API call is supported under Windows only. - The call blocks until the kernel driver detects a second change - reported by the device. + /** + * @brief Check if a device support reading/writing of UTC parameters. + * + * This API call checks if a device supports reading/writing a GPS %UTC + * parameter set via the PC bus. Reading/writing these parameters via the + * serial port using the Meinberg binary data protocol is supported by all + * Meinberg GPS and GNSS devices. + * + * The %UTC parameter set is usually received from the satellites' broadcasts + * and contains the current time offset between GPS time and UTC, plus information + * on a pending leap second event. + * + * It may be useful to overwrite them to do some tests, or for applications + * where a card is freewheeling. + * + * @note This function should be preferred over ::mbg_dev_has_utc_parm, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_utc_parm + * @see ::mbg_set_utc_parm + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_utc_parm( MBG_DEV_HANDLE dh ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME structure to be filled up + /** + * @brief Check if a device supports reading correlation info + * + * The PZF phase modulation decoded by DCF77 PZF receivers is decoded + * using a correlation approach, and optionally there's an API call + * supported which can be used to retrieve the correlation value + * and thus determine the quality of the input signal. + * + * @note This function should be preferred over ::mbg_dev_has_corr_info, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_has_pzf + * @see ::mbg_get_corr_info + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_corr_info( MBG_DEV_HANDLE dh ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device supports configurable distance from transmitter + * + * The distance from transmitter parameter is used to compensate + * the RF propagation delay, mostly with long wave receivers. + * + * @note This function should be preferred over ::mbg_dev_has_tr_distance, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_chk_dev_has_pzf + * @see ::mbg_get_tr_distance + * @see ::mbg_set_tr_distance + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_tr_distance( MBG_DEV_HANDLE dh ) ; - @see mbg_get_time() - */ - _MBG_API_ATTR int _MBG_API mbg_get_time_sec_change( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ; + /** + * @brief Check if a device provides a debug status word to be read + * + * @note This function should be preferred over ::mbg_dev_has_debug_status, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_get_debug_status + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_debug_status( MBG_DEV_HANDLE dh ) ; /** - Read a ::PCPS_HR_TIME (High Resolution time) structure returning - the current %UTC time (seconds since 1970), %UTC offset, and status. - The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() - check whether this call is supported by a specific card. + * @brief Check if a device provides an on-board event log + * + * @note This function should be preferred over ::mbg_dev_has_evt_log, + * which has been deprecated. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs + * @see ::mbg_clr_evt_log + * @see ::mbg_get_num_evt_log_entries + * @see ::mbg_get_first_evt_log_entry + * @see ::mbg_get_next_evt_log_entry + */ + _MBG_API_ATTR int _MBG_API mbg_chk_dev_has_evt_log( MBG_DEV_HANDLE dh ) ; - <b>Note:</b> This API call provides a higher accuracy and resolution - than mbg_get_time(). However, it does not account for the latency - which is introduced when accessing the board. - The mbg_get_hr_time_cycles() and mbg_get_hr_time_comp() calls - provides mechanisms to account for and/or compensate the latency. + /** + * @brief Check if a device supports the ::RECEIVER_INFO structure and related calls + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_receiver_info preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_receiver_info + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_receiver_info" ) _MBG_API mbg_dev_has_receiver_info( MBG_DEV_HANDLE dh, int *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up + /** + * @brief Check if a device supports large configuration data structures + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_gps_data preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_gps_data + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_gps_data" ) _MBG_API mbg_dev_has_gps_data( MBG_DEV_HANDLE dh, int *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device supports the ::mbg_generic_io API call + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_generic_io preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_generic_io + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_generic_io" ) _MBG_API mbg_dev_has_generic_io( MBG_DEV_HANDLE dh, int *p ) ; - @see mbg_dev_has_hr_time() - @see mbg_get_time() - @see mbg_get_hr_time_cycles() - @see mbg_get_hr_time_comp() - */ - _MBG_API_ATTR int _MBG_API mbg_get_hr_time( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p ) ; + /** + * @brief Check if a device supports the ::mbg_get_asic_version call + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_asic_version preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_asic_version + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_asic_version" ) _MBG_API mbg_dev_has_asic_version( MBG_DEV_HANDLE dh, int *p ) ; - /* (Intentionally excluded from Doxygen ) - Write a high resolution time stamp ::PCPS_TIME_STAMP to the clock - to configure a %UTC time when the clock shall generate an event. - The macro _pcps_has_event_time() or the API call mbg_dev_has_event_time() - check whether this call is supported by a specific card. + /** + * @brief Check if a device supports the ::mbg_get_asic_features call. + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_asic_features preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_asic_features + * @see ::mbg_get_asic_features + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_asic_features" ) _MBG_API mbg_dev_has_asic_features( MBG_DEV_HANDLE dh, int *p ) ; - <b>Note:</b> This is only supported by some special firmware. + /** + * @brief Check if a device provides extended multi ref (XMR) inputs. + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_xmr preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_xmr + * @see @ref group_multi_ref_ext + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_xmr" ) _MBG_API mbg_dev_has_xmr( MBG_DEV_HANDLE dh, int *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME_STAMP structure to be written + /** + * @brief Check if a device supports GNSS configuration + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_gnss preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_gnss + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_gnss" ) _MBG_API mbg_dev_is_gnss( MBG_DEV_HANDLE dh, int *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device is a GPS receiver + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_gps preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_gps + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_gps" ) _MBG_API mbg_dev_is_gps( MBG_DEV_HANDLE dh, int *p ) ; - @see mbg_dev_has_event_time() - */ - _MBG_API_ATTR int _MBG_API mbg_set_event_time( MBG_DEV_HANDLE dh, const PCPS_TIME_STAMP *p ) ; + /** + * @brief Check if a device is a DCF77 receiver + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_dcf preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_dcf + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_dcf" ) _MBG_API mbg_dev_is_dcf( MBG_DEV_HANDLE dh, int *p ) ; /** - Read the configuration of a device's serial port. - The macro _pcps_has_serial() checks whether this call - is supported by a specific card. + * @brief Check if a device supports demodulation of the DCF77 PZF code + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_pzf preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_pzf + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_pzf" ) _MBG_API mbg_dev_has_pzf( MBG_DEV_HANDLE dh, int *p ) ; - <b>Note:</b> This function is supported only by a certain class - of devices, so it should not be called directly. The generic - function mbg_get_serial_settings() should be used instead. + /** + * @brief Check if a device is a MSF receiver + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_msf preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_msf + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_msf" ) _MBG_API mbg_dev_is_msf( MBG_DEV_HANDLE dh, int *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_SERIAL structure to be filled up + /** + * @brief Check if a device is a WWVB receiver + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_wwvb preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_wwvb + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_wwvb" ) _MBG_API mbg_dev_is_wwvb( MBG_DEV_HANDLE dh, int *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device is any long wave signal receiver + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_lwr preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_lwr + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_lwr" ) _MBG_API mbg_dev_is_lwr( MBG_DEV_HANDLE dh, int *p ) ; - @see \ref group_cmd_bytes - @see mbg_get_serial_settings() - */ - _MBG_API_ATTR int _MBG_API mbg_get_serial( MBG_DEV_HANDLE dh, PCPS_SERIAL *p ) ; + /** + * @brief Check if a device provides a configurable IRIG input. + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_is_tcr preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_is_tcr + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_is_tcr" ) _MBG_API mbg_dev_is_irig_rx( MBG_DEV_HANDLE dh, int *p ) ; /** - Write the configuration of a device's serial port. - The macro _pcps_has_serial() checks whether this call - is supported by a specific card. + * @brief Check if a device supports simple LAN interface API calls + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_lan_intf preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_lan_intf + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_lan_intf" ) _MBG_API mbg_dev_has_lan_intf( MBG_DEV_HANDLE dh, int *p ) ; - <b>Note:</b> This function is supported only by a certain class - of devices, so it should not be called directly. The generic - function mbg_save_serial_settings() should be used instead. + /** + * @brief Check if a device supports PTP configuration/status calls + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_ptp preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_ptp + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_ptp" ) _MBG_API mbg_dev_has_ptp( MBG_DEV_HANDLE dh, int *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_SERIAL structure to be written + /** + * @brief Check if a device supports PTP unicast feature/configuration + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_ptp_unicast preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_ptp_unicast + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_ptp_unicast" ) _MBG_API mbg_dev_has_ptp_unicast( MBG_DEV_HANDLE dh, int *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device supports the HR_TIME functions + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_hr_time preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_hr_time + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_hr_time" ) _MBG_API mbg_dev_has_hr_time( MBG_DEV_HANDLE dh, int *p ) ; - @see \ref group_cmd_bytes - @see mbg_save_serial_settings() - */ - _MBG_API_ATTR int _MBG_API mbg_set_serial( MBG_DEV_HANDLE dh, const PCPS_SERIAL *p ) ; + /** + * @brief Check if a device supports the mbg_get_fast_hr_timestamp_...() calls + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_fast_hr_timestamp preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_fast_hr_timestamp + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_fast_hr_timestamp" ) _MBG_API mbg_dev_has_fast_hr_timestamp( MBG_DEV_HANDLE dh, int *p ) ; /** - Read the card's time zone/daylight saving configuration code. - That tzcode is supported by some simpler cards and only allows only - a very basic configuration. - The macro _pcps_has_tzcode() or the API call mbg_dev_has_tzcode() - check whether this call is supported by a specific card. - Other cards may support the mbg_get_pcps_tzdl() or mbg_get_gps_tzdl() - calls instead which allow for a more detailed configuration of the - time zone and daylight saving settings. + * @brief Check if a device supports configurable time scales + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_time_scale preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_time_scale + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_time_scale" ) _MBG_API mbg_dev_has_time_scale( MBG_DEV_HANDLE dh, int *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TZCODE structure to be filled up + /** + * @brief Check if a device supports setting an event time + * + * @note This is only supported by some customized devices + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_event_time preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_event_time + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_event_time" ) _MBG_API mbg_dev_has_event_time( MBG_DEV_HANDLE dh, int *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device supports the ::mbg_get_ucap_entries and ::mbg_get_ucap_event calls + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_ucap preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_ucap + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_ucap" ) _MBG_API mbg_dev_has_ucap( MBG_DEV_HANDLE dh, int *p ) ; - @see mbg_dev_has_tzcode() - @see mbg_set_tzcode() - @see mbg_get_pcps_tzdl() - @see mbg_get_gps_tzdl() - @see \ref group_cmd_bytes - */ - _MBG_API_ATTR int _MBG_API mbg_get_tzcode( MBG_DEV_HANDLE dh, PCPS_TZCODE *p ) ; + /** + * @brief Check if a device supports the ::mbg_clr_ucap_buff call + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_can_clr_ucap_buff preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_can_clr_ucap_buff + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_can_clr_ucap_buff" ) _MBG_API mbg_dev_can_clr_ucap_buff( MBG_DEV_HANDLE dh, int *p ) ; /** - Write the card's time zone/daylight saving configuration code. - That tzcode is supported by some simpler cards and only allows only - a very basic configuration. - The macro _pcps_has_tzcode() or the API call mbg_dev_has_tzcode() - check whether this call is supported by a specific card. - Other cards may support the mbg_set_pcps_tzdl() or mbg_set_gps_tzdl() - calls instead which allow for a more detailed configuration of the - time zone and daylight saving settings. + * @brief Check if a device supports timezone configuration using the ::TZDL structure + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_tzdl preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_tzdl + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_tzdl" ) _MBG_API mbg_dev_has_tzdl( MBG_DEV_HANDLE dh, int *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TZCODE structure to be written + /** + * @brief Check if a device supports timezone configuration using the ::PCPS_TZDL structure + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_pcps_tzdl preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_pcps_tzdl + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_pcps_tzdl" ) _MBG_API mbg_dev_has_pcps_tzdl( MBG_DEV_HANDLE dh, int *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device supports timezone configuration using the ::PCPS_TZCODE type + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_tzcode preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_tzcode + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_tzcode" ) _MBG_API mbg_dev_has_tzcode( MBG_DEV_HANDLE dh, int *p ) ; - @see mbg_dev_has_tzcode() - @see mbg_get_tzcode() - @see mbg_set_pcps_tzdl() - @see mbg_set_gps_tzdl() - @see \ref group_cmd_bytes - */ - _MBG_API_ATTR int _MBG_API mbg_set_tzcode( MBG_DEV_HANDLE dh, const PCPS_TZCODE *p ) ; + /** + * @brief Check if a device supports any kind of timezone configuration + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_tz preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_tz + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_tz" ) _MBG_API mbg_dev_has_tz( MBG_DEV_HANDLE dh, int *p ) ; /** - Read the card's time zone/daylight saving parameters using the - ::PCPS_TZDL structure. - The macro _pcps_has_pcps_tzdl() or the API call mbg_dev_has_pcps_tzdl() - check whether this call is supported by a specific card. - Other cards may support the mbg_get_tzcode() or mbg_get_gps_tzdl() - calls instead. + * @brief Check if a device provides either an IRIG input or output + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_irig preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_irig + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_irig" ) _MBG_API mbg_dev_has_irig( MBG_DEV_HANDLE dh, int *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TZDL structure to be filled up + /** + * @brief Check if a device provides a configurable IRIG output + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_irig_tx preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_irig_tx + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_irig_tx" ) _MBG_API mbg_dev_has_irig_tx( MBG_DEV_HANDLE dh, int *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device supports the ::mbg_get_irig_ctrl_bits call + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_irig_ctrl_bits preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_irig_ctrl_bits + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_irig_ctrl_bits" ) _MBG_API mbg_dev_has_irig_ctrl_bits( MBG_DEV_HANDLE dh, int *p ) ; - @see mbg_dev_has_pcps_tzdl() - @see mbg_set_pcps_tzdl() - @see mbg_get_tzcode() - @see mbg_get_gps_tzdl() - @see \ref group_cmd_bytes - */ - _MBG_API_ATTR int _MBG_API mbg_get_pcps_tzdl( MBG_DEV_HANDLE dh, PCPS_TZDL *p ) ; + /** + * @brief Check if a device supports the ::mbg_get_raw_irig_data call + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_raw_irig_data preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_raw_irig_data + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_raw_irig_data" ) _MBG_API mbg_dev_has_raw_irig_data( MBG_DEV_HANDLE dh, int *p ) ; /** - Write the card's time zone/daylight saving parameters using the - ::PCPS_TZDL structure. - The macro _pcps_has_pcps_tzdl() or the API call mbg_dev_has_pcps_tzdl() - check whether this call is supported by a specific card. - Other cards may support the mbg_set_tzcode() or mbg_set_gps_tzdl() - calls instead. + * @brief Check if a device supports the ::mbg_get_irig_time call + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_irig_time preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_irig_time + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_irig_time" ) _MBG_API mbg_dev_has_irig_time( MBG_DEV_HANDLE dh, int *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TZDL structure to be written + /** + * @brief Check if a device provides the level of its inputs signal + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_signal preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_signal + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_signal" ) _MBG_API mbg_dev_has_signal( MBG_DEV_HANDLE dh, int *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device provides a modulation signal + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_mod preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_mod + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_mod" ) _MBG_API mbg_dev_has_mod( MBG_DEV_HANDLE dh, int *p ) ; - @see mbg_dev_has_pcps_tzdl() - @see mbg_get_pcps_tzdl() - @see mbg_set_tzcode() - @see mbg_set_gps_tzdl() - @see \ref group_cmd_bytes - */ - _MBG_API_ATTR int _MBG_API mbg_set_pcps_tzdl( MBG_DEV_HANDLE dh, const PCPS_TZDL *p ) ; + /* (Intentionally excluded from Doxygen) + * @brief Check if a device supports higher baud rates than usual + * + * Check if a device provides a serial output that supports + * higher baud rates than older cards, i.e. ::DEFAULT_BAUD_RATES_DCF_HS + * rather than ::DEFAULT_BAUD_RATES_DCF. + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_serial_hs preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_serial_hs + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_serial_hs" ) _MBG_API mbg_dev_has_serial_hs( MBG_DEV_HANDLE dh, int *p ) ; /** - Read the reference time offset from %UTC for clocks which can't determine - that offset automatically, e.g. from an IRIG input signal. - The macro _pcps_has_ref_offs() or the API call mbg_dev_has_ref_offs() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_REF_OFFS value to be filled up + * @brief Check if a device provides a programmable frequency synthesizer + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_synth preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_synth + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_synth" ) _MBG_API mbg_dev_has_synth( MBG_DEV_HANDLE dh, int *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device provides GPIO signal inputs and/or outputs + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_gpio preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_gpio + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_gpio" ) _MBG_API mbg_dev_has_gpio( MBG_DEV_HANDLE dh, int *p ) ; - @see mbg_dev_has_ref_offs() - @see mbg_set_ref_offs() - @see ::PCPS_GET_REF_OFFS - */ - _MBG_API_ATTR int _MBG_API mbg_get_ref_offs( MBG_DEV_HANDLE dh, MBG_REF_OFFS *p ) ; + /** + * @brief Check if a device supports configuration of antenna cable length + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_cab_len preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_cab_len + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_cab_len" ) _MBG_API mbg_dev_has_cab_len( MBG_DEV_HANDLE dh, int *p ) ; /** - Write the reference time offset from %UTC for clocks which can't determine - that offset automatically, e.g. from an IRIG input signal. - The macro _pcps_has_ref_offs() or the API call mbg_dev_has_ref_offs() - check whether this call is supported by a specific card. + * @brief Check if a device provides a configurable ref time offset + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_ref_offs preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_ref_offs + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_ref_offs" ) _MBG_API mbg_dev_has_ref_offs( MBG_DEV_HANDLE dh, int *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_REF_OFFS value to be written + /** + * @brief Check if a device supports the ::MBG_OPT_INFO/::MBG_OPT_SETTINGS + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_opt_flags preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_opt_flags + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_opt_flags" ) _MBG_API mbg_dev_has_opt_flags( MBG_DEV_HANDLE dh, int *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device support reading/writing of ::UTC parameters + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_utc_parm preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_utc_parm + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_utc_parm" ) _MBG_API mbg_dev_has_utc_parm( MBG_DEV_HANDLE dh, int *p ) ; - @see mbg_dev_has_ref_offs() - @see mbg_get_ref_offs() - @see ::PCPS_SET_REF_OFFS - */ - _MBG_API_ATTR int _MBG_API mbg_set_ref_offs( MBG_DEV_HANDLE dh, const MBG_REF_OFFS *p ) ; + /** + * @brief Check if a device supports reading correlation info + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_corr_info preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_corr_info + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_corr_info" ) _MBG_API mbg_dev_has_corr_info( MBG_DEV_HANDLE dh, int *p ) ; /** - Read a ::MBG_OPT_INFO structure containing optional settings, controlled by flags. - The ::MBG_OPT_INFO structure contains a mask of supported flags plus the current - settings of those flags. - The macro _pcps_has_opt_flags() or the API call mbg_dev_has_opt_flags() - check whether this call is supported by a specific card. + * @brief Check if a device supports configurable distance from transmitter + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_tr_distance preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_tr_distance + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_tr_distance" ) _MBG_API mbg_dev_has_tr_distance( MBG_DEV_HANDLE dh, int *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_OPT_INFO structure to be filled up + /** + * @brief Check if a device provides a debug status word to be read + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_debug_status preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_debug_status + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_debug_status" ) _MBG_API mbg_dev_has_debug_status( MBG_DEV_HANDLE dh, int *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Check if a device provides an on-board event log. + * + * @deprecated This function is deprecated, use ::mbg_chk_dev_has_evt_log preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an int which is updated if the API call succeeds. + * The flag is set != 0 if the requested feature is supported, else 0. + * + * @return ::MBG_SUCCESS on success, if *p has been updated, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_chk_supp_fncs_deprecated + * @see ::mbg_chk_dev_has_evt_log + */ + _MBG_API_ATTR int _DEPRECATED_BY( "mbg_chk_dev_has_evt_log" ) _MBG_API mbg_dev_has_evt_log( MBG_DEV_HANDLE dh, int *p ) ; - @see mbg_dev_has_opt_flags() - @see mbg_set_opt_settings() - */ - _MBG_API_ATTR int _MBG_API mbg_get_opt_info( MBG_DEV_HANDLE dh, MBG_OPT_INFO *p ) ; + /** + * @brief Create a device file name according to an index number + * + * Create a system-specific device file name string, e.g. "/dev/mbgclock0" + * under Linux and similar systems, which can be used with the + * open() call on systems which support this. + * + * Under Windows a hardware ID string is used, so a Windows-specific function + * is called to retrieve the string + * + * @param[out] s Pointer to the output buffer. + * @param[in] max_len Size of the output buffer. + * @param[in] dev_idx The device index number. + * + * @see mbg_svc_get_device_path under Windows + */ + _MBG_API_ATTR int _MBG_API mbg_dev_fn_from_dev_idx( char *s, int max_len, int dev_idx ) ; /** - Write a ::MBG_OPT_SETTINGS structure contains optional settings, controlled by flags. - The macro _pcps_has_opt_flags() or the API call mbg_dev_has_opt_flags() - check whether this call is supported by a specific card. - The ::MBG_OPT_INFO structure should be read first to check which of the specified - flags is supported by a specific card. + * @brief Open a device by index number + * + * For details and similar functions see @ref mbgdevio_open_fncs. + * + * @param[in] dev_idx Device index number, starting from 0. + * + * @return A valid device handle on success, else ::MBG_INVALID_DEV_HANDLE + * + * @ingroup mbgdevio_open_fncs + * @see ::mbg_close_device + * @see @ref mbgdevio_open_fncs + */ + MBG_DEV_HANDLE _MBG_API mbg_open_device( int dev_idx ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_OPT_SETTINGS structure to be written + /** + * @brief Open a device specified by a device file name + * + * The format the device file name depends on the operating system. + * see ::MBG_DEV_FN. + * + * For details and similar functions see @ref mbgdevio_open_fncs. + * + * @param[in] dev_fn The device file name + * + * @return A valid device handle on success, else ::MBG_INVALID_DEV_HANDLE + * + * @ingroup mbgdevio_open_fncs + * @see ::mbg_close_device + * @see @ref mbgdevio_open_fncs + * @see ::MBG_DEV_FN + */ + _MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device_by_dev_fn( const char *dev_fn ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Open a device specified by a device file name + * + * @deprecated This function is deprecated, use + * ::mbg_open_device_by_dev_fn preferably. + * + * The format the device file name depends on the operating system. + * see ::MBG_DEV_FN. + * + * For details and similar functions see @ref mbgdevio_open_fncs. + * + * @param[in] dev_fn The device file name, see ::MBG_DEV_FN + * + * @return A valid device handle on success, else ::MBG_INVALID_DEV_HANDLE + * + * @ingroup mbgdevio_open_fncs + * @see ::mbg_close_device + * @see @ref mbgdevio_open_fncs + * @see ::MBG_DEV_FN + */ + _MBG_API_ATTR MBG_DEV_HANDLE _DEPRECATED_BY( "mbg_open_device_by_dev_fn" ) _MBG_API mbg_open_device_by_hw_id( const char *dev_fn ) ; - @see mbg_dev_has_opt_flags() - @see mbg_get_opt_info() - */ - _MBG_API_ATTR int _MBG_API mbg_set_opt_settings( MBG_DEV_HANDLE dh, const MBG_OPT_SETTINGS *p ) ; + /** + * @brief Get the number of devices installed on the computer + * + * The function ::mbg_find_devices_with_names should eventually + * be used preferafly. See @ref mbgdevio_open_fncs. + * + * @return The number of devices found + * + * @see ::mbg_find_devices_with_names + * @see ::mbg_open_device + * @see @ref mbgdevio_open_fncs + */ + _MBG_API_ATTR int _MBG_API mbg_find_devices( void ) ; /** - Read an ::IRIG_INFO structure containing the configuration of an IRIG input - plus the possible settings supported by that input. - The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx() - check whether this call is supported by a specific card. + * @brief Allocate memory and set up a list of installed and supported devices + * + * Allocate and fill a list with the names of Meinberg devices currently + * present in the system. + * + * This can be used e.g. to populate a device selection dialog + * in a configuration program. + * + * When the list is not used anymore it can be freed by calling + * ::mbg_free_device_name_list. + * + * @param[in] p_list Pointer to a linked list to be allocated. + * @param[in] max_devices Maximum number of devices to be searched for + * (must not exceed ::N_SUPP_DEV_BUS). + * + * @return The number of present devices + * + * @see ::mbg_free_device_name_list + * @see ::mbg_find_devices + * @see ::MBG_DEV_NAME + */ + _MBG_API_ATTR int _MBG_API mbg_find_devices_with_names( MBG_DEV_NAME_LIST_ENTRY **p_list, int max_devices ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to an ::IRIG_INFO structure to be filled up + /** + * @brief Free the memory allocated for a list of ::MBG_DEV_NAME_LIST_ENTRY entries. + * + * The list may have been set up and allocated before + * by ::mbg_find_devices_with_names. + * + * @param[in,out] list Linked list of ::MBG_DEV_NAME_LIST_ENTRY entries. + * + * @see ::mbg_find_devices_with_names + */ + _MBG_API_ATTR void _MBG_API mbg_free_device_name_list( MBG_DEV_NAME_LIST_ENTRY *list ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Return a handle to a device with a particular device name + * + * See ::MBG_DEV_NAME for the possible formats of a device name. + * + * For details and similar functions see @ref mbgdevio_open_fncs. + * + * @param[in] srch_name String with the ::MBG_DEV_NAME of a device to be opened + * @param[in] selection_mode One of the ::MBG_MATCH_MODES + * + * @return A valid device handle on success, else ::MBG_INVALID_DEV_HANDLE + * + * @ingroup mbgdevio_open_fncs + * @see ::mbg_close_device + * @see @ref mbgdevio_open_fncs + * @see ::MBG_DEV_NAME + * @see ::MBG_MATCH_MODES + */ + _MBG_API_ATTR MBG_DEV_HANDLE _MBG_API mbg_open_device_by_name( const char *srch_name, int selection_mode ) ; - @see mbg_set_irig_rx_settings() - @see mbg_dev_is_irig_rx() - @see mbg_dev_has_irig_tx() - @see mbg_dev_has_irig() - @see \ref group_icode - */ - _MBG_API_ATTR int _MBG_API mbg_get_irig_rx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p ) ; + /** + * @brief Close a device handle and set the handle value to ::MBG_INVALID_DEV_HANDLE + * + * @param[in,out] dev_handle Pointer to a Meinberg device handle + * + * @see @ref mbgdevio_open_fncs + */ + _MBG_API_ATTR void _MBG_API mbg_close_device( MBG_DEV_HANDLE *dev_handle ) ; /** - Write an ::IRIG_SETTINGS structure containing the configuration of an IRIG input. - The macro _pcps_is_irig_rx() or the API call mbg_dev_is_irig_rx() - check whether this call is supported by a specific card. - The ::IRIG_INFO structure should be read first to determine the possible - settings supported by this card's IRIG input. + * @brief Read information about the driver handling a given device + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p A ::PCPS_DRVR_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ + _MBG_API_ATTR int _MBG_API mbg_get_drvr_info( MBG_DEV_HANDLE dh, PCPS_DRVR_INFO *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::IRIG_SETTINGS structure to be written + /** + * @brief Read detailed device information + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] *p A ::PCPS_DEV structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ + _MBG_API_ATTR int _MBG_API mbg_get_device_info( MBG_DEV_HANDLE dh, PCPS_DEV *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Read the current state of the on-board ::PCPS_STATUS_PORT + * + * This function is useful to read the device's status port which + * also includes the ::PCPS_ST_MOD bit reflecting the time code + * modulation of long wave receivers. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p A ::PCPS_STATUS_PORT value to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see @ref group_status_port "bitmask" //### TODO check syntax + */ + _MBG_API_ATTR int _MBG_API mbg_get_status_port( MBG_DEV_HANDLE dh, PCPS_STATUS_PORT *p ) ; - @see mbg_get_irig_rx_info() - @see mbg_dev_is_irig_rx() - @see mbg_dev_has_irig_tx() - @see mbg_dev_has_irig() - @see \ref group_icode - */ - _MBG_API_ATTR int _MBG_API mbg_set_irig_rx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p ) ; + /* (Intentionally excluded from Doxygen) + * Generic read function which writes a command code to a device + * and reads a number of replied data to a generic buffer. + * + * <b>Warning</b>: This is for debugging purposes only! + * The specialized API calls should be used preferably. + * Not all devices support each of the ::PC_GPS_COMMANDS. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] cmd Can be any @ref PCPS_CMD_CODES "command code" supported by the device + * @param[out] p Pointer to a buffer to be filled up + * @param[in] size Size of the output buffer + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_generic_write + * @see ::mbg_generic_read_gps + * @see ::mbg_generic_write_gps + * @see ::mbg_generic_io + */ + _MBG_API_ATTR int _MBG_API mbg_generic_read( MBG_DEV_HANDLE dh, int cmd, void *p, int size ) ; - /** - Check if a specific device supports the mbg_get_irig_ctrl_bits() call. + /* (Intentionally excluded from Doxygen) + * Generic read function which writes a GPS command code to a device + * and reads a number of data bytes back into a generic buffer. + * The function ::mbg_chk_dev_has_gps_data can be used to check + * whether this call is supported by a device. + * + * <b>Warning</b>: This is for debugging purposes only! + * The specialized API calls should be used preferably. + * Not all devices support each of the ::PC_GPS_COMMANDS. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] cmd One of the ::PCPS_CMD_CODES supported by the device. + * @param[out] p Pointer to a buffer to be filled up + * @param[in] size Size of the buffer, has to match the expected data size associated with cmd + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_gps_data + * @see ::mbg_generic_write_gps + * @see ::mbg_generic_read + * @see ::mbg_generic_write + * @see ::mbg_generic_io + */ + _MBG_API_ATTR int _MBG_API mbg_generic_read_gps( MBG_DEV_HANDLE dh, int cmd, void *p, int size ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + /* (Intentionally excluded from Doxygen) + * Generic write function which writes a command code plus an + * associated number of data bytes to a device. + * + * <b>Warning</b>: This is for debugging purposes only! + * The specialized API calls should be used preferably. + * Not all devices support each of the ::PC_GPS_COMMANDS. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] cmd One of the ::PCPS_CMD_CODES supported by the device. + * @param[in] p Pointer to a buffer of data to be written + * @param[in] size Size of the buffer, has to match the expected data size associated with cmd + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_generic_read + * @see ::mbg_generic_read_gps + * @see ::mbg_generic_write_gps + * @see ::mbg_generic_io + */ + _MBG_API_ATTR int _MBG_API mbg_generic_write( MBG_DEV_HANDLE dh, int cmd, const void *p, int size ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /* (Intentionally excluded from Doxygen) + * Generic write function which writes a GPS command code plus an + * associated number of data bytes to a device. + * The function ::mbg_chk_dev_has_gps_data can be used to check + * whether this call is supported by a device. + * + * <b>Warning</b>: This is for debugging purposes only! + * The specialized API calls should be used preferably. + * Not all devices support each of the ::PC_GPS_COMMANDS. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] cmd One of the ::PCPS_CMD_CODES supported by the device. + * @param[in] p Pointer to a buffer of data to be written + * @param[in] size Size of the buffer, has to match the expected data size associated with cmd + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_gps_data + * @see ::mbg_generic_read_gps + * @see ::mbg_generic_read + * @see ::mbg_generic_write + * @see ::mbg_generic_io + */ + _MBG_API_ATTR int _MBG_API mbg_generic_write_gps( MBG_DEV_HANDLE dh, int cmd, const void *p, int size ) ; - @see mbg_get_irig_ctrl_bits() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_irig_ctrl_bits( MBG_DEV_HANDLE dh, int *p ) ; + /* (Intentionally excluded from Doxygen) + * Write and/or read generic data to/from a device. + * The function ::mbg_chk_dev_has_generic_io checks + * whether this call is supported by a device. + * + * <b>Warning</b>: This call is for debugging purposes and internal use only! + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_generic_io + * @see ::mbg_generic_read + * @see ::mbg_generic_write + * @see ::mbg_generic_read_gps + * @see ::mbg_generic_write_gps + */ + _MBG_API_ATTR int _MBG_API mbg_generic_io( MBG_DEV_HANDLE dh, int type, const void *in_p, int in_sz, void *out_p, int out_sz ) ; /** - Read a ::MBG_IRIG_CTRL_BITS type which contains the control function - bits of the latest IRIG input frame. Those bits may carry some - well-known information, as in the IEEE1344 code, but may also contain - some customized information, depending on the IRIG frame type and - the configuration of the IRIG generator. So these bits are returned - as-is and must be interpreted by the application. - The macro _pcps_has_irig_ctrl_bits() or the API call mbg_dev_has_irig_ctrl_bits() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_IRIG_CTRL_BITS type to be filled up + * @brief Read a ::PCPS_TIME structure returning the current date/time/status + * + * The returned time is local time according to the card's time zone setting, + * with a resolution of 10 ms (i.e. 10ths of seconds) only. + * + * This call is supported by any device manufactured by Meinberg. + * However, for higher accuracy and resolution the @ref mbgdevio_hr_time_fncs or + * the @ref mbgdevio_fast_timestamp_fncs group of calls should be used preferably, + * if supported by the device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_legacy_time_fncs + * @see ::mbg_get_hr_time + * @see ::mbg_set_time + * @see ::mbg_get_sync_time + */ + _MBG_API_ATTR int _MBG_API mbg_get_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Set the device's on-board clock to a given date and time. + * + * The macro ::_pcps_can_set_time checks whether + * this call is supported by a device. + * + * @todo Provide an API function replacing ::_pcps_can_set_time. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PCPS_STIME structure to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_time + */ + _MBG_API_ATTR int _MBG_API mbg_set_time( MBG_DEV_HANDLE dh, const PCPS_STIME *p ) ; - @see mbg_dev_has_irig_ctrl_bits() -*/ - _MBG_API_ATTR int _MBG_API mbg_get_irig_ctrl_bits( MBG_DEV_HANDLE dh, MBG_IRIG_CTRL_BITS *p ) ; + /** + * @brief Read the time when the device has last recently synchronized + * + * Fills a ::PCPS_TIME structure with the date/time/status reporting + * when the device was synchronized the last time to its time source, + * e.g. the DCF77 signal, the GPS satellites, or similar. + * + * The macro ::_pcps_has_sync_time checks whether + * this call is supported by a device. + * + * <b>Note:</b> If that information is not available on the board then + * the value of the returned ::PCPS_TIME::sec field is set to 0xFF. + * The macro ::_pcps_time_is_read can be used to check whether the + * returned information is valid, or "not set". + * + * @todo Provide an API function replacing ::_pcps_has_sync_time. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_time + */ + _MBG_API_ATTR int _MBG_API mbg_get_sync_time( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ; /** - Check if a specific device supports the mbg_get_raw_irig_data() call. + * @brief Wait until the next second change, then return current time + * + * Returns time in a ::PCPS_TIME structure similar to ::mbg_get_time. + * + * <b>Note:</b> This API call is supported under Windows only. + * The call blocks until the kernel driver detects a second change + * reported by the device. The accuracy of this call is limited + * to a few milliseconds. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_legacy_time_fncs + * @see ::mbg_get_time + */ + _MBG_API_ATTR int _MBG_API mbg_get_time_sec_change( MBG_DEV_HANDLE dh, PCPS_TIME *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + /** + * @brief Read the card's current time with high resolution, including status + * + * Fills up a ::PCPS_HR_TIME (High Resolution time) structure containing + * the current %UTC time (seconds since 1970), %UTC offset, and status. + * + * The API call ::mbg_chk_dev_has_hr_time checks whether + * this call is supported by a device. + * + * For details see @ref ::mbgdevio_hr_time_fncs + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_HR_TIME structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_hr_time_fncs + * @see @ref mbgdevio_hr_time_fncs + * @see @ref mbgdevio_fast_timestamp_fncs + * @see @ref mbgdevio_legacy_time_fncs + */ + _MBG_API_ATTR int _MBG_API mbg_get_hr_time( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /* (Intentionally excluded from Doxygen ) + * Write a high resolution time stamp ::PCPS_TIME_STAMP to a device + * to configure a %UTC time when the clock shall generate an event. + * The API call ::mbg_chk_dev_has_event_time checks whether + * this call is supported by a device. + * + * <b>Note:</b> This is only supported by some special firmware. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PCPS_TIME_STAMP structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_event_time + */ + _MBG_API_ATTR int _MBG_API mbg_set_event_time( MBG_DEV_HANDLE dh, const PCPS_TIME_STAMP *p ) ; - @see mbg_get_raw_irig_data() - @see mbg_get_raw_irig_data_on_sec_change() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_raw_irig_data( MBG_DEV_HANDLE dh, int *p ) ; + /** + * @brief Read the serial port configuration from an old type of device + * + * @deprecated Direct usage of this function is deprecated. The generic + * API function ::mbg_get_serial_settings should be used instead + * which fully supports the capabilities of current devices. + * + * The macro ::_pcps_has_serial checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_SERIAL structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_serial_settings + */ + _MBG_API_ATTR int _MBG_API mbg_get_serial( MBG_DEV_HANDLE dh, PCPS_SERIAL *p ) ; /** - Read a ::MBG_RAW_IRIG_DATA type which contains all data - bits of the latest IRIG input frame. - The macro _pcps_has_raw_irig_data() or the API call mbg_dev_has_raw_irig_data() - check whether this call is supported by a specific card. + * @brief Write the serial port configuration to an old type of device + * + * @deprecated Direct usage of this function is deprecated. The generic + * API function ::mbg_save_serial_settings should be used instead + * which fully supports the capabilities of current devices. + * + * The macro ::_pcps_has_serial checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PCPS_SERIAL structure to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_save_serial_settings + */ + _MBG_API_ATTR int _MBG_API mbg_set_serial( MBG_DEV_HANDLE dh, const PCPS_SERIAL *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up + /** + * @brief Read time zone/daylight saving configuration code from a device. + * + * The APIs using ::TZCODE are only supported by some simpler cards + * and allow just a very basic configuration. + * + * The API call ::mbg_chk_dev_has_tzcode checks whether + * this call is supported by a device. + * + * Other devices may support the ::mbg_get_pcps_tzdl or ::mbg_get_gps_tzdl + * calls instead which allow for a more detailed configuration of the + * time zone and daylight saving settings. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TZCODE structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_tzcode + * @see ::mbg_set_tzcode + * @see ::mbg_get_pcps_tzdl + * @see ::mbg_get_gps_tzdl + */ + _MBG_API_ATTR int _MBG_API mbg_get_tzcode( MBG_DEV_HANDLE dh, PCPS_TZCODE *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Write time zone/daylight saving configuration code to a device. + * + * The APIs using ::TZCODE are only supported by some simpler cards + * and allow just a very basic configuration. + * + * The API call ::mbg_chk_dev_has_tzcode checks whether + * this call is supported by a device. + * + * Other devices may support the ::mbg_set_pcps_tzdl or ::mbg_set_gps_tzdl + * calls instead which allow for a more detailed configuration of the + * time zone and daylight saving settings. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PCPS_TZCODE structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_tzcode + * @see ::mbg_get_tzcode + * @see ::mbg_set_pcps_tzdl + * @see ::mbg_set_gps_tzdl + */ + _MBG_API_ATTR int _MBG_API mbg_set_tzcode( MBG_DEV_HANDLE dh, const PCPS_TZCODE *p ) ; - @see mbg_dev_has_raw_irig_data() - @see mbg_get_raw_irig_data_on_sec_change() -*/ - _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data( MBG_DEV_HANDLE dh, MBG_RAW_IRIG_DATA *p ) ; + /** + * @brief Read time zone/daylight saving parameters from a device. + * + * This function fills up a ::PCPS_TZDL structure which supports a more + * detailed configuration of time zone and daylight saving than the ::TZCODE + * structure. + * + * The API call ::mbg_chk_dev_has_pcps_tzdl checks whether + * this call is supported by a device. + * + * Other devices may support the ::mbg_get_tzcode or ::mbg_get_gps_tzdl + * calls instead. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TZDL structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_pcps_tzdl + * @see ::mbg_set_pcps_tzdl + * @see ::mbg_get_tzcode + * @see ::mbg_get_gps_tzdl + */ + _MBG_API_ATTR int _MBG_API mbg_get_pcps_tzdl( MBG_DEV_HANDLE dh, PCPS_TZDL *p ) ; /** - Read a ::MBG_RAW_IRIG_DATA type just after a second change which contains all data - bits of the latest IRIG input frame. - The macro _pcps_has_raw_irig_data() or the API call mbg_dev_has_raw_irig_data() - check whether this call is supported by a specific card. + * @brief Write time zone/daylight saving parameters to a device. + * + * This function passes a ::PCPS_TZDL structure to a device which supports + * a more detailed configuration of time zone and daylight saving than the + * ::TZCODE structure. + * + * The API call ::mbg_chk_dev_has_pcps_tzdl checks whether + * this call is supported by a device. + * Other cards may support the ::mbg_set_tzcode or ::mbg_set_gps_tzdl + * calls instead. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PCPS_TZDL structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_pcps_tzdl + * @see ::mbg_get_pcps_tzdl + * @see ::mbg_set_tzcode + * @see ::mbg_set_gps_tzdl + */ + _MBG_API_ATTR int _MBG_API mbg_set_pcps_tzdl( MBG_DEV_HANDLE dh, const PCPS_TZDL *p ) ; - <b>Note:</b> The mbg_get_time_sec_change() function called by this function is - supported under Windows only, so this function can also only be used under Windows. + /** + * @brief Read the %UTC offset configuration of the reference time from a device + * + * This parameter is used to specify the %UTC offset of an incoming + * reference time signal if a kind of time signal e.g. an IRIG input + * signal) does not provide this information. + * + * The API call ::mbg_chk_dev_has_ref_offs checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_REF_OFFS value to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ref_offs + * @see ::mbg_set_ref_offs + */ + _MBG_API_ATTR int _MBG_API mbg_get_ref_offs( MBG_DEV_HANDLE dh, MBG_REF_OFFS *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up + /** + * @brief Write the %UTC offset configuration of the reference time to a device. + * + * This parameter is used to specify the %UTC offset of an incoming + * reference time signal if a kind of time signal e.g. an IRIG input + * signal) does not provide this information. + * + * The API call ::mbg_chk_dev_has_ref_offs checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::MBG_REF_OFFS value to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ref_offs + * @see ::mbg_get_ref_offs + */ + _MBG_API_ATTR int _MBG_API mbg_set_ref_offs( MBG_DEV_HANDLE dh, const MBG_REF_OFFS *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Read a ::MBG_OPT_INFO structure containing optional settings, controlled by flags + * + * The ::MBG_OPT_INFO structure contains a mask of supported flags plus the current + * settings of those flags. + * + * The API call ::mbg_chk_dev_has_opt_flags checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_OPT_INFO structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_opt_flags + * @see ::mbg_set_opt_settings + */ + _MBG_API_ATTR int _MBG_API mbg_get_opt_info( MBG_DEV_HANDLE dh, MBG_OPT_INFO *p ) ; - @see mbg_dev_has_raw_irig_data() - @see mbg_get_raw_irig_data() -*/ - _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data_on_sec_change( MBG_DEV_HANDLE dh, MBG_RAW_IRIG_DATA *p ) ; + /** + * @brief Write a ::MBG_OPT_SETTINGS structure containing optional device settings. + * + * The API call ::mbg_chk_dev_has_opt_flags checks whether + * this call is supported by a device. + * + * ::mbg_get_opt_info should be called first to check which of + * the specified flags is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_OPT_SETTINGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_opt_flags + * @see ::mbg_get_opt_info + */ + _MBG_API_ATTR int _MBG_API mbg_set_opt_settings( MBG_DEV_HANDLE dh, const MBG_OPT_SETTINGS *p ) ; /** - Check if a specific device supports the mbg_get_irig_time() call. + * @brief Read the current IRIG input settings plus capabilities + * + * @deprecated Calling this function directly is deprecated. The function + * ::mbg_get_all_irig_rx_info should be used instead which also reads some + * other associated parameters affecting the behaviour of the IRIG input. + * + * The API call ::mbg_chk_dev_is_tcr checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] *p An ::IRIG_INFO structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_all_irig_rx_info + * @see ::mbg_set_irig_rx_settings + * @see ::mbg_chk_dev_is_tcr + * @see ::mbg_chk_dev_has_irig_tx + * @see ::mbg_chk_dev_has_irig + * @see @ref group_icode + */ + _MBG_API_ATTR int _MBG_API mbg_get_irig_rx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + /** + * @brief Write an ::IRIG_SETTINGS structure to a device to configure an IRIG input. + * + * @deprecated Calling this function directly is deprecated. The function + * ::mbg_save_all_irig_rx_settings should be used instead which also writes some + * other associated parameters affecting the behaviour of the IRIG input. + * + * The API call ::mbg_chk_dev_is_tcr checks whether + * this call is supported by a device. + * ::mbg_get_irig_rx_info should be called first to determine + * the possible settings supported by the device's IRIG input. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::IRIG_SETTINGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_save_all_irig_rx_settings + * @see ::mbg_get_irig_rx_info + * @see ::mbg_chk_dev_is_tcr + * @see ::mbg_chk_dev_has_irig_tx + * @see ::mbg_chk_dev_has_irig + * @see @ref group_icode + */ + _MBG_API_ATTR int _MBG_API mbg_set_irig_rx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Read all IRIG input configuration information from a device + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] pdev Pointer to the device's ::PCPS_DEV structure //### TODO Make this obsolete + * @param[in] p_irig_info Pointer to a ::IRIG_SETTINGS structure to be written + * @param[in] p_ref_offs Pointer to a ::MBG_REF_OFFS structure to be written + * @param[in] p_opt_info Pointer to a ::MBG_OPT_SETTINGS structure to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_save_all_irig_rx_settings + * @see ::mbg_set_irig_rx_settings + * @see ::mbg_set_ref_offs + * @see ::mbg_set_opt_settings + */ + _MBG_API_ATTR int _MBG_API mbg_get_all_irig_rx_info( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, IRIG_INFO *p_irig_info, MBG_REF_OFFS *p_ref_offs, MBG_OPT_INFO *p_opt_info ) ; - @see mbg_get_irig_time() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_irig_time( MBG_DEV_HANDLE dh, int *p ) ; + /** + * @brief Write all IRIG input configuration settings to a device. + * + * The API call ::mbg_chk_dev_is_tcr checks whether + * this call is supported by a device. + * ::mbg_get_all_irig_rx_info should be called before to determine + * the possible settings supported by the IRIG input. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] pdev Pointer to the device's ::PCPS_DEV structure //### TODO Make this obsolete + * @param[out] p_irig_settings Pointer to a ::IRIG_SETTINGS structure to be written + * @param[out] p_ref_offs Pointer to a ::MBG_REF_OFFS structure to be written + * @param[out] p_opt_settings Pointer to a ::MBG_OPT_SETTINGS structure to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_all_irig_rx_info + * @see ::mbg_set_irig_rx_settings + * @see ::mbg_set_ref_offs + * @see ::mbg_set_opt_settings + */ + _MBG_API_ATTR int _MBG_API mbg_save_all_irig_rx_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, const IRIG_SETTINGS *p_irig_settings, const MBG_REF_OFFS *p_ref_offs, const MBG_OPT_SETTINGS *p_opt_settings ) ; /** - Read a ::PCPS_IRIG_TIME type which returns the raw IRIG day-of-year number - and time decoded from the latest IRIG input frame. If the configured IRIG code - also contains the year number then the year number is also returned, otherwise - the returned year number is 0xFF. - The macro _pcps_has_irig_time() or the API call mbg_dev_has_irig_time() - check whether this call is supported by a specific card. + * @brief Read the control function bits received from an incoming IRIG signal. + * + * This function fills an ::MBG_IRIG_CTRL_BITS structure with the control function + * bits decoded from the incoming IRIG signal. + * + * The meaning of these bits depends on the type of IRIG code frame format. + * + * In some IRIG formats these bits provide some well-known information which can + * also be evaluated by the device. For example, in IEEE 1344 or IEEE C37.118 code + * the control function bits are used to provide the year number, UTC offset, + * DST status, leap second warning, etc. + * + * For most IRIG code formats, however, these bits are reserved, i.e. not used + * at all, or application defined, depending on the configuration of the IRIG + * generator providing the IRIG signal. + * + * In the latter case the application has to evaluate the received control function + * bits and can use this function to retrieve these bits from the receiver device. + * + * The API call ::mbg_chk_dev_has_irig_ctrl_bits checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_IRIG_CTRL_BITS type to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_irig_ctrl_bits + */ + _MBG_API_ATTR int _MBG_API mbg_get_irig_ctrl_bits( MBG_DEV_HANDLE dh, MBG_IRIG_CTRL_BITS *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_IRIG_TIME type to be filled up + /** + * @brief Read raw IRIG data from an IRIG receiver. + * + * This function reads an ::MBG_RAW_IRIG_DATA structure with the raw data bits received + * from the incoming IRIG signal. This enables an application itself to decode the + * information provided by the IRIG signal. + * + * The API call ::mbg_chk_dev_has_raw_irig_data checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_raw_irig_data + * @see ::mbg_get_raw_irig_data_on_sec_change + */ + _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data( MBG_DEV_HANDLE dh, MBG_RAW_IRIG_DATA *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Wait for second changeover then read raw IRIG data from an IRIG receiver. + * + * This function waits until the second of the device's on-board time rolls over, + * and then reads the last recent raw IRIG data from the device. + * + * The API call ::mbg_chk_dev_has_raw_irig_data checks whether + * this call is supported by a device. + * + * <b>Note:</b> The ::mbg_get_time_sec_change function called + * by this function is supported under Windows only, so this function + * can also be used under Windows only. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_RAW_IRIG_DATA type to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_raw_irig_data + * @see ::mbg_get_raw_irig_data + * @see ::mbg_get_time_sec_change + */ + _MBG_API_ATTR int _MBG_API mbg_get_raw_irig_data_on_sec_change( MBG_DEV_HANDLE dh, MBG_RAW_IRIG_DATA *p ) ; - @see mbg_dev_has_irig_time() -*/ + /** + * @brief Read the IRIG time and day-of-year number from an IRIG receiver. + * + * Reads a ::PCPS_IRIG_TIME structure with the raw IRIG day-of-year number + * and time decoded from the latest IRIG input frame. If the configured IRIG code + * also contains the year number then the year number is also returned, otherwise + * the returned year number is 0xFF. + * + * The API call ::mbg_chk_dev_has_irig_time checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_IRIG_TIME type to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_irig_time + */ _MBG_API_ATTR int _MBG_API mbg_get_irig_time( MBG_DEV_HANDLE dh, PCPS_IRIG_TIME *p ) ; /** - Clear the card's on-board time capture FIFO buffer. - The macro _pcps_can_clr_ucap_buff() or the API call mbg_dev_can_clr_ucap_buff() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_can_clr_ucap_buff() - @see mbg_get_ucap_entries() - @see mbg_get_ucap_event() - */ + * @brief Clear a device's on-board time capture FIFO buffer. + * + * The API call ::mbg_chk_dev_can_clr_ucap_buff checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_can_clr_ucap_buff + * @see ::mbg_get_ucap_entries + * @see ::mbg_get_ucap_event + */ _MBG_API_ATTR int _MBG_API mbg_clr_ucap_buff( MBG_DEV_HANDLE dh ) ; /** - Read a ::PCPS_UCAP_ENTRIES structure to retrieve the number of saved - user capture events and the maximum capture buffer size. - The macro _pcps_has_ucap() or the API call mbg_dev_has_ucap() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_UCAP_ENTRIES structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ucap() - @see mbg_get_ucap_entries() - @see mbg_get_ucap_event() - */ + * @brief Read information on a device's event capture buffer. + * + * Reads a ::PCPS_UCAP_ENTRIES structure with the number of user capture + * events actually stored in the FIFO buffer, and the maximum number of + * events that can be held by the buffer. + * + * The API call ::mbg_chk_dev_has_ucap checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_UCAP_ENTRIES structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ucap + * @see ::mbg_get_ucap_entries + * @see ::mbg_get_ucap_event + */ _MBG_API_ATTR int _MBG_API mbg_get_ucap_entries( MBG_DEV_HANDLE dh, PCPS_UCAP_ENTRIES *p ) ; /** - Retrieve a single time capture event from the on-board FIFO buffer - using a ::PCPS_HR_TIME structure. The oldest entry of the FIFO is retrieved - and then removed from the FIFO. - If no capture event is available in the FIFO buffer then both the seconds - and the fractions of the returned timestamp are 0. - The macro _pcps_has_ucap() or the API call mbg_dev_has_ucap() - check whether this call is supported by a specific card. - - <b>Note:</b> This call is very much faster than the older mbg_get_gps_ucap() - call which is obsolete but still supported for compatibility with - older cards. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ucap() - @see mbg_get_ucap_entries() - @see mbg_clr_ucap_buff() - */ + * @brief Retrieve a single time capture event from the on-board FIFO buffer + * + * The capture event is returned in a ::PCPS_HR_TIME structure. The oldest entry + * in the FIFO is retrieved and then removed from the FIFO. + * + * If no capture event is available in the FIFO buffer then both the seconds + * and the fractions of the returned timestamp are 0. + * + * The API call ::mbg_chk_dev_has_ucap checks whether + * this call is supported by a device. + * + * <b>Note:</b> This call is very much faster than the older ::mbg_get_gps_ucap + * call which is obsolete but still supported for compatibility with + * older cards. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_HR_TIME structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ucap + * @see ::mbg_get_ucap_entries + * @see ::mbg_clr_ucap_buff + */ _MBG_API_ATTR int _MBG_API mbg_get_ucap_event( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p ) ; /** - Read the card's time zone/daylight saving parameters using the ::TZDL - structure. - The macro _pcps_has_tzdl() or the API call mbg_dev_has_tzdl() - check whether this call is supported by a specific card. - - <b>Note:</b> In spite of the function name this call may also be - supported by non-GPS cards. Other cards may support the mbg_get_tzcode() - or mbg_get_pcps_tzdl() calls instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TZDL structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_tzdl() - @see mbg_set_gps_tzdl() - @see mbg_get_tzcode() - @see mbg_get_pcps_tzdl() - @see \ref group_tzdl - */ + * @brief Read the card's time zone/daylight saving parameters + * + * This function returns the time zone/daylight saving parameters + * in a ::TZDL structure. + * + * The API call ::mbg_chk_dev_has_tzdl checks whether + * this call is supported by a device. + * + * <b>Note:</b> In spite of the function name this call may also be + * supported by non-GPS cards. Other cards may support the ::mbg_get_tzcode + * or ::mbg_get_pcps_tzdl calls instead. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::TZDL structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_tzdl + * @see ::mbg_set_gps_tzdl + * @see ::mbg_get_tzcode + * @see ::mbg_get_pcps_tzdl + * @see @ref group_tzdl + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_tzdl( MBG_DEV_HANDLE dh, TZDL *p ) ; /** - Write the card's time zone/daylight saving parameters using the ::TZDL - structure. - The macro _pcps_has_tzdl() or the API call mbg_dev_has_tzdl() - check whether this call is supported by a specific card. - - <b>Note:</b> In spite of the function name this call may also be - supported by non-GPS cards. Other cards may support the mbg_set_tzcode() - or mbg_set_pcps_tzdl() calls instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TZDL structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_tzdl() - @see mbg_get_gps_tzdl() - @see mbg_set_tzcode() - @see mbg_set_pcps_tzdl() - @see \ref group_tzdl - */ + * @brief Write the card's time zone/daylight saving parameters. + * + * This function writes the time zone/daylight saving parameters + * in a ::TZDL structure to a device. + * + * The API call ::mbg_chk_dev_has_tzdl checks whether + * this call is supported by a device. + * + * <b>Note:</b> In spite of the function name this call may also be + * supported by non-GPS cards. Other cards may support the ::mbg_set_tzcode + * or ::mbg_set_pcps_tzdl calls instead. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::TZDL structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_tzdl + * @see ::mbg_get_gps_tzdl + * @see ::mbg_set_tzcode + * @see ::mbg_set_pcps_tzdl + * @see @ref group_tzdl + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_tzdl( MBG_DEV_HANDLE dh, const TZDL *p ) ; /** - Retrieve the software revision of a GPS receiver. - This call is obsolete but still supported for compatibility - with older GPS cards. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - <b>Note:</b> The function mbg_get_gps_receiver_info() should - be used instead, if supported by the card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::SW_REV structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_is_gps() - @see mbg_get_gps_receiver_info() - */ + * @brief Retrieve the software revision of a GPS receiver + * + * @deprecated This function is deprecated. + * + * This function is deprecated, but still supported + * for compatibility with older GPS cards. Normally + * the software revision is part of the ::RECEIVER_INFO + * structure. See ::mbg_setup_receiver_info which takes + * care of the different options. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::SW_REV structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_setup_receiver_info + * @see ::mbg_chk_dev_is_gps + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_sw_rev( MBG_DEV_HANDLE dh, SW_REV *p ) ; /** - Retrieve the status of the battery buffered GPS variables. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - The GPS receiver stays in cold boot mode until all of the - data sets are valid. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::BVAR_STAT structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ + * @brief Retrieve the status of the battery buffered GPS variables. + * + * GPS receivers require some navigational data set to be available + * to be able to decode position and time accurately. This data set + * is transmitted periodically by the satellites, so it can + * simply be collected if it's not available. + * + * The ::BVAR_STAT type reports which parts of the data set are + * available in the receiver, and which are not. + * + * If the available data set is not complete then the receiver + * stays in COLD BOOT mode until all data have been received + * and thus all data sets are valid. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::BVAR_STAT structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_is_gps + * @see ::BVAR_FLAGS + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_bvar_stat( MBG_DEV_HANDLE dh, BVAR_STAT *p ) ; /** - Read the current board time using a ::TTM structure. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - <b>Note:</b> This call is pretty slow, so the mbg_get_hr_time_..() - group of calls should be used preferably. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TTM structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ + * @brief Read the current board time using a ::TTM structure + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * <b>Note:</b> This API call is pretty slow, so ::mbg_get_hr_time or + * ::mbg_get_fast_hr_timestamp or associated calls should be used preferably. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::TTM structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_hr_time + * @see ::mbg_get_fast_hr_timestamp + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_time( MBG_DEV_HANDLE dh, TTM *p ) ; /** - Write a ::TTM structure to a GPS receiver in order to set the - on-board date and time. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TTM structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ + * @brief Set the time on a GPS receiver device + * + * Write a ::TTM structure to a GPS receiver in order to set + * the on-board date and time. Date and time must be local time + * according to the device's on-board time zone configuration + * (::TZDL). + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::TTM structure to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_time( MBG_DEV_HANDLE dh, const TTM *p ) ; /** - Read a ::PORT_PARM structure to retrieve the configuration - of the device's serial ports. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - <b>Note:</b> This function is obsolete since it is only - supported by a certain class of devices and can handle only - up to 2 ports. The generic function mbg_get_serial_settings() - should be used instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PORT_PARM structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_serial_settings() -*/ + * @brief Read a ::PORT_PARM structure with a device's serial port configuration. + * + * @deprecated This function is deprecated, use ::mbg_get_serial_settings preferably. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * <b>Note:</b> This function is deprecated since it is only + * supported by a certain class of devices and can handle only + * up to 2 serial ports. The generic function ::mbg_get_serial_settings + * should be used instead. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PORT_PARM structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_serial_settings + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_port_parm( MBG_DEV_HANDLE dh, PORT_PARM *p ) ; /** - Write a ::PORT_PARM structure to configure the on-board - serial ports. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - <b>Note:</b> This function is obsolete since it is only - supported by a certain class of devices and can handle only - up to 2 ports. The generic function mbg_save_serial_settings() - should be used instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PORT_PARM structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_save_serial_settings() -*/ + * @brief Write a ::PORT_PARM structure to configure the on-board serial ports. + * + * @deprecated This function is deprecated, use ::mbg_save_serial_settings preferably. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * <b>Note:</b> This function is deprecated since it is only + * supported by a certain class of devices and can handle only + * up to 2 ports. The generic function ::mbg_save_serial_settings + * should be used instead. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PORT_PARM structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_save_serial_settings + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_port_parm( MBG_DEV_HANDLE dh, const PORT_PARM *p ) ; /** - Read an ::ANT_INFO structure to retrieve status information of the GPS antenna. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - <b>Note:</b> Normally the antenna connection status can also be - determined by evaluation of the ::PCPS_TIME::signal or ::PCPS_HR_TIME::signal - fields. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ANT_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ + * @brief Read an ::ANT_INFO structure to retrieve an extended GPS antenna status. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * <b>Note:</b> Normally the current antenna connection status can also be + * determined by evaluation of the ::PCPS_TIME::signal or ::PCPS_HR_TIME::signal + * fields. The "disconnected" status reported by ::ANT_INFO disappears only if + * the antenna has been reconnected <b>and</b> the receiver has synchronized + * to the GPS satellites again. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::ANT_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_ant_info( MBG_DEV_HANDLE dh, ANT_INFO *p ) ; /** - Read a time capture event from the on-board FIFO buffer using a ::TTM structure. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - <b>Note:</b> This call is pretty slow and has been obsoleted by - mbg_get_ucap_event() which should be used preferably, if supported - by the card. Anyway, this call is still supported for compatibility - with older cards. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TTM structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_ucap_entries() - @see mbg_get_ucap_event() - @see mbg_clr_ucap_buff() -*/ + * @brief Read a time capture event from the on-board FIFO buffer using a ::TTM structure + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * <b>Note:</b> This call is pretty slow and has been obsoleted by + * ::mbg_get_ucap_event which should be used preferably, if supported + * by the device. Anyway, this call is still supported for compatibility + * with older devices which don't support ::mbg_get_ucap_event. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::TTM structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_ucap_entries + * @see ::mbg_get_ucap_event + * @see ::mbg_clr_ucap_buff + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_ucap( MBG_DEV_HANDLE dh, TTM *p ) ; /** - Read an ::ENABLE_FLAGS structure reporting whether certain outputs - shall be enabled immediately after the card's power-up, or only - after the card has synchronized to its input signal. - The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data() - check whether this call is supported by a specific card. - - <b>Note:</b> Not all of the input signals specified for the - ::ENABLE_FLAGS structure can be modified individually. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::ENABLE_FLAGS structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see ::ENABLE_FLAGS - @see mbg_set_gps_enable_flags() -*/ + * @brief Read the ::ENABLE_FLAGS structure controlling when outputs are to be enabled + * + * The ::ENABLE_FLAGS structure controls whether certain signal outputs + * are to be enabled immediately after the device's power-up, or only + * after the device has synchronized to its input signal. + * + * The function ::mbg_chk_dev_has_gps_data can be used to check + * whether this call is supported by a device. + * + * <b>Note:</b> Not all of the input signals specified for the + * ::ENABLE_FLAGS structure can be modified individually. + * See ::ENABLE_FLAGS_CODES. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::ENABLE_FLAGS structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::ENABLE_FLAGS + * @see ::ENABLE_FLAGS_CODES + * @see ::mbg_set_gps_enable_flags + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_enable_flags( MBG_DEV_HANDLE dh, ENABLE_FLAGS *p ) ; /** - Write an ENABLE_FLAGS structure to configure whether certain outputs - shall be enabled immediately after the card's power-up, or only - after the card has synchronized to its input signal. - The macro _pcps_has_gps_data() or the API call mbg_dev_has_gps_data() - check whether this call is supported by a specific card. - - <b>Note:</b> Not all of the input signals specified for the - ENABLE_FLAGS structure can be modified individually. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ENABLE_FLAGS structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see ENABLE_FLAGS - @see mbg_get_gps_enable_flags() -*/ + * @brief Write an ;;ENABLE_FLAGS structure to configure when outputs shall be enabled. + * + * The ::ENABLE_FLAGS structure controls whether certain signal outputs + * are to be enabled immediately after the device's power-up, or only + * after the device has synchronized to its input signal. + * + * The function ::mbg_chk_dev_has_gps_data can be used to check + * whether this call is supported by a device. + * + * <b>Note:</b> Not all of the input signals specified for the + * ::ENABLE_FLAGS structure can be modified individually. + * See ::ENABLE_FLAGS_CODES. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ENABLE_FLAGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::ENABLE_FLAGS + * @see ::ENABLE_FLAGS_CODES + * @see ::mbg_get_gps_enable_flags + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_enable_flags( MBG_DEV_HANDLE dh, const ENABLE_FLAGS *p ) ; /** - Read a ::STAT_INFO structure to retrieve the status of the - GPS receiver, including mode of operation and numer of - visible/usable satellites. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::STAT_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see ::STAT_INFO -*/ + * @brief Read the extended GPS receiver status from a device. + * + * The ::STAT_INFO structure reports the status of the GPS receiver, + * including mode of operation and number of visible/usable satellites. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::STAT_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::STAT_INFO + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_stat_info( MBG_DEV_HANDLE dh, STAT_INFO *p ) ; /** - Sends a ::GPS_CMD to a GPS receiver. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::GPS_CMD - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see ::PC_GPS_CMD_BOOT, ::PC_GPS_CMD_INIT_SYS, ::PC_GPS_CMD_INIT_USER, ::PC_GPS_CMD_INIT_DAC -*/ + * @brief Send one of the ::PC_GPS_COMMANDS to a GPS receiver device + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::GPS_CMD + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::PC_GPS_COMMANDS + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_cmd( MBG_DEV_HANDLE dh, const GPS_CMD *p ) ; /** - Read the current GPS receiver position using the ::POS structure - which contains different coordinate formats. - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::POS structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_gps_pos_xyz() - @see mbg_set_gps_pos_lla() -*/ + * @brief Read the current geographic position from a GPS device. + * + * The returned ::POS structure contains the current position in + * ECEF (Earth Centered, Earth Fixed) kartesian coordinates, and in + * geographic coordinates with different formats, using the WGS84 + * geographic datum. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::POS structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_gps_pos_xyz + * @see ::mbg_set_gps_pos_lla + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_pos( MBG_DEV_HANDLE dh, POS *p ) ; /** - Preset the GPS receiver position using ::XYZ coordinates - (ECEF: WGS84 "Earth Centered, Earth fixed" kartesian coordinates). - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param p Position in ::XYZ format to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_gps_pos_lla() - @see mbg_get_gps_pos() -*/ + * @brief Set the GPS receiver position using ::XYZ coordinates + * + * The structure ::XYZ must specify the new position in ECEF + * (Earth Centered, Earth Fixed) kartesian coordinates. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Position in ::XYZ format to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_gps_pos_lla + * @see ::mbg_get_gps_pos + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_xyz( MBG_DEV_HANDLE dh, const XYZ p ) ; /** - Preset the GPS receiver position using ::LLA coordinates - (longitude, latitude, altitude) - The macro _pcps_is_gps() or the API call mbg_dev_is_gps() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param p Position in ::LLA format to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_gps_pos_xyz() - @see mbg_get_gps_pos() -*/ + * @brief Set the GPS receiver position using ::LLA coordinates + * + * The structure ::LLA must specify the new position as longitude, + * latitude, and altitude, using the WGS84 geographic datum. + * + * The API call ::mbg_chk_dev_is_gps checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Position in ::LLA format to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_gps_pos_xyz + * @see ::mbg_get_gps_pos + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_pos_lla( MBG_DEV_HANDLE dh, const LLA p ) ; /** - Read the configured length of the GPS antenna cable (::ANT_CABLE_LEN). - The cable delay is internally compensated by 5ns per meter cable. - The macro _pcps_has_cab_len() or the API call mbg_dev_has_cab_len() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p ::ANT_CABLE_LEN structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_cab_len() - @see mbg_set_gps_ant_cable_len() -*/ + * @brief Read the configured antenna cable length from a device + * + * The antenna cable length parameter is used by GPS/GNSS receivers + * to compensate the propagation delay of the RF signal over the antenna + * cable, which is about 5 ns/m. + * + * The API call ::mbg_chk_dev_has_cab_len checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an ::ANT_CABLE_LEN structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_cab_len + * @see ::mbg_set_gps_ant_cable_len + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_ant_cable_len( MBG_DEV_HANDLE dh, ANT_CABLE_LEN *p ) ; /** - Write the length of the GPS antenna cable (::ANT_CABLE_LEN). - The cable delay is internally compensated by 5ns per meter cable. - The macro _pcps_has_cab_len() or the API call mbg_dev_has_cab_len() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p ::ANT_CABLE_LEN structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_cab_len() - @see mbg_get_gps_ant_cable_len() -*/ + * @brief Write the GPS antenna cable length configuration to a device. + * + * The antenna cable length parameter is used by GPS/GNSS receivers + * to compensate the propagation delay of the RF signal over the antenna + * cable, which is about 5 ns/m. + * + * The API call ::mbg_chk_dev_has_cab_len checks whether + * this call is supported by a device. + * + * @note Different devices may accept different maximum values, so the + * written value should be re-read using ::mbg_get_gps_ant_cable_len + * to check if the parameter has been accepted. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an ::ANT_CABLE_LEN structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_cab_len + * @see ::mbg_get_gps_ant_cable_len + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_ant_cable_len( MBG_DEV_HANDLE dh, const ANT_CABLE_LEN *p ) ; /** - Read a ::RECEIVER_INFO structure from a card. - The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info() - check whether this call is supported by a specific card. - - <b>Note:</b> Applications should call mbg_setup_receiver_info() - preferably, which also sets up a basic ::RECEIVER_INFO structure - for card which don't provide that structure by themselves. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::RECEIVER_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_setup_receiver_info() -*/ + * @brief Read the ::RECEIVER_INFO structure from a device + * + * The API call ::mbg_chk_dev_has_receiver_info checks + * whether this call is supported by a device. + * + * <b>Note:</b> Applications should call ::mbg_setup_receiver_info + * preferably, which also sets up a basic ::RECEIVER_INFO structure + * for devices which don't provide that structure by themselves. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::RECEIVER_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_setup_receiver_info + * @see ::mbg_chk_dev_has_receiver_info + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_receiver_info( MBG_DEV_HANDLE dh, RECEIVER_INFO *p ) ; /** - Write the configuration for a single serial port using the ::PORT_SETTINGS_IDX - structure which contains both the ::PORT_SETTINGS and the port index value. - Except for the parameter types, this call is equivalent to mbg_set_gps_port_settings(). - The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info() - check whether this call is supported by a specific card. - - <b>Note:</b> The function mbg_save_serial_settings() should be used preferably - to write new port configuration to the board. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::PORT_SETTINGS_IDX structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_save_serial_settings() - @see mbg_set_gps_port_settings() - @see mbg_dev_has_receiver_info() -*/ - _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings_idx( MBG_DEV_HANDLE dh, const PORT_SETTINGS_IDX *p ) ; + * @brief Read a ::STR_TYPE_INFO_IDX array of supported string types. + * + * A valid ::RECEIVER_INFO associated with the device + * has to be passed to this function. + * + * <b>Note:</b> The function ::mbg_get_serial_settings should be used preferably + * to get retrieve the current port settings and configuration options. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] stii Pointer to a an array of string type information to be filled up. + * @param[in] p_ri Pointer to the ::RECEIVER_INFO associated with the device //### TODO Make this obsolete + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_serial_settings + * @see ::mbg_get_gps_all_port_info + * @see ::mbg_setup_receiver_info + */ + _MBG_API_ATTR int _MBG_API mbg_get_gps_all_str_type_info( MBG_DEV_HANDLE dh, STR_TYPE_INFO_IDX stii[], const RECEIVER_INFO *p_ri ) ; /** - Write the configuration for a single serial port using the ::PORT_SETTINGS - structure plus the port index. - Except for the parameter types, this call is equivalent to mbg_set_gps_port_settings_idx(). - The macro _pcps_has_receiver_info() or the API call mbg_dev_has_receiver_info() - check whether this call is supported by a specific card. - - <b>Note:</b> The function mbg_save_serial_settings() should be used preferably - to write new port configuration to the board. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::PORT_SETTINGS structure to be filled up - @param idx Index of the serial port to be configured (starting from 0 ). - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_save_serial_settings() - @see mbg_set_gps_port_settings_idx() - @see mbg_dev_has_receiver_info() -*/ - _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings( MBG_DEV_HANDLE dh, const PORT_SETTINGS *p, int idx ) ; + * @brief Read a ::PORT_INFO_IDX array of supported serial port configurations. + * + * A valid ::RECEIVER_INFO associated with the device + * has to be passed to this function. + * + * <b>Note:</b> The function ::mbg_get_serial_settings should be used preferably + * to get retrieve the current port settings and configuration options. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] pii Pointer to a an array of port configuration information to be filled up. + * @param[in] p_ri Pointer to the ::RECEIVER_INFO associated with the device //### TODO Make this obsolete + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_serial_settings + * @see ::mbg_get_gps_all_str_type_info + * @see ::mbg_setup_receiver_info + */ + _MBG_API_ATTR int _MBG_API mbg_get_gps_all_port_info( MBG_DEV_HANDLE dh, PORT_INFO_IDX pii[], const RECEIVER_INFO *p_ri ) ; /** - Set up a ::RECEIVER_INFO structure for a device. - If the device supports the ::RECEIVER_INFO structure then the structure - is read from the device, otherwise a structure is set up using - default values depending on the device type. - The function mbg_get_device_info() must have been called before, - and the returned PCPS_DEV structure passed to this function. - - @param dh Valid handle to a Meinberg device. - @param *pdev Pointer to a ::PCPS_DEV structure returned by mbg_get_device_info() - @param *p Pointer to a ::RECEIVER_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_device_info() - @see mbg_dev_has_receiver_info() -*/ - _MBG_API_ATTR int _MBG_API mbg_setup_receiver_info( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, RECEIVER_INFO *p ) ; + * @brief Write the configuration for a single serial port to a device. + * + * The ::PORT_SETTINGS_IDX structure contains both the ::PORT_SETTINGS + * and the port index value. Except for the parameter types this call is + * equivalent to ::mbg_set_gps_port_settings. + * + * The API call ::mbg_chk_dev_has_receiver_info checks + * whether this call is supported by a device. + * + * <b>Note:</b> The function ::mbg_save_serial_settings should be used preferably + * to write new port configuration to the board. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PORT_SETTINGS_IDX structure to be written + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_save_serial_settings + * @see ::mbg_set_gps_port_settings + * @see ::mbg_chk_dev_has_receiver_info + */ + _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings_idx( MBG_DEV_HANDLE dh, const PORT_SETTINGS_IDX *p ) ; /** - Read all serial port settings and supported configuration parameters. - - The functions mbg_get_device_info() and mbg_setup_receiver_info() - must have been called before, and the returned ::PCPS_DEV and - ::RECEIVER_INFO structures must be passed to this function. - - The complementary function mbg_save_serial_settings() should be used - to write the modified serial port configuration back to the board. - - @param dh Valid handle to a Meinberg device. - @param *pdev Pointer to a ::PCPS_DEV structure. - @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure to be filled up. - @param *p_ri Pointer to a ::RECEIVER_INFO structure. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_device_info() - @see mbg_setup_receiver_info() - @see mbg_save_serial_settings() -*/ - _MBG_API_ATTR int _MBG_API mbg_get_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, RECEIVER_PORT_CFG *pcfg, const RECEIVER_INFO *p_ri ) ; + * @brief Write the configuration for a single serial port to a device. + * + * The ::PORT_SETTINGS structure does not contain the port index, so the + * the port index must be given separately. Except for the parameter types + * this call is equivalent to ::mbg_set_gps_port_settings_idx. + * + * The API call ::mbg_chk_dev_has_receiver_info checks + * whether this call is supported by a device. + * + * <b>Note:</b> The function ::mbg_save_serial_settings should be used preferably + * to write new port configuration to the board. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::PORT_SETTINGS structure to be written. + * @param[in] idx Index of the serial port to be configured (starting from 0). + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_save_serial_settings + * @see ::mbg_set_gps_port_settings_idx + * @see ::mbg_chk_dev_has_receiver_info + */ + _MBG_API_ATTR int _MBG_API mbg_set_gps_port_settings( MBG_DEV_HANDLE dh, const PORT_SETTINGS *p, int idx ) ; /** - Write the configuration settings for a single serial port to the board. - - Modifications to the serial port configuration should be made only - after mbg_get_serial_settings() had been called to read all serial port - settings and supported configuration parameters. - This function has finally to be called once for every serial port - the configuration of which has been modified. - - As also required by mbg_get_serial_settings(), the functions - mbg_get_device_info() and mbg_setup_receiver_info() must have been - called before, and the returned ::PCPS_DEV and ::RECEIVER_INFO structures - must be passed to this function. - - @param dh Valid handle to a Meinberg device - @param *pdev Pointer to a ::PCPS_DEV structure - @param *pcfg Pointer to a ::RECEIVER_PORT_CFG structure - @param port_num Index of the ::serial port to be saved - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_serial_settings() - @see mbg_get_device_info() - @see mbg_setup_receiver_info() -*/ - _MBG_API_ATTR int _MBG_API mbg_save_serial_settings( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, RECEIVER_PORT_CFG *pcfg, int port_num ) ; + * @brief Set up a ::RECEIVER_INFO structure for a device. + * + * If the device supports the ::RECEIVER_INFO structure then the structure + * is read from the device, otherwise a structure is set up using + * default values depending on the device type. + * + * Optionally, the function ::mbg_get_device_info may have been called + * before, and the returned ::PCPS_DEV structure can be passed to this + * function. + * + * If a NULL pointer is passed instead, the device info is retrieved + * directly from the device, using the device handle. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p_dev Optional pointer to a ::PCPS_DEV structure, may be NULL. + * @param[out] p Pointer to a ::RECEIVER_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_device_info + * @see ::mbg_chk_dev_has_receiver_info + */ + _MBG_API_ATTR int _MBG_API mbg_setup_receiver_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, RECEIVER_INFO *p ) ; /** - Read the version code of the on-board PCI/PCIe interface ASIC. - The macro _pcps_has_asic_version() or the API call mbg_dev_has_asic_version() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCI_ASIC_VERSION type to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function - - @see mbg_dev_has_asic_version() -*/ + * @brief Read the version code of the on-board PCI/PCIe interface ASIC. + * + * The API call ::mbg_chk_dev_has_asic_version checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCI_ASIC_VERSION type to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_asic_version + */ _MBG_API_ATTR int _MBG_API mbg_get_asic_version( MBG_DEV_HANDLE dh, PCI_ASIC_VERSION *p ) ; /** - Read the features of the on-board PCI/PCIe interface ASIC. - The macro _pcps_has_asic_features() or the API call mbg_dev_has_asic_features() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::PCI_ASIC_FEATURES type to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_asic_features() -*/ + * @brief Read the features of the on-board PCI/PCIe interface ASIC + * + * The API call ::mbg_chk_dev_has_asic_features checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCI_ASIC_FEATURES type to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_asic_features + */ _MBG_API_ATTR int _MBG_API mbg_get_asic_features( MBG_DEV_HANDLE dh, PCI_ASIC_FEATURES *p ) ; /** - Check if a specific device supports configurable time scales. - - By default the cards return UTC and/or local time. However, some cards - can be configured to return pure GPS time or TAI instead. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_time_scale_info() - @see mbg_set_time_scale_settings() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_time_scale( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Read a ::MBG_TIME_SCALE_INFO structure from a card telling which time scales - are supported by a card, and the current settings of the card. - - The macro _pcps_has_time_scale() or the API call mbg_dev_has_time_scale() - check whether this call is supported by a specific card. - See also the notes for mbg_dev_has_time_scale(). - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_TIME_SCALE_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_time_scale_settings() - @see mbg_dev_has_time_scale() -*/ + * @brief Read the current time scale settings and which time scales are supported + * + * The ::MBG_TIME_SCALE_INFO structure tells which time scale settings are supported + * by a device, and which time scale is currently configured. + * + * The API call ::mbg_chk_dev_has_time_scale checks whether + * this call is supported by a device. + * + * See also the notes for ::mbg_chk_dev_has_time_scale. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_TIME_SCALE_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_time_scale_settings + * @see ::mbg_chk_dev_has_time_scale + */ _MBG_API_ATTR int _MBG_API mbg_get_time_scale_info( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_INFO *p ) ; /** - Write a ::MBG_TIME_SCALE_SETTINGS structure to a card which determines - which time scale shall be represented by time stamps read from the card. - - The macro _pcps_has_time_scale() or the API call mbg_dev_has_time_scale() - check whether this call is supported by a specific card. - See also the notes for mbg_dev_has_time_scale(). - - The function mbg_get_time_scale_info() should have been called before - in order to determine which time scales are supported by the card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_TIME_SCALE_SETTINGS structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_time_scale_info() - @see mbg_dev_has_time_scale() -*/ - _MBG_API_ATTR int _MBG_API mbg_set_time_scale_settings( MBG_DEV_HANDLE dh, MBG_TIME_SCALE_SETTINGS *p ) ; - - /** - Check if a specific device supports reading/writing a GPS UTC parameter - set via the PC bus (reading/writing these parameters via the serial port - is supported by all GPS devices). - - The UTC parameters are normally received from the satellites' broadcasts - and contain the current time offset between GPT time and UTC, plus information - on a pending leap second. - - It may be useful to overwrite them to do some tests, or for applications - where a card is freewheeling. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_utc_parm() - @see mbg_set_utc_parm() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_utc_parm( MBG_DEV_HANDLE dh, int *p ) ; + * @brief Write the time scale configuration to a device + * + * The ::MBG_TIME_SCALE_SETTINGS structure determines which time scale + * is to be used for the time stamps which can be read from a device. + * + * The API call ::mbg_chk_dev_has_time_scale checks whether + * this call is supported by a device. + * + * See also the notes for ::mbg_chk_dev_has_time_scale. + * + * The function ::mbg_get_time_scale_info should have been called before + * in order to determine which time scales are supported by the card. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::MBG_TIME_SCALE_SETTINGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_time_scale_info + * @see ::mbg_chk_dev_has_time_scale + */ + _MBG_API_ATTR int _MBG_API mbg_set_time_scale_settings( MBG_DEV_HANDLE dh, const MBG_TIME_SCALE_SETTINGS *p ) ; /** - Read a ::UTC structure from a card. - - The macro _pcps_has_utc_parm() or the API call mbg_dev_has_utc_parm() - check whether this call is supported by a specific card. - See also the notes for mbg_dev_has_utc_parm(). - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::UTC structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_utc_parm() - @see mbg_set_utc_parm() -*/ + * @brief Read a ::UTC parameter structure from a device + * + * The API call ::mbg_chk_dev_has_utc_parm checks whether + * this call is supported by a device. + * + * See also the notes for ::mbg_chk_dev_has_utc_parm. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::UTC structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_utc_parm + * @see ::mbg_set_utc_parm + */ _MBG_API_ATTR int _MBG_API mbg_get_utc_parm( MBG_DEV_HANDLE dh, UTC *p ) ; /** - Write a ::UTC structure to a card. - - This should only be done for testing, or if a card is operated in - freewheeling mode. If the card receives any satellites the settings - written to the board are overwritten by the parameters broadcasted - by the satellites. - - The macro _pcps_has_utc_parm() or the API call mbg_dev_has_utc_parm() - check whether this call is supported by a specific card. - See also the notes for mbg_dev_has_utc_parm(). - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a valid ::UTC structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_utc_parm() - @see mbg_get_utc_parm() -*/ - _MBG_API_ATTR int _MBG_API mbg_set_utc_parm( MBG_DEV_HANDLE dh, UTC *p ) ; + * @brief Write a ::UTC parameter structure to a device. + * + * This should only be done for testing, or if a card is operated in + * freewheeling mode. If the receiver is tracking any satellites then the settings + * written to the device are overwritten by the parameters broadcast + * by the satellites. + * + * The API call ::mbg_chk_dev_has_utc_parm checks whether + * this call is supported by a device. + * + * See also the notes for mbg_chk_dev_has_utc_parm. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a valid ::UTC structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_utc_parm + * @see ::mbg_get_utc_parm + */ + _MBG_API_ATTR int _MBG_API mbg_set_utc_parm( MBG_DEV_HANDLE dh, const UTC *p ) ; /** - Read a ::PCPS_TIME_CYCLES structure that contains a ::PCPS_TIME structure - and a PC cycle counter value which can be used to compensate the latency - of the call, i.e. the program execution time until the time stamp has actually - been read from the board. - - This call is supported for any card, similar to mbg_get_time(). However, - the mbg_get_hr_time_cyles() call should be used preferably if supported by - the specific card since that call provides much better accuracy than this one. - - The cycle counter value corresponds to a value returned by QueryPerformanceCounter() - under Windows, and get_cycles() under Linux. On other operating systems the returned - cycles value is always 0. - - Applications should first pick up their own cycle counter value and then call - this function. The difference of the cycle counter values corresponds to the - latency of the call in units of the cycle counter clock frequency, e.g as reported - by QueryPerformanceFrequency() under Windows. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME_CYCLES structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_hr_time_cycles() - @see mbg_get_hr_time_comp() - @see mbg_get_hr_time() - @see mbg_get_time() -*/ + * @brief Read the current time plus the associated PC cycles from a device. + * + * The ::PCPS_TIME_CYCLES structure contains a ::PCPS_TIME structure + * and a PC cycles counter value which can be used to compensate the latency + * of the call, i.e. the program execution time until the time stamp has actually + * been read from the board. + * + * This call is supported for any card, similar to ::mbg_get_time. However, + * the ::mbg_get_hr_time_cycles call should be used preferably if supported by + * the device since that call provides much better accuracy than this one. + * + * The cycles counter value corresponds to a value returned by QueryPerformanceCounter() + * under Windows, and get_cycles() under Linux. On operating systems or targets which don't + * provide a cycles counter the returned cycles value is always 0. + * + * Applications should first pick up their own cycles counter value and then call + * this function. The difference of the cycles counter values corresponds to the + * latency of the call in units of the cycles counter clock frequency, e.g as reported + * by QueryPerformanceFrequency() under Windows. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME_CYCLES structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_legacy_time_fncs + * @see ::mbg_get_hr_time_cycles + * @see ::mbg_get_hr_time_comp + * @see ::mbg_get_hr_time + * @see ::mbg_get_time + */ _MBG_API_ATTR int _MBG_API mbg_get_time_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_CYCLES *p ) ; /** - Read a ::PCPS_HR_TIME_CYCLES structure that contains a ::PCPS_HR_TIME structure - and a PC cycle counter value which can be used to compensate the latency - of the call, i.e. the program execution time until the time stamp has actually - been read from the board. - - The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() - check whether this call is supported by a specific card. - - The cycle counter value corresponds to a value returned by QueryPerformanceCounter() - under Windows, and get_cycles() under Linux. On other operating systems the returned - cycles value is always 0. - - Applications should first pick up their own cycle counter value and then call - this function. The difference of the cycle counter values corresponds to the - latency of the call in units of the cycle counter clock frequency, e.g as reported - by QueryPerformanceFrequency() under Windows. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_HR_TIME_CYCLES structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_hr_time_comp() - @see mbg_get_hr_time() - @see mbg_get_time_cycles() - @see mbg_get_time() -*/ + * @brief Read the current high resolution time plus the associated PC cycles from a device. + * + * The returned ::PCPS_HR_TIME_CYCLES structure contains a ::PCPS_HR_TIME + * structure and a PC cycles counter value which can be used to compensate + * the latency of the call, i.e. the program execution time until the time stamp + * has actually been read from the board. + * + * The API call ::mbg_chk_dev_has_hr_time checks whether + * this call is supported by the device. + * + * For details see @ref ::mbgdevio_hr_time_fncs + * + * The cycles counter value corresponds to a value returned by QueryPerformanceCounter() + * under Windows, and get_cycles() under Linux. On operating systems or targets which don't + * provide a cycles counter the returned cycles value is always 0. + * + * Applications should first pick up their own cycles counter value and then call + * this function. The difference of the cycles counter values corresponds to the + * latency of the call in units of the cycles counter clock frequency, e.g as reported + * by QueryPerformanceFrequency() under Windows. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_HR_TIME_CYCLES structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_hr_time_fncs + * @see ::mbg_chk_dev_has_hr_time + * @see ::mbg_get_hr_time + * @see ::mbg_get_hr_time_cycles + * @see ::mbg_get_hr_time_comp + * @see @ref mbgdevio_hr_time_fncs + * @see @ref mbgdevio_fast_timestamp_fncs + * @see @ref mbgdevio_legacy_time_fncs + */ _MBG_API_ATTR int _MBG_API mbg_get_hr_time_cycles( MBG_DEV_HANDLE dh, PCPS_HR_TIME_CYCLES *p ) ; /** - Read a ::PCPS_HR_TIME structure plus cycle counter value, and correct the - time stamp for the latency of the call as described for mbg_get_hr_time_cycles(), - then return the compensated time stamp and optionally the latency. - - The macro _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() - check whether this call is supported by a specific card. - - The cycle counter value corresponds to a value returned by QueryPerformanceCounter() - under Windows, and get_cycles() under Linux. On other operating systems the returned - cycles value is always 0. - - Applications should first pick up their own cycle counter value and then call - this function. The difference of the cycle counter values corresponds to the - latency of the call in units of the cycle counter clock frequency, e.g as reported - by QueryPerformanceFrequency() under Windows. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_HR_TIME structure to be filled up - @param *hns_latency Optional pointer to an int32_t value to return - the latency in 100ns units. Pass NULL if not used. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_hr_time_comp() - @see mbg_get_hr_time() - @see mbg_get_time_cycles() - @see mbg_get_time() -*/ + * @brief Read the current high resolution time, and compensate the call's latency. + * + * Read a ::PCPS_HR_TIME structure plus cycles counter value, and correct the + * time stamp for the latency of the call as described for ::mbg_get_hr_time_cycles, + * then return the compensated time stamp, and optionally the latency. + * + * The API call ::mbg_chk_dev_has_hr_time checks whether + * this call is supported by the device. + * + * For details see @ref ::mbgdevio_hr_time_fncs + * + * The cycles counter value corresponds to a value returned by QueryPerformanceCounter() + * under Windows, and get_cycles() under Linux. On operating systems or targets which don't + * provide a cycles counter the returned cycles value is always 0. + * + * Applications should first pick up their own cycles counter value and then call + * this function. The difference of the cycles counter values corresponds to the + * latency of the call in units of the cycles counter clock frequency, e.g as reported + * by QueryPerformanceFrequency() under Windows. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_HR_TIME structure to be filled up + * @param[out] hns_latency Optional pointer to an int32_t value to return + * the latency in 100ns units, or NULL, if not used. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_hr_time_fncs + * @see ::mbg_chk_dev_has_hr_time + * @see ::mbg_get_hr_time + * @see ::mbg_get_hr_time_cycles + * @see ::mbg_get_hr_time_comp + * @see @ref mbgdevio_hr_time_fncs + * @see @ref mbgdevio_fast_timestamp_fncs + * @see @ref mbgdevio_legacy_time_fncs + */ _MBG_API_ATTR int _MBG_API mbg_get_hr_time_comp( MBG_DEV_HANDLE dh, PCPS_HR_TIME *p, int32_t *hns_latency ) ; /** - Read an ::IRIG_INFO structure containing the configuration of an IRIG output - plus the possible settings supported by that output. - The macro _pcps_has_irig_tx() or the API call mbg_dev_has_irig_tx() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an ::IRIG_INFO structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_irig_tx_settings() - @see mbg_dev_has_irig_tx() - @see mbg_dev_is_irig_rx() - @see mbg_dev_has_irig() - @see \ref group_icode -*/ + * @brief Read the current IRIG output settings plus the supported settings. + * + * The returned ::IRIG_INFO structure contains the configuration of an IRIG output + * plus the possible settings supported by that output. + * + * The API call ::mbg_chk_dev_has_irig_tx checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to an ::IRIG_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_irig_tx_settings + * @see ::mbg_chk_dev_has_irig_tx + * @see ::mbg_chk_dev_is_tcr + * @see ::mbg_chk_dev_has_irig + * @see @ref group_icode + */ _MBG_API_ATTR int _MBG_API mbg_get_irig_tx_info( MBG_DEV_HANDLE dh, IRIG_INFO *p ) ; /** - Write an ::IRIG_SETTINGS structure containing the configuration of an IRIG output. - The macro _pcps_has_irig_tx() or the API call mbg_dev_has_irig_tx() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an ::IRIG_INFO structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_irig_tx_info() - @see mbg_dev_has_irig_tx() - @see mbg_dev_is_irig_rx() - @see mbg_dev_has_irig() - @see \ref group_icode -*/ + * @brief Write an ::IRIG_SETTINGS structure to a device to configure the IRIG output + * + * The API call ::mbg_chk_dev_has_irig_tx checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to an ::IRIG_INFO structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_irig_tx_info + * @see ::mbg_chk_dev_has_irig_tx + * @see ::mbg_chk_dev_is_tcr + * @see ::mbg_chk_dev_has_irig + * @see @ref group_icode + */ _MBG_API_ATTR int _MBG_API mbg_set_irig_tx_settings( MBG_DEV_HANDLE dh, const IRIG_SETTINGS *p ) ; /** - Read a ::SYNTH structure containing the configuration of an optional - on-board programmable frequency synthesizer. - The macro _pcps_has_synth() or the API call mbg_dev_has_synth() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::SYNTH structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_synth() - @see mbg_set_synth() - @see mbg_get_synth_state() - @see \ref group_synth -*/ + * @brief Read the current frequency synthesizer settings from a device + * + * Read a ::SYNTH structure containing the configuration of an optional + * on-board programmable frequency synthesizer. + * + * The API call ::mbg_chk_dev_has_synth checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::SYNTH structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_synth + * @see ::mbg_set_synth + * @see ::mbg_get_synth_state + * @see @ref group_synth + */ _MBG_API_ATTR int _MBG_API mbg_get_synth( MBG_DEV_HANDLE dh, SYNTH *p ) ; /** - Write a ::SYNTH structure containing the configuration of an optional - on-board programmable frequency synthesizer. - The macro _pcps_has_synth() or the API call mbg_dev_has_synth() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::SYNTH structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_synth() - @see mbg_get_synth() - @see mbg_get_synth_state() - @see \ref group_synth -*/ + * @brief Write frequency synthesizer configuration settings to a device + * + * Write a ::SYNTH structure containing the configuration of an optional + * on-board programmable frequency synthesizer. + * + * The API call ::mbg_chk_dev_has_synth checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::SYNTH structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_synth + * @see ::mbg_get_synth + * @see ::mbg_get_synth_state + * @see @ref group_synth + */ _MBG_API_ATTR int _MBG_API mbg_set_synth( MBG_DEV_HANDLE dh, const SYNTH *p ) ; /** - Read a ::SYNTH_STATE structure reporting the current state - of an optional on-board programmable frequency synthesizer. - The macro _pcps_has_synth() or the API call mbg_dev_has_synth() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::SYNTH_STATE structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_synth() - @see mbg_get_synth() - @see mbg_set_synth() - @see \ref group_synth -*/ + * @brief Read the current status of the on-board frequency synthesizer + * + * The API call ::mbg_chk_dev_has_synth checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::SYNTH_STATE structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_synth + * @see ::mbg_get_synth + * @see ::mbg_set_synth + * @see @ref group_synth + */ _MBG_API_ATTR int _MBG_API mbg_get_synth_state( MBG_DEV_HANDLE dh, SYNTH_STATE *p ) ; /** - Check if a specific device supports the mbg_get_fast_hr_timestamp_...() calls. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_fast_hr_timestamp_cycles() - @see mbg_get_fast_hr_timestamp_comp() - @see mbg_get_fast_hr_timestamp() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_fast_hr_timestamp( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Read a high resolution ::PCPS_TIME_STAMP_CYCLES structure via memory mapped access. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME_STAMP_CYCLES structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_fast_hr_timestamp() - @see mbg_get_fast_hr_timestamp_comp() - @see mbg_get_fast_hr_timestamp() -*/ + * @brief Read a high resolution ::PCPS_TIME_STAMP_CYCLES structure via memory mapped access. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME_STAMP_CYCLES structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_fast_timestamp_fncs + * @see ::mbg_chk_dev_has_fast_hr_timestamp + * @see ::mbg_get_fast_hr_timestamp_comp + * @see ::mbg_get_fast_hr_timestamp + * @see @ref mbgdevio_fast_timestamp_fncs + */ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_cycles( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP_CYCLES *p ) ; /** - Read a high resolution ::PCPS_TIME_STAMP via memory mapped access, - and compensate the latency of the time stamp before it is returned. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME_STAMP structure to be filled up - @param *hns_latency Optionally receive the latency in hectonanoseconds - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_fast_hr_timestamp() - @see mbg_get_fast_hr_timestamp_cycles() - @see mbg_get_fast_hr_timestamp() -*/ + * @brief Read a high resolution timestamp and compensate the latency of the call + * + * The retrieved ::PCPS_TIME_STAMP is read from memory mapped registers, + * and timestamp is compensated for the call's latency before it is returned. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME_STAMP structure to be filled up + * @param[out] hns_latency Optionally receives the latency in hectonanoseconds //### TODO Check if hns + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_fast_timestamp_fncs + * @see ::mbg_chk_dev_has_fast_hr_timestamp + * @see ::mbg_get_fast_hr_timestamp_cycles + * @see ::mbg_get_fast_hr_timestamp + * @see @ref mbgdevio_fast_timestamp_fncs + */ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp_comp( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP *p, int32_t *hns_latency ) ; /** - Read a high resolution ::PCPS_TIME_STAMP structure via memory mapped access. - - This function does not return or evaluate a cycles count, so the latency - of the call can not be determined. However, depending on the timer hardware - used as cycles counter it may take quite some time to read the cycles count - on some hardware architectures, so this call can be used to yield lower - latencies, under the restriction to be unable to determine the exact latency. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_TIME_STAMP structure to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_fast_hr_timestamp() - @see mbg_get_fast_hr_timestamp_comp() - @see mbg_get_fast_hr_timestamp_cycles() -*/ + * @brief Read a high resolution ::PCPS_TIME_STAMP structure via memory mapped access + * + * This function does not return or evaluate a cycles count, so the latency + * of the call can not be determined. However, depending on the timer hardware + * used as cycles counter it may take quite some time to read the cycles count + * on some hardware architectures, so this call can be used to yield lower + * latencies, under the restriction to be unable to determine the exact latency. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_TIME_STAMP structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup mbgdevio_fast_timestamp_fncs + * @see ::mbg_chk_dev_has_fast_hr_timestamp + * @see ::mbg_get_fast_hr_timestamp_comp + * @see ::mbg_get_fast_hr_timestamp_cycles + * @see @ref mbgdevio_fast_timestamp_fncs + */ _MBG_API_ATTR int _MBG_API mbg_get_fast_hr_timestamp( MBG_DEV_HANDLE dh, PCPS_TIME_STAMP *p ) ; /** - Check if a specific device is a GPS receiver. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_is_gps( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device is a DCF77 receiver. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_is_dcf( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device is a MSF receiver. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_is_msf( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device is a WWVB receiver. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_is_wwvb( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device is a long wave signal receiver, e.g. DCF77, MSF or WWVB. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_is_lwr( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device is an IRIG receiver which supports - configuration of the IRIG input. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_irig_rx_info() - @see mbg_set_irig_rx_settings() - @see mbg_dev_has_irig_tx() - @see mbg_dev_has_irig() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_is_irig_rx( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports the HR_TIME functions. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_hr_time() - @see mbg_get_hr_time_cycles() - @see mbg_get_hr_time_comp() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_hr_time( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports configuration of antenna cable length. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_gps_ant_cable_len() - @see mbg_set_gps_ant_cable_len() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_cab_len( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports timezone / daylight saving configuration - using the ::TZDL structure. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_gps_tzdl() - @see mbg_set_gps_tzdl() - @see mbg_dev_has_tz() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_tzdl( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports timezone / daylight saving configuration - using the ::PCPS_TZDL structure. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_pcps_tzdl() - @see mbg_set_pcps_tzdl() - @see mbg_dev_has_tz() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_pcps_tzdl( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports timezone configuration - using the ::PCPS_TZCODE type. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_tzcode() - @see mbg_set_tzcode() - @see mbg_dev_has_tz() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_tzcode( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports any kind of timezone configuration. - This can be used e.g. to check if a specifig dialog or menu has to - be displayed. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_tzdl() - @see mbg_dev_has_pcps_tzdl() - @see mbg_dev_has_tzcode() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_tz( MBG_DEV_HANDLE dh, int *p ) ; - - /* (Intentionally excluded from Doxygen) - Check if a specific device supports setting an event time, i.e. - configure a %UTC time when the clock shall generate an event. - - <b>Note:</b> This is only supported by some special firmware. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_event_time() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_event_time( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports the ::RECEIVER_INFO structure and related calls. - Older GPS devices may not support that structure. - - The mbg_get_gps_receiver_info() call uses this call to decide whether a - ::RECEIVER_INFO can be read directly from a device, or whether a default - structure has to be set up using default values depending on the device type. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_gps_receiver_info() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_receiver_info( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports the mbg_clr_ucap_buff() call - used to clear a card's on-board time capture FIFO buffer. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_clr_ucap_buff() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_can_clr_ucap_buff( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports the mbg_get_ucap_entries() and - mbg_get_ucap_event() calls. - - If the card does not but it is a GPS card then the card provides - a time capture FIFO buffer and the obsolete mbg_get_gps_ucap() - call can be used to retrieve entries from the FIFO buffer. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_ucap_entries() - @see mbg_get_ucap_event() - @see mbg_clr_ucap_buff() - @see mbg_get_gps_ucap() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_ucap( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device provides an IRIG output which can - be configured. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_irig_tx_info() - @see mbg_set_irig_tx_settings() - @see mbg_dev_is_irig_rx() - @see mbg_dev_has_irig() - @see \ref group_icode - -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_irig_tx( MBG_DEV_HANDLE dh, int *p ) ; - - /* (Intentionally excluded from Doxygen) - Check if a specific device provides a serial output supporting - higher baud rates than older cards, i.e. ::DEFAULT_BAUD_RATES_DCF_HS - rather than ::DEFAULT_BAUD_RATES_DCF. - - The mbg_get_serial_settings() takes care of this, so applications - which use that call as suggested won't need to use this call directly. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_serial_settings() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_serial_hs( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device provides an input signal level value which - may be displayed, e.g. DCF77 or IRIG cards. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_signal( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device provides an modulation signal which may be - displayed, e.g. the second marks of a DCF77 AM receiver. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_mod( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device provides either an IRIG input or output. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_is_irig_rx() - @see mbg_dev_has_irig_tx() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_irig( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device provides a configurable ref time offset - required to convert the received time to %UTC. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_ref_offs() - @see mbg_set_ref_offs() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_ref_offs( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports the ::MBG_OPT_INFO/::MBG_OPT_SETTINGS - structures containing optional settings, controlled by flags. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_opt_info() - @see mbg_set_opt_settings() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_opt_flags( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports large configuration data structures - as have been introducesde with the GPS receivers. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_gps_data( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device provides a programmable frequency synthesizer. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_synth() - @see mbg_set_synth() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_synth( MBG_DEV_HANDLE dh, int *p ) ; - - /* (Intentionally excluded from Doxygen) - Check if a specific device supports the mbg_generic_io() call. - - <b>Warning</b>: That call is for debugging purposes and internal use only! - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_generic_io() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_generic_io( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports the mbg_get_asic_version() call. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_asic_version() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_asic_version( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device supports the mbg_get_asic_features() call. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_asic_features() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_asic_features( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Read a ::POUT_INFO_IDX array of current settings and configuration - options of a card's programmable pulse outputs. - The function mbg_setup_receiver_info() must have been called before, - and the returned ::RECEIVER_INFO structure passed to this function. - The function should only be called if the ::RECEIVER_INFO::n_prg_out - field (i.e. the number of programmable outputs on the board) is not 0. - - The array passed to this function to receive the returned data - must be able to hold at least ::RECEIVER_INFO::n_prg_out elements. - - @param dh Valid handle to a Meinberg device. - @param pii Pointer to a an array of ::POUT_INFO_IDX structures to be filled up - @param *p_ri Pointer to a ::RECEIVER_INFO structure returned by mbg_setup_receiver_info() - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_set_gps_pout_settings_idx() - @see mbg_set_gps_pout_settings() - @see mbg_setup_receiver_info() -*/ + * @brief Read current configuraton and features provided by the programmable pulse outputs. + * + * Read a ::POUT_INFO_IDX array of current settings and configuration + * options of the device's programmable pulse outputs. + * + * A valid ::RECEIVER_INFO associated with the device + * has to be passed to this function. + * + * The function should only be called if the ::RECEIVER_INFO::n_prg_out + * field (i.e. the number of programmable outputs on the board) is not 0. + * + * The array passed to this function to receive the returned data + * must be able to hold at least ::RECEIVER_INFO::n_prg_out elements. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] pii Pointer to a an array of ::POUT_INFO_IDX structures to be filled up + * @param[in] p_ri Pointer to the ::RECEIVER_INFO associated with the device //### TODO Make this obsolete + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_gps_pout_settings_idx + * @see ::mbg_set_gps_pout_settings + * @see ::mbg_setup_receiver_info + */ _MBG_API_ATTR int _MBG_API mbg_get_gps_all_pout_info( MBG_DEV_HANDLE dh, POUT_INFO_IDX pii[], const RECEIVER_INFO *p_ri ) ; /** - Write the configuration for a single programmable pulse output using - the ::POUT_SETTINGS_IDX structure which contains both the ::POUT_SETTINGS - and the output index value. - Except for the parameter types, this call is equivalent to - mbg_set_gps_pout_settings(). - The function should only be called if the ::RECEIVER_INFO::n_prg_out field - (i.e. the number of programmable outputs on the board) is not 0, and the - output index value must be in the range 0..::RECEIVER_INFO::n_prg_out. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::POUT_SETTINGS_IDX structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_gps_all_pout_info() - @see mbg_set_gps_pout_settings() -*/ + * @brief Write the configuration for a single programmable pulse output + * + * The ::POUT_SETTINGS_IDX structure contains both the ::POUT_SETTINGS + * and the output index value. Except for the parameter types this call + * is equivalent to ::mbg_set_gps_pout_settings. + * + * The function should only be called if the ::RECEIVER_INFO::n_prg_out field + * (i.e. the number of programmable outputs on the board) is not 0, and the + * output index value must be in the range 0..::RECEIVER_INFO::n_prg_out. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::POUT_SETTINGS_IDX structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_gps_all_pout_info + * @see ::mbg_set_gps_pout_settings + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings_idx( MBG_DEV_HANDLE dh, const POUT_SETTINGS_IDX *p ) ; /** - Write the configuration for a single programmable pulse output using - the ::POUT_SETTINGS structure plus the index of the output to be configured. - Except for the parameter types, this call is equivalent to - mbg_set_gps_pout_settings_idx(). - The function should only be called if the ::RECEIVER_INFO::n_prg_out field - (i.e. the number of programmable outputs on the board) is not 0, and the - output index value must be in the range 0..::RECEIVER_INFO::n_prg_out. - - @param dh Valid handle to a Meinberg device. - @param *p Pointer to a ::POUT_SETTINGS structure to be written - @param idx Index of the programmable pulse output to be configured (starting from 0 ). - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_gps_all_pout_info() - @see mbg_set_gps_pout_settings_idx() -*/ + * @brief Write the configuration for a single programmable pulse output + * + * The ::POUT_SETTINGS structure does not contain the index of the + * programmable output to be configured, so the index must explicitly + * be passed to this function. Except for the parameter types this call + * is equivalent to ::mbg_set_gps_pout_settings_idx. + * + * The function should only be called if the ::RECEIVER_INFO::n_prg_out field + * (i.e. the number of programmable outputs on the board) is not 0, and the + * output index value must be in the range 0..::RECEIVER_INFO::n_prg_out. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::POUT_SETTINGS structure to be written. + * @param[in] idx Index of the programmable pulse output to be configured (starting from 0 ). + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_gps_all_pout_info + * @see ::mbg_set_gps_pout_settings_idx + */ _MBG_API_ATTR int _MBG_API mbg_set_gps_pout_settings( MBG_DEV_HANDLE dh, const POUT_SETTINGS *p, int idx ) ; /** - Read a card's IRQ status information which includes flags indicating - whether IRQs are currently enabled, and whether IRQ support by a card - is possibly unsafe due to the firmware and interface chip version. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PCPS_IRQ_STAT_INFO variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - */ + * @brief Read a device's IRQ status information. + * + * IRQ status information includes flags indicating whether IRQs are + * actually enabled, and whether IRQ support by a card is possibly + * unsafe due to the firmware and interface chip version. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PCPS_IRQ_STAT_INFO variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see @ref PCPS_IRQ_STAT_INFO_DEFS + */ _MBG_API_ATTR int _MBG_API mbg_get_irq_stat_info( MBG_DEV_HANDLE dh, PCPS_IRQ_STAT_INFO *p ) ; /** - Check if a specific device provides simple LAN interface API calls. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_lan_if_info() - @see mbg_get_ip4_state() - @see mbg_get_ip4_settings() - @see mbg_set_ip4_settings() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_lan_intf( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Read LAN interface information from a card which supports this. - The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::LAN_IF_INFO variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_lan_intf() - @see mbg_get_ip4_state() - @see mbg_get_ip4_settings() - @see mbg_set_ip4_settings() - */ + * @brief Read LAN interface information from a device + * + * The API call ::mbg_chk_dev_has_lan_intf checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::LAN_IF_INFO variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_get_ip4_state + * @see ::mbg_get_ip4_settings + * @see ::mbg_set_ip4_settings + */ _MBG_API_ATTR int _MBG_API mbg_get_lan_if_info( MBG_DEV_HANDLE dh, LAN_IF_INFO *p ) ; /** - Read LAN IPv4 state from a card which supports this. - The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::IP4_SETTINGS variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_lan_intf() - @see mbg_get_lan_if_info() - @see mbg_get_ip4_settings() - @see mbg_set_ip4_settings() - */ + * @brief Read LAN IPv4 state from a device + * + * The API call ::mbg_chk_dev_has_lan_intf checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::IP4_SETTINGS variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_get_lan_if_info + * @see ::mbg_get_ip4_settings + * @see ::mbg_set_ip4_settings + */ _MBG_API_ATTR int _MBG_API mbg_get_ip4_state( MBG_DEV_HANDLE dh, IP4_SETTINGS *p ) ; /** - Read LAN IPv4 settings from a card which supports this. - The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::IP4_SETTINGS variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_lan_intf() - @see mbg_get_lan_if_info() - @see mbg_get_ip4_state() - @see mbg_set_ip4_settings() - */ + * @brief Read LAN IPv4 settings from a device. + * + * The API call ::mbg_chk_dev_has_lan_intf checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::IP4_SETTINGS variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_get_lan_if_info + * @see ::mbg_get_ip4_state + * @see ::mbg_set_ip4_settings + */ _MBG_API_ATTR int _MBG_API mbg_get_ip4_settings( MBG_DEV_HANDLE dh, IP4_SETTINGS *p ) ; /** - Write LAN IPv4 settings to a card which supports this. - The macro _pcps_has_lan_intf() or the API call mbg_dev_has_lan_intf() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p ::IP4_SETTINGS structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_lan_intf() - @see mbg_get_lan_if_info() - @see mbg_get_ip4_settings() -*/ + * @brief Write LAN IPv4 settings to a device + * + * The API call ::mbg_chk_dev_has_lan_intf checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p ::IP4_SETTINGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_lan_intf + * @see ::mbg_get_lan_if_info + * @see ::mbg_get_ip4_settings + */ _MBG_API_ATTR int _MBG_API mbg_set_ip4_settings( MBG_DEV_HANDLE dh, const IP4_SETTINGS *p ) ; /** - Check if a specific device provides PTP configuration/status calls. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_ptp_state() - @see mbg_get_ptp_cfg_info() - @see mbg_set_ptp_cfg_settings() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_ptp( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Check if a specific device provides PTP Unicast feature/configuration. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_get_ptp_state() - @see mbg_get_ptp_uc_master_cfg_limits() - @see mbg_get_all_ptp_uc_master_info() - @see mbg_set_ptp_unicast_cfg_settings() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_ptp_unicast( MBG_DEV_HANDLE dh, int *p ) ; - - /** - Read PTP/IEEE1588 status from a card which supports this. - The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PTP_CFG_INFO variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ptp() - @see mbg_get_ptp_cfg_info() - @see mbg_set_ptp_cfg_settings() - */ + * @brief Read PTP/IEEE1588 status from a device + * + * The API call ::mbg_chk_dev_has_ptp checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PTP_STATE variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ptp + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_cfg_info + * @see ::mbg_set_ptp_cfg_settings + * @see ::mbg_chk_dev_has_ptp_unicast + */ _MBG_API_ATTR int _MBG_API mbg_get_ptp_state( MBG_DEV_HANDLE dh, PTP_STATE *p ) ; /** - Read PTP/IEEE1588 config info and current settings from a card which supports this. - The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PTP_CFG_INFO variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ptp() - @see mbg_get_ptp_state() - @see mbg_set_ptp_cfg_settings() - */ + * @brief Read PTP/IEEE1588 config info and current settings from a device + * + * The API call ::mbg_chk_dev_has_ptp checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PTP_CFG_INFO variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ptp + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_state + * @see ::mbg_set_ptp_cfg_settings + * @see ::mbg_chk_dev_has_ptp_unicast + */ _MBG_API_ATTR int _MBG_API mbg_get_ptp_cfg_info( MBG_DEV_HANDLE dh, PTP_CFG_INFO *p ) ; /** - Write PTP/IEEE1588 configuration settings to a card which supports this. - The macro _pcps_has_ptp() or the API call mbg_dev_has_ptp() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p ::PTP_CFG_SETTINGS structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ptp() - @see mbg_get_ptp_state() - @see mbg_get_ptp_cfg_info() -*/ + * @brief Write PTP/IEEE1588 configuration settings to a device. + * + * The API call ::mbg_chk_dev_has_ptp checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p ::PTP_CFG_SETTINGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ptp + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_state + * @see ::mbg_get_ptp_cfg_info + * @see ::mbg_chk_dev_has_ptp_unicast + */ _MBG_API_ATTR int _MBG_API mbg_set_ptp_cfg_settings( MBG_DEV_HANDLE dh, const PTP_CFG_SETTINGS *p ) ; /** - Read PTP/IEEE1588 unicast config info and current settings from a card which supports this. - The macro _pcps_has_ri_ptp_unicast() or the API call mbg_dev_has_ptp_unicast() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::PTP_UNICAST_CFG_INFO variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ptp_unicast() - @see mbg_set_ptp_unicast_cfg_settings() - */ + * @brief Read PTP/IEEE1588 unicast master configuration limits from a device. + * + * The API call ::mbg_chk_dev_has_ptp_unicast checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::PTP_UC_MASTER_CFG_LIMITS variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ptp_unicast + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_all_ptp_uc_master_info + * @see ::mbg_set_ptp_uc_master_settings_idx + * @see ::mbg_get_ptp_state + */ _MBG_API_ATTR int _MBG_API mbg_get_ptp_uc_master_cfg_limits( MBG_DEV_HANDLE dh, PTP_UC_MASTER_CFG_LIMITS *p ) ; /** - Read a ::IOCTL_SET_PTP_UNICAST_CFG_SETTINGS array of current settings and configuration - options of a card's programmable pulse outputs. - The function mbg_setup_receiver_info() must have been called before, - and the returned ::RECEIVER_INFO structure passed to this function. - The function should only be called if the ::RECEIVER_INFO::n_prg_out - field (i.e. the number of programmable outputs on the board) is not 0. - - The array passed to this function to receive the returned data - must be able to hold at least ::RECEIVER_INFO::n_prg_out elements. - - @param dh Valid handle to a Meinberg device. - @param pii Pointer to a an array of ::PTP_UC_MASTER_INFO_IDX structures to be filled up - @param p_umsl Pointer to a ::PTP_UC_MASTER_CFG_LIMITS structure returned by mbg_get_ptp_uc_master_cfg_limits() - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see //##++++++++++++++++++++++ - @see - @see -*/ + * @brief Read PTP Unicast master settings and configuration options. + * + * The array passed to this function to receive the returned data + * must be able to hold at least ::PTP_UC_MASTER_CFG_LIMITS::n_supp_master elements. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] pii Pointer to a an array of ::PTP_UC_MASTER_INFO_IDX structures to be filled up. + * @param[in] p_umsl Pointer to a ::PTP_UC_MASTER_CFG_LIMITS structure returned by ::mbg_get_ptp_uc_master_cfg_limits + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ptp_unicast + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_uc_master_cfg_limits + * @see ::mbg_set_ptp_uc_master_settings_idx + * @see ::mbg_get_ptp_state + */ _MBG_API_ATTR int _MBG_API mbg_get_all_ptp_uc_master_info( MBG_DEV_HANDLE dh, PTP_UC_MASTER_INFO_IDX pii[], const PTP_UC_MASTER_CFG_LIMITS *p_umsl ) ; /** - Write PTP/IEEE1588 unicast configuration settings to a card which supports this. - The macro _pcps_has_ri_ptp_unicast() or the API call mbg_dev_has_ptp_unicast() - check whether this call is supported by a specific card. - - @param dh Valid handle to a Meinberg device. - @param *p ::PTP_UNICAST_CFG_SETTINGS structure to be written - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_ptp_unicast() - @see mbg_get_ptp_state() - @see mbg_get_ptp_cfg_info() - @see mbg_get_ptp_unicast_cfg_info() -*/ + * @brief Write PTP/IEEE1588 unicast configuration settings to a device + * + * The API call ::mbg_chk_dev_has_ptp_unicast checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p ::PTP_UC_MASTER_SETTINGS_IDX structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_ptp_unicast + * @see ::mbg_get_all_ptp_cfg_info + * @see ::mbg_get_ptp_uc_master_cfg_limits + * @see ::mbg_get_all_ptp_uc_master_info + * @see ::mbg_get_ptp_state + */ _MBG_API_ATTR int _MBG_API mbg_set_ptp_uc_master_settings_idx( MBG_DEV_HANDLE dh, const PTP_UC_MASTER_SETTINGS_IDX *p ) ; /** - Read system time and card time from the kernel driver. The kernel - driver reads the current system time plus a HR time structure from - a card immediately after each other. The returned info structure also - contains some cycles counts to be able to determine the execution times - required to read those time stamps. - - The advantage of this call compared to mbg_get_time_info_tstamp() is - that this call also returns the card's status. On the other hand, reading - the HR time from the card may block e.g. if another application accesses - the board. - - This call makes a mbg_get_hr_time_cycles() call internally so the macro - _pcps_has_hr_time() or the API call mbg_dev_has_hr_time() can be - used to check whether this call is supported with a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_TIME_INFO_HRT variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_hr_time() - @see mbg_get_time_info_tstamp() - */ + * @brief Read both system time and associated device time from the kernel driver + * + * The kernel driver reads the current system time plus a HR time structure + * from a card immediately after each other. The returned info structure also + * contains some cycles counts to be able to determine the execution times + * required to read those time stamps. + * + * The advantage of this call compared to ::mbg_get_time_info_tstamp is + * that this call also returns the card's status. On the other hand, reading + * the HR time from the card may block e.g. if another application accesses + * the board. + * + * This call makes a ::mbg_get_hr_time_cycles call internally so the API call + * ::mbg_chk_dev_has_hr_time can be used to check whether this call is supported + * by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_TIME_INFO_HRT structure to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_hr_time + * @see ::mbg_get_time_info_tstamp + */ _MBG_API_ATTR int _MBG_API mbg_get_time_info_hrt( MBG_DEV_HANDLE dh, MBG_TIME_INFO_HRT *p ) ; /** - This call is similar to mbg_get_time_info_hrt() except that a - mbg_get_fast_hr_timestamp_cycles() call is made internally, so the macro - _pcps_has_fast_hr_timestamp() or the API call mbg_dev_has_fast_hr_timestamp() - can be used to check whether this call is supported with a specific card. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::MBG_TIME_INFO_TSTAMP variable to be filled up - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_fast_hr_timestamp() - @see mbg_get_time_info_hrt() - */ + * @brief Read both system time and associated device timestamp from the kernel driver + * + * This call is similar to ::mbg_get_time_info_hrt except that a + * ::mbg_get_fast_hr_timestamp_cycles call is made internally, so + * the API call ::mbg_chk_dev_has_fast_hr_timestamp can be used to check whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_TIME_INFO_TSTAMP structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_fast_hr_timestamp + * @see ::mbg_get_time_info_hrt + */ _MBG_API_ATTR int _MBG_API mbg_get_time_info_tstamp( MBG_DEV_HANDLE dh, MBG_TIME_INFO_TSTAMP *p ) ; /** - Check if a specific device supports demodulation of the DCF77 PZF code. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_corr_info() - @see mbg_dev_has_tr_distance() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_pzf( MBG_DEV_HANDLE dh, int *p ) ; + * @brief Read PZF correlation info from a device + * + * The API call ::mbg_chk_dev_has_corr_info checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::CORR_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_pzf + * @see ::mbg_chk_dev_has_corr_info + */ + _MBG_API_ATTR int _MBG_API mbg_get_corr_info( MBG_DEV_HANDLE dh, CORR_INFO *p ) ; /** - Check if a specific device supports reading correlation info. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. - - @return ::MBG_SUCCESS or error code returned by device I/O control function. - - @see mbg_dev_has_pzf() - @see mbg_get_corr_info() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_corr_info( MBG_DEV_HANDLE dh, int *p ) ; + * @brief Read configurable "distance from transmitter" parameter from a device + * + * The distance from transmitter parameter is used to compensate + * the RF propagation delay, mostly with long wave receivers. + * + * The API call ::mbg_chk_dev_has_tr_distance checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::TR_DISTANCE variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_pzf + * @see ::mbg_chk_dev_has_tr_distance + * @see ::mbg_set_tr_distance + */ + _MBG_API_ATTR int _MBG_API mbg_get_tr_distance( MBG_DEV_HANDLE dh, TR_DISTANCE *p ) ; /** - Check if a specific device supports configurable distance from transmitter - used to compensate RF propagation delay. - - @param dh Valid handle to a Meinberg device - @param *p Pointer to an int which is set 0 or != 0 unless the call fails. + * @brief Write configurable "distance from transmitter" parameter to a device. + * + * The distance from transmitter parameter is used to compensate + * the RF propagation delay, mostly with long wave receivers. + * + * The API call ::mbg_chk_dev_has_tr_distance checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::TR_DISTANCE variable to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_pzf + * @see ::mbg_chk_dev_has_tr_distance + * @see ::mbg_get_tr_distance + */ + _MBG_API_ATTR int _MBG_API mbg_set_tr_distance( MBG_DEV_HANDLE dh, const TR_DISTANCE *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Read a debug status word from a device + * + * This is mainly supported by IRIG timecode receiver cards, and the status + * word is intended to provide more detailed information why a card might not + * synchronize to the incoming timecode signal. + * + * See ::MBG_DEBUG_STATUS and related definitions for details. + * + * The API call ::mbg_chk_dev_has_debug_status checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_DEBUG_STATUS variable to be filled up + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_debug_status + */ + _MBG_API_ATTR int _MBG_API mbg_get_debug_status( MBG_DEV_HANDLE dh, MBG_DEBUG_STATUS *p ) ; - @see mbg_dev_has_pzf() - @see mbg_get_tr_distance() - @see mbg_set_tr_distance() -*/ - _MBG_API_ATTR int _MBG_API mbg_dev_has_tr_distance( MBG_DEV_HANDLE dh, int *p ) ; + /** + * @brief Clear the device's on-board event log + * + * The API call ::mbg_chk_dev_has_evt_log checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_evt_log + * @see ::mbg_get_num_evt_log_entries + * @see ::mbg_get_first_evt_log_entry + * @see ::mbg_get_next_evt_log_entry + */ + _MBG_API_ATTR int _MBG_API mbg_clr_evt_log( MBG_DEV_HANDLE dh ) ; /** - Read PZF correlation info from a card which supports this. - The macro _pcps_has_corr_info() or the API call mbg_dev_has_corr_info() - check whether this call is supported by a specific card. + * @brief Read details about a device's on-board event log buffer + * + * The returned ::MBG_NUM_EVT_LOG_ENTRIES structure tells how many + * event log entries can be saved on the board, and how many entries + * actually have been saved. + * + * The API call ::mbg_chk_dev_has_evt_log checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_NUM_EVT_LOG_ENTRIES variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_evt_log + * @see ::mbg_clr_evt_log + * @see ::mbg_get_first_evt_log_entry + * @see ::mbg_get_next_evt_log_entry + */ + _MBG_API_ATTR int _MBG_API mbg_get_num_evt_log_entries( MBG_DEV_HANDLE dh, MBG_NUM_EVT_LOG_ENTRIES *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::CORR_INFO variable to be filled up + /** + * @brief Read the first (oldest) event log entry from a device + * + * @note Subsequent reads should be made using ::mbg_get_next_evt_log_entry. + * + * The API call ::mbg_chk_dev_has_evt_log checks whether + * this call is supported by a device. + * + * If no (more) event log entry is available on the device then + * the returned MBG_EVT_LOG_ENTRY::code is MBG_EVT_ID_NONE. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_EVT_LOG_ENTRY variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_evt_log + * @see ::mbg_clr_evt_log + * @see ::mbg_get_num_evt_log_entries + * @see ::mbg_get_next_evt_log_entry + */ + _MBG_API_ATTR int _MBG_API mbg_get_first_evt_log_entry( MBG_DEV_HANDLE dh, MBG_EVT_LOG_ENTRY *p ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Read the next event log entry from a device + * + * @note The first read should be made using ::mbg_get_first_evt_log_entry + * to set the on-board read index to the oldest entry. + * + * The API call ::mbg_chk_dev_has_evt_log checks whether + * this call is supported by a device. + * + * If no (more) event log entry is available on the device then + * the returned MBG_EVT_LOG_ENTRY::code is MBG_EVT_ID_NONE. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_EVT_LOG_ENTRY variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_evt_log + * @see ::mbg_clr_evt_log + * @see ::mbg_get_num_evt_log_entries + * @see ::mbg_get_first_evt_log_entry + */ + _MBG_API_ATTR int _MBG_API mbg_get_next_evt_log_entry( MBG_DEV_HANDLE dh, MBG_EVT_LOG_ENTRY *p ) ; - @see mbg_dev_has_pzf() - @see mbg_dev_has_corr_info() - */ - _MBG_API_ATTR int _MBG_API mbg_get_corr_info( MBG_DEV_HANDLE dh, CORR_INFO *p ) ; + /** + * @brief Read the current GNSS mode info including current settings + * + * The ::MBG_GNSS_MODE_INFO structure tells which GNSS systems are supported + * by a device, and also includes the settings currently in effect. + * + * The API call ::mbg_chk_dev_is_gnss can be used to check whether + * this call is supported by a device. + * + * See also the notes for ::mbg_chk_dev_is_gnss. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p_mi Pointer to a ::MBG_GNSS_MODE_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_gps_gnss_mode_settings + * @see ::mbg_get_gps_all_gnss_sat_info + * @see ::mbg_chk_dev_is_gnss + */ + _MBG_API_ATTR int _MBG_API mbg_get_gps_gnss_mode_info( MBG_DEV_HANDLE dh, MBG_GNSS_MODE_INFO *p_mi ) ; /** - Read configurable "distance from transmitter" parameter from a card - which supports this. The parameter is used to compensate the RF signal - propagation delay. - The macro _pcps_has_tr_distance() or the API call mbg_dev_has_tr_distance() - check whether this call is supported by a specific card. + * @brief Write the GNSS mode configuration to a device + * + * The ::MBG_GNSS_MODE_SETTINGS structure determines the GNSS settings + * for a device, e.g. which satellite systems have to be used. + * + * The function ::mbg_get_gps_gnss_mode_info should have been called before + * to determine which GNSS settings are supported by the device. + * + * The API call ::mbg_chk_dev_is_gnss can be used to check whether + * this call is supported by a device. + * + * See also the notes for ::mbg_chk_dev_is_gnss. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p_ms Pointer to a ::MBG_GNSS_MODE_SETTINGS structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_gps_gnss_mode_info + * @see ::mbg_get_gps_all_gnss_sat_info + * @see ::mbg_chk_dev_is_gnss + */ + _MBG_API_ATTR int _MBG_API mbg_set_gps_gnss_mode_settings( MBG_DEV_HANDLE dh, const MBG_GNSS_MODE_SETTINGS *p_ms ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TR_DISTANCE variable to be filled up + /** + * @brief Read a ::GNSS_SAT_INFO_IDX array of satellite status information + * + * The function ::mbg_get_gps_gnss_mode_info must have been called before, + * and the returned ::MBG_GNSS_MODE_INFO structure be passed to this function. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] gsii Pointer to a an array of satellite info structures to be filled up. + * @param[in] p_mi Pointer to a ::MBG_GNSS_MODE_INFO structure returned by ::mbg_get_gps_gnss_mode_info. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_gps_gnss_mode_info + * @see ::mbg_set_gps_gnss_mode_settings + * @see ::mbg_chk_dev_is_gnss + */ + _MBG_API_ATTR int _MBG_API mbg_get_gps_all_gnss_sat_info( MBG_DEV_HANDLE dh, GNSS_SAT_INFO_IDX gsii[], const MBG_GNSS_MODE_INFO *p_mi ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Read common GPIO configuration limits + * + * The API call ::mbg_chk_dev_has_gpio checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p A ::MBG_GPIO_CFG_LIMITS structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_gpio + * @see ::mbg_get_gpio_cfg_limits + * @see ::mbg_get_gps_all_gpio_info + * @see ::mbg_set_gps_gpio_settings_idx + * @see ::mbg_get_gps_all_gpio_status + */ + _MBG_API_ATTR int _MBG_API mbg_get_gpio_cfg_limits( MBG_DEV_HANDLE dh, MBG_GPIO_CFG_LIMITS *p ) ; - @see mbg_dev_has_pzf() - @see mbg_dev_has_tr_distance() - @see mbg_set_tr_distance() - */ - _MBG_API_ATTR int _MBG_API mbg_get_tr_distance( MBG_DEV_HANDLE dh, TR_DISTANCE *p ) ; + /** + * @brief Get all GPIO settings and capabilities. + * + * The API call ::mbg_chk_dev_has_gpio checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] gii An array of ::MBG_GPIO_STATUS_IDX structures to be filled up. + * @param[in] p_gcl Pointer to a ::MBG_GPIO_CFG_LIMITS structure read before. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_gpio + * @see ::mbg_get_gpio_cfg_limits + * @see ::mbg_get_gps_all_gpio_info + * @see ::mbg_set_gps_gpio_settings_idx + * @see ::mbg_get_gps_all_gpio_status + */ + _MBG_API_ATTR int _MBG_API mbg_get_gps_all_gpio_info( MBG_DEV_HANDLE dh, MBG_GPIO_INFO_IDX gii[], const MBG_GPIO_CFG_LIMITS *p_gcl ) ; /** - Write configurable "distance from transmitter" parameter to a card - which supports this. The parameter is used to compensate the RF signal - propagation delay. - The macro _pcps_has_tr_distance() or the API call mbg_dev_has_tr_distance() - check whether this call is supported by a specific card. + * @brief Write the configuration for a single GPIO port to a device + * + * The ::MBG_GPIO_SETTINGS_IDX structure contains both the ::MBG_GPIO_SETTINGS + * and the port index value. + * + * The API call ::mbg_chk_dev_has_gpio checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_GPIO_SETTINGS_IDX structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_gpio + * @see ::mbg_get_gpio_cfg_limits + * @see ::mbg_get_gps_all_gpio_info + * @see ::mbg_set_gps_gpio_settings_idx + * @see ::mbg_get_gps_all_gpio_status + */ + _MBG_API_ATTR int _MBG_API mbg_set_gps_gpio_settings_idx( MBG_DEV_HANDLE dh, const MBG_GPIO_SETTINGS_IDX *p ) ; - @param dh Valid handle to a Meinberg device - @param *p Pointer to a ::TR_DISTANCE variable to be written + /** + * @brief Read the status of all GPIO signal ports + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] gsi An array of ::MBG_GPIO_STATUS_IDX structures to be filled up. + * @param[in] p_gcl Pointer to a ::MBG_GPIO_CFG_LIMITS structure read before. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_gpio + * @see ::mbg_get_gpio_cfg_limits + * @see ::mbg_get_gps_all_gpio_info + * @see ::mbg_set_gps_gpio_settings_idx + */ + _MBG_API_ATTR int _MBG_API mbg_get_gps_all_gpio_status( MBG_DEV_HANDLE dh, MBG_GPIO_STATUS_IDX gsi[], const MBG_GPIO_CFG_LIMITS *p_gcl ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. + /** + * @brief Read ::XMULTI_REF_INSTANCES + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p A ::XMULTI_REF_INSTANCES structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_xmr + * @see ::mbg_get_gps_all_xmr_status + * @see ::mbg_get_gps_all_xmr_info + * @see ::mbg_set_gps_xmr_settings_idx + * @see ::mbg_get_xmr_holdover_status + */ + _MBG_API_ATTR int _MBG_API mbg_get_xmr_instances( MBG_DEV_HANDLE dh, XMULTI_REF_INSTANCES *p ) ; - @see mbg_dev_has_pzf() - @see mbg_dev_has_tr_distance() - @see mbg_get_tr_distance() - */ - _MBG_API_ATTR int _MBG_API mbg_set_tr_distance( MBG_DEV_HANDLE dh, const TR_DISTANCE *p ) ; + /** + * @brief Read the status of all XMR sources + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] xmrsi An array of ::XMULTI_REF_STATUS_IDX structures to be filled up. + * @param[in] p_xmri Pointer to a ::XMULTI_REF_INSTANCES structure read before. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_xmr + * @see ::mbg_get_xmr_instances + * @see ::mbg_get_gps_all_xmr_info + * @see ::mbg_set_gps_xmr_settings_idx + * @see ::mbg_get_xmr_holdover_status + */ + _MBG_API_ATTR int _MBG_API mbg_get_gps_all_xmr_status( MBG_DEV_HANDLE dh, XMULTI_REF_STATUS_IDX xmrsi[], const XMULTI_REF_INSTANCES *p_xmri ) ; /** - Read the CPU affinity of a process, i.e. on which of the available - CPUs the process can be executed. + * @brief Read all XMR settings and capabilities + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] xmrii An array of ::XMULTI_REF_INFO_IDX structures to be filled up. + * @param[in] p_xmri Pointer to a ::XMULTI_REF_INSTANCES structure read before. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_xmr + * @see ::mbg_get_xmr_instances + * @see ::mbg_get_gps_all_xmr_status + * @see ::mbg_set_gps_xmr_settings_idx + * @see ::mbg_get_xmr_holdover_status + */ + _MBG_API_ATTR int _MBG_API mbg_get_gps_all_xmr_info( MBG_DEV_HANDLE dh, XMULTI_REF_INFO_IDX xmrii[], const XMULTI_REF_INSTANCES *p_xmri ) ; - @param pid The process ID. - @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. + /** + * @brief Write a single XMR setting to a device + * + * The ::XMULTI_REF_SETTINGS_IDX structure contains both the ::XMULTI_REF_SETTINGS + * and the index value. + * + * The API call ::mbg_chk_dev_has_xmr checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] p Pointer to a ::XMULTI_REF_SETTINGS_IDX structure to be written. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_xmr + * @see ::mbg_get_xmr_instances + * @see ::mbg_get_gps_all_xmr_status + * @see ::mbg_get_gps_all_xmr_info + * @see ::mbg_get_xmr_holdover_status + */ + _MBG_API_ATTR int _MBG_API mbg_set_gps_xmr_settings_idx( MBG_DEV_HANDLE dh, const XMULTI_REF_SETTINGS_IDX *p ) ; - @return ::MBG_SUCCESS or error code returned by the system call. + /** + * @brief Read the current XMR holdover interval from a device + * + * The API call ::mbg_chk_dev_has_xmr checks whether + * this call is supported by a device. + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::XMR_HOLDOVER_INTV structure to be filled up. + * @param[in] p_xmri Pointer to a ::XMULTI_REF_INSTANCES structure read before. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_chk_dev_has_xmr + * @see ::mbg_get_xmr_instances + * @see ::mbg_get_gps_all_xmr_status + * @see ::mbg_get_gps_all_xmr_info + * @see ::mbg_set_gps_xmr_settings_idx + */ + _MBG_API_ATTR int _MBG_API mbg_get_xmr_holdover_status( MBG_DEV_HANDLE dh, XMR_HOLDOVER_STATUS *p, const XMULTI_REF_INSTANCES *p_xmri ) ; - @see mbg_set_process_affinity() - @see mbg_set_current_process_affinity_to_cpu() - */ + /** + * @brief Read the CPU affinity of a process + * + * This means on which of the available CPUs or CPU cores + * a process may be executed. + * + * @param[in] pid The process ID. + * @param[out] p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_set_process_affinity + * @see ::mbg_set_current_process_affinity_to_cpu + */ _MBG_API_ATTR int _MBG_API mbg_get_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p ) ; /** - Set the CPU affinity of a process, i.e. on which of the available - CPUs the process is allowed to be executed. - - @param pid The process ID. - @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. - - @return ::MBG_SUCCESS or error code returned by the system call. - - @see mbg_get_process_affinity() - @see mbg_set_current_process_affinity_to_cpu() - */ + * @brief Set the CPU affinity of a process. + * + * This determines on which of the available CPUs + * or CPU cores the process is allowed to be executed. + * + * @param[in] pid The process ID. + * @param[out] p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_process_affinity + * @see ::mbg_set_current_process_affinity_to_cpu + */ _MBG_API_ATTR int _MBG_API mbg_set_process_affinity( MBG_PROCESS_ID pid, MBG_CPU_SET *p ) ; /** - Set the CPU affinity of a process for a single CPU only, i.e. the process - may only be executed on that single CPU. - - @param cpu_num The number of the CPU. - - @return ::MBG_SUCCESS or error code returned by the system call. - - @see mbg_get_process_affinity() - @see mbg_set_process_affinity() - */ + * @brief Set the CPU affinity of a process for a single CPU only + * + * This means the process may only be executed on that single CPU. + * + * @param[in] cpu_num The number of the CPU. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_process_affinity + * @see ::mbg_set_process_affinity + */ _MBG_API_ATTR int _MBG_API mbg_set_current_process_affinity_to_cpu( int cpu_num ) ; /** - Create a new execution thread for the current process. - This function is only implemented for targets which support threads. - - @param p_ti Pointer to a ::MBG_THREAD_INFO structure to be filled up. - @param fnc The name of the thread function to be started. - @param arg A generic argument passed to the thread function. - - @return ::MBG_SUCCESS or error code returned by the system call. - - @see mbg_thread_stop() - @see mbg_thread_sleep_interruptible() - @see mbg_thread_set_affinity() - */ - _MBG_API_ATTR int _MBG_API mbg_thread_create( MBG_THREAD_INFO *p_ti, MBG_THREAD_FNC_RET_VAL (MBG_THREAD_FNC_ATTR *fnc)(void *), void *arg ) ; + * @brief Create a new execution thread for the current process. + * + * This function is only implemented for targets that support threads. + * + * @param[in] p_ti Pointer to a ::MBG_THREAD_INFO structure to be filled up. + * @param[in] fnc The name of the thread function to be started. + * @param[in] arg A generic argument passed to the thread function. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_thread_stop + * @see ::mbg_thread_sleep_interruptible + * @see ::mbg_thread_set_affinity + */ + _MBG_API_ATTR int _MBG_API mbg_thread_create( MBG_THREAD_INFO *p_ti, MBG_THREAD_FNC fnc, void *arg ) ; /** - Stop a thread which has been created by mbg_thread_create(). Wait - until the thread has finished and release all resources. - This function is only implemented for targets which support threads. - - @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. - - @return ::MBG_SUCCESS or error code returned by the system call. - - @see mbg_thread_create() - @see mbg_thread_sleep_interruptible() - @see mbg_thread_set_affinity() - */ + * @brief Stop a thread which has been created by ::mbg_thread_create. + * + * Wait until the thread has finished and release all resources. + * + * This function is only implemented for targets that support threads. + * + * @param[in,out] p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_thread_create + * @see ::mbg_thread_sleep_interruptible + * @see ::mbg_thread_set_affinity + */ _MBG_API_ATTR int _MBG_API mbg_thread_stop( MBG_THREAD_INFO *p_ti ) ; /** - Let the current thread sleep for a certain interval unless a signal is - received indicating the thread should terminate. - This function is only implemented for targets which support threads. - - @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. - @param sleep_ms The number of milliseconds to sleep - @return 0 if the sleep interval has expired normally - 1 if a signal to terminate has been received - <0 if an error has occurred - - @see mbg_thread_create() - @see mbg_thread_stop() - @see mbg_thread_set_affinity() - */ + * @brief Let the current thread sleep for a certain interval + * + * The sleep is interrupted if a signal is received indicating + * the thread should terminate. + * + * This function is only implemented for targets that support threads. + * + * @param[in,out] p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. + * @param[in] sleep_ms The number of milliseconds to sleep + * + * @return MBG_SUCCESS if the sleep interval has expired normally, + * MBG_ERR_INTR if a signal to terminate has been received, + * or one of the other @ref MBG_ERROR_CODES + * + * @see ::mbg_thread_create + * @see ::mbg_thread_stop + * @see ::mbg_thread_set_affinity + */ _MBG_API_ATTR int _MBG_API mbg_thread_sleep_interruptible( MBG_THREAD_INFO *p_ti, ulong sleep_ms ) ; /** - Set the CPU affinity of a single thread, i.e. on which of the available - CPUs the thread is allowed to be executed. - This function is only implemented for targets which support thread affinity. - - @param p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. - @param *p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. - - @return ::MBG_SUCCESS or error code returned by the system call. - - @see mbg_thread_create() - @see mbg_thread_stop() - @see mbg_thread_sleep_interruptible() - */ + * @brief Set the CPU affinity of a single thread + * + * This determines on which of the available CPUs the thread + * is allowed to be executed. + * + * This function is only implemented for targets that support thread affinity. + * + * @param[in,out] p_ti Pointer to a ::MBG_THREAD_INFO structure associated with the thread. + * @param[in] p Pointer to a ::MBG_CPU_SET variable which contains a mask of CPUs. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_thread_create + * @see ::mbg_thread_stop + * @see ::mbg_thread_sleep_interruptible + */ _MBG_API_ATTR int _MBG_API mbg_thread_set_affinity( MBG_THREAD_INFO *p_ti, MBG_CPU_SET *p ) ; /** - Set up a ::MBG_POLL_THREAD_INFO structure and start a new thread - which runs the mbg_xhrt_poll_thread_fnc() function. - This function is only implemented for targets which support threads. - - @param *p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure. - @param dh the handle of the device to be polled. - @param freq_hz The initial cycles frequency, if known, in Hz. - @param sleep_ms the sleep interval for the poll thread function in ms. - If this parameter is 0 then the default sleep interval is used. - - @return ::MBG_SUCCESS on success, - ::MBG_ERR_NOT_SUPP_BY_DEV if the device to poll does not support HR time - else the result of mbg_thread_create() - - @see mbg_xhrt_poll_thread_fnc() - @see mbg_xhrt_poll_thread_stop() - @see mbg_get_xhrt_time_as_pcps_hr_time() - @see mbg_get_xhrt_time_as_filetime() - @see mbg_get_xhrt_cycles_frequency() - */ + * @brief Set up a ::MBG_POLL_THREAD_INFO structure and start a new thread + * + * The new thread runs a function which periodically reads + * a time stamp / cycles pair from a device. + * + * This function is only implemented for targets that support threads. + * + * @param[in,out] p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure. + * @param[in] dh the Handle of the device to be polled. + * @param[in] freq_hz The initial cycles frequency, if known, in Hz. + * @param[in] sleep_ms the sleep interval for the poll thread function in ms. + * If this parameter is 0 then the default sleep interval is used. + * + * @return ::MBG_SUCCESS on success, + * ::MBG_ERR_NOT_SUPP_BY_DEV if the device to poll does not support HR time + * else the result of ::mbg_thread_create. + * + * @see ::mbg_xhrt_poll_thread_stop + * @see ::mbg_get_xhrt_time_as_pcps_hr_time + * @see ::mbg_get_xhrt_time_as_filetime + * @see ::mbg_get_xhrt_cycles_frequency + */ _MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_create( MBG_POLL_THREAD_INFO *p_pti, MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY freq_hz, int sleep_ms ) ; /** - Stop a polling thread started by mbg_xhrt_poll_thread_create() - and release all associated resources. - - @param *p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure. - - @return the result of mbg_thread_stop() - - @see mbg_xhrt_poll_thread_fnc() - @see mbg_xhrt_poll_thread_create() - @see mbg_get_xhrt_time_as_pcps_hr_time() - @see mbg_get_xhrt_time_as_filetime() - @see mbg_get_xhrt_cycles_frequency() - */ + * @brief Stop a polling thread started by ::mbg_xhrt_poll_thread_create + * + * This call also releases all associated resources. + * + * @param[in,out] p_pti Pointer to a ::MBG_POLL_THREAD_INFO structure. + * + * @return The result of ::mbg_thread_stop. + * + * @see ::mbg_xhrt_poll_thread_create + * @see ::mbg_get_xhrt_time_as_pcps_hr_time + * @see ::mbg_get_xhrt_time_as_filetime + * @see ::mbg_get_xhrt_cycles_frequency + */ _MBG_API_ATTR int _MBG_API mbg_xhrt_poll_thread_stop( MBG_POLL_THREAD_INFO *p_pti ) ; /** - Retrieve a time stamp in PCPS_HR_TIME format which is extrapolated - using the system's current cycles counter value and a time stamp - plus associated cycles counter value saved by the polling thread. - See mbg_xhrt_poll_thread_fnc() for details and limitations. - This function is only implemented for targets which support threads. - - @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. - @param *p_hrt Pointer to a ::PCPS_HR_TIME structure to be filled up. - - @return MBG_SUCCESS or another return value from the polling thread's IOCTL call. - - @see mbg_xhrt_poll_thread_fnc() - @see mbg_xhrt_poll_thread_create() - @see mbg_xhrt_poll_thread_stop() - @see mbg_get_xhrt_time_as_filetime() - @see mbg_get_xhrt_cycles_frequency() - */ + * @brief Retrieve an extrapolated time stamp in ::PCPS_HR_TIME format + * + * The time stamp is extrapolated using the system's current cycles counter value + * and a time stamp plus associated cycles counter value saved by the polling thread. + * See @ref mbg_xhrt_poll_group for details and limitations. + * + * This function is only implemented for targets that support threads. + * + * @param[in,out] p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. + * @param[out] p_hrt Pointer to a ::PCPS_HR_TIME structure to be filled up. + * + * @return The return code from the API call used by the polling thread + * to read the time from the device, usually ::mbg_get_hr_time_cycles, + * so ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES. + * + * @ingroup mbg_xhrt_poll_group + * @see ::mbg_xhrt_poll_thread_create + * @see ::mbg_xhrt_poll_thread_stop + * @see ::mbg_get_xhrt_time_as_filetime + * @see ::mbg_get_xhrt_cycles_frequency + * @see @ref mbg_xhrt_poll_group + */ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_pcps_hr_time( MBG_XHRT_INFO *p, PCPS_HR_TIME *p_hrt ) ; /** - Retrieve a time stamp in FILETIME format which is extrapolated - using the system's current cycles counter value and a time stamp - plus associated cycles counter value saved by the polling thread. - See mbg_xhrt_poll_thread_fnc() for details and limitations. - Since FILETIME is a Windows specific type this function is only - implemented under Windows. - - @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. - @param *p_ft Pointer to a ::FILETIME structure to be filled up. - - @return MBG_SUCCESS or another return value from the polling thread's IOCTL call. - - @see mbg_xhrt_poll_thread_fnc() - @see mbg_xhrt_poll_thread_create() - @see mbg_xhrt_poll_thread_stop() - @see mbg_get_xhrt_time_as_pcps_hr_time() - @see mbg_get_xhrt_cycles_frequency() - */ + * @brief Retrieve an extrapolated time stamp in FILETIME format + * + * The time stamp is extrapolated using the system's current cycles counter value + * and a time stamp plus associated cycles counter value saved by the polling thread. + * See @ref mbg_xhrt_poll_group for details and limitations. + * + * Since FILETIME is a Windows-specific type this function is only + * implemented under Windows. + * + * @param[in,out] p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. + * @param[out] p_ft Pointer to a FILETIME structure to be filled up. + * + * @return The return code from the API call used by the polling thread + * to read the time from the device, usually ::mbg_get_hr_time_cycles, + * so ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES. + * + * @ingroup mbg_xhrt_poll_group + * @see ::mbg_xhrt_poll_thread_create + * @see ::mbg_xhrt_poll_thread_stop + * @see ::mbg_get_xhrt_time_as_pcps_hr_time + * @see ::mbg_get_xhrt_cycles_frequency + * @see @ref mbg_xhrt_poll_group + */ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_time_as_filetime( MBG_XHRT_INFO *p, FILETIME *p_ft ) ; /** - Retrieve the frequency of the system's cycles counter as determined - by the device polling thread. - See mbg_xhrt_poll_thread_fnc() for details and limitations. - This function is only implemented for targets which support threads. - - @param *p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. - @param *p_freq_hz Pointer to a ::MBG_PC_CYCLES_FREQUENCY variable in which the frequency is returned. - @return a status code from the polling thread: MBG_SUCCESS or an IOCTL error code. - - @see mbg_xhrt_poll_thread_fnc() - @see mbg_xhrt_poll_thread_create() - @see mbg_xhrt_poll_thread_stop() - @see mbg_get_xhrt_time_as_pcps_hr_time() - @see mbg_get_xhrt_time_as_filetime() - */ + * @brief Retrieve the frequency of the system's cycles counter + * + * The frequency is determined by the device polling thread. + * See @ref mbg_xhrt_poll_group for details and limitations. + * + * This function is only implemented for targets that support threads. + * + * @param[in,out] p Pointer to a ::MBG_XHRT_INFO structure used to retrieve data from the polling thread. + * @param[out] p_freq_hz Pointer to a ::MBG_PC_CYCLES_FREQUENCY variable in which the frequency is returned. + * + * @return The return code from the API call used by the polling thread + * to read the time from the device, usually ::mbg_get_hr_time_cycles, + * so ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES. + * + * @ingroup mbg_xhrt_poll_group + * @see ::mbg_xhrt_poll_thread_create + * @see ::mbg_xhrt_poll_thread_stop + * @see ::mbg_get_xhrt_time_as_pcps_hr_time + * @see ::mbg_get_xhrt_time_as_filetime + * @see @ref mbg_xhrt_poll_group + */ _MBG_API_ATTR int _MBG_API mbg_get_xhrt_cycles_frequency( MBG_XHRT_INFO *p, MBG_PC_CYCLES_FREQUENCY *p_freq_hz ) ; /** - Retrieve the default system's cycles counter frequency from the kernel driver. + * @brief Retrieve the system's default cycles counter frequency from the kernel driver + * + * This API call can be used on systems which don't provide this information in user space. + * + * @param[in] dh Handle of the device to which the IOCTL call is sent. + * @param[out] p Pointer of a ::MBG_PC_CYCLES_FREQUENCY variable to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @see ::mbg_get_default_cycles_frequency + */ + _MBG_API_ATTR int _MBG_API mbg_get_default_cycles_frequency_from_dev( MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY *p ) ; - @param dh handle of the device to which the IOCTL call is sent. - @param *p Pointer of a ::MBG_PC_CYCLES_FREQUENCY variable to be filled up. + /** + * @brief Retrieve the system's default cycles counter frequency + * + * @note This may not be supported on all target platforms, in which case the + * returned frequency is 0 and the ::mbg_get_default_cycles_frequency_from_dev + * call should be used instead. + * + * @return the default cycles counter frequency in Hz, or 0 if the value is not available. + * + * @see ::mbg_get_default_cycles_frequency_from_dev + */ + _MBG_API_ATTR MBG_PC_CYCLES_FREQUENCY _MBG_API mbg_get_default_cycles_frequency( void ) ; - @return ::MBG_SUCCESS or error code returned by device I/O control function. - @see mbg_get_default_cycles_frequency() - */ - _MBG_API_ATTR int _MBG_API mbg_get_default_cycles_frequency_from_dev( MBG_DEV_HANDLE dh, MBG_PC_CYCLES_FREQUENCY *p ) ; +/* ----- function prototypes end ----- */ - /** - Retrieve the default system's cycles counter frequency. - @note This may not be supported on all target platforms, in which case the - returned frequency is 0 and the mbg_get_default_cycles_frequency_from_dev() - call should be used. +#if defined( MBG_TGT_WIN32 ) - @return the default cycles counter frequency in Hz, or 0 if the value is not available. +static __mbg_inline +MBGDEVIO_RET_VAL do_mbg_ioctl( MBG_DEV_HANDLE dh, int ioctl_code, + const void *in_p, int in_sz, void *out_p, int out_sz ) +{ + DWORD ReturnedLength; - @see mbg_get_default_cycles_frequency_from_dev() -*/ - _MBG_API_ATTR MBG_PC_CYCLES_FREQUENCY _MBG_API mbg_get_default_cycles_frequency( void ) ; + if ( !DeviceIoControl( dh, ioctl_code, + (LPVOID) in_p, in_sz, out_p, out_sz, + &ReturnedLength, + NULL + ) ) + { + DWORD rc = GetLastError(); // FIXME + #if 0 //### TODO + // We can't call mbgsvctl_log_mbgdevio_error() here (for now). + // Is is defined in mbgsvctl.h, and including mbgsvctl.h here, + // or copying the prototype here results in DLL import/export + // mismatch errors. -/* ----- function prototypes end ----- */ + // do not report a USB device timeout error + if ( rc != MBG_ERR_USB_ACCESS ) + mbgsvctl_log_mbgdevio_error( ioctl_code, rc ); + #endif -#ifdef __cplusplus -} -#endif + return rc; + } + return MBG_SUCCESS; -#if defined( MBG_TGT_WIN32 ) +} // do_mbg_ioctl #define _do_mbg_ioctl( _dh, _ioctl, _p, _in_sz, _out_sz ) \ do_mbg_ioctl( _dh, _ioctl, (LPVOID) _p, _in_sz, (LPVOID) _p, _out_sz ) -#elif defined( MBG_TGT_UNIX ) +#elif defined( MBG_HAS_POSIX_IOCTL ) + + // In case of an error ioctl returns -1, and errno has been set to a *positive* + // error number according to negative Meinberg error codes, so we need to return + // -errno in case of an error to pass the original negative Meinberg error code. + + static __mbg_inline + MBGDEVIO_RET_VAL do_mbg_ioctl( MBG_DEV_HANDLE dh, unsigned long ioctl_code, const void *p ) + { + int rc = ioctl( dh, ioctl_code, (void *) p ); + + if ( rc == -1 ) // error + { + rc = -errno; + #if DEBUG_IOCTL + fprintf( stderr, "IOCTL 0x%08lX error: %s (rc: %i)\n", + (ulong) ioctl_code, mbg_strerror( rc ), rc ); + #endif + } + + return rc; + } #define _do_mbg_ioctl( _dh, _ioctl, _p, _in_sz, _out_sz ) \ - ioctl( _dh, _ioctl, _p ) + do_mbg_ioctl( _dh, _ioctl, _p ) #endif @@ -3219,21 +5434,42 @@ extern "C" { // The code below depends on whether the target device is accessed via // IOCTLs to a device driver, or the hardware is accessed directly. -#if defined( _MBGIOCTL_H ) // using IOCTL to access device driver - +#if defined( MBG_USE_KERNEL_DRIVER ) // using IOCTL to access device driver + + /** + * @brief Send a generic IOCTL command to the driver. + * + * @param dh Valid handle to a Meinberg device + * @param info Additional information for the kernel driver depending on + * the IOCTL code, i.e. the low level function to be called: <br> + * one of the PCPS_... commands with IOCTL_PCPS_GENERIC_{READ|WRITE}<br> + * one of the PC_GPS_... commands with IOCTL_PCPS_GENERIC_{READ|WRITE}_GPS<br> + * one of the PCPS_GEN_IO_... enumeration codes with IOCTL_PCPS_GENERIC_IO + * @param ioctl_code One of the IOCTL_GENERIC_... codes telling the kernel driver + * which low level function to use, e.g. normal read or write, + * large (GPS) data read or write, or generic I/O. + * @param in_p Pointer to an input buffer passed to the driver, can be NULL + * @param in_sz Size of the input buffer, can be 0 if no buffer is used + * @param out_p Pointer to an output buffer passed to the driver, can be NULL + * @param out_sz Size of the output buffer, can be 0 if no buffer is used + * + * @return ::MBG_SUCCESS or error code returned by device I/O control function. + */ static __mbg_inline int mbgdevio_do_gen_io( MBG_DEV_HANDLE dh, int info, unsigned int ioctl_code, const void *in_p, int in_sz, void *out_p, int out_sz ) { - _mbgdevio_vars(); - - #if _MBG_SUPP_VAR_ACC_SIZE - info; // avoid "unused" warning + MBGDEVIO_RET_VAL rc; - rc = do_mbg_ioctl( dh, ioctl_code, in_p, in_sz, out_p, out_sz ); //##++++ in_p / out_p vs. _do_mbg_ioctl() + // Generic IOCTL calls always need to pass some info beside + // the I/O buffers down to the driver, which usually is + // the command code for the device. + // Thus we must always use one of the control structures + // IOCTL_GENERIC_REQ or IOCTL_GENERIC_BUFFER, whichever + // is appropriate for the target OS. - #elif USE_IOCTL_GENERIC_REQ + #if USE_IOCTL_GENERIC_REQ IOCTL_GENERIC_REQ req = { 0 }; @@ -3254,7 +5490,7 @@ extern "C" { p_buff = (IOCTL_GENERIC_BUFFER *) malloc( buff_size ); if ( p_buff == NULL ) - return _mbg_err_to_os( MBG_ERR_NO_MEM ); + return MBG_ERR_NO_MEM; p_buff->ctl.info = info; p_buff->ctl.data_size_in = in_sz; @@ -3274,7 +5510,7 @@ extern "C" { #endif - return _mbgdevio_ret_val; + return _mbgdevio_cnv_ret_val( rc ); } // mbgdevio_do_gen_io @@ -3301,8 +5537,10 @@ extern "C" { #define _mbgdevio_write_cmd( _dh, _cmd, _ioctl ) \ _do_mbgdevio_write( _dh, _cmd, _ioctl, NULL, 0 ) + #define _mbgdevio_read_gps _do_mbgdevio_read #define _mbgdevio_read_gps_var _mbgdevio_read_var + #define _mbgdevio_write_gps _do_mbgdevio_write #define _mbgdevio_write_gps_var _mbgdevio_write_var @@ -3324,10 +5562,10 @@ extern "C" { #else // accessing hardware device directly - #define _mbgdevio_chk_cond( _cond ) \ - { \ - if ( !(_cond) ) \ - return _mbg_err_to_os( MBG_ERR_NOT_SUPP_BY_DEV ); \ + #define _mbgdevio_chk_cond( _cond ) \ + { \ + if ( !(_cond) ) \ + return MBG_ERR_NOT_SUPP_BY_DEV; \ } #define _mbgdevio_read( _dh, _cmd, _ioctl, _p, _sz ) \ @@ -3408,38 +5646,52 @@ extern "C" { -#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX ) +#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_POSIX ) + +// NOTE +// For some reason the code below causes an internal compiler error +// with Borland C++Builder 5.0 release builds. Since we don't need +// this function in the BC5 projects anyway we simply exclude it +// from build. + +#if !defined( __BORLANDC__ ) static __mbg_inline void mbg_chk_tstamp64_leap_sec( uint64_t *tstamp64, PCPS_TIME_STATUS_X *status ) { if ( *status & ( PCPS_LS_ANN | PCPS_LS_ENB ) ) { - time_t t = (uint32_t) ( *tstamp64 >> 32 ); - struct tm tm = *gmtime( &t ); + struct tm tm = { 0 }; + time_t t = cvt_to_time_t( (uint32_t) ( (*tstamp64) >> 32 ) ); + int rc = mbg_gmtime( &tm, &t ); - // Handle leap second and status - if ( tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0 ) + if ( mbg_rc_is_success( rc ) ) { - if ( *status & PCPS_LS_ANN ) + // Handle leap second and status + if ( tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0 ) { - // Set leap second enabled flag on rollover to the leap second and clear announce flag - *status &= ~PCPS_LS_ANN; - *status |= PCPS_LS_ENB; - - // Decrement interpolated second to avoid automated overflow during the leap second. - // Second 59 appears for the second time. - *tstamp64 -= PCPS_HRT_BIN_FRAC_SCALE; + if ( *status & PCPS_LS_ANN ) + { + // Set leap second enabled flag on rollover to the leap second and clear announce flag + *status &= ~PCPS_LS_ANN; + *status |= PCPS_LS_ENB; + + // Decrement interpolated second to avoid automated overflow during the leap second. + // Second 59 appears for the second time. + *tstamp64 -= MBG_FRAC32_UNITS_PER_SEC; + } + else + if ( *status & PCPS_LS_ENB ) // Clear bits when leap second expires and 0:00:00 UTC is reached + *status &= ~( PCPS_LS_ANN | PCPS_LS_ENB ); } - else - if ( *status & PCPS_LS_ENB ) // Clear bits when leap second expires and 0:00:00 UTC is reached - *status &= ~( PCPS_LS_ANN | PCPS_LS_ENB ); } } } // mbg_chk_tstamp64_leap_sec -#endif // defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX ) +#endif // !defined( __BORLANDC__ ) + +#endif // defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_POSIX ) @@ -3475,6 +5727,10 @@ void uint64_to_pcps_time_stamp( PCPS_TIME_STAMP *ts, uint64_t n ) #endif +#ifdef __cplusplus +} +#endif + #if defined( _USING_BYTE_ALIGNMENT ) #pragma pack() // set default alignment #undef _USING_BYTE_ALIGNMENT @@ -3484,6 +5740,7 @@ void uint64_to_pcps_time_stamp( PCPS_TIME_STAMP *ts, uint64_t n ) #undef _ext +#undef _DO_INIT #endif /* _MBGDEVIO_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgerror.c b/src/external/bsd/meinberg/dist/mbglib/common/mbgerror.c new file mode 100755 index 0000000..ffd4bb8 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgerror.c @@ -0,0 +1,793 @@ + +/************************************************************************** + * + * $Id: mbgerror.c 1.3 2017/07/05 09:20:07 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Meinberg Library to communicate with USB devices from user space + * + * ----------------------------------------------------------------------- + * $Log: mbgerror.c $ + * Revision 1.3 2017/07/05 09:20:07 martin + * Fixed a bug where POSIX error ENODEV wasn't mapped at all, but + * EXDEV was instead translated erraneously to MBG_ERR_NO_DEV. + * Mapped POSIX error ENOSPC to MBG_ERR_NO_SPACE, and EFAULT + * to MBG_ERR_INV_PARM. + * Mapped Windows WSA error codes WSAEFAULT and WSAEINVAL + * to MBG_ERR_INV_PARM. + * Renamed mbg_ioctl_err() to mbg_cond_err_msg(). + * New function mbg_cond_err_msg_info() which takes an optional + * info string which is printed if the error code to be checked + * is MBG_ERR_NOT_SUPP_BY_DEV. + * Fixed build in Windows kernel mode. + * Fixed syntax error in CVI-specific code. + * Quieted some compiler warnings. + * Revision 1.2 2016/08/05 12:25:44Z martin + * Added some functions. + * Revision 1.1 2014/03/07 12:08:14 martin + * Initial revision. + * + **************************************************************************/ + +#define _MBGERROR + #include <mbgerror.h> +#undef _MBGERROR + +#include <mbg_tgt.h> + +#include <stdio.h> +#include <string.h> + +#if defined( MBG_TGT_POSIX ) || \ + defined( MBG_TGT_WIN32 ) || \ + defined( MBG_TGT_DOS ) + #define _MBG_TGT_HAS_POSIX_ERRNO 1 +#else + #define _MBG_TGT_HAS_POSIX_ERRNO 0 +#endif + +#if _MBG_TGT_HAS_POSIX_ERRNO + #include <errno.h> +#endif + +#if defined( MBG_TGT_DOS ) + #include <stddef.h> +#endif + +#if defined( MBG_TGT_POSIX ) + #include <netdb.h> +#endif + +#if defined(USE_MBG_ZLIB) + #include <zlib.h> +#endif + + +typedef struct +{ + int orig_errno; + int mbg_errno; + +} ERRNO_CNV_ENTRY; + + + +#if _MBG_TGT_HAS_POSIX_ERRNO + +static ERRNO_CNV_ENTRY posix_errno_table[] = +{ + // POSIX codes taken from Linux asm-generic/errno.h + { EPERM, MBG_ERR_PERM }, // 1, Operation not permitted + { ENOENT, MBG_ERR_NO_ENTITY }, // 2, No such file or directory + // { ESRCH, }, // 3, No such process + { EINTR, MBG_ERR_INTR }, // 4, Interrupted system call + { EIO, MBG_ERR_IO }, // 5, I/O error + { ENXIO, MBG_ERR_NOT_FOUND }, // 6, No such device or address + // { E2BIG, }, // 7, Argument list too long + // { ENOEXEC, }, // 8, Exec format error + // { EBADF, }, // 9, Bad file number + // { ECHILD, }, // 10, No child processes + // { EAGAIN, }, // 11, Try again + { ENOMEM, MBG_ERR_NO_MEM }, // 12, Out of memory + { EACCES, MBG_ERR_ACCESS }, // 13, Permission denied + { EFAULT, MBG_ERR_INV_PARM }, // 14, Bad address, e.g. invalid pointer + // { ENOTBLK, }, // 15, Block device required + { EBUSY, MBG_ERR_BUSY }, // 16, Device or resource busy + { EEXIST, MBG_ERR_EXIST }, // 17, File exists + // { EXDEV, }, // 18, Cross-device link + { ENODEV, MBG_ERR_NO_DEV }, // 19, No such device + // { ENOTDIR, }, // 20, Not a directory + // { EISDIR, }, // 21, Is a directory + { EINVAL, MBG_ERR_INV_PARM }, // 22, Invalid argument + // { ENFILE, }, // 23, File table overflow + // { EMFILE, }, // 24, Too many open files + // { ENOTTY, }, // 25, Not a typewriter + // { ETXTBSY, }, // 26, Text file busy + // { EFBIG, }, // 27, File too large + { ENOSPC, MBG_ERR_NO_SPACE }, // 28, No space left on device + { ESPIPE, MBG_ERR_PIPE }, // 29, Illegal seek + // { EROFS, }, // 30, Read-only file system + // { EMLINK, }, // 31, Too many links + // { EPIPE, }, // 32, Broken pipe + // { EDOM, }, // 33, Math argument out of domain of func + { ERANGE, MBG_ERR_RANGE }, // 34, Math result not representable +#if defined( EOVERFLOW ) + { EOVERFLOW, MBG_ERR_OVERFLOW }, // 75, Value too large for defined data type +#endif +#if defined( ENOTSOCK ) + { ENOTSOCK, MBG_ERR_NOT_A_SOCKET }, // 88, Socket operation on non-socket +#endif +#if defined( ECONNRESET ) + { ECONNRESET, MBG_ERR_CONN_RESET }, // 104, Connection reset by peer +#endif + { 0, 0 } // end-of-table identifier + +}; // posix_errno_table + +#endif // _MBG_TGT_HAS_POSIX_ERRNO + + + +#if defined( MBG_TGT_POSIX ) + +static ERRNO_CNV_ENTRY posix_h_errno_table[] = +{ + // POSIX codes taken from Linux netdb.h + { HOST_NOT_FOUND, MBG_ERR_HOST_NOT_FOUND }, // The specified host is unknown + // { NO_ADDRESS, }, // Usually same numeric value as NO_DATA + // { NO_DATA, }, // The requested name is valid but does not have an IP address + // { NO_RECOVERY, }, // A nonrecoverable name server error occurred + // { TRY_AGAIN, }, // A temporary error occurred on an authoritative name server. Try again later. + { 0, 0 } // end-of-table identifier + +}; // posix_h_errno_table + +#endif // defined( MBG_TGT_POSIX ) + + + +#if defined( MBG_TGT_CVI ) + +static ERRNO_CNV_ENTRY cvi_rs232_error_table[] = +{ + // { kRS_UnknownSysError, }, // Unknown system error. + // { kRS_InvalidPortNum, }, // In valid port number. + // { kRS_PortNotOpen, }, // Port is not open. + // { kRS_UnknownIOError, }, // Unknown I/O error. + // { kRS_InternalError, }, // Unexpected internal error. + // { kRS_NoPortFound, }, // No serial port found. + // { kRS_CanNotOpenPort, }, // Cannot open port. + // { kRS_NullPointerPassed, }, // A NULL pointer was passed when a non-NULL pointer was expected. + // { kRS_OutOfMemory, }, // Out of memory. + // { kRS_OutOfSystemResources, }, // Unable to allocate system resources. + // { kRS_InvalidParameter, }, // Invalid parameter. + // { kRS_InvalidBaudRate, }, // Invalid baud rate. + // { kRS_InvalidParity, }, // Invalid parity. + // { kRS_InvalidDataBits, }, // Invalid number of data bits. + // { kRS_InvalidStopBits, }, // Invalid number of stop bits. + // { kRS_BadFileHandle, }, // Bad file handle. + // { kRS_FileIOError, }, // File I/O error. + // { kRS_InvalidCount, }, // Invalid count; must be greater than or equal to 0. + // { kRS_InvalidIntLevel, }, // Invalid interrupt level. + // { kRS_IOTimeOut, }, // I/O operation timed out. + // { kRS_InvalidBreakTime, }, // Break time must be a positive value. + // { kRS_InvalidInQSize, }, // Requested input queue size must be 0 or greater. + // { kRS_InvalidOutQSize, }, // Requested output queue size must be 0 or greater. + // { kRS_GeneralIOFailure, }, // General I/O error. + // { kRS_InvalidBufferPointer, }, // Buffer parameter is NULL. + // { kRS_VISALibrariesMissing, }, // A necessary run-time library could not be found or loaded. + // { kRS_NoAckReceived, }, // Packet was sent, but no acknowledgment was received. + // { kRS_MaxRetriesBeforeSend, }, // Packet was not sent within retry limit. + // { kRS_MaxRetriesBeforeReceived, }, // Packet was not received within retry limit. + // { kRS_UnexpectedEOT, }, // End of transmission character encountered when start of data character expected. + // { kRS_CanNotReadPackNum, }, // Unable to read packet number. + // { kRS_InconsistentPackNum, }, // Inconsistent packet number. + // { kRS_CanNotReadPackData, }, // Unable to read packet data. + // { kRS_CanNotReadCheckSum, }, // Unable to read checksum. + // { kRS_CheckSumError, }, // Checksum received did not match computed checksum. + // { kRS_PackSizeGTInQ, }, // Packet size exceeds input queue size. + // { kRS_OpenFileError, }, // Error opening file. + // { kRS_ReadFileError, }, // Error reading file. + // { kRS_NoInitNegAck, }, // Did not receive initial negative acknowledgment character. + // { kRS_NoAckAfterEOT, }, // Did not receive acknowledgment after end of transmission character was sent. + // { kRS_WriteFileError, }, // Error writing to file. + // { kRS_NoSOHorEOT, }, // Did not receive either a start of data or end of transmission character when expected. + // { kRS_TransferCancelled, }, // Transfer was canceled because CAN ASCII character was received. + // { kRS_InvalidStartDelay, }, // Invalid start delay. + // { kRS_InvalidMaxTries, }, // Invalid maximum number of retries. + // { kRS_InvalidWaitPeriod, }, // Invalid wait period. + // { kRS_InvalidPacketSize, }, // Invalid packet size. + // { kRS_CanNotReadCRC, }, // Unable to read Cyclical Redundancy Check. + // { kRS_CRCError, }, // Cyclical Redundancy Check error. + { 0, 0 } // end-of-table identifier + +}; // cvi_rs232_error_table + +#endif // defined( MBG_TGT_CVI ) + + + +#if defined( MBG_TGT_WIN32 ) && !defined( MBG_TGT_KERNEL ) + +static ERRNO_CNV_ENTRY win32_error_table[] = +{ + // Windows System Error Codes (0-499) + { ERROR_INVALID_PARAMETER, MBG_ERR_INV_PARM }, + + // Windows System Error Codes (1300-1699) + { ERROR_ACCESS_DENIED, MBG_ERR_ACCESS }, // + { ERROR_PRIVILEGE_NOT_HELD, MBG_ERR_PERM }, // + { ERROR_INVALID_HANDLE, MBG_ERR_INV_HANDLE }, // + { ERROR_NOT_ENOUGH_MEMORY, MBG_ERR_NO_MEM }, // + { ERROR_OUTOFMEMORY, MBG_ERR_NO_MEM }, // + // { ERROR_WRITE_PROTECT, }, // + // { ERROR_BAD_UNIT, }, // + // { ERROR_NOT_READY, }, // + // { ERROR_WRITE_FAULT, }, // + // { ERROR_READ_FAULT, }, // + // { ERROR_GEN_FAILURE, }, // + // { ERROR_SHARING_VIOLATION, }, // + // { ERROR_LOCK_VIOLATION, }, // + // { ERROR_NOT_SUPPORTED, }, // + // { ERROR_DUP_NAME, }, // + // { ERROR_BAD_DEV_TYPE, }, // + // { ERROR_BUFFER_OVERFLOW, }, // + { ERROR_BUSY, MBG_ERR_BUSY }, // + // { ERROR_NOACCESS, }, // + { 0, 0 } // end-of-table identifier + +}; // win32_error_table + + + +static ERRNO_CNV_ENTRY win32_wsa_err_table[] = +{ + { WSAEINTR, MBG_ERR_INTR }, // 10004L A blocking operation was interrupted by a call to WSACancelBlockingCall. + // { WSAEBADF // 10009L The file handle supplied is not valid. + // { WSAEACCES // 10013L An attempt was made to access a socket in a way forbidden by its access permissions. + { WSAEFAULT, MBG_ERR_INV_PARM }, // 10014L The system detected an invalid pointer address in attempting to use a pointer argument in a call. + { WSAEINVAL, MBG_ERR_INV_PARM }, // 10022L An invalid argument was supplied. + // { WSAEMFILE // 10024L Too many open sockets. + // { WSAEWOULDBLOCK // 10035L A non-blocking socket operation could not be completed immediately. + // { WSAEINPROGRESS // 10036L A blocking operation is currently executing. + // { WSAEALREADY // 10037L An operation was attempted on a non-blocking socket that already had an operation in progress. + { WSAENOTSOCK, MBG_ERR_NOT_A_SOCKET }, // 10038L An operation was attempted on something that is not a socket. + // { WSAEDESTADDRREQ // 10039L A required address was omitted from an operation on a socket. + // { WSAEMSGSIZE // 10040L A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself. + // { WSAEPROTOTYPE // 10041L A protocol was specified in the socket function call that does not support the semantics of the socket type requested. + // { WSAENOPROTOOPT // 10042L An unknown, invalid, or unsupported option or level was specified in a getsockopt or setsockopt call. + // { WSAEPROTONOSUPPORT // 10043L The requested protocol has not been configured into the system, or no implementation for it exists. + // { WSAESOCKTNOSUPPORT // 10044L The support for the specified socket type does not exist in this address family. + // { WSAEOPNOTSUPP // 10045L The attempted operation is not supported for the type of object referenced. + // { WSAEPFNOSUPPORT // 10046L The protocol family has not been configured into the system or no implementation for it exists. + // { WSAEAFNOSUPPORT // 10047L An address incompatible with the requested protocol was used. + // { WSAEADDRINUSE // 10048L Only one usage of each socket address (protocol/network address/port) is normally permitted. + // { WSAEADDRNOTAVAIL // 10049L The requested address is not valid in its context. + // { WSAENETDOWN // 10050L A socket operation encountered a dead network. + // { WSAENETUNREACH // 10051L A socket operation was attempted to an unreachable network. + // { WSAENETRESET // 10052L The connection has been broken due to keep-alive activity detecting a failure while the operation was in progress. + // { WSAECONNABORTED // 10053L An established connection was aborted by the software in your host machine. + { WSAECONNRESET, MBG_ERR_CONN_RESET }, // 10054L An existing connection was forcibly closed by the remote host. + // { WSAENOBUFS // 10055L An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full. + // { WSAEISCONN // 10056L A connect request was made on an already connected socket. + // { WSAENOTCONN // 10057L A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied. + // { WSAESHUTDOWN // 10058L A request to send or receive data was disallowed because the socket had already been shut down in that direction with a previous shutdown call. + // { WSAETOOMANYREFS // 10059L Too many references to some kernel object. + // { WSAETIMEDOUT // 10060L A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. + // { WSAECONNREFUSED // 10061L No connection could be made because the target machine actively refused it. + // { WSAELOOP // 10062L Cannot translate name. + // { WSAENAMETOOLONG // 10063L Name component or name was too long. + // { WSAEHOSTDOWN // 10064L A socket operation failed because the destination host was down. + // { WSAEHOSTUNREACH // 10065L A socket operation was attempted to an unreachable host. + // { WSAENOTEMPTY // 10066L Cannot remove a directory that is not empty. + // { WSAEPROCLIM // 10067L A Windows Sockets implementation may have a limit on the number of applications that may use it simultaneously. + // { WSAEUSERS // 10068L Ran out of quota. + // { WSAEDQUOT // 10069L Ran out of disk quota. + // { WSAESTALE // 10070L File handle reference is no longer available. + // { WSAEREMOTE // 10071L Item is not available locally. + // { WSASYSNOTREADY // 10091L WSAStartup cannot function at this time because the underlying system it uses to provide network services is currently unavailable. + // { WSAVERNOTSUPPORTED // 10092L The Windows Sockets version requested is not supported. + { WSANOTINITIALISED, MBG_ERR_SOCK_INIT }, // 10093L Either the application has not called WSAStartup, or WSAStartup failed. + // { WSAEDISCON // 10101L Returned by WSARecv or WSARecvFrom to indicate the remote party has initiated a graceful shutdown sequence. + // { WSAENOMORE // 10102L No more results can be returned by WSALookupServiceNext. + // { WSAECANCELLED // 10103L A call to WSALookupServiceEnd was made while this call was still processing. The call has been canceled. + // { WSAEINVALIDPROCTABLE // 10104L The procedure call table is invalid. + // { WSAEINVALIDPROVIDER // 10105L The requested service provider is invalid. + // { WSAEPROVIDERFAILEDINIT // 10106L The requested service provider could not be loaded or initialized. + // { WSASYSCALLFAILURE // 10107L A system call that should never fail has failed. + // { WSASERVICE_NOT_FOUND // 10108L No such service is known. The service cannot be found in the specified name space. + // { WSATYPE_NOT_FOUND // 10109L The specified class was not found. + // { WSA_E_NO_MORE // 10110L No more results can be returned by WSALookupServiceNext. + // { WSA_E_CANCELLED // 10111L A call to WSALookupServiceEnd was made while this call was still processing. The call has been canceled. + // { WSAEREFUSED // 10112L A database query failed because it was actively refused. + { WSAHOST_NOT_FOUND, MBG_ERR_HOST_NOT_FOUND }, // 11001L No such host is known. + // { WSATRY_AGAIN // 11002L This is usually a temporary error during hostname resolution and means that the local server did not receive a response from an authoritative server. + // { WSANO_RECOVERY // 11003L A non-recoverable error occurred during a database lookup. + // { WSANO_DATA // 11004L The requested name is valid, but no data of the requested type was found. + { 0, 0 } // end-of-table identifier + +}; // win32_wsa_err_table + +#endif // defined( MBG_TGT_WIN32 ) + + + +/** + * @brief Lookup some error code in a conversion table + * + * @param[in] orig_errno + * @param[in] tbl + * + * @return @ref MBG_ERROR_CODES associated with the original error code, + * or ::MBG_ERR_UNSPEC if origianl code not found in table. + */ +static /*HDR*/ +int lookup_mbg_errno( int orig_errno, const ERRNO_CNV_ENTRY tbl[] ) +{ + const ERRNO_CNV_ENTRY *p; + + for ( p = tbl; p->orig_errno || p->mbg_errno; p++ ) + if ( p->orig_errno == orig_errno ) + return p->mbg_errno; + + return MBG_ERR_UNSPEC; + +} // lookup_mbg_errno + + + +/*HDR*/ +/** + * @brief Return an error string associated with the @ref MBG_ERROR_CODES + * + * @param[in] mbg_errno One of the @ref MBG_ERROR_CODES + * + * @return A constant string describing the error, or NULL for unknown error codes + */ +const char *mbg_strerror( int mbg_errno ) +{ + static const MBG_CODE_NAME_TABLE_ENTRY tbl[] = MBG_ERR_NAMES_ENG; + + const MBG_CODE_NAME_TABLE_ENTRY *p; + + for ( p = tbl; p->name; p++ ) + { + if ( mbg_errno == p->code ) + return p->name; + } + + + return "Unknown error"; + +} // mbg_strerror + + + +#if !( defined( MBG_TGT_WIN32 ) && defined( MBG_TGT_KERNEL ) ) // not supported in Windows kernel mode + +/*HDR*/ +/** + * @brief Check if a value is an error code and print an associated error message + * + * @param[in] rc A positive number including ::MBG_SUCCESS, or one of the @ref MBG_ERROR_CODES + * @param[in] what A string indicated what failed + * + * @return true if rc represented an error code, and a message has been printed, else false + */ +bool mbg_cond_err_msg( int rc, const char *what ) +{ + return mbg_cond_err_msg_info( rc, what, NULL ); + +} // mbg_cond_err_msg + + + +/*HDR*/ +/** + * @brief Check if a value is an general or a "not supported" error code and print an associated message + * + * If rc contains an error code then an error message is printed, and true is returned. + * + * If the optional parameter string info2 is not NULL then it should contain + * the name of a feature which has been tested before. In this case, if the error + * code is the specific error ::MBG_ERR_NOT_SUPP_BY_DEV then a "not supported" message + * is printed using info2. + * + * If info2 is NULL, or the error code is not ::MBG_ERR_NOT_SUPP_BY_DEV then the standard + * error message is printed anyway. + * + * @param[in] rc A positive number including ::MBG_SUCCESS, or one of the @ref MBG_ERROR_CODES + * @param[in] what A string indicated what failed + * @param[in] info An optional informational string telling what is not supported (may be NULL). + * + * @return true if rc represented an error code, and a message has been printed, else false + */ +bool mbg_cond_err_msg_info( int rc, const char *what, const char *info ) +{ + if ( mbg_rc_is_error( rc ) ) + { + if ( info && ( rc == MBG_ERR_NOT_SUPP_BY_DEV ) ) + fprintf( stderr, "This device does not %s.\n", info ); + else + fprintf( stderr, "** %s failed: %s (rc: %i)\n", what, mbg_strerror( rc ), rc ); + + return true; + } + + return false; + +} // mbg_cond_err_msg_info + +#endif // !( defined( MBG_TGT_WIN32 ) && defined( MBG_TGT_KERNEL ) ) + + + +#if defined( MBG_TGT_CVI ) + +/*HDR*/ +/** + * @brief Translate an error code from the Labwindows/CVI RS-232 library to one of the @ref MBG_ERROR_CODES + * + * @param[in] cvi_rc An error code returned by a CVI RS-232 library function + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + * + * @see http://zone.ni.com/reference/en-XX/help/370051V-01/cvi/libref/cvirs232_error_conditions/ + */ +int mbg_cvi_rs232_error_to_mbg( int cvi_rc, const char *info ) +{ + #if DEBUG + if ( info ) + fprintf( stderr, "%s, CVI RS-232 rc: %i\n", info, cvi_rc ); + #else + (void) info; // avoid compiler warning + #endif + + return ( cvi_rc < 0 ) ? lookup_mbg_errno( cvi_rc, cvi_rs232_error_table ) : MBG_SUCCESS; + +} // mbg_cvi_rs232_error_to_mbg + +#endif + + + +#if defined( MBG_TGT_WIN32 ) && !defined( MBG_TGT_KERNEL ) + +/*HDR*/ +/** + * @brief Translate a Windows non-socket API error code to one of the @ref MBG_ERROR_CODES + * + * @param[in] last_err A Windows non-socket API error code as returned by GetLastError() + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_win32_last_err_to_mbg( DWORD last_err, const char *info ) +{ + #if DEBUG + if ( info ) + fprintf( stderr, "%s, wsa_err: 0x%08lX\n", info, (long) last_err ); + #else + (void) info; // avoid compiler warning + #endif + + return ( last_err == ERROR_SUCCESS ) ? MBG_SUCCESS : lookup_mbg_errno( last_err, win32_error_table ); + +} // mbg_win32_last_err_to_mbg + + + +/*HDR*/ +/** + * @brief Translate a Windows socket API error code to one of the @ref MBG_ERROR_CODES + * + * @param[in] wsa_err A Windows socket API error code as returned by WSAGetLastError() + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_win32_wsa_err_to_mbg( DWORD wsa_err, const char *info ) +{ + #if DEBUG + if ( info ) + fprintf( stderr, "%s, wsa_err: 0x%08lX\n", info, (long) wsa_err ); + #else + (void) info; // avoid compiler warning + #endif + + // The WSA error code is only retrieved after an error has occurred, so + // we don't need care for the success case here. + return lookup_mbg_errno( wsa_err, win32_wsa_err_table ); + +} // mbg_win32_wsa_err_to_mbg + +#endif // defined( MBG_TGT_WIN32 ) + + + +#if _MBG_TGT_HAS_POSIX_ERRNO + +/*HDR*/ +/** + * @brief Translate a POSIX errno error code to one of the @ref MBG_ERROR_CODES + * + * @param[in] posix_errno A POSIX error code as usually defined in errno.h + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_posix_errno_to_mbg( int posix_errno, const char *info ) +{ + #if DEBUG + if ( info ) + fprintf( stderr, "%s: %s (errno: %i)\n", info, + strerror( posix_errno ), posix_errno ); + #else + (void) info; // avoid compiler warning + #endif + + return lookup_mbg_errno( posix_errno, posix_errno_table ); + +} // mbg_posix_errno_to_mbg + +#endif // _MBG_TGT_HAS_POSIX_ERRNO + + + +#if defined( MBG_TGT_POSIX ) + +/*HDR*/ +/** + * @brief Translate a POSIX h_errno error code to one of the @ref MBG_ERROR_CODES + * + * This function is specific to translate error codes returned by + * gethostbyname() and gethostbyaddr(). In case of error these functions + * don't set errno but h_errno to a specific value. + * + * The functions gethostbyname() and gethostbyaddr() are obsolete, + * and getaddressinfo() should be used preferably. + * + * @param[in] posix_h_errno An error code as usually defined in netdb.h + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_posix_h_errno_to_mbg( int posix_h_errno, const char *info ) +{ + #if DEBUG + if ( info ) + fprintf( stderr, "%s: %s (h_errno: %i)\n", info, + hstrerror( posix_h_errno ), posix_h_errno ); + #else + (void) info; // avoid compiler warning + #endif + + return lookup_mbg_errno( posix_h_errno, posix_h_errno_table ); + +} // mbg_posix_h_errno_to_mbg + +#endif // defined( MBG_TGT_POSIX ) + + + +/*HDR*/ +/** + * @brief Get and translate last error after non-socket function call + * + * Retrieve the "last error" code after a non-socket function has been called + * and translate to one of the @ref MBG_ERROR_CODES. + * + * On POSIX systems the "last error" code is always stored in errno, but + * e.g. under Windows the "last error" code after a socket function + * has to be retrieved by calling WSAGetLastError(), whereas the "last error" + * code from non-socket POSIX-like functions has to be retrieved + * by calling GetLastError(). + * + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_get_last_error( const char *info ) +{ + #if defined( MBG_TGT_WIN32 ) + + #if !defined( MBG_TGT_KERNEL ) + // Under Windows the "last error" code after a non-socket function + // has to be retrieved by calling GetLastError(), whereas + // the "last error" code from POSIX-like socket functions + // is retrieved by calling WSAGetLastError(). + return mbg_win32_last_err_to_mbg( GetLastError(), info ); + #else + return MBG_ERR_GENERIC; + #endif + + #elif defined( MBG_TGT_POSIX ) + + // On POSIX systems the "last error" code is always stored in errno. + return mbg_posix_errno_to_mbg( errno, info ); + + #else + + // ### TODO #error This function is not supported for this target. + return mbg_posix_errno_to_mbg( errno, info ); + + #endif + +} // mbg_get_last_error + + + +#if !defined( MBG_TGT_DOS ) + +/*HDR*/ +/** + * @brief Get and translate last error after socket function call + * + * Retrieve the "last error" code after a socket function has been called + * and translate to one of the @ref MBG_ERROR_CODES. + * + * On POSIX systems the "last error" code is always stored in errno, but + * e.g. under Windows the "last error" code after a socket function + * has to be retrieved by calling WSAGetLastError, whereas the "last error" + * code from non-socket POSIX-like functions is stored in errno as usual. + * + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_get_last_socket_error( const char *info ) +{ + #if defined( MBG_TGT_CVI ) + + #warning This needs to be implemented for CVI + return MBG_ERR_UNSPEC; + + #elif defined( MBG_TGT_WIN32 ) + + #if !defined( MBG_TGT_KERNEL ) + // Under Windows the "last error" code after a socket function + // has to be retrieved by calling WSAGetLastError, whereas + // the "last error" code from non-socket POSIX-like functions + // is stored in errno as usual. + return mbg_win32_wsa_err_to_mbg( WSAGetLastError(), info ); + #else + return MBG_ERR_GENERIC; + #endif + + #elif defined( MBG_TGT_POSIX ) + + // On POSIX systems the "last error" code is always stored in errno. + return mbg_posix_errno_to_mbg( errno, info ); + + #else + + #error This function is not supported for this target. + + #endif + +} // mbg_get_last_socket_error + + + +/*HDR*/ +/** + * @brief Retrieve and convert last error after gethostbyname() + * + * This function is specific to retrieve and translate error codes + * returned by gethostbyname() and gethostbyaddr(). In case of error + * these functions don't set errno but h_errno on POSIX systems, but + * under Windows the error code can be retrieved by WSAGetLastError() + * as usual. + * + * The functions gethostbyname() and gethostbyaddr() are obsolete, + * and getaddressinfo() should be used preferably. + * + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_get_gethostbyname_error( const char *info ) +{ + #if defined( MBG_TGT_CVI ) + + #warning This needs to be implemented for CVI + return MBG_ERR_UNSPEC; + + #elif defined( MBG_TGT_WIN32 ) + + #if !defined( MBG_TGT_KERNEL ) + return mbg_win32_wsa_err_to_mbg( WSAGetLastError(), info ); + #else + return MBG_ERR_GENERIC; + #endif + + #elif defined( MBG_TGT_POSIX ) + + return mbg_posix_h_errno_to_mbg( h_errno, info ); + + #else + + #error This function is not supported for this target. + + #endif + +} // mbg_get_gethostbyname_error + +#endif // !defined( MBG_TGT_DOS ) + + + +#if 0 // not yet finished +// error handler for getaddressinfo() +/* + * Handle specific error returned by getaddressinfo() + */ + /*HDR*/ +int mbg_gai_error( int rc, const char *info ) +{ + #if defined( MBG_TGT_CVI ) + + #warning This needs to be implemented for CVI + return MBG_ERR_UNSPEC; + + #elif defined( MBG_TGT_WIN32 ) + + return mbg_win32_wsa_err_to_mbg( WSAGetLastError(), info ); + + #elif defined( MBG_TGT_POSIX ) + + return mbg_posix_h_errno_to_mbg( h_errno, info ); + + #else + + return MBG_ERR_UNSPEC; + + #endif + +} // mbg_get_gai_error + +#endif + + + +#if defined( USE_MBG_ZLIB ) + +/*HDR*/ +/** + * @brief Retrieve and convert last zlib internal error code + * + * @param[in] zlib_error zlib internal error code + * @param[in] info An optional informational text string, or NULL + * @param[in] msg An optional zlib specific error msg, or NULL. + * Struct z_stream contains member msg. + * + * @return One of the @ref MBG_ERROR_CODES + */ +int mbg_zlib_error_to_mbg( int zlib_error, const char *info, const char *msg ) +{ + #if DEBUG + if ( info && msg ) + fprintf( stderr, "%s: %s (zlib_error: %d)\n", info, + msg, zlib_error ); + #endif + + switch ( zlib_error ) + { + case Z_ERRNO: return mbg_get_last_error( info ); + case Z_MEM_ERROR: return MBG_ERR_NO_MEM; + /* + * All other zlib error codes are not specified any further. + * So, it's hard to guess what they mean and we return MBG_UNSPEC so far. + */ + default: + return MBG_ERR_UNSPEC; + } + +} // mbg_zlib_error_to_mbg + +#endif // defined( USE_MBG_ZLIB ) + + diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgerror.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgerror.h index 714dd45..20a3edc 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbgerror.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgerror.h @@ -1,8 +1,7 @@ /************************************************************************** * - * $Id: mbgerror.h 1.5.1.1 2011/04/20 16:09:19 martin TRASH martin $ - * $Name: $ + * $Id: mbgerror.h 1.15 2017/07/05 09:27:25 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -12,7 +11,40 @@ * * ----------------------------------------------------------------------- * $Log: mbgerror.h $ - * Revision 1.5.1.1 2011/04/20 16:09:19 martin + * Revision 1.15 2017/07/05 09:27:25 martin + * New error code MBG_ERR_PARM_FMT. + * Changed message text for MBG_ERR_NO_ENTITY. + * Replaced old _mbg_err_to_os() macro by new inline functions + * mbg_errno_to_os() and mbg_ret_val_to_os(). + * Fixed build under Windows. + * Updated doxygen comments. + * Updated function prototypes. + * Revision 1.14 2017/05/10 15:21:39 martin + * Tiny cleanup. + * Revision 1.13 2017/02/28 15:23:14 gregoire + * error code MBG_ERR_INV_IDX added + * Revision 1.12 2017/01/10 15:54:56 philipp + * Fixed syntax error + * Revision 1.11 2017/01/10 14:26:31 philipp + * Added error MBG_ERR_NOT_CONFIGURED + * Revision 1.10 2016/12/16 12:40:33 thomas-b + * Added MBG_ERR_NO_SPACE + * Revision 1.9 2016/10/31 17:41:55 martin + * New error code MBG_ERR_DATA_FMT. + * Revision 1.8 2016/08/05 12:29:20 martin + * Re-enabled some symbols which have been commented out. + * Added new codes, and initializers for code/string conversion tables. + * Updated doxygen comments. + * Updated function prorotypes. + * Revision 1.7 2014/05/27 13:32:47Z martin + * Defined additional common error codes which can be + * translated from OS specific codes. + * Function prototypes from new module mbgerror.c. + * Comments in doxygen style. + * Revision 1.6 2012/10/02 18:42:26Z martin + * New codes MBG_ERR_N_POUT_EXCEEDS_SUPP and + * MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP. + * Modified comments for doxygen. * Revision 1.5 2011/03/31 10:56:17 martin * Added MBG_ERR_COPY_TO_USER and MBG_ERR_COPY_FROM_USER. * Revision 1.4 2008/12/05 13:28:50 martin @@ -36,6 +68,7 @@ /* Other headers to be included */ #include <mbg_tgt.h> +#include <words.h> #ifdef _MBGERROR #define _ext @@ -47,112 +80,530 @@ /* Start of header body */ +#ifdef __cplusplus +extern "C" { +#endif + +#if defined( MBG_TGT_WIN32 ) + + #if !defined( STATUS_SUCCESS ) // not in kernel mode + #define STATUS_SUCCESS 0 + #endif + +#endif + + +#if !defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_KERNEL ) + // A dummy declaration for DWORD to avoid compiler errors. + // Also reqired in Windows kernel mode. + #define DWORD uint32_t +#endif + + + /** - @defgroup group_error_codes Error codes - - Error codes used with Meinberg devices and drivers. - The codes will be translated into an OS dependent error code, - when they are returned to the calling function. - - For Windows, these codes are made positive and or'ed with 0xE0000000 afterwards. - - Example: Code -19 (#MBG_ERR_GENERIC) will be converted to 0xE0000013 under Windows. - - @note Attention: - These error codes below must match exactly the corresponding codes that are evaluated in user space. - For Windows, they are located in messages.mc/.h in mbgsvctl.dll - - @{ -*/ - - -#define MBG_SUCCESS PCPS_SUCCESS /**< 0, no error */ - -// The codes below are defined in pcpsdefs.h and returned by the firmware: -#define MBG_ERR_STIME PCPS_ERR_STIME /**< -1, invalid date/time/status passed */ -#define MBG_ERR_CFG PCPS_ERR_CFG /**< -2, invalid parms with a PCPS_CFG_GROUP cmd */ - -// Codes returned by the driver's low level functions: -#define MBG_ERR_GENERIC -19 /**< Generic error */ -#define MBG_ERR_TIMEOUT -20 /**< Timeout accessing the board */ -#define MBG_ERR_FW_ID -21 /**< Invalid firmware ID */ -#define MBG_ERR_NBYTES -22 /**< The number of parameter bytes - passed to the board did not match - the number of bytes expected. */ -#define MBG_ERR_INV_TIME -23 /**< The device's time is not valid */ -#define MBG_ERR_FIFO -24 /**< The device's FIFO is empty, though - it shouldn't be */ -#define MBG_ERR_NOT_READY -25 /**< Board is temporary unable to respond - (during initialization after RESET) */ -#define MBG_ERR_INV_TYPE -26 /**< Board did not recognize data type */ - - -// Codes returned by the driver's high level functions: -#define MBG_ERR_NO_MEM -27 /**< Failed to allocate memory */ -#define MBG_ERR_CLAIM_RSRC -28 /**< Failed to claim port or mem resource */ -#define MBG_ERR_DEV_NOT_SUPP -29 /**< Specified device type not supported by driver */ -#define MBG_ERR_INV_DEV_REQUEST -30 /**< IOCTL call not supported by driver */ -#define MBG_ERR_NOT_SUPP_BY_DEV -31 /**< Cmd or feature not supported by device */ -#define MBG_ERR_USB_ACCESS -32 /**< USB access failed */ -#define MBG_ERR_CYCLIC_TIMEOUT -33 /**< Cyclic event (IRQ, etc.) didn't occur */ -#define MBG_ERR_NOT_SUPP_ON_OS -34 /**< The function is not supported on this operating system */ -#define MBG_ERR_LIB_NOT_COMPATIBLE -35 /**< The installed version of the DLL/shared object is not - compatible with version used to build the application */ -#define MBG_ERR_N_COM_EXCEEDS_SUPP -36 /**< The number of COM ports provided by the device - exceeds the maximum supported by the driver */ -#define MBG_ERR_N_STR_EXCEEDS_SUPP -37 /**< The number of string formats supported by the device - exceeds the maximum supported by the driver */ -#define MBG_ERR_IRQ_UNSAFE -38 /**< The enabled IRQs are unsafe with this firmware/ASIC version */ -#define MBG_ERR_N_POUT_EXCEEDS_SUPP -39 /**< The number of programmable outputs provided by the device - exceeds the maximum supported by the driver */ + * @brief Error codes used with Meinberg devices and drivers + * + * Appropriate error strings can be retrieved via the ::mbg_strerror function. + * + * @see ::MBG_ERR_NAMES_ENG + * + * @anchor MBG_RETURN_CODES @{ */ + +/* ### TODO + * Under Windows, some message strings are provided as resources appended + * to the mbgctrl DLL, but the codes specified here have to be translated + * to Windows-specific error codes before the appropriate resource string + * can be retrieved. Actually this is done by taking the absolute number + * of an error code and have it or'ed with 0xE0000000 afterwards, e.g. + * ::MBG_ERR_GENERIC (-19) will yield Windows code 0xE0000013. + * * See ::_mbg_err_to_os + */ + +// NOTE: Some of these codes have to match codes which are defined in pcpsdefs.h +// and returned by the firmware of bus-level devices, so the definitions +// must *not* be renumbered. + +#define MBG_SUCCESS 0 ///< no error, has to match ::PCPS_SUCCESS + + /** @anchor MBG_ERROR_CODES @{ */ + +// Other codes which have to match codes defined in pcpsdefs.h returned by bus-level devices +#define MBG_ERR_STIME -1 ///< tried to write invalid date/time/status to device, has to match ::PCPS_ERR_STIME +#define MBG_ERR_CFG -2 ///< tried to write invalid configuration parameters to device, has to match ::PCPS_ERR_CFG (see also ::MBG_ERR_INV_CFG) + + +// Codes returned by low level functions of the bus-level device driver +#define MBG_ERR_GENERIC -19 ///< generic error +#define MBG_ERR_TIMEOUT -20 ///< timeout accessing the device +#define MBG_ERR_FW_ID -21 ///< invalid firmware ID +#define MBG_ERR_NBYTES -22 ///< the number of parameter bytes passed to the device did not + ///< match the number of bytes expected by the device + +#define MBG_ERR_INV_TIME -23 ///< the device doesn't have valid time +#define MBG_ERR_FIFO -24 ///< the data FIFO of a bus-level device is empty, though it shouldn't be +#define MBG_ERR_NOT_READY -25 ///< bus-level device is temp. unable to respond e.g. during init. after RESET +#define MBG_ERR_INV_TYPE -26 ///< bus-level device didn't recognize data type + + +// Codes returned by the high level API functions +#define MBG_ERR_NO_MEM -27 ///< failed to allocate memory +#define MBG_ERR_CLAIM_RSRC -28 ///< failed to claim port or mem resource +#define MBG_ERR_DEV_NOT_SUPP -29 ///< specified device type not supported by driver +#define MBG_ERR_INV_DEV_REQUEST -30 ///< IOCTL call not supported by driver +#define MBG_ERR_NOT_SUPP_BY_DEV -31 ///< cmd or feature not supported by device +#define MBG_ERR_USB_ACCESS -32 ///< USB access failed +#define MBG_ERR_CYCLIC_TIMEOUT -33 ///< cyclic event (IRQ, etc.) didn't occur +#define MBG_ERR_NOT_SUPP_ON_OS -34 ///< function is not supported under this operating system +#define MBG_ERR_LIB_NOT_COMPATIBLE -35 ///< installed shared lib. version not compat. with version used at build time +#define MBG_ERR_N_COM_EXCEEDS_SUPP -36 ///< num. COM ports of the device exceeds max. supp. by driver +#define MBG_ERR_N_STR_EXCEEDS_SUPP -37 ///< num. string formats of the device exceeds max. supp. by driver +#define MBG_ERR_IRQ_UNSAFE -38 ///< enabled IRQ of bus-level device is unsafe with this firmware/ASIC version +#define MBG_ERR_N_POUT_EXCEEDS_SUPP -39 ///< num. prog. outputs of the device exceeds max. supp. by driver // Legacy codes used with DOS TSRs only: -#define MBG_ERR_INV_INTNO -40 /**< Invalid interrupt number */ -#define MBG_ERR_NO_DRIVER -41 /**< A driver could not be found */ -#define MBG_ERR_DRV_VERSION -42 /**< The driver is too old */ +#define MBG_ERR_INV_INTNO -40 ///< invalid interrupt number +#define MBG_ERR_NO_DRIVER -41 ///< a driver could not be found +#define MBG_ERR_DRV_VERSION -42 ///< the driver is too old + +#define MBG_ERR_COPY_TO_USER -43 ///< kernel driver failed to copy data from kernel to user space +#define MBG_ERR_COPY_FROM_USER -44 ///< kernel driver failed to copy data from use to kernel space -#define MBG_ERR_COPY_TO_USER -43 /**< kernel driver failed to copy data from kernel to user space */ -#define MBG_ERR_COPY_FROM_USER -44 /**< kernel driver failed to copy data from use to kernel space */ // More codes returned by the driver's high level functions: +#define MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP -45 ///< num. PTP unicast masters of the device exceeds max. supp. by driver +#define MBG_ERR_N_GNSS_EXCEEDS_SUPP -46 ///< num. of GNSS systems supp. by device exceeds max. supp. by driver +#define MBG_ERR_N_GPIO_EXCEEDS_SUPP -47 ///< num. of GPIO ports supp. by device exceeds max. supp. by driver +#define MBG_ERR_N_XMR_EXCEEDS_SUPP -48 ///< num. of XMR sources supp. by device exceeds max. supp. by driver + +#define MBG_ERR_UNSPEC -60 ///< unspecified error + +#define MBG_ERR_HDR_CSUM -61 ///< binary protocol header checksum error +#define MBG_ERR_DATA_CSUM -62 ///< binary protocol data checksum error +#define MBG_ERR_RCVD_NACK -63 ///< binary protocol received reply msg with a NACK code +#define MBG_ERR_RCVD_NO_ACK -64 ///< binary protocol received reply msg without expected ACK code //### TODO +#define MBG_ERR_CONN_TYPE -65 ///< binary protocol no valid/supported connection type specified +#define MBG_ERR_BYTES_WRITTEN -66 ///< binary protocol failed to write all bytes +#define MBG_ERR_AUTH -67 ///< binary protocol failed authentication + +#define MBG_ERR_SOCK_INIT -68 ///< socket interface not initialized, or failed to initialize +#define MBG_ERR_INV_SOCK_FD -69 ///< invalid socket when tried to open network socket +#define MBG_ERR_NOT_A_SOCKET -70 ///< socket descriptor is not a socket +#define MBG_ERR_NBLOCK_WAIT_SLCT -71 ///< select timed out when waiting for non-blocking network port to become ready +#define MBG_ERR_NBLOCK_WAIT_WR_FD -72 ///< write fd not set after select when waiting for non-blocking network port to become ready + +#define MBG_ERR_IO -73 ///< generic I/O error +#define MBG_ERR_INV_PARM -74 ///< invalid parameter +#define MBG_ERR_NO_DEV -75 ///< specified device not found +#define MBG_ERR_NOT_FOUND -76 ///< specified item not found + +#define MBG_ERR_OVERFLOW -77 ///< range or buffer overflow +#define MBG_ERR_PIPE -78 ///< pipe error +#define MBG_ERR_INTR -79 ///< interrupted system call +#define MBG_ERR_ACCESS -80 ///< access denied, e.g. when trying to access a device +#define MBG_ERR_PERM -81 ///< operation not permitted, e.g. when trying to set the system time +#define MBG_ERR_BUSY -82 ///< device busy +#define MBG_ERR_INV_HANDLE -83 ///< invalid file/device handle specified + +#define MBG_ERR_XBP_CASC_LVL -84 ///< too many XBP cascading levels +#define MBG_ERR_ENCRYPT -85 ///< encryption failed +#define MBG_ERR_DECRYPT -86 ///< decryption failed + +#define MBG_ERR_DISCONN -87 ///< connection closed by remote site / host +#define MBG_ERR_INV_CFG -88 ///< invalid/inconsistent configuration parameters read from device, see also ::MBG_ERR_CFG +#define MBG_ERR_RANGE -89 ///< input parameter was out of range + +#define MBG_ERR_INV_TLV_ANN_BYTES -90 ///< number of announced TLV bytes doesn't match number of transferred bytes +#define MBG_ERR_INV_TLV_SIZE -91 ///< ### TODO +#define MBG_ERR_INV_TLV_UID -92 ///< ### TODO + +#define MBG_ERR_EXIST -93 ///< file exists +#define MBG_ERR_DATA_SIZE -94 ///< the received data size toesn't match the expected data size +#define MBG_ERR_NO_ENTITY -95 ///< no such file or directory +#define MBG_ERR_ALREADY_ALLOC -96 ///< pointer already allocated when trying to allocate memory +#define MBG_ERR_HOST_NOT_FOUND -97 ///< host not found +#define MBG_ERR_CONN_RESET -98 ///< connection reset by peer +#define MBG_ERR_DATA_FMT -99 ///< invalid data format + +#define MBG_ERR_NO_SPACE -100 ///< insufficient disk space left on the device +#define MBG_ERR_NOT_CONFIGURED -101 ///< configuration option is not active/configured +#define MBG_ERR_INV_IDX -102 ///< invalid index value used + +#define MBG_ERR_PARM_FMT -103 ///< parameter string format error + +// NOTE: New codes have to be appended to this list, and the sequence of codes must not +// be changed. Whenever new codes have been defined, appropriate entries have to be added +// to the ::MBG_ERR_NAMES_ENG table initializer below, and the Windows-specific message +// texts specified in messages.mc/.h from which the resources appended to mbgsvctl.dll +// are generated have to be updated accordingly. + +/** @} anchor MBG_ERROR_CODES */ + +/** @} anchor MBG_RETURN_CODES */ -#define MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP -39 /**< The number of PTP unicast masters supported by the device - exceeds the maximum supported by the driver */ -/** @} group_error_codes */ -// Depending on the operating system, the codes above have to be converted before -// they are sent up to user space -#if defined( MBG_TGT_WIN32 ) - #if !defined( STATUS_SUCCESS ) // not in kernel mode - #define STATUS_SUCCESS 0 - #endif +/** + * @brief Strings associated with @ref MBG_RETURN_CODES + * + * @see @ref MBG_RETURN_CODES + */ +#define MBG_ERR_NAMES_ENG \ +{ \ + { MBG_SUCCESS, "Success, no error" }, \ + { MBG_ERR_STIME, "Invalid date/time for device" }, \ + { MBG_ERR_CFG, "Invalid configuration parameters for device" }, \ + { MBG_ERR_GENERIC, "Generic error" }, \ + { MBG_ERR_TIMEOUT, "Timeout" }, \ + { MBG_ERR_FW_ID, "Invalid firmware ID" }, \ + { MBG_ERR_NBYTES, "Unexpected number of data bytes for this API" }, \ + { MBG_ERR_INV_TIME, "Invalid time passed to device" }, \ + { MBG_ERR_FIFO, "FIFO unexpectedly empty" }, \ + { MBG_ERR_NOT_READY, "Device not ready" }, \ + { MBG_ERR_INV_TYPE, "Unsupported data type" }, \ + { MBG_ERR_NO_MEM, "Memory allocation error" }, \ + { MBG_ERR_CLAIM_RSRC, "Faild to claim resources" }, \ + { MBG_ERR_DEV_NOT_SUPP, "Device not supported" }, \ + { MBG_ERR_INV_DEV_REQUEST, "Request not supported" }, \ + { MBG_ERR_NOT_SUPP_BY_DEV, "Not supported by device" }, \ + { MBG_ERR_USB_ACCESS, "USB access failed" }, \ + { MBG_ERR_CYCLIC_TIMEOUT, "Cyclic message timeout" }, \ + { MBG_ERR_NOT_SUPP_ON_OS, "Not supported by OS" }, \ + { MBG_ERR_LIB_NOT_COMPATIBLE, "Shared lib not compatible" }, \ + { MBG_ERR_N_COM_EXCEEDS_SUPP, "Num. COM ports exceeds supported" }, \ + { MBG_ERR_N_STR_EXCEEDS_SUPP, "Num. string formats exceeds supported" }, \ + { MBG_ERR_IRQ_UNSAFE, "Unsafe IRQ support" }, \ + { MBG_ERR_N_POUT_EXCEEDS_SUPP, "Num prog. outputs exceeds supported" }, \ + { MBG_ERR_INV_INTNO, "Invalid interrupt number" }, \ + { MBG_ERR_NO_DRIVER, "Driver not found" }, \ + { MBG_ERR_DRV_VERSION, "Driver too old" }, \ + { MBG_ERR_COPY_TO_USER, "Error copying to user space" }, \ + { MBG_ERR_COPY_FROM_USER, "Error copying from user space" }, \ + { MBG_ERR_N_UC_MSTR_EXCEEDS_SUPP, "Num. PTP Unicast masters exceeds supported" }, \ + { MBG_ERR_N_GNSS_EXCEEDS_SUPP, "Num. GNSS systems exceeds supported" }, \ + { MBG_ERR_N_GPIO_EXCEEDS_SUPP, "Num. GPIO ports exceeds supported" }, \ + { MBG_ERR_N_XMR_EXCEEDS_SUPP, "Num. XMR sources exceeds supported" }, \ + { MBG_ERR_UNSPEC, "Unspecified error" }, \ + { MBG_ERR_HDR_CSUM, "Header checksum error" }, \ + { MBG_ERR_DATA_CSUM, "Data checksum error" }, \ + { MBG_ERR_RCVD_NACK, "Received NACK message" }, \ + { MBG_ERR_RCVD_NO_ACK, "Didn't receive ACK message" }, \ + { MBG_ERR_CONN_TYPE, "Invalid I/O connection type" }, \ + { MBG_ERR_BYTES_WRITTEN, "Failed to write all bytes" }, \ + { MBG_ERR_AUTH, "Authentication failed" }, \ + { MBG_ERR_SOCK_INIT, "Failed to initialize socket" }, \ + { MBG_ERR_INV_SOCK_FD, "Invalid socket descriptor" }, \ + { MBG_ERR_NOT_A_SOCKET, "Not a socket descriptor" }, \ + { MBG_ERR_NBLOCK_WAIT_SLCT, "Select timed out waiting for port ready" }, \ + { MBG_ERR_NBLOCK_WAIT_WR_FD, "Write file descriptor not ready after waiting for port ready" }, \ + { MBG_ERR_IO, "Generic I/O error" }, \ + { MBG_ERR_INV_PARM, "Invalid parameter" }, \ + { MBG_ERR_NO_DEV, "Specified device not found" }, \ + { MBG_ERR_NOT_FOUND, "Specified item not found" }, \ + { MBG_ERR_OVERFLOW, "Buffer overflow" }, \ + { MBG_ERR_PIPE, "Pipe error" }, \ + { MBG_ERR_INTR, "Interrupted system call" }, \ + { MBG_ERR_ACCESS, "Access denied" }, \ + { MBG_ERR_PERM, "Operation not permitted" }, \ + { MBG_ERR_BUSY, "Device busy" }, \ + { MBG_ERR_INV_HANDLE, "Invalid handle" }, \ + { MBG_ERR_XBP_CASC_LVL, "Too many XBP cascading levels" }, \ + { MBG_ERR_ENCRYPT, "Encryption failed" }, \ + { MBG_ERR_DECRYPT, "Decryption failed" }, \ + { MBG_ERR_DISCONN, "Connection closed by remote site/host" }, \ + { MBG_ERR_INV_CFG, "Invalid/inconsistent configuration read from device" }, \ + { MBG_ERR_RANGE, "Input parameter was out of range" }, \ + { MBG_ERR_INV_TLV_ANN_BYTES, "TLV num of transferred bytes differs from num of announced bytes" }, \ + { MBG_ERR_INV_TLV_SIZE, "MBG_ERR_INV_TLV_SIZE" }, /* ### TODO */ \ + { MBG_ERR_INV_TLV_UID, "MBG_ERR_INV_TLV_UID" }, /* ### TODO */ \ + { MBG_ERR_EXIST, "File exists" }, \ + { MBG_ERR_DATA_SIZE, "Received data size mismatch" }, \ + { MBG_ERR_NO_ENTITY, "No such file or directory" }, \ + { MBG_ERR_ALREADY_ALLOC, "Memory already allocated" }, \ + { MBG_ERR_HOST_NOT_FOUND, "Host not found" }, \ + { MBG_ERR_CONN_RESET, "Connection reset by peer" }, \ + { MBG_ERR_DATA_FMT, "Invalid data format" }, \ + { MBG_ERR_NO_SPACE, "Insufficient disk space" }, \ + { MBG_ERR_NOT_CONFIGURED, "Configuration is not active and/or configured" }, \ + { MBG_ERR_INV_IDX, "Invalid or unsupported index value used"}, \ + { MBG_ERR_PARM_FMT, "Parameter string format error" }, \ + { 0, NULL } /* end of table */ \ +} - #define _mbg_err_to_os( _c ) \ - ( ( _c == MBG_SUCCESS ) ? STATUS_SUCCESS : ( abs( _c ) | 0xE0000000 ) ) -#endif -// If no specific conversion has been defined -// then use the original codes. -#if !defined( _mbg_err_to_os ) - #define _mbg_err_to_os( _c ) ( _c ) -#endif +#if defined( __mbg_inline ) +static __mbg_inline +/** + * @brief Check if the code returned by a function indicates an error + * + * @param[in] rc One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_rc_is_success + * @see @ref MBG_RETURN_CODES + */ +bool mbg_rc_is_error( int rc ) +{ + // Meinberg error codes are all < 0. + return rc < MBG_SUCCESS; +} // mbg_rc_is_error -/* function prototypes: */ -#ifdef __cplusplus -extern "C" { +static __mbg_inline +/** + * @brief Check if the code returned by a function indicates success + * + * @param[in] rc One of the @ref MBG_RETURN_CODES + * + * @see ::mbg_rc_is_error + * @see @ref MBG_RETURN_CODES + */ +bool mbg_rc_is_success( int rc ) +{ + // There are functions which don't only return MBG_SUCCESS + // on success but some arbitrary positive number, e.g. the + // number of bytes sent. So success just means "not an error". + return !mbg_rc_is_error( rc ); + +} // mbg_rc_is_success + +#else + + #define mbg_rc_is_error( _rc ) ( (_rc) < MBG_SUCCESS ) + #define mbg_rc_is_success( _rc ) ( !mbg_rc_is_error( _rc ) ) + #endif + + +static __mbg_inline /*HDR*/ +/** + * @brief Convert one of the @ref MBG_ERROR_CODES to an OS-specific format + * + * @param[in] err_no One of the @ref MBG_ERROR_CODES. + * + * @see @ref MBG_ERROR_CODES + */ +int mbg_errno_to_os( int err_no ) +{ + #if defined( MBG_TGT_WIN32 ) + + // Windows uses specially encoded numbers + return ( -err_no | 0xE0000000L ); + + #elif defined( MBG_TGT_BSD ) + + return -err_no; + + #else + + return err_no; + + #endif + +} // mbg_errno_to_os + + + +static __mbg_inline /*HDR*/ +/** + * @brief Convert one of the @ref MBG_RETURN_CODES to an OS-specific format + * + * @param[in] rc One of the @ref MBG_RETURN_CODES. + * + * @see @ref MBG_RETURN_CODES + */ +int mbg_ret_val_to_os( int rc ) +{ + #if defined( MBG_TGT_WIN32 ) + + return mbg_rc_is_error( rc ) ? mbg_errno_to_os( rc ) : STATUS_SUCCESS; + + #elif defined( MBG_TGT_BSD ) + + return mbg_rc_is_error( rc ) ? mbg_errno_to_os( rc ) : MBG_SUCCESS; + + #else + + return rc; + + #endif + +} // mbg_ret_val_to_os + + + /* ----- function prototypes begin ----- */ /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ -/* (no header definitions found) */ + /** + * @brief Return an error string associated with the @ref MBG_ERROR_CODES + * + * @param[in] mbg_errno One of the @ref MBG_ERROR_CODES + * + * @return A constant string describing the error, or NULL for unknown error codes + */ + const char *mbg_strerror( int mbg_errno ) ; + + /** + * @brief Check if a value is an error code and print an associated error message + * + * @param[in] rc A positive number including ::MBG_SUCCESS, or one of the @ref MBG_ERROR_CODES + * @param[in] what A string indicated what failed + * + * @return true if rc represented an error code, and a message has been printed, else false + */ + bool mbg_cond_err_msg( int rc, const char *what ) ; + + /** + * @brief Check if a value is an general or a "not supported" error code and print an associated message + * + * If rc contains an error code then an error message is printed, and true is returned. + * + * If the optional parameter string info2 is not NULL then it should contain + * the name of a feature which has been tested before. In this case, if the error + * code is the specific error ::MBG_ERR_NOT_SUPP_BY_DEV then a "not supported" message + * is printed using info2. + * + * If info2 is NULL, or the error code is not ::MBG_ERR_NOT_SUPP_BY_DEV then the standard + * error message is printed anyway. + * + * @param[in] rc A positive number including ::MBG_SUCCESS, or one of the @ref MBG_ERROR_CODES + * @param[in] what A string indicated what failed + * @param[in] info An optional informational string telling what is not supported (may be NULL). + * + * @return true if rc represented an error code, and a message has been printed, else false + */ + bool mbg_cond_err_msg_info( int rc, const char *what, const char *info ) ; + + /** + * @brief Translate an error code from the Labwindows/CVI RS-232 library to one of the @ref MBG_ERROR_CODES + * + * @param[in] cvi_rc An error code returned by a CVI RS-232 library function + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + * + * @see http://zone.ni.com/reference/en-XX/help/370051V-01/cvi/libref/cvirs232_error_conditions/ + */ + int mbg_cvi_rs232_error_to_mbg( int cvi_rc, const char *info ) ; + + /** + * @brief Translate a Windows non-socket API error code to one of the @ref MBG_ERROR_CODES + * + * @param[in] last_err A Windows non-socket API error code as returned by GetLastError() + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_win32_last_err_to_mbg( DWORD last_err, const char *info ) ; + + /** + * @brief Translate a Windows socket API error code to one of the @ref MBG_ERROR_CODES + * + * @param[in] wsa_err A Windows socket API error code as returned by WSAGetLastError() + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_win32_wsa_err_to_mbg( DWORD wsa_err, const char *info ) ; + + /** + * @brief Translate a POSIX errno error code to one of the @ref MBG_ERROR_CODES + * + * @param[in] posix_errno A POSIX error code as usually defined in errno.h + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_posix_errno_to_mbg( int posix_errno, const char *info ) ; + + /** + * @brief Translate a POSIX h_errno error code to one of the @ref MBG_ERROR_CODES + * + * This function is specific to translate error codes returned by + * gethostbyname() and gethostbyaddr(). In case of error these functions + * don't set errno but h_errno to a specific value. + * + * The functions gethostbyname() and gethostbyaddr() are obsolete, + * and getaddressinfo() should be used preferably. + * + * @param[in] posix_h_errno An error code as usually defined in netdb.h + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_posix_h_errno_to_mbg( int posix_h_errno, const char *info ) ; + + /** + * @brief Get and translate last error after non-socket function call + * + * Retrieve the "last error" code after a non-socket function has been called + * and translate to one of the @ref MBG_ERROR_CODES. + * + * On POSIX systems the "last error" code is always stored in errno, but + * e.g. under Windows the "last error" code after a socket function + * has to be retrieved by calling WSAGetLastError(), whereas the "last error" + * code from non-socket POSIX-like functions has to be retrieved + * by calling GetLastError(). + * + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_get_last_error( const char *info ) ; + + /** + * @brief Get and translate last error after socket function call + * + * Retrieve the "last error" code after a socket function has been called + * and translate to one of the @ref MBG_ERROR_CODES. + * + * On POSIX systems the "last error" code is always stored in errno, but + * e.g. under Windows the "last error" code after a socket function + * has to be retrieved by calling WSAGetLastError, whereas the "last error" + * code from non-socket POSIX-like functions is stored in errno as usual. + * + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_get_last_socket_error( const char *info ) ; + + /** + * @brief Retrieve and convert last error after gethostbyname() + * + * This function is specific to retrieve and translate error codes + * returned by gethostbyname() and gethostbyaddr(). In case of error + * these functions don't set errno but h_errno on POSIX systems, but + * under Windows the error code can be retrieved by WSAGetLastError() + * as usual. + * + * The functions gethostbyname() and gethostbyaddr() are obsolete, + * and getaddressinfo() should be used preferably. + * + * @param[in] info An optional informational text string, or NULL + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_get_gethostbyname_error( const char *info ) ; + + /** + * @brief Retrieve and convert last zlib internal error code + * + * @param[in] zlib_error zlib internal error code + * @param[in] info An optional informational text string, or NULL + * @param[in] msg An optional zlib specific error msg, or NULL. + * Struct z_stream contains member msg. + * + * @return One of the @ref MBG_ERROR_CODES + */ + int mbg_zlib_error_to_mbg( int zlib_error, const char *info, const char *msg ) ; + /* ----- function prototypes end ----- */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbggenio.h b/src/external/bsd/meinberg/dist/mbglib/common/mbggenio.h index 0d6c1ef..4487130 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbggenio.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbggenio.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbggenio.h 1.5.1.3 2011/02/09 17:08:30 martin TRASH $ + * $Id: mbggenio.h 1.6 2012/10/02 18:43:36 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,11 +10,10 @@ * * ----------------------------------------------------------------------- * $Log: mbggenio.h $ - * Revision 1.5.1.3 2011/02/09 17:08:30 martin + * Revision 1.6 2012/10/02 18:43:36 martin + * Fixed includes for NetBSD. * Specify I/O range number when calling port I/O macros * so they can be used for different ranges under BSD. - * Revision 1.5.1.2 2011/02/01 12:12:18 martin - * Revision 1.5.1.1 2011/01/31 17:29:26 martin * Account for modified resource handling under *BSD. * Revision 1.5 2008/12/05 13:27:33 martin * Generally put macro arguments in brackets for evaluation @@ -72,10 +71,12 @@ extern "C" { #endif #elif defined( MBG_TGT_BSD ) - + #include <sys/param.h> #include <sys/types.h> #include <sys/bus.h> - #include <machine/bus.h> + #if !defined(__NetBSD_Version__) || __NetBSD_Version__ < 599005500 + #include <machine/bus.h> + #endif #define _mbg_inp8( _d, _i, _p ) ( (uint8_t) bus_space_read_1( ( (_d)->rsrc_info.port[_i].bsd.bst ), \ ( (_d)->rsrc_info.port[_i].bsd.bsh ), (_p) ) ) diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbggeo.h b/src/external/bsd/meinberg/dist/mbglib/common/mbggeo.h index 76cf179..ff3165d 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbggeo.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbggeo.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbggeo.h 1.11 2011/06/22 10:18:10 martin TRASH $ + * $Id: mbggeo.h 1.14 2017/05/10 15:21:40 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,7 +10,7 @@ * * Terms used: * - * WGS84 world geodetic system of 1984 + * WGS84 World Geodetic System of 1984 * * XYZ WGS84 earth centered, earth fixed (ECEF) kartesian * coordinates @@ -22,6 +22,13 @@ * * ----------------------------------------------------------------------- * $Log: mbggeo.h $ + * Revision 1.14 2017/05/10 15:21:40 martin + * Tiny cleanup. + * Revision 1.13 2017/01/27 08:57:58 martin + * Fixed macro syntax. + * Revision 1.12 2016/10/31 16:50:56 martin + * Fixed a typo. + * Updated doxygen comments. * Revision 1.11 2011/06/22 10:18:10 martin * Cleaned up handling of pragma pack(). * Revision 1.10 2008/09/03 14:54:28 martin @@ -34,7 +41,7 @@ * Revision 1.7 2003/02/14 13:23:04Z martin * Omit inclusion of mystd.h. * Revision 1.6 2003/01/13 15:17:15 martin - * Structures were defined with default alignment which + * Structures were defined with default alignment which * could result in different data sizes on different platforms. * Revision 1.5 2002/12/18 14:46:41Z martin * Removed variable USER_POS meinberg. @@ -69,106 +76,136 @@ #define _USING_BYTE_ALIGNMENT #endif +#ifdef __cplusplus +extern "C" { +#endif + /** - Geographic longitude or latitude in [degrees, minutes, seconds] - longitude East latitude North and positve, South or West angles negative + * @brief Geographic longitude or latitude in [degrees, minutes, seconds] + * + * Longitude East and latitude North are positive angles, South or West + * angles are negative. */ typedef struct { - uint16_t prefix; /**< 'N', 'E', 'S' or 'W' */ - uint16_t deg; /**< [0...90 (lat) or 0...180 (lon)] */ - uint16_t min; /**< [0...59] */ - double sec; /**< [0...59.999] */ + uint16_t prefix; ///< 'N', 'E', 'S' or 'W' + uint16_t deg; ///< [0...90 (lat) or 0...180 (lon)] + uint16_t min; ///< [0...59] + double sec; ///< [0...59.99999...] + } DMS; -// The corresponding macro _mbg_swab_dms() is defined in gpsdefs.h. #define _mbg_swab_dms( _p ) \ +do \ { \ _mbg_swab16( &(_p)->prefix ); \ _mbg_swab16( &(_p)->deg ); \ _mbg_swab16( &(_p)->min ); \ _mbg_swab_double( &(_p)->sec ); \ -} +} while ( 0 ) +/** + * @brief A geographic position represented in different formats + */ typedef struct { - XYZ xyz; /**< always WGS84 ECEF coordinates */ - LLA lla; /**< depending on the ellipsoid used for reference */ - DMS longitude; /**< longitude in degrees, minutes, seconds */ - DMS latitude; /**< latitude in degrees, minutes, seconds */ - int16_t ellipsoid; /**< ellipsoid used for reference */ + XYZ xyz; ///< Always WGS84 ECEF coordinates + LLA lla; ///< Longitude, latitude and altitude, depending on the ellipsoid used for reference + DMS longitude; ///< Longitude broken down to degrees, minutes, seconds + DMS latitude; ///< Latitude broken down to degrees, minutes, seconds + int16_t ellipsoid; ///< Ellipsoid used for reference, see ::ELLIPSOIDS + } POS; #define _mbg_swab_pos( _p ) \ +do \ { \ _mbg_swab_xyz( (_p)->xyz ); \ _mbg_swab_lla( (_p)->lla ); \ _mbg_swab_dms( &(_p)->longitude ); \ _mbg_swab_dms( &(_p)->latitude ); \ _mbg_swab16( &(_p)->ellipsoid ); \ -} +} while ( 0 ) +/** + * @brief A structure used internally to compute a geographic position + * + * Also contains intermediate results useful for the computation. + */ typedef struct { - CSUM csum; /* checksum of the remaining bytes */ - int16_t valid; /* flag data are valid */ + CSUM csum; ///< Checksum of the remaining bytes + int16_t valid; ///< Indicator if data is valid - char name[40]; - POS pos; /* the position in WGS84 ECEF coords and LLA */ + char name[40]; ///< Informational string + POS pos; ///< The position in WGS84 ECEF coords and ::LLA double det; -/* The components below hold the results of intermediate terms */ -/* computed in complete_user_pos(). */ + // The components below hold the results of intermediate terms + // computed in complete_user_pos(). -/* The sin.., cos.., nt.. and ut.. variables are used to compute the */ -/* enu_dcos[] parameters of a SV structure in xyz_to_ead(). */ + // The sin.., cos.., nt.. and ut.. variables are used to compute the + // enu_dcos[] parameters of a SV structure in xyz_to_ead(). -/* The e_radius.. variables are used to compute the latitude, longitude */ -/* and altitude from ECEF coordinates in lla_to_xyz(). */ + // The e_radius.. variables are used to compute the latitude, longitude + // and altitude from ECEF coordinates in lla_to_xyz(). - double sin_lat; /* sin( latitude ) */ - double cos_lat; /* cos( latitude ) */ - double sin_lon; /* sin( longitude ) */ - double cos_lon; /* cos( longitude ) */ + double sin_lat; ///< sin( latitude ) + double cos_lat; ///< cos( latitude ) + double sin_lon; ///< sin( longitude ) + double cos_lon; ///< cos( longitude ) - double nt1; /* -sin_lat * cos_lon */ - double nt2; /* -sin_lat * sin_lon */ - double utx; /* cos_lat * cos_lon */ - double uty; /* cos_lat * sin_lon */ + double nt1; ///< -sin_lat * cos_lon + double nt2; ///< -sin_lat * sin_lon + double utx; ///< cos_lat * cos_lon + double uty; ///< cos_lat * sin_lon - double e_radius; /* N */ - double e_radius_alt; /* N + h */ + double e_radius; ///< N + double e_radius_alt; ///< N + h } USER_POS; +/** + * @brief Characteristics of a geographic reference ellipsoid + */ typedef struct { - CSUM csum; /* checksum of the remaining bytes */ - int16_t valid; /* flag data are valid */ + CSUM csum; ///< Checksum of the remaining bytes + int16_t valid; ///< Indicator if data is valid char name[40]; - XYZ dxyz; /* offset from the WGS84 ECEF coords */ - double a; /* semi major axis */ - double rcp_f; /* reciproke of flatness */ + XYZ dxyz; ///< Offset from the WGS84 ECEF coords + double a; ///< Semi major axis + double rcp_f; ///< Reciproke of flatness + + // The variables below are computed in the init_mbggeo() function: -/* the variables below will be computed in the init_mbggeo() function: */ + double f; ///< Flatness + double b; ///< Semi minor axis + double sqr_e; ///< Square of numerical eccentricity - double f; /* flatness */ - double b; /* semi minor axis */ - double sqr_e; /* square of numerical eccentricity */ } ELLIPSOID; -enum { WGS84, BESSEL, N_ELLIPSOIDS }; +/** + * @brief An enumeration of known ellipsoids + */ +enum ELLIPSOIDS +{ + WGS84, + BESSEL, + N_ELLIPSOIDS +}; + _ext ELLIPSOID ellipsoid[N_ELLIPSOIDS] #ifdef _DO_INIT @@ -191,15 +228,15 @@ _ext ELLIPSOID ellipsoid[N_ELLIPSOIDS] ; -/* WGS84 constants used */ +// WGS84 constants used -_ext double OMEGADOTe /* earth's rotation rate [rad/sec] */ +_ext double OMEGADOTe // Earth's rotation rate [rad/sec] #ifdef _DO_INIT = 7.2921151467e-5 #endif ; -_ext double mue /* earth's gravitational constant [m^3/sec^2] */ +_ext double mue // Earth's gravitational constant [m^3/sec^2] #ifdef _DO_INIT = 3.986005e14 #endif @@ -249,18 +286,12 @@ _ext double d2r ; -/* variables for simplifying computations */ +// Variables for simplifying computations _ext double gps_two_pi; -_ext double sqrt_mue; /* sqrt( mue ) */ - - +_ext double sqrt_mue; // sqrt( mue ) -/* function prototypes: */ -#ifdef __cplusplus -extern "C" { -#endif /* ----- function prototypes begin ----- */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgioctl.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgioctl.h index 2dfb6a0..54732c1 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbgioctl.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgioctl.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgioctl.h 1.24.1.10 2011/07/20 15:49:00 martin TRASH $ + * $Id: mbgioctl.h 1.27 2017/07/05 09:37:18 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,22 +10,29 @@ * * ----------------------------------------------------------------------- * $Log: mbgioctl.h $ - * Revision 1.24.1.10 2011/07/20 15:49:00 martin + * Revision 1.27 2017/07/05 09:37:18 martin + * Definitions to support GPIO ports and XMR. + * Support new way to check if specific feature supported. + * Moved some IOCTL-related definitions from pcpsdev.h here. + * Added some doxygen comments. + * Revision 1.26 2013/09/26 08:27:04Z martin + * Support GNSS API. + * Revision 1.25 2012/10/02 18:45:55 martin + * There are some g++ versions which fail to compile source code using + * the macros provided by Linux to define IOCTL codes. If only the API + * functions are called by an application then the IOCTL codes aren't + * required anyway, so we just avoid inclusion of mbgioctl.h. + * However, some IOCTL related definitions are required anyway, so + * they have been moved to pcpsdev.h which is always included. + * Support on-board event logs. + * Support debug status. * Conditionally use older IOCTL request buffer structures. - * Revision 1.24.1.9 2011/07/19 12:31:59 martin - * Relaxed required priority level for generic read functions. - * Revision 1.24.1.8 2011/07/18 10:18:49 martin - * Revision 1.24.1.7 2011/07/15 14:50:11 martin - * Revision 1.24.1.6 2011/07/14 14:54:01 martin * Modified generic IOCTL handling such that for calls requiring variable sizes * a fixed request block containing input and output buffer pointers and sizes is * passed down to the kernel driver. This simplifies implementation under *BSD * and also works for other target systems. - * Revision 1.24.1.5 2011/07/06 11:19:28 martin * Support reading CORR_INFO, and reading/writing TR_DISTANCE. - * Revision 1.24.1.4 2011/06/29 10:52:00 martin * New code IOCTL_DEV_HAS_PZF. - * Revision 1.24.1.3 2011/06/21 15:03:29 martin * Support PTP unicast configuration. * Changed the names of a few IOCTL codes to follow general naming conventions. * Added definitions to support privilege level requirements for IOCTLs. @@ -33,13 +40,9 @@ * Added definitions to set up a table of all known * IOCTL codes and names. * Use MBG_TGT_KERNEL instead of _KDD_. - * Fixed a typo. - * Revision 1.24.1.2 2011/03/22 11:19:46 martin * Use IOTYPE 'Z' under *BSD since this means passthrough on NetBSD. - * Revision 1.24.1.1 2011/02/15 11:21:21 daniel - * Added ioctls to support PTP unicast configuration * Revision 1.24 2009/12/15 15:34:59Z daniel - * Support reading the raw IRIG data bits for firmware versions + * Support reading the raw IRIG data bits for firmware versions * which support this feature. * Revision 1.23 2009/09/29 15:08:41Z martin * Support retrieving time discipline info. @@ -79,23 +82,23 @@ * Added support for programmable pulse outputs. * Revision 1.12 2005/06/02 10:22:05Z martin * Added IOCTL code IOCTL_GET_SYNTH_STATE. - * Added IOCTL codes IOCTL_DEV_HAS_GENERIC_IO, + * Added IOCTL codes IOCTL_DEV_HAS_GENERIC_IO, * IOCTL_PCPS_GENERIC_IO, and IOCTL_GET_SYNTH_STATE. * Revision 1.11 2005/01/14 10:21:11Z martin * Added IOCTLs which query device features. * Revision 1.10 2004/12/09 11:03:36Z martin * Support configuration of on-board frequency synthesizer. * Revision 1.9 2004/11/09 12:49:41Z martin - * Modifications were required in order to be able to configure IRIG + * Modifications were required in order to be able to configure IRIG * settings of cards which provide both IRIG input and output. - * The existing codes have been renamed with .._RX.. and are used to - * configure the IRIG receiver (input). New codes have been defined + * The existing codes have been renamed with .._RX.. and are used to + * configure the IRIG receiver (input). New codes have been defined * used to configure the IRIG transmitter. * Renamed IOCTL_GET_GPS_STAT to IOCTL_GET_GPS_BVAR_STAT. * Use more specific data types than generic types. * Modified IOCTL codes used for hardware debugging. * Revision 1.8 2004/09/06 15:46:04Z martin - * Changed definition of IOCTL codes to support syntax used + * Changed definition of IOCTL codes to support syntax used * with Linux kernel 2.6.x. * Account for renamed symbols. * Revision 1.7 2004/04/07 10:08:11 martin @@ -129,17 +132,57 @@ /* Other headers to be included */ #include <mbg_tgt.h> +#include <mbgerror.h> #include <mbggeo.h> #include <pcpsdev.h> #include <pci_asic.h> -#define USE_DEBUG_PORT defined( MBG_ARCH_X86 ) +#if defined( MBG_TGT_LINUX ) + #include <linux/ioctl.h> +#endif -#if defined( MBG_TGT_LINUX ) +#if defined( MBG_TGT_BSD ) + #include <sys/ioccom.h> +#endif - #include <linux/ioctl.h> + +#if defined( MBG_TGT_WIN32 ) + + #if !defined( MBG_TGT_KERNEL ) + #include <winioctl.h> + #endif + + #if !defined( MBG_TGT_WIN32_NON_PNP ) + #ifdef _MBGIOCTL + #include <initguid.h> // instance the GUID + #else + #include <guiddef.h> // just define the GUID + #endif + #endif + +#endif + + + +/* Start of header body */ + +// We have to use native alignment here! + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined( MBG_ARCH_X86 ) + #define USE_DEBUG_PORT 1 +#else + #define USE_DEBUG_PORT 0 +#endif + + +#if defined( MBG_TGT_LINUX ) // a magic number used to generate IOCTL cmd codes #define IOTYPE 'M' @@ -153,8 +196,6 @@ #elif defined( MBG_TGT_BSD ) - #include <sys/ioccom.h> - // Under NetBSD 'Z' marks passthrough IOCTLs, under FreeBSD the code // does not seem to matter, so we use 'Z' anyway. #define IOTYPE 'Z' @@ -171,19 +212,6 @@ #define _MBG_SUPP_VAR_ACC_SIZE 1 #endif - #if !defined( MBG_TGT_KERNEL ) - #include <windows.h> - #include <winioctl.h> - #endif - - #if !defined( MBG_TGT_WIN32_NON_PNP ) - #ifdef _MBGIOCTL - #include <initguid.h> // instance the GUID - #else - #include <guiddef.h> // just define the GUID - #endif - #endif - #ifdef DEFINE_GUID // don't break compiles of drivers that // include this header but don't want the // GUIDs @@ -221,18 +249,6 @@ #endif -#ifdef _MBGIOCTL - #define _ext - #define _DO_INIT -#else - #define _ext extern -#endif - - -/* Start of header body */ - -// We must use native alignment here! - // The structure below is used by the IOCTL_PCPS_GENERIC_... calls. @@ -242,6 +258,11 @@ #endif #endif +#if defined( MBG_TGT_WIN32 ) + // required for 32bit/64 bit compatibility + #define USE_IOCTL_GENERIC_REQ 0 +#endif + #if !defined( USE_IOCTL_GENERIC_REQ ) #define USE_IOCTL_GENERIC_REQ 1 #endif @@ -249,9 +270,13 @@ #if USE_IOCTL_GENERIC_REQ -// This does not yet work properly under Linux/Sparc where the kernel may be 64 bit -// while user space is 32 bit, which leads to different sizes for pointers and size_t. - +/** + * @brief A structure used to pass generic IOCTL requests to the kernel driver + * + * @note This does not work properly under Linux/Sparc where the kernel + * may be 64 bit while user space is 32 bit, which leads to different sizes + * for pointers, size_t, etc. + */ typedef struct { ulong info; @@ -266,18 +291,36 @@ typedef struct #else -// The structure below is used by the IOCTL_PCPS_GENERIC_... calls. +/** + * @brief Control structure used for generic IOCTL requests + * + * Used by the IOCTL_PCPS_GENERIC_... calls. + * + * @note Is slower, but avoids OS-specific problems occurring + * with IOCTL_GENERIC_REQ. + */ typedef struct { uint32_t info; uint32_t data_size_in; uint32_t data_size_out; + } IOCTL_GENERIC_CTL; + +/** + * @brief Data buffer used for generic IOCTL requests + * + * Used by the IOCTL_PCPS_GENERIC_... calls. + * + * @note Is slower, but avoids OS-specific problems occurring + * with IOCTL_GENERIC_REQ. + */ typedef struct { IOCTL_GENERIC_CTL ctl; uint8_t data[1]; + } IOCTL_GENERIC_BUFFER; #define _MBG_IOG( _t, _n, _s ) _MBG_IO( _t, _n ) @@ -286,6 +329,27 @@ typedef struct +/** + * @brief Request buffer used to query a device feature + */ +typedef struct +{ + uint32_t feat_req_type; ///< See ::DEV_FEAT_REQ_TYPES + uint32_t feat_num; ///< Number and range depending on ::IOCTL_DEV_FEAT_REQ::feat_req_type value + +} IOCTL_DEV_FEAT_REQ; + + + +/** + * @defgroup group_ioctl_codes IOCTL codes used by Meinberg drivers + * + * @see ::IOCTL_CODES_TABLE + * + * @anchor IOCTL_CODES + * + * @{ */ + // read general driver info, device info, and status port #define IOCTL_GET_PCPS_DRVR_INFO _MBG_IOR( IOTYPE, 0x00, PCPS_DRVR_INFO ) #define IOCTL_GET_PCPS_DEV _MBG_IOR( IOTYPE, 0x01, PCPS_DEV ) @@ -480,6 +544,35 @@ typedef struct #define IOCTL_GET_TR_DISTANCE _MBG_IOR( IOTYPE, 0x8C, TR_DISTANCE ) #define IOCTL_SET_TR_DISTANCE _MBG_IOW( IOTYPE, 0x8D, TR_DISTANCE ) +#define IOCTL_DEV_HAS_DEBUG_STATUS _MBG_IOR( IOTYPE, 0x8E, int ) +#define IOCTL_GET_DEBUG_STATUS _MBG_IOR( IOTYPE, 0x8F, MBG_DEBUG_STATUS ) + +#define IOCTL_DEV_HAS_EVT_LOG _MBG_IOR( IOTYPE, 0x90, int ) +#define IOCTL_CLR_EVT_LOG _MBG_IO( IOTYPE, 0x91 ) +#define IOCTL_GET_NUM_EVT_LOG_ENTRIES _MBG_IOR( IOTYPE, 0x92, MBG_NUM_EVT_LOG_ENTRIES ) +#define IOCTL_GET_FIRST_EVT_LOG_ENTRY _MBG_IOR( IOTYPE, 0x93, MBG_EVT_LOG_ENTRY ) +#define IOCTL_GET_NEXT_EVT_LOG_ENTRY _MBG_IOR( IOTYPE, 0x94, MBG_EVT_LOG_ENTRY ) + +#define IOCTL_DEV_IS_GNSS _MBG_IOR( IOTYPE, 0x95, int ) +#define IOCTL_GET_GNSS_MODE_INFO _MBG_IOR( IOTYPE, 0x96, MBG_GNSS_MODE_INFO ) +#define IOCTL_SET_GNSS_MODE_SETTINGS _MBG_IOW( IOTYPE, 0x97, MBG_GNSS_MODE_SETTINGS ) +#define IOCTL_GET_ALL_GNSS_SAT_INFO _MBG_IOG( IOTYPE, 0x98, IOCTL_GENERIC_REQ ) // variable size + +#define IOCTL_DEV_HAS_GPIO _MBG_IOR( IOTYPE, 0x99, int ) +#define IOCTL_GET_GPIO_CFG_LIMITS _MBG_IOR( IOTYPE, 0x9A, MBG_GPIO_CFG_LIMITS ) +#define IOCTL_GET_ALL_GPIO_INFO _MBG_IOG( IOTYPE, 0x9B, IOCTL_GENERIC_REQ ) // variable size +#define IOCTL_SET_GPIO_SETTINGS_IDX _MBG_IOW( IOTYPE, 0x9C, MBG_GPIO_SETTINGS_IDX ) + +#define IOCTL_DEV_HAS_XMR _MBG_IOR( IOTYPE, 0x9D, int ) +#define IOCTL_GET_XMR_INSTANCES _MBG_IOR( IOTYPE, 0x9E, XMULTI_REF_INSTANCES ) +#define IOCTL_GET_ALL_XMR_INFO _MBG_IOG( IOTYPE, 0x9F, IOCTL_GENERIC_REQ ) // variable size +#define IOCTL_SET_XMR_SETTINGS_IDX _MBG_IOW( IOTYPE, 0xA0, XMULTI_REF_SETTINGS_IDX ) +#define IOCTL_GET_ALL_XMR_STATUS _MBG_IOG( IOTYPE, 0xA1, IOCTL_GENERIC_REQ ) // variable size +#define IOCTL_GET_XMR_HOLDOVER_STATUS _MBG_IOR( IOTYPE, 0xA2, XMR_HOLDOVER_STATUS ) + +#define IOCTL_GET_ALL_GPIO_STATUS _MBG_IOG( IOTYPE, 0xA3, IOCTL_GENERIC_REQ ) // variable size +#define IOCTL_CHK_DEV_FEAT _MBG_IOW( IOTYPE, 0xA4, IOCTL_DEV_FEAT_REQ ) + // The codes below are subject to changes without notice. They may be supported // by some kernel drivers, but usage is restricted to Meinberg software development. // Unrestricted usage may cause system malfunction !! @@ -489,154 +582,182 @@ typedef struct #define IOCTL_MBG_DBG_CLR_BIT _MBG_IOW( IOTYPE, 0xF3, uint8_t ) #define IOCTL_MBG_DBG_CLR_ALL _MBG_IO( IOTYPE, 0xF4 ) +/** @} defgroup group_ioctl_codes */ + /** * @brief An initializer for a table of IOCTL codes and associated names. * - * This can e.g. be assigned to an array of MBG_CODE_NAME_TABLE_ENTRY elements + * This can e.g. initialize an array of ::MBG_CODE_NAME_TABLE_ENTRY elements * and may be helpful when debugging. + * + * @see @ref IOCTL_CODES */ -#define MBG_IOCTL_CODE_TABLE \ -{ \ - { IOCTL_GET_PCPS_DRVR_INFO, "IOCTL_GET_PCPS_DRVR_INFO" }, \ - { IOCTL_GET_PCPS_DEV, "IOCTL_GET_PCPS_DEV" }, \ - { IOCTL_GET_PCPS_STATUS_PORT, "IOCTL_GET_PCPS_STATUS_PORT" }, \ - { IOCTL_PCPS_GENERIC_READ, "IOCTL_PCPS_GENERIC_READ" }, \ - { IOCTL_PCPS_GENERIC_WRITE, "IOCTL_PCPS_GENERIC_WRITE" }, \ - { IOCTL_PCPS_GENERIC_READ_GPS, "IOCTL_PCPS_GENERIC_READ_GPS" }, \ - { IOCTL_PCPS_GENERIC_WRITE_GPS, "IOCTL_PCPS_GENERIC_WRITE_GPS" }, \ - { IOCTL_GET_PCPS_TIME, "IOCTL_GET_PCPS_TIME" }, \ - { IOCTL_SET_PCPS_TIME, "IOCTL_SET_PCPS_TIME" }, \ - { IOCTL_GET_PCPS_SYNC_TIME, "IOCTL_GET_PCPS_SYNC_TIME" }, \ - { IOCTL_GET_PCPS_TIME_SEC_CHANGE, "IOCTL_GET_PCPS_TIME_SEC_CHANGE" }, \ - { IOCTL_GET_PCPS_HR_TIME, "IOCTL_GET_PCPS_HR_TIME" }, \ - { IOCTL_SET_PCPS_EVENT_TIME, "IOCTL_SET_PCPS_EVENT_TIME" }, \ - { IOCTL_GET_PCPS_SERIAL, "IOCTL_GET_PCPS_SERIAL" }, \ - { IOCTL_SET_PCPS_SERIAL, "IOCTL_SET_PCPS_SERIAL" }, \ - { IOCTL_GET_PCPS_TZCODE, "IOCTL_GET_PCPS_TZCODE" }, \ - { IOCTL_SET_PCPS_TZCODE, "IOCTL_SET_PCPS_TZCODE" }, \ - { IOCTL_GET_PCPS_TZDL, "IOCTL_GET_PCPS_TZDL" }, \ - { IOCTL_SET_PCPS_TZDL, "IOCTL_SET_PCPS_TZDL" }, \ - { IOCTL_GET_REF_OFFS, "IOCTL_GET_REF_OFFS" }, \ - { IOCTL_SET_REF_OFFS, "IOCTL_SET_REF_OFFS" }, \ - { IOCTL_GET_MBG_OPT_INFO, "IOCTL_GET_MBG_OPT_INFO" }, \ - { IOCTL_SET_MBG_OPT_SETTINGS, "IOCTL_SET_MBG_OPT_SETTINGS" }, \ - { IOCTL_GET_PCPS_IRIG_RX_INFO, "IOCTL_GET_PCPS_IRIG_RX_INFO" }, \ - { IOCTL_SET_PCPS_IRIG_RX_SETTINGS, "IOCTL_SET_PCPS_IRIG_RX_SETTINGS" }, \ - { IOCTL_PCPS_CLR_UCAP_BUFF, "IOCTL_PCPS_CLR_UCAP_BUFF" }, \ - { IOCTL_GET_PCPS_UCAP_ENTRIES, "IOCTL_GET_PCPS_UCAP_ENTRIES" }, \ - { IOCTL_GET_PCPS_UCAP_EVENT, "IOCTL_GET_PCPS_UCAP_EVENT" }, \ - { IOCTL_GET_GPS_TZDL, "IOCTL_GET_GPS_TZDL" }, \ - { IOCTL_SET_GPS_TZDL, "IOCTL_SET_GPS_TZDL" }, \ - { IOCTL_GET_GPS_SW_REV, "IOCTL_GET_GPS_SW_REV" }, \ - { IOCTL_GET_GPS_BVAR_STAT, "IOCTL_GET_GPS_BVAR_STAT" }, \ - { IOCTL_GET_GPS_TIME, "IOCTL_GET_GPS_TIME" }, \ - { IOCTL_SET_GPS_TIME, "IOCTL_SET_GPS_TIME" }, \ - { IOCTL_GET_GPS_PORT_PARM, "IOCTL_GET_GPS_PORT_PARM" }, \ - { IOCTL_SET_GPS_PORT_PARM, "IOCTL_SET_GPS_PORT_PARM" }, \ - { IOCTL_GET_GPS_ANT_INFO, "IOCTL_GET_GPS_ANT_INFO" }, \ - { IOCTL_GET_GPS_UCAP, "IOCTL_GET_GPS_UCAP" }, \ - { IOCTL_GET_GPS_ENABLE_FLAGS, "IOCTL_GET_GPS_ENABLE_FLAGS" }, \ - { IOCTL_SET_GPS_ENABLE_FLAGS, "IOCTL_SET_GPS_ENABLE_FLAGS" }, \ - { IOCTL_GET_GPS_STAT_INFO, "IOCTL_GET_GPS_STAT_INFO" }, \ - { IOCTL_SET_GPS_CMD, "IOCTL_SET_GPS_CMD" }, \ - { IOCTL_GET_GPS_IDENT, "IOCTL_GET_GPS_IDENT" }, \ - { IOCTL_GET_GPS_POS, "IOCTL_GET_GPS_POS" }, \ - { IOCTL_SET_GPS_POS_XYZ, "IOCTL_SET_GPS_POS_XYZ" }, \ - { IOCTL_SET_GPS_POS_LLA, "IOCTL_SET_GPS_POS_LLA" }, \ - { IOCTL_GET_GPS_ANT_CABLE_LEN, "IOCTL_GET_GPS_ANT_CABLE_LEN" }, \ - { IOCTL_SET_GPS_ANT_CABLE_LEN, "IOCTL_SET_GPS_ANT_CABLE_LEN" }, \ - { IOCTL_GET_GPS_RECEIVER_INFO, "IOCTL_GET_GPS_RECEIVER_INFO" }, \ - { IOCTL_GET_GPS_ALL_STR_TYPE_INFO, "IOCTL_GET_GPS_ALL_STR_TYPE_INFO" }, \ - { IOCTL_GET_GPS_ALL_PORT_INFO, "IOCTL_GET_GPS_ALL_PORT_INFO" }, \ - { IOCTL_SET_GPS_PORT_SETTINGS_IDX, "IOCTL_SET_GPS_PORT_SETTINGS_IDX" }, \ - { IOCTL_GET_PCI_ASIC_VERSION, "IOCTL_GET_PCI_ASIC_VERSION" }, \ - { IOCTL_GET_PCPS_TIME_CYCLES, "IOCTL_GET_PCPS_TIME_CYCLES" }, \ - { IOCTL_GET_PCPS_HR_TIME_CYCLES, "IOCTL_GET_PCPS_HR_TIME_CYCLES" }, \ - { IOCTL_GET_PCPS_IRIG_TX_INFO, "IOCTL_GET_PCPS_IRIG_TX_INFO" }, \ - { IOCTL_SET_PCPS_IRIG_TX_SETTINGS, "IOCTL_SET_PCPS_IRIG_TX_SETTINGS" }, \ - { IOCTL_GET_SYNTH, "IOCTL_GET_SYNTH" }, \ - { IOCTL_SET_SYNTH, "IOCTL_SET_SYNTH" }, \ - { IOCTL_DEV_IS_GPS, "IOCTL_DEV_IS_GPS" }, \ - { IOCTL_DEV_IS_DCF, "IOCTL_DEV_IS_DCF" }, \ - { IOCTL_DEV_IS_IRIG_RX, "IOCTL_DEV_IS_IRIG_RX" }, \ - { IOCTL_DEV_HAS_HR_TIME, "IOCTL_DEV_HAS_HR_TIME" }, \ - { IOCTL_DEV_HAS_CAB_LEN, "IOCTL_DEV_HAS_CAB_LEN" }, \ - { IOCTL_DEV_HAS_TZDL, "IOCTL_DEV_HAS_TZDL" }, \ - { IOCTL_DEV_HAS_PCPS_TZDL, "IOCTL_DEV_HAS_PCPS_TZDL" }, \ - { IOCTL_DEV_HAS_TZCODE, "IOCTL_DEV_HAS_TZCODE" }, \ - { IOCTL_DEV_HAS_TZ, "IOCTL_DEV_HAS_TZ" }, \ - { IOCTL_DEV_HAS_EVENT_TIME, "IOCTL_DEV_HAS_EVENT_TIME" }, \ - { IOCTL_DEV_HAS_RECEIVER_INFO, "IOCTL_DEV_HAS_RECEIVER_INFO" }, \ - { IOCTL_DEV_CAN_CLR_UCAP_BUFF, "IOCTL_DEV_CAN_CLR_UCAP_BUFF" }, \ - { IOCTL_DEV_HAS_UCAP, "IOCTL_DEV_HAS_UCAP" }, \ - { IOCTL_DEV_HAS_IRIG_TX, "IOCTL_DEV_HAS_IRIG_TX" }, \ - { IOCTL_DEV_HAS_SERIAL_HS, "IOCTL_DEV_HAS_SERIAL_HS" }, \ - { IOCTL_DEV_HAS_SIGNAL, "IOCTL_DEV_HAS_SIGNAL" }, \ - { IOCTL_DEV_HAS_MOD, "IOCTL_DEV_HAS_MOD" }, \ - { IOCTL_DEV_HAS_IRIG, "IOCTL_DEV_HAS_IRIG" }, \ - { IOCTL_DEV_HAS_REF_OFFS, "IOCTL_DEV_HAS_REF_OFFS" }, \ - { IOCTL_DEV_HAS_OPT_FLAGS, "IOCTL_DEV_HAS_OPT_FLAGS" }, \ - { IOCTL_DEV_HAS_GPS_DATA, "IOCTL_DEV_HAS_GPS_DATA" }, \ - { IOCTL_DEV_HAS_SYNTH, "IOCTL_DEV_HAS_SYNTH" }, \ - { IOCTL_DEV_HAS_GENERIC_IO, "IOCTL_DEV_HAS_GENERIC_IO" }, \ - { IOCTL_PCPS_GENERIC_IO, "IOCTL_PCPS_GENERIC_IO" }, \ - { IOCTL_GET_SYNTH_STATE, "IOCTL_GET_SYNTH_STATE" }, \ - { IOCTL_GET_GPS_ALL_POUT_INFO, "IOCTL_GET_GPS_ALL_POUT_INFO" }, \ - { IOCTL_SET_GPS_POUT_SETTINGS_IDX, "IOCTL_SET_GPS_POUT_SETTINGS_IDX" }, \ - { IOCTL_GET_MAPPED_MEM_ADDR, "IOCTL_GET_MAPPED_MEM_ADDR" }, \ - { IOCTL_UNMAP_MAPPED_MEM, "IOCTL_UNMAP_MAPPED_MEM" }, \ - { IOCTL_GET_PCI_ASIC_FEATURES, "IOCTL_GET_PCI_ASIC_FEATURES" }, \ - { IOCTL_DEV_HAS_PCI_ASIC_FEATURES, "IOCTL_DEV_HAS_PCI_ASIC_FEATURES" }, \ - { IOCTL_DEV_HAS_PCI_ASIC_VERSION, "IOCTL_DEV_HAS_PCI_ASIC_VERSION" }, \ - { IOCTL_DEV_IS_MSF, "IOCTL_DEV_IS_MSF" }, \ - { IOCTL_DEV_IS_LWR, "IOCTL_DEV_IS_LWR" }, \ - { IOCTL_DEV_IS_WWVB, "IOCTL_DEV_IS_WWVB" }, \ - { IOCTL_GET_IRQ_STAT_INFO, "IOCTL_GET_IRQ_STAT_INFO" }, \ - { IOCTL_GET_CYCLES_FREQUENCY, "IOCTL_GET_CYCLES_FREQUENCY" }, \ - { IOCTL_DEV_HAS_FAST_HR_TIMESTAMP, "IOCTL_DEV_HAS_FAST_HR_TIMESTAMP" }, \ - { IOCTL_GET_FAST_HR_TIMESTAMP_CYCLES, "IOCTL_GET_FAST_HR_TIMESTAMP_CYCLES" }, \ - { IOCTL_GET_FAST_HR_TIMESTAMP, "IOCTL_GET_FAST_HR_TIMESTAMP" }, \ - { IOCTL_DEV_HAS_GPS_TIME_SCALE, "IOCTL_DEV_HAS_GPS_TIME_SCALE" }, \ - { IOCTL_GET_GPS_TIME_SCALE_INFO, "IOCTL_GET_GPS_TIME_SCALE_INFO" }, \ - { IOCTL_SET_GPS_TIME_SCALE_SETTINGS, "IOCTL_SET_GPS_TIME_SCALE_SETTINGS" }, \ - { IOCTL_DEV_HAS_GPS_UTC_PARM, "IOCTL_DEV_HAS_GPS_UTC_PARM" }, \ - { IOCTL_GET_GPS_UTC_PARM, "IOCTL_GET_GPS_UTC_PARM" }, \ - { IOCTL_SET_GPS_UTC_PARM, "IOCTL_SET_GPS_UTC_PARM" }, \ - { IOCTL_DEV_HAS_IRIG_CTRL_BITS, "IOCTL_DEV_HAS_IRIG_CTRL_BITS" }, \ - { IOCTL_GET_IRIG_CTRL_BITS, "IOCTL_GET_IRIG_CTRL_BITS" }, \ - { IOCTL_DEV_HAS_LAN_INTF, "IOCTL_DEV_HAS_LAN_INTF" }, \ - { IOCTL_GET_LAN_IF_INFO, "IOCTL_GET_LAN_IF_INFO" }, \ - { IOCTL_GET_IP4_STATE, "IOCTL_GET_IP4_STATE" }, \ - { IOCTL_GET_IP4_SETTINGS, "IOCTL_GET_IP4_SETTINGS" }, \ - { IOCTL_SET_IP4_SETTINGS, "IOCTL_SET_IP4_SETTINGS" }, \ - { IOCTL_DEV_IS_PTP, "IOCTL_DEV_IS_PTP" }, \ - { IOCTL_DEV_HAS_PTP, "IOCTL_DEV_HAS_PTP" }, \ - { IOCTL_GET_PTP_STATE, "IOCTL_GET_PTP_STATE" }, \ - { IOCTL_GET_PTP_CFG_INFO, "IOCTL_GET_PTP_CFG_INFO" }, \ - { IOCTL_SET_PTP_CFG_SETTINGS, "IOCTL_SET_PTP_CFG_SETTINGS" }, \ - { IOCTL_DEV_HAS_IRIG_TIME, "IOCTL_DEV_HAS_IRIG_TIME" }, \ - { IOCTL_GET_IRIG_TIME, "IOCTL_GET_IRIG_TIME" }, \ - { IOCTL_GET_TIME_INFO_HRT, "IOCTL_GET_TIME_INFO_HRT" }, \ - { IOCTL_GET_TIME_INFO_TSTAMP, "IOCTL_GET_TIME_INFO_TSTAMP" }, \ - { IOCTL_DEV_HAS_RAW_IRIG_DATA, "IOCTL_DEV_HAS_RAW_IRIG_DATA" }, \ - { IOCTL_GET_RAW_IRIG_DATA, "IOCTL_GET_RAW_IRIG_DATA" }, \ - { IOCTL_DEV_HAS_PTP_UNICAST, "IOCTL_DEV_HAS_PTP_UNICAST" }, \ - { IOCTL_PTP_UC_MASTER_CFG_LIMITS, "IOCTL_PTP_UC_MASTER_CFG_LIMITS" }, \ - { IOCTL_GET_ALL_PTP_UC_MASTER_INFO, "IOCTL_GET_ALL_PTP_UC_MASTER_INFO" }, \ - { IOCTL_SET_PTP_UC_MASTER_SETTINGS_IDX, "IOCTL_SET_PTP_UC_MASTER_SETTINGS_IDX" }, \ - { IOCTL_DEV_HAS_PZF, "IOCTL_DEV_HAS_PZF" }, \ - { IOCTL_DEV_HAS_CORR_INFO, "IOCTL_DEV_HAS_CORR_INFO" }, \ - { IOCTL_DEV_HAS_TR_DISTANCE, "IOCTL_DEV_HAS_TR_DISTANCE" }, \ - { IOCTL_GET_CORR_INFO, "IOCTL_GET_CORR_INFO" }, \ - { IOCTL_GET_TR_DISTANCE, "IOCTL_GET_TR_DISTANCE" }, \ - { IOCTL_SET_TR_DISTANCE, "IOCTL_SET_TR_DISTANCE" }, \ - { IOCTL_MBG_DBG_GET_PORT_ADDR, "IOCTL_MBG_DBG_GET_PORT_ADDR" }, \ - { IOCTL_MBG_DBG_SET_PORT_ADDR, "IOCTL_MBG_DBG_SET_PORT_ADDR" }, \ - { IOCTL_MBG_DBG_SET_BIT, "IOCTL_MBG_DBG_SET_BIT" }, \ - { IOCTL_MBG_DBG_CLR_BIT, "IOCTL_MBG_DBG_CLR_BIT" }, \ - { 0, NULL } \ +#define IOCTL_CODES_TABLE \ +{ \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_DRVR_INFO ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_DEV ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_STATUS_PORT ), \ + _mbg_cn_table_entry( IOCTL_PCPS_GENERIC_READ ), \ + _mbg_cn_table_entry( IOCTL_PCPS_GENERIC_WRITE ), \ + _mbg_cn_table_entry( IOCTL_PCPS_GENERIC_READ_GPS ), \ + _mbg_cn_table_entry( IOCTL_PCPS_GENERIC_WRITE_GPS ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_TIME ), \ + _mbg_cn_table_entry( IOCTL_SET_PCPS_TIME ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_SYNC_TIME ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_TIME_SEC_CHANGE ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_HR_TIME ), \ + _mbg_cn_table_entry( IOCTL_SET_PCPS_EVENT_TIME ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_SERIAL ), \ + _mbg_cn_table_entry( IOCTL_SET_PCPS_SERIAL ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_TZCODE ), \ + _mbg_cn_table_entry( IOCTL_SET_PCPS_TZCODE ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_TZDL ), \ + _mbg_cn_table_entry( IOCTL_SET_PCPS_TZDL ), \ + _mbg_cn_table_entry( IOCTL_GET_REF_OFFS ), \ + _mbg_cn_table_entry( IOCTL_SET_REF_OFFS ), \ + _mbg_cn_table_entry( IOCTL_GET_MBG_OPT_INFO ), \ + _mbg_cn_table_entry( IOCTL_SET_MBG_OPT_SETTINGS ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_IRIG_RX_INFO ), \ + _mbg_cn_table_entry( IOCTL_SET_PCPS_IRIG_RX_SETTINGS ), \ + _mbg_cn_table_entry( IOCTL_PCPS_CLR_UCAP_BUFF ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_UCAP_ENTRIES ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_UCAP_EVENT ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_TZDL ), \ + _mbg_cn_table_entry( IOCTL_SET_GPS_TZDL ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_SW_REV ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_BVAR_STAT ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_TIME ), \ + _mbg_cn_table_entry( IOCTL_SET_GPS_TIME ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_PORT_PARM ), \ + _mbg_cn_table_entry( IOCTL_SET_GPS_PORT_PARM ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_ANT_INFO ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_UCAP ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_ENABLE_FLAGS ), \ + _mbg_cn_table_entry( IOCTL_SET_GPS_ENABLE_FLAGS ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_STAT_INFO ), \ + _mbg_cn_table_entry( IOCTL_SET_GPS_CMD ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_IDENT ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_POS ), \ + _mbg_cn_table_entry( IOCTL_SET_GPS_POS_XYZ ), \ + _mbg_cn_table_entry( IOCTL_SET_GPS_POS_LLA ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_ANT_CABLE_LEN ), \ + _mbg_cn_table_entry( IOCTL_SET_GPS_ANT_CABLE_LEN ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_RECEIVER_INFO ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_ALL_STR_TYPE_INFO ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_ALL_PORT_INFO ), \ + _mbg_cn_table_entry( IOCTL_SET_GPS_PORT_SETTINGS_IDX ), \ + _mbg_cn_table_entry( IOCTL_GET_PCI_ASIC_VERSION ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_TIME_CYCLES ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_HR_TIME_CYCLES ), \ + _mbg_cn_table_entry( IOCTL_GET_PCPS_IRIG_TX_INFO ), \ + _mbg_cn_table_entry( IOCTL_SET_PCPS_IRIG_TX_SETTINGS ), \ + _mbg_cn_table_entry( IOCTL_GET_SYNTH ), \ + _mbg_cn_table_entry( IOCTL_SET_SYNTH ), \ + _mbg_cn_table_entry( IOCTL_DEV_IS_GPS ), \ + _mbg_cn_table_entry( IOCTL_DEV_IS_DCF ), \ + _mbg_cn_table_entry( IOCTL_DEV_IS_IRIG_RX ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_HR_TIME ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_CAB_LEN ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_TZDL ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_PCPS_TZDL ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_TZCODE ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_TZ ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_EVENT_TIME ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_RECEIVER_INFO ), \ + _mbg_cn_table_entry( IOCTL_DEV_CAN_CLR_UCAP_BUFF ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_UCAP ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_IRIG_TX ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_SERIAL_HS ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_SIGNAL ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_MOD ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_IRIG ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_REF_OFFS ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_OPT_FLAGS ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_GPS_DATA ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_SYNTH ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_GENERIC_IO ), \ + _mbg_cn_table_entry( IOCTL_PCPS_GENERIC_IO ), \ + _mbg_cn_table_entry( IOCTL_GET_SYNTH_STATE ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_ALL_POUT_INFO ), \ + _mbg_cn_table_entry( IOCTL_SET_GPS_POUT_SETTINGS_IDX ), \ + _mbg_cn_table_entry( IOCTL_GET_MAPPED_MEM_ADDR ), \ + _mbg_cn_table_entry( IOCTL_UNMAP_MAPPED_MEM ), \ + _mbg_cn_table_entry( IOCTL_GET_PCI_ASIC_FEATURES ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_PCI_ASIC_FEATURES ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_PCI_ASIC_VERSION ), \ + _mbg_cn_table_entry( IOCTL_DEV_IS_MSF ), \ + _mbg_cn_table_entry( IOCTL_DEV_IS_LWR ), \ + _mbg_cn_table_entry( IOCTL_DEV_IS_WWVB ), \ + _mbg_cn_table_entry( IOCTL_GET_IRQ_STAT_INFO ), \ + _mbg_cn_table_entry( IOCTL_GET_CYCLES_FREQUENCY ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_FAST_HR_TIMESTAMP ), \ + _mbg_cn_table_entry( IOCTL_GET_FAST_HR_TIMESTAMP_CYCLES ), \ + _mbg_cn_table_entry( IOCTL_GET_FAST_HR_TIMESTAMP ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_GPS_TIME_SCALE ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_TIME_SCALE_INFO ), \ + _mbg_cn_table_entry( IOCTL_SET_GPS_TIME_SCALE_SETTINGS ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_GPS_UTC_PARM ), \ + _mbg_cn_table_entry( IOCTL_GET_GPS_UTC_PARM ), \ + _mbg_cn_table_entry( IOCTL_SET_GPS_UTC_PARM ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_IRIG_CTRL_BITS ), \ + _mbg_cn_table_entry( IOCTL_GET_IRIG_CTRL_BITS ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_LAN_INTF ), \ + _mbg_cn_table_entry( IOCTL_GET_LAN_IF_INFO ), \ + _mbg_cn_table_entry( IOCTL_GET_IP4_STATE ), \ + _mbg_cn_table_entry( IOCTL_GET_IP4_SETTINGS ), \ + _mbg_cn_table_entry( IOCTL_SET_IP4_SETTINGS ), \ + _mbg_cn_table_entry( IOCTL_DEV_IS_PTP ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_PTP ), \ + _mbg_cn_table_entry( IOCTL_GET_PTP_STATE ), \ + _mbg_cn_table_entry( IOCTL_GET_PTP_CFG_INFO ), \ + _mbg_cn_table_entry( IOCTL_SET_PTP_CFG_SETTINGS ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_IRIG_TIME ), \ + _mbg_cn_table_entry( IOCTL_GET_IRIG_TIME ), \ + _mbg_cn_table_entry( IOCTL_GET_TIME_INFO_HRT ), \ + _mbg_cn_table_entry( IOCTL_GET_TIME_INFO_TSTAMP ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_RAW_IRIG_DATA ), \ + _mbg_cn_table_entry( IOCTL_GET_RAW_IRIG_DATA ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_PTP_UNICAST ), \ + _mbg_cn_table_entry( IOCTL_PTP_UC_MASTER_CFG_LIMITS ), \ + _mbg_cn_table_entry( IOCTL_GET_ALL_PTP_UC_MASTER_INFO ), \ + _mbg_cn_table_entry( IOCTL_SET_PTP_UC_MASTER_SETTINGS_IDX ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_PZF ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_CORR_INFO ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_TR_DISTANCE ), \ + _mbg_cn_table_entry( IOCTL_GET_CORR_INFO ), \ + _mbg_cn_table_entry( IOCTL_GET_TR_DISTANCE ), \ + _mbg_cn_table_entry( IOCTL_SET_TR_DISTANCE ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_DEBUG_STATUS ), \ + _mbg_cn_table_entry( IOCTL_GET_DEBUG_STATUS ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_EVT_LOG ), \ + _mbg_cn_table_entry( IOCTL_CLR_EVT_LOG ), \ + _mbg_cn_table_entry( IOCTL_GET_NUM_EVT_LOG_ENTRIES ), \ + _mbg_cn_table_entry( IOCTL_GET_FIRST_EVT_LOG_ENTRY ), \ + _mbg_cn_table_entry( IOCTL_GET_NEXT_EVT_LOG_ENTRY ), \ + _mbg_cn_table_entry( IOCTL_DEV_IS_GNSS ), \ + _mbg_cn_table_entry( IOCTL_GET_GNSS_MODE_INFO ), \ + _mbg_cn_table_entry( IOCTL_SET_GNSS_MODE_SETTINGS ), \ + _mbg_cn_table_entry( IOCTL_GET_ALL_GNSS_SAT_INFO ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_GPIO ), \ + _mbg_cn_table_entry( IOCTL_GET_GPIO_CFG_LIMITS ), \ + _mbg_cn_table_entry( IOCTL_GET_ALL_GPIO_INFO ), \ + _mbg_cn_table_entry( IOCTL_SET_GPIO_SETTINGS_IDX ), \ + _mbg_cn_table_entry( IOCTL_DEV_HAS_XMR ), \ + _mbg_cn_table_entry( IOCTL_GET_XMR_INSTANCES ), \ + _mbg_cn_table_entry( IOCTL_GET_ALL_XMR_INFO ), \ + _mbg_cn_table_entry( IOCTL_SET_XMR_SETTINGS_IDX ), \ + _mbg_cn_table_entry( IOCTL_GET_ALL_XMR_STATUS ), \ + _mbg_cn_table_entry( IOCTL_GET_XMR_HOLDOVER_STATUS ), \ + _mbg_cn_table_entry( IOCTL_GET_ALL_GPIO_STATUS ), \ + _mbg_cn_table_entry( IOCTL_CHK_DEV_FEAT ), \ + \ + _mbg_cn_table_entry( IOCTL_MBG_DBG_GET_PORT_ADDR ), \ + _mbg_cn_table_entry( IOCTL_MBG_DBG_SET_PORT_ADDR ), \ + _mbg_cn_table_entry( IOCTL_MBG_DBG_SET_BIT ), \ + _mbg_cn_table_entry( IOCTL_MBG_DBG_CLR_BIT ), \ + _mbg_cn_table_end() \ } @@ -665,7 +786,7 @@ typedef struct * Implementation should be done in a way which introduces as low * latency as possible when reading time stamps from a device. */ -enum +enum MBG_REQ_PRIVL { MBG_REQ_PRIVL_NONE, //< e.g. read date/time/sync status MBG_REQ_PRIVL_EXT_STATUS, //< e.g. read receiver position @@ -736,6 +857,13 @@ int ioctl_get_required_privilege( ulong ioctl_code ) case IOCTL_GET_IP4_STATE: case IOCTL_GET_PTP_STATE: case IOCTL_GET_CORR_INFO: + case IOCTL_GET_DEBUG_STATUS: + case IOCTL_GET_NUM_EVT_LOG_ENTRIES: + case IOCTL_GET_FIRST_EVT_LOG_ENTRY: + case IOCTL_GET_NEXT_EVT_LOG_ENTRY: + #if _MBG_SUPP_VAR_ACC_SIZE + case IOCTL_GET_ALL_GNSS_SAT_INFO: + #endif return MBG_REQ_PRIVL_NONE; // Commands returning device capabilities and features: @@ -744,6 +872,7 @@ int ioctl_get_required_privilege( ulong ioctl_code ) case IOCTL_DEV_IS_MSF: case IOCTL_DEV_IS_WWVB: case IOCTL_DEV_IS_LWR: + case IOCTL_DEV_IS_GNSS: case IOCTL_DEV_IS_IRIG_RX: case IOCTL_DEV_HAS_HR_TIME: case IOCTL_DEV_HAS_CAB_LEN: @@ -780,12 +909,18 @@ int ioctl_get_required_privilege( ulong ioctl_code ) case IOCTL_DEV_HAS_PZF: case IOCTL_DEV_HAS_CORR_INFO: case IOCTL_DEV_HAS_TR_DISTANCE: + case IOCTL_DEV_HAS_DEBUG_STATUS: + case IOCTL_DEV_HAS_EVT_LOG: + case IOCTL_DEV_HAS_GPIO: + case IOCTL_DEV_HAS_XMR: + case IOCTL_CHK_DEV_FEAT: return MBG_REQ_PRIVL_NONE; // The next codes are somewhat special since they change something // on the board but do not affect basic operation: case IOCTL_PCPS_CLR_UCAP_BUFF: case IOCTL_SET_PCPS_EVENT_TIME: // supported by some customized firmware only + case IOCTL_CLR_EVT_LOG: return MBG_REQ_PRIVL_NONE; // Status information which may not be available for everybody: @@ -825,7 +960,15 @@ int ioctl_get_required_privilege( ulong ioctl_code ) case IOCTL_GET_GPS_ALL_PORT_INFO: case IOCTL_GET_GPS_ALL_POUT_INFO: case IOCTL_GET_ALL_PTP_UC_MASTER_INFO: + case IOCTL_GET_ALL_GPIO_INFO: + case IOCTL_GET_ALL_GPIO_STATUS: + case IOCTL_GET_ALL_XMR_STATUS: + case IOCTL_GET_ALL_XMR_INFO: #endif + case IOCTL_GET_GNSS_MODE_INFO: + case IOCTL_GET_GPIO_CFG_LIMITS: + case IOCTL_GET_XMR_INSTANCES: + case IOCTL_GET_XMR_HOLDOVER_STATUS: return MBG_REQ_PRIVL_CFG_READ; // Writing device configuration: @@ -847,6 +990,8 @@ int ioctl_get_required_privilege( ulong ioctl_code ) case IOCTL_SET_PTP_CFG_SETTINGS: case IOCTL_SET_PTP_UC_MASTER_SETTINGS_IDX: case IOCTL_SET_TR_DISTANCE: + case IOCTL_SET_GNSS_MODE_SETTINGS: + case IOCTL_SET_GPIO_SETTINGS_IDX: return MBG_REQ_PRIVL_CFG_WRITE; // Operations which may severely affect system operation: @@ -857,6 +1002,7 @@ int ioctl_get_required_privilege( ulong ioctl_code ) case IOCTL_SET_GPS_TIME_SCALE_SETTINGS: case IOCTL_SET_GPS_UTC_PARM: case IOCTL_SET_GPS_CMD: + case IOCTL_SET_XMR_SETTINGS_IDX: // generic write operations can do anything case IOCTL_PCPS_GENERIC_WRITE: case IOCTL_PCPS_GENERIC_WRITE_GPS: @@ -887,18 +1033,6 @@ int ioctl_get_required_privilege( ulong ioctl_code ) -/* End of header body */ - -#undef _ext -#undef _DO_INIT - - -/* function prototypes: */ - -#ifdef __cplusplus -extern "C" { -#endif - /* ----- function prototypes begin ----- */ /* This section was generated automatically */ @@ -913,4 +1047,9 @@ extern "C" { #endif +/* End of header body */ + +#undef _ext +#undef _DO_INIT + #endif /* _MBGIOCTL_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgklist.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgklist.h new file mode 100755 index 0000000..01a3f21 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgklist.h @@ -0,0 +1,318 @@ + +/************************************************************************** + * + * $Id: mbgklist.h 1.3 2017/07/05 09:52:39 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Userspace implementation of Linux Kernel's list.h + * + * ----------------------------------------------------------------------- + * $Log: mbgklist.h $ + * Revision 1.3 2017/07/05 09:52:39 martin + * Safe loop macros added by philipp. + * Check if 'typeof' is supported based on the type of compiler. + * Reformatted code to conform to standard header file format. + * Updated function prototypes. + * Revision 1.2 2015/10/06 07:08:45 philipp + * Added functions to loop containers of list entries + * Revision 1.1 2015/09/09 10:42:27 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _MBGKLIST_H +#define _MBGKLIST_H + +/* Other headers to be included */ + +#include <mbg_cof.h> + + +#ifdef _MBGKLIST + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + + +#define MBG_KLIST_INIT(name) { &(name), &(name) } + +#define MBG_KLIST_DECLARE(name) \ + struct mbg_klist_head name = MBG_KLIST_INIT(name) + +#define mbg_klist_for_each(head, pos) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +#define mbg_klist_for_each_safe(head, pos, n) \ + for (pos = (head)->next, n = (pos)->next; \ + pos != (head); \ + pos = n, n = pos->next) + +#define mbg_klist_for_each_rev(head, pos) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +#define mbg_klist_for_each_rev_safe(head, pos, n) \ + for (pos = (head)->prev, n = (pos)->prev; \ + pos != (head); \ + pos = n, n = pos->prev) + +#define mbg_klist_entry(ptr, type, member) \ + mbg_container_of(ptr, type, member) + +#define mbg_klist_first_entry(ptr, type, member) \ + mbg_klist_entry((ptr)->next, type, member) + +#define mbg_klist_last_entry(ptr, type, member) \ + mbg_klist_entry((ptr)->prev, type, member) + + + +#if defined( __GNUC__ ) || defined( __clang__ ) // "typeof" supported + +#define mbg_klist_next_entry(pos, member) \ + mbg_klist_entry((pos)->member.next, typeof(*pos), member) + +#define mbg_klist_prev_entry(pos, member) \ + mbg_klist_entry((pos)->member.prev, typeof(*pos), member) + +#define mbg_klist_for_each_entry(head, pos, member) \ + for (pos = mbg_klist_first_entry(head, typeof(*pos), member); \ + &pos->member != (head); \ + pos = mbg_klist_next_entry(pos, member)) + +#define mbg_klist_for_each_entry_rev(head, pos, member) \ + for (pos = mbg_klist_last_entry(head, typeof(*pos), member); \ + &pos->member != (head); \ + pos = mbg_klist_prev_entry(pos, member)) + +#define mbg_klist_for_each_entry_safe(head, pos, n, member) \ + for (pos = mbg_klist_first_entry(head, typeof(*pos), member), \ + n = mbg_klist_next_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = mbg_klist_next_entry(pos, member)) + +#define mbg_klist_for_each_entry_rev_safe(head, pos, n, member) \ + for (pos = mbg_klist_last_entry(head, typeof(*pos), member), \ + n = mbg_klist_prev_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = mbg_klist_prev_entry(pos, member)) + +#endif + + + +struct mbg_klist_head +{ + struct mbg_klist_head *prev; + struct mbg_klist_head *next; +}; + + + +static __mbg_inline +void mbg_klist_init( struct mbg_klist_head *head ) +{ + head->next = head; + head->prev = head; +} + + +static __mbg_inline +void __mbg_klist_add_item( struct mbg_klist_head *item, struct mbg_klist_head *prev, struct mbg_klist_head *next ) +{ + next->prev = item; + item->next = next; + item->prev = prev; + prev->next = item; +} + + +static __mbg_inline +void mbg_klist_prepend_item( struct mbg_klist_head *head, struct mbg_klist_head *item ) +{ + __mbg_klist_add_item( item, head, head->next ); +} + + +static __mbg_inline +void mbg_klist_append_item( struct mbg_klist_head *head, struct mbg_klist_head *item ) +{ + __mbg_klist_add_item( item, head->prev, head ); +} + + +static __mbg_inline +void __mbg_klist_delete_item( struct mbg_klist_head *prev, struct mbg_klist_head *next ) +{ + next->prev = prev; + prev->next = next; +} + + +static __mbg_inline +void mbg_klist_delete_item( struct mbg_klist_head *item ) +{ + __mbg_klist_delete_item( item->prev, item->next ); +} + + +static __mbg_inline +void mbg_klist_delete_item_init( struct mbg_klist_head *item ) +{ + __mbg_klist_delete_item( item->prev, item->next ); + mbg_klist_init( item ); +} + + +static __mbg_inline +void mbg_klist_replace_item( struct mbg_klist_head *old, struct mbg_klist_head *item ) +{ + item->next = old->next; + item->next->prev = item; + item->prev = old->prev; + item->prev->next = item; +} + + +static __mbg_inline +void mbg_klist_replace_item_init( struct mbg_klist_head *old, struct mbg_klist_head *item ) +{ + mbg_klist_replace_item( old, item ); + mbg_klist_init( item ); +} + + +static __mbg_inline +void mbg_klist_move_prepend_item( struct mbg_klist_head *head, struct mbg_klist_head *item ) +{ + mbg_klist_delete_item( item ); + mbg_klist_prepend_item( head, item ); +} + + +static __mbg_inline +void mbg_klist_move_append_item( struct mbg_klist_head *head, struct mbg_klist_head *item ) +{ + mbg_klist_delete_item( item ); + mbg_klist_append_item( head, item ); +} + + +static __mbg_inline +int mbg_klist_is_first( const struct mbg_klist_head *head, const struct mbg_klist_head *item ) +{ + return ( ( item->prev == head ) ? 1 : 0 ); +} + + +static __mbg_inline +int mbg_klist_is_last( const struct mbg_klist_head *head, const struct mbg_klist_head *item ) +{ + return ( ( item->next == head ) ? 1 : 0 ); +} + + +static __mbg_inline +int mbg_klist_is_empty( const struct mbg_klist_head *head ) +{ + return ( ( head->next == head ) ? 1 : 0 ); +} + + +static __mbg_inline +void __mbg_klist_add_list( const struct mbg_klist_head *list, struct mbg_klist_head *prev, struct mbg_klist_head *next ) +{ + struct mbg_klist_head *first = list->next; + struct mbg_klist_head *last = list->prev; + + first->prev = prev; + prev->next = first; + + last->next = next; + next->prev = last; +} + + +static __mbg_inline +void mbg_klist_prepend_list( struct mbg_klist_head *head, const struct mbg_klist_head *list ) +{ + if ( !mbg_klist_is_empty( list ) ) + __mbg_klist_add_list( list, head, head->next ); +} + + +static __mbg_inline +void mbg_klist_append_list( struct mbg_klist_head *head, const struct mbg_klist_head *list ) +{ + if ( !mbg_klist_is_empty( list ) ) + __mbg_klist_add_list( list, head->prev, head ); +} + + +static __mbg_inline +void mbg_klist_prepend_list_init( struct mbg_klist_head *head, struct mbg_klist_head *list ) +{ + if ( !mbg_klist_is_empty( list ) ) + { + __mbg_klist_add_list( list, head, head->next ); + mbg_klist_init( list ); + } +} + + +static __mbg_inline +void mbg_klist_append_list_init( struct mbg_klist_head *head, struct mbg_klist_head *list ) +{ + if ( !mbg_klist_is_empty( list ) ) + { + __mbg_klist_add_list( list, head->prev, head ); + mbg_klist_init( list ); + } +} + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + /** + * @brief Sort a list + * + * @param[in] priv Private data, opaque to ::mbg_klist_sort, passed to @p cmp + * @param[in] head The list to sort + * @param[in] cmp The elements comparison function + * + * This function implements "merge sort", which has O(nlog(n)) + * complexity. + * + * The comparison function @p cmp must return a negative value if a + * should sort before b, and a positive value if a should sort after + * b. If a and b are equivalent, and their original relative + * ordering is to be preserved, cmp must return 0. + */ + void mbg_klist_sort( void *priv, struct mbg_klist_head *head, int (*cmp)( void *priv, struct mbg_klist_head *a, struct mbg_klist_head *b ) ) ; + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _MBGKLIST_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.c b/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.c index 3285b73..d6990c1 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.c +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgmktm.c 1.1 2006/08/22 08:57:15 martin REL_M $ + * $Id: mbgmktm.c 1.2 2017/07/05 10:00:29 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,11 @@ * * ----------------------------------------------------------------------- * $Log: mbgmktm.c $ + * Revision 1.2 2017/07/05 10:00:29 martin + * Let mbg_mktime() fail if year is out of a range which depends on + * the size of the 'time_t' type provided by the build environment. + * Allow 0 as valid return value for mbg_mktime(). + * Added some doxygen comments. * Revision 1.1 2006/08/22 08:57:15 martin * Former function totalsec() moved here from pcpsmktm.c. * @@ -19,7 +24,7 @@ #include <mbgmktm.h> #undef _MBGMKTM -#include <sys/types.h> +#include <assert.h> static const char Days[12] = @@ -33,41 +38,56 @@ static int YDays[12] = }; -/*-------------------------------------------------------------- - * Name: mbg_mktime() - * - * Purpose: This function works like the standard mktime() - * function but does not account for a timezone - * setting configured for the standard C library. - * Also, it does not take a structure but a set - * of variables which makes it more versatile. - * The accepted variables are in the same ranges - * as the struct tm members used by mktime(). + +/*HDR*/ +/** + * @brief Compute a linear time_t value from broken down date and time * - * Input: int year year - 1900 - * int month months since January, 0..11 - * int day days after 1st, 0..30 - * int hour 0..23 - * int min 0..59 - * int sec 0..59, 60 if leap second + * This function works like the standard mktime() function but does not + * account for a timezone setting configured for the standard C library. + * Also, it does not take a structure but a set of variables which makes + * it more versatile. The accepted variables are in the same ranges + * as the struct tm members used by mktime(). * - * Output: -- + * @param[in] year year number - 1900 + * @param[in] month months since January, 0..11 + * @param[in] day days after 1st, 0..30 + * @param[in] hour 0..23 + * @param[in] min 0..59 + * @param[in] sec 0..59, 60 if leap second * - * Ret value: seconds since 1970 (Unix time_t format) - * or -1 if range overflow - *-------------------------------------------------------------*/ - -/*HDR*/ -long mbg_mktime( int year, int month, int day, - int hour, int min, int sec ) + * @return seconds since 1970-01-01 (Unix time_t format) or ((time_t) -1) if range overflow + */ +time_t mbg_mktime( int year, int month, int day, + int hour, int min, int sec ) { int leaps; long days; - long secs; + time_t secs; + // time_t should be at least 4 bytes + assert( sizeof( time_t ) >= 4 ); - if ( year < 70 || year > 138 ) - return ( -1 ); + if ( sizeof( time_t ) == 4 ) + { + // 32 bit *signed* time_t will roll over after 2038-01-19 03:14:07 + // when the number of seconds reaches 0x7FFFFFFF, so we don't try + // conversions for 2038 or later, though 32 bit *unsigned* time_t + // may still work after year 2100. + if ( year < 70 || year > 137 ) + goto fail; + } + else + if ( sizeof( time_t ) == 8 ) + { + // 64 bit time_t will work for million years. However, it's not + // clear what happes for dates before 1970-01-01T00:00:00 if time_t + // is *unsigned*. + if ( year < 70 ) + goto fail; + } + else + goto fail; min += sec / 60; sec %= 60; /* Seconds are normalized */ @@ -111,7 +131,14 @@ long mbg_mktime( int year, int month, int day, secs = days * 86400L + hour * 3600L + min * 60L + sec; - return( secs > 0 ? secs : -1 ); + if ( secs < 0 ) // == 0 is valid for 1970-01-01 00:00:00 + goto fail; + + return secs; + + +fail: + return (time_t) -1; } // mbg_mktime diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.h index 2aada2a..d7a5473 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgmktm.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgmktm.h 1.1 2006/08/22 08:57:15 martin REL_M $ + * $Id: mbgmktm.h 1.2 2017/07/05 10:02:42 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,9 @@ * * ----------------------------------------------------------------------- * $Log: mbgmktm.h $ + * Revision 1.2 2017/07/05 10:02:42 martin + * Include time.h. + * Updated function prototypes. * Revision 1.1 2006/08/22 08:57:15 martin * Former function totalsec() moved here from pcpsmktm.c. * @@ -21,6 +24,9 @@ /* Other headers to be included */ +#include <time.h> + + #ifdef _MBGMKTM #define _ext #else @@ -30,9 +36,6 @@ /* Start of header body */ - -/* function prototypes: */ - #ifdef __cplusplus extern "C" { #endif @@ -42,7 +45,26 @@ extern "C" { /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ -long mbg_mktime( int year, int month, int day, int hour, int min, int sec ) ; + /** + * @brief Compute a linear time_t value from broken down date and time + * + * This function works like the standard mktime() function but does not + * account for a timezone setting configured for the standard C library. + * Also, it does not take a structure but a set of variables which makes + * it more versatile. The accepted variables are in the same ranges + * as the struct tm members used by mktime(). + * + * @param[in] year year number - 1900 + * @param[in] month months since January, 0..11 + * @param[in] day days after 1st, 0..30 + * @param[in] hour 0..23 + * @param[in] min 0..59 + * @param[in] sec 0..59, 60 if leap second + * + * @return seconds since 1970-01-01 (Unix time_t format) or ((time_t) -1) if range overflow + */ + time_t mbg_mktime( int year, int month, int day, int hour, int min, int sec ) ; + /* ----- function prototypes end ----- */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgmutex.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgmutex.h index 6ef6f2a..50d7938 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbgmutex.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgmutex.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgmutex.h 1.1.1.6 2011/05/31 14:19:55 martin TRASH $ + * $Id: mbgmutex.h 1.4 2017/07/05 10:05:02 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,17 +11,16 @@ * * ----------------------------------------------------------------------- * $Log: mbgmutex.h $ - * Revision 1.1.1.6 2011/05/31 14:19:55 martin - * Revision 1.1.1.5 2011/05/16 17:39:41 martin + * Revision 1.4 2017/07/05 10:05:02 martin + * windows.h is now included by mbg_tgt.h. + * Check for MBG_TGT_POSIX instead of MBG_TGT_UNIX. + * Revision 1.3 2013/04/11 13:46:58 martin + * Use non-specific spinlock function under Windows. + * Revision 1.2 2012/03/08 12:19:01Z martin + * Fixes for Linux kernel and FreeBSD. + * Fixed build under DOS and QNX usinc dummy defines. * Don't define macros for semaphore destroy functions * if not required/supported on the target OS. - * Revision 1.1.1.4 2011/05/06 09:11:16Z martin - * Fix for DOS. - * Revision 1.1.1.3 2011/05/04 09:24:18Z martin - * Revision 1.1.1.2 2011/05/04 08:57:23 martin - * Fix for FreeBSD. - * Revision 1.1.1.1 2011/05/03 15:46:06 martin - * Fix for Linux kernel. * Revision 1.1 2011/04/15 12:26:59 martin * Initial revision. * @@ -46,6 +45,10 @@ /* Start of header body */ +#ifdef __cplusplus +extern "C" { +#endif + #if defined( MBG_TGT_KERNEL ) // definitions used in kernel space #if defined( MBG_TGT_WIN32 ) // Windows kernel space @@ -53,8 +56,8 @@ typedef KSPIN_LOCK MBG_SPINLOCK; #define _mbg_spin_lock_init( _spl ) KeInitializeSpinLock( _spl ) // _mbg_spin_lock_destroy is not supported - #define _mbg_spin_lock_acquire( _spl ) KeAcquireSpinLockAtDpcLevel( _spl ) - #define _mbg_spin_lock_release( _spl ) KeReleaseSpinLockFromDpcLevel( _spl ) + #define _mbg_spin_lock_acquire( _spl ) KeAcquireSpinLock( _spl, &OldIrql ) + #define _mbg_spin_lock_release( _spl ) KeReleaseSpinLock( _spl, OldIrql ) #define _MBG_SPINLOCK_DEFINED 1 @@ -147,8 +150,6 @@ #if defined( MBG_TGT_WIN32 ) // Windows user space - #include <windows.h> - // definitions used with mutexes typedef HANDLE MBG_MUTEX; #define _mbg_mutex_init( _pm ) *(_pm) = CreateMutex( NULL, FALSE, NULL ) @@ -167,7 +168,7 @@ #define _MBG_CRIT_SECT_DEFINED 1 - #elif defined( MBG_TGT_UNIX ) // Unix user space use pthread library + #elif defined( MBG_TGT_POSIX ) // Unix user space use pthread library #include <pthread.h> @@ -185,7 +186,7 @@ // For critical sections use defaults specified below - #elif defined( MBG_TGT_DOS ) + #elif defined( MBG_TGT_DOS ) || defined( MBG_TGT_QNX ) typedef int MBG_MUTEX; // just a dummy declaration @@ -237,13 +238,6 @@ #endif - -/* function prototypes: */ - -#ifdef __cplusplus -extern "C" { -#endif - /* ----- function prototypes begin ----- */ /* This section was generated automatically */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgpccyc.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgpccyc.h index 7a47edf..cc9854a 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbgpccyc.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgpccyc.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgpccyc.h 1.1.1.4 2011/07/20 15:58:53 martin TRASH $ + * $Id: mbgpccyc.h 1.7 2017/05/10 15:21:41 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,12 +10,21 @@ * * ----------------------------------------------------------------------- * $Log: mbgpccyc.h $ - * Revision 1.1.1.4 2011/07/20 15:58:53 martin - * Support cycles on IA64 only in kernel space. - * Revision 1.1.1.3 2011/07/13 09:44:49 martin - * Moved IA64 includes from pcpsdev.h to mbgpccyc.h. - * Revision 1.1.1.2 2011/07/06 13:23:36 martin - * Revision 1.1.1.1 2011/07/05 12:25:08 martin + * Revision 1.7 2017/05/10 15:21:41 martin + * Tiny cleanup. + * Revision 1.6 2016/08/09 16:01:10 martin + * Syntax fix. + * Revision 1.5 2016/02/17 16:04:18 martin + * Include header file missing for FreeBSD. + * Revision 1.4 2015/10/19 09:16:45 martin + * Fixed some spelling. + * Revision 1.3 2014/10/08 13:10:14 martin + * Check for MBG_TGT_POSIX instead of MBG_TGT_UNIX. + * Revision 1.2 2012/03/12 13:45:57 martin + * Added cycles support for Linux/IA64, FreeBSD and NetBSD + * in kernel space. + * Use get_cycles() in Linux kernel mode if no special cycles support + * is provided for the given hardware platform. * Revision 1.1 2011/06/23 15:36:07 martin * Initial revision. * @@ -40,6 +49,7 @@ #if defined( MBG_TGT_FREEBSD ) #if defined( MBG_TGT_KERNEL ) #if defined( MBG_ARCH_X86 ) + #include <sys/time.h> #include <machine/clock.h> /* for symbol 'tsc_freq' */ #endif #endif @@ -48,7 +58,6 @@ #if defined( MBG_TGT_LINUX ) #if defined( MBG_ARCH_IA64 ) && defined( MBG_TGT_KERNEL ) #include <asm/ia64regs.h> - #include <asm/intel_intrin.h> #endif #endif @@ -63,13 +72,17 @@ /* Start of header body */ +#ifdef __cplusplus +extern "C" { +#endif + /** * @brief Generic types to hold PC cycle counter values. * * The cycle counter value is usually derived from the PC CPU's TSC or some other * timer hardware on the mainboard. */ -#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_UNIX ) +#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_POSIX ) typedef int64_t MBG_PC_CYCLES; typedef uint64_t MBG_PC_CYCLES_FREQUENCY; @@ -106,7 +119,7 @@ // which would copy the output regs edx:eax as a 64 bit // number to a variable x. // - // The "=A" expression should implicitely tell the compiler + // The "=A" expression should implicitly tell the compiler // the edx and eax registers have been clobbered. However, // this does not seem to work properly at least with gcc 4.1.2 // shipped with Centos 5. @@ -118,14 +131,14 @@ // assumes edx is unchanged, which may yield faulty results // or even lead to segmentation faults. // - // A possible workaround could be to mark edx explicitely as + // A possible workaround could be to mark edx explicitly as // being clobbered in the asm inline code, but unfortunately // other gcc versions report an error if a register which is - // implicitely (by "=A") known to be clobbered is also listed - // explicitely to be clobbered. + // implicitly (by "=A") known to be clobbered is also listed + // explicitly to be clobbered. // // So the code below is a workaround which tells the compiler - // implicitely that the eax ("=a") and edx ("=d") registers + // implicitly that the eax ("=a") and edx ("=d") registers // are being used and thus clobbered. union @@ -153,6 +166,8 @@ static __mbg_inline void mbg_get_pc_cycles( MBG_PC_CYCLES *p ) { +#if !defined( OMIT_PC_CYCLES_SUPPORT ) + #if defined( MBG_TGT_WIN32 ) #if defined( MBG_TGT_KERNEL ) // kernel space @@ -168,11 +183,6 @@ void mbg_get_pc_cycles( MBG_PC_CYCLES *p ) *p = mbg_rdtscll(); #define MBG_PC_CYCLES_SUPPORTED 1 - #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_SPARC ) && defined( MBG_TGT_KERNEL ) - - *p = get_cycles(); - #define MBG_PC_CYCLES_SUPPORTED 1 - #elif defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_IA64 ) && defined( MBG_TGT_KERNEL ) unsigned long result = ia64_getreg( _IA64_REG_AR_ITC ); @@ -189,21 +199,32 @@ void mbg_get_pc_cycles( MBG_PC_CYCLES *p ) #define MBG_PC_CYCLES_SUPPORTED 1 + #elif defined( MBG_TGT_LINUX ) && defined( MBG_TGT_KERNEL ) + + *p = get_cycles(); + #define MBG_PC_CYCLES_SUPPORTED 1 + #elif defined( MBG_TGT_FREEBSD ) && defined( MBG_ARCH_X86 ) *p = mbg_rdtscll(); #define MBG_PC_CYCLES_SUPPORTED 1 - #elif defined( MBG_TGT_NETBSD ) && defined ( MBG_TGT_KERNEL ) + #elif defined( MBG_TGT_NETBSD ) && defined( MBG_TGT_KERNEL ) *p = cpu_counter(); //##++ or cpu_counter_serializing() #define MBG_PC_CYCLES_SUPPORTED 1 - #else + #endif + +#endif + + + #if !defined( MBG_PC_CYCLES_SUPPORTED ) *p = 0; + #define MBG_PC_CYCLES_SUPPORTED 0 #endif @@ -259,7 +280,7 @@ void mbg_get_pc_cycles_frequency( MBG_PC_CYCLES_FREQUENCY *p ) static __mbg_inline MBG_PC_CYCLES mbg_delta_pc_cycles( const MBG_PC_CYCLES *p1, const MBG_PC_CYCLES *p2 ) { -#if 0 && !defined( MBG_PC_CYCLES_SUPPORTED ) //##+++++++++++++++++ +#if 0 && !MBG_PC_CYCLES_SUPPORTED // Cycle counts not supported on this target platform. // Under SPARC this may even result in bus errors // due to alignment of the underlying data structures. @@ -272,12 +293,6 @@ MBG_PC_CYCLES mbg_delta_pc_cycles( const MBG_PC_CYCLES *p1, const MBG_PC_CYCLES -/* function prototypes: */ - -#ifdef __cplusplus -extern "C" { -#endif - /* ----- function prototypes begin ----- */ /* This section was generated automatically */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgsystm.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgsystm.h new file mode 100755 index 0000000..e481943 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgsystm.h @@ -0,0 +1,494 @@ + +/************************************************************************** + * + * $Id: mbgsystm.h 1.3 2017/07/26 14:26:17 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Generic functions and definitions to deal with the computer's + * system time, and prototypes for mbgsystm.c. + * + * ----------------------------------------------------------------------- + * $Log: mbgsystm.h $ + * Revision 1.3 2017/07/26 14:26:17 martin + * Fixed build for NetBSD. + * Revision 1.2 2017/07/04 12:26:57 martin + * More detailed control of inclusion of other headers. + * Made mbg_delta_sys_time_ms() as inline function here. + * Updated function prototypes. + * Cleanup. + * Revision 1.1 2015/09/15 13:21:00Z martin + * Initial revision. + * Moved existing code from different modules here. + * + **************************************************************************/ + +#ifndef _MBGSYSTM_H +#define _MBGSYSTM_H + + +/* Other headers to be included */ + +#include <mbg_tgt.h> +#include <words.h> + +#if defined( MBG_TGT_POSIX ) + + #if defined( MBG_TGT_KERNEL ) + + #if defined( MBG_TGT_LINUX ) + + #define LINUX_KERNEL_HAS_MSLEEP ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 16 ) ) + #define LINUX_KERNEL_HAS_GETNSTIMEOFDAY ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 22 ) ) + #define LINUX_KERNEL_HAS_KTIME_H ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 16 ) ) + + #if !LINUX_KERNEL_HAS_MSLEEP + #include <linux/wait.h> + #include <linux/sched.h> + #endif + + // We need the prototype for getnstimeofday(). In newer kernels + // (e.g. 4.x) this is available via linux/ktime.h, which in turn + // includes linux/timekeeping.h, which declares the prototype. + #if LINUX_KERNEL_HAS_KTIME_H + #include <linux/ktime.h> + #endif + + // In older kernel versions the prototype for getnstimeofday() + // is declared in linux/time.h, so we include that one anyway. + #include <linux/time.h> + + #include <linux/delay.h> + #include <linux/jiffies.h> + + #elif defined( MBG_TGT_BSD ) + + #if defined( MBG_TGT_FREEBSD ) + #include <sys/libkern.h> + #endif + + #if defined( MBG_TGT_NETBSD ) + #include <sys/param.h> // mstohz + #include <sys/kernel.h> // hz + #endif + + #include <sys/time.h> + + #endif + + #else // POSIX user space + + #include <time.h> + + #if defined( MBG_TGT_LINUX ) + #include <sys/sysinfo.h> + #endif + + #endif + +#elif defined( MBG_TGT_WIN32 ) + + #if defined( MBG_TGT_KERNEL ) + #include <mbg_w32.h> + #endif + + #include <mbgtime.h> + +#elif defined( MBG_TGT_DOS ) + + #include <dos.h> + +#endif + + +#ifdef _MBGSYSTM + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Define generic types to hold PC cycle counter values and system timestamps. + The generic types are defined using native types used by the target operating + systems. + + The cycle counter value is usually derived from the PC CPU's TSC or some other + timer hardware on the mainboard. + */ +#if defined( MBG_TGT_POSIX ) + + typedef NANO_TIME_64 MBG_SYS_TIME; + typedef int64_t MBG_SYS_UPTIME; // [s] + +#elif defined( MBG_TGT_WIN32 ) + + typedef LARGE_INTEGER MBG_SYS_TIME; + typedef int64_t MBG_SYS_UPTIME; // [s] + +#elif defined( MBG_TGT_OS2 ) + + typedef uint32_t MBG_SYS_TIME; //## dummy + typedef long MBG_SYS_UPTIME; //## dummy + +#elif defined( MBG_TGT_DOS ) + + typedef uint32_t MBG_SYS_TIME; //## dummy + typedef long MBG_SYS_UPTIME; //## dummy + +#else // other target OSs which access the hardware directly + + typedef uint32_t MBG_SYS_TIME; //## dummy + typedef long MBG_SYS_UPTIME; //## dummy + +#endif + +//### TODO +// MBG_SYS_TIME is always read in native machine endianess, +// so no need to convert endianess. +#define _mbg_swab_mbg_sys_time( _p ) \ + _nop_macro_fnc() + + + +static __mbg_inline +void mbg_get_sys_time( MBG_SYS_TIME *p ) +{ + #if defined( MBG_TGT_POSIX ) + + #if defined( MBG_TGT_KERNEL ) // kernel space functions even differ for POSIX systems + + #if defined( MBG_TGT_LINUX ) // Linux kernel space + + #if ( LINUX_KERNEL_HAS_GETNSTIMEOFDAY ) + { + // getnstimeofday() supported + struct timespec ts; + + getnstimeofday( &ts ); + + p->secs = ts.tv_sec; + p->nano_secs = ts.tv_nsec; + } + #else + { + // getnstimeofday() *not* supported + struct timeval tv; + + do_gettimeofday( &tv ); + + p->secs = tv.tv_sec; + p->nano_secs = tv.tv_usec * 1000; + } + #endif + + #elif defined( MBG_TGT_BSD ) // BSD kernel space + { + struct timespec ts; + + nanotime( &ts ); + + p->secs = ts.tv_sec; + p->nano_secs = ts.tv_nsec; + } + #endif + + #else // POSIX user space + { + struct timespec ts; + + #if defined( CLOCK_REALTIME_PRECISE ) // at least available in FreeBSD + clock_gettime( CLOCK_REALTIME_PRECISE, &ts ); + #else + clock_gettime( CLOCK_REALTIME, &ts ); + #endif + + p->secs = ts.tv_sec; + p->nano_secs = ts.tv_nsec; + } + #endif + + #elif defined( MBG_TGT_WIN32 ) + + #if defined( MBG_TGT_KERNEL ) // Windows kernel space + #if defined( MBG_TGT_WIN32_PNP ) && !defined( MBG_TGT_WIN32_PNP_X64 ) + extern KE_QUERY_SYSTEM_TIME_FNC ke_query_system_time_fnc; + ke_query_system_time_fnc( p ); + #else + KeQuerySystemTime( p ); + #endif + #else // Windows user space + { + FILETIME ft; + GetSystemTimeAsFileTime( &ft ); + p->LowPart = ft.dwLowDateTime; + p->HighPart = ft.dwHighDateTime; + } + #endif + + #else + + *p = 0; // dummy + + #endif + +} // mbg_get_sys_time + + + +static __mbg_inline +void mbg_get_sys_uptime( MBG_SYS_UPTIME *p ) +{ + #if defined( MBG_TGT_WIN32 ) + + #if defined( MBG_TGT_KERNEL ) // kernel space + + ULONGLONG time_increment = KeQueryTimeIncrement(); + LARGE_INTEGER tick_count; + + KeQueryTickCount( &tick_count ); + + // multiplication by time_increment yields HNS units, + // but we need seconds + *p = ( tick_count.QuadPart * time_increment ) / HNS_PER_SEC; + + #else // user space + + DWORD tickCount; + DWORD timeAdjustment; + DWORD timeIncrement; + BOOL timeAdjustmentDisabled; + + if ( !GetSystemTimeAdjustment( &timeAdjustment, &timeIncrement, &timeAdjustmentDisabled ) ) + *p = -1; // failed + + // ATTENTION: This is compatible with older Windows versions, but + // the returned tick count wraps around to zero after 49.7 days. + // A new GetTickCount64() call is available under Windows Vista and newer, + // but the function call had to be imported dynamically since otherwise + // programs refused to start under pre-Vista versions due to undefined DLL symbol. + tickCount = GetTickCount(); + + *p = ( ( (MBG_SYS_UPTIME) tickCount ) * timeIncrement ) / HNS_PER_SEC; + + #endif + + #elif defined( MBG_TGT_LINUX ) + + #if defined( MBG_TGT_KERNEL ) + // getrawmonotonic() can possibly be used for this in newer kernels + { + // Using a simple 64 bit division may result in a linker error + // in kernel mode due to a missing symbol __udivdi3, so we use + // a specific inline function do_div(). + // Also, the jiffies counter is not set to 0 at startup but to + // a defined initialization value we need to account for. + uint64_t tmp = get_jiffies_64() - INITIAL_JIFFIES; + do_div( tmp, HZ ); + *p = tmp; + } + #else + { + struct sysinfo si; + int rc = sysinfo( &si ); + *p = ( rc == 0 ) ? si.uptime : -1; + } + #endif + + #elif defined( MBG_TGT_BSD ) + + #if defined( MBG_TGT_KERNEL ) + { + struct timespec ts; + #if 0 //##+++++++ + { + struct bintime bt; + + binuptime( &bt ); + #if defined( DEBUG ) + printf( "binuptime: %lli.%09lli\n", + (long long) bt.sec, + (long long) bt.frac ); + #endif + } + #endif + + nanouptime( &ts ); + #if defined( DEBUG ) + printf( "nanouptime: %lli.%09lli\n", + (long long) ts.tv_sec, + (long long) ts.tv_nsec ); + #endif + *p = ts.tv_sec; + } + #elif defined( MBG_TGT_FREEBSD ) + { + struct timespec ts; + // CLOCK_UPTIME_FAST is specific to FreeBSD + int rc = clock_gettime( CLOCK_UPTIME_FAST, &ts ); + *p = ( rc == 0 ) ? ts.tv_sec : -1; + } + #else // MBG_TGT_NETBSD, ... + + *p = -1; //##++ needs to be implemented + + #endif + + #else + + *p = -1; // not supported + + #endif + +} // mbg_get_sys_uptime + + + +/** + * @brief Compute delta between two ::MBG_SYS_TIME times, in milliseconds + * + * @param[in] t2 the time to be subtracted from + * @param[in] t1 The time to be subtracted + * + * @return The time difference in [milliseconds] + */ +static __mbg_inline +long mbg_delta_sys_time_ms( const MBG_SYS_TIME *t2, const MBG_SYS_TIME *t1 ) +{ + #if defined( MBG_TGT_POSIX ) + long dt = ( t2->secs - t1->secs ) * 1000; + #if defined ( MBG_TGT_LINUX ) && defined( MBG_TGT_KERNEL ) + int64_t tmp64 = t2->nano_secs - t1->nano_secs; + do_div( tmp64, 1000000 ); + dt += tmp64; + #else + dt += ( t2->nano_secs - t1->nano_secs ) / 1000000; + #endif + return dt; + #elif defined( MBG_TGT_WIN32 ) + return (long) ( ( t2->QuadPart - t1->QuadPart ) / HNS_PER_MS ); + #else + return 0; + #endif + +} // mbg_delta_sys_time_ms + + + +static __mbg_inline +void mbg_sleep_sec( long sec ) +{ + #if defined( MBG_TGT_POSIX ) + + #if defined( MBG_TGT_KERNEL ) // kernel space functions even differ for POSIX systems + + #if defined( MBG_TGT_LINUX ) // Linux kernel space + + // msleep is not defined in older kernels, so we use this + // only if it is surely supported. + #if LINUX_KERNEL_HAS_MSLEEP + msleep( sec * 1000 ); + #else + { + DECLARE_WAIT_QUEUE_HEAD( tmp_wait ); + wait_event_interruptible_timeout( tmp_wait, 0, sec * HZ + 1 ); + } + #endif + + #elif defined( MBG_TGT_FREEBSD ) + + struct timeval tv = { 0 }; + int ticks; + tv.tv_sec = sec; + ticks = tvtohz( &tv ); + + #if defined( DEBUG ) + printf( "pause: %lli.%06lli (%i ticks)\n", + (long long) tv.tv_sec, + (long long) tv.tv_usec, + ticks ); + #endif + + pause( "pause", ticks ); + + #elif defined( MBG_TGT_NETBSD ) + + int timeo = mstohz( sec * 1000 ); + + #if defined( DEBUG ) + printf( "kpause: %i s (%i ticks)\n", sec, timeo ); + #endif + + kpause( "pause", 1, timeo, NULL ); + + #endif + + #else // POSIX user space + + sleep( sec ); + + #endif + + #elif defined( MBG_TGT_WIN32 ) + + #if defined( MBG_TGT_KERNEL ) // kernel space + + LARGE_INTEGER delay; + + // we need to pass a negative value to KeDelayExecutionThread() + // since the given time is a relative time interval, not absolute + // time. See the API docs for KeDelayExecutionThread(). + delay.QuadPart = - ((LONGLONG) sec * HNS_PER_SEC); + + KeDelayExecutionThread( KernelMode, FALSE, &delay ); + + #else // user space + + // Sleep() expects milliseconds + Sleep( sec * 1000 ); + + #endif + + #elif defined( MBG_TGT_DOS ) + + delay( (unsigned) ( sec * 1000 ) ); + + #else + + // This needs to be implemented for the target OS + // and thus will probably yield a linker error. + do_sleep_sec( sec ); + + #endif + +} // mbg_sleep_sec + + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + +/* (no header definitions found) */ + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _MBGSYSTM_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgtime.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgtime.h index ba6900f..847cb88 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbgtime.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgtime.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgtime.h 1.17.1.6 2011/05/06 09:03:12 martin TRASH $ + * $Id: mbgtime.h 1.24 2017/07/04 14:02:25 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,15 +10,32 @@ * * ----------------------------------------------------------------------- * $Log: mbgtime.h $ - * Revision 1.17.1.6 2011/05/06 09:03:12 martin - * Fix for DOS. - * Revision 1.17.1.5 2011/05/06 08:07:58Z daniel - * include <time.h> for WIN32 target and firmware only - * Revision 1.17.1.4 2011/02/09 15:46:48Z martin - * Revision 1.17.1.3 2011/01/24 17:09:20 martin - * Fixed build under FreeBSD. - * Revision 1.17.1.2 2010/08/13 11:57:13 martin - * Revision 1.17.1.1 2010/08/13 11:39:20Z martin + * Revision 1.24 2017/07/04 14:02:25 martin + * Made definitions of some constants signed to avoid + * signed/unsigned compiler warnings. + * Moved some macros and inline functions for fraction + * conversion here. They are excluded from build in kernel + * mode, though, since some kernels don't support this properly. + * Moved some NANO_TIME- and NANO_TIME_64-related inline + * functions to new module nanotime.c. + * Renamed PCPS_HRT_BIN_FRAC_SCALE to MBG_FRAC32_UNITS_PER_SEC. + * Updated function prototypes. + * Doxygen stuff. + * Revision 1.23 2017/03/16 12:26:13 martin + * Updated function prototypes. + * Revision 1.22 2017/01/25 13:10:55 gregoire.diehl + * nano_time_64_to_double and double_to_nano_time_64 added + * Revision 1.21 2016/12/15 17:44:59Z martin + * Changed conditions to include time.h. + * Fixed spelling. + * Removed trailing spaces. + * Revision 1.20 2014/05/27 08:09:19 martin + * Added NTP_SEC_BIAS. + * Revision 1.19 2013/05/22 16:47:01 martin + * Added some useful macros. + * Revision 1.18 2012/10/02 18:51:11 martin + * Include <time.h> for WIN32 target and firmware only + * Fixed build under QNX, DOS, and FreeBSD. * Revision 1.17 2010/08/06 13:03:03 martin * Removed obsolete code. * Revision 1.16 2010/07/16 10:22:07Z martin @@ -65,9 +82,7 @@ #include <gpsdefs.h> -#if _IS_MBG_FIRMWARE \ - || defined( MBG_TGT_WIN32 ) \ - || defined( MBG_TGT_DOS ) +#if !defined( MBG_TGT_KERNEL ) || defined( MBG_TGT_WIN32 ) #include <time.h> #endif @@ -78,6 +93,7 @@ extern "C" { #ifdef _MBGTIME #define _ext + #define _DO_INIT #else #define _ext extern #endif @@ -86,13 +102,30 @@ extern "C" { /* Start of header body */ -// The Unix time_t epoche is usually 1970-01-01 00:00 whereas -// the GPS epoche is 1980-01-06 00:00, so the difference is 10 years, -// plus 2 days due to leap years (1972 and 1976), plus the difference -// of the day-of-month (6 - 1). -#define GPS_SEC_BIAS 315964800UL // ( ( ( 10UL * 365UL ) + 2 + 5 ) * SECS_PER_DAY ) +/** + * @brief GPS epoch bias from ordinary time_t epoch + * + * The Unix time_t epoch is usually 1970-01-01 00:00 whereas + * the GPS epoch is 1980-01-06 00:00, so the difference is 10 years, + * plus 2 days due to leap years (1972 and 1976), plus the difference + * of the day-of-month (6 - 1), so:<br> + * + * time_t t = ( gps_week * ::SECS_PER_WEEK ) + sec_of_week + ::GPS_SEC_BIAS + */ +#define GPS_SEC_BIAS 315964800UL // ( ( ( 10UL * 365UL ) + 2 + 5 ) * SECS_PER_DAY ) + + +/** + * @brief NTP epoch bias from ordinary time_t epoch + * + * The Unix time_t epoch is usually 1970-01-01 00:00 whereas + * the NTP epoch is 1900-01-01 00:00, so the difference is + * a constant number of seconds:<br> + * + * time_t t = ntp_time - ::NTP_SEC_BIAS + */ +#define NTP_SEC_BIAS 2208988800UL -// time_t t = ( gps_week * SECS_PER_WEEK ) + sec_of_week + GPS_SEC_BIAS // Modified Julian Day (MJD) numbers for some commonly used epochs. @@ -105,7 +138,7 @@ extern "C" { // The constant below defines the Windows FILETIME number (100 ns intervals -// since 1601-01-01) for 1970-01-01, which is usually the epoche for the time_t +// since 1601-01-01) for 1970-01-01, which is usually the epoch for the time_t // type used by the standard C library. #if !defined( FILETIME_1970 ) // FILETIME represents a 64 bit number, so we need to defined the @@ -174,6 +207,7 @@ typedef struct clock_t start; clock_t stop; short is_set; + } TIMEOUT; @@ -203,77 +237,96 @@ typedef struct #define MSEC_PER_HOUR ( MSEC_PER_SEC * SECS_PER_HOUR ) #define MSEC_PER_DAY ( MSEC_PER_SEC * SECS_PER_DAY ) -#define NSECS_PER_SEC 1000000000UL +#define NSECS_PER_SEC 1000000000L #if !defined( HNS_PER_SEC ) - #define HNS_PER_SEC 10000000UL + #define HNS_PER_SEC 10000000L #endif #if !defined( HNS_PER_MS ) - #define HNS_PER_MS 10000UL + #define HNS_PER_MS 10000L #endif +/** + * @brief A table with the days of month + * + * First row is for standard years, second row is + * for leap years. + * + * @see DAYS_OF_MONTH_TABLE_INIT + */ +typedef char DAYS_OF_MONTH_TABLE[2][12]; + + +/** + * @brief An initializer for a ::DAYS_OF_MONTH_TABLE + */ +#define DAYS_OF_MONTH_TABLE_INIT \ +{ \ + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, \ + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } \ +} + + + _ext TM_GPS dhms; _ext TM_GPS datum; _ext const char *short_time_fmt -#ifdef _MBGTIME +#ifdef _DO_INIT = "%2i:%02i" #endif ; _ext const char *time_fmt -#ifdef _MBGTIME +#ifdef _DO_INIT = "%2i:%02i:%02i" #endif ; _ext const char *long_time_fmt -#ifdef _MBGTIME +#ifdef _DO_INIT = "%2i:%02i:%02i.%02i" #endif ; _ext const char *date_fmt -#ifdef _MBGTIME +#ifdef _DO_INIT = "%2i.%02i.%04i" #endif ; _ext const char *day_date_fmt -#ifdef _MBGTIME +#ifdef _DO_INIT = "%s, %2i.%02i.%04i" #endif ; _ext const char *day_name_eng[] -#ifdef _MBGTIME +#ifdef _DO_INIT = { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" } #endif ; _ext const char *day_name_ger[] -#ifdef _MBGTIME +#ifdef _DO_INIT = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" } #endif ; _ext const TM_GPS init_tm -#ifdef _MBGTIME +#ifdef _DO_INIT = { 1980, 1, 1, 0, 0, 0, 0, 0, 0, 0 } #endif ; -_ext char days_of_month[2][12] -#ifdef _MBGTIME - = { - { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, - { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } - } +_ext DAYS_OF_MONTH_TABLE days_of_month +#ifdef _DO_INIT + = DAYS_OF_MONTH_TABLE_INIT #endif ; @@ -283,34 +336,380 @@ _ext char days_of_month[2][12] n_days( (_s)->mday, (_s)->month, (_s)->year ) +#define _is_leap_year( _y ) \ + ( ( ( ( (_y) % 4 ) == 0 ) && ( ( (_y) % 100 ) != 0 ) ) || ( ( (_y) % 400 ) == 0 ) ) + + +#define _get_days_of_month( _y, _m ) \ + days_of_month[ _is_leap_year( _y ) ][_m] + + + +#if !defined( MBG_TGT_KERNEL ) + +/** + * @brief Data type used for intermediate results on 32 bit multiplications + * + * We need 64 bits for intermediate integer results to avoid a range overflow + * from 32 x 32 bit multiplications. On systems which don't support 64 bit types + * we use the "double" type as a workaround. + */ +#if defined( MBG_TGT_MISSING_64_BIT_TYPES ) + #define MBG_FRAC32_CONVERSION_TYPE double +#else + #define MBG_FRAC32_CONVERSION_TYPE int64_t +#endif + +/** + * @brief Constant used to convert e.g. ::PCPS_TIME_STAMP::frac values + * + * Max value of ::PCPS_TIME_STAMP::frac + 1, used for scaling + */ +#define MBG_FRAC32_UNITS_PER_SEC ( (MBG_FRAC32_CONVERSION_TYPE) 4294967296.0 ) // == 0x100000000 + + + +/** + * @brief Convert a 16 bit binary fraction to a scaled decimal + * + * @param[in] bin The binary fraction + * @param[in] scale The scale factor + * + * @return The calculated number + * + * @see ::dec_frac_to_bin_frac_16 + * @see ::dec_frac_to_bin_frac_32 + * @see ::bin_frac_32_to_dec_frac + * @see ::frac_sec_from_bin + */ +static __mbg_inline +uint32_t bin_frac_16_to_dec_frac( uint16_t bin, uint32_t scale ) +{ + return (uint32_t) ( (MBG_FRAC32_CONVERSION_TYPE) bin * scale + / 0x10000UL ); + +} // bin_frac_16_to_dec_frac + + + +/** + * @brief Convert a 32 bit binary fraction to a scaled decimal + * + * @param[in] bin The binary fraction + * @param[in] scale The scale factor + * + * @return The calculated number + * + * @see ::dec_frac_to_bin_frac_32 + * @see ::dec_frac_to_bin_frac_16 + * @see ::bin_frac_16_to_dec_frac + */ +static __mbg_inline +uint32_t bin_frac_32_to_dec_frac( uint32_t bin, uint32_t scale ) +{ + return (uint32_t) ( (MBG_FRAC32_CONVERSION_TYPE) bin * scale + / MBG_FRAC32_UNITS_PER_SEC ); + +} // bin_frac_32_to_dec_frac + + + +#if !defined( MBG_TGT_MISSING_64_BIT_TYPES ) + +// On targets which don't provide 64 bit data types +// MBG_FRAC32_CONVERSION_TYPE is defined as double, +// in which case the ">> 1" operation in the 2 functions +// below yields an "invalid use of floating point" error. +// This could probably be fixed by a different way of +// casting, at least for a partial expression. + +static __mbg_inline +uint16_t dec_frac_to_bin_frac_16( uint32_t dec, uint32_t scale ) +{ + return (uint16_t) ( ( ( (MBG_FRAC32_CONVERSION_TYPE) dec * 0x20000 / scale ) + 1 ) >> 1 ); + +} // dec_frac_to_bin_frac_16 + + +static __mbg_inline +uint32_t dec_frac_to_bin_frac_32( uint32_t dec, uint32_t scale ) +{ + return (uint32_t) ( ( ( (MBG_FRAC32_CONVERSION_TYPE) dec * MBG_FRAC32_UNITS_PER_SEC * 2 / scale ) + 1 ) >> 1 ); + +} // dec_frac_to_bin_frac_32 + +#endif // !defined( MBG_TGT_MISSING_64_BIT_TYPES ) + + + +#define bin_frac_32_to_msec( _bin ) bin_frac_32_to_dec_frac( (_bin), 1000L ) +#define bin_frac_32_to_usec( _bin ) bin_frac_32_to_dec_frac( (_bin), 1000000L ) +#define bin_frac_32_to_nsec( _bin ) bin_frac_32_to_dec_frac( (_bin), 1000000000L ) +#define bin_frac_16_to_msec( _bin ) bin_frac_16_to_dec_frac( (_bin), 1000L ) +#define bin_frac_16_to_usec( _bin ) bin_frac_16_to_dec_frac( (_bin), 1000000L ) +#define bin_frac_16_to_nsec( _bin ) bin_frac_16_to_dec_frac( (_bin), 1000000000L ) + + +#define msec_to_bin_frac_32( _msec ) dec_frac_to_bin_frac_32( (_msec), 1000L ) +#define usec_to_bin_frac_32( _usec ) dec_frac_to_bin_frac_32( (_usec), 1000000L ) +#define nsec_to_bin_frac_32( _nsec ) dec_frac_to_bin_frac_32( (_nsec), 1000000000L ) +#define msec_to_bin_frac_16( _msec ) dec_frac_to_bin_frac_16( (_msec), 1000L ) +#define usec_to_bin_frac_16( _usec ) dec_frac_to_bin_frac_16( (_usec), 1000000L ) +#define nsec_to_bin_frac_16( _nsec ) dec_frac_to_bin_frac_16( (_nsec), 1000000000L ) + + + +/** + * @brief Convert a binary fraction to a scaled decimal + * + * Convert a binary fraction (e.g. of a second, as in ::PCPS_TIME_STAMP::frac) + * to a decimal fraction, using a specified scale factor. + * + * @deprecated This function is deprecated, use ::bin_frac_32_to_dec_frac preferably. + * + * @param[in] b The binary fraction + * @param[in] scale The scale factor + * + * @return The calculated number + * + * @see ::bin_frac_32_to_dec_frac + */ +static __mbg_inline +uint32_t _DEPRECATED_BY( "bin_frac_32_to_dec_frac" ) frac_sec_from_bin( uint32_t b, uint32_t scale ) +{ + return bin_frac_32_to_dec_frac( b, scale ); + +} // frac_sec_from_bin + + + +/** + * @brief Convert a binary fraction to "double" fractions + * + * Convert a binary fraction (e.g. of a second, as in ::PCPS_TIME_STAMP::frac) + * to a "double" with the units of seconds.<br> + * E.g. a 0xFFFFFFFF fraction yields 0.9999999999.... + * + * @note Excluded from build for kernel drivers which usually + * don't support floating point operations. + * + * @param[in] b The binary fraction + * + * @return The calculated fraction + * + * @see ::MBG_FRAC32_UNITS_PER_SEC + */ +static __mbg_inline +double dfrac_sec_from_bin( uint32_t b ) +{ + return (double) b / (double) MBG_FRAC32_UNITS_PER_SEC; + +} // dfrac_sec_from_bin + +#endif // !defined( MBG_TGT_KERNEL ) + + + /* ----- function prototypes begin ----- */ /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ + /** + * @brief Set a timeout object to specified interval + * + * @param[out] t The timeout object + * @param[in] clk The current time, in clock_t ticks + * @param[in] interval The interval until expiration, in clock_t ticks + */ void set_timeout( TIMEOUT *t, clock_t clk, clock_t interval ) ; + + /** + * @brief Stretch a timeout specified in given timeout object + * + * @param[in,out] t The timeout object + * @param[in] interval The interval until expiration, in clock_t ticks + */ void stretch_timeout( TIMEOUT *t, clock_t interval ) ; + + /** + * @brief Check if a timeout object has expired + * + * @param[in] t The timeout object + * @param[in] clk The current time, in clock_t ticks + * + * @return 1 if timeout expired, else 0 + */ bit check_timeout( TIMEOUT *t, clock_t clk ) ; - int err_tm( TM_GPS *tm ) ; + + /** + * @brief Check if a ::TM_GPS structure contains a valid date and time + * + * @param[in] tm The date/time structure to be checked + * + * @return 0 if date/time is valid, else a negative number indicating + * which field was found invalid + */ + int err_tm( const TM_GPS *tm ) ; + + /** + * @brief Set the time in a ::TM_GPS structure to 00:00:00.000 + * + * @param[in,out] tm The date/time structure to be set + * + * @return Pointer to the ::TM_GPS structure that has been passed + */ TM_GPS *clear_time( TM_GPS *tm ) ; + + /** + * @brief Convert second-of-week to day-of-week and time-of-day + * + * @param[in] wsec The second-of-week number to be converted + * @param[out] tm Address of a ::TM_GPS structure which takes the computed results + * + * @return Pointer to the ::TM_GPS structure that has been passed + * + * @see ::tm_to_wsec + */ TM_GPS *wsec_to_tm( long wsec, TM_GPS *tm ) ; - long tm_to_wsec( TM_GPS *tm ) ; + + /** + * @brief Compute second-of-week from day-of-week and time-of-day + * + * @todo Specify input / output ranges + * + * @param[in] tm Address of a ::TM_GPS structure providing day-of-week and time-of-day + * + * @return The computed second-of-week number + * + * @see ::wsec_to_tm + */ + long tm_to_wsec( const TM_GPS *tm ) ; + + /** + * @brief Check if a specific year is a leap year + * + * @param[in] y The full year number + * + * @return != 0 if the year is a leap year, else 0 + */ int is_leap_year( int y ) ; + + /** + * @brief Compute the day-of-year from a given date + * + * @param[in] day The day-of-month + * @param[in] month The month + * @param[in] year The full year number + * + * @return The computed day-of-year + */ int day_of_year( int day, int month, int year ) ; + + /** + * @brief Compute a date from a given year and day-of-year + * + * @param[in] year The full year number + * @param[in] day_num Number of days from the beginning of that year, may be negative + * @param[out] tm Address of a ::TM_GPS structure which takes the computed results + */ void date_of_year ( int year, int day_num, TM_GPS *tm ) ; + + /** + * @brief Compute day-of-week from a given date + * + * @todo Specify range of returned day-of-week. Should we just call n_days()? + * + * @param[in] day The day-of-month + * @param[in] month The month + * @param[in] year The full year number + * + * @return The computed day-of-week + * + * @see ::n_days + */ int day_of_week( int day, int month, int year ) ; + + /** + * @brief Update a year number by a number of days, accounting for leap years + * + * @param[in] day_num The number of days to evaluate + * @param[in] year The year number to start with + * + * @return The computed year number + */ int days_to_years( long *day_num, int year ) ; + + /** + * @brief Compute number of days after Jan 1, 0000 for a given date + * + * @param[in] mday The day-of-month + * @param[in] month The month + * @param[in] year The full year number + * + * @return The computed number of days + * + * @see ::day_of_week + */ long n_days( ushort mday, ushort month, ushort year ) ; - double nano_time_to_double( const NANO_TIME *p ) ; - void double_to_nano_time( NANO_TIME *p, double d ) ; + + /** + * @brief Print time with hours, minutes, seconds to a string + * + * @param[out] s Address of a string buffer to be filled + * @param[in] tm Address of a ::TM_GPS structure providing date and time + */ int sprint_time( char *s, const TM_GPS *tm ) ; - int sprint_short_time( char *s, TM_GPS *time ) ; + + /** + * @brief Print time with hours, minutes to a string + * + * @param[out] s Address of a string buffer to be filled + * @param[in] tm Address of a ::TM_GPS structure providing date and time + */ + int sprint_short_time( char *s, const TM_GPS *tm ) ; + + /** + * @brief Print date to a string + * + * @param[out] s Address of a string buffer to be filled + * @param[in] tm Address of a ::TM_GPS structure providing date and time + */ int sprint_date( char *s, const TM_GPS *tm ) ; + + /** + * @brief Print day-of-week and date to a string + * + * @param[out] s Address of a string buffer to be filled + * @param[in] tm Address of a ::TM_GPS structure providing date and time + */ int sprint_day_date( char *s, const TM_GPS *tm ) ; + + /** + * @brief Print day-of-week, date and time to a string + * + * @param[out] s Address of a string buffer to be filled + * @param[in] tm Address of a ::TM_GPS structure providing date and time + */ int sprint_tm( char *s, const TM_GPS *tm ) ; - void sscan_time( char *s, TM_GPS *tm ) ; + + /** + * @brief Extract a time from a string + * + * @param[in] s A time string in format hh:mm:ss + * @param[out] tm Address of a ::TM_GPS structure which takes the extracted time + */ + void sscan_time( const char *s, TM_GPS *tm ) ; + + /** + * @brief Extract a date from a string + * + * @param[in] s A date string in format dd.mm. or dd.mm.yyyy + * @param[out] tm Address of a ::TM_GPS structure which takes the extracted date + */ void sscan_date( char *s, TM_GPS *tm ) ; + /* ----- function prototypes end ----- */ @@ -318,6 +717,7 @@ _ext char days_of_month[2][12] #undef _ext +#undef _DO_INIT #ifdef __cplusplus } diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.c b/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.c index 1a4156e..e588485 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.c +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgutil.c 1.5.2.1 2010/07/15 13:06:59 martin TEST $ + * $Id: mbgutil.c 1.7 2017/07/05 16:40:35 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,7 +10,17 @@ * * ----------------------------------------------------------------------- * $Log: mbgutil.c $ - * Revision 1.5.2.1 2010/07/15 13:06:59 martin + * Revision 1.7 2017/07/05 16:40:35 martin + * Use functions from new module timeutil. + * Use safe string functions from str_util.c. + * Quieted some compiler warninges. + * Account for frac_sec_from_bin() obsoleted by bin_frac_32_to_dec_frac(). + * Account for renamed library symbols. + * Added doxygen comments. + * Revision 1.6 2012/10/15 13:12:17 martin + * Fixed build under DOS. + * Fixed format/type mismatch when printing UTC offset. + * Fixed generation of firmware and ASIC version string. * Revision 1.5 2009/03/19 09:09:55Z daniel * Fixed ambiguous syntax in mbg_str_dev_name(). * Support TAI and GPS time scales in mbg_str_pcps_hr_tstamp_loc(). @@ -32,13 +42,17 @@ #include <mbgutil.h> #undef _MBGUTIL +#include <cfg_hlp.h> +#include <mbgerror.h> #include <pcpsutil.h> -#include <pcpslstr.h> -//#include <gpsutils.h> +#include <charcode.h> #include <pcpsdev.h> +#include <str_util.h> +#include <qsdefs.h> #include <stdio.h> #include <time.h> +#include <limits.h> // required at least for Linux: #include <stdarg.h> @@ -58,32 +72,18 @@ static int mbg_date_time_dist = 2; static int mbg_pos_dist = 2; static uint16_t mbg_year_lim = 1980; - - -#if defined( MBG_TGT_WIN32 ) - #define mbg_vsnprintf _vsnprintf -#else - #define mbg_vsnprintf vsnprintf -#endif - - -#if defined( MBG_TGT_DOS ) - -static /*HDR*/ -int vsnprintf( char *s, int max_len, const char *fmt, va_list arg_list ) -{ - return vsprintf( s, fmt, arg_list ); - -} // vsnprintf - -#endif +static const char str_inv_cnv[] = "(invalid conversion)"; /*HDR*/ +/** + * @brief Get the DLL/shared library's version code + * + * @return The version code at which the library was built + */ _MBG_API_ATTR int _MBG_API mbgutil_get_version( void ) { - return MBGUTIL_VERSION; } // mbgutil_get_version @@ -91,70 +91,99 @@ _MBG_API_ATTR int _MBG_API mbgutil_get_version( void ) /*HDR*/ +/** + * @brief Check the DLL/shared library's compatibility + * + * @param[in] header_version Version code defined in the header file when the application is built + * + * @return ::MBG_SUCCESS if compatible, else ::MBG_ERR_LIB_NOT_COMPATIBLE + */ _MBG_API_ATTR int _MBG_API mbgutil_check_version( int header_version ) { if ( header_version >= MBGUTIL_COMPAT_VERSION ) - return PCPS_SUCCESS; + return MBG_SUCCESS; - return -1; + return MBG_ERR_LIB_NOT_COMPATIBLE; } // mbgutil_check_version -// We have our own version of snprintf() since under Windows -// _snprintf(), returns -1 and does not write a terminating 0 -// if the output exceeds the buffer size. -// -// This function terminates the output string properly. However, -// the maximum return value is (max_len - 1), so the function -// can not be used to determine the buffer size that would be -// required for an untruncated string. - /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_snprintf( char *s, size_t max_len, const char * fmt, ... ) +/** + * @brief A portable, safe implementation of snprintf() + * + * The output string buffer is in any case properly terminated by 0. + * For a detailed description see ::vsnprintf_safe + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] fmt Format string according to subsequent parameters + * @param[in] ... Variable argument list according to the format string + * + * @return the number of characters written to the output buffer, except the terminating 0 + * + * @see ::vsnprintf_safe + * @see ::snprintf_safe + */ +_MBG_API_ATTR int __attribute__( ( format( printf, 3, 4 ) ) ) +_MBG_API mbg_snprintf( char *s, size_t max_len, const char * fmt, ... ) { - int n; - + size_t n; va_list ap; - va_start( ap, fmt ); - - n = mbg_vsnprintf( s, max_len, fmt, ap ); - - va_end( ap ); - - - #if defined( MBG_TGT_WIN32 ) + // TODO: size_t can be larger than int, so what happens if + // a very long string is written to the buffer and the number + // of bytes written exceeds MAXINT, in which case the number + // can't be returned? - // Terminate the output string properly under Windows. - // For other targets assume the POSIX version is available. - if ( n < 0 || n >= (int) max_len ) - { - n = max_len - 1; - s[n] = 0; - } + va_start( ap, fmt ); - #endif + n = vsnprintf_safe( s, max_len, fmt, ap ); + va_end( ap ); - return n; + return _int_from_size_t( n ); } // mbg_snprintf /*HDR*/ +/** + * @brief A portable, safe implementation of strncpy() + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the destination string buffer + * @param[in] max_len Size of the destination string buffer + * @param[in] src Pointer to the source string buffer + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_strncpy( char *s, size_t max_len, const char *src ) { - //##++ This could be coded more efficiently - return mbg_snprintf( s, max_len, "%s", src ); + size_t n = sn_cpy_str_safe( s, max_len, src ); + + return _int_from_size_t( n ); } // mbg_strncpy /*HDR*/ +/** + * @brief Write a character multiple times to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] c The character to write to the output buffer + * @param[in] n The number of characters to write to the output buffer + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_strchar( char *s, size_t max_len, char c, size_t n ) { size_t i; @@ -166,251 +195,542 @@ _MBG_API_ATTR int _MBG_API mbg_strchar( char *s, size_t max_len, char c, size_t if ( i >= max_len ) break; + if ( i >= ( INT_MAX - 1 ) ) + break; + s[i] = c; } s[i] = 0; - return i; + return (int) i; } // mbg_strchar /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_date_short( char *s, int max_len, +/** + * @brief Write a short date string "dd.mm." to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] mday Day-of-month number, 1..31 + * @param[in] month Month number, 1..12 + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_date_short( char *s, int max_len, int mday, int month ) { - return mbg_snprintf( s, max_len, "%02u.%02u.", mday, month ); - + size_t n = snprintf_safe( s, max_len, "%02u.%02u.", mday, month ); + + return _int_from_size_t( n ); + } // mbg_str_date_short /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_date( char *s, int max_len, +/** + * @brief Write a date string "dd.mm.yyyy" to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] mday Day-of-month number, 1..31 + * @param[in] month Month number, 1..12 + * @param[in] year Year number + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_date( char *s, int max_len, int mday, int month, int year ) { - int n = mbg_str_date_short( s, max_len, mday, month ); - n += mbg_snprintf( s + n, max_len - n, "%04u", - ( year < 256 ) ? - pcps_exp_year( (uint8_t) year, mbg_year_lim ) : - year - ); - return n; + size_t n = mbg_str_date_short( s, max_len, mday, month ); + + n += snprintf_safe( &s[n], max_len - n, "%04u", + ( year < 256 ) ? + pcps_exp_year( (uint8_t) year, mbg_year_lim ) : + year ); + + return _int_from_size_t( n ); } // mbg_str_date /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_time_short( char *s, int max_len, +/** + * @brief Write a short time string "hh:mm" to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] hour Hours number, 0..23 + * @param[in] min Minutes number, 0..59 + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_time_short( char *s, int max_len, int hour, int min ) { - return mbg_snprintf( s, max_len, "%2u:%02u", hour, min ); + size_t n = snprintf_safe( s, max_len, "%2u:%02u", hour, min ); + + return _int_from_size_t( n ); } // mbg_str_time_short /*HDR*/ +/** + * @brief Write a time string "hh:mm:ss" to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] hour Hours number, 0..23 + * @param[in] min Minutes number, 0..59 + * @param[in] sec Seconds number, 0..59, or 60 in case of leap second + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_time( char *s, int max_len, int hour, int min, int sec ) { - int n = mbg_str_time_short( s, max_len, hour, min ); + size_t n = mbg_str_time_short( s, max_len, hour, min ); - n += mbg_snprintf( s + n, max_len - n, ":%02u", sec ); + n += snprintf_safe( &s[n], max_len - n, ":%02u", sec ); - return n; + return _int_from_size_t( n ); } // mbg_str_time /*HDR*/ +/** + * @brief Write a long time string "hh:mm:ss.cc" to a string buffer + * + * Include 100ths of seconds. + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] hour Hours number, 0..23 + * @param[in] min Minutes number, 0..59 + * @param[in] sec Seconds number, 0..59, or 60 in case of leap second + * @param[in] sec100 Hundreths of seconds, 0..99 + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_time_long( char *s, int max_len, int hour, int min, int sec, int sec100 ) { - int n = mbg_str_time( s, max_len, hour, min, sec ); + size_t n = mbg_str_time( s, max_len, hour, min, sec ); - n += mbg_snprintf( s + n, max_len - n, ".%02u", sec100 ); + n += snprintf_safe( &s[n], max_len - n, ".%02u", sec100 ); - return n; + return _int_from_size_t( n ); } // mbg_str_time_long /*HDR*/ +/** + * @brief Write a full date and time string to a string buffer + * + * The number of space characters between date and time + * is determined by the global variable ::mbg_date_time_dist. + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::TM_GPS structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_tm_gps_date_time( char *s, int max_len, const TM_GPS *pt ) { - int n = mbg_str_date( s, max_len, pt->mday, pt->month, pt->year ); - n += mbg_strchar( s + n, max_len - n, ' ', mbg_date_time_dist ); - n += mbg_str_time( s + n, max_len - n, pt->hour, pt->min, pt->sec ); + size_t n = mbg_str_date( s, max_len, pt->mday, pt->month, pt->year ); + n += mbg_strchar( &s[n], max_len - n, ' ', mbg_date_time_dist ); + n += mbg_str_time( &s[n], max_len - _int_from_size_t( n ), pt->hour, pt->min, pt->sec ); - return n; + return _int_from_size_t( n ); } // mbg_str_tm_gps_date_time /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_date_short( char *s, int max_len, +/** + * @brief Write the short date given as ::PCPS_TIME structure to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_date_short( char *s, int max_len, const PCPS_TIME *pt ) { - return mbg_str_date_short( s, max_len, pt->mday, pt->month ); + size_t n = mbg_str_date_short( s, max_len, pt->mday, pt->month ); + + return _int_from_size_t( n ); } // mbg_str_pcps_date_short /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_date( char *s, int max_len, +/** + * @brief Write the date given as ::PCPS_TIME structure to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_date( char *s, int max_len, const PCPS_TIME *pt ) { - return mbg_str_date( s, max_len, pt->mday, pt->month, pt->year ); + size_t n = mbg_str_date( s, max_len, pt->mday, pt->month, pt->year ); + + return _int_from_size_t( n ); } // mbg_str_pcps_date /*HDR*/ +/** + * @brief Write the short time given as ::PCPS_TIME structure to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_pcps_time_short( char *s, int max_len, const PCPS_TIME *pt ) { - return mbg_str_time_short( s, max_len, pt->hour, pt->min ); + size_t n = mbg_str_time_short( s, max_len, pt->hour, pt->min ); + + return _int_from_size_t( n ); } // mbg_str_pcps_time_short /*HDR*/ +/** + * @brief Write the time given as ::PCPS_TIME structure to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_pcps_time( char *s, int max_len, const PCPS_TIME *pt ) { - return mbg_str_time( s, max_len, pt->hour, pt->min, pt->sec ); + size_t n = mbg_str_time( s, max_len, pt->hour, pt->min, pt->sec ); + + return _int_from_size_t( n ); } // mbg_str_pcps_time /*HDR*/ +/** + * @brief Write the time including sec100ths given as ::PCPS_TIME structure to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_pcps_time_long( char *s, int max_len, const PCPS_TIME *pt ) { - return mbg_str_time_long( s, max_len, pt->hour, pt->min, pt->sec, pt->sec100 ); + size_t n = mbg_str_time_long( s, max_len, pt->hour, pt->min, pt->sec, pt->sec100 ); + + return _int_from_size_t( n ); } // mbg_str_pcps_time_long /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_date_time( char *s, int max_len, - const PCPS_TIME *pt, +/** + * @brief Write date and time given as ::PCPS_TIME structure to a string buffer + * + * The number of space characters between date and time + * is determined by the global variable ::mbg_date_time_dist. + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_TIME structure providing date and time + * @param[in] tz_str Optional time zone string to be appended, currently not used, may be NULL + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_date_time( char *s, int max_len, + const PCPS_TIME *pt, const char *tz_str ) { - int n = mbg_str_pcps_date( s, max_len, pt ); - n += mbg_strchar( s + n, max_len - n, ' ', mbg_date_time_dist ); - n += mbg_str_pcps_time( s + n, max_len - n, pt ); + size_t n = mbg_str_pcps_date( s, max_len, pt ); + n += mbg_strchar( &s[n], max_len - n, ' ', mbg_date_time_dist ); + n += mbg_str_pcps_time( &s[n], max_len - _int_from_size_t( n ), pt ); + // FIXME Use tz_str ? + + return _int_from_size_t( n ); - return n; - } // mbg_str_pcps_date_time /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date( char *s, int max_len, +/** + * @brief Write date derived from seconds-since-epoch to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] sec Number of seconds since the epoch to be converted to date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date( char *s, int max_len, uint32_t sec ) { - time_t t = sec; - struct tm tm = *gmtime( &t ); - return mbg_str_date( s, max_len, tm.tm_mday, tm.tm_mon + 1, tm.tm_year ); + struct tm tm = { 0 }; + time_t t = cvt_to_time_t( sec ); + int rc = mbg_gmtime( &tm, &t ); + + return mbg_rc_is_success( rc ) ? + mbg_str_date( s, max_len, tm.tm_mday, tm.tm_mon + 1, tm.tm_year ) : + sn_cpy_str_safe( s, max_len, str_inv_cnv ); } // mbg_str_pcps_hr_date /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time( char *s, int max_len, +/** + * @brief Write time derived from seconds-since-epoch to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] sec Number of seconds since the epoch to be converted to date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time( char *s, int max_len, uint32_t sec ) { - time_t t = sec; - struct tm tm = *gmtime( &t ); - return mbg_str_time( s, max_len, tm.tm_hour, tm.tm_min, tm.tm_sec ); + struct tm tm = { 0 }; + time_t t = cvt_to_time_t( sec ); + int rc = mbg_gmtime( &tm, &t ); + + return mbg_rc_is_success( rc ) ? + mbg_str_time( s, max_len, tm.tm_hour, tm.tm_min, tm.tm_sec ) : + sn_cpy_str_safe( s, max_len, str_inv_cnv ); } // mbg_str_pcps_hr_time +static /*HDR*/ +/* (explicitly excluded from Doxygen) + * @brief Write UTC date and time given as ::PCPS_HR_TIME structure to a string buffer + * + * The number of space characters between date and time + * is determined by the global variable ::mbg_date_time_dist. + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] p_t Pointer to a time_t variable providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +int do_str_pcps_hr_date_time( char *s, int max_len, const time_t *p_t ) +{ + struct tm tm = { 0 }; + int n = 0; + int rc = mbg_gmtime( &tm, p_t ); + + if ( mbg_rc_is_success( rc ) ) + { + n = mbg_str_date( s, max_len, tm.tm_mday , tm.tm_mon + 1, tm.tm_year ); + n += mbg_strchar( &s[n], max_len - n, ' ', mbg_date_time_dist ); + n += mbg_str_time( &s[n], max_len - n, tm.tm_hour, tm.tm_min, tm.tm_sec ); + } + else + n = sn_cpy_str_safe( s, max_len, str_inv_cnv ); + + return n; + +} // do_str_pcps_hr_date_time + + + /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_utc( char *s, int max_len, +/** + * @brief Write UTC date and time given as ::PCPS_HR_TIME structure to a string buffer + * + * The number of space characters between date and time + * is determined by the global variable ::mbg_date_time_dist. + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_utc( char *s, int max_len, const PCPS_HR_TIME *pt ) { - time_t t = pt->tstamp.sec; - struct tm tm = *gmtime( &t ); - int n = mbg_str_date( s, max_len, tm.tm_mday , tm.tm_mon + 1, tm.tm_year ); - n += mbg_strchar( s + n, max_len - n, ' ', mbg_date_time_dist ); - n += mbg_str_time( s + n, max_len - n, tm.tm_hour, tm.tm_min, tm.tm_sec ); + time_t t = cvt_to_time_t( pt->tstamp.sec ); - return n; + return do_str_pcps_hr_date_time( s, max_len, &t ); } // mbg_str_pcps_hr_date_time_utc /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_loc( char *s, int max_len, +/** + * @brief Write local date and time given as ::PCPS_HR_TIME structure to a string buffer + * + * The number of space characters between date and time + * is determined by the global variable ::mbg_date_time_dist. + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_loc( char *s, int max_len, const PCPS_HR_TIME *pt ) { - time_t t = pt->tstamp.sec + pt->utc_offs; - struct tm tm = *gmtime( &t ); - int n = mbg_str_date( s, max_len, tm.tm_mday , tm.tm_mon + 1, tm.tm_year ); - n += mbg_strchar( s + n, max_len - n, ' ', mbg_date_time_dist ); - n += mbg_str_time( s + n, max_len - n, tm.tm_hour, tm.tm_min, tm.tm_sec ); + long l = (long) pt->tstamp.sec + pt->utc_offs; + time_t t = cvt_to_time_t( l ); - return n; + return do_str_pcps_hr_date_time( s, max_len, &t ); } // mbg_str_pcps_hr_date_time_loc /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_frac( char *s, int max_len, +/** + * @brief Print binary ::PCPS_FRAC_32 fractions in decimal to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] frac Binary fractions of a second in ::PCPS_FRAC_32 format + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_frac( char *s, int max_len, uint32_t frac ) { - return mbg_snprintf( s, max_len, PCPS_HRT_FRAC_SCALE_FMT, - frac_sec_from_bin( frac, PCPS_HRT_FRAC_SCALE ) ); + size_t n = snprintf_safe( s, max_len, PCPS_HRT_FRAC_SCALE_FMT, + (ulong) bin_frac_32_to_dec_frac( frac, PCPS_HRT_FRAC_SCALE ) ); + return _int_from_size_t( n ); } // mbg_str_pcps_hr_time_frac /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_offs( char *s, int max_len, +/** + * @brief Print the UTC offset from a ::PCPS_HR_TIME structure to a string buffer + * + * The output format is sign - hours - minutes, e.g. "+01:45h". + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date, and UTC offset + * @param[in] info An informational text to be prepended + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_offs( char *s, int max_len, const PCPS_HR_TIME *pt, const char *info ) { - int n = mbg_snprintf( s, max_len, "%s", info ); + size_t n = snprintf_safe( s, max_len, "%s", info ); if ( pt->utc_offs ) { ldiv_t ldt = ldiv( labs( pt->utc_offs ) / 60, 60 ); - n += mbg_snprintf( s + n, max_len - n, "%c%02u:%02uh", - ( pt->utc_offs < 0 ) ? '-' : '+', - ldt.quot, ldt.rem ); + n += snprintf_safe( &s[n], max_len - n, "%c%02lu:%02luh", + ( pt->utc_offs < 0 ) ? '-' : '+', + ldt.quot, ldt.rem ); } - return n; + return _int_from_size_t( n ); } // mbg_str_pcps_hr_time_offs /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_utc( char *s, int max_len, +/** + * @brief Write a high resolution UTC time stamp including fractions to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_utc( char *s, int max_len, const PCPS_HR_TIME *pt ) { int n = mbg_str_pcps_hr_date_time_utc( s, max_len, pt ); @@ -418,7 +738,7 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_utc( char *s, int max_len, if ( n < ( max_len - 1 ) ) { s[n++] = '.'; - n += mbg_str_pcps_hr_time_frac( s + n, max_len - n, pt->tstamp.frac ); + n += mbg_str_pcps_hr_time_frac( &s[n], max_len - n, pt->tstamp.frac ); } return n; @@ -428,7 +748,18 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_utc( char *s, int max_len, /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, +/** + * @brief Write a high resolution local time stamp including fractions to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, const PCPS_HR_TIME *pt ) { int n = mbg_str_pcps_hr_date_time_loc( s, max_len, pt ); @@ -436,7 +767,7 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, if ( n < ( max_len - 1 ) ) { s[n++] = '.'; - n += mbg_str_pcps_hr_time_frac( s + n, max_len - n, pt->tstamp.frac ); + n += mbg_str_pcps_hr_time_frac( &s[n], max_len - n, pt->tstamp.frac ); } if ( n < ( max_len - 1 ) ) @@ -450,7 +781,7 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, cp = "GPS"; s[n++] = ' '; - n += mbg_str_pcps_hr_time_offs( s + n, max_len - n, pt, cp ); + n += mbg_str_pcps_hr_time_offs( &s[n], max_len - n, pt, cp ); } return n; @@ -460,69 +791,138 @@ _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_tstamp_raw( char *s, int max_len, +/** + * @brief Write a raw high resolution time stamp to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_tstamp_raw( char *s, int max_len, const PCPS_TIME_STAMP *pt ) { - return mbg_snprintf( s, max_len, "%08lX.%08lX", pt->sec, pt->frac ); + size_t n = snprintf_safe( s, max_len, "%08lX.%08lX", (ulong) pt->sec, (ulong) pt->frac ); + return _int_from_size_t( n ); } // mbg_str_pcps_tstamp_raw /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_raw( char *s, int max_len, +/** + * @brief Write a raw high resolution time stamp plus converted local time to a string buffer + * + * The output string also has the time status code appended as hex number. + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_raw( char *s, int max_len, const PCPS_HR_TIME *pt ) { - int n = mbg_str_pcps_tstamp_raw( s, max_len, &pt->tstamp ); - n += mbg_str_pcps_hr_time_offs( s + n, max_len - n, pt, ", Loc: " ); - n += mbg_snprintf( s + n, max_len - n, ", st: 0x%04X", pt->status ); + size_t n = mbg_str_pcps_tstamp_raw( s, max_len, &pt->tstamp ); + n += mbg_str_pcps_hr_time_offs( &s[n], max_len - _int_from_size_t( n ), pt, ", Loc: " ); + n += snprintf_safe( &s[n], max_len - n, ", st: 0x%04X", pt->status ); + + return _int_from_size_t( n ); - return n; - } // mbg_str_pcps_hr_time_raw /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_ucap( char *s, int max_len, +/** + * @brief Write time capture / user capture time stamp to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure containing a user capture event + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_ucap( char *s, int max_len, const PCPS_HR_TIME *pt ) { - int n = mbg_snprintf( s, max_len, "CAP%u: ", pt->signal ); - n += mbg_str_pcps_hr_tstamp_loc( s + n, max_len - n, pt ); + size_t n = snprintf_safe( s, max_len, "CAP%u: ", pt->signal ); + n += mbg_str_pcps_hr_tstamp_loc( &s[n], max_len - _int_from_size_t( n ), pt ); + + return _int_from_size_t( n ); - return n; - } // mbg_str_ucap /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pos_dms( char *s, int max_len, +/** + * @brief Write a geographic coordinate in degrees - minutes - seconds to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pdms Pointer to a ::DMS structure containing the coordinate + * @param[in] prec Number of digits of the geographic seconds after the decimal separator + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pos_dms( char *s, int max_len, const DMS *pdms, int prec ) { - return mbg_snprintf( s, max_len, "%c %i" DEG "%02i'%02.*f\"", - pdms->prefix, - pdms->deg, - pdms->min, - prec, - pdms->sec - ); + size_t n = snprintf_safe( s, max_len, "%c %i" DEG "%02i'%02.*f\"", + pdms->prefix, pdms->deg, pdms->min, + prec, pdms->sec ); + return _int_from_size_t( n ); } // mbg_str_pos_dms /*HDR*/ +/** + * @brief Write a position's altitude parameter to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] alt The altitude parameter, in meters + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_pos_alt( char *s, int max_len, double alt ) { - return mbg_snprintf( s, max_len, "%.0fm", alt ); + size_t n = snprintf_safe( s, max_len, "%.0fm", alt ); + return _int_from_size_t( n ); } // mbg_str_pos_alt /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_pos( char *s, int max_len, +/** + * @brief Write geographic coordinates to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] ppos Pointer to a ::POS structure containing the coordinates + * @param[in] prec Number of digits of the geographic seconds after the decimal separator + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_pos( char *s, int max_len, const POS *ppos, int prec ) { int n; @@ -530,15 +930,15 @@ _MBG_API_ATTR int _MBG_API mbg_str_pos( char *s, int max_len, if ( ppos->lla[LON] || ppos->lla[LAT] || ppos->lla[ALT] ) { n = mbg_str_pos_dms( s, max_len, &ppos->latitude, prec ); - n += mbg_strchar( s + n, max_len - n, ',', 1 ); - n += mbg_strchar( s + n, max_len - n, ' ', mbg_pos_dist ); - n += mbg_str_pos_dms( s + n, max_len - n, &ppos->longitude, prec ); - n += mbg_strchar( s + n, max_len - n, ',', 1 ); - n += mbg_strchar( s + n, max_len - n, ' ', mbg_pos_dist ); - n += mbg_str_pos_alt( s + n, max_len - n, ppos->lla[ALT] ); + n += mbg_strchar( &s[n], max_len - n, ',', 1 ); + n += mbg_strchar( &s[n], max_len - n, ' ', mbg_pos_dist ); + n += mbg_str_pos_dms( &s[n], max_len - n, &ppos->longitude, prec ); + n += mbg_strchar( &s[n], max_len - n, ',', 1 ); + n += mbg_strchar( &s[n], max_len - n, ' ', mbg_pos_dist ); + n += mbg_str_pos_alt( &s[n], max_len - n, ppos->lla[ALT] ); } else - n = mbg_strncpy( s, max_len, "N/A" ); + n = mbg_strncpy( s, max_len, str_not_avail ); return n; @@ -547,53 +947,94 @@ _MBG_API_ATTR int _MBG_API mbg_str_pos( char *s, int max_len, /*HDR*/ -_MBG_API_ATTR int _MBG_API mbg_str_dev_name( char *s, int max_len, const char *short_name, - uint16_t fw_rev_num, PCI_ASIC_VERSION asic_version_num ) +/** + * @brief Write device info to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] short_name Short device name, e.g. in ::MBG_DEV_NAME format + * @param[in] fw_rev_num The firmware revision number + * @param[in] asic_ver_num The ASIC version number + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ +_MBG_API_ATTR int _MBG_API mbg_str_dev_name( char *s, int max_len, const char *short_name, + uint16_t fw_rev_num, PCI_ASIC_VERSION asic_ver_num ) { - #define HW_NAME_SZ PCPS_CLOCK_NAME_SZ+PCPS_SN_SIZE+1 - - char model_code[HW_NAME_SZ]; - PCPS_SN_STR sernum; + MBG_DEV_NAME dev_name = { 0 }; + PCPS_SN_STR sernum = { 0 }; unsigned int i = 0; - int n = 0; + size_t n = 0; + size_t l = strlen( short_name ); - memset( model_code, 0, sizeof( model_code ) ); - memset( sernum, 0, sizeof( sernum ) ); - - if ( strlen( short_name ) > 0 ) + if ( l > 0 ) { - if ( strstr( short_name, "COM") ) - return mbg_snprintf(s, max_len,"%s", short_name); + // For a serial port string specifies we just + // copy the short_name. + if ( device_id_is_serial( short_name ) ) + { + n = sn_cpy_str_safe( s, max_len, short_name ); + goto out; + } - for ( i = 0; ( i < HW_NAME_SZ ) && ( i < strlen( short_name ) ); i++ ) + // If the short_name has more than sizeof( dev_name ) characters + // then we have to reduce the maximum length. + // For a bus level device the short_name usually consists of + // the model name, followed by an underscore '_', followed + // by the serial number, e.g. "PZF180PEX_046411000030". + // See ::MBG_DEV_NAME. + if ( l > sizeof( dev_name ) ) + l = sizeof( dev_name ); + + for ( i = 0; i < l; i++ ) { if ( short_name[i] == '_' ) { i++; break; } - model_code[i] = short_name[i]; + + dev_name[i] = short_name[i]; } - strncpy( sernum, &short_name[i], PCPS_SN_SIZE-1 ); - if ( sernum[12] == ' ' ) - sernum[12] = '\0'; + strncpy_safe( sernum, &short_name[i], sizeof( sernum ) ); + + //### TODO + // Legal serial numbers have MBG_GRP_SERNUM_LEN characters, which is + // less than the maximum length of a PCPS_SN_STR type string. + // Do we really have to check and truncate the PCPS_SN_STR sernum? + if ( sernum[MBG_GRP_SERNUM_LEN] == ' ' ) + sernum[MBG_GRP_SERNUM_LEN] = '\0'; } - n = mbg_snprintf( s, max_len, "%s, S/N %s", model_code, sernum ); + n = snprintf_safe( s, max_len, "%s, S/N %s", dev_name, sernum ); - if ( fw_rev_num > 0 ) - n += mbg_snprintf( &s[n], max_len," (FW v%X.%02X", fw_rev_num>>8, fw_rev_num & 0x00FF ); + if ( fw_rev_num || asic_ver_num ) + n += sn_cpy_str_safe( &s[n], max_len - n, " (" ); - if ( asic_version_num > 0 ) + if ( fw_rev_num ) { - mbg_snprintf( &s[n], max_len," / ASIC v%X.%02X)", _convert_asic_version_number( asic_version_num ) >> 8, - ( _convert_asic_version_number( asic_version_num ) ) & 0xFF ); + n += snprintf_safe( &s[n], max_len - n, "FW v%X.%02X", + fw_rev_num >> 8, fw_rev_num & 0xFF ); + // Append a separator if ASIC version will follow. + if ( asic_ver_num ) + n += sn_cpy_str_safe( &s[n], max_len - n, " / " ); } - else - mbg_snprintf( &s[n], max_len,")" ); - return strlen(s); + if ( asic_ver_num ) + { + n += snprintf_safe( &s[n], max_len - n, "ASIC v%d.%02d", + _convert_asic_version_number( asic_ver_num ) >> 8, + _convert_asic_version_number( asic_ver_num ) & 0xFF ); + } + + if ( fw_rev_num || asic_ver_num ) + n += sn_cpy_str_safe( &s[n], max_len - n, ")" ); + +out: + return _int_from_size_t( n ); } // mbg_str_dev_name diff --git a/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.h b/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.h index 761db23..bc29f36 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/mbgutil.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgutil.h 1.16.1.2 2011/06/22 10:21:57 martin TRASH $ + * $Id: mbgutil.h 1.18 2017/07/05 16:44:35 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,10 +10,14 @@ * * ----------------------------------------------------------------------- * $Log: mbgutil.h $ - * Revision 1.16.1.2 2011/06/22 10:21:57 martin - * Cleaned up handling of pragma pack(). - * Revision 1.16.1.1 2011/02/09 15:27:23 martin + * Revision 1.18 2017/07/05 16:44:35 martin + * New version code 0x0400, compatibility version still 0x0110. + * Include timeutil.h. + * windows.h is now included in mbg_tgt.h. + * Updated function prototypes. + * Revision 1.17 2012/10/15 10:08:32 martin * Include stdlib.h. + * Cleaned up handling of pragma pack(). * Revision 1.16 2009/08/14 10:11:53Z daniel * New version code 306, compatibility version still 110. * Revision 1.15 2009/06/09 08:57:47Z daniel @@ -56,6 +60,7 @@ /* Other headers to be included */ #include <mbg_tgt.h> +#include <timeutil.h> #include <use_pack.h> #include <pcpsdefs.h> #include <mbggeo.h> @@ -64,14 +69,13 @@ #include <stdlib.h> -#define MBGUTIL_VERSION 0x0306 +#define MBGUTIL_VERSION 0x0400 #define MBGUTIL_COMPAT_VERSION 0x0110 #if defined( MBG_TGT_WIN32 ) - #include <windows.h> #elif defined( MBG_TGT_LINUX ) @@ -104,24 +108,11 @@ #endif -#if defined( MBG_TGT_WIN32 ) - -#elif defined( MBG_TGT_LINUX ) - -#elif defined( MBG_TGT_OS2 ) - -#else - -#endif - - - -/* function prototypes: */ - #ifdef __cplusplus extern "C" { #endif + // The macro below can be used to simplify the API call if // a string variable is used rather than a char *. #define _mbg_strncpy( _s, _src ) \ @@ -133,38 +124,449 @@ extern "C" { /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ + /** + * @brief Get the DLL/shared library's version code + * + * @return The version code at which the library was built + */ _MBG_API_ATTR int _MBG_API mbgutil_get_version( void ) ; + + /** + * @brief Check the DLL/shared library's compatibility + * + * @param[in] header_version Version code defined in the header file when the application is built + * + * @return ::MBG_SUCCESS if compatible, else ::MBG_ERR_LIB_NOT_COMPATIBLE + */ _MBG_API_ATTR int _MBG_API mbgutil_check_version( int header_version ) ; - _MBG_API_ATTR int _MBG_API mbg_snprintf( char *s, size_t max_len, const char * fmt, ... ) ; + + /** + * @brief A portable, safe implementation of snprintf() + * + * The output string buffer is in any case properly terminated by 0. + * For a detailed description see ::vsnprintf_safe + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] fmt Format string according to subsequent parameters + * @param[in] ... Variable argument list according to the format string + * + * @return the number of characters written to the output buffer, except the terminating 0 + * + * @see ::vsnprintf_safe + * @see ::snprintf_safe + */ + _MBG_API_ATTR int __attribute__( ( format( printf, 3, 4 ) ) ) _MBG_API mbg_snprintf( char *s, size_t max_len, const char * fmt, ... ) ; + + /** + * @brief A portable, safe implementation of strncpy() + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the destination string buffer + * @param[in] max_len Size of the destination string buffer + * @param[in] src Pointer to the source string buffer + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_strncpy( char *s, size_t max_len, const char *src ) ; + + /** + * @brief Write a character multiple times to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] c The character to write to the output buffer + * @param[in] n The number of characters to write to the output buffer + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_strchar( char *s, size_t max_len, char c, size_t n ) ; - _MBG_API_ATTR int _MBG_API mbg_str_date_short( char *s, int max_len, int mday, int month ) ; - _MBG_API_ATTR int _MBG_API mbg_str_date( char *s, int max_len, int mday, int month, int year ) ; - _MBG_API_ATTR int _MBG_API mbg_str_time_short( char *s, int max_len, int hour, int min ) ; + + /** + * @brief Write a short date string "dd.mm." to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] mday Day-of-month number, 1..31 + * @param[in] month Month number, 1..12 + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_date_short( char *s, int max_len, int mday, int month ) ; + + /** + * @brief Write a date string "dd.mm.yyyy" to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] mday Day-of-month number, 1..31 + * @param[in] month Month number, 1..12 + * @param[in] year Year number + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_date( char *s, int max_len, int mday, int month, int year ) ; + + /** + * @brief Write a short time string "hh:mm" to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] hour Hours number, 0..23 + * @param[in] min Minutes number, 0..59 + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_time_short( char *s, int max_len, int hour, int min ) ; + + /** + * @brief Write a time string "hh:mm:ss" to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] hour Hours number, 0..23 + * @param[in] min Minutes number, 0..59 + * @param[in] sec Seconds number, 0..59, or 60 in case of leap second + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_time( char *s, int max_len, int hour, int min, int sec ) ; + + /** + * @brief Write a long time string "hh:mm:ss.cc" to a string buffer + * + * Include 100ths of seconds. + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] hour Hours number, 0..23 + * @param[in] min Minutes number, 0..59 + * @param[in] sec Seconds number, 0..59, or 60 in case of leap second + * @param[in] sec100 Hundreths of seconds, 0..99 + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_time_long( char *s, int max_len, int hour, int min, int sec, int sec100 ) ; + + /** + * @brief Write a full date and time string to a string buffer + * + * The number of space characters between date and time + * is determined by the global variable ::mbg_date_time_dist. + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::TM_GPS structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_tm_gps_date_time( char *s, int max_len, const TM_GPS *pt ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_date_short( char *s, int max_len, const PCPS_TIME *pt ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_date( char *s, int max_len, const PCPS_TIME *pt ) ; + + /** + * @brief Write the short date given as ::PCPS_TIME structure to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_date_short( char *s, int max_len, const PCPS_TIME *pt ) ; + + /** + * @brief Write the date given as ::PCPS_TIME structure to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_date( char *s, int max_len, const PCPS_TIME *pt ) ; + + /** + * @brief Write the short time given as ::PCPS_TIME structure to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_pcps_time_short( char *s, int max_len, const PCPS_TIME *pt ) ; + + /** + * @brief Write the time given as ::PCPS_TIME structure to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_pcps_time( char *s, int max_len, const PCPS_TIME *pt ) ; + + /** + * @brief Write the time including sec100ths given as ::PCPS_TIME structure to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_pcps_time_long( char *s, int max_len, const PCPS_TIME *pt ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_date_time( char *s, int max_len, const PCPS_TIME *pt, const char *tz_str ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date( char *s, int max_len, uint32_t sec ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time( char *s, int max_len, uint32_t sec ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_utc( char *s, int max_len, const PCPS_HR_TIME *pt ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_loc( char *s, int max_len, const PCPS_HR_TIME *pt ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_frac( char *s, int max_len, uint32_t frac ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_offs( char *s, int max_len, const PCPS_HR_TIME *pt, const char *info ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_utc( char *s, int max_len, const PCPS_HR_TIME *pt ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, const PCPS_HR_TIME *pt ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_tstamp_raw( char *s, int max_len, const PCPS_TIME_STAMP *pt ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_raw( char *s, int max_len, const PCPS_HR_TIME *pt ) ; - _MBG_API_ATTR int _MBG_API mbg_str_ucap( char *s, int max_len, const PCPS_HR_TIME *pt ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pos_dms( char *s, int max_len, const DMS *pdms, int prec ) ; + + /** + * @brief Write date and time given as ::PCPS_TIME structure to a string buffer + * + * The number of space characters between date and time + * is determined by the global variable ::mbg_date_time_dist. + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_TIME structure providing date and time + * @param[in] tz_str Optional time zone string to be appended, currently not used, may be NULL + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_date_time( char *s, int max_len, const PCPS_TIME *pt, const char *tz_str ) ; + + /** + * @brief Write date derived from seconds-since-epoch to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] sec Number of seconds since the epoch to be converted to date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date( char *s, int max_len, uint32_t sec ) ; + + /** + * @brief Write time derived from seconds-since-epoch to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] sec Number of seconds since the epoch to be converted to date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time( char *s, int max_len, uint32_t sec ) ; + + /** + * @brief Write UTC date and time given as ::PCPS_HR_TIME structure to a string buffer + * + * The number of space characters between date and time + * is determined by the global variable ::mbg_date_time_dist. + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_utc( char *s, int max_len, const PCPS_HR_TIME *pt ) ; + + /** + * @brief Write local date and time given as ::PCPS_HR_TIME structure to a string buffer + * + * The number of space characters between date and time + * is determined by the global variable ::mbg_date_time_dist. + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_date_time_loc( char *s, int max_len, const PCPS_HR_TIME *pt ) ; + + /** + * @brief Print binary ::PCPS_FRAC_32 fractions in decimal to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] frac Binary fractions of a second in ::PCPS_FRAC_32 format + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_frac( char *s, int max_len, uint32_t frac ) ; + + /** + * @brief Print the UTC offset from a ::PCPS_HR_TIME structure to a string buffer + * + * The output format is sign - hours - minutes, e.g. "+01:45h". + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date, and UTC offset + * @param[in] info An informational text to be prepended + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_offs( char *s, int max_len, const PCPS_HR_TIME *pt, const char *info ) ; + + /** + * @brief Write a high resolution UTC time stamp including fractions to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_utc( char *s, int max_len, const PCPS_HR_TIME *pt ) ; + + /** + * @brief Write a high resolution local time stamp including fractions to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_tstamp_loc( char *s, int max_len, const PCPS_HR_TIME *pt ) ; + + /** + * @brief Write a raw high resolution time stamp to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_tstamp_raw( char *s, int max_len, const PCPS_TIME_STAMP *pt ) ; + + /** + * @brief Write a raw high resolution time stamp plus converted local time to a string buffer + * + * The output string also has the time status code appended as hex number. + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure providing date and time + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pcps_hr_time_raw( char *s, int max_len, const PCPS_HR_TIME *pt ) ; + + /** + * @brief Write time capture / user capture time stamp to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pt Pointer to a ::PCPS_HR_TIME structure containing a user capture event + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_ucap( char *s, int max_len, const PCPS_HR_TIME *pt ) ; + + /** + * @brief Write a geographic coordinate in degrees - minutes - seconds to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] pdms Pointer to a ::DMS structure containing the coordinate + * @param[in] prec Number of digits of the geographic seconds after the decimal separator + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pos_dms( char *s, int max_len, const DMS *pdms, int prec ) ; + + /** + * @brief Write a position's altitude parameter to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] alt The altitude parameter, in meters + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ _MBG_API_ATTR int _MBG_API mbg_str_pos_alt( char *s, int max_len, double alt ) ; - _MBG_API_ATTR int _MBG_API mbg_str_pos( char *s, int max_len, const POS *ppos, int prec ) ; - _MBG_API_ATTR int _MBG_API mbg_str_dev_name( char *s, int max_len, const char *short_name, uint16_t fw_rev_num, PCI_ASIC_VERSION asic_version_num ) ; + + /** + * @brief Write geographic coordinates to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] ppos Pointer to a ::POS structure containing the coordinates + * @param[in] prec Number of digits of the geographic seconds after the decimal separator + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_pos( char *s, int max_len, const POS *ppos, int prec ) ; + + /** + * @brief Write device info to a string buffer + * + * The output string buffer is in any case properly terminated by 0. + * + * @param[out] s Pointer to the output buffer + * @param[in] max_len Size of the output buffer + * @param[in] short_name Short device name, e.g. in ::MBG_DEV_NAME format + * @param[in] fw_rev_num The firmware revision number + * @param[in] asic_ver_num The ASIC version number + * + * @return the number of characters written to the output buffer, except the terminating 0 + */ + _MBG_API_ATTR int _MBG_API mbg_str_dev_name( char *s, int max_len, const char *short_name, uint16_t fw_rev_num, PCI_ASIC_VERSION asic_ver_num ) ; + /* ----- function prototypes end ----- */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/myutil.h b/src/external/bsd/meinberg/dist/mbglib/common/myutil.h index 7e6b901..aad15f1 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/myutil.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/myutil.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: myutil.h 1.14 2011/02/16 14:02:35 martin REL_M $ + * $Id: myutil.h 1.20 2017/03/22 15:09:03 andre.hartmann REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,18 @@ * * ----------------------------------------------------------------------- * $Log: myutil.h $ + * Revision 1.20 2017/03/22 15:09:03 andre.hartmann + * added macros for lin. interpolation + * Revision 1.19 2017/01/27 12:24:08Z martin + * Moved STRINGIFY() macro to words.h. + * Revision 1.18 2014/10/20 12:30:38 martin + * Moved macro _isdigit() to words.h. + * Revision 1.17 2014/07/15 06:19:48Z andre + * added function _sgn( _x ), returns sign of _x + * Revision 1.16 2013/12/16 13:32:57Z martin + * Don't redefine MIN and MAX. + * Revision 1.15 2012/10/02 18:51:52 martin + * Updated handling of pragma pack(). * Revision 1.14 2011/02/16 14:02:35 martin * Added STRINGIFY() macro. * Revision 1.13 2010/12/13 15:59:39 martin @@ -66,26 +78,12 @@ /* Start of header body */ -#if defined( _USE_PACK ) // set byte alignment - #pragma pack( 1 ) +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT #endif -// The two macros below can be used to define a constant string on the -// compiler's command line, e.g. like -DVERSION_STRING="v1.0 BETA". -// Source code like -// const char version_string[] = VERSION_STRING; -// may not work for every compiler since the double quotes -// in VERSION_STRING may be removed when the definition is evaluated. -// A proper solution is to use the STRINGIFY() macro below: -// const char version_string[] = STRINGIFY( VERSION_STRING ); -// The XSTRINGIFY() macro is simply a helper macro which should not -// be used alone. -#define STRINGIFY(x) XSTRINGIFY(x) -#define XSTRINGIFY(x) #x - - - #if MBG_TGT_HAS_64BIT_TYPES #define _frac( _x ) ( ( (_x) == 0.0 ) ? 0.0 : ( (_x) - (double) ( (int64_t) (_x) ) ) ) #else @@ -93,12 +91,16 @@ #endif -#define _isdigit( _c ) ( (_c) >= '0' && (_c) <= '9' ) - #define _eos( _s ) ( &(_s)[strlen( _s )] ) -#define MIN( _x, _y ) ( ( (_x) < (_y) ) ? (_x) : (_y) ) -#define MAX( _x, _y ) ( ( (_x) > (_y) ) ? (_x) : (_y) ) +#if !defined( MIN ) + #define MIN( _x, _y ) ( ( (_x) < (_y) ) ? (_x) : (_y) ) +#endif + +#if !defined( MAX ) + #define MAX( _x, _y ) ( ( (_x) > (_y) ) ? (_x) : (_y) ) +#endif + #define SWAP( _x, _y ) { temp = (_x); (_x) = (_y); (_y) = temp; } #define SQR( _x ) ( (_x) * (_x) ) @@ -157,6 +159,14 @@ typedef union #define _is_supported( _i, _msk ) \ ( ( (_msk) & _idx_bit( _i ) ) != 0 ) +// return the sign of a number +#define _sgn( _x ) ( ( ( _x ) < 0 ) ? -1 : 1 ) + + +// macro for linear interpolation y = _m * x + _b between two points ( X1; Y1 ), ( X2; Y2 ) +#define _m( _Y1, _X1, _Y2, _X2 ) ( ( _Y2 -_Y1 ) / ( _X2 -_X1 ) ) +#define _b( _Y1, _X1, _Y2, _X2 ) ( ( ( _Y1 * _X2 ) - ( _Y2 * _X1 ) ) / ( _X2 -_X1 ) ) + /* * The macro below copies a string, taking care not to @@ -208,8 +218,9 @@ extern "C" { #endif -#if defined( _USE_PACK ) // set default alignment - #pragma pack() +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT #endif /* End of header body */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/nanotime.c b/src/external/bsd/meinberg/dist/mbglib/common/nanotime.c new file mode 100755 index 0000000..43cf863 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/nanotime.c @@ -0,0 +1,312 @@ + +/************************************************************************** + * + * $Id: nanotime.c 1.2 2017/06/12 13:54:04 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Meinberg Library module providing functions to handle NANO_TIME + * and NANO_TIME_64. + * + * ----------------------------------------------------------------------- + * $Log: nanotime.c $ + * Revision 1.2 2017/06/12 13:54:04 martin + * Fixed build under Windows. + * Revision 1.1 2017/06/12 08:49:09Z martin + * Initial revision. + * + **************************************************************************/ + +#define _NANOTIME + #include <nanotime.h> +#undef _NANOTIME + +#include <mbgtime.h> +#include <str_util.h> + +#include <stdlib.h> + + +// At least MSVC++ 9.0 / Visual Studio 2008 or older +// doesn't provide strtoll() +#if defined( _MSC_VER ) && ( _MSC_VER <= 1500 ) + #define strtoll _strtoi64 +#endif + + +/*HDR*/ +/** + * @brief Convert a ::NANO_TIME time to double + * + * @param[in] p Address of a ::NANO_TIME structure to be converted + * + * @return The computed number of seconds with fractions, as double + * + * @see ::double_to_nano_time + */ +double nano_time_to_double( const NANO_TIME *p ) +{ + double d = p->secs; + + d += ( (double) p->nano_secs ) / 1e9; + + return d; + +} // nano_time_to_double + + + +/*HDR*/ +/** + * @brief Setup a ::NANO_TIME structure from a time provided as double + * + * @param[out] p Address of a ::NANO_TIME structure to be set up + * @param[in] d The time to be converted, in seconds with fractions, as double + * + * @see ::nano_time_to_double + */ +void double_to_nano_time( NANO_TIME *p, double d ) +{ + p->secs = (int32_t) d; + + d -= (double) p->secs; + + p->nano_secs = (int32_t) ( d * 1e9 ); + +} // double_to_nano_time + + + +/*HDR*/ +/** + * @brief Print nano time into string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] nt The ::NANO_TIME to be printed + */ +size_t snprint_nano_time( char *s, size_t max_len, const NANO_TIME *nt ) +{ + size_t n = snprintf_safe( s, max_len, "%c%li.%09li", + _nano_time_negative( nt ) ? '-' : '+', + labs( (long) nt->secs ), + labs( (long) nt->nano_secs ) ); + return n; + +} // snprint_nano_time + + + +#if !defined( MBG_TGT_MISSING_64_BIT_TYPES ) + +/*HDR*/ +/** + * @brief Normalize a ::NANO_TIME_64 time + * + * After normalization, the following can be assumed:<br> + * - nano_secs is in the range [-10^9 + 1, 10^9 - 1]<br> + * - if secs is not 0, secs and nano_secs have the same sign + * + * @param[in,out] nt The ::NANO_TIME_64 to be normalized + */ +void normalize_nano_time_64( NANO_TIME_64 *nt ) +{ + int64_t additional_secs; + + // Step 1: Make sure nano seconds are in the interval [-10^9 + 1, 10^9 - 1] + additional_secs = nt->nano_secs / NSECS_PER_SEC; + nt->nano_secs -= additional_secs * NSECS_PER_SEC; + nt->secs += additional_secs; + + // Step 2: Make sure seconds and nanoseconds have same sign if seconds is not 0 + if ( nt->secs > 0 && nt->nano_secs < 0 ) + { + nt->secs -= 1; + nt->nano_secs += NSECS_PER_SEC; + } + else if ( nt->secs < 0 && nt->nano_secs > 0 ) + { + nt->secs += 1; + nt->nano_secs -= NSECS_PER_SEC; + } + +} // normalize_nano_time_64 + + + +/*HDR*/ +/** + * @brief Convert a ::NANO_TIME_64 time to double + * + * @param[in] p Address of a ::NANO_TIME_64 structure to be converted + * + * @return The computed number of seconds with fractions, as double + * + * @see ::double_to_nano_time_64 + */ +double nano_time_64_to_double( const NANO_TIME_64 *p ) +{ + double d = (double) p->secs; + + d += ( (double) p->nano_secs ) / 1e9; + + return d; + +} // nano_time_64_to_double + + + +/*HDR*/ +/** + * @brief Setup a ::NANO_TIME_64 structure from a time as double + * + * @param[out] p Address of a ::NANO_TIME_64 structure to be set up + * @param[in] d The time to be converted, in seconds with fractions, as double + * + * @see ::nano_time_64_to_double + */ +void double_to_nano_time_64( NANO_TIME_64 *p, double d ) +{ + p->secs = (int32_t) d; + + d -= (double) p->secs; + + p->nano_secs = (int32_t) ( d * 1e9 ); + +} // double_to_nano_time_64 + + + +/*HDR*/ +/** + * @brief Print a normalized ::NANO_TIME_64 into a string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] nt The ::NANO_TIME_64 to be printed + */ +size_t snprint_nano_time_64( char *s, size_t max_len, const NANO_TIME_64 *nt ) +{ + size_t n = snprintf_safe( s, max_len, "%c%" PRId64 ".%09" PRId64, + _nano_time_negative( nt ) ? '-' : '+', + _abs64( nt->secs ), + _abs64( nt->nano_secs ) ); + return n; + +} // snprint_nano_time_64 + + + +static __mbg_inline /*HDR*/ +/** + * @brief Generic function to set up a ::NANO_TIME_64 structure from a string + * + * @param[in] s A string with a time in seconds, with fractions separated by decimal point + * @param[out] p Address of a ::NANO_TIME_64 structure to be set up + * @param[in] base The base of the conversion, i.e. 10 for a string with decimal numbers, or 16 for a hex string + * @param[in] frac_digits The number of fractions required to represent 1 nanosecond, e.g. + * 9 for a decimal string like 0.000000001, or + * TODO for a hex string like 0x00000000.00000000 + */ +void str_to_nano_time_64( const char *s, NANO_TIME_64 *p, int base, int frac_digits ) +{ + char *cp = NULL; + + p->secs = strtoll( s, &cp, base ); + + if ( *cp == '.' ) // fractions may follow + { + char *ep = NULL; + + cp++; // skip '.' + + p->nano_secs = strtoll( cp, &ep, base ); + + if ( p->nano_secs ) // only if fractions not 0 + { + int l = ep - cp; + + while ( l < frac_digits ) + { + p->nano_secs *= base; + l++; + } + + while ( l > frac_digits ) + { + p->nano_secs /= base; + l--; + } + + if ( p->secs < 0 ) + p->nano_secs = -p->nano_secs; + } + } + +} // str_to_nano_time_64 + + + +static __mbg_inline /*HDR*/ +/** + * @brief Generic function to divide ::NANO_TIME_64 value + * + * @param[in,out] p Address of a ::NANO_TIME_64 structure to be divided + * @param[in] div The number by which to divide + * @param[in] mul The complementary number to div, i.e. mul = 1000000000 / div + */ +void div_nano_time_64( NANO_TIME_64 *p, long div, long mul ) +{ + // At least MSVC++ 9.0 / Visual Studio 2008 or older + // doesn't provide lldiv_t and lldiv(). + #if defined( _MSC_VER ) && ( _MSC_VER <= 1500 ) //### TODO: Test this code + int64_t rem = p->secs % div; + p->secs /= div; + p->nano_secs = ( rem * mul ) + ( p->nano_secs / div ); + #else + lldiv_t lldt = lldiv( p->secs, div ); + p->secs = lldt.quot; + p->nano_secs = ( lldt.rem * mul ) + ( p->nano_secs / div ); + #endif + +} // div_nano_time_64 + + + +/*HDR*/ +/** + * @brief Set up a ::NANO_TIME_64 structure from a string with a time in seconds and fractions + * + * @param[in] s A string with a time in seconds, with fractions separated by decimal point + * @param[out] p Address of a ::NANO_TIME_64 structure to be set up + */ +void str_s_to_nano_time_64( const char *s, NANO_TIME_64 *p ) +{ + str_to_nano_time_64( s, p, 10, 9 ); + +} // str_s_to_nano_time_64 + + + +/*HDR*/ +/** + * @brief Set up a ::NANO_TIME_64 structure from a string with a time in milliseconds and fractions + * + * @param[in] s A string with a time in milliseconds, with fractions separated by decimal point + * @param[out] p Address of a ::NANO_TIME_64 structure to be set up + */ +void str_ms_to_nano_time_64( const char *s, NANO_TIME_64 *p ) +{ + // First do the same conversion as for a string representing seconds + str_s_to_nano_time_64( s, p ); + + // Now we have the value in milliseconds + // Divide by 1000 to get seconds + div_nano_time_64( p, 1000, 1000000UL ); + +} // str_ms_to_nano_time_64 + +#endif // !defined( MBG_TGT_MISSING_64_BIT_TYPES ) + + diff --git a/src/external/bsd/meinberg/dist/mbglib/common/nanotime.h b/src/external/bsd/meinberg/dist/mbglib/common/nanotime.h new file mode 100755 index 0000000..85963a6 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/nanotime.h @@ -0,0 +1,148 @@ + +/************************************************************************** + * + * $Id: nanotime.h 1.1 2017/06/12 08:49:09 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for nanotime.c + * + * ----------------------------------------------------------------------- + * $Log: nanotime.h $ + * Revision 1.1 2017/06/12 08:49:09 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _NANOTIME_H +#define _NANOTIME_H + +/* Other headers to be included */ + +#include <words.h> // implicitly includes mbg_tgt.h, if required, + // and defines some basic structures + +#ifdef _NANOTIME + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + + + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + /** + * @brief Convert a ::NANO_TIME time to double + * + * @param[in] p Address of a ::NANO_TIME structure to be converted + * + * @return The computed number of seconds with fractions, as double + * + * @see ::double_to_nano_time + */ + double nano_time_to_double( const NANO_TIME *p ) ; + + /** + * @brief Setup a ::NANO_TIME structure from a time provided as double + * + * @param[out] p Address of a ::NANO_TIME structure to be set up + * @param[in] d The time to be converted, in seconds with fractions, as double + * + * @see ::nano_time_to_double + */ + void double_to_nano_time( NANO_TIME *p, double d ) ; + + /** + * @brief Print nano time into string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] nt The ::NANO_TIME to be printed + */ + size_t snprint_nano_time( char *s, size_t max_len, const NANO_TIME *nt ) ; + + /** + * @brief Normalize a ::NANO_TIME_64 time + * + * After normalization, the following can be assumed:<br> + * - nano_secs is in the range [-10^9 + 1, 10^9 - 1]<br> + * - if secs is not 0, secs and nano_secs have the same sign + * + * @param[in,out] nt The ::NANO_TIME_64 to be normalized + */ + void normalize_nano_time_64( NANO_TIME_64 *nt ) ; + + /** + * @brief Convert a ::NANO_TIME_64 time to double + * + * @param[in] p Address of a ::NANO_TIME_64 structure to be converted + * + * @return The computed number of seconds with fractions, as double + * + * @see ::double_to_nano_time_64 + */ + double nano_time_64_to_double( const NANO_TIME_64 *p ) ; + + /** + * @brief Setup a ::NANO_TIME_64 structure from a time as double + * + * @param[out] p Address of a ::NANO_TIME_64 structure to be set up + * @param[in] d The time to be converted, in seconds with fractions, as double + * + * @see ::nano_time_64_to_double + */ + void double_to_nano_time_64( NANO_TIME_64 *p, double d ) ; + + /** + * @brief Print a normalized ::NANO_TIME_64 into a string buffer + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] nt The ::NANO_TIME_64 to be printed + */ + size_t snprint_nano_time_64( char *s, size_t max_len, const NANO_TIME_64 *nt ) ; + + /** + * @brief Set up a ::NANO_TIME_64 structure from a string with a time in seconds and fractions + * + * @param[in] s A string with a time in seconds, with fractions separated by decimal point + * @param[out] p Address of a ::NANO_TIME_64 structure to be set up + */ + void str_s_to_nano_time_64( const char *s, NANO_TIME_64 *p ) ; + + /** + * @brief Set up a ::NANO_TIME_64 structure from a string with a time in milliseconds and fractions + * + * @param[in] s A string with a time in milliseconds, with fractions separated by decimal point + * @param[out] p Address of a ::NANO_TIME_64 structure to be set up + */ + void str_ms_to_nano_time_64( const char *s, NANO_TIME_64 *p ) ; + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _NANOTIME_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/ntp_shm.c b/src/external/bsd/meinberg/dist/mbglib/common/ntp_shm.c new file mode 100755 index 0000000..4be1d30 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/ntp_shm.c @@ -0,0 +1,93 @@ + +/************************************************************************** + * + * $Id: ntp_shm.c 1.2 2017/07/05 16:49:00 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * NTP shared memory support functions. + * + * ----------------------------------------------------------------------- + * $Log: ntp_shm.c $ + * Revision 1.2 2017/07/05 16:49:00 martin + * Patch submitted by <juergen.perlinger@t-online.de>: + * Support number of the first SHM unit to use. + * This intentionally changes the prototype for ntpshm_init(). + * Revision 1.1 2012/05/29 09:54:15 martin + * Initial revision. + * + **************************************************************************/ + +#define _NTP_SHM + #include <ntp_shm.h> +#undef _NTP_SHM + +#include <syslog.h> +#include <errno.h> +#include <string.h> + + + +/*HDR*/ +struct shmTime *getShmTime( int unit ) +{ + struct shmTime *p; + + int shmid = shmget( (key_t) ( NTPD_BASE + unit ), + sizeof( struct shmTime ), IPC_CREAT | 0644 ); + + if ( shmid == -1 ) + { + syslog( LOG_ERR, "shmget %i failed: %s", unit, strerror( errno ) ); + return NULL; + } + + + p = (struct shmTime *) shmat( shmid, 0, 0 ); + + if ( (long) p == -1L ) + { + syslog( LOG_ERR, "shmat %i failed: %s", unit, strerror( errno ) ); + return NULL; + } + + return p; + +} // getShmTime + + + +/*HDR*/ +int ntpshm_init( struct shmTime **shmTime, int n_units, int n_unit0 ) +{ + int i; + int ret_val = 0; + + for ( i = 0; i < n_units; i++ ) + { + int u = i + n_unit0; + struct shmTime *p = getShmTime( u ); + shmTime[i] = p; + + if ( p == NULL ) + { + syslog( LOG_WARNING, "** Failed to initialize NTP SHM unit %i", u ); + ret_val = -1; + continue; + } + + memset( p, 0, sizeof( *p ) ); + + p->mode = 1; + p->precision = -5; /* initially 0.5 sec */ + p->nsamples = 3; /* stages of median filter */ + + syslog( LOG_INFO, "NTP SHM unit %i initialized successfully", u ); + } + + return ret_val; + +} // ntpshm_init + + diff --git a/src/external/bsd/meinberg/dist/mbglib/common/ntp_shm.h b/src/external/bsd/meinberg/dist/mbglib/common/ntp_shm.h new file mode 100755 index 0000000..2cefc00 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/ntp_shm.h @@ -0,0 +1,151 @@ + +/************************************************************************** + * + * $Id: ntp_shm.h 1.3 2017/07/05 16:52:25 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for ntp_shm.c. + * + * ----------------------------------------------------------------------- + * $Log: ntp_shm.h $ + * Revision 1.3 2017/07/05 16:52:25 martin + * Defined MAX_SHM_UNIT_OFFSET. + * Doxygen changes and fixes. + * Updated function prototypes. + * Revision 1.2 2013/01/02 10:23:41 daniel + * Added nsec support + * Revision 1.1 2012/05/29 09:54:15 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _NTP_SHM_H +#define _NTP_SHM_H + + +/* Other headers to be included */ + +#include <sys/ipc.h> +#include <sys/shm.h> + + +#ifdef _NTP_SHM + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if 0 && defined( _USE_PACK ) // use default alignment + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup group_ntp_defs NTP interface definitions + * + * @note These definitions have been copied from the NTP source code (http://www.ntp.org) + * + * @{ */ + +/** + * @brief Structure of NTP's shared memory segment + */ +struct shmTime +{ + int mode; /* 0 - if valid set + * use values, + * clear valid + * 1 - if valid set + * if count before and after read of + * values is equal, + * use values + * clear valid + */ + int count; + time_t clockTimeStampSec; /* external clock */ + int clockTimeStampUSec; /* external clock */ + time_t receiveTimeStampSec; /* internal clock, when external value was received */ + int receiveTimeStampUSec; /* internal clock, when external value was received */ + int leap; ///< see @ref NTP_LEAP_BITS + int precision; + int nsamples; + int valid; + unsigned clockTimeStampNSec; /* unsigned ns timestamps */ + unsigned receiveTimeStampNSec; + int dummy[8]; +}; + +/** + * @defgroup NTP_LEAP_BITS NTP Leap Bits + * + * @note This describes NTP leap bits + * + * @{ */ + +#define LEAP_NOWARNING 0x0 /**< normal, no leap second warning */ +#define LEAP_ADDSECOND 0x1 /**< last minute of day has 61 seconds */ +#define LEAP_DELSECOND 0x2 /**< last minute of day has 59 seconds */ +#define LEAP_NOTINSYNC 0x3 /**< overload, clock is free running */ + +/** @} defgroup NTP_LEAP_BITS */ + + +/** + * @brief Number of units (refclocks) supported by the SMH segment + */ +#define MAX_SHM_REFCLOCKS 4 + + +/** + * @brief Max. Number of SHM unit offset + */ +#define MAX_SHM_UNIT_OFFSET 128 + + +/** + * @brief Basic SHM unit identifier (unit 0) + */ +#define NTPD_BASE 0x4e545030 ///< "NTP0" + +/** @} defgroup group_ntp_defs */ + + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + struct shmTime *getShmTime( int unit ) ; + int ntpshm_init( struct shmTime **shmTime, int n_units, int n_unit0 ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + + +#undef _ext +#undef _DO_INIT + +#endif /* _NTP_SHM_H */ + diff --git a/src/external/bsd/meinberg/dist/mbglib/common/parmgps.c b/src/external/bsd/meinberg/dist/mbglib/common/parmgps.c deleted file mode 100755 index 44e620b..0000000 --- a/src/external/bsd/meinberg/dist/mbglib/common/parmgps.c +++ /dev/null @@ -1,242 +0,0 @@ - -/************************************************************************** - * - * $Id: parmgps.c 1.5 2008/10/21 10:47:26 martin REL_M $ - * - * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany - * - * Description: - * Functions to handle/convert Meinberg GPS specific parameters. - * - * ----------------------------------------------------------------------- - * $Log: parmgps.c $ - * Revision 1.5 2008/10/21 10:47:26 martin - * Renamed check_port_info() to check_valid_port_info() - * to avoid naming conflicts. - * Revision 1.4 2008/09/15 14:11:25 martin - * New function check_port_info() which returns a bit mask indicating - * which fields of a PORT_SETTINGS structure are not valid. - * This is based on code taken from valid_port_info(), which now calls - * check_port_info() and returns a value compatible to the earlier version. - * Revision 1.3 2004/11/09 14:21:36 martin - * Redefined some data types using C99 fixed-size definitions. - * Revision 1.2 2002/02/19 13:30:23Z MARTIN - * Bug fix in port_settings_from_port_parm_mode(). - * Revision 1.1 2002/01/30 10:30:26 MARTIN - * Initial revision - * - **************************************************************************/ - -#define _PARMGPS - #include <parmgps.h> -#undef _PARMGPS - -#include <myutil.h> -#include <string.h> - - - -/*HDR*/ -int get_str_idx( const char *search, - const char *str_table[], - int n_entries ) -{ - int i; - - for ( i = 0; i < n_entries; i++ ) - if ( strcmp( search, str_table[i] ) == 0 ) - return i; - - return -1; - -} // get_str_idx - - - -/*HDR*/ -int get_baud_rate_idx( BAUD_RATE baud_rate ) -{ - int i; - - for ( i = 0; i < N_MBG_BAUD_RATES; i++ ) - if ( baud_rate == mbg_baud_rate[i] ) - return i; - - return -1; - -} // get_baud_rate_idx - - - -/*HDR*/ -int get_framing_idx( const char *framing ) -{ - return get_str_idx( framing, mbg_framing_str, N_MBG_FRAMINGS ); - -} // get_framing_idx - - - -/*HDR*/ -void port_settings_from_port_parm_mode( - PORT_SETTINGS *p_ps, - uint8_t pp_mode, - int str_type_cap - ) -{ - if ( pp_mode >= STR_UCAP ) - { - p_ps->str_type = str_type_cap; - p_ps->mode = ( pp_mode == STR_UCAP ) ? STR_AUTO : STR_ON_REQ; - } - else - { - p_ps->str_type = 0; - p_ps->mode = pp_mode; - } - -} // port_settings_from_port_parm_mode - - - -/*HDR*/ -void port_parm_mode_from_port_settings( - uint8_t *pp_mode, - const PORT_SETTINGS *p_ps, - int str_type_cap - ) -{ - if ( p_ps->str_type == str_type_cap ) - *pp_mode = ( p_ps->mode == STR_ON_REQ ) ? STR_UCAP_REQ : STR_UCAP; - else - *pp_mode = p_ps->mode; - -} // port_parm_mode_from_port_settings - - - -/*HDR*/ -void port_settings_from_port_parm( - PORT_SETTINGS *p_ps, - int port_num, - const PORT_PARM *p_pp, - int cap_str_idx -) -{ - p_ps->parm = p_pp->com[port_num]; - - port_settings_from_port_parm_mode( p_ps, p_pp->mode[port_num], - cap_str_idx ); - -} // port_info_from_port_parm - - - -/*HDR*/ -void port_parm_from_port_settings( - PORT_PARM *p_pp, - int port_num, - const PORT_SETTINGS *p_ps, - int cap_str_idx -) -{ - p_pp->com[port_num] = p_ps->parm; - - port_parm_mode_from_port_settings( &p_pp->mode[port_num], - p_ps, cap_str_idx ); - -} // port_parm_from_port_settings - - - -/*HDR*/ -int check_valid_port_info( const PORT_INFO *p_pi, - const STR_TYPE_INFO_IDX str_type_info_idx[], - int n_str_type ) - -{ - const PORT_SETTINGS *p_ps = &p_pi->port_settings; - int idx; - int flags = 0; - - - if ( p_pi->supp_baud_rates & ~_mask( N_MBG_BAUD_RATES ) ) - flags |= MBG_PS_MSK_BAUD_RATE_OVR_SW; // dev. supports more baud rates than driver - - idx = get_baud_rate_idx( p_ps->parm.baud_rate ); - - if ( !_inrange( idx, 0, N_MBG_BAUD_RATES ) || - !_is_supported( idx, p_pi->supp_baud_rates ) ) - flags |= MBG_PS_MSK_BAUD_RATE; - - - if ( p_pi->supp_framings & ~_mask( N_MBG_FRAMINGS ) ) - flags |= MBG_PS_MSK_FRAMING_OVR_SW; // dev. supports more framings than driver - - idx = get_framing_idx( p_ps->parm.framing ); - - if ( !_inrange( idx, 0, N_MBG_FRAMINGS ) || - !_is_supported( idx, p_pi->supp_framings ) ) - flags |= MBG_PS_MSK_FRAMING; - - - if ( p_ps->parm.handshake >= N_COM_HS ) - flags |= MBG_PS_MSK_HS_OVR_SW; // handshake index exceeds max. - - if ( p_ps->parm.handshake != HS_NONE ) // currently no device supports any handshake - flags |= MBG_PS_MSK_HS; // handshake mode not supp. by dev. - - - if ( p_pi->supp_str_types & ~_mask( n_str_type ) ) - flags |= MBG_PS_MSK_STR_TYPE_OVR_SW; // firmware error: more string types supported than reported - - idx = p_ps->str_type; - - if ( idx >= n_str_type ) - flags |= MBG_PS_MSK_STR_TYPE_OVR_DEV; // string type index exceeds max. - else - { - if ( !_is_supported( idx, p_pi->supp_str_types ) ) - flags |= MBG_PS_MSK_STR_TYPE; // string type not supported by this port - else - { - // Use the str_type index to get the supported output mode mask - // from the string type info table. This is required to check - // whether the selected mode is supported by the selected - // string type. - ulong supp_modes = str_type_info_idx[idx].str_type_info.supp_modes; - - if ( supp_modes & ~_mask( N_STR_MODE ) ) - flags |= MBG_PS_MSK_STR_MODE_OVR_SW; // dev. supports more string modes than driver - - idx = p_ps->mode; - - if ( idx >= N_STR_MODE ) // mode is always >= 0 - flags |= MBG_PS_MSK_STR_MODE_OVR_SW; // string mode index exceeds max. - else - if ( !_is_supported( idx, supp_modes ) ) - flags |= MBG_PS_MSK_STR_MODE; // string mode not supp. by this string type and port - } - } - - - if ( p_ps->flags != 0 ) /* currently always 0 */ - flags |= MBG_PS_MSK_FLAGS_OVR_SW | MBG_PS_MSK_FLAGS; - - - return flags; - -} // check_valid_port_info - - - -/*HDR*/ -int valid_port_info( const PORT_INFO *p_pi, - const STR_TYPE_INFO_IDX str_type_info_idx[], - int n_str_type ) -{ - return check_valid_port_info( p_pi, str_type_info_idx, n_str_type ) == 0; - -} // valid_port_info - - diff --git a/src/external/bsd/meinberg/dist/mbglib/common/parmgps.h b/src/external/bsd/meinberg/dist/mbglib/common/parmgps.h deleted file mode 100755 index 46d28fc..0000000 --- a/src/external/bsd/meinberg/dist/mbglib/common/parmgps.h +++ /dev/null @@ -1,138 +0,0 @@ - -/************************************************************************** - * - * $Id: parmgps.h 1.7 2011/02/16 10:12:13 martin TEST $ - * - * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany - * - * Description: - * Definitions and prototypes for parmgps.c. - * - * ----------------------------------------------------------------------- - * $Log: parmgps.h $ - * Revision 1.7 2011/02/16 10:12:13 martin - * Fixed macro syntax for _setup_default_receiver_info_gps(). - * Revision 1.6 2008/10/21 10:41:09Z martin - * Renamed check_port_info() to check_valid_port_info() - * to avoid naming conflicts. - * Revision 1.5 2008/09/10 16:22:32 martin - * Updated function prototypes. - * Revision 1.4 2004/11/09 14:22:34 martin - * Updated function prototypes. - * Revision 1.3 2004/05/19 07:50:16Z martin - * Use symbolic constant as initializer. - * Revision 1.2 2004/04/14 09:21:23Z martin - * Pack structures 1 byte aligned. - * Revision 1.1 2002/01/30 10:33:38Z MARTIN - * Initial revision - * - **************************************************************************/ - -#ifndef _PARMGPS_H -#define _PARMGPS_H - - -/* Other headers to be included */ - -#include <gpsdefs.h> -#include <use_pack.h> - - -#ifdef _PARMGPS - #define _ext - #define _DO_INIT -#else - #define _ext extern -#endif - - -/* Start of header body */ - -#if defined( _USE_PACK ) // set byte alignment - #pragma pack( 1 ) -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - - -#define DEFAULT_N_STR_TYPE_GPS 2 - -#define DEFAULT_SUPP_STR_TYPES_GPS \ - ( ( 1UL << DEFAULT_N_STR_TYPE_GPS ) - 1 ) - - -/* - * The macro below can be used to initialize a - * RECEIVER_INFO structure for old GPS receiver models - * which don't supply that structure. - * - * Parameters: (RECEIVER_INFO *) _p - */ -#define _setup_default_receiver_info_gps( _p ) \ -do \ -{ \ - memset( (_p), 0, sizeof( *(_p) ) ); \ - \ - (_p)->ticks_per_sec = DEFAULT_GPS_TICKS_PER_SEC; \ - (_p)->n_ucaps = 2; \ - (_p)->n_com_ports = DEFAULT_N_COM; \ - (_p)->n_str_type = DEFAULT_N_STR_TYPE_GPS; \ -} while ( 0 ) - - -_ext BAUD_RATE mbg_baud_rate[N_MBG_BAUD_RATES] -#ifdef _DO_INIT - = MBG_BAUD_RATES -#endif -; - -_ext const char *mbg_baud_str[N_MBG_BAUD_RATES] -#ifdef _DO_INIT - = MBG_BAUD_STRS -#endif -; - -_ext const char *mbg_framing_str[N_MBG_FRAMINGS] -#ifdef _DO_INIT - = MBG_FRAMING_STRS -#endif -; - - -/* ----- function prototypes begin ----- */ - -/* This section was generated automatically */ -/* by MAKEHDR, do not remove the comments. */ - - int get_str_idx( const char *search, const char *str_table[], int n_entries ) ; - int get_baud_rate_idx( BAUD_RATE baud_rate ) ; - int get_framing_idx( const char *framing ) ; - void port_settings_from_port_parm_mode( PORT_SETTINGS *p_ps, uint8_t pp_mode, int str_type_cap ) ; - void port_parm_mode_from_port_settings( uint8_t *pp_mode, const PORT_SETTINGS *p_ps, int str_type_cap ) ; - void port_settings_from_port_parm( PORT_SETTINGS *p_ps, int port_num, const PORT_PARM *p_pp, int cap_str_idx ) ; - void port_parm_from_port_settings( PORT_PARM *p_pp, int port_num, const PORT_SETTINGS *p_ps, int cap_str_idx ) ; - int check_valid_port_info( const PORT_INFO *p, const STR_TYPE_INFO_IDX str_type_info_idx[], int n_str_type ) ; - int valid_port_info( const PORT_INFO *p, const STR_TYPE_INFO_IDX str_type_info_idx[], int n_str_type ) ; - -/* ----- function prototypes end ----- */ - - -#ifdef __cplusplus -} -#endif - - -#if defined( _USE_PACK ) // set default alignment - #pragma pack() -#endif - -/* End of header body */ - -#undef _ext -#undef _DO_INIT - -#endif /* _PARMGPS_H */ - diff --git a/src/external/bsd/meinberg/dist/mbglib/common/parmpcps.c b/src/external/bsd/meinberg/dist/mbglib/common/parmpcps.c deleted file mode 100755 index cd02754..0000000 --- a/src/external/bsd/meinberg/dist/mbglib/common/parmpcps.c +++ /dev/null @@ -1,115 +0,0 @@ - -/************************************************************************** - * - * $Id: parmpcps.c 1.4 2004/11/09 14:24:15 martin REL_M $ - * - * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany - * - * Description: - * Functions to handle/convert parameters used by Meinberg plug-in - * radio clocks. - * - * ----------------------------------------------------------------------- - * $Log: parmpcps.c $ - * Revision 1.4 2004/11/09 14:24:15 martin - * Redefined interface data types using C99 fixed-size definitions. - * Revision 1.3 2003/04/17 10:43:35Z martin - * Moved some definitions to parmpcps.h. - * Removed some functions which are now in mbgdevio.c. - * Revision 1.2 2002/03/25 09:03:43Z MARTIN - * Fixed a bug where the wrong framing was configured for DCF77 clocks. - * Revision 1.1 2002/02/19 14:00:19 MARTIN - * Initial revision - * - **************************************************************************/ - -#define _PARMPCPS - #include <parmpcps.h> -#undef _PARMPCPS - -#include <parmgps.h> -#include <pcpsutil.h> -#include <myutil.h> - -#include <string.h> - - -static const int pcps_to_mbg_framing_tbl[N_PCPS_FR_DCF] = -{ - MBG_FRAMING_8N1, - MBG_FRAMING_7E2, - MBG_FRAMING_8N2, - MBG_FRAMING_8E1 -}; - - - -/*HDR*/ -void port_info_from_pcps_serial( - PORT_INFO_IDX *p_pii, - PCPS_SERIAL pcps_serial, - uint32_t supp_baud_rates -) -{ - PCPS_SER_PACK ser_pack; - PORT_INFO *p_pi; - PORT_SETTINGS *p_ps; - - ser_pack.pack = pcps_serial; - pcps_unpack_serial( &ser_pack ); - - p_pi = &p_pii[0].port_info; - p_ps = &p_pi->port_settings; - - p_ps->parm.baud_rate = mbg_baud_rate[ser_pack.baud]; - - _strncpy_0( p_ps->parm.framing, - mbg_framing_str[pcps_to_mbg_framing_tbl[ser_pack.frame]] ); - - p_ps->parm.handshake = HS_NONE; - - p_ps->str_type = 0; - p_ps->mode = ser_pack.mode; - - p_pi->supp_baud_rates = supp_baud_rates; - p_pi->supp_framings = DEFAULT_FRAMINGS_DCF; - p_pi->supp_str_types = DEFAULT_SUPP_STR_TYPES_DCF; - -} // port_info_from_pcps_serial - - -/*HDR*/ -void pcps_serial_from_port_info( - PCPS_SERIAL *p, - const PORT_INFO_IDX *p_pii -) -{ - PCPS_SER_PACK ser_pack; - const PORT_INFO *p_pi = &p_pii[0].port_info; - const PORT_SETTINGS *p_ps = &p_pi->port_settings; - int framing_idx = get_framing_idx( p_ps->parm.framing ); - int i; - - - ser_pack.baud = get_baud_rate_idx( p_ps->parm.baud_rate ); - - // Translate the common framing index to the corresponding - // number used with the old PCPS_SERIAL parameter. - // This should always return a valid result since the - // framing index is expected to be selected from - // supported framings. - for ( i = 0; i < N_PCPS_FR_DCF; i++ ) - if ( pcps_to_mbg_framing_tbl[i] == framing_idx ) - break; - - ser_pack.frame = i; - - ser_pack.mode = p_ps->mode; - - pcps_pack_serial( &ser_pack ); - - *p = ser_pack.pack; - -} // pcps_serial_from_port_info - - diff --git a/src/external/bsd/meinberg/dist/mbglib/common/parmpcps.h b/src/external/bsd/meinberg/dist/mbglib/common/parmpcps.h deleted file mode 100755 index 7095d48..0000000 --- a/src/external/bsd/meinberg/dist/mbglib/common/parmpcps.h +++ /dev/null @@ -1,159 +0,0 @@ - -/************************************************************************** - * - * $Id: parmpcps.h 1.7 2011/04/01 10:30:51 martin REL_M $ - * - * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany - * - * Description: - * Definitions and prototypes for parmpcps.c. - * - * ----------------------------------------------------------------------- - * $Log: parmpcps.h $ - * Revision 1.7 2011/04/01 10:30:51 martin - * Fixed macro syntax for _setup_default_receiver_info_dcf(). - * Revision 1.6 2011/02/16 10:13:12 martin - * Fixed macro syntax for _setup_default_receiver_info_pcps(). - * Revision 1.5 2004/11/09 14:24:58Z martin - * Updated function prototypes. - * Revision 1.4 2004/05/19 07:52:25Z martin - * Fixed macro setting default number of string types. - * Revision 1.3 2004/04/14 09:21:44Z martin - * Pack structures 1 byte aligned. - * Revision 1.2 2003/04/17 10:42:46Z martin - * Moved typedef RECEIVER_PORT_CFG to pcpsdev.h. - * Moved some definitions from parmpcps.c here. - * Removed some global variables. - * Updated function prototypes. - * Revision 1.1 2002/02/19 14:00:19Z MARTIN - * Initial revision - * - **************************************************************************/ - -#ifndef _PARMPCPS_H -#define _PARMPCPS_H - -/* Other headers to be included */ - -#include <pcpsdev.h> -#include <use_pack.h> - - -#ifdef _PARMPCPS - #define _ext - #define _DO_INIT -#else - #define _ext extern -#endif - - -/* Start of header body */ - -#if defined( _USE_PACK ) // set byte alignment - #pragma pack( 1 ) -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - - -#define DEFAULT_BAUD_RATES_DCF \ -( \ - MBG_PORT_HAS_300 | \ - MBG_PORT_HAS_600 | \ - MBG_PORT_HAS_1200 | \ - MBG_PORT_HAS_2400 | \ - MBG_PORT_HAS_4800 | \ - MBG_PORT_HAS_9600 \ -) - -#define DEFAULT_BAUD_RATES_DCF_HS \ -( \ - MBG_PORT_HAS_300 | \ - MBG_PORT_HAS_600 | \ - MBG_PORT_HAS_1200 | \ - MBG_PORT_HAS_2400 | \ - MBG_PORT_HAS_4800 | \ - MBG_PORT_HAS_9600 | \ - MBG_PORT_HAS_19200 | \ - MBG_PORT_HAS_38400 \ -) - - -#define DEFAULT_FRAMINGS_DCF \ -( \ - MBG_PORT_HAS_7E2 | \ - MBG_PORT_HAS_8N1 | \ - MBG_PORT_HAS_8N2 | \ - MBG_PORT_HAS_8E1 \ -) - - -#define DEFAULT_N_STR_TYPE_DCF 1 - -#define DEFAULT_SUPP_STR_TYPES_DCF \ - ( ( 1UL << DEFAULT_N_STR_TYPE_DCF ) - 1 ) - - -/* - * The macro below can be used to initialize a - * RECEIVER_INFO structure for DCF77 receivers - * which don't supply that structure. - * - * Parameters: (RECEIVER_INFO *) _p - */ -#define _setup_default_receiver_info_dcf( _p, _pdev ) \ -do \ -{ \ - memset( (_p), 0, sizeof( *(_p) ) ); \ - \ - (_p)->ticks_per_sec = DEFAULT_GPS_TICKS_PER_SEC; \ - (_p)->n_ucaps = 0; \ - (_p)->n_com_ports = _pcps_has_serial( _pdev ) ? 1 : 0; \ - (_p)->n_str_type = ( (_p)->n_com_ports != 0 ) ? \ - DEFAULT_N_STR_TYPE_DCF : 0; \ -} while ( 0 ) - - -#define DEFAULT_MAX_STR_TYPE 2 //##++ DEFAULT_N_STR_TYPE_GPS - -_ext STR_TYPE_INFO default_str_type_info[DEFAULT_MAX_STR_TYPE] -#ifdef _DO_INIT - = { - { DEFAULT_STR_MODES, "Default Time String", "Time", 0 }, - { DEFAULT_STR_MODES_UCAP, "Capture String", "Cap", 0 } - } -#endif -; - - - -/* ----- function prototypes begin ----- */ - -/* This section was generated automatically */ -/* by MAKEHDR, do not remove the comments. */ - - void port_info_from_pcps_serial( PORT_INFO_IDX *p_pii, PCPS_SERIAL pcps_serial, uint32_t supp_baud_rates ) ; - void pcps_serial_from_port_info( PCPS_SERIAL *p, const PORT_INFO_IDX *p_pii ) ; - -/* ----- function prototypes end ----- */ - - -#ifdef __cplusplus -} -#endif - - -#if defined( _USE_PACK ) // set default alignment - #pragma pack() -#endif - -/* End of header body */ - - -#undef _ext -#undef _DO_INIT - -#endif /* _PARMPCPS_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pci.h b/src/external/bsd/meinberg/dist/mbglib/common/pci.h index fc8abb5..8f0a644 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pci.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/pci.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pci.h 1.9 2008/01/30 13:42:29 martin REL_M $ + * $Id: pci.h 1.10 2017/05/10 15:24:21 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,8 @@ * * ----------------------------------------------------------------------- * $Log: pci.h $ + * Revision 1.10 2017/05/10 15:24:21 martin + * Tiny cleanup. * Revision 1.9 2008/01/30 13:42:29 martin * Code cleanup to support different build environments properly. * Revision 1.8 2006/07/11 08:59:00Z martin @@ -67,7 +69,6 @@ #endif - #ifdef _PCI #define _ext #else @@ -77,6 +78,10 @@ /* Start of header body */ +#ifdef __cplusplus +extern "C" { +#endif + #if !defined( pci_fnc_init ) #define pci_fnc_init() 0 #endif @@ -132,16 +137,6 @@ #endif // defined( MBG_PCI_MACROS_MAP_GENERIC ) -/* End of header body */ - -#undef _ext - - -/* function prototypes: */ - -#ifdef __cplusplus -extern "C" { -#endif /* ----- function prototypes begin ----- */ @@ -157,6 +152,10 @@ extern "C" { #endif +/* End of header body */ + +#undef _ext + #endif /* _PCI_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pci_asic.h b/src/external/bsd/meinberg/dist/mbglib/common/pci_asic.h index cc859f4..3bbba03 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pci_asic.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/pci_asic.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pci_asic.h 1.20 2011/06/30 13:52:26 martin REL_M $ + * $Id: pci_asic.h 1.29 2017/07/04 14:18:03 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,7 +10,26 @@ * * ----------------------------------------------------------------------- * $Log: pci_asic.h $ - * Revision 1.20 2011/06/30 13:52:26 martin + * Revision 1.29 2017/07/04 14:18:03 martin + * Updated minor version for PTP270PEX. + * Revision 1.28 2017/05/10 15:24:21 martin + * Tiny cleanup. + * Revision 1.27 2017/04/25 11:36:30 martin + * Renamed GRC181PEX to GNS181PEX. + * Revision 1.26 2016/09/15 14:55:02 martin + * Support GRC181PEX. + * Added doxgen comments. + * Revision 1.25 2014/10/17 11:38:39 martin + * Updated version info for GPS180PEX. + * Revision 1.24 2013/10/01 15:29:39 martin + * Updated version info for PTP270PEX. + * Revision 1.23 2013/06/26 15:57:07Z martin + * Support GLN180PEX. + * Revision 1.22 2011/10/05 09:46:12 martin + * Updated version info for GPS180PEX. + * Revision 1.21 2011/09/13 07:36:21Z martin + * Updated version info for GPS180PEX. + * Revision 1.20 2011/06/30 13:52:26Z martin * Updated version info for GPS180PEX. * Revision 1.19 2011/06/29 08:58:32Z martin * Support PZF180PEX. @@ -32,7 +51,7 @@ * Modified syntax of macro _convert_asic_version_number(). * Added macros to deal with the ASIC version number. * Added definition PCI_ASIC_HAS_PGMB_IRQ. - * Added ASIC revision numbers for PEX511, TCR511PEX, and GPS170PEX + * Added ASIC revision numbers for PEX511, TCR511PEX, and GPS170PEX * which fix an IRQ bug with these cards. * Added definitions for PTP270PEX, FRC511PEX, and TCR170PEX. * Revision 1.12 2008/07/21 10:30:00Z martin @@ -58,7 +77,7 @@ * Revision 1.4 2004/10/14 15:01:23 martin * Added support for TCR167PCI. * Revision 1.3 2003/05/13 14:38:55Z MARTIN - * Added ushort fields to unions PCI_ASIC_REG and + * Added ushort fields to unions PCI_ASIC_REG and * PCI_ASIC_ADDON_DATA. * Revision 1.2 2003/04/03 10:56:38 martin * Use unions for registers. @@ -92,77 +111,145 @@ #define _USING_BYTE_ALIGNMENT #endif +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set of PCI ASIC registers which are writeable once after power-up + **/ typedef struct { uint32_t cfg_class_rev_id; uint16_t cfg_badr_0; uint16_t cfg_dev_id; + } PCI_ASIC_CFG; +/** + * @brief A PCI ASIC register as 32, 16, or 8 bit accessible union + */ typedef union { uint32_t ul; uint16_t us[2]; uint8_t b[4]; + } PCI_ASIC_REG; + +/** + * @brief A data type to hold the PCI ASIC version code + */ typedef uint32_t PCI_ASIC_VERSION; + #define _mbg_swab_asic_version( _p ) _mbg_swab32( _p ) + + +/** + * @brief A data type to hold the PCI ASIC feature flags mask + * + * @see @ref PCI_ASIC_FEATURE_MASKS + */ typedef uint32_t PCI_ASIC_FEATURES; + #define _mbg_swab_asic_features( _p ) _mbg_swab32( _p ) -#define PCI_ASIC_HAS_MM_IO 0x0001 -#define PCI_ASIC_HAS_PGMB_IRQ 0x0002 +/** + * @brief Bit masks used with ::PCI_ASIC_FEATURES + * + * @see ::PCI_ASIC_FEATURES + * + * @anchor PCI_ASIC_FEATURE_MASKS @{ */ + +#define PCI_ASIC_HAS_MM_IO 0x0001 ///< The device supports memory mapped I/O +#define PCI_ASIC_HAS_PGMB_IRQ 0x0002 ///< The device supports programmable interrupts (yet not used) + +/** @} anchor PCI_ASIC_FEATURE_MASKS */ + + + +/** + * @brief The addon-data part of a PCI ASIC + */ typedef union { uint32_t ul[4]; uint16_t us[8]; uint8_t b[16]; + } PCI_ASIC_ADDON_DATA; + +/** + * @brief Register layout of a PCI ASIC + */ typedef struct { - PCI_ASIC_CFG cfg; // writeable from add-on once after power-up - PCI_ASIC_VERSION raw_version; - PCI_ASIC_FEATURES features; - PCI_ASIC_REG status_port; - PCI_ASIC_REG control_status; // codes defined below - PCI_ASIC_REG pci_data; // pass byte from PCI bus to add-on - PCI_ASIC_REG reserved_1; - - PCI_ASIC_ADDON_DATA addon_data; // returns data from add-on to PCI bus - PCI_ASIC_ADDON_DATA reserved_2; // currently not implemented + PCI_ASIC_CFG cfg; ///< Registers which are writeable from add-on once after power-up + PCI_ASIC_VERSION raw_version; ///< Raw version code + PCI_ASIC_FEATURES features; ///< PCI ASIC feature mask, see @ref PCI_ASIC_FEATURE_MASKS + PCI_ASIC_REG status_port; ///< The status port register + PCI_ASIC_REG control_status; ///< See @ref PCI_ASIC_CONTROL_STATUS_MASKS + PCI_ASIC_REG pci_data; ///< Register used to pass byte from PCI bus to add-on side + PCI_ASIC_REG reserved_1; ///< Currently not implemented / used + + PCI_ASIC_ADDON_DATA addon_data; ///< Register set used to return data from add-on to PCI bus + PCI_ASIC_ADDON_DATA reserved_2; ///< Currently not implemented / used + } PCI_ASIC; -// The following bits are used with the control_status register. -// All other bits are reserved for future use. -// The IRQ flag for the add-on side is set whenever data is -// written to the cmd register. It is cleared if the add-on -// microcontroller writes this bit back to the control_status -// register. If the bit is set, the add-on signals /ADD_ON_IRQ -// and ADD_ON_BUSY are asserted. +/** + * @brief Bit masks used with ::PCI_ASIC::control_status + * + * @see ::PCI_ASIC + * + * @anchor PCI_ASIC_CONTROL_STATUS_MASKS @{ */ + +/** + * @brief Add-on IRQ flag + * + * The IRQ flag for the add-on side is set whenever data is + * written to the cmd register. It is cleared if the add-on + * microcontroller writes this bit back to the control_status + * register. If the bit is set, the add-on signals /ADD_ON_IRQ + * and ADD_ON_BUSY are asserted. + */ #define PCI_ASIC_ADD_ON_IRQF 0x00000001UL -// The IRQ flag for the PCI bus is set whenever the add-on -// microcontroller asserts the ASIC's /PCI_IRQ line, or the -// add-on microcontroller sets this bit to 1. It is cleared -// if this bit is written back from the PCI side. If the bit -// is set, an IRQ is asserted on the PCI bus. +/** + * @brief PCI IRQ flag + * + * The IRQ flag for the PCI bus is set whenever the add-on + * microcontroller asserts the ASIC's /PCI_IRQ line, or the + * add-on microcontroller sets this bit to 1. It is cleared + * if this bit is written back from the PCI side. If the bit + * is set, an IRQ is asserted on the PCI bus. + */ #define PCI_ASIC_PCI_IRQF 0x00010000UL +// NOTE All other bits are reserved for future use. + +/** @} anchor PCI_ASIC_CONTROL_STATUS_MASKS */ -// The ASIC's address decoder always decodes 8 bits, so -// each device must request at least that number of -// addresses from the PCI BIOS: + + +/** + * @brief PCI address range + * + * The ASIC's address decoder always decodes 8 bits, so + * each device must request at least this number of + * addresses from the PCI BIOS. + */ #define PCI_ASIC_ADDR_RANGE 0x100U @@ -221,34 +308,42 @@ typedef struct _hilo_16( PCI_DEV_TCR511PCI ) \ } -/* - Handling of the version numbers of the PCI interface - chips has changed between the ASICs used for standard PCI - and the EPLDs used to configure the PEX8311 chip - for a specific device. - The macro below can be used to convert both types - of version number into the same format so that the - version numbers can be handled in the same way: -*/ + +/** + * @brief Version number conversion macro + * + * Handling of the version numbers of the PCI interface + * chips has changed between the ASICs used for standard PCI + * and the EPLDs used to configure the PEX8311 chip + * for a specific device. + * + * This macro can be used to convert both types of + * version number into the same format so that the + * version numbers can be handled in the same way + */ #define _convert_asic_version_number( _n ) \ ( ( (_n) < 0x100 ) ? ( (_n) << 8 ) : (_n) ) -/* - * Macros to extract the major and minor part of an ASIC version number */ - +/** + * @brief Extract the major part of an ASIC version number + */ #define _pcps_asic_version_major( _v ) \ ( ( (_v) >> 8 ) & 0xFF ) + +/** + * @brief Extract the minor part of an ASIC version number + */ #define _pcps_asic_version_minor( _v ) \ ( (_v) & 0xFF ) -/* - * Macros to check whether a version number is correct - * and matches a required minimum version + +/** + * @brief Check whether a version number is correct and matches a required minimum version */ #define _pcps_asic_version_greater_equal( _v, _v_major, _v_minor ) \ ( \ @@ -257,69 +352,86 @@ typedef struct ) -/* - The low byte of the converted version number is handled - as a minor version, whereas the remaining upper bytes are - interpreted as a major number which may be specific - for a device. -*/ -enum + +/** + * @brief ASIC major version numbers + * + * @see @ref PCI_ASIC_MINOR_VERSION_NUMBERS + */ +enum PCI_ASIC_MAJOR_VERSION_NUMBERS { - PCI_ASIC_MAJOR_PCI_0, // PCI ASIC with CRC bug - PCI_ASIC_MAJOR_PCI_1, // fixed version of PCI ASIC - PCI_ASIC_MAJOR_PEX511, // PEX EPLD for PEX511 - PCI_ASIC_MAJOR_GPS170PEX, // PEX EPLD for GPS170PEX - PCI_ASIC_MAJOR_TCR511PEX, // PEX EPLD for TCR511PEX - PCI_ASIC_MAJOR_PTP270PEX, // PEX EPLD for PTP270PEX - PCI_ASIC_MAJOR_FRC511PEX, // PEX EPLD for FRC511PEX - PCI_ASIC_MAJOR_TCR170PEX, // PEX EPLD for TCR170PEX - PCI_ASIC_MAJOR_GPS180PEX, // PEX EPLD for GPS180PEX - PCI_ASIC_MAJOR_TCR180PEX, // PEX EPLD for TCR180PEX - PCI_ASIC_MAJOR_PZF180PEX, // PEX EPLD for PZF180PEX - N_PCI_ASIC_MAJOR // the number of known codes + PCI_ASIC_MAJOR_PCI_0, ///< PCI ASIC with CRC bug + PCI_ASIC_MAJOR_PCI_1, ///< fixed version of PCI ASIC + PCI_ASIC_MAJOR_PEX511, ///< PEX EPLD for PEX511 + PCI_ASIC_MAJOR_GPS170PEX, ///< PEX EPLD for GPS170PEX + PCI_ASIC_MAJOR_TCR511PEX, ///< PEX EPLD for TCR511PEX + PCI_ASIC_MAJOR_PTP270PEX, ///< PEX EPLD for PTP270PEX + PCI_ASIC_MAJOR_FRC511PEX, ///< PEX EPLD for FRC511PEX + PCI_ASIC_MAJOR_TCR170PEX, ///< PEX EPLD for TCR170PEX + PCI_ASIC_MAJOR_GPS180PEX, ///< PEX EPLD for GPS180PEX/GPS180AMC + PCI_ASIC_MAJOR_TCR180PEX, ///< PEX EPLD for TCR180PEX + PCI_ASIC_MAJOR_PZF180PEX, ///< PEX EPLD for PZF180PEX + PCI_ASIC_MAJOR_GLN180PEX, ///< PEX EPLD for GLN180PEX + PCI_ASIC_MAJOR_GNS181PEX, ///< PEX EPLD for GNS181PEX + N_PCI_ASIC_MAJOR ///< the number of known codes }; -/* - The minor number increases when a new EPLD image is released. - At least EPLD images with the following "required minor" numbers - should be installed for proper operation. The "current minor" - numbers can be used to check if a newer EPLD image is available: -*/ + + +/** + * @brief ASIC minor version definitions + * + * The minor number increases when a new EPLD image is released. + * At least EPLD images with the defined "required minor" numbers + * should be installed for proper operation. The "current minor" + * numbers can be used to check if a newer EPLD image is available. + * + * @see ::PCI_ASIC_MAJOR_VERSION_NUMBERS + * + * @anchor PCI_ASIC_MINOR_VERSION_NUMBERS @{ */ + #define PCI_ASIC_CURRENT_MINOR_PEX511 0x04 #define PCI_ASIC_REQUIRED_MINOR_PEX511 0x03 -#define PCI_ASIC_FIX_HRT_MINOR_PEX511 0x04 // increases HRT accuracy -#define PCI_ASIC_FIX_IRQ_MINOR_PEX511 0x03 // fixes IRQ problem -#define PCI_ASIC_HR_TIME_MINOR_PEX511 0x02 // supports HR time with PEX511 +#define PCI_ASIC_FIX_HRT_MINOR_PEX511 0x04 // Increases HRT accuracy +#define PCI_ASIC_FIX_IRQ_MINOR_PEX511 0x03 // Fixes IRQ problem +#define PCI_ASIC_HR_TIME_MINOR_PEX511 0x02 // Supports HR time with PEX511 #define PCI_ASIC_CURRENT_MINOR_GPS170PEX 0x05 #define PCI_ASIC_REQUIRED_MINOR_GPS170PEX 0x03 -#define PCI_ASIC_ENH_HRT_MINOR_GPS170PEX 0x05 // enhanced MM HRT accuracy -#define PCI_ASIC_FIX_HRT_MINOR_GPS170PEX 0x04 // increases MM HRT accuracy -#define PCI_ASIC_FIX_IRQ_MINOR_GPS170PEX 0x03 // fixes IRQ problem +#define PCI_ASIC_ENH_HRT_MINOR_GPS170PEX 0x05 // Enhanced MM HRT accuracy +#define PCI_ASIC_FIX_HRT_MINOR_GPS170PEX 0x04 // Increases MM HRT accuracy +#define PCI_ASIC_FIX_IRQ_MINOR_GPS170PEX 0x03 // Fixes IRQ problem #define PCI_ASIC_CURRENT_MINOR_TCR511PEX 0x04 #define PCI_ASIC_REQUIRED_MINOR_TCR511PEX 0x03 // 0x04 // EPLD sources shared with PEX511 0x04 -#define PCI_ASIC_FIX_IRQ_MINOR_TCR511PEX 0x03 // fixes IRQ problem, increases HRT accuracy +#define PCI_ASIC_FIX_IRQ_MINOR_TCR511PEX 0x03 // Fixes IRQ problem, increases HRT accuracy -#define PCI_ASIC_CURRENT_MINOR_PTP270PEX 0x02 +#define PCI_ASIC_CURRENT_MINOR_PTP270PEX 0x06 #define PCI_ASIC_REQUIRED_MINOR_PTP270PEX 0x01 -// 0x02 // increased accuracy of IRIG DCLS slopes -// 0x01 // supports inversion of ucap slopes +// 0x06 // Supports 1 PPS pulse shift +// 0x05 // ... +// 0x04 // ... +// 0x03 // ... +// 0x02 // Increased accuracy of IRIG DCLS slopes +// 0x01 // Supports inversion of ucap slopes #define PCI_ASIC_CURRENT_MINOR_FRC511PEX 0x01 #define PCI_ASIC_REQUIRED_MINOR_FRC511PEX 0x01 #define PCI_ASIC_CURRENT_MINOR_TCR170PEX 0x03 #define PCI_ASIC_REQUIRED_MINOR_TCR170PEX 0x02 -#define PCI_ASIC_FIX_EE_ACCESS_TCR170PEX 0x02 // fixes EE access problem after reset -#define PCI_ASIC_FIX_FO_IN_LEVEL_TCR170PEX 0x03 // correct polarity for fiber optic input +#define PCI_ASIC_FIX_EE_ACCESS_TCR170PEX 0x02 // Fixes EE access problem after reset +#define PCI_ASIC_FIX_FO_IN_LEVEL_TCR170PEX 0x03 // Correct polarity for fiber optic input -#define PCI_ASIC_CURRENT_MINOR_GPS180PEX 0x03 +#define PCI_ASIC_CURRENT_MINOR_GPS180PEX 0x06 #define PCI_ASIC_REQUIRED_MINOR_GPS180PEX 0x01 -// 0x01 // updated VHDL compiler and associated PCI primitives +// 0x01 // Updated VHDL compiler and associated PCI primitives // 0x02 // I/O using 3.3V LVTTL // 0x03 // GPS TIC pulse len now 1 sample clock +// 0x04 // Enabled PCI IRQ line which had unintentionally been disabled earlier +// 0x05 // Increased accuracy of synthesizer output +// 0x06 // T0 AUX Capture used by firmware v2.0x #define PCI_ASIC_CURRENT_MINOR_TCR180PEX 0x00 #define PCI_ASIC_REQUIRED_MINOR_TCR180PEX 0x00 @@ -327,15 +439,38 @@ enum #define PCI_ASIC_CURRENT_MINOR_PZF180PEX 0x00 #define PCI_ASIC_REQUIRED_MINOR_PZF180PEX 0x00 +#define PCI_ASIC_CURRENT_MINOR_GLN180PEX 0x00 +#define PCI_ASIC_REQUIRED_MINOR_GLN180PEX 0x00 + +#define PCI_ASIC_CURRENT_MINOR_GNS181PEX 0x00 +#define PCI_ASIC_REQUIRED_MINOR_GNS181PEX 0x00 + +/** @} anchor PCI_ASIC_MINOR_VERSION_NUMBERS */ + + +/** + * @brief A structure holding version information for a specific device + * + * @see ::DEFAULT_PCI_ASIC_VERSION_INFO_TABLE + */ typedef struct { unsigned int dev_type_num; unsigned int major; unsigned int current_minor; unsigned int required_minor; + } PCI_ASIC_VERSION_INFO; + +/** + * @brief An initializer for a table of ASIC version information for all known devices + * + * @note GPS180AMC uses the same ASIC as GPS180PEX + * + * @see ::PCI_ASIC_VERSION_INFO + */ #define DEFAULT_PCI_ASIC_VERSION_INFO_TABLE \ { \ { PCPS_TYPE_PEX511, PCI_ASIC_MAJOR_PEX511, PCI_ASIC_CURRENT_MINOR_PEX511, PCI_ASIC_REQUIRED_MINOR_PEX511 }, \ @@ -347,16 +482,13 @@ typedef struct { PCPS_TYPE_GPS180PEX, PCI_ASIC_MAJOR_GPS180PEX, PCI_ASIC_CURRENT_MINOR_GPS180PEX, PCI_ASIC_REQUIRED_MINOR_GPS180PEX }, \ { PCPS_TYPE_TCR180PEX, PCI_ASIC_MAJOR_TCR180PEX, PCI_ASIC_CURRENT_MINOR_TCR180PEX, PCI_ASIC_REQUIRED_MINOR_TCR180PEX }, \ { PCPS_TYPE_PZF180PEX, PCI_ASIC_MAJOR_PZF180PEX, PCI_ASIC_CURRENT_MINOR_PZF180PEX, PCI_ASIC_REQUIRED_MINOR_PZF180PEX }, \ + { PCPS_TYPE_GLN180PEX, PCI_ASIC_MAJOR_GLN180PEX, PCI_ASIC_CURRENT_MINOR_GLN180PEX, PCI_ASIC_REQUIRED_MINOR_GLN180PEX }, \ + { PCPS_TYPE_GPS180AMC, PCI_ASIC_MAJOR_GPS180PEX, PCI_ASIC_CURRENT_MINOR_GPS180PEX, PCI_ASIC_REQUIRED_MINOR_GPS180PEX }, \ + { PCPS_TYPE_GNS181PEX, PCI_ASIC_MAJOR_GNS181PEX, PCI_ASIC_CURRENT_MINOR_GNS181PEX, PCI_ASIC_REQUIRED_MINOR_GNS181PEX }, \ { 0 } \ } -/* function prototypes: */ - -#ifdef __cplusplus -extern "C" { -#endif - /* ----- function prototypes begin ----- */ /* This section was generated automatically */ @@ -382,4 +514,3 @@ extern "C" { #undef _DO_INIT #endif /* _PCI_ASIC_H */ - diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcidefs.h b/src/external/bsd/meinberg/dist/mbglib/common/pcidefs.h index ed365d2..83c503d 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pcidefs.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/pcidefs.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pcidefs.h 1.7 2008/06/09 10:43:09 martin REL_M $ + * $Id: pcidefs.h 1.9 2017/05/10 15:24:15 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,7 +10,13 @@ * * ----------------------------------------------------------------------- * $Log: pcidefs.h $ - * Revision 1.7 2008/06/09 10:43:09 martin + * Revision 1.9 2017/05/10 15:24:15 martin + * Tiny cleanup. + * Revision 1.8 2013/09/26 09:26:34 martin + * Added num of addr regs for PCI CFG header type 0x01. + * Re-ordered definition of PCI vendor IDs based on numerical code. + * Added some PCI vendor IDs. + * Revision 1.7 2008/06/09 10:43:09Z martin * Added PCI_CMD_ENB_MEM_ACC code. * Revision 1.6 2005/09/19 13:06:15Z martin * Added definition for number of base address registers. @@ -43,6 +49,9 @@ /* Start of header body */ +#ifdef __cplusplus +extern "C" { +#endif // Available PCI subfunction codes depend on the operating system // so they are defined in the associated headers. @@ -170,7 +179,8 @@ typedef struct #define PCI_CS_MIN_GNT 0x3E #define PCI_CS_MAX_LAT 0x3F -#define PCI_CS_N_BASE_ADDRESS 6 /* max number of address spaces */ +#define PCI_CS_N_BASE_ADDRESS 6 /* num of badr regs for header type 0x00 */ +#define PCI_CS_N_BASE_ADDRESS_01 2 /* num of badr regs for header type 0x01 */ #define PCI_CMD_ENB_IO_ACC 0x01 @@ -213,39 +223,45 @@ typedef struct -// some known vendor IDs, in alphabetical order: +// some known vendor IDs, in numerical order: -#define PCI_VENDOR_3COM 0x10B7 -#define PCI_VENDOR_ADAPTEC_1 0x9004 -#define PCI_VENDOR_ADAPTEC_2 0x9005 -#define PCI_VENDOR_AMCC 0x10E8 -#define PCI_VENDOR_AMD 0x1022 #define PCI_VENDOR_ASUS 0x1000 +#define PCI_VENDOR_ATI 0x1002 #define PCI_VENDOR_CIRRUS_LOGIC 0x1013 -#define PCI_VENDOR_ELSA 0x5333 #define PCI_VENDOR_IBM 0x1014 -#define PCI_VENDOR_INTEL 0x8086 +#define PCI_VENDOR_AMD 0x1022 #define PCI_VENDOR_MATROX 0x102B +#define PCI_VENDOR_NEC 0x1033 +#define PCI_VENDOR_TEXAS_INSTR 0x104C +#define PCI_VENDOR_PLX 0x10B5 +#define PCI_VENDOR_3COM 0x10B7 +#define PCI_VENDOR_AMCC 0x10E8 +#define PCI_VENDOR_REALTEK 0x10EC #define PCI_VENDOR_MEINBERG 0x1360 +#define PCI_VENDOR_JMICRON 0x197B +#define PCI_VENDOR_ELSA 0x5333 +#define PCI_VENDOR_INTEL 0x8086 +#define PCI_VENDOR_ADAPTEC_1 0x9004 +#define PCI_VENDOR_ADAPTEC_2 0x9005 -/* End of header body */ -#undef _ext +/* ----- function prototypes begin ----- */ +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ +/* (no header definitions found) */ -/* function prototypes: */ +/* ----- function prototypes end ----- */ #ifdef __cplusplus -extern "C" { +} #endif -// currently none -#ifdef __cplusplus -} -#endif +/* End of header body */ +#undef _ext #endif /* _PCIDEFS_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsdefs.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdefs.h index e29d384..d3fcf99 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pcpsdefs.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdefs.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pcpsdefs.h 1.46.1.11 2011/07/18 10:19:28 martin TRASH $ + * $Id: pcpsdefs.h 1.62 2017/07/04 16:24:53 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,36 +10,63 @@ * * ----------------------------------------------------------------------- * $Log: pcpsdefs.h $ - * Revision 1.46.1.11 2011/07/18 10:19:28 martin - * Added an initializer for a table of GPS command code/names. - * Revision 1.46.1.10 2011/07/06 11:21:38 martin - * Added commands to read CORR_INFO, and read/write TR_DISTANCE. - * Added swab macros for CORR_INFO and TR_DISTANCE. - * Modified some comments. - * Revision 1.46.1.9 2011/07/05 08:27:00 martin - * Comments only. - * Revision 1.46.1.8 2011/07/04 15:27:52 martin + * Revision 1.62 2017/07/04 16:24:53 martin + * Moved definitions PCPS_HRT_FRAC_SCALE and PCPS_HRT_FRAC_SCALE_FMT + * back here. + * New types PCPS_SECONDS and PCPS_FRAC_32. + * Fixed typo, wording, and doxygen comments. + * Revision 1.61 2017/04/25 11:38:38 martin + * Renamed GRC181PEX to GNS181PEX. + * Revision 1.60 2017/03/17 12:00:05 martin + * Moved definitions of PCPS_HRT_FRAC_CONVERSION_TYPE, + * PCPS_HRT_BIN_FRAC_SCALE, and PCPS_HRT_FRAC_SCALE_FMT + * to cfg_hlp.h. + * Revision 1.59 2017/01/27 08:11:19 martin + * Fixed macro syntax. + * Revision 1.58 2016/11/08 16:42:52 martin + * New GPS cmd codes PC_GPS_XFEATURE_BUFFER and PC_GPS_TLV_INFO. + * Revision 1.57 2016/11/08 16:40:39 martin + * Doxygen cleanup. + * Revision 1.56 2016/10/26 13:22:41 martin + * Added definitions for GRC181PEX. + * New symbol IRIG_TIME_UNKNOWN_YEAR. + * Removed trailing spaces. + * Updated doxygen comments. + * Revision 1.55 2014/07/17 10:52:24 martin + * Increased safety of firmware builds. + * Revision 1.54 2014/07/17 09:54:19 martin + * New command codes PC_GPS_XMR_HOLDOVER_STATUS + * and PC_GPS_ALL_GPIO_STATUS. + * Huge update and cleanup on doxygen comments. + * Revision 1.53 2014/05/27 10:13:20 martin + * Support GPS180AMC. + * Moved some signal constant definitions to pcpsdefs.h. + * Simplified declaration of code/name tables. + * Huge rework of comments in doxygen format. + * Revision 1.52 2013/09/26 09:02:52Z martin + * Support GNSS API. + * Updated doxygen comments. + * Revision 1.51 2013/06/25 09:51:39 martin + * Support GLN180PEX. + * Revision 1.50 2013/01/30 15:59:54 martin + * Updated and fixed some doxygen comments. + * Revision 1.49 2012/10/02 18:53:02 martin + * Added structure PCPS_TIME_STATUS_X_MASKS. + * Added initializer for command names, useful for debugging. + * Revision 1.48 2011/11/25 15:02:28 martin + * Support on-board event logs. + * Revision 1.47 2011/11/25 10:22:44 martin + * Modified handling of pragma pack(). * Made command group codes obsolete. They are still supported * when building firmware, though. - * Revision 1.46.1.7 2011/07/04 14:53:46 martin - * Added definitions MBG_PCPS_FMT_STATUS and PCPS_SYNC_PZF. - * Modified some comments. - * Revision 1.46.1.6 2011/06/29 14:08:28 martin - * Updated some comments. - * Revision 1.46.1.5 2011/06/29 09:10:25 martin - * Renamed PZF600PEX to PZF180PEX. - * Revision 1.46.1.4 2011/06/21 13:45:14 martin - * Support PZF600PEX. - * Renamed *_GPIO_CFG_INFO to *_GPIO_CFG_LIMITS - * to follow common naming conventions. * Support PTP unicast configuration. - * Modified handling of pragma pack(). - * Revision 1.46.1.3 2011/04/18 13:29:39 martin - * Doxygen changes. - * Revision 1.46.1.2 2011/04/07 15:56:25 martin * Support GPIO configuration. - * Revision 1.46.1.1 2011/02/15 10:55:28 daniel - * New command PC_GPS_PTP_UNICAST_CFG + * Support PZF180PEX. + * Added commands to read CORR_INFO, read/write TR_DISTANCE, + * PCPS_SYNC_PZF status, and associated structures. + * Added an initializer for a table of GPS command code/names. + * Added definitions MBG_PCPS_FMT_STATUS. + * Updated some comments. * Revision 1.46 2011/01/13 11:44:29Z martin * Moved status port register definitions here. * Revision 1.45 2010/09/06 07:36:24 martin @@ -81,12 +108,12 @@ * Added new REF type PCPS_REF_MSF. * Revision 1.35 2008/01/17 09:18:46Z daniel * Made comments compatible for doxygen parser. - * No sourcecode changes. + * No sourcecode changes. * Revision 1.34 2007/07/17 08:22:47Z martin * Added support for TCR511PEX and GPS170PEX. * Revision 1.33 2007/05/20 21:39:51Z martin * Added support for PEX511. - * Added PCPS_GET_STATUS_PORT cmd code for devices + * Added PCPS_GET_STATUS_PORT cmd code for devices * that do not support a hardware status port. * Revision 1.32 2007/03/29 12:57:32Z martin * Renamed some TZCODE numbers for unique naming conventions. @@ -118,14 +145,14 @@ * Support configuration of on-board frequency synthesizer. * Revision 1.21 2004/11/09 12:55:32Z martin * Redefined interface data types using C99 fixed-size definitions. - * Added workaround macros for some structure sizes because the C166 - * compiler always reports an even structure size even if the structure - * size is in fact odd, which might lead to different sizes in C166 and + * Added workaround macros for some structure sizes because the C166 + * compiler always reports an even structure size even if the structure + * size is in fact odd, which might lead to different sizes in C166 and * other environments. - * Modifications were required in order to be able to configure IRIG + * Modifications were required in order to be able to configure IRIG * settings of cards which provide both IRIG input and output. - * The existing codes have been renamed with .._RX.. and are used to - * configure the IRIG receiver (input). New codes have been defined + * The existing codes have been renamed with .._RX.. and are used to + * configure the IRIG receiver (input). New codes have been defined * used to configure the IRIG transmitter. * Renamed PC_GPS_STAT to PC_GPS_BVAR_STAT. * Use more specific data types than generic types. @@ -143,12 +170,12 @@ * fill level. * Revision 1.16 2003/04/03 10:48:53 martin * Support for PCI510, GPS169PCI, and TCR510PCI. - * New codes PCPS_GET_REF_OFFS, PCPS_SET_REF_OFFS + * New codes PCPS_GET_REF_OFFS, PCPS_SET_REF_OFFS * and related structures. * New codes PCPS_GET_OPT_INFO, PCPS_SET_OPT_SETTINGS * and related structures. * New codes PCPS_GET_IRIG_INFO, PCPS_SET_IRIG_SETTINGS. - * Preliminary PCPS_TZDL structure and cmd codes + * Preliminary PCPS_TZDL structure and cmd codes * to read/write that structure. * Revision 1.15 2002/08/08 13:24:03 MARTIN * Moved definition of ref time sources here. @@ -212,8 +239,8 @@ * Changes before put under RCS control: * * Revision 1.5 2000/03/24 - * Introduced PCPS_GIVE_SERNUM - * Cleaned up for definitions for serial parameter byte + * Introduced PCPS_GIVE_SERNUM. + * Cleaned up for definitions for serial parameter byte. * Reviewed and updated comments. * * 1998/07/22 @@ -222,7 +249,7 @@ * Reviewed and updated comments. * * 1997/06/12 - * GPS definitions added. + * Added GPS definitions. * * 1996/01/25 * PCPS_TIME redefined from an array of bytes to a structure. @@ -238,6 +265,13 @@ #include <words.h> #include <use_pack.h> +#ifndef _USE_PCPSPRIV + #define _USE_PCPSPRIV _IS_MBG_FIRMWARE +#endif + +#if _USE_PCPSPRIV + #include <pcpspriv.h> +#endif /* Start of header body */ @@ -250,25 +284,30 @@ /** * @brief Enumeration of the ref time signal sources used by Meinberg devices */ -enum +enum PCPS_REF_TYPES { - PCPS_REF_NONE, /**< (unknown or not defined) */ - PCPS_REF_DCF, /**< see http://www.meinberg.de/english/info/dcf77.htm */ - PCPS_REF_GPS, /**< see http://www.meinberg.de/english/info/gps.htm */ - PCPS_REF_IRIG, /**< see http://www.meinberg.de/english/info/irig.htm */ - PCPS_REF_MSF, /**< MSF Receiver (UK) */ - PCPS_REF_PTP, /**< PTP/IEEE1588 network protocol */ - PCPS_REF_FRC, /**< Free Running Clock */ - PCPS_REF_WWVB, /**< WWVB Receiver (US) */ - PCPS_REF_JJY, /**< JJY Receiver (Japan) */ - N_PCPS_REF /**< number of valid ref time sources */ + PCPS_REF_NONE, ///< unknown, or not defined + PCPS_REF_DCF, ///< DCF77 long wave signal (Germany), see http://www.meinberg.de/english/info/dcf77.htm + PCPS_REF_GPS, ///< GPS satellite system, see http://www.meinberg.de/english/info/gps.htm + PCPS_REF_IRIG, ///< IRIG or similar time code, see http://www.meinberg.de/english/info/irig.htm + PCPS_REF_MSF, ///< MSF long wave signal (UK) + PCPS_REF_PTP, ///< PTP/IEEE1588 network protocol + PCPS_REF_FRC, ///< Free Running Clock + PCPS_REF_WWVB, ///< WWVB long wave signal (U.S.) + PCPS_REF_JJY, ///< JJY long wave signal (Japan) + N_PCPS_REF ///< number of defined ref time sources }; -/* Initializers for the reference source names */ +/** + * @defgroup group_pcps_ref_type_names Reference type names + * + * @see ::PCPS_REF_TYPES + * + * @{ */ -#define PCPS_REF_NAME_NONE_ENG "unknown" -#define PCPS_REF_NAME_NONE_GER "nicht bekannt" +#define PCPS_REF_NAME_NONE_ENG "unknown" +#define PCPS_REF_NAME_NONE_GER "nicht bekannt" #define PCPS_REF_NAME_DCF "DCF77" #define PCPS_REF_NAME_GPS "GPS" #define PCPS_REF_NAME_IRIG "IRIG" @@ -278,7 +317,14 @@ enum #define PCPS_REF_NAME_WWVB "WWVB" #define PCPS_REF_NAME_JJY "JJY" +/** @} @defgroup group_pcps_ref_type_names */ + +/** + * @brief Initializer for an array of English reference type names + * + * @see ::PCPS_REF_TYPES + */ #define PCPS_REF_NAMES_ENG \ { \ PCPS_REF_NAME_NONE_ENG, \ @@ -293,6 +339,11 @@ enum } +/** + * @brief Initializer for a multi-language array of reference type names + * + * @see ::PCPS_REF_TYPES + */ #define PCPS_REF_NAMES_LSTR \ { \ { PCPS_REF_NAME_NONE_ENG, PCPS_REF_NAME_NONE_GER }, \ @@ -309,14 +360,23 @@ enum /** - * @brief Meinberg PCI vendor ID (assigned by PCI SIG) + * @brief Meinberg PCI vendor ID (assigned by the PCI SIG) + * + * @see @ref MEINBERG_PCI_DEVICE_IDS */ #define PCI_VENDOR_MEINBERG 0x1360 -/* PCI device ID numbers (assigned by Meinberg) * - * High byte: type of ref time source - * Low Byte: enumeration of device types - */ + +/** + * @brief PCI device IDs assigned by Meinberg + * + * High byte: type of ref time source, see ::PCPS_REF_TYPES + * Low Byte: enumeration of device types + * + * @see ::PCI_VENDOR_MEINBERG + * + * @anchor MEINBERG_PCI_DEVICE_IDS @{ */ + #define PCI_DEV_PCI32 ( ( PCPS_REF_DCF << 8 ) | 0x01 ) #define PCI_DEV_PCI509 ( ( PCPS_REF_DCF << 8 ) | 0x02 ) #define PCI_DEV_PCI510 ( ( PCPS_REF_DCF << 8 ) | 0x03 ) @@ -330,6 +390,9 @@ enum #define PCI_DEV_GPS170PCI ( ( PCPS_REF_GPS << 8 ) | 0x04 ) #define PCI_DEV_GPS170PEX ( ( PCPS_REF_GPS << 8 ) | 0x05 ) #define PCI_DEV_GPS180PEX ( ( PCPS_REF_GPS << 8 ) | 0x06 ) +#define PCI_DEV_GLN180PEX ( ( PCPS_REF_GPS << 8 ) | 0x07 ) +#define PCI_DEV_GPS180AMC ( ( PCPS_REF_GPS << 8 ) | 0x08 ) +#define PCI_DEV_GNS181PEX ( ( PCPS_REF_GPS << 8 ) | 0x09 ) #define PCI_DEV_TCR510PCI ( ( PCPS_REF_IRIG << 8 ) | 0x01 ) #define PCI_DEV_TCR167PCI ( ( PCPS_REF_IRIG << 8 ) | 0x02 ) @@ -342,37 +405,56 @@ enum #define PCI_DEV_FRC511PEX ( ( PCPS_REF_FRC << 8 ) | 0x01 ) +/** @} anchor MEINBERG_PCI_DEVICE_IDS */ -// definitions used for the status port register -// (not to be intermixed with PCPS_TIME_STATUS) -typedef uint8_t PCPS_STATUS_PORT; /**< see @ref group_status_port "Bitmask" */ /** - * @defgroup group_status_port Bit masks of PCPS_STATUS_PORT + * @defgroup group_status_port Definitions used with the status port * - * Bit definitions used with the #PCPS_STATUS_PORT register. + * The status port register on bus-level cards reflects some hardware + * signals (e.g. DCF-77 modulation), and flags used for communication + * with the card (e.g. the BUSY flag, ::PCPS_ST_BUSY). + * + * @note Must not be confused with ::PCPS_TIME_STATUS which returns + * the synchronization status and associated information + * + * @{ */ + +/** + * @brief Type of the status register port + */ +typedef uint8_t PCPS_STATUS_PORT; ///< see @ref PCPS_STATUS_PORT_BIT_MASKS + + +/** + * @brief Bit masks used with ::PCPS_STATUS_PORT * - * The flags #PCPS_ST_SEC and #PCPS_ST_MIN are cleared whenever the clock - * is read, so they are not very reliable in multitasking environments. + * The flags ::PCPS_ST_SEC and ::PCPS_ST_MIN are cleared whenever the clock + * is read, so they are not very reliable in multitasking environments + * and thus should be considered as deprecated. * - * @note The PCPS_ST_IRQF flag originates from old ISA cards. + * The ::PCPS_ST_IRQF flag was used with old ISA cards to check + * if the device has generated an IRQ. * Some PCI cards also support this, but in case of PCI cards the * associated flag of the PCI interface chip should be checked to see - * if a certain card has generated an IRQ on the PC bus. + * if a particular card has generated an IRQ on the PC bus. * - * The macro _pcps_ddev_has_gen_irq() cares about this and should be used + * The macro ::_pcps_ddev_has_gen_irq cares about this and should be used * to determine in a portable way whether a card has generated an IRQ. * - * @{ */ + * @anchor PCPS_STATUS_PORT_BIT_MASKS @{ */ + +#define PCPS_ST_BUSY 0x01 ///< the clock is busy filling the output FIFO +#define PCPS_ST_IRQF 0x02 ///< the clock has generated an IRQ on the PC bus (ISA cards only) +#define PCPS_ST_MOD 0x20 ///< the raw demodulated DCF77 signal +#define PCPS_ST_SEC 0x40 ///< seconds have changed since last reading +#define PCPS_ST_MIN 0x80 ///< minutes have changed since last reading + +/** @} anchor PCPS_STATUS_PORT_BIT_MASKS */ -#define PCPS_ST_BUSY 0x01 /**< the clock is busy filling the output FIFO */ -#define PCPS_ST_IRQF 0x02 /**< the clock has generated an IRQ on the PC bus (ISA only)*/ -#define PCPS_ST_MOD 0x20 /**< the raw demodulated DCF77 signal */ -#define PCPS_ST_SEC 0x40 /**< seconds have changed since last reading */ -#define PCPS_ST_MIN 0x80 /**< minutes have changed since last reading */ +/** @} defgroup group_status_port */ -/** @} group_status_port */ /** * A format string to be used with snprintb() which is available on some Unix @@ -384,615 +466,709 @@ typedef uint8_t PCPS_STATUS_PORT; /**< see @ref group_status_port "Bitmask" */ -/** @defgroup group_cmd_bytes Command bytes used to access the device - - The commands described below are used to access computer peripherals - manufactured by Meinberg. - - The header files pcpsdev.h and pcpsdrvr.h contain macros which can be - used to check if a detected device supports a certain feature or command. - If checking is required then the name of the macro is given in the - comments below. - - Some commands expect parameters to be passed to the board. In that - case, the board returns the number of parameter bytes expected when - the command code is passed. Every parameter byte has to be supplied - to the board exactly like a command byte. - Refer to function pcps_write_data() and the macro _pcps_write_var() - for details. - - - - #PCPS_GIVE_TIME<br> - Return a PCPS_TIME structure with current date, - time and status. Supported by all clocks. - - - #PCPS_GIVE_TIME_NOCLEAR<br> - Same as #PCPS_GIVE_TIME but the bits #PCPS_ST_SEC - and #PCPS_ST_MIN (see pcpsdev.h) of the status - port are not cleared. - Supported by all clocks except PC31/PS31 with - firmware version older than v3.0. - This is mainly used by the DOS TSR and should - not be used in other environments. - - - #PCPS_GIVE_SYNC_TIME<br> - Return a ::PCPS_TIME structure with date and time - of last synchronization of the clock or - the last time set via the interface. - _pcps_has_sync_time() checks whether supported. - - - #PCPS_GIVE_HR_TIME<br> - Return a PCPS_HR_TIME structure with current - date, time and status. This command should be - used to read the clock with higher resolution. - _pcps_has_hr_time() checks whether supported. - - - #PCPS_GIVE_IRIG_TIME<br> - Return a PCPS_IRIG_TIME structure with day-of-year, - time and status as decoded from the IRIG signal. - _pcps_has_irig_time() checks whether supported. - - - #PCPS_SET_TIME<br> - Set the board date, time and status. This - command expects sizeof( ::PCPS_STIME ) parameter - bytes. - _pcps_can_set_time() checks whether supported. - - - #PCPS_SET_EVENT_TIME<br> - Send a high resolution time stamp to the clock to - configure a UTC time when the clock shall generate - some event. This command expects a PCPS_TIME_STAMP - parameter. - _pcps_has_event_time() checks whether supported. - (requires custom GPS CERN firmware) - - - #PCPS_IRQ_NONE<br> - Disable the board's hardware IRQ<br> - - #PCPS_IRQ_1_SEC<br> - Enable hardware IRQs once per second<br> - - #PCPS_IRQ_1_MIN<br> - Enable hardware IRQs once per minute<br> - - #PCPS_IRQ_10_MIN<br> - Enable hardware IRQs once per 10 minutes<br> - - #PCPS_IRQ_30_MIN<br> - Enable hardware IRQs once per 30 minutes<br> - - - #PCPS_GET_SERIAL<br> - #PCPS_SET_SERIAL<br> - These commands read or set the configuration - of a clock's serial port COM0. The commands - expect PCPS_SERIAL_BYTES parameter bytes and - should be used preferably with the DCF77 - clocks which have only one COM port. - _pcps_has_serial() checks whether supported. - Recent GPS clocks' COM ports should be cfg'd - using the structures RECEIVER_INFO, PORT_INFO, - and STR_TYPE_INFO. - _pcps_has_receiver_info() checks whether - these are supported. If they are not, then - the code #PC_GPS_PORT_PARM together with the - #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA - commands should be used. - - - #PCPS_GET_TZCODE<br> - #PCPS_SET_TZCODE<br> - These commands read or set a DCF77 clock's - time zone code and should be used preferably - with the newer DCF77 clocks which have limited - support of different time zones. - _pcps_has_tzcode() checks whether supported. - A GPS clock's time zone must be cfg'd using - the code #PC_GPS_TZDL together with the - #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA - commands. - - - #PCPS_GET_PCPS_TZDL<br> - #PCPS_SET_PCPS_TZDL<br> - These commands read or set a DCF77 clock's - time zone / daylight saving configuration. - _pcps_has_pcps_tzdl() checks whether supported. - A GPS clock's time zone must be cfg'd using - the code #PC_GPS_TZDL together with the - #PCPS_READ_GPS_DATA and #PCPS_WRITE_GPS_DATA - commands. - - - #PCPS_GET_REF_OFFS<br> - #PCPS_SET_REF_OFFS<br> - These commands can be used to configure the - reference time offset from UTC for clocks - which can't determine the offset automatically, - e.g. from an IRIG input signal. - _pcps_has_ref_offs() checks whether supported. - - - #PCPS_GET_OPT_INFO<br> - #PCPS_SET_OPT_SETTINGS<br> - These commands can be used to configure some - optional settings, controlled by flags. - When reading, the clock returns a MBG_OPT_INFO - structure which contains the supported values, - plus the current settings. - When writing, clocks accepts a MBG_OPT_SETTINGS - structure only which contain the desired settings - of the supported flags only. - _pcps_has_opt_flags() checks whether supported. - - - #PCPS_GET_IRIG_RX_INFO<br> - #PCPS_SET_IRIG_RX_SETTINGS<br> - #PCPS_GET_IRIG_TX_INFO<br> - #PCPS_SET_IRIG_TX_SETTINGS<br> - These commands can be used to configure IRIG - inputs and outputs.<br> - When reading, the clock returns an IRIG_INFO - structure which contains the supported values, - plus the current settings.<br> - When writing, clocks accepts an IRIG_SETTINGS - structure only which contain the desired settings - only. _pcps_is_irig_rx() and _pcps_is_irig_tx() - check whether supported. - - - #PCPS_GET_IRIG_CTRL_BITS<br> - This command can be used to retrieve the control function - bits of the latest IRIG input frame. Those bits may carry - some well-known information as in the IEEE1344 code, but - may also contain some customized information, depending on - the IRIG frame type and the configuration of the IRIG generator. - So these bits are returned as-is and must be interpreted - by the application. - _pcps_has_irig_ctrl_bits() checks whether supported. - - - #PCPS_GET_SYNTH<br> - #PCPS_SET_SYNTH<br> - #PCPS_GET_SYNTH_STATE<br> - These commands can be used to configure an on-board - frequency synthesizer and query the synthesizer - status. The commands are only supported if the board - supports the RECEIVER_INFO structure and the flag - #GPS_HAS_SYNTH is set in the RECEIVER_INFO::features. - _pcps_has_synth() checks whether supported. - The structures SYNTH and SYNTH_STATE used with these - commands are defined in gpsdefs.h. - - - #PCPS_GIVE_FW_ID_1<br> - #PCPS_GIVE_FW_ID_2<br> - Returns the first/second block of PCPS_FIFO_SIZE - characters of the firmware ID string. These - commands can be used to check if the board - responds properly. This is done by the clock - detection functions. - - - #PCPS_GIVE_SERNUM<br> - Returns PCPS_FIFO_SIZE characters of the - clock's serial number. - _pcps_has_sernum() checks whether supported. - - - #PCPS_GENERIC_IO<br> - Generic I/O read and write. Can be used to query - specific data, e.g. a selected element of an array. - _pcps_has_generic_io() checks whether supported. - - - #PCPS_GET_DEBUG_STATUS<br> - This command reads a MBG_DEBUG_STATUS structure - which represents the internal status of the - IRIG decoder and some additional debug info. - _pcps_has_debug_status() checks whether supported. - - - #PCPS_READ_GPS_DATA<br> - #PCPS_WRITE_GPS_DATA<br> - These commands are used by the functions - pcps_read_gps_data() and pcps_write_gps_data() - to read or write large data structures to - Meinberg GPS plug-in clocks. - _pcps_is_gps() checks whether supported. - - - #PCPS_CLR_UCAP_BUFF<br> - Clear a clock's time capture buffer. - _pcps_can_clr_ucap_buff() checks whether - supported. - - - #PCPS_GIVE_UCAP_ENTRIES<br> - Read a PCPS_UCAP_ENTRIES structure which - reports the max number of entries and the - currently used number of entries in the - user capture buffer. - _pcps_has_ucap() checks whether supported. - - - #PCPS_GIVE_UCAP_EVENT<br> - Read capture events using a PCPS_HR_TIME - structure. This is faster than reading using the - GPS command #PC_GPS_UCAP. If no capture event is - available then the structure is filled with 0s. - _pcps_has_ucap() checks whether supported. - - - #PCPS_GET_CORR_INFO<br> - Read PZF correlation info using a CORR_INFO - structure. - _pcps_has_pzf() checks whether supported. - - - #PCPS_GET_TR_DISTANCE<br> - #PCPS_SET_TR_DISTANCE<br> - Read or write distance from the RF transmitter. - This is used to compensate the RF propagation delay - for PZF receivers. - _pcps_has_tr_distance() checks whether supported. - - - #PCPS_FORCE_RESET<br> - Resets the microprocessor on the device. This is - for special test scenarios only and should not be - used by standard applications since this may lock up - the PC. - - The command codes listed above are defined below. The commands are - grouped for bytes having the same high nibble: - - @{ */ - - -#if _IS_MBG_FIRMWARE //##++ - -// These group codes are obsolete and should be removed. -// The explicite command codes defined below should be used instead. -#define PCPS_GIVE_TIME_GROUP 0x00 -#define PCPS_SET_TIME_GROUP 0x10 -#define PCPS_IRQ_GROUP 0x20 -#define PCPS_CFG_GROUP 0x30 -#define PCPS_GIVE_DATA_GROUP 0x40 -#define PCPS_GPS_DATA_GROUP 0x50 -#define PCPS_CTRL_GROUP 0x60 -#define PCPS_CFG2_GROUP 0x70 - -#endif +/** + * @brief Command codes used to communicate with bus level devices + * + * These commands are used for low level access to bus-level devices + * manufactured by Meinberg. + * + * Applications should instead use the API functions declared in mbgdevio.h. + * + * The header files pcpsdev.h and pcpsdrvr.h contain macros which can be + * used to check if a detected device supports a certain feature or command. + * If checking is required then the name of the macro is given in the + * comments associated with the command codes. + * + * Some commands expect parameters to be passed to the board. In that + * case, the board returns the number of parameter bytes expected when + * the command code is passed. Every parameter byte has to be supplied + * to the board exactly like a command byte. + * + * Refer to function ::pcps_write and the macro ::_pcps_write_var + * for details. + * + * - ::PCPS_GIVE_TIME<br> + * Return a ::PCPS_TIME structure with current date, + * time and status. Supported by all clocks. + * + * - ::PCPS_GIVE_TIME_NOCLEAR<br> + * Same as ::PCPS_GIVE_TIME but the bits ::PCPS_ST_SEC + * and ::PCPS_ST_MIN of the status port are not cleared. + * Supported by all clocks except PC31/PS31 with + * firmware version older than v3.0. + * This is mainly used by the DOS TSR and should + * not be used in other environments. + * + * - ::PCPS_GIVE_SYNC_TIME<br> + * Return a ::PCPS_TIME structure with date and time + * of last synchronization of the clock or + * the last time set via the interface. + * ::_pcps_has_sync_time checks whether supported. + * + * - ::PCPS_GIVE_HR_TIME<br> + * Return a ::PCPS_HR_TIME structure with current + * date, time and status. This command should be + * used to read the clock with higher resolution. + * ::_pcps_has_hr_time checks whether supported. + * + * - ::PCPS_GIVE_IRIG_TIME<br> + * Return a ::PCPS_IRIG_TIME structure with day-of-year, + * time and status as decoded from the IRIG signal. + * ::_pcps_has_irig_time checks whether supported. + * + * - ::PCPS_SET_TIME<br> + * Set the board date, time and status. This command + * expects sizeof( ::PCPS_STIME ) parameter bytes. + * ::_pcps_can_set_time checks whether supported. + * + * - ::PCPS_SET_EVENT_TIME<br> + * Send a high resolution time stamp to the clock to + * configure a %UTC time when the clock shall generate + * some event. This command expects a ::PCPS_TIME_STAMP + * parameter. + * ::_pcps_has_event_time checks whether supported. + * (requires custom GPS CERN firmware) + * + * - ::PCPS_IRQ_NONE<br> + * Disable the card's hardware IRQ<br> + * - ::PCPS_IRQ_1_SEC<br> + * Enable hardware IRQs once per second<br> + * - ::PCPS_IRQ_1_MIN<br> + * Enable hardware IRQs once per minute (deprecated)<br> + * - ::PCPS_IRQ_10_MIN<br> + * Enable hardware IRQs once per 10 minutes (deprecated)<br> + * - ::PCPS_IRQ_30_MIN<br> + * Enable hardware IRQs once per 30 minutes (deprecated)<br> + * + * - ::PCPS_GET_SERIAL<br> + * ::PCPS_SET_SERIAL<br> + * Deprecated. Read or write the configuration of a card's + * serial port COM0 in ::PCPS_SERIAL format. + * ::_pcps_has_serial checks whether supported. + * Newer cards should be configured using the structures ::RECEIVER_INFO, + * ::PORT_INFO, and STR_TYPE_INFO. + * ::_pcps_has_receiver_info checks whether these are supported. + * + * - ::PCPS_GET_TZCODE<br> + * ::PCPS_SET_TZCODE<br> + * These commands read or set a DCF77 clock's + * time zone code and should be used preferably + * with older DCF77 receivers which have limited + * support of different time zones. + * ::_pcps_has_tzcode checks whether supported. + * Most newer devices support the ::TZDL structure which can be + * read or written using ::PC_GPS_TZDL. + * + * - ::PCPS_GET_PCPS_TZDL<br> + * ::PCPS_SET_PCPS_TZDL<br> + * Read or write time zone / daylight saving information + * in ::PCPS_TZDL format. + * ::_pcps_has_pcps_tzdl checks whether supported. + * + * - ::PCPS_GET_REF_OFFS<br> + * ::PCPS_SET_REF_OFFS<br> + * These commands can be used to configure the + * reference time offset from %UTC for clocks + * which can't determine the offset automatically, + * e.g. from an IRIG input signal. + * ::_pcps_has_ref_offs checks whether supported. + * + * - ::PCPS_GET_OPT_INFO<br> + * ::PCPS_SET_OPT_SETTINGS<br> + * These commands can be used to configure some + * optional settings, controlled by flags. + * When reading, the clock returns a ::MBG_OPT_INFO + * structure which contains the supported values, + * plus the current settings. + * When writing, clocks accepts a ::MBG_OPT_SETTINGS + * structure only which contain the desired settings + * of the supported flags only. + * ::_pcps_has_opt_flags checks whether supported. + * + * - ::PCPS_GET_IRIG_RX_INFO<br> + * ::PCPS_SET_IRIG_RX_SETTINGS<br> + * ::PCPS_GET_IRIG_TX_INFO<br> + * ::PCPS_SET_IRIG_TX_SETTINGS<br> + * These commands can be used to configure IRIG + * inputs and outputs.<br> + * When reading, the clock returns an ::IRIG_INFO + * structure which contains the supported values, + * plus the current settings.<br> + * When writing, clocks accepts an ::IRIG_SETTINGS + * structure only which contain the desired settings + * only. ::_pcps_is_irig_rx and ::_pcps_has_irig_tx + * check whether supported. + * + * - ::PCPS_GET_IRIG_CTRL_BITS<br> + * This command can be used to retrieve the control function + * bits of the latest IRIG input frame. Those bits may carry + * some well-known information as in the IEEE 1344 code, but + * may also contain some customized information, depending on + * the IRIG frame type and the configuration of the IRIG generator. + * So these bits are returned as-is and must be interpreted + * by the application. + * ::_pcps_has_irig_ctrl_bits checks whether supported. + * + * - ::PCPS_GET_SYNTH<br> + * ::PCPS_SET_SYNTH<br> + * ::PCPS_GET_SYNTH_STATE<br> + * These commands can be used to configure an on-board + * frequency synthesizer and query the synthesizer + * status. The commands are only supported if the board + * supports the ::RECEIVER_INFO structure and the flag + * #GPS_HAS_SYNTH is set in the ::RECEIVER_INFO::features. + * ::_pcps_has_synth checks whether supported. + * The structures ::SYNTH and ::SYNTH_STATE used with these + * commands are defined in gpsdefs.h. + * + * - ::PCPS_GIVE_FW_ID_1<br> + * ::PCPS_GIVE_FW_ID_2<br> + * Returns the first/second block of ::PCPS_FIFO_SIZE + * characters of the firmware ID string. These + * commands can be used to check if the board + * responds properly. This is done by the clock + * detection functions. + * + * - ::PCPS_GIVE_SERNUM<br> + * Returns ::PCPS_FIFO_SIZE characters of the + * clock's serial number. + * ::_pcps_has_sernum checks whether supported. + * + * - ::PCPS_GENERIC_IO<br> + * Generic I/O read and write. Can be used to query + * specific data, e.g. a selected element of an array. + * ::_pcps_has_generic_io checks whether supported. + * + * - ::PCPS_GET_DEBUG_STATUS<br> + * This command reads an ::MBG_DEBUG_STATUS structure + * which represents the internal status of the + * IRIG decoder and some additional debug info. + * ::_pcps_has_debug_status checks whether supported. + * + * - ::PCPS_READ_GPS_DATA<br> + * ::PCPS_WRITE_GPS_DATA<br> + * These commands are used by the functions + * ::pcps_read_gps and ::pcps_write_gps + * to read or write large data structures to + * Meinberg GPS plug-in clocks. + * ::_pcps_is_gps checks whether supported. + * + * - ::PCPS_CLR_UCAP_BUFF<br> + * Clear a clock's time capture buffer. + * ::_pcps_can_clr_ucap_buff checks whether + * supported. + * + * - ::PCPS_GIVE_UCAP_ENTRIES<br> + * Read a ::PCPS_UCAP_ENTRIES structure which + * reports the max number of entries and the + * currently used number of entries in the + * user capture buffer. + * ::_pcps_has_ucap checks whether supported. + * + * - ::PCPS_GIVE_UCAP_EVENT<br> + * Read capture events using a PCPS_HR_TIME + * structure. This is faster than reading using the + * GPS command ::PC_GPS_UCAP. If no capture event is + * available then the returned structure is all 0. + * ::_pcps_has_ucap checks whether supported. + * + * - ::PCPS_GET_CORR_INFO<br> + * Read PZF correlation info using a ::CORR_INFO + * structure. + * ::_pcps_has_pzf checks whether supported. + * + * - ::PCPS_GET_TR_DISTANCE<br> + * ::PCPS_SET_TR_DISTANCE<br> + * Read or write distance from the RF transmitter. + * This is used to compensate the RF propagation delay + * for PZF receivers. + * ::_pcps_has_tr_distance checks whether supported. + * + * - ::PCPS_CLR_EVT_LOG<br> + * Clear on-board event log. + * ::_pcps_has_evt_log checks whether supported. + * + * - ::PCPS_NUM_EVT_LOG_ENTRIES<br> + * Read max. number of num event log entries which can + * be saved on the board, and how many entries have currently + * been saved. + * ::_pcps_has_evt_log checks whether supported. + * + * - ::PCPS_FIRST_EVT_LOG_ENTRY<br> + * ::PCPS_NEXT_EVT_LOG_ENTRY<br> + * Read first (oldest) or next event log entry. + * ::_pcps_has_evt_log checks whether supported. + * + * - ::PCPS_FORCE_RESET<br> + * Resets the card's hardware. This may lock up the computer + * and thus should only be used by very specific applications. + * + * @anchor PCPS_CMD_CODES @{ */ +#define PCPS_GIVE_TIME 0x00 ///< (r-) Read current time in ::PCPS_TIME format +#define PCPS_GIVE_TIME_NOCLEAR 0x01 ///< (r-) Read current time in ::PCPS_TIME format, don't clear sec and min flags (deprecated) +#define PCPS_GIVE_SYNC_TIME 0x02 ///< (r-) Read last sync time as ::PCPS_TIME, only if ::_pcps_has_sync_time +#define PCPS_GIVE_HR_TIME 0x03 ///< (r-) Read high res. time as ::PCPS_HR_TIME, only if ::_pcps_has_hr_time +#define PCPS_GIVE_IRIG_TIME 0x04 ///< (r-) Read raw IRIG time as ::PCPS_IRIG_TIME, only if ::_pcps_has_irig_time +#define PCPS_SET_TIME 0x10 ///< (-w) Set on-board time, see ::PCPS_STIME. Returns ::MBG_ERR_STIME on error. -#define PCPS_GIVE_TIME 0x00 -#define PCPS_GIVE_TIME_NOCLEAR 0x01 -#define PCPS_GIVE_SYNC_TIME 0x02 // only supported if _pcps_has_sync_time() -#define PCPS_GIVE_HR_TIME 0x03 // only supported if _pcps_has_hr_time() -#define PCPS_GIVE_IRIG_TIME 0x04 // only supported if _pcps_has_irig_time() +#define PCPS_SET_EVENT_TIME 0x14 ///< (-w) Write event time as ::PCPS_TIME_STAMP, only if ::_pcps_has_event_time -#define PCPS_SET_TIME 0x10 -/* on error, return PCPS_ERR_STIME */ +#define PCPS_IRQ_NONE 0x20 ///< (-w) Disable IRQs +#define PCPS_IRQ_1_SEC 0x21 ///< (-w) Enable IRQ per 1 second +#define PCPS_IRQ_1_MIN 0x22 ///< (-w) Enable IRQ per 1 minute (deprecated) +#define PCPS_IRQ_10_MIN 0x24 ///< (-w) Enable IRQ per 10 minutes (deprecated) +#define PCPS_IRQ_30_MIN 0x28 ///< (-w) Enable IRQ per 10 minutes (deprecated) -/* Attention: The code below can be used EXCLUSIVELY */ -/* with a GPS167PCI with customized CERN firmware !! */ -/* _pcps_has_event_time() checks whether supported. */ -#define PCPS_SET_EVENT_TIME 0x14 +#define PCPS_GET_SERIAL 0x30 ///< (r-) Read serial settings as ::PCPS_SERIAL, deprecated by ::PC_GPS_ALL_PORT_INFO +#define PCPS_SET_SERIAL 0x31 ///< (-w) Write serial settings as ::PCPS_SERIAL, deprecated by ::PC_GPS_PORT_SETTINGS_IDX, returns ::MBG_ERR_CFG on error -#define PCPS_IRQ_NONE 0x20 -#define PCPS_IRQ_1_SEC 0x21 -#define PCPS_IRQ_1_MIN 0x22 -#define PCPS_IRQ_10_MIN 0x24 -#define PCPS_IRQ_30_MIN 0x28 +#define PCPS_GET_TZCODE 0x32 ///< (r-) Read ::PCPS_TZCODE, only if ::_pcps_has_tzcode +#define PCPS_SET_TZCODE 0x33 ///< (-w) Write ::PCPS_TZCODE, only if ::_pcps_has_tzcode, returns ::MBG_ERR_CFG on error -#define PCPS_GET_SERIAL 0x30 -#define PCPS_SET_SERIAL 0x31 -/* on error, return PCPS_ERR_CFG */ +#define PCPS_GET_PCPS_TZDL 0x34 ///< (r-) Read ::PCPS_TZDL, only if ::_pcps_has_pcps_tzdl +#define PCPS_SET_PCPS_TZDL 0x35 ///< (-w) Write ::PCPS_TZDL, only if ::_pcps_has_pcps_tzdl, returns ::MBG_ERR_CFG on error -typedef uint8_t PCPS_SERIAL; +#define PCPS_GET_REF_OFFS 0x36 ///< (r-) Read ::MBG_REF_OFFS, only if ::_pcps_has_ref_offs +#define PCPS_SET_REF_OFFS 0x37 ///< (-w) Write ::MBG_REF_OFFS, only if ::_pcps_has_ref_offs, returns ::MBG_ERR_CFG on error +#define PCPS_GET_OPT_INFO 0x38 ///< (r-) Read ::MBG_OPT_INFO, only if ::_pcps_has_opt_flags +#define PCPS_SET_OPT_SETTINGS 0x39 ///< (-w) Write ::MBG_OPT_SETTINGS, only if ::_pcps_has_opt_flags, returns ::MBG_ERR_CFG on error -#define PCPS_GET_TZCODE 0x32 -#define PCPS_SET_TZCODE 0x33 -/* on error, return PCPS_ERR_CFG */ +#define PCPS_GET_IRIG_RX_INFO 0x3A ///< (r-) Read ::IRIG_INFO, only if ::_pcps_is_irig_rx +#define PCPS_SET_IRIG_RX_SETTINGS 0x3B ///< (-w) Write ::IRIG_SETTINGS, only if ::_pcps_is_irig_rx, returns ::MBG_ERR_CFG on error -typedef uint8_t PCPS_TZCODE; +#define PCPS_GET_IRIG_TX_INFO 0x3C ///< (r-) Read ::IRIG_INFO, only if ::_pcps_has_irig_tx +#define PCPS_SET_IRIG_TX_SETTINGS 0x3D ///< (-w) Write ::IRIG_SETTINGS, only if ::_pcps_has_irig_tx, returns ::MBG_ERR_CFG on error -/* the following codes are used with the PCPS_TZCODE parameter: */ -enum -{ - PCPS_TZCODE_CET_CEST, /* default as broadcasted by DCF77 (UTC+1h/UTC+2h) */ - PCPS_TZCODE_CET, /* always CET (UTC+1h), discard DST */ - PCPS_TZCODE_UTC, /* always UTC */ - PCPS_TZCODE_EET_EEST, /* East European Time, CET/CEST + 1h */ - N_PCPS_TZCODE /* the number of valid codes */ -}; +#define PCPS_GET_SYNTH 0x3E ///< (r-) Read ::SYNTH, only if ::_pcps_has_synth +#define PCPS_SET_SYNTH 0x3F ///< (-w) Write ::SYNTH, only if ::_pcps_has_synth, returns ::MBG_ERR_CFG on error -/* the definitions below are for compatibily only: */ -#define PCPS_TZCODE_MEZMESZ PCPS_TZCODE_CET_CEST -#define PCPS_TZCODE_MEZ PCPS_TZCODE_CET -#define PCPS_TZCODE_OEZ PCPS_TZCODE_EET_EEST +#define PCPS_GIVE_FW_ID_1 0x40 ///< (r-) Read first ::PCPS_FIFO_SIZE chars of firmware ID +#define PCPS_GIVE_FW_ID_2 0x41 ///< (r-) Read last ::PCPS_FIFO_SIZE chars of firmware ID +#define PCPS_GIVE_SERNUM 0x42 ///< (r-) Read serial number as ::PCPS_SN_STR, only if ::_pcps_has_sernum +#define PCPS_GENERIC_IO 0x43 ///< (rw) See ::pcps_generic_io or ::_mbgdevio_gen_io +#define PCPS_GET_SYNTH_STATE 0x44 ///< (r-) Read ::SYNTH_STATE, only if ::_pcps_has_synth +#define PCPS_GET_IRIG_CTRL_BITS 0x45 ///< (r-) Read ::MBG_IRIG_CTRL_BITS, only if ::_pcps_has_irig_ctrl_bits +#define PCPS_GET_RAW_IRIG_DATA 0x46 ///< (r-) Read ::MBG_RAW_IRIG_DATA, only if ::_pcps_has_raw_irig_data +#define PCPS_GET_STATUS_PORT 0x4B ///< (r-) Read ::PCPS_STATUS_PORT +#define PCPS_GET_DEBUG_STATUS 0x4C ///< (r-) Read ::MBG_DEBUG_STATUS, only if ::_pcps_has_debug_status -#define PCPS_GET_PCPS_TZDL 0x34 -#define PCPS_SET_PCPS_TZDL 0x35 -/* on error, return PCPS_ERR_CFG */ +/// @note Command codes 0x4D, 0x4E, and 0x4F are reserved. +#define PCPS_READ_GPS_DATA 0x50 ///< (r-) Read large data structure, see ::PC_GPS_CMD_CODES +#define PCPS_WRITE_GPS_DATA 0x51 ///< (-w) Write large data structure, see ::PC_GPS_CMD_CODES -/** - * The structures below can be used to configure a clock's - * time zone/daylight saving setting. This structure is shorter - * than the TZDL structure used with GPS clocks. - */ -typedef struct -{ - // The year_or_wday field below contains the full year number - // or 0..6 == Sun..Sat if the DL_AUTO_FLAG is set; see below. - uint16_t year_or_wday; - uint8_t month; - uint8_t mday; - uint8_t hour; - uint8_t min; -} PCPS_DL_ONOFF; +#define PCPS_CLR_UCAP_BUFF 0x60 ///< (-w) No param., clear on-board capture FIFO, only if ::_pcps_has_ucap +#define PCPS_GIVE_UCAP_ENTRIES 0x61 ///< (r-) Read ::PCPS_UCAP_ENTRIES, only if ::_pcps_has_ucap +#define PCPS_GIVE_UCAP_EVENT 0x62 ///< (r-) Return oldest event as ::PCPS_HR_TIME, only if ::_pcps_has_ucap -#define _mbg_swab_pcps_dl_onoff( _p ) \ -{ \ - _mbg_swab16( &(_p)->year_or_wday ); \ -} +#define PCPS_GET_CORR_INFO 0x63 ///< (r-) Read ::CORR_INFO structure, only if ::_pcps_has_pzf +#define PCPS_GET_TR_DISTANCE 0x64 ///< (r-) Read ::TR_DISTANCE, only if ::_pcps_has_tr_distance +#define PCPS_SET_TR_DISTANCE 0x65 ///< (-w) Write ::TR_DISTANCE, only if ::_pcps_has_tr_distance -/** - * If the field year_or_wday is or'ed with the constant DL_AUTO_FLAG - * defined below then this means that start and end of daylight saving - * time shall be computed automatically for each year. In this case - * the remaining bits represent the day-of-week after the specified - * mday/month at which the change shall occur. If that flag is not set - * then the field contains the full four-digit year number and the - * mday/month values specify the exact date of that year. - */ -#define DL_AUTO_FLAG 0x8000 // also defined in gpsdefs.h +#define PCPS_CLR_EVT_LOG 0x66 ///< (-w) Write clear on-board event log, only if ::_pcps_has_evt_log +#define PCPS_NUM_EVT_LOG_ENTRIES 0x67 ///< (r-) Read ::MBG_NUM_EVT_LOG_ENTRIES, only if ::_pcps_has_evt_log +#define PCPS_FIRST_EVT_LOG_ENTRY 0x68 ///< (r-) Read first (oldest) ::MBG_EVT_LOG_ENTRY, only if ::_pcps_has_evt_log +#define PCPS_NEXT_EVT_LOG_ENTRY 0x69 ///< (r-) Read next ::MBG_EVT_LOG_ENTRY, only if ::_pcps_has_evt_log -typedef struct -{ - int16_t offs; /**< offset from UTC to local time [min] */ - int16_t offs_dl; /**< additional offset if DST enabled [min] */ - PCPS_DL_ONOFF tm_on; /**< date/time when daylight saving starts */ - PCPS_DL_ONOFF tm_off; /**< date/time when daylight saving ends */ -} PCPS_TZDL; +#define PCPS_FORCE_RESET 0x80 ///< (-w) No param., reset the device (deprecated, this can lock up the computer!!) -#define _mbg_swab_pcps_tzdl( _p ) \ -{ \ - _mbg_swab16( &(_p)->offs ); \ - _mbg_swab16( &(_p)->offs_dl ); \ - _mbg_swab_pcps_dl_onoff( &(_p)->tm_on ); \ - _mbg_swab_pcps_dl_onoff( &(_p)->tm_off ); \ -} +/// @note Command codes 0xF0 through 0xFF are reserved. +/** @} anchor PCPS_CMD_CODES */ -#define PCPS_GET_REF_OFFS 0x36 -#define PCPS_SET_REF_OFFS 0x37 -/* on error, return PCPS_ERR_CFG */ -/* The associated type MBG_REF_OFFS is defined in gpsdefs.h. */ +#if _IS_MBG_FIRMWARE +/** + * @brief Deprecated command group codes + * + * @deprecated These group codes are deprecated. + * They should not be used anymore but removed + * from existing source code. The explicite command + * codes @ref PCPS_CMD_CODES should be used instead. + * + * @anchor PCPS_CMD_GROUP_CODES @{ */ -#define PCPS_GET_OPT_INFO 0x38 -#define PCPS_SET_OPT_SETTINGS 0x39 -/* on error, return PCPS_ERR_CFG */ +#define PCPS_GIVE_TIME_GROUP 0x00 +#define PCPS_SET_TIME_GROUP 0x10 +#define PCPS_IRQ_GROUP 0x20 +#define PCPS_CFG_GROUP 0x30 +#define PCPS_GIVE_DATA_GROUP 0x40 +#define PCPS_GPS_DATA_GROUP 0x50 +#define PCPS_CTRL_GROUP 0x60 +#define PCPS_CFG2_GROUP 0x70 -/* The associated structures MBG_OPT_INFO and MBG_OPT_SETTINGS - are defined in gpsdefs.h. */ +/** @} anchor PCPS_CMD_GROUP_CODES */ +#endif // _IS_MBG_FIRMWARE -#define PCPS_GET_IRIG_RX_INFO 0x3A -#define PCPS_SET_IRIG_RX_SETTINGS 0x3B -/* on error, return PCPS_ERR_CFG */ -#define PCPS_GET_IRIG_TX_INFO 0x3C -#define PCPS_SET_IRIG_TX_SETTINGS 0x3D -/* on error, return PCPS_ERR_CFG */ -/* The associated structures IRIG_INFO and IRIG_SETTINGS - are defined in gpsdefs.h. */ +#if !defined( MBG_CMD_TABLE_EXT ) + #define MBG_CMD_TABLE_EXT _mbg_cn_table_end() +#endif +/** + * @brief An initializer for a table of code/name entries of non-GPS commands. + * + * This can e.g. initialize an array of ::MBG_CODE_NAME_TABLE_ENTRY elements + * and may be helpful when debugging. + * + * @see @ref PCPS_CMD_CODES + */ +#define PCPS_CMD_CODES_TABLE \ +{ \ + _mbg_cn_table_entry( PCPS_GIVE_TIME ), /* 0x00 */ \ + _mbg_cn_table_entry( PCPS_GIVE_TIME_NOCLEAR ), /* 0x01 */ \ + _mbg_cn_table_entry( PCPS_GIVE_SYNC_TIME ), /* 0x02 */ \ + _mbg_cn_table_entry( PCPS_GIVE_HR_TIME ), /* 0x03 */ \ + _mbg_cn_table_entry( PCPS_GIVE_IRIG_TIME ), /* 0x04 */ \ + _mbg_cn_table_entry( PCPS_SET_TIME ), /* 0x10 */ \ + _mbg_cn_table_entry( PCPS_SET_EVENT_TIME ), /* 0x14 */ \ + _mbg_cn_table_entry( PCPS_IRQ_NONE ), /* 0x20 */ \ + _mbg_cn_table_entry( PCPS_IRQ_1_SEC ), /* 0x21 */ \ + _mbg_cn_table_entry( PCPS_IRQ_1_MIN ), /* 0x22 */ \ + _mbg_cn_table_entry( PCPS_IRQ_10_MIN ), /* 0x24 */ \ + _mbg_cn_table_entry( PCPS_IRQ_30_MIN ), /* 0x28 */ \ + _mbg_cn_table_entry( PCPS_GET_SERIAL ), /* 0x30 */ \ + _mbg_cn_table_entry( PCPS_SET_SERIAL ), /* 0x31 */ \ + _mbg_cn_table_entry( PCPS_GET_TZCODE ), /* 0x32 */ \ + _mbg_cn_table_entry( PCPS_SET_TZCODE ), /* 0x33 */ \ + _mbg_cn_table_entry( PCPS_GET_PCPS_TZDL ), /* 0x34 */ \ + _mbg_cn_table_entry( PCPS_SET_PCPS_TZDL ), /* 0x35 */ \ + _mbg_cn_table_entry( PCPS_GET_REF_OFFS ), /* 0x36 */ \ + _mbg_cn_table_entry( PCPS_SET_REF_OFFS ), /* 0x37 */ \ + _mbg_cn_table_entry( PCPS_GET_OPT_INFO ), /* 0x38 */ \ + _mbg_cn_table_entry( PCPS_SET_OPT_SETTINGS ), /* 0x39 */ \ + _mbg_cn_table_entry( PCPS_GET_IRIG_RX_INFO ), /* 0x3A */ \ + _mbg_cn_table_entry( PCPS_SET_IRIG_RX_SETTINGS ), /* 0x3B */ \ + _mbg_cn_table_entry( PCPS_GET_IRIG_TX_INFO ), /* 0x3C */ \ + _mbg_cn_table_entry( PCPS_SET_IRIG_TX_SETTINGS ), /* 0x3D */ \ + _mbg_cn_table_entry( PCPS_GET_SYNTH ), /* 0x3E */ \ + _mbg_cn_table_entry( PCPS_SET_SYNTH ), /* 0x3F */ \ + _mbg_cn_table_entry( PCPS_GIVE_FW_ID_1 ), /* 0x40 */ \ + _mbg_cn_table_entry( PCPS_GIVE_FW_ID_2 ), /* 0x41 */ \ + _mbg_cn_table_entry( PCPS_GIVE_SERNUM ), /* 0x42 */ \ + _mbg_cn_table_entry( PCPS_GENERIC_IO ), /* 0x43 */ \ + _mbg_cn_table_entry( PCPS_GET_SYNTH_STATE ), /* 0x44 */ \ + _mbg_cn_table_entry( PCPS_GET_IRIG_CTRL_BITS ), /* 0x45 */ \ + _mbg_cn_table_entry( PCPS_GET_RAW_IRIG_DATA ), /* 0x46 */ \ + _mbg_cn_table_entry( PCPS_GET_STATUS_PORT ), /* 0x4B */ \ + _mbg_cn_table_entry( PCPS_GET_DEBUG_STATUS ), /* 0x4C */ \ + _mbg_cn_table_entry( PCPS_READ_GPS_DATA ), /* 0x50 */ \ + _mbg_cn_table_entry( PCPS_WRITE_GPS_DATA ), /* 0x51 */ \ + _mbg_cn_table_entry( PCPS_CLR_UCAP_BUFF ), /* 0x60 */ \ + _mbg_cn_table_entry( PCPS_GIVE_UCAP_ENTRIES ), /* 0x61 */ \ + _mbg_cn_table_entry( PCPS_GIVE_UCAP_EVENT ), /* 0x62 */ \ + _mbg_cn_table_entry( PCPS_GET_CORR_INFO ), /* 0x63 */ \ + _mbg_cn_table_entry( PCPS_GET_TR_DISTANCE ), /* 0x64 */ \ + _mbg_cn_table_entry( PCPS_SET_TR_DISTANCE ), /* 0x65 */ \ + _mbg_cn_table_entry( PCPS_CLR_EVT_LOG ), /* 0x66 */ \ + _mbg_cn_table_entry( PCPS_NUM_EVT_LOG_ENTRIES ), /* 0x67 */ \ + _mbg_cn_table_entry( PCPS_FIRST_EVT_LOG_ENTRY ), /* 0x68 */ \ + _mbg_cn_table_entry( PCPS_NEXT_EVT_LOG_ENTRY ), /* 0x69 */ \ + _mbg_cn_table_entry( PCPS_FORCE_RESET ), /* 0x80 */ \ + MBG_CMD_TABLE_EXT, \ + _mbg_cn_table_end() \ +} -#define PCPS_GET_SYNTH 0x3E -#define PCPS_SET_SYNTH 0x3F -/* on error, return PCPS_ERR_CFG */ -/* The associated structure SYNTH is defined in gpsdefs.h. */ +/** + * @brief Bus level command return codes + * + * @deprecated These codes are deprecated and @ref MBG_RETURN_CODES should be used + * instead which provide corresponding symbols with same numeric values. + * + * @anchor PCPS_LEVEL_CMD_RETURN_CODES @{ */ -#define PCPS_GIVE_FW_ID_1 0x40 -#define PCPS_GIVE_FW_ID_2 0x41 -#define PCPS_GIVE_SERNUM 0x42 -#define PCPS_GENERIC_IO 0x43 -#define PCPS_GET_SYNTH_STATE 0x44 -#define PCPS_GET_IRIG_CTRL_BITS 0x45 -#define PCPS_GET_RAW_IRIG_DATA 0x46 +#define PCPS_SUCCESS 0 ///< OK, no error (see ::MBG_SUCCESS) +#define PCPS_ERR_STIME -1 ///< invalid date/time/status passed (see ::MBG_ERR_STIME) +#define PCPS_ERR_CFG -2 ///< invalid parms for a cmd writing config parameters (see ::MBG_ERR_CFG) +/** @} anchor PCPS_LEVEL_CMD_RETURN_CODES */ -#define PCPS_GET_STATUS_PORT 0x4B -#define PCPS_GET_DEBUG_STATUS 0x4C -// expects sizeof( MBG_DEBUG_STATUS ) chars -// Command codes 0x4D, 0x4E, and 0x4F are reserved. +#if !defined( BITMASK ) + #define BITMASK( b ) ( ( 1 << b ) - 1 ) +#endif -#define PCPS_READ_GPS_DATA 0x50 -#define PCPS_WRITE_GPS_DATA 0x51 +/** @brief The size of a bus level device's command/data FIFO */ +#define PCPS_FIFO_SIZE 16 -#define PCPS_CLR_UCAP_BUFF 0x60 -#define PCPS_GIVE_UCAP_ENTRIES 0x61 -#define PCPS_GIVE_UCAP_EVENT 0x62 +/** @brief A data buffer for a bus level device's command/data */ +typedef int8_t PCPS_BUFF[PCPS_FIFO_SIZE]; -typedef struct -{ - uint32_t used; /**< the number of saved capture events */ - uint32_t max; /**< capture buffer size */ -} PCPS_UCAP_ENTRIES; -#define _mbg_swab_pcps_ucap_entries( _p ) \ -{ \ - _mbg_swab32( &(_p)->used ); \ - _mbg_swab32( &(_p)->max ); \ -} +/** @brief The maximum length of an ID string, including terminating 0 */ +#define PCPS_ID_SIZE ( 2 * PCPS_FIFO_SIZE + 1 ) ///< ASCIIZ string +/** @brief A buffer for an ID string, including terminating 0 */ +typedef char PCPS_ID_STR[PCPS_ID_SIZE]; -#define PCPS_GET_CORR_INFO 0x63 // read CORR_INFO structure, only if _pcps_has_pzf() -#define PCPS_GET_TR_DISTANCE 0x64 // read TR_DISTANCE, only if _pcps_has_tr_distance() -#define PCPS_SET_TR_DISTANCE 0x65 // write TR_DISTANCE, only if _pcps_has_tr_distance() +/** @brief The maximum length of a serial number string, including terminating 0 */ +#define PCPS_SN_SIZE ( PCPS_FIFO_SIZE + 1 ) ///< ASCIIZ string +/** @brief A buffer for a serial number string, including terminating 0 */ +typedef char PCPS_SN_STR[PCPS_SN_SIZE]; /** - special -- use with care ! -*/ -#define PCPS_FORCE_RESET 0x80 + * @brief Seconds since epoch 1970-01-01, usually %UTC scale + * + * Used with ::PCPS_TIME_STAMP. + * + * @see ::PCPS_FRAC_32 + * @see ::PCPS_TIME_STAMP + */ +typedef uint32_t PCPS_SECONDS; -// Command codes 0xF0 through 0xFF are reserved. +#define _mbg_swab_pcps_seconds( _p ) \ +do \ +{ \ + _mbg_swab32( _p ); \ +} while ( 0 ) -/** @} group_cmd_bytes */ -/* Codes returned when commands with parameters have been passed */ -/* to the board */ -#define PCPS_SUCCESS 0 /**< OK, no error */ -#define PCPS_ERR_STIME -1 /**< invalid date/time/status passed */ -#define PCPS_ERR_CFG -2 /**< invalid parms for a cmd writing config parameters */ +/** + * @brief 32 bit binary fraction of a second + * + * Used with ::PCPS_TIME_STAMP, e.g. + * 0x80000000 == 0.5 s, 0xFFFFFFFF == 0.9999999.. s, etc. + * Use ::bin_frac_32_to_dec_frac for conversion. + * + * @see ::bin_frac_32_to_dec_frac + * @see ::PCPS_SECONDS + * @see ::PCPS_TIME_STAMP + * @see ::PCPS_HRT_FRAC_SCALE + * @see ::PCPS_HRT_FRAC_SCALE_FMT + */ +typedef uint32_t PCPS_FRAC_32; +#define _mbg_swab_pcps_frac_32( _p ) \ +do \ +{ \ + _mbg_swab32( _p ); \ +} while ( 0 ) -#ifndef BITMASK - #define BITMASK( b ) ( ( 1 << b ) - 1 ) -#endif +/** + * @brief A high resolution time stamp + */ +typedef struct +{ + PCPS_SECONDS sec; ///< seconds since 1970, usually %UTC scale + PCPS_FRAC_32 frac; ///< binary fractions of second, see ::PCPS_FRAC_32 -/** The size of the plug-in card's on-board FIFO */ -#define PCPS_FIFO_SIZE 16 +} PCPS_TIME_STAMP; -typedef int8_t PCPS_BUFF[PCPS_FIFO_SIZE]; +#define _mbg_swab_pcps_time_stamp( _p ) \ +do \ +{ \ + _mbg_swab_pcps_seconds( &(_p)->sec ); \ + _mbg_swab_pcps_frac_32( &(_p)->frac ); \ +} while ( 0 ) -#define PCPS_ID_SIZE ( 2 * PCPS_FIFO_SIZE + 1 ) /**< ASCIIZ string */ -typedef char PCPS_ID_STR[PCPS_ID_SIZE]; +#ifndef PCPS_HRT_FRAC_SCALE + /** + * @brief Scale to be used to print ::PCPS_TIME_STAMP::frac values + * + * The function ::frac_sec_from_bin can be used for the conversion. + * + * @see ::PCPS_HRT_FRAC_SCALE_FMT + */ + #define PCPS_HRT_FRAC_SCALE 10000000UL +#endif + +#ifndef PCPS_HRT_FRAC_SCALE_FMT + /** + * @brief Format specifier used to print ::PCPS_TIME_STAMP::frac values + * + * Used to print values scaled with ::frac_sec_from_bin called + * with ::PCPS_HRT_FRAC_SCALE. + * + * @see ::PCPS_HRT_FRAC_SCALE + */ + #define PCPS_HRT_FRAC_SCALE_FMT "%07lu" +#endif -#define PCPS_SN_SIZE ( PCPS_FIFO_SIZE + 1 ) /**< ASCIIZ string */ -typedef char PCPS_SN_STR[PCPS_SN_SIZE]; /** - * The structure has been introduced to be able to handle - * high resolution time stamps. + * @brief Extended status code + * + * Low byte corresponds to ::PCPS_TIME_STATUS, high byte + * contains additional flags. + * + * @see ::PCPS_TIME_STATUS + * @see @ref PCPS_TIME_STATUS_FLAGS */ -typedef struct -{ - uint32_t sec; /**< seconds since 1970 (UTC) */ - uint32_t frac; /**< fractions of second ( 0xFFFFFFFF == 0.9999.. sec) */ -} PCPS_TIME_STAMP; +typedef uint16_t PCPS_TIME_STATUS_X; -#define _mbg_swab_pcps_time_stamp( _p ) \ -{ \ - _mbg_swab32( &(_p)->sec ); \ - _mbg_swab32( &(_p)->frac ); \ -} +#define _mbg_swab_pcps_time_status_x( _p ) _mbg_swab16( _p ) +typedef struct +{ + PCPS_TIME_STATUS_X set_mask; + PCPS_TIME_STATUS_X clr_mask; -// Depending on the target environment define a data type -// which can be used to convert binary fractions without -// range overflow. -#if defined( MBG_TGT_UNIX ) - #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t -#elif defined( MBG_TGT_WIN32 ) - #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t -#elif defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 ) - #define PCPS_HRT_FRAC_CONVERSION_TYPE int64_t -#else - #define PCPS_HRT_FRAC_CONVERSION_TYPE double -#endif +} PCPS_TIME_STATUS_X_MASKS; -// Max value of PCPS_TIME_STAMP::frac + 1 used for scaling -#define PCPS_HRT_BIN_FRAC_SCALE ( (PCPS_HRT_FRAC_CONVERSION_TYPE) 4294967296.0 ) // == 0x100000000 +#define _mbg_swab_pcps_time_status_x_masks( _p ) \ +do \ +{ \ + _mbg_swab_pcps_time_status_x( &(_p)->set_mask ); \ + _mbg_swab_pcps_time_status_x( &(_p)->clr_mask ); \ +} while ( 0 ) -// The scale and format to be used to print the fractions -// of a second as returned in the PCPS_TIME_STAMP structure. -// The function frac_sec_from_bin() can be used for -// the conversion. -#ifndef PCPS_HRT_FRAC_SCALE - #define PCPS_HRT_FRAC_SCALE 10000000UL -#endif -#ifndef PCPS_HRT_FRAC_SCALE_FMT - #define PCPS_HRT_FRAC_SCALE_FMT "%07lu" -#endif +/** + * @brief Definitions used to report a signal strength + * + * @anchor PCPS_SIG_VAL_DEFS @{ */ +/** + * @brief A data type used to report the signal value + */ +typedef uint8_t PCPS_SIG_VAL; +// The following constants are used to draw a signal bar +// depending on a DCF77 clock's signal value: +#define PCPS_SIG_BIAS 55 +#define PCPS_SIG_ERR 1 +#define PCPS_SIG_MIN 20 +#define PCPS_SIG_MAX 68 -typedef uint16_t PCPS_TIME_STATUS_X; /**< extended status */ +// These constants are used by non-DCF77 devices to indicate +// if an input signal is available or not: +#define PCPS_SIG_LVL_SIG_NOT_AVAIL 0 +#define PCPS_SIG_LVL_SIG_AVAIL 128 + +/** @} anchor PCPS_SIG_VAL_DEFS */ -#define _mbg_swab_pcps_time_status_x( _p ) _mbg_swab16( _p ) /** - * The structure has been introduced to be able to read the - * current time with higher resolution of fractions of seconds and - * more detailed information on the time zone and status. - * The structure is returned if the new command #PCPS_GIVE_HR_TIME - * is written to the board. - * _pcps_has_hr_time() checks whether supported. - * - * Newer GPS boards also accept the #PCPS_GIVE_UCAP_EVENT command - * to return user capture event times using this format. In this - * case, the "signal" field contains the number of the capture - * input line, e.g. 0 or 1. - * _pcps_has_ucap() checks whether supported. + * @brief High resolution time including status and local time offset + * + * Used to read time with high resolution of fractions of seconds and + * more detailed information on the local time offset and status. + * Should be prefered over ::PCPS_TIME. + * + * ::_pcps_has_hr_time checks whether the command ::PCPS_GIVE_TIME is + * supported to read a device's current time using this format. + * + * Newer devices providing time capture input may also accept the + * ::PCPS_GIVE_UCAP_EVENT command to read user capture event times + * using this format. In this case, the "signal" field contains + * the number of the capture input line, e.g. 0 or 1. + * ::_pcps_has_ucap checks whether this is supported. */ typedef struct { - PCPS_TIME_STAMP tstamp; /**< High resolution time stamp (UTC) */ - int32_t utc_offs; /**< UTC offs [sec] (loc_time = UTC + utc_offs) */ - PCPS_TIME_STATUS_X status; /**< status flags as defined below */ - uint8_t signal; /**< for normal time, the relative RF signal level, for ucap, the channel number */ + PCPS_TIME_STAMP tstamp; ///< High resolution time stamp (%UTC) + int32_t utc_offs; ///< %UTC offs [sec] (loc_time = tstamp + utc_offs) + PCPS_TIME_STATUS_X status; ///< status bits, see @ref PCPS_TIME_STATUS_FLAGS + PCPS_SIG_VAL signal; ///< signal strength, see @ref PCPS_SIG_VAL_DEFS, or capture input channel number + } PCPS_HR_TIME; #define _mbg_swab_pcps_hr_time( _p ) \ +do \ { \ _mbg_swab_pcps_time_stamp( &(_p)->tstamp ); \ _mbg_swab32( &(_p)->utc_offs ); \ _mbg_swab_pcps_time_status_x( &(_p)->status ); \ -} +} while ( 0 ) +/** + * @brief Time synchronization status + * + * Used by legacy API calls. New API calls provide + * an extended status word ::PCPS_TIME_STATUS_X. + * + * @see ::PCPS_TIME_STATUS_FLAGS_COMMON + * @see ::PCPS_TIME_STATUS_X + */ typedef uint8_t PCPS_TIME_STATUS; -/** - The standard structure used to read times from the board. - The time has a resultion of 10 ms. -*/ -typedef struct PCPS_TIME_s + + +/** + * @brief Local calendar date and time, plus sync status + * + * This legacy structure is supported by all bus level devices but + * has a time resultion of 10 ms only. For more accurate time stamps + * the structures ::PCPS_HR_TIME and ::PCPS_TIME_STAMP should be + * used preferably. + * + * @see ::PCPS_HR_TIME + * @see ::PCPS_TIME_STAMP + * @see ::PCPS_STIME + */ +typedef struct { - uint8_t sec100; /**< hundredths of seconds, 0..99 */ - uint8_t sec; /**< seconds, 0..59, or 60 if leap second */ - uint8_t min; /**< minutes, 0..59 */ - uint8_t hour; /**< hours, 0..23 */ - - uint8_t mday; /**< day of month, 0..31 */ - uint8_t wday; /**< day of week, 1..7, 1 = Monday */ - uint8_t month; /**< month, 1..12 */ - uint8_t year; /**< year of the century, 0..99 */ - - PCPS_TIME_STATUS status; /**< status bits, see below */ - uint8_t signal; /**< relative signal strength, range depends on device type */ - int8_t offs_utc; /**< [hours], 0 if !_pcps_has_utc_offs() */ + uint8_t sec100; ///< hundredths of seconds, 0..99, 10 ms resolution + uint8_t sec; ///< seconds, 0..59, or 60 if leap second + uint8_t min; ///< minutes, 0..59 + uint8_t hour; ///< hours, 0..23 + + uint8_t mday; ///< day of month, 0..31 + uint8_t wday; ///< day of week, 1..7, 1 = Monday + uint8_t month; ///< month, 1..12 + uint8_t year; ///< year of the century, 0..99 + + PCPS_TIME_STATUS status; ///< status bits, see ::PCPS_TIME_STATUS_FLAGS_COMMON + PCPS_SIG_VAL signal; ///< signal strength, see @ref PCPS_SIG_VAL_DEFS + int8_t offs_utc; ///< [hours], 0 if not ::_pcps_has_utc_offs + } PCPS_TIME; -/** - The structure is passed as parameter with the PCPS_SET_TIME cmd -*/ -typedef struct PCPS_STIME_s + +/** + * @brief Date time and status used with the ::PCPS_SET_TIME command + * + * Similar to ::PCPS_TIME, but missing the ::PCPS_TIME::signal + * and ::PCPS_TIME::offs_utc fields. + * + * @see ::PCPS_TIME + */ +typedef struct { - uint8_t sec100; /**< hundredths of seconds, 0..99 */ - uint8_t sec; /**< seconds, 0..59, or 60 if leap second */ - uint8_t min; /**< minutes, 0..59 */ - uint8_t hour; /**< hours, 0..23 */ + uint8_t sec100; ///< hundredths of seconds, 0..99, 10 ms resolution + uint8_t sec; ///< seconds, 0..59, or 60 if leap second + uint8_t min; ///< minutes, 0..59 + uint8_t hour; ///< hours, 0..23 + + uint8_t mday; ///< day of month, 0..31 + uint8_t wday; ///< day of week, 1..7, 1 = Monday + uint8_t month; ///< month, 1..12 + uint8_t year; ///< year of the century, 0..99 - uint8_t mday; /**< day of month, 0..31 */ - uint8_t wday; /**< day of week, 1..7, 1 = Monday */ - uint8_t month; /**< month, 1..12 */ - uint8_t year; /**< year of the century, 0..99 */ + PCPS_TIME_STATUS status; ///< status bits, see ::PCPS_TIME_STATUS_FLAGS_COMMON - PCPS_TIME_STATUS status; /**< status bits, see below */ } PCPS_STIME; #ifdef _C166 - // This is a workaround to specify some structure sizes. The C166 compiler - // always reports an even structure size although the structure size may - // be odd due to the number of bytes. This might lead to errors between + // This is a workaround to specify some structure sizes. The C166 compiler + // always reports an even structure size although the structure size may + // be odd due to the number of bytes. This might lead to errors between // the C166 and other build environments. #define sizeof_PCPS_TIME ( sizeof( PCPS_TIME ) - 1 ) #define sizeof_PCPS_STIME ( sizeof( PCPS_STIME ) - 1 ) @@ -1005,129 +1181,174 @@ typedef union { PCPS_TIME t; PCPS_STIME stime; + } PCPS_TIME_UNION; /** - The structure below can be used to read the raw IRIG time - from an IRIG receiver card, if the card supports this. - See the #PCPS_GIVE_IRIG_TIME command. - - The granularity of the value in the .frac field depends on - the update interval of the structure as implementation - in the firmware. I.e. if the raw IRIG time is updated - only once per second, the .frac value can always be 0. -*/ -typedef struct PCPS_IRIG_TIME_s + * @brief Raw IRIG time + * + * Used to read the raw IRIG time from an IRIG receiver card, if the card + * supports this. See the ::PCPS_GIVE_IRIG_TIME command. + * + * The granularity of the value in the ::PCPS_IRIG_TIME::frac field + * depends on the update interval at which the structure is updated + * by the firmeware. I.e., if the raw IRIG time is updated only + * once per second, the ::PCPS_IRIG_TIME::frac value can always be 0. + * + * @see @ref group_icode + * @see ::ICODE_RX_CODES + */ +typedef struct { - PCPS_TIME_STATUS_X status; /**< status bits, see below */ - int16_t offs_utc; /**< [minutes] */ - uint16_t yday; /**< day of year, 1..365/366 */ - uint16_t frac; /**< fractions of seconds, 0.1 ms units */ - uint8_t sec; /**< seconds, 0..59, or 60 if leap second */ - uint8_t min; /**< minutes, 0..59 */ - uint8_t hour; /**< hours, 0..23 */ - uint8_t year; /**< 2 digit year number, 0xFF if year not supp. by the IRIG code */ - uint8_t signal; /**< relative signal strength, range depends on device type */ - uint8_t reserved; /**< currently not used, always 0 */ + PCPS_TIME_STATUS_X status; ///< status bits, see @ref PCPS_TIME_STATUS_FLAGS + int16_t offs_utc; ///< [minutes], 0 unless supported by the code format, see ::MSK_ICODE_RX_HAS_TZI + uint16_t yday; ///< day of year, 1..365/366 + uint16_t frac; ///< fractions of seconds, 0.1 ms units + uint8_t sec; ///< seconds, 0..59, may be 60 for leap second + uint8_t min; ///< minutes, 0..59 + uint8_t hour; ///< hours, 0..23 + uint8_t year; ///< 2 digit year number, or ::IRIG_TIME_UNKNOWN_YEAR if year not supported + ///< by the time code, see ::MSK_ICODE_RX_HAS_ANY_SHORT_YEAR + PCPS_SIG_VAL signal; ///< signal strength, see @ref PCPS_SIG_VAL_DEFS + uint8_t reserved; ///< currently not used, always 0 + } PCPS_IRIG_TIME; #define _mbg_swab_pcps_irig_time( _p ) \ +do \ { \ _mbg_swab_pcps_time_status_x( &(_p)->status ); \ _mbg_swab16( &(_p)->offs_utc ); \ _mbg_swab16( &(_p)->yday ); \ _mbg_swab16( &(_p)->frac ); \ -} - - +} while ( 0 ) /** - * Bit masks used with both PCPS_TIME_STATUS and PCPS_TIME_STATUS_X + * @brief A constant representing a 2 digit unknown IRIG year number + * + * Used with ::PCPS_IRIG_TIME::year */ -#define PCPS_FREER 0x01 /**< DCF77 clock running on xtal */ - /**< GPS receiver has not verified its position */ - -#define PCPS_DL_ENB 0x02 /**< daylight saving enabled */ +#define IRIG_TIME_UNKNOWN_YEAR 0xFF -#define PCPS_SYNCD 0x04 /**< clock has sync'ed at least once after pwr up */ - -#define PCPS_DL_ANN 0x08 /**< a change in daylight saving is announced */ - -#define PCPS_UTC 0x10 /**< a special UTC firmware is installed */ - -#define PCPS_LS_ANN 0x20 /**< leap second announced */ - /**< (requires firmware rev. REV_PCPS_LS_ANN_...) */ - -#define PCPS_IFTM 0x40 /**< the current time was set via PC */ - /**< (requires firmware rev. REV_PCPS_IFTM_...) */ - -#define PCPS_INVT 0x80 /**< invalid time because battery was disconn'd */ /** - * Bit masks used only with PCPS_TIME_STATUS_X - */ -#define PCPS_LS_ENB 0x0100 /**< current second is leap second */ -#define PCPS_ANT_FAIL 0x0200 /**< antenna failure */ -#define PCPS_LS_ANN_NEG 0x0400 /**< announced leap second is negative */ -#define PCPS_SCALE_GPS 0x0800 /**< time stamp is GPS scale */ -#define PCPS_SCALE_TAI 0x1000 /**< time stamp is TAI scale */ + * @brief Time status flags + * + * @anchor PCPS_TIME_STATUS_FLAGS @{ */ /** - * Bit masks used only with time stamps representing user capture events + * @brief Legacy time status flags + * + * Bit masks used with both ::PCPS_TIME_STATUS and ::PCPS_TIME_STATUS_X */ -#define PCPS_UCAP_OVERRUN 0x2000 /**< events interval too short */ -#define PCPS_UCAP_BUFFER_FULL 0x4000 /**< events read too slow */ +enum PCPS_TIME_STATUS_FLAGS_COMMON +{ + PCPS_FREER = 0x01, ///< long wave or time code receiver running on xtal, satellite receiver has not verified its position + PCPS_DL_ENB = 0x02, ///< daylight saving currently enabled + PCPS_SYNCD = 0x04, ///< long wave or time code receiver has sync'ed at least once after pwr up, sat receiver is synchronized + PCPS_DL_ANN = 0x08, ///< a change in daylight saving status is announced + PCPS_UTC = 0x10, ///< returned time is always %UTC instead of some local time + PCPS_LS_ANN = 0x20, ///< leap second announced, for *very* old clocks see ::REV_PCPS_LS_ANN_PC31PS31 + PCPS_IFTM = 0x40, ///< the current time has been set by an API call, for *very* old clocks see ::REV_PCPS_IFTM_PC31PS31 + PCPS_INVT = 0x80 ///< invalid time because battery had been disconnected, or absolute time can't be decoded safely +}; -/** - * Bit masks used only with time stamps representing the current board time. - * A DCF77 PZF receiver can set this bit if it is actually synchronized - * using PZF correlation and thus provides higher accuracy than AM receivers. - */ -#define PCPS_SYNC_PZF 0x2000 /**< same code as PCPS_UCAP_OVERRUN */ /** - * Immediately after a clock has been accessed, subsequent accesses - * are blocked for up to 1.5 msec to give the clock's microprocessor - * some time to decode the incoming time signal. - * The flag below is set if a program tries to read the PCPS_HR_TIME - * during this interval. In this case the read function returns the - * proper time stamp which is taken if the command byte is written, - * however, the read function returns with delay. - * This flag is not supported by all clocks. + * @brief Extended time status flags + * + * Bit masks used with ::PCPS_TIME_STATUS_X only */ -#define PCPS_IO_BLOCKED 0x8000 +enum PCPS_TIME_STATUS_FLAGS_EXT +{ + PCPS_LS_ENB = 0x0100, ///< current second is leap second + PCPS_ANT_FAIL = 0x0200, ///< antenna failure + PCPS_LS_ANN_NEG = 0x0400, ///< announced leap second is negative + PCPS_SCALE_GPS = 0x0800, ///< time stamp is GPS scale + PCPS_SCALE_TAI = 0x1000, ///< time stamp is TAI scale + + PCPS_UCAP_OVERRUN = 0x2000, ///< events interval too short (capture events only) + PCPS_UCAP_BUFFER_FULL = 0x4000, ///< events read too slow (capture events only) + + /** + * Bit masks used only with time stamps representing the current board time. + * A DCF77 PZF receiver can set this bit if it is actually synchronized + * using PZF correlation and thus provides higher accuracy than AM receivers. + * Same numeric code as ::PCPS_UCAP_OVERRUN + */ + PCPS_SYNC_PZF = 0x2000, + + /** + * Immediately after a clock has been accessed, subsequent accesses + * may be blocked for up to 1.5 msec to give the clock's microprocessor + * some time to decode the incoming time signal. + * The flag below is eventually set if a program tries to read ::PCPS_HR_TIME + * during this interval. In this case the read function returns the + * proper time stamp which is taken if the command byte is written, + * however, the read function returns with delay. + * This flag is not supported by all clocks. + */ + PCPS_IO_BLOCKED = 0x8000 +}; + + /** * This bit mask can be used to extract the time scale information out * of a PCPS_TIME_STATUS_X value. -*/ + */ #define PCPS_SCALE_MASK ( PCPS_SCALE_TAI | PCPS_SCALE_GPS ) +/** @} anchor PCPS_TIME_STATUS_FLAGS */ + + + +/** + * @brief Legacy definitions used to configure a device's serial port + * + * @deprecated This structure and the associated command codes + * are deprecated. ::PORT_SETTINGS, ::PORT_INFO and associated + * definitions should be used instead, if supported. + * + * @anchor PCPS_OLD_SERIAL_CFG @{ */ + /** - * Some DCF77 clocks have a serial interface that can be controlled - * using the commands PCPS_SET_SERIAL and PCPS_GET_SERIAL. Both commands - * use a parameter byte describing transmission speed, framing and mode - * of operation. The parameter byte can be build using the constants - * defined below, by or'ing one of the constants of each group, shifted - * to the right position. PCPS_GET_SERIAL expects that parameter byte - * and PCPS_GET_SERIAL returns the current configuration from the board. - * _pcps_has_serial() checks whether supported. - * For GPS clocks, please refer to the comments for the PCPS_GET_SERIAL + * @brief Configuration information for a device's serial port + * + * Used with ::PCPS_GET_SERIAL and ::PCPS_SET_SERIAL + * + * The serial interface on some old DCF77 clocks can be configured + * using the commands ::PCPS_SET_SERIAL and ::PCPS_GET_SERIAL. + * Both commands use a parameter byte describing transmission speed, + * framing and mode of operation. The parameter byte can be assembled + * using the constants defined in ::PCPS_BD_CODES, ::PCPS_FR_CODES, + * and ::PCPS_MOD_CODES, by or'ing one of the constants of each group, + * shifted to the right position. ::PCPS_GET_SERIAL expects that parameter + * byte and ::PCPS_GET_SERIAL returns the current configuration from + * the board. + * ::_pcps_has_serial checks whether supported. + * For old GPS clocks refer to the comments for the ::PCPS_GET_SERIAL * command. */ +typedef uint8_t PCPS_SERIAL; + /** - * Baud rate indices. The values below are obsolete and should - * be replaced by the codes named MBG_BAUD_RATE_... which are - * defined in gpsdefs.h. The resulting index numbers, however, - * have not changed. + * @brief Deprecated baud rate indices + * + * @deprecated These values are deprecated. + * ::MBG_BAUD_RATE_CODES and associated structures + * should be used preferably. + * + * The sequence of codes matches the sequence + * defined in ::MBG_BAUD_RATE_CODES. */ -enum +enum PCPS_BD_CODES { PCPS_BD_300, PCPS_BD_600, @@ -1136,233 +1357,429 @@ enum PCPS_BD_4800, PCPS_BD_9600, PCPS_BD_19200, - N_PCPS_BD /* number of codes */ + N_PCPS_BD ///< number of codes }; -#define PCPS_BD_BITS 4 /* field with in the cfg byte */ -#define PCPS_BD_SHIFT 0 /* num of bits to shift left */ +#define PCPS_BD_BITS 4 ///< field with in the cfg byte +#define PCPS_BD_SHIFT 0 ///< num of bits to shift left -/* - * Initializers for a table of all baud rate strings - * and values can be found in gpsdefs.h. - */ /** - * Unfortunately, the framing codes below can not simply be - * replaced by the newer MBG_FRAMING_... definitions since - * the order of indices does not match. + * @brief Deprecated framing code indices + * + * @deprecated These values are deprecated. + * ::MBG_FRAMING_CODES and associated structures + * should be used preferably. + * + * Unfortunately, these framing codes can *not* simply + * be replaced by the newer MBG_FRAMING_... definitions + * since the order of indices doesn't match. */ -enum +enum PCPS_FR_CODES { PCPS_FR_8N1, PCPS_FR_7E2, PCPS_FR_8N2, PCPS_FR_8E1, - N_PCPS_FR_DCF /* number of valid codes */ + N_PCPS_FR_DCF ///< number of valid codes }; -#define PCPS_FR_BITS 2 /* field with in the cfg byte */ -#define PCPS_FR_SHIFT PCPS_BD_BITS /* num of bits to shift left */ +#define PCPS_FR_BITS 2 ///< field with in the cfg byte +#define PCPS_FR_SHIFT PCPS_BD_BITS ///< num of bits to shift left + + -/* - * An initializer for a table of framing strings is only defined for - * the new MBG_FRAMING_... definitions. For editing the serial port - * configuration, the old codes above should be translated to the new - * codes to unify handling inside the edit functions. +/** + * @brief Deprecated codes for modes of operation + * + * @deprecated These values are deprecated. + * ::STR_MODES and associated structures + * should be used preferably. + * + * The sequence of codes matches the sequence + * defined in ::STR_MODES. */ +enum PCPS_MOD_CODES +{ + PCPS_MOD_REQ, ///< time string on request '?' only + PCPS_MOD_SEC, ///< time string once per second + PCPS_MOD_MIN, ///< time string once per minute + PCPS_MOD_RSVD, ///< reserved + N_PCPS_MOD_DCF ///< number of possible codes +}; + +#define PCPS_MOD_BITS 2 ///< field with in the cfg byte +#define PCPS_MOD_SHIFT ( PCPS_BD_BITS + PCPS_FR_BITS ) ///< num of bits to shift left -/** - Modes of operation +/** @} anchor PCPS_OLD_SERIAL_CFG */ - * Indices for modes of operation. The values below are obsolete - * and should be replaced by the codes named STR_... which are - * defined in gpsdefs.h. The resulting index numbers, however, - * have not changed. + + +/** + * @brief Type of variable to hold a TZ code + * + * This is used with the PCI interface but differs from ::TZCODE + * which is used with the binary protocol. + * + * @see ::TZCODE + * @see ::TZCODE_UNION */ -enum +typedef uint8_t PCPS_TZCODE; + + +/** + * @brief Enumeration of codes used with PCPS_TZCODE + */ +enum PCPS_TZCODES { - PCPS_MOD_REQ, /* time string on request '?' only */ - PCPS_MOD_SEC, /* time string once per second */ - PCPS_MOD_MIN, /* time string once per minute */ - PCPS_MOD_RSVD, /* reserved */ - N_PCPS_MOD_DCF /* number of possible codes */ + PCPS_TZCODE_CET_CEST, ///< default as broadcast by DCF77 (UTC+1h/UTC+2h) + PCPS_TZCODE_CET, ///< always CET (UTC+1h), discard DST + PCPS_TZCODE_UTC, ///< always %UTC + PCPS_TZCODE_EET_EEST, ///< East European Time, CET/CEST + 1h + N_PCPS_TZCODE ///< the number of valid codes }; -#define PCPS_MOD_BITS 2 /* field with in the cfg byte */ -#define PCPS_MOD_SHIFT ( PCPS_BD_BITS + PCPS_FR_BITS ) - /* num of bits to shift left */ +/* the definitions below are for compatibily only: */ +#define PCPS_TZCODE_MEZMESZ PCPS_TZCODE_CET_CEST +#define PCPS_TZCODE_MEZ PCPS_TZCODE_CET +#define PCPS_TZCODE_OEZ PCPS_TZCODE_EET_EEST + + +/** + * @brief Daylight changeover specification + * + * Used as member field of ::PCPS_TZDL only. Most devices supporting + * conversion to local time support the ::TZDL structure instead. + * + * @see ::TZDL + */ +typedef struct +{ + uint16_t year_or_wday; ///< The full year number, or 0..6 == Sun..Sat if the ::DL_AUTO_FLAG is set + uint8_t month; ///< [1..12] + uint8_t mday; ///< [1..31] + uint8_t hour; ///< [0..23] + uint8_t min; ///< [0..59] + +} PCPS_DL_ONOFF; + +#define _mbg_swab_pcps_dl_onoff( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->year_or_wday ); \ +} while ( 0 ) + +/** + * @brief A flag indicating if DST changeovers are to be computed automatically + * + * If ::PCPS_DL_ONOFF::year_or_wday is or'ed with the constant ::DL_AUTO_FLAG + * then start and end of daylight saving time shall be computed automatically + * for each year. In this case the remaining bits represent the day-of-week + * after the specified mday/month at which the change shall occur. + * If that flag is not set then the field contains the full four-digit year number + * and the ::PCPS_DL_ONOFF::mday and ::PCPS_DL_ONOFF::month values specify + * the exact date of that year. Most devices supporting conversion to local time + * support the ::TZDL structure instead. + * + * @see ::TZDL + * @see ::PCPS_TZDL + */ +#define DL_AUTO_FLAG 0x8000 // also defined in gpsdefs.h /** - * Some definitions used with PZF receivers + * @brief Specification of a local time zone + * + * Most devices supporting conversion to local time support + * the ::TZDL structure instead. + * + * @see ::DL_AUTO_FLAG + * @see ::TZDL */ +typedef struct +{ + int16_t offs; ///< offset from %UTC to local time [min] (local time = %UTC + offs) + int16_t offs_dl; ///< additional offset if DST enabled [min] (DST time = local time + offs_dl) + PCPS_DL_ONOFF tm_on; ///< date/time when daylight saving starts + PCPS_DL_ONOFF tm_off; ///< date/time when daylight saving ends + +} PCPS_TZDL; + +#define _mbg_swab_pcps_tzdl( _p ) \ +do \ +{ \ + _mbg_swab16( &(_p)->offs ); \ + _mbg_swab16( &(_p)->offs_dl ); \ + _mbg_swab_pcps_dl_onoff( &(_p)->tm_on ); \ + _mbg_swab_pcps_dl_onoff( &(_p)->tm_off ); \ +} while ( 0 ) + -/* receiver distance from transmitter [km] */ -typedef uint16_t TR_DISTANCE; + +/** + * @brief Status of the time capture FIFO buffer + * + * Only supported if ::RECEIVER_INFO::n_ucaps > 0. + */ +typedef struct +{ + uint32_t used; ///< the number of saved capture events + uint32_t max; ///< capture buffer size + +} PCPS_UCAP_ENTRIES; + +#define _mbg_swab_pcps_ucap_entries( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->used ); \ + _mbg_swab32( &(_p)->max ); \ +} while ( 0 ) + + + +/** + * @defgroup group_pzf_supp Definitions used with PZF receivers + * + * @{ */ + +/** + * @brief Receiver distance from transmitter [km] + */ +typedef uint16_t TR_DISTANCE; ///< Range may vary with receiver type #define _mbg_swab_tr_distance( _p ) \ _mbg_swab16( _p ) - -/* correlation status info */ +/** + * @brief PZF correlation status info + */ typedef struct { - uint8_t val; /**< correlation value, or check count if status == PZF_CORR_CHECK */ - uint8_t status; /**< status codes, see below */ - char corr_dir; /**< space, '<', or '>' */ - uint8_t signal; /**< signal level, may always be 0 for devices which do not support this */ + uint8_t val; ///< correlation value, or check count if status ==:: PZF_CORR_CHECK + uint8_t status; ///< status codes, see ::PZF_CORR_STATES + char corr_dir; ///< space, '<', or '>', just for information + PCPS_SIG_VAL signal; ///< signal strength, see @ref PCPS_SIG_VAL_DEFS + } CORR_INFO; #define _mbg_swab_corr_info( _p ) \ _nop_macro_fnc() -/** Codes used with CORR_INFO::status: */ -enum +/** + * @brief Codes used with ::CORR_INFO::status + */ +enum PZF_CORR_STATES { - PZF_CORR_RAW, /**< trying raw correlation, combi receivers running in AM mode */ - PZF_CORR_CHECK, /**< raw correlation achieved, doing plausibility checks */ - PZF_CORR_FINE, /**< fine correlation achieved */ + PZF_CORR_RAW, ///< trying raw correlation, combi receivers running in AM mode + PZF_CORR_CHECK, ///< raw correlation achieved, doing plausibility checks + PZF_CORR_FINE, ///< fine correlation achieved N_PZF_CORR_STATE }; -/** @defgroup group_gps_cmds_bus GPS commands passed via the system bus +#define PZF_CORR_STATE_NAME_RAW_ENG "Searching" +#define PZF_CORR_STATE_NAME_CHECK_ENG "Correlating" +#define PZF_CORR_STATE_NAME_FINE_ENG "Locked" - This enumeration defines the various types of data that can be read - from or written to Meinberg bus level devices which support this. - Access should be done using the functions ::pcps_read_gps_data() - and ::pcps_write_gps_data() since the size of some of the structures - exceeds the size of the devices's I/O buffer and must therefore be - accessed in several portions. +#define PZF_CORR_STATE_NAME_RAW_GER "suchen" +#define PZF_CORR_STATE_NAME_CHECK_GER "korrelieren" +#define PZF_CORR_STATE_NAME_FINE_GER "eingerastet" - The structures to be used are defined in gpsdefs.h. Not all structures - are supportet, yet. Check the R/W indicators for details. - * @{ */ -enum -{ // R/W data type description - // system data ----------------------------------------------- - PC_GPS_TZDL = 0, // R/W TZDL time zone / daylight saving - PC_GPS_SW_REV, // R/- SW_REV software revision - PC_GPS_BVAR_STAT, // R/- BVAR_STAT status of buffered variables - PC_GPS_TIME, // R/W TTM curr. time - PC_GPS_POS_XYZ, // -/W XYZ curr. pos. in ECEF coords - PC_GPS_POS_LLA, // -/W LLA curr. pos. in geogr. coords - PC_GPS_PORT_PARM, // R/W PORT_PARM param. of the serial ports - PC_GPS_ANT_INFO, // R/- ANT_INFO time diff after ant. disconn. - PC_GPS_UCAP, // R/- TTM user capture - PC_GPS_ENABLE_FLAGS, // R/W ENABLE_FLAGS controls when to enable outp. - PC_GPS_STAT_INFO, // R/- GPS_STAT_INFO - PC_GPS_CMD, // -/W GPS_CMD commands as described below - PC_GPS_IDENT, // R/- GPS_IDENT serial number - PC_GPS_POS, // R/- POS position XYZ, LLA, and DMS - PC_GPS_ANT_CABLE_LEN, // R/W ANT_CABLE_LEN used to compensate delay - // The codes below are supported by new GPS receiver boards: - PC_GPS_RECEIVER_INFO, // R/- RECEIVER_INFO rcvr model info - PC_GPS_ALL_STR_TYPE_INFO, // R/- n*STR_TYPE_INFO_IDX all string types - PC_GPS_ALL_PORT_INFO, // R/- n*PORT_INFO_IDX all port info - PC_GPS_PORT_SETTINGS_IDX, // -/W PORT_SETTINGS_IDX port settings only - PC_GPS_ALL_POUT_INFO, // R/- n*POUT_INFO_IDX all pout info - PC_GPS_POUT_SETTINGS_IDX, // -/W POUT_SETTINGS_IDX pout settings only - PC_GPS_TIME_SCALE, // R/W MBG_TIME_SCALE_{SETTINGS|INFO}, only if PCPS_HAS_TIME_SCALE - PC_GPS_LAN_IF_INFO, // R/- LAN_IF_INFO LAN interface info, only if PCPS_HAS_LAN_INTF - PC_GPS_IP4_STATE, // R/- IP4_SETTINGS LAN interface state, only if PCPS_HAS_LAN_INTF - PC_GPS_IP4_SETTINGS, // R/W IP4_SETTINGS LAN interface configuration, only if PCPS_HAS_LAN_INTF - PC_GPS_PTP_STATE, // R/- PTP_STATE, only if PCPS_HAS_PTP - PC_GPS_PTP_CFG, // R/W PTP_CFG_{SETTINGS|INFO}, only if PCPS_HAS_PTP - PC_GPS_PTP_UC_MASTER_CFG_LIMITS, // R/- PTP_UC_MASTER_CFG_LIMITS, only if can be unicast master - PC_GPS_ALL_PTP_UC_MASTER_INFO, // R/- n*PTP_UC_MASTER_INFO_IDX, only if can be unicast master - PC_GPS_PTP_UC_MASTER_SETTINGS_IDX, // -/W PTP_UC_MASTER_SETTINGS_IDX, only if can be unicast master - PC_GPS_GPIO_CFG_LIMITS, // R/- MBG_GPIO_CFG_LIMITS, only if PCPS_HAS_GPIO - PC_GPS_ALL_GPIO_INFO, // R/- n*MBG_GPIO_INFO, all GPIO info, only if PCPS_HAS_GPIO - PC_GPS_GPIO_SETTINGS_IDX, // -/W MBG_GPIO_SETTINGS_IDX, GPIO cfg for a specific port, only if PCPS_HAS_GPIO +#define PZF_CORR_STATE_NAMES_ENG \ +{ \ + PZF_CORR_STATE_NAME_RAW_ENG, \ + PZF_CORR_STATE_NAME_CHECK_ENG, \ + PZF_CORR_STATE_NAME_FINE_ENG \ +} + + +#define PZF_CORR_STATE_NAMES_LSTR \ +{ \ + { PZF_CORR_STATE_NAME_RAW_ENG, PZF_CORR_STATE_NAME_RAW_GER }, \ + { PZF_CORR_STATE_NAME_CHECK_ENG, PZF_CORR_STATE_NAME_CHECK_GER }, \ + { PZF_CORR_STATE_NAME_FINE_ENG, PZF_CORR_STATE_NAME_FINE_GER } \ +} + +/** @} defgroup group_pzf_supp */ + + + +/** + * @brief GPS Command codes passed via the system bus + * + * Codes specifying various types of data that can be read from or + * written to Meinberg bus level devices which support this. + * Access is done using the low level functions ::pcps_read_gps + * and ::pcps_write_gps since the size of some of the structures + * exceeds the size of the device's I/O buffer and must therefore be + * accessed in several blocks. + * + * Applications should instead use the API functions declared in mbgdevio.h. + * + * The structures to be used are defined in gpsdefs.h. Not all structures + * are supported, yet. Check the r/w indicators for details. + * + * @see @ref PCPS_CMD_CODES + * @see ::PC_GPS_CMD_CODES_TABLE + */ +enum PC_GPS_CMD_CODES +{ + PC_GPS_TZDL, ///< (r/w) ::TZDL, time zone / daylight saving, only if ::GPS_MODEL_HAS_TZDL + PC_GPS_SW_REV, ///< (r/-) ::SW_REV, software revision, deprecated by ::PC_GPS_RECEIVER_INFO + PC_GPS_BVAR_STAT, ///< (r/-) ::BVAR_STAT, status of buffered variables, only if ::GPS_MODEL_HAS_BVAR_STAT + PC_GPS_TIME, ///< (r/w) ::TTM, current time, deprecated by ::PCPS_GIVE_HR_TIME + PC_GPS_POS_XYZ, ///< (-/w) ::XYZ, current position in ECEF coordinates, only if ::GPS_MODEL_HAS_POS_XYZ + PC_GPS_POS_LLA, ///< (-/w) ::LLA, current position in geographic coordinates, only if ::GPS_MODEL_HAS_POS_LLA + PC_GPS_PORT_PARM, ///< (r/w) ::PORT_PARM, param. of the serial ports, deprecated by ::PC_GPS_ALL_PORT_INFO + PC_GPS_ANT_INFO, ///< (r/-) ::ANT_INFO, time diff at sync. after antenna had been disconn., only if ::GPS_MODEL_HAS_ANT_INFO + + PC_GPS_UCAP, ///< (r/-) ::TTM, user capture events, deprecated by ::PCPS_GIVE_UCAP_EVENT + PC_GPS_ENABLE_FLAGS, ///< (r/w) ::ENABLE_FLAGS, when to enable serial, pulses, and synth, only if ::GPS_MODEL_HAS_ENABLE_FLAGS + PC_GPS_STAT_INFO, ///< (r/-) ::GPS_STAT_INFO, satellite info, mode of operation, and DAC info, only if ::GPS_MODEL_HAS_STAT_INFO + PC_GPS_CMD, ///< (-/w) ::GPS_CMD, send one of the ::PC_GPS_COMMANDS + PC_GPS_IDENT, ///< (r/-) ::IDENT, serial number, deprecated by ::PC_GPS_RECEIVER_INFO + PC_GPS_POS, ///< (r/-) ::POS, position ::XYZ, ::LLA, and ::DMS combined, only if ::GPS_MODEL_HAS_POS + PC_GPS_ANT_CABLE_LEN, ///< (r/w) ::ANT_CABLE_LEN, length of antenna cable, only if ::GPS_MODEL_HAS_ANT_CABLE_LEN + PC_GPS_RECEIVER_INFO, ///< (r/-) ::RECEIVER_INFO, rcvr model info, only if ::PCPS_HAS_RECEIVER_INFO + + PC_GPS_ALL_STR_TYPE_INFO, ///< (r/-) n * ::STR_TYPE_INFO_IDX, names and capabilities of all supp. string types, only if ::RECEIVER_INFO::n_str_type > 0 + PC_GPS_ALL_PORT_INFO, ///< (r/-) n * ::PORT_INFO_IDX, settings and capabilities of all serial ports, only if ::RECEIVER_INFO::n_com_ports > 0 + PC_GPS_PORT_SETTINGS_IDX, ///< (-/w) ::PORT_SETTINGS_IDX, settings for specified serial port, only if ::RECEIVER_INFO::n_com_ports > 0 + PC_GPS_ALL_POUT_INFO, ///< (r/-) n * ::POUT_INFO_IDX, all programmable output info + PC_GPS_POUT_SETTINGS_IDX, ///< (-/w) ::POUT_SETTINGS_IDX, settings for one programmable output + PC_GPS_TIME_SCALE, ///< (r/w) ::MBG_TIME_SCALE_SETTINGS / ::MBG_TIME_SCALE_INFO, only if ::PCPS_HAS_TIME_SCALE + PC_GPS_LAN_IF_INFO, ///< (r/-) ::LAN_IF_INFO, LAN interface info, only if ::PCPS_HAS_LAN_INTF + PC_GPS_IP4_STATE, ///< (r/-) ::IP4_SETTINGS, LAN interface state, only if ::PCPS_HAS_LAN_INTF + + PC_GPS_IP4_SETTINGS, ///< (r/w) ::IP4_SETTINGS, LAN interface configuration, only if ::PCPS_HAS_LAN_INTF + PC_GPS_PTP_STATE, ///< (r/-) ::PTP_STATE, only if ::PCPS_HAS_PTP + PC_GPS_PTP_CFG, ///< (r/w) ::PTP_CFG_SETTINGS / ::PTP_CFG_INFO, only if ::PCPS_HAS_PTP + PC_GPS_PTP_UC_MASTER_CFG_LIMITS, ///< (r/-) ::PTP_UC_MASTER_CFG_LIMITS, only if ::PTP_CFG_MSK_SUPPORT_PTP_UNICAST + PC_GPS_ALL_PTP_UC_MASTER_INFO, ///< (r/-) n * ::PTP_UC_MASTER_INFO_IDX, only if ::PTP_CFG_MSK_SUPPORT_PTP_UNICAST + PC_GPS_PTP_UC_MASTER_SETTINGS_IDX, ///< (-/w) ::PTP_UC_MASTER_SETTINGS_IDX, only if ::PTP_CFG_MSK_SUPPORT_PTP_UNICAST + PC_GPS_GPIO_CFG_LIMITS, ///< (r/-) ::MBG_GPIO_CFG_LIMITS, only if ::GPS_HAS_GPIO + PC_GPS_ALL_GPIO_INFO, ///< (r/-) n * ::MBG_GPIO_INFO_IDX, all GPIO info, only if ::GPS_HAS_GPIO + + PC_GPS_GPIO_SETTINGS_IDX, ///< (-/w) ::MBG_GPIO_SETTINGS_IDX, settings for a specific port, only if ::GPS_HAS_GPIO + PC_GPS_GNSS_MODE, ///< (r/w) ::MBG_GNSS_MODE_INFO / ::MBG_GNSS_MODE_SETTINGS, only if ::PCPS_IS_GNSS + PC_GPS_ALL_GNSS_SAT_INFO, ///< (r/-) n * ::GNSS_SAT_INFO_IDX, satellite info, only if ::PCPS_IS_GNSS + PC_GPS_XMR_INSTANCES, ///< (r/-) ::XMULTI_REF_INSTANCES, only if ::GPS_HAS_XMULTI_REF and ::GPS_HAS_XMRS_MULT_INSTC + PC_GPS_XMR_SETTINGS_IDX, ///< (-/w) ::XMULTI_REF_SETTINGS_IDX, idx 0..::XMULTI_REF_INSTANCES::n_xmr_settings-1, only if ::GPS_HAS_XMULTI_REF + PC_GPS_ALL_XMR_INFO, ///< (r/-) n * ::XMULTI_REF_INFO_IDX, where n == ::XMULTI_REF_INSTANCES::n_xmr_settings, only if ::GPS_HAS_XMULTI_REF + PC_GPS_ALL_XMR_STATUS, ///< (r/w) n * ::XMULTI_REF_STATUS_IDX, where n == ::XMULTI_REF_INSTANCES::n_xmr_settings, one structure on write, only if ::GPS_HAS_XMULTI_REF + PC_GPS_XMR_HOLDOVER_STATUS, ///< (r/-) ::XMR_HOLDOVER_STATUS, only if ::XMRIF_MSK_HOLDOVER_STATUS_SUPP + + PC_GPS_ALL_GPIO_STATUS, ///< (r/-) n * ::MBG_GPIO_STATUS_IDX, where n == ::MBG_GPIO_CFG_LIMITS::num_io, only if ::MBG_GPIO_CFG_LIMIT_FLAG_MASK_STATUS_SUPP + PC_GPS_XFEATURE_BUFFER, ///< (r/-) ::MBG_XFEATURE_BUFFER, only if ::GPS_HAS_XFEATURE + PC_GPS_TLV_INFO, ///< (r/-) ::MBG_TLV_INFO, only if ::MBG_XFEATURE_TLV_API // GPS data - PC_GPS_CFGH = 0x80, // -/- CFGH SVs' config. and health codes - PC_GPS_ALM, // -/- SV_ALM one SV's num and almanac - PC_GPS_EPH, // -/- SV_EPH one SV's num and ephemeris - PC_GPS_UTC, // R/W UTC UTC corr. param., only if PCPS_HAS_UTC_PARM - PC_GPS_IONO, // -/- IONO ionospheric corr. param. - PC_GPS_ASCII_MSG // -/- ASCII_MSG the GPS ASCII message + PC_GPS_CFGH = 0x80, ///< (-/-) ::CFGH, SVs' config. and health codes (yet not used) + PC_GPS_ALM, ///< (-/-) ::SV_ALM, one SV's num and almanac (yet not used) + PC_GPS_EPH, ///< (-/-) ::SV_EPH, one SV's num and ephemeris (yet not used) + PC_GPS_UTC, ///< (r/w) ::UTC, %UTC corr. param., only if ::PCPS_HAS_UTC_PARM + PC_GPS_IONO, ///< (-/-) ::IONO, ionospheric corr. param. (yet not used) + PC_GPS_ASCII_MSG ///< (-/-) ::ASCII_MSG, the GPS ASCII message (yet not used) }; -/** @} group_gps_cmds_bus */ - /** * @brief An initializer for a table of code/name entries of GPS commands. * - * This can e.g. be assigned to an array of MBG_CODE_NAME_TABLE_ENTRY elements + * This can e.g. be assigned to an array of ::MBG_CODE_NAME_TABLE_ENTRY elements * and may be helpful when debugging. + * + * @see ::PC_GPS_CMD_CODES */ -#define MBG_PC_GPS_CMD_TABLE \ -{ \ - { PC_GPS_TZDL, "PC_GPS_TZDL" }, \ - { PC_GPS_SW_REV, "PC_GPS_SW_REV" }, \ - { PC_GPS_BVAR_STAT, "PC_GPS_BVAR_STAT" }, \ - { PC_GPS_TIME, "PC_GPS_TIME" }, \ - { PC_GPS_POS_XYZ, "PC_GPS_POS_XYZ" }, \ - { PC_GPS_POS_LLA, "PC_GPS_POS_LLA" }, \ - { PC_GPS_PORT_PARM, "PC_GPS_PORT_PARM" }, \ - { PC_GPS_ANT_INFO, "PC_GPS_ANT_INFO" }, \ - { PC_GPS_UCAP, "PC_GPS_UCAP" }, \ - { PC_GPS_ENABLE_FLAGS, "PC_GPS_ENABLE_FLAGS" }, \ - { PC_GPS_STAT_INFO, "PC_GPS_STAT_INFO" }, \ - { PC_GPS_CMD, "PC_GPS_CMD" }, \ - { PC_GPS_IDENT, "PC_GPS_IDENT" }, \ - { PC_GPS_POS, "PC_GPS_POS" }, \ - { PC_GPS_ANT_CABLE_LEN, "PC_GPS_ANT_CABLE_LEN" }, \ - { PC_GPS_RECEIVER_INFO, "PC_GPS_RECEIVER_INFO" }, \ - { PC_GPS_ALL_STR_TYPE_INFO, "PC_GPS_ALL_STR_TYPE_INFO" }, \ - { PC_GPS_ALL_PORT_INFO, "PC_GPS_ALL_PORT_INFO" }, \ - { PC_GPS_PORT_SETTINGS_IDX, "PC_GPS_PORT_SETTINGS_IDX" }, \ - { PC_GPS_ALL_POUT_INFO, "PC_GPS_ALL_POUT_INFO" }, \ - { PC_GPS_POUT_SETTINGS_IDX, "PC_GPS_POUT_SETTINGS_IDX" }, \ - { PC_GPS_TIME_SCALE, "PC_GPS_TIME_SCALE" }, \ - { PC_GPS_LAN_IF_INFO, "PC_GPS_LAN_IF_INFO" }, \ - { PC_GPS_IP4_STATE, "PC_GPS_IP4_STATE" }, \ - { PC_GPS_IP4_SETTINGS, "PC_GPS_IP4_SETTINGS" }, \ - { PC_GPS_PTP_STATE, "PC_GPS_PTP_STATE" }, \ - { PC_GPS_PTP_CFG, "PC_GPS_PTP_CFG" }, \ - { PC_GPS_PTP_UC_MASTER_CFG_LIMITS, "PC_GPS_PTP_UC_MASTER_CFG_LIMITS" }, \ - { PC_GPS_ALL_PTP_UC_MASTER_INFO, "PC_GPS_ALL_PTP_UC_MASTER_INFO" }, \ - { PC_GPS_PTP_UC_MASTER_SETTINGS_IDX, "PC_GPS_PTP_UC_MASTER_SETTINGS_IDX" }, \ - { PC_GPS_GPIO_CFG_LIMITS, "PC_GPS_GPIO_CFG_LIMITS" }, \ - { PC_GPS_ALL_GPIO_INFO, "PC_GPS_ALL_GPIO_INFO" }, \ - { PC_GPS_GPIO_SETTINGS_IDX, "PC_GPS_GPIO_SETTINGS_IDX" }, \ - { PC_GPS_CFGH, "PC_GPS_CFGH" }, \ - { PC_GPS_ALM, "PC_GPS_ALM" }, \ - { PC_GPS_EPH, "PC_GPS_EPH" }, \ - { PC_GPS_UTC, "PC_GPS_UTC" }, \ - { PC_GPS_IONO, "PC_GPS_IONO" }, \ - { PC_GPS_ASCII_MSG, "PC_GPS_ASCII_MSG" }, \ - { 0, NULL } \ +#define PC_GPS_CMD_CODES_TABLE \ +{ \ + _mbg_cn_table_entry( PC_GPS_TZDL ), \ + _mbg_cn_table_entry( PC_GPS_SW_REV ), \ + _mbg_cn_table_entry( PC_GPS_BVAR_STAT ), \ + _mbg_cn_table_entry( PC_GPS_TIME ), \ + _mbg_cn_table_entry( PC_GPS_POS_XYZ ), \ + _mbg_cn_table_entry( PC_GPS_POS_LLA ), \ + _mbg_cn_table_entry( PC_GPS_PORT_PARM ), \ + _mbg_cn_table_entry( PC_GPS_ANT_INFO ), \ + _mbg_cn_table_entry( PC_GPS_UCAP ), \ + _mbg_cn_table_entry( PC_GPS_ENABLE_FLAGS ), \ + _mbg_cn_table_entry( PC_GPS_STAT_INFO ), \ + _mbg_cn_table_entry( PC_GPS_CMD ), \ + _mbg_cn_table_entry( PC_GPS_IDENT ), \ + _mbg_cn_table_entry( PC_GPS_POS ), \ + _mbg_cn_table_entry( PC_GPS_ANT_CABLE_LEN ), \ + _mbg_cn_table_entry( PC_GPS_RECEIVER_INFO ), \ + _mbg_cn_table_entry( PC_GPS_ALL_STR_TYPE_INFO ), \ + _mbg_cn_table_entry( PC_GPS_ALL_PORT_INFO ), \ + _mbg_cn_table_entry( PC_GPS_PORT_SETTINGS_IDX ), \ + _mbg_cn_table_entry( PC_GPS_ALL_POUT_INFO ), \ + _mbg_cn_table_entry( PC_GPS_POUT_SETTINGS_IDX ), \ + _mbg_cn_table_entry( PC_GPS_TIME_SCALE ), \ + _mbg_cn_table_entry( PC_GPS_LAN_IF_INFO ), \ + _mbg_cn_table_entry( PC_GPS_IP4_STATE ), \ + _mbg_cn_table_entry( PC_GPS_IP4_SETTINGS ), \ + _mbg_cn_table_entry( PC_GPS_PTP_STATE ), \ + _mbg_cn_table_entry( PC_GPS_PTP_CFG ), \ + _mbg_cn_table_entry( PC_GPS_PTP_UC_MASTER_CFG_LIMITS ), \ + _mbg_cn_table_entry( PC_GPS_ALL_PTP_UC_MASTER_INFO ), \ + _mbg_cn_table_entry( PC_GPS_PTP_UC_MASTER_SETTINGS_IDX ), \ + _mbg_cn_table_entry( PC_GPS_GPIO_CFG_LIMITS ), \ + _mbg_cn_table_entry( PC_GPS_ALL_GPIO_INFO ), \ + _mbg_cn_table_entry( PC_GPS_GPIO_SETTINGS_IDX ), \ + _mbg_cn_table_entry( PC_GPS_GNSS_MODE ), \ + _mbg_cn_table_entry( PC_GPS_ALL_GNSS_SAT_INFO ), \ + _mbg_cn_table_entry( PC_GPS_XMR_INSTANCES ), \ + _mbg_cn_table_entry( PC_GPS_XMR_SETTINGS_IDX ), \ + _mbg_cn_table_entry( PC_GPS_ALL_XMR_INFO ), \ + _mbg_cn_table_entry( PC_GPS_ALL_XMR_STATUS ), \ + _mbg_cn_table_entry( PC_GPS_XMR_HOLDOVER_STATUS ), \ + _mbg_cn_table_entry( PC_GPS_ALL_GPIO_STATUS ), \ + _mbg_cn_table_entry( PC_GPS_XFEATURE_BUFFER ), \ + _mbg_cn_table_entry( PC_GPS_TLV_INFO ), \ + \ + _mbg_cn_table_entry( PC_GPS_CFGH ), \ + _mbg_cn_table_entry( PC_GPS_ALM ), \ + _mbg_cn_table_entry( PC_GPS_EPH ), \ + _mbg_cn_table_entry( PC_GPS_UTC ), \ + _mbg_cn_table_entry( PC_GPS_IONO ), \ + _mbg_cn_table_entry( PC_GPS_ASCII_MSG ), \ + _mbg_cn_table_end() \ } -/** codes used with PC_GPS_CMD */ -enum +/** + * @brief Codes used with ::PC_GPS_CMD + * + * @note These commands should only used with care, in very rare cases! + */ +enum PC_GPS_COMMANDS //##++++++++++++++ { - PC_GPS_CMD_BOOT = 1, /**< force the clock to boot mode */ - PC_GPS_CMD_INIT_SYS, /**< let the clock clear its system variables */ - PC_GPS_CMD_INIT_USER, /**< reset the clock's user parameters to defaults */ - PC_GPS_CMD_INIT_DAC, /**< initialize the oscillator disciplining values */ - N_PC_GPS_CMD /**< no command, just the number of known commands */ + PC_GPS_CMD_BOOT = 1, ///< force a GPS receiver to boot mode + PC_GPS_CMD_INIT_SYS, ///< let the clock clear its system variables + PC_GPS_CMD_INIT_USER, ///< reset the clock's user parameters to defaults + PC_GPS_CMD_INIT_DAC, ///< initialize the oscillator disciplining values + N_PC_GPS_CMD_CODES ///< no command, just the number of known commands }; -// The type below can be used to store an unambiguous command code. -// In case of the standard PCPS_... commands the lower byte contains -// the command code and the upper byte is 0. -// In case of a GPS command the lower byte contains PCPS_READ_GPS_DATA -// or PCPS_WRITE_GPS_DATA, as appropriate, and the upper byte contains -// the associated PC_GPS_... type code. +/** + * @brief A type used to store an unambiguous command code + * + * In case of the standard @ref PCPS_CMD_CODES the lower byte contains + * the command code and the upper byte is 0. + * In case of a GPS command the lower byte contains ::PCPS_READ_GPS_DATA + * or ::PCPS_WRITE_GPS_DATA, as appropriate, and the upper byte contains + * the associated type code from ::PC_GPS_CMD_CODES. + * + * Used internally by the firmware only. + */ typedef uint16_t PCPS_CMD_INFO; diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsdev.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdev.h index 7598a6f..313ccca 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pcpsdev.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdev.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pcpsdev.h 1.49.1.52 2011/07/19 10:41:48 martin TRASH $ + * $Id: pcpsdev.h 1.56.1.1 2017/07/26 14:28:29 martin TEST $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -17,93 +17,77 @@ * * ----------------------------------------------------------------------- * $Log: pcpsdev.h $ - * Revision 1.49.1.52 2011/07/19 10:41:48 martin - * Revision 1.49.1.51 2011/07/14 13:29:14 martin - * Revision 1.49.1.50 2011/07/13 09:44:53 martin + * Revision 1.56.1.1 2017/07/26 14:28:29 martin + * Removed includes that are obsolete for NetBSD. + * Revision 1.56 2017/07/04 16:31:08 martin + * New types PCPS_CLOCK_NAME and MBG_DEV_NAME. + * Definitions used with new feature check implementation. + * Changed some macros and definitions to clean up + * I/O port usage and storage. + * Moved some definitions used with IOCTLs to mbgioctl.h. + * Revision 1.55 2017/04/25 11:36:40 martin + * Renamed GRC181PEX to GNS181PEX. + * Revision 1.54 2017/01/27 09:10:57 martin + * Support GPS180AMC. + * Support GRC181PEX. + * Support GPIO ports. + * IRIG TX support for GPS180PEX and TCR180PEX only + * if GPS_HAS_IRIG_TX flag is set. + * New type PCPS_FW_REV_NUM. + * Moved some code to new module mbgsystm.h. + * Moved NANO_TIME_64 to gpsdefs.h. + * Moved inline function num_bits_set() to cfg_hlp.h. + * Added macro _ri_addr(). + * Added macro _pcps_has_ri_xmr(). + * Fixed macro syntax. + * Doxygen stuff. + * Removed trailing spaces. + * Cleanup. + * Revision 1.53 2013/11/08 08:46:00 martin + * Doxygen comment updates. + * Revision 1.52 2013/09/26 09:06:47Z martin + * Support GLN180PEX and GNSS API. + * Added inline fnc num_bits_set(). + * Revision 1.51 2013/01/25 15:44:21 martin + * Added inline function setup_hr_time_cycles_from_timestamp_cycles() which sets + * up a PCPS_HR_TIME_CYCLES structure from PCPS_TIME_STAMP_CYCLES. + * Revision 1.50 2012/10/02 19:00:46 martin + * Support GPS180PEX, TCR180PEX, and PZF180PEX. + * Support DCF600USB, TCR600USB, MSF600USB, and WVB600USB. + * Runtime support for precise time API introduced with Windows 8. + * This does not yet for x64 builds. + * There are some g++ versions which fail to compile source code using + * the macros provided by Linux to define IOCTL codes. If only the API + * functions are called by an application then the IOCTL codes aren't + * required anyway, so we just avoid inclusion of mbgioctl.h. + * However, some IOCTL related definitions are required anyway, so + * they have been moved to this file which is always included. + * Bug fix: Use negative sign for delay in KeDelayExecutionThread() + * Support on-board event logs. + * Moved macro _must_do_fw_workaround_20ms() here. + * New macro _pcps_has_debug_status(). + * Added some macros to test if specific stat_info stuff is supported. + * Moved some definitions useful for configuration tools to new file cfg_hlp.h. * Moved IA64 includes from pcpsdev.h to mbgpccyc.h. - * Revision 1.49.1.49 2011/07/06 13:23:24 martin - * Revision 1.49.1.48 2011/07/06 11:22:50 martin * Added macros _pcps_has_corr_info() and _pcps_has_tr_distance(). - * Revision 1.49.1.47 2011/07/05 12:25:19 martin - * Revision 1.49.1.46 2011/07/04 10:29:44 martin - * Modified a comment. - * Revision 1.49.1.45 2011/06/29 14:06:08 martin - * Added support for TCR600USB, MSF600USB, and WVB600USB. * Extended bus flag for USB v2 and macro _pcps_is_usb_v2(). * New feature ..._HAS_PZF and macro _pcps_has_pzf(). - * Revision 1.49.1.44 2011/06/29 09:10:26 martin - * Renamed PZF600PEX to PZF180PEX. - * Revision 1.49.1.43 2011/06/24 10:26:52 martin - * Fixed warning under DOS. - * Revision 1.49.1.42 2011/06/24 08:07:03Z martin * Moved PC cycles stuff to an new extra header. - * Revision 1.49.1.41 2011/06/21 15:17:36 martin - * Fixed build under DOS. - * Revision 1.49.1.40 2011/06/21 14:23:59Z martin * Cleaned up handling of pragma pack(). * Introduced generic MBG_SYS_TIME with nanosecond resolution. * Support struct timespec under Linux, if available. - * Revision 1.49.1.39 2011/06/01 09:29:09 martin - * Revision 1.49.1.38 2011/05/31 14:20:54 martin - * Revision 1.49.1.37 2011/05/16 13:18:38 martin * Use MBG_TGT_KERNEL instead of _KDD_. - * Revision 1.49.1.36 2011/05/06 13:47:38Z martin - * Support PZF600PEX. - * Revision 1.49.1.35 2011/04/19 15:06:24 martin * Added PTP unicast master configuration stuff. - * Revision 1.49.1.34 2011/03/29 14:08:45 martin * For compatibility use cpu_counter() instead of cpu_counter_serializing() under NetBSD. - * Revision 1.49.1.33 2011/03/28 09:50:18 martin - * Modifications for NetBSD from Frank Kardel. - * Revision 1.49.1.32 2011/03/25 11:09:43 martin * Optionally support timespec for sys time (USE_TIMESPEC). - * Started to support NetBSD. - * Revision 1.49.1.31 2011/02/16 10:10:49 martin - * Fixed macro syntax for _pcps_time_set_unread(). - * Revision 1.49.1.30 2011/02/15 14:24:56Z martin - * Revision 1.49.1.29 2011/02/10 13:34:21 martin - * Revision 1.49.1.28 2011/02/10 13:21:59 martin - * Revision 1.49.1.27 2011/02/10 12:26:17 martin - * Revision 1.49.1.26 2011/02/09 15:46:49 martin - * Revision 1.49.1.25 2011/02/04 14:44:44 martin - * Revision 1.49.1.24 2011/02/04 10:10:00 martin - * Revision 1.49.1.23 2011/02/02 12:34:10 martin - * Revision 1.49.1.22 2011/02/01 17:12:04 martin - * Revision 1.49.1.21 2011/01/28 13:11:11 martin - * Preliminary implementation of mbg_get_sys_time for FreeBSD traps. - * Revision 1.49.1.20 2011/01/28 10:34:37 martin + * Support FreeBSD and NetBSD. * Moved MBG_TGT_SUPP_MEM_ACC definition here. - * Revision 1.49.1.19 2011/01/26 16:39:05 martin - * Preliminarily support FreeBSD build. - * Revision 1.49.1.18 2011/01/24 17:09:51 martin - * Preliminarily fixed build under FreeBSD. - * Revision 1.49.1.17 2010/12/14 13:19:58 martin - * Fixed doxgen comments. - * Revision 1.49.1.16 2010/12/14 12:20:10 martin - * Revision 1.49.1.15 2010/11/25 14:54:22 martin * Moved status port register definitions to pcpsdefs.h. - * Revision 1.49.1.14 2010/11/11 09:15:38 martin - * Added definitions to support DCF600USB. - * Revision 1.49.1.13 2010/09/27 13:09:06 martin * Features are now defined using enum and bit masks. * Added initializer for feature names (used for debug). - * Revision 1.49.1.12 2010/08/25 12:44:42 martin - * Revision 1.49.1.11 2010/08/20 09:34:41Z martin * Added macro _pcps_features(). - * Revision 1.49.1.10 2010/08/17 15:34:23 martin - * Revision 1.49.1.9 2010/08/16 15:41:32 martin - * Revision 1.49.1.8 2010/08/13 12:14:46 daniel - * Revision 1.49.1.7 2010/08/13 11:57:54Z martin - * Revision 1.49.1.6 2010/08/13 11:39:28Z martin - * Revision 1.49.1.5 2010/08/13 11:19:41 martin * Implemented portable mbg_get_sys_uptime() and mbg_sleep_sec() * functions and associated types. - * Revision 1.49.1.4 2010/08/11 14:32:14 martin - * Revision 1.49.1.3 2010/08/11 13:47:42 martin - * Cleanup. - * Revision 1.49.1.2 2010/07/14 14:50:42 martin - * Revision 1.49.1.1 2010/06/30 13:17:18 martin - * Support GPS180PEX and TCR180PEX. * Revision 1.49 2010/06/30 13:03:48 martin * Use new preprocessor symbol MBG_ARCH_X86. * Use ulong port addresses for all platforms but x86. @@ -135,7 +119,7 @@ * Moved some inline functions dealing with MBG_PC_CYCLES * from mbgdevio.h here. * Merged the code from _pcps_get_cycles() and _pcps_get_cycles_frequency() - * to the mbg_get_pc_cycles...() inline functions which now replace the + * to the mbg_get_pc_cycles...() inline functions which now replace the * _pcps_get_cycles...() macros. * Fixed cycles code for non-x86 architectures. * Revision 1.39 2008/12/05 16:24:24Z martin @@ -146,7 +130,7 @@ * Defined firmware version numbers which fix an IRQ problem with PEX511, * TCR511PEX, and GPS170PEX cards. The fix also requires specific ASIC * versions specified in pci_asic.h. - * Defined firmware versions at which PCI511 and PEX511 start + * Defined firmware versions at which PCI511 and PEX511 start * to support HR time. * Support mapped I/O resources. * Changed MBG_PC_CYCLES type for Windows to int64_t. @@ -166,11 +150,11 @@ * _psps_has_asic_version(), _pcps_has_asic_features(). * Revision 1.37 2008/01/17 09:58:11Z daniel * Made comments compatible for doxygen parser. - * No sourcecode changes. + * No sourcecode changes. * Revision 1.36 2007/09/26 09:34:38Z martin * Added support for USB in general and new USB device USB5131. * Added new types PCPS_DEV_ID and PCPS_REF_TYPE. - * Removed old PCPS_ERR_... codes. Use MBG_ERR_... codes + * Removed old PCPS_ERR_... codes. Use MBG_ERR_... codes * from mbgerror.h instead. The old values haven't changed. * Revision 1.35 2007/07/17 08:22:47Z martin * Added support for TCR511PEX and GPS170PEX. @@ -183,15 +167,15 @@ * Preliminary support for *BSD. * Preliminary support for USB. * Revision 1.32 2006/10/23 08:47:55Z martin - * Don't use abs() in _pcps_ref_offs_out_of_range() since this might + * Don't use abs() in _pcps_ref_offs_out_of_range() since this might * not work properly for 16 bit integers and value 0x8000. * Revision 1.31 2006/06/14 12:59:13Z martin * Added support for TCR511PCI. * Revision 1.30 2006/04/05 14:58:41 martin * Support higher baud rates for PCI511. * Revision 1.29 2006/04/03 07:29:07Z martin - * Added a note about the missing PCPS_ST_IRQF signal - * on PCI510 cards. + * Added a note about the missing PCPS_ST_IRQF signal + * on PCI510 cards. * Revision 1.28 2006/03/10 10:32:56Z martin * Added support for PCI511. * Added support for programmable pulse outputs. @@ -212,8 +196,8 @@ * New type PCPS_STATUS_PORT. * Removed obsolete inclusion of asm/timex.h for Linux. * Revision 1.21 2004/09/06 15:19:49Z martin - * Support a GPS_DATA interface where sizes are specified - * by 16 instead of the original 8 bit quantities, thus allowing + * Support a GPS_DATA interface where sizes are specified + * by 16 instead of the original 8 bit quantities, thus allowing * to transfer data blocks which exceed 255 bytes. * Modified inclusion of header files under Linux. * Modified definition of MBG_PC_CYCLES for Linux. @@ -292,22 +276,21 @@ #include <mbg_tgt.h> #include <mbgtime.h> +#include <mbgsystm.h> #include <mbgpccyc.h> #include <pcpsdefs.h> #include <gpsdefs.h> #include <usbdefs.h> #include <use_pack.h> +#if !defined( MBG_TGT_KERNEL ) + #include <string.h> +#endif + #if defined( MBG_TGT_LINUX ) - #if defined( MBG_TGT_KERNEL ) - #include <linux/delay.h> - #include <linux/time.h> - #else + #if !defined( MBG_TGT_KERNEL ) #include <unistd.h> - #include <time.h> - #include <sys/time.h> - #include <sys/sysinfo.h> #endif #elif defined( MBG_TGT_FREEBSD ) @@ -315,16 +298,25 @@ #if defined( MBG_TGT_KERNEL ) #include <sys/sysproto.h> #include <sys/pcpu.h> + #include <sys/param.h> + #include <sys/systm.h> + #include <sys/proc.h> #else + #include <unistd.h> #include <sys/time.h> #endif #elif defined( MBG_TGT_NETBSD ) #if !defined( MBG_TGT_KERNEL ) + #include <unistd.h> #include <sys/time.h> #endif +#elif defined( MBG_TGT_QNX_NTO ) + + #include <unistd.h> + #elif defined( MBG_TGT_DOS ) #include <dos.h> // for delay() @@ -342,55 +334,14 @@ #endif -#if defined( MBG_TGT_UNIX ) - #define USE_GENERIC_SYS_TIME 1 -#else - #define USE_GENERIC_SYS_TIME 0 -#endif - - -#if USE_GENERIC_SYS_TIME - - typedef struct - { - uint64_t sec; - uint64_t nsec; - } NANO_TIME_64; - - typedef NANO_TIME_64 MBG_SYS_TIME; - -#endif - - - -/** - Define generic types to hold PC cycle counter values and system timestamps. - The generic types are defined using native types used by the target operating - systems. - - The cycle counter value is usually derived from the PC CPU's TSC or some other - timer hardware on the mainboard. - */ -#if defined( MBG_TGT_WIN32 ) - - #define MBG_TGT_SUPP_MEM_ACC 1 - - typedef int64_t MBG_SYS_UPTIME; // [s] - - typedef LARGE_INTEGER MBG_SYS_TIME; - -#elif defined( MBG_TGT_LINUX ) +#if defined( MBG_TGT_LINUX ) #define MBG_TGT_SUPP_MEM_ACC 1 - typedef int64_t MBG_SYS_UPTIME; // [s] - #elif defined( MBG_TGT_BSD ) #define MBG_TGT_SUPP_MEM_ACC 1 - typedef int64_t MBG_SYS_UPTIME; // [s] - #if defined( MBG_TGT_NETBSD ) #ifdef __LP64__ #define MBG_MEM_ADDR uint64_t @@ -399,26 +350,14 @@ #endif #endif -#elif defined( MBG_TGT_OS2 ) +#elif defined( MBG_TGT_WIN32 ) - typedef long MBG_SYS_UPTIME; //## dummy - - typedef uint32_t MBG_SYS_TIME; //## dummy + #define MBG_TGT_SUPP_MEM_ACC 1 #elif defined( MBG_TGT_DOS ) #define MBG_MEM_ADDR uint32_t // 64 bit not supported, nor required. - typedef long MBG_SYS_UPTIME; //## dummy - - typedef uint32_t MBG_SYS_TIME; //## dummy - -#else // other target OSs which access the hardware directly - - typedef long MBG_SYS_UPTIME; //## dummy - - typedef uint32_t MBG_SYS_TIME; //## dummy - #endif @@ -427,283 +366,62 @@ #endif -// MBG_SYS_TIME is always read in native machine endianess, -// so no endianess conversion is required. -#define _mbg_swab_mbg_sys_time( _p ) \ - _nop_macro_fnc() +#if !defined( MBG_MEM_ADDR ) + // By default a memory address is stored + // as a 64 bit quantitiy. + #define MBG_MEM_ADDR uint64_t +#endif + + + +typedef uint8_t MBG_DBG_DATA; +typedef uint16_t MBG_DBG_PORT; /** - The structure holds a system timestamp in a format depending on the target OS - plus two cycles counter values which can be taken before and after reading - the system time. These cycles values can be used to determine the execution - time required to read the system time. - - Limitations of the operating system need to be taken into account, - e.g. the Windows system time may increase once every ~16 ms only. - */ + * @brief System time plus associated cycles counter values + * + * The structure holds a system timestamp in a format depending on the target OS + * plus two cycles counter values which can be taken before and after reading + * the system time. These cycles values can be used to determine the execution + * time required to read the system time. + * + * Limitations of the operating system need to be taken into account, + * e.g. the Windows system time may increase once every ~16 ms or ~1 ms only, + * depending on the Windows version. + */ typedef struct { - MBG_PC_CYCLES cyc_before; /**< cycles count before sys time is read */ - MBG_PC_CYCLES cyc_after; /**< cycles count after sys time has been read */ - MBG_SYS_TIME sys_time; /**< system time stamp */ + MBG_PC_CYCLES cyc_before; ///< cycles count before sys time is read + MBG_PC_CYCLES cyc_after; ///< cycles count after sys time has been read + MBG_SYS_TIME sys_time; ///< system time stamp + } MBG_SYS_TIME_CYCLES; #define _mbg_swab_mbg_sys_time_cycles( _p ) \ +do \ { \ _mbg_swab_mbg_pc_cycles( &(_p)->cyc_before ); \ _mbg_swab_mbg_pc_cycles( &(_p)->cyc_after ); \ _mbg_swab_mbg_sys_time( &(_p)->sys_time ); \ -} - - - - -static __mbg_inline -void mbg_get_sys_time( MBG_SYS_TIME *p ) -{ - #if defined( MBG_TGT_WIN32 ) - - #if defined( MBG_TGT_KERNEL ) // kernel space - KeQuerySystemTime( p ); - #else // user space - { - FILETIME ft; - GetSystemTimeAsFileTime( &ft ); - p->LowPart = ft.dwLowDateTime; - p->HighPart = ft.dwHighDateTime; - } - #endif - - #elif defined( MBG_TGT_LINUX ) - - #if defined( MBG_TGT_KERNEL ) - - #if ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 22 ) ) //##+++++++++++++ - { - // getnstimeofday() supported - struct timespec ts; - - getnstimeofday( &ts ); - - p->sec = ts.tv_sec; - p->nsec = ts.tv_nsec; - } - #else - { - // getnstimeofday() *not* supported - struct timeval tv; - - do_gettimeofday( &tv ); - - p->sec = tv.tv_sec; - p->nsec = tv.tv_usec * 1000; - } - #endif - - #else // Linux user space - { - struct timespec ts; - - clock_gettime( CLOCK_REALTIME, &ts ); - - p->sec = ts.tv_sec; - p->nsec = ts.tv_nsec; - } - #endif - - #elif defined( MBG_TGT_BSD ) +} while ( 0 ) - struct timespec ts; - #if defined( MBG_TGT_KERNEL ) - nanotime( &ts ); - #else - #if defined( MBG_TGT_FREEBSD ) - clock_gettime( CLOCK_REALTIME_PRECISE, &ts ); - #else // MBG_TGT_NETBSD, ... - clock_gettime( CLOCK_REALTIME, &ts ); - #endif - #endif - - p->sec = ts.tv_sec; - p->nsec = ts.tv_nsec; - - #else - - *p = 0; - - #endif - -} // mbg_get_sys_time - - - -static __mbg_inline -void mbg_get_sys_uptime( MBG_SYS_UPTIME *p ) -{ - #if defined( MBG_TGT_WIN32 ) - - #if defined( MBG_TGT_KERNEL ) // kernel space - - ULONGLONG time_increment = KeQueryTimeIncrement(); - LARGE_INTEGER tick_count; - - KeQueryTickCount( &tick_count ); - - // multiplication by time_increment yields HNS units, - // but we need seconds - *p = ( tick_count.QuadPart * time_increment ) / HNS_PER_SEC; - - #else // user space - - DWORD tickCount; - DWORD timeAdjustment; - DWORD timeIncrement; - BOOL timeAdjustmentDisabled; - - if ( !GetSystemTimeAdjustment( &timeAdjustment, &timeIncrement, &timeAdjustmentDisabled ) ) - *p = -1; // failed - - // ATTENTION: This is compatible with older Windows versions, but - // the returned tick count wraps around to zero after 49.7 days. - // A new GetTickCount64() call is available under Windows Vista and newer, - // but the function call had to be imported dynamically since otherwise - // programs refused to start under pre-Vista versions due to undefined DLL symbol. - tickCount = GetTickCount(); - - *p = ( ( (MBG_SYS_UPTIME) tickCount ) * timeIncrement ) / HNS_PER_SEC; - - #endif - - #elif defined( MBG_TGT_LINUX ) - - #if defined( MBG_TGT_KERNEL ) - { - // Using a simple 64 bit division may result in a linker error - // in kernel mode due to a missing symbol __udivdi3, so we use - // a specific inline function do_div(). - // Also, the jiffies counter is not set to 0 at startup but to - // a defined initialization value we need to account for. - uint64_t tmp = get_jiffies_64() - INITIAL_JIFFIES; - do_div( tmp, HZ ); - *p = tmp; - } - #else - { - struct sysinfo si; - int rc = sysinfo( &si ); - *p = ( rc == 0 ) ? si.uptime : -1; - } - #endif - - #elif defined( MBG_TGT_BSD ) - - #if defined( MBG_TGT_KERNEL ) - { - struct timespec ts; - - getnanouptime( &ts ); - - *p = ts.tv_sec; - } - #elif defined( MBG_TGT_FREEBSD ) - { - struct timespec ts; - // CLOCK_UPTIME_FAST is specific to FreeBSD - int rc = clock_gettime( CLOCK_UPTIME_FAST, &ts ); - *p = ( rc == 0 ) ? ts.tv_sec : -1; - } - #else // MBG_TGT_NETBSD, ... - - *p = -1; //##++ needs to be implemented - - #endif - - #else - - *p = -1; // not supported - - #endif - -} // mbg_get_sys_uptime - - - -static __mbg_inline -void mbg_sleep_sec( long sec ) -{ - #if defined( MBG_TGT_WIN32 ) - - #if defined( MBG_TGT_KERNEL ) // kernel space - LARGE_INTEGER delay; - - // we need to pass a negative value to KeDelayExecutionThread() - // since the given time is a relative time interval, not absolute - // time. See the API docs for KeDelayExecutionThread(). - delay.QuadPart = (LONGLONG) sec * HNS_PER_SEC; - - KeDelayExecutionThread( KernelMode, FALSE, &delay ); - #else // user space - // Sleep() expects milliseconds - Sleep( sec * 1000 ); - #endif - - #elif defined( MBG_TGT_LINUX ) - - #if defined( MBG_TGT_KERNEL ) - // msleep is not defined in older kernels, so we use this - // only if it is surely supported. - #if ( LINUX_VERSION_CODE >= KERNEL_VERSION( 2, 6, 16 ) ) //##+++++ - msleep( sec * 1000 ); - #else - { - DECLARE_WAIT_QUEUE_HEAD( tmp_wait ); - wait_event_interruptible_timeout( tmp_wait, 0, sec * HZ + 1 ); - } - #endif - #else - sleep( sec ); - #endif - - #elif defined( MBG_TGT_BSD ) - - //##+++++++++++++++++++ needs to be defined - - #elif defined( MBG_TGT_DOS ) - - delay( (unsigned) ( sec * 1000 ) ); - - #else - - // This needs to be implemented for the target OS - // and thus will probably yield a linker error. - do_sleep_sec( sec ); - - #endif - -} // mbg_sleep_sec - - - -#if !defined( MBG_MEM_ADDR ) - // By default a memory address is stored - // as a 64 bit quantitiy. - #define MBG_MEM_ADDR uint64_t -#endif - - -typedef uint8_t MBG_DBG_DATA; -typedef uint16_t MBG_DBG_PORT; +/** + * @defgroup group_bus_flag_masks BUS flag masks + * + * @anchor PCPS_BUS_FLAG_MASKS + * + * @{ */ // The following flags describe the bus types which are // supported by the plugin clocks. -#define PCPS_BUS_ISA 0x0001 // IBM compatible PC/AT ISA bus -#define PCPS_BUS_MCA 0x0002 // IBM PS/2 micro channel -#define PCPS_BUS_PCI 0x0004 // PCI -#define PCPS_BUS_USB 0x0008 // USB +#define PCPS_BUS_ISA 0x0001 ///< IBM compatible PC/AT ISA bus +#define PCPS_BUS_MCA 0x0002 ///< IBM PS/2 micro channel +#define PCPS_BUS_PCI 0x0004 ///< PCI +#define PCPS_BUS_USB 0x0008 ///< USB // The flags below are or'ed to the PC_BUS_PCI code @@ -711,10 +429,10 @@ typedef uint16_t MBG_DBG_PORT; // on a PCI card. If no flag is set then the S5933 chip is // installed which has been used for the first generation // of Meinberg PCI cards. -#define PCPS_BUS_PCI_CHIP_S5920 0x8000 // S5920 PCI interface chip. -#define PCPS_BUS_PCI_CHIP_ASIC 0x4000 // Meinberg's own PCI interface chip. -#define PCPS_BUS_PCI_CHIP_PEX8311 0x2000 // PEX8311 PCI Express interface chip -#define PCPS_BUS_PCI_CHIP_MBGPEX 0x1000 // Meinberg's own PCI Express interface chip +#define PCPS_BUS_PCI_CHIP_S5920 0x8000 ///< S5920 PCI interface chip. +#define PCPS_BUS_PCI_CHIP_ASIC 0x4000 ///< Meinberg's own PCI interface chip. +#define PCPS_BUS_PCI_CHIP_PEX8311 0x2000 ///< PEX8311 PCI Express interface chip +#define PCPS_BUS_PCI_CHIP_MBGPEX 0x1000 ///< Meinberg's own PCI Express interface chip // The constants below combine the PCI bus flags: #define PCPS_BUS_PCI_S5933 ( PCPS_BUS_PCI ) @@ -733,9 +451,13 @@ typedef uint16_t MBG_DBG_PORT; // The constant below combines the PCI bus flags: #define PCPS_BUS_USB_V2 ( PCPS_BUS_USB | PCPS_BUS_USB_FLAG_V2 ) +/** @} defgroup group_bus_flag_masks */ + -/** A list of known radio clocks. */ +/** + * @brief A list of known devices + */ enum PCPS_TYPES { PCPS_TYPE_PC31, @@ -771,52 +493,72 @@ enum PCPS_TYPES PCPS_TYPE_TCR600USB, PCPS_TYPE_MSF600USB, PCPS_TYPE_WVB600USB, + PCPS_TYPE_GLN180PEX, + PCPS_TYPE_GPS180AMC, + PCPS_TYPE_GNS181PEX, N_PCPS_DEV_TYPE }; #define PCPS_CLOCK_NAME_SZ 10 // including terminating 0 +typedef char PCPS_CLOCK_NAME[PCPS_CLOCK_NAME_SZ]; + typedef uint16_t PCPS_DEV_ID; typedef uint16_t PCPS_REF_TYPE; typedef uint16_t PCPS_BUS_FLAGS; /** - The structure contains the characteristics of each - of the clocks listed above. These fields are always the - same for a single type of clock and do not change with - firmware version, port address, etc. - */ + * @brief Device type specification + * + * Contains the characteristics of one of the ::PCPS_TYPES. + * These specifications are always the same for a particular + * type of device and do not change with firmware version, + * port address, etc. + */ typedef struct { - uint16_t num; - char name[PCPS_CLOCK_NAME_SZ]; - PCPS_DEV_ID dev_id; - PCPS_REF_TYPE ref_type; - PCPS_BUS_FLAGS bus_flags; -} PCPS_DEV_TYPE; + uint16_t num; ///< see ::PCPS_TYPES + PCPS_CLOCK_NAME name; + PCPS_DEV_ID dev_id; ///< see @ref MEINBERG_PCI_DEVICE_IDS and @ref MBG_USB_DEVICE_IDS + PCPS_REF_TYPE ref_type; ///< see ::PCPS_REF_TYPES + PCPS_BUS_FLAGS bus_flags; ///< see @ref PCPS_BUS_FLAG_MASKS +} PCPS_DEV_TYPE; -#if !defined( MBG_TGT_UNIX ) || defined( MBG_ARCH_X86 ) - typedef uint16_t PCPS_PORT_ADDR; -#else - typedef uint64_t PCPS_PORT_ADDR; -#endif +/** + * @brief Legacy I/O address type, see ::PCPS_SHORT_PORT_RSRC + */ +typedef uint16_t PCPS_SHORT_PORT_ADDR; /** - The structure below describes an I/O port resource - used by a clock. -*/ + * @brief An I/O port resource used by a device + * + * This structure has originally been used to store information + * on an I/O address range. + * However, the 16 bits provided by ::PCPS_SHORT_PORT_ADDR may + * not be sufficient to hold an address on some target platforms, + * so this is only kept to maintain API compatibility when + * reporting I/O addresses to user space via ::PCPS_DEV_CFG + * and thus ::PCPS_DEV structures. + * A different structure is actually being used internally + * by the kernel drivers. + */ typedef struct { - PCPS_PORT_ADDR base; + PCPS_SHORT_PORT_ADDR base; uint16_t num; -} PCPS_PORT_RSRC; -/** The max number of I/O port resources used by a clock. */ +} PCPS_SHORT_PORT_RSRC; + + + +/** + * @brief The max. number of I/O port resources used by a clock + */ #define N_PCPS_PORT_RSRC 2 @@ -830,61 +572,83 @@ typedef struct #else ulong len; #endif + } PCPS_MAPPED_MEM; -typedef uint32_t PCPS_ERR_FLAGS; /**< see \ref group_err_flags "Error flags" */ -typedef uint32_t PCPS_FEATURES; /**< see \ref group_features "Features" */ +typedef uint32_t PCPS_ERR_FLAGS; ///< see @ref PCPS_ERR_FLAG_MASKS +typedef uint32_t PCPS_FEATURES; ///< see @ref PCPS_FEATURE_MASKS typedef uint16_t PCPS_BUS_NUM; typedef uint16_t PCPS_SLOT_NUM; +typedef uint16_t PCPS_FW_REV_NUM; ///< firmware revision number, MSB major, LSB minor version /** - The structure below contains data which depends - on a individual instance of the clock, e.g. - the firmware which is currently installed, the - port address which has been configured, etc. -*/ + * @brief Device information + * + * Contains variable data which depends on a particular instance + * of a device, e.g. the firmware which is currently installed, + * the port address which has actually been assigned, etc. + */ typedef struct { - PCPS_ERR_FLAGS err_flags; /**< See \ref group_err_flags "Error flags" */ + PCPS_ERR_FLAGS err_flags; ///< See @ref PCPS_ERR_FLAG_MASKS PCPS_BUS_NUM bus_num; PCPS_SLOT_NUM slot_num; - PCPS_PORT_RSRC port[N_PCPS_PORT_RSRC]; - uint16_t status_port; + PCPS_SHORT_PORT_RSRC port[N_PCPS_PORT_RSRC]; + PCPS_SHORT_PORT_ADDR short_status_port; int16_t irq_num; uint32_t timeout_clk; - uint16_t fw_rev_num; - PCPS_FEATURES features; /**< See \ref group_features "Feature flags" */ + PCPS_FW_REV_NUM fw_rev_num; + PCPS_FEATURES features; ///< See @ref PCPS_FEATURE_MASKS PCPS_ID_STR fw_id; PCPS_SN_STR sernum; + } PCPS_DEV_CFG; -/** @defgroup group_err_flags Error flags in PCPS_DEV_CFG - Flags used with PCPS_DEV_CFG::err_flags - @{ -*/ -#define PCPS_EF_TIMEOUT 0x00000001 /**< timeout occured */ -#define PCPS_EF_INV_EPROM_ID 0x00000002 /**< invalid EPROM ID */ -#define PCPS_EF_IO_INIT 0x00000004 /**< I/O intf not init'd */ -#define PCPS_EF_IO_CFG 0x00000008 /**< I/O intf not cfg'd */ -#define PCPS_EF_IO_ENB 0x00000010 /**< I/O intf not enabled */ -#define PCPS_EF_IO_RSRC 0x00000020 /**< I/O not registered w/ rsrcmgr */ -/** @} */ - -/** @defgroup group_features Feature flags used with PCPS_FEATURES - - Some features of the radio clocks have been introduced with - specific firmware versions, so depending on the firmware version - a clock may support a feature or not. The clock detection function - checks the clock model and firmware version and updates the field - PCPS_DEV_CFG::features accordingly. There are some macros which - can easily be used to query whether a clock device actually - supports a function, or not. The definitions define - the possible features. - @{ -*/ -enum + + +/** + * @brief Possible device initialization error flags + * + * Used with ::PCPS_DEV_CFG::err_flags + * + * @see ::PCPS_ERR_FLAGS + * + * @anchor PCPS_ERR_FLAG_MASKS @{ */ + +#define PCPS_EF_TIMEOUT 0x00000001 ///< timeout occured +#define PCPS_EF_INV_FW_ID 0x00000002 ///< invalid firmware ID +#define PCPS_EF_IO_INIT 0x00000004 ///< I/O interface not initialized +#define PCPS_EF_IO_CFG 0x00000008 ///< I/O interface not configured +#define PCPS_EF_IO_ENB 0x00000010 ///< I/O interface not enabled +#define PCPS_EF_IO_RSRC 0x00000020 ///< I/O resource not registered with resource manager + +/** @} anchor PCPS_ERR_FLAG_MASKS */ + + + +/** + * @defgroup group_pcps_features Feature flags used with PCPS_FEATURES + * + * Some features of the radio clocks have been introduced with + * specific firmware versions, so depending on the firmware version + * a clock may support a feature or not. The clock detection function + * checks the clock model and firmware version and updates the field + * ::PCPS_DEV_CFG::features accordingly. There are some macros which + * can easily be used to query whether a clock device actually + * supports a function, or not. + * + * @see ::PCPS_FEATURES + * + * @{ */ + +/** + * @brief Feature bits for bus-level devices + * + * @see @ref PCPS_FEATURE_MASKS + */ +enum PCPS_FEATURE_BITS { PCPS_BIT_CAN_SET_TIME, PCPS_BIT_HAS_SERIAL, @@ -917,40 +681,59 @@ enum PCPS_BIT_HAS_FAST_HR_TSTAMP, PCPS_BIT_HAS_RAW_IRIG_DATA, PCPS_BIT_HAS_PZF, // can also demodulate DCF77 PZF + PCPS_BIT_HAS_EVT_LOG, + PCPS_BIT_IS_GNSS, // supports several satellite systems and GNSS API calls - N_PCPS_FEATURE // must not exceed 32 !! + N_PCPS_FEATURE_BITS // must not exceed 32 !! }; -#define PCPS_CAN_SET_TIME ( 1UL << PCPS_BIT_CAN_SET_TIME ) -#define PCPS_HAS_SERIAL ( 1UL << PCPS_BIT_HAS_SERIAL ) -#define PCPS_HAS_SYNC_TIME ( 1UL << PCPS_BIT_HAS_SYNC_TIME ) -#define PCPS_HAS_TZDL ( 1UL << PCPS_BIT_HAS_TZDL ) -#define PCPS_HAS_IDENT ( 1UL << PCPS_BIT_HAS_IDENT ) -#define PCPS_HAS_UTC_OFFS ( 1UL << PCPS_BIT_HAS_UTC_OFFS ) -#define PCPS_HAS_HR_TIME ( 1UL << PCPS_BIT_HAS_HR_TIME ) -#define PCPS_HAS_SERNUM ( 1UL << PCPS_BIT_HAS_SERNUM ) -#define PCPS_HAS_TZCODE ( 1UL << PCPS_BIT_HAS_TZCODE ) -#define PCPS_HAS_CABLE_LEN ( 1UL << PCPS_BIT_HAS_CABLE_LEN ) -#define PCPS_HAS_EVENT_TIME ( 1UL << PCPS_BIT_HAS_EVENT_TIME ) -#define PCPS_HAS_RECEIVER_INFO ( 1UL << PCPS_BIT_HAS_RECEIVER_INFO ) -#define PCPS_CAN_CLR_UCAP_BUFF ( 1UL << PCPS_BIT_CAN_CLR_UCAP_BUFF ) -#define PCPS_HAS_PCPS_TZDL ( 1UL << PCPS_BIT_HAS_PCPS_TZDL ) -#define PCPS_HAS_UCAP ( 1UL << PCPS_BIT_HAS_UCAP ) -#define PCPS_HAS_IRIG_TX ( 1UL << PCPS_BIT_HAS_IRIG_TX ) -#define PCPS_HAS_GPS_DATA_16 ( 1UL << PCPS_BIT_HAS_GPS_DATA_16 ) -#define PCPS_HAS_SYNTH ( 1UL << PCPS_BIT_HAS_SYNTH ) -#define PCPS_HAS_GENERIC_IO ( 1UL << PCPS_BIT_HAS_GENERIC_IO ) -#define PCPS_HAS_TIME_SCALE ( 1UL << PCPS_BIT_HAS_TIME_SCALE ) -#define PCPS_HAS_UTC_PARM ( 1UL << PCPS_BIT_HAS_UTC_PARM ) -#define PCPS_HAS_IRIG_CTRL_BITS ( 1UL << PCPS_BIT_HAS_IRIG_CTRL_BITS ) -#define PCPS_HAS_LAN_INTF ( 1UL << PCPS_BIT_HAS_LAN_INTF ) -#define PCPS_HAS_PTP ( 1UL << PCPS_BIT_HAS_PTP ) -#define PCPS_HAS_IRIG_TIME ( 1UL << PCPS_BIT_HAS_IRIG_TIME ) -#define PCPS_HAS_FAST_HR_TSTAMP ( 1UL << PCPS_BIT_HAS_FAST_HR_TSTAMP ) -#define PCPS_HAS_RAW_IRIG_DATA ( 1UL << PCPS_BIT_HAS_RAW_IRIG_DATA ) -#define PCPS_HAS_PZF ( 1UL << PCPS_BIT_HAS_PZF ) +/** + * @brief Feature bit masks for bus-level devices + * + * Used with ::PCPS_DEV_CFG::features + * + * @see ::PCPS_FEATURE_BITS + * @see ::PCPS_FEATURES + * + * @anchor PCPS_FEATURE_MASKS @{ */ + +#define PCPS_CAN_SET_TIME ( 1UL << PCPS_BIT_CAN_SET_TIME ) ///< see ::PCPS_BIT_CAN_SET_TIME +#define PCPS_HAS_SERIAL ( 1UL << PCPS_BIT_HAS_SERIAL ) ///< see ::PCPS_BIT_HAS_SERIAL +#define PCPS_HAS_SYNC_TIME ( 1UL << PCPS_BIT_HAS_SYNC_TIME ) ///< see ::PCPS_BIT_HAS_SYNC_TIME +#define PCPS_HAS_TZDL ( 1UL << PCPS_BIT_HAS_TZDL ) ///< see ::PCPS_BIT_HAS_TZDL +#define PCPS_HAS_IDENT ( 1UL << PCPS_BIT_HAS_IDENT ) ///< see ::PCPS_BIT_HAS_IDENT +#define PCPS_HAS_UTC_OFFS ( 1UL << PCPS_BIT_HAS_UTC_OFFS ) ///< see ::PCPS_BIT_HAS_UTC_OFFS +#define PCPS_HAS_HR_TIME ( 1UL << PCPS_BIT_HAS_HR_TIME ) ///< see ::PCPS_BIT_HAS_HR_TIME +#define PCPS_HAS_SERNUM ( 1UL << PCPS_BIT_HAS_SERNUM ) ///< see ::PCPS_BIT_HAS_SERNUM + +#define PCPS_HAS_TZCODE ( 1UL << PCPS_BIT_HAS_TZCODE ) ///< see ::PCPS_BIT_HAS_TZCODE +#define PCPS_HAS_CABLE_LEN ( 1UL << PCPS_BIT_HAS_CABLE_LEN ) ///< see ::PCPS_BIT_HAS_CABLE_LEN +#define PCPS_HAS_EVENT_TIME ( 1UL << PCPS_BIT_HAS_EVENT_TIME ) ///< see ::PCPS_BIT_HAS_EVENT_TIME +#define PCPS_HAS_RECEIVER_INFO ( 1UL << PCPS_BIT_HAS_RECEIVER_INFO ) ///< see ::PCPS_BIT_HAS_RECEIVER_INFO +#define PCPS_CAN_CLR_UCAP_BUFF ( 1UL << PCPS_BIT_CAN_CLR_UCAP_BUFF ) ///< see ::PCPS_BIT_CAN_CLR_UCAP_BUFF +#define PCPS_HAS_PCPS_TZDL ( 1UL << PCPS_BIT_HAS_PCPS_TZDL ) ///< see ::PCPS_BIT_HAS_PCPS_TZDL +#define PCPS_HAS_UCAP ( 1UL << PCPS_BIT_HAS_UCAP ) ///< see ::PCPS_BIT_HAS_UCAP +#define PCPS_HAS_IRIG_TX ( 1UL << PCPS_BIT_HAS_IRIG_TX ) ///< see ::PCPS_BIT_HAS_IRIG_TX + +#define PCPS_HAS_GPS_DATA_16 ( 1UL << PCPS_BIT_HAS_GPS_DATA_16 ) ///< see ::PCPS_BIT_HAS_GPS_DATA_16 +#define PCPS_HAS_SYNTH ( 1UL << PCPS_BIT_HAS_SYNTH ) ///< see ::PCPS_BIT_HAS_SYNTH +#define PCPS_HAS_GENERIC_IO ( 1UL << PCPS_BIT_HAS_GENERIC_IO ) ///< see ::PCPS_BIT_HAS_GENERIC_IO +#define PCPS_HAS_TIME_SCALE ( 1UL << PCPS_BIT_HAS_TIME_SCALE ) ///< see ::PCPS_BIT_HAS_TIME_SCALE +#define PCPS_HAS_UTC_PARM ( 1UL << PCPS_BIT_HAS_UTC_PARM ) ///< see ::PCPS_BIT_HAS_UTC_PARM +#define PCPS_HAS_IRIG_CTRL_BITS ( 1UL << PCPS_BIT_HAS_IRIG_CTRL_BITS ) ///< see ::PCPS_BIT_HAS_IRIG_CTRL_BITS +#define PCPS_HAS_LAN_INTF ( 1UL << PCPS_BIT_HAS_LAN_INTF ) ///< see ::PCPS_BIT_HAS_LAN_INTF +#define PCPS_HAS_PTP ( 1UL << PCPS_BIT_HAS_PTP ) ///< see ::PCPS_BIT_HAS_PTP + +#define PCPS_HAS_IRIG_TIME ( 1UL << PCPS_BIT_HAS_IRIG_TIME ) ///< see ::PCPS_BIT_HAS_IRIG_TIME +#define PCPS_HAS_FAST_HR_TSTAMP ( 1UL << PCPS_BIT_HAS_FAST_HR_TSTAMP ) ///< see ::PCPS_BIT_HAS_FAST_HR_TSTAMP +#define PCPS_HAS_RAW_IRIG_DATA ( 1UL << PCPS_BIT_HAS_RAW_IRIG_DATA ) ///< see ::PCPS_BIT_HAS_RAW_IRIG_DATA +#define PCPS_HAS_PZF ( 1UL << PCPS_BIT_HAS_PZF ) ///< see ::PCPS_BIT_HAS_PZF +#define PCPS_HAS_EVT_LOG ( 1UL << PCPS_BIT_HAS_EVT_LOG ) ///< see ::PCPS_BIT_HAS_EVT_LOG +#define PCPS_IS_GNSS ( 1UL << PCPS_BIT_IS_GNSS ) ///< see ::PCPS_BIT_IS_GNSS + +/** @} anchor PCPS_FEATURE_MASKS */ #define PCPS_FEATURE_NAMES \ @@ -981,11 +764,13 @@ enum "PCPS_HAS_PTP", \ "PCPS_HAS_IRIG_TIME", \ "PCPS_HAS_FAST_HR_TSTAMP", \ - "PCPS_HAS_RAW_IRIG_DATA" \ - "PCPS_HAS_PZF" \ + "PCPS_HAS_RAW_IRIG_DATA", \ + "PCPS_HAS_PZF", \ + "PCPS_HAS_EVT_LOG", \ + "PCPS_IS_GNSS" \ } -/** @} */ +/** @} defgroup group_pcps_features */ @@ -1102,13 +887,25 @@ enum #define PCPS_FEAT_WWVB51USB ( PCPS_FEAT_MSF51USB ) -#define PCPS_FEAT_GPS180PEX ( PCPS_FEAT_GPS170PEX | PCPS_HAS_FAST_HR_TSTAMP ) +#define PCPS_FEAT_GPS180PEX ( ( PCPS_FEAT_GPS170PEX | PCPS_HAS_FAST_HR_TSTAMP ) \ + & ~PCPS_HAS_IRIG_TX ) ///< IRIG TX only supp. if ::GPS_HAS_IRIG_TX -#define PCPS_FEAT_TCR180PEX ( PCPS_FEAT_TCR170PEX | PCPS_HAS_FAST_HR_TSTAMP ) +#define PCPS_FEAT_TCR180PEX ( ( PCPS_FEAT_TCR170PEX | PCPS_HAS_FAST_HR_TSTAMP ) \ + & ~PCPS_HAS_IRIG_TX ) ///< IRIG TX only supp. if ::GPS_HAS_IRIG_TX #define PCPS_FEAT_DCF600USB ( PCPS_FEAT_USB5131 ) -#define PCPS_FEAT_PZF180PEX ( PCPS_FEAT_PEX511 | PCPS_HAS_PZF ) +#define PCPS_FEAT_PZF180PEX ( PCPS_FEAT_LVL2 \ + | PCPS_HAS_TZDL \ + | PCPS_HAS_HR_TIME \ + | PCPS_HAS_SERNUM \ + | PCPS_HAS_RECEIVER_INFO \ + | PCPS_CAN_CLR_UCAP_BUFF \ + | PCPS_HAS_UCAP \ + | PCPS_HAS_GPS_DATA_16 \ + | PCPS_HAS_GENERIC_IO \ + | PCPS_HAS_UTC_PARM \ + | PCPS_HAS_PZF ) #define PCPS_FEAT_TCR600USB ( PCPS_FEAT_TCR51USB \ | PCPS_HAS_IRIG_CTRL_BITS \ @@ -1119,6 +916,12 @@ enum #define PCPS_FEAT_WVB600USB ( PCPS_FEAT_WWVB51USB ) +#define PCPS_FEAT_GLN180PEX ( PCPS_FEAT_GPS180PEX | PCPS_IS_GNSS ) + +#define PCPS_FEAT_GPS180AMC ( PCPS_FEAT_GPS180PEX ) + +#define PCPS_FEAT_GNS181PEX ( PCPS_FEAT_GLN180PEX ) + // Some features of the API used to access Meinberg plug-in devices // have been implemented starting with the special firmware revision // numbers defined below. @@ -1128,12 +931,12 @@ enum // There are some versions of PCI Express cards out there which do not -// safely support hardware IRQs. The following firmware versions are required +// safely support hardware IRQs. The following firmware versions are required // for safe IRQ operation: #define REV_HAS_IRQ_FIX_MINOR_PEX511 0x0106 #define REV_HAS_IRQ_FIX_MINOR_TCR511PEX 0x0105 #define REV_HAS_IRQ_FIX_MINOR_GPS170PEX 0x0104 -// Additionally there are certain revisions of the bus interface logic +// Additionally there are certain revisions of the bus interface logic // required. The associated version codes are defined in pci_asic.h. // The macro below can be used to check whether the required versions are there: @@ -1158,8 +961,8 @@ enum #define REV_HAS_IRIG_CTRL_BITS_TCR511PCI 0x0107 #define REV_HAS_IRIG_CTRL_BITS_TCR51USB 0x0106 -/* This board uses the GPS_DATA interface with 16 bit buffer sizes - instead of the original 8 bit sizes, thus allowing to transfer +/* This board uses the GPS_DATA interface with 16 bit buffer sizes + instead of the original 8 bit sizes, thus allowing to transfer data blocks which exceed 255 bytes (PCPS_HAS_GPS_DATA_16) */ #define REV_HAS_GPS_DATA_16_GPS169PCI 0x0202 @@ -1214,16 +1017,26 @@ enum /** - The structure has been defined to pass all - information on a clock device from a device driver - to a user program. */ + * @brief Device info structure + * + * Used to pass all information on a bus-level device + * from a device driver to a user space application. + */ typedef struct { PCPS_DEV_TYPE type; PCPS_DEV_CFG cfg; + } PCPS_DEV; +#if 1 || defined( MBG_TGT_KERNEL ) //### FIXME + #define _USE_DEV_MACROS 1 +#else + #define _USE_DEV_MACROS 0 +#endif + + // The macros below simplify access to the data // stored in PCPS_DEV structure and should be used // to extract the desired information. @@ -1247,6 +1060,7 @@ typedef struct #define _pcps_is_irig_rx( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_IRIG ) #define _pcps_is_ptp( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_PTP ) #define _pcps_is_frc( _d ) ( _pcps_ref_type( _d ) == PCPS_REF_FRC ) +#define _pcps_is_gnss( _d ) _pcps_has_feature( (_d), PCPS_IS_GNSS ) #define _pcps_is_lwr( _d ) ( _pcps_is_dcf( _d ) || _pcps_is_msf( _d ) || _pcps_is_wwvb( _d ) ) @@ -1270,12 +1084,11 @@ typedef struct #define _pcps_bus_num( _d ) ( (_d)->cfg.bus_num ) #define _pcps_slot_num( _d ) ( (_d)->cfg.slot_num ) -#define _pcps_cfg_port_rsrc( _c, _n ) ( (_c)->port[_n] ) -#define _pcps_port_rsrc( _d, _n ) _pcps_cfg_port_rsrc( &(_d)->cfg, (_n) ) -#define _pcps_port_rsrc_unused( _d ) ( (_d)->base == 0 || (_d)->num == 0 ) +#define _pcps_cfg_short_port_rsrc( _c, _n ) ( (_c)->port[_n] ) +#define _pcps_short_port_rsrc( _d, _n ) _pcps_cfg_short_port_rsrc( &(_d)->cfg, (_n) ) -#define _pcps_cfg_port_base( _c, _n ) ( _pcps_cfg_port_rsrc( (_c), (_n) ).base ) -#define _pcps_port_base( _d, _n ) ( _pcps_port_rsrc( (_d), (_n) ).base ) +#define _pcps_cfg_short_port_base( _c, _n ) ( _pcps_cfg_short_port_rsrc( (_c), (_n) ).base ) +#define _pcps_short_port_base( _d, _n ) ( _pcps_short_port_rsrc( (_d), (_n) ).base ) #define _pcps_cfg_irq_num( _c ) ( (_c)->irq_num ) #define _pcps_irq_num( _d ) _pcps_cfg_irq_num( &(_d)->cfg ) @@ -1296,12 +1109,18 @@ typedef struct #define _pcps_clr_err_flags( _d, _msk ) ( _pcps_err_flags( _d ) &= ~(_msk) ) -// Query whether a special feature is supported: +#if _USE_DEV_MACROS + +/// Check whether a special feature is supported #define _pcps_has_feature( _d, _f ) ( ( (_d)->cfg.features & (_f) ) != 0 ) -// Query whether a special feature is supported according to RECEIVER_INFO: +/// Check whether a special feature is supported according to ::RECEIVER_INFO #define _pcps_has_ri_feature( _p_ri, _f ) ( ( (_p_ri)->features & (_f) ) != 0 ) +#define _ri_addr( _p ) &(_p)->xdev_features.receiver_info +#define _xfeat_addr( _p ) &(_p)->xdev_features.xfeature_buffer +#define _tlv_info_addr( _p ) &(_p)->xdev_features.tlv_info + #define _pcps_can_set_time( _d ) _pcps_has_feature( (_d), PCPS_CAN_SET_TIME ) #define _pcps_has_serial( _d ) _pcps_has_feature( (_d), PCPS_HAS_SERIAL ) @@ -1397,6 +1216,25 @@ typedef struct #define _pcps_has_tr_distance( _d ) _pcps_has_pzf( _d ) +#define _pcps_has_evt_log( _d ) _pcps_has_feature( (_d), PCPS_HAS_EVT_LOG ) + +#define _pcps_has_debug_status( _d ) _pcps_is_irig_rx( _d ) + +#define _pcps_has_stat_info( _d ) ( _pcps_is_gps( _d ) || _pcps_has_pzf( _d ) ) + +#define _pcps_has_stat_info_mode( _d ) _pcps_is_gps( _d ) + +#define _pcps_has_stat_info_svs( _d ) _pcps_is_gps( _d ) + +#define _pcps_has_ri_gpio( _p_ri ) _pcps_has_ri_feature( (_p_ri), GPS_HAS_GPIO ) + +// We only report that XMR is supported if all required features are supported. +#define _pcps_has_ri_xmr( _p_ri ) ( _pcps_has_ri_feature( (_p_ri), GPS_HAS_XMULTI_REF ) && \ + _pcps_has_ri_feature( (_p_ri), GPS_HAS_XMRS_MULT_INSTC ) ) +//### TODO should also check GPS_MODEL_HAS_XMR_HOLDOVER_INTV, which is a builtin feature flag only + +#endif // _USE_DEV_MACROS + // There are some versions of IRIG receiver cards which ignore the TFOM code // of an incoming IRIG signal even if an IRIG code has been configured which @@ -1404,7 +1242,7 @@ typedef struct // signal even if the TFOM code reports the IRIG generator is not synchronized. // The intended behaviour is that the IRIG receiver card changes its status // to "freewheeling" in this case, unless it has been configured to ignore -// the TFOM code of the incoming IRIG signal (see the IFLAGS_DISABLE_TFOM flag +// the TFOM code of the incoming IRIG signal (see the ::IFLAGS_DISABLE_TFOM flag // defined in gpsdefs.h). // The macro below can be used to check based on the device info if a specific @@ -1418,76 +1256,64 @@ typedef struct // PCI bridge built into the chip. Unfortunately there are some mainboards out there // which do not handle PCI resources behind this PCI bridge correctly. The symptom is // usually that both I/O address ranges of these cards get the same base address -// assigned by the BIOS, and the efeect is that in this case a card is not accessible +// assigned by the BIOS, and the effect is that in this case a card is not accessible // properly, since both I/O ranges try to respond to the same I/O addresses. -// As a consequence data read from the card is usually garbage. +// As a consequence, data read from the card is usually garbage. // The only known fix for this is a BIOS update for the mainboard which makes the // BIOS handle the card's resources properly. // The macro below can be used to test if both port base addresses assigned to a card // are identical, and thus the BIOS is probably faulty:: #define _pcps_pci_cfg_err( _d ) \ - ( _pcps_port_base( _d, 1 ) == _pcps_port_base( _d, 0 ) ) + ( _pcps_is_pci( _d ) && ( _pcps_short_port_base( _d, 1 ) == _pcps_short_port_base( _d, 0 ) ) ) -/** - The structure is used to return info - on the device driver.*/ -typedef struct -{ - uint16_t ver_num; /**< the device driver's version number */ - uint16_t n_devs; /**< the number of radio clocks handled by the driver */ - PCPS_ID_STR id_str; /**< the device driver's ID string */ -} PCPS_DRVR_INFO; +// There are some versions of GPS PCI firmware which may occasionally return +// a HR time stamp which is wrong by 20 milliseconds, if the HR time is read +// right after some GPS data. As a workaround for that bug an application +// must wait at least 1.5 ms and then just read the PCPS_TIME structure +// in order to re-initialize the software interface state. +// This has been fixed in more recent versions of the affected firmware, +// but this macro can be used to let an application determine whether it +// must account for this bug with a given card and firmware version. +#define _must_do_fw_workaround_20ms( _d ) \ +( \ + ( _pcps_type_num( _d ) == PCPS_TYPE_GPS168PCI && _pcps_fw_rev_num( _d ) < 0x0102 ) || \ + ( _pcps_type_num( _d ) == PCPS_TYPE_GPS167PCI && _pcps_fw_rev_num( _d ) < 0x0420 ) \ +) -/* - * The definitions and types below are used to collect - * all configuration parameters of a clock's serial ports - * that can be handled by this library: +/** + * @brief Codes used with ::IOCTL_DEV_FEAT_REQ::feat_req_type */ - -// The maximum number of clocks' serial ports and string types -// that can be handled by the configuration programs: -#define MAX_PARM_PORT 4 -#define MAX_PARM_STR_TYPE 20 - -typedef PORT_INFO_IDX ALL_PORT_INFO[MAX_PARM_PORT]; -typedef STR_TYPE_INFO_IDX ALL_STR_TYPE_INFO[MAX_PARM_STR_TYPE]; - -typedef struct +enum DEV_FEAT_REQ_TYPES { - ALL_PORT_INFO pii; - ALL_STR_TYPE_INFO stii; - PORT_PARM tmp_pp; - -} RECEIVER_PORT_CFG; - - - -/* - * The definitions and types below are used to collect - * all configuration parameters of a clock's programmable - * pulse outputs that can be handled by this library: - */ - -#define MAX_PARM_POUT 4 - -typedef POUT_INFO_IDX ALL_POUT_INFO[MAX_PARM_POUT]; + DEV_FEAT_REQ_TYPE_BUILTIN, ///< feat_num field contains one of the ::GPS_BUILTIN_FEATURE_BITS + DEV_FEAT_REQ_TYPE_REF_TYPE, ///< feat_num field contains one of the ::PCPS_REF_TYPES + DEV_FEAT_REQ_TYPE_PCPS, ///< feat_num field contains one of the ::PCPS_FEATURE_BITS + DEV_FEAT_REQ_TYPE_RI, ///< feat_num field contains one of the ::GPS_FEATURE_BITS + DEV_FEAT_REQ_TYPE_XFEAT, ///< feat_num field contains one of the ::MBG_XFEATURE_BITS + DEV_FEAT_REQ_TYPE_TLV_FEAT, ///< feat_num field contains one of the ::MBG_TLV_FEAT_TYPES + N_DEV_FEAT_REQ_TYPES +}; -/* - * The definitions and types below are used to collect - * all configuration parameters of PTP device's unicast - * master specification: +/** + * @brief Device driver information + * + * Used to pass info on the device driver to + * a user space application. */ +typedef struct +{ + uint16_t ver_num; ///< the device driver's version number + uint16_t n_devs; ///< the number of devices handled by the driver + PCPS_ID_STR id_str; ///< the device driver's ID string -#define MAX_PARM_PTP_UC_MASTER 3 - -typedef PTP_UC_MASTER_INFO_IDX ALL_PTP_UC_MASTER_INFO[MAX_PARM_PTP_UC_MASTER]; +} PCPS_DRVR_INFO; @@ -1500,99 +1326,125 @@ typedef PTP_UC_MASTER_INFO_IDX ALL_PTP_UC_MASTER_INFO[MAX_PARM_PTP_UC_MASTER]; /** - The structure is used to read the current time from - a device, combined with an associated PC cycle counter value - to compensate program execution time. - */ + * @brief Time read from a device plus associated system cycles count + * + * Contains current time from a device, plus an associated PC + * cycles counter value useful to compensate execution time. + */ typedef struct { MBG_PC_CYCLES cycles; PCPS_TIME t; + } PCPS_TIME_CYCLES; /** - The structure is used to read a high resolution UTC time stamp - plus associated PC cycles counter value to compensate the latency. - */ + * @brief High resolution time stamp plus associated system cycles count + * + * Contains current high resolution UTC time stamp from a device, plus + * an associated PC cycles counter value useful to compensate execution time. + */ typedef struct { MBG_PC_CYCLES cycles; - PCPS_TIME_STAMP tstamp; /**< High resolution time stamp (UTC) */ + PCPS_TIME_STAMP tstamp; ///< High resolution time stamp (%UTC) + } PCPS_TIME_STAMP_CYCLES; #define _mbg_swab_pcps_time_stamp_cycles( _p ) \ +do \ { \ _mbg_swab_mbg_pc_cycles( &(_p)->cycles ); \ _mbg_swab_pcps_time_stamp( &(_p)->tstamp ); \ -} +} while ( 0 ) /** - The structure is used to read the current high resolution time - from a device, combined with an associated PC cycle counter value - to compensate program execution time. - */ + * @brief High resolution time plus associated system cycles count + * + * Contains current high resolution %UTC time from a device, including + * local time offset and status, plus an associated PC cycles counter value + * useful to compensate execution time. + */ typedef struct { MBG_PC_CYCLES cycles; PCPS_HR_TIME t; + } PCPS_HR_TIME_CYCLES; #define _mbg_swab_pcps_hr_time_cycles( _p ) \ +do \ { \ _mbg_swab_mbg_pc_cycles( &(_p)->cycles ); \ _mbg_swab_pcps_hr_time( &(_p)->t ); \ -} +} while ( 0 ) /** - The structure below can be used to let the kernel driver read - the current system time plus the associated HR time from a plugin card - as close as possibly, and return the results to a user space application - which can then compute the time difference and latencies. - This structure also contains the card's status information (e.g. sync status). - */ + * @brief High resolution device time, system time, and associated cycles counts + * + * Used to let the kernel driver read the current system time plus the associated + * high resolution time from a bus-level device as close as possible, and return + * the results to the caller which can then compute the time difference, taking + * into account the latencies determined from the cycles counts. + * + * This structure also contains the card's status information (e.g. sync status). + */ typedef struct { - PCPS_HR_TIME_CYCLES ref_hr_time_cycles; /**< HR time read from the card, plus cycles */ - MBG_SYS_TIME_CYCLES sys_time_cycles; /**< system timestamp plus associated cycles */ + PCPS_HR_TIME_CYCLES ref_hr_time_cycles; ///< HR time read from the card, plus cycles + MBG_SYS_TIME_CYCLES sys_time_cycles; ///< system time stamp plus associated cycles + } MBG_TIME_INFO_HRT; #define _mbg_swab_mbg_time_info_hrt( _p ) \ +do \ { \ _mbg_swab_pcps_hr_time_cycles( &(_p)->ref_hr_time_cycles ); \ _mbg_swab_mbg_sys_time_cycles( &(_p)->sys_time_cycles ); \ -} +} while ( 0 ) /** - The structure below can be used to let the kernel driver read - the current system time plus an associated HR timestamp from a plugin card - as close as possibly, and return the results to a user space application - which can then compute the time difference and latencies. - Since the card's time stamp is usually taken using the fast memory mapped - access this structure does *not* contain the card's status information - (e.g. sync status). - */ + * @brief High resolution device time stamp, system time, and associated cycles counts + * + * Used to let the kernel driver read the current system time plus the associated + * high resolution time stamp from a bus-level device as close as possible, and return + * the results to the caller which can then compute the time difference, taking + * into account the latencies determined from the cycles counts. + * + * Since the card's time stamp is taken from the fast memory mapped registers + * this structure does *not* contain the card's status information (e.g. sync status). + */ typedef struct { - PCPS_TIME_STAMP_CYCLES ref_tstamp_cycles; /**< HR timestamp from the card, plus cycles */ - MBG_SYS_TIME_CYCLES sys_time_cycles; /**< system timestamp plus associated cycles */ + PCPS_TIME_STAMP_CYCLES ref_tstamp_cycles; ///< HR timestamp from the card, plus cycles + MBG_SYS_TIME_CYCLES sys_time_cycles; ///< system timestamp plus associated cycles + } MBG_TIME_INFO_TSTAMP; #define _mbg_swab_mbg_time_info_tstamp( _p ) \ +do \ { \ _mbg_swab_pcps_time_stamp_cycles( &(_p)->ref_tstamp_cycles ); \ _mbg_swab_mbg_sys_time_cycles( &(_p)->sys_time_cycles ); \ -} +} while ( 0 ) +/** + * @defgroup group_irq_stat_info IRQ status information + * + * @anchor PCPS_IRQ_STAT_INFO_DEFS + * + * @{ */ + typedef uint32_t PCPS_IRQ_STAT_INFO; // Flags used with PCPS_IRQ_STAT_INFO: @@ -1602,6 +1454,10 @@ typedef uint32_t PCPS_IRQ_STAT_INFO; #define PCPS_IRQ_STATE_DANGER ( PCPS_IRQ_STAT_ENABLED | PCPS_IRQ_STAT_UNSAFE ) +/** @} defgroup group_irq_stat_info */ + + + #define _pcps_fw_rev_num_major( _v ) \ ( ( (_v) >> 8 ) & 0xFF ) @@ -1614,6 +1470,37 @@ typedef uint32_t PCPS_IRQ_STAT_INFO; #undef _USING_BYTE_ALIGNMENT #endif + +#if !defined( MBG_TGT_KERNEL ) + +static __mbg_inline +void setup_hr_time_cycles_from_timestamp_cycles( PCPS_HR_TIME_CYCLES *p_ht_c, + const PCPS_TIME_STAMP_CYCLES *p_ts_c ) +{ + memset( p_ht_c, 0, sizeof( *p_ht_c ) ); + + p_ht_c->t.tstamp = p_ts_c->tstamp; + p_ht_c->cycles = p_ts_c->cycles; + +} // setup_hr_time_cycles_from_timestamp_cycles + +#endif + + + +/** + * @brief A string buffer for a unique device ID + * + * The unique ID is made up of the device model name + * and its serial number, i.e. [model_name]_[serial_number] + * E.g.: "GPS170PCI_028210040670" + * + * @see ::snprint_dev_name + */ +typedef char MBG_DEV_NAME[PCPS_CLOCK_NAME_SZ + PCPS_SN_SIZE + 1]; + + + /* End of header body */ #undef _ext diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.c b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.c index 4b1856f..fd6df88 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.c +++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pcpsdrvr.c 1.46.2.48 2011/07/19 12:48:10 martin TRASH $ + * $Id: pcpsdrvr.c 1.52 2017/07/04 16:45:36 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -25,15 +25,16 @@ * USB v1: USB5131, TCR51USB, MSF51USB, WWVB51USB * PCI express: PEX511, TCR511PEX, GPS170PEX, PTP270PEX, * FRC511PEX, TCR170PEX, GPS180PEX, TCR180PEX - * PZF180PEX + * PZF180PEX, GLN180PEX, GPS180AMC, GNS181PEX * PCI bus 5V/3.3V: PCI510, PCI511, GPS169PCI, GPS170PCI, * TCR510PCI, TCR167PCI, TCR511PCI * PCI bus 5V: PCI32, GPS167PCI, PCI509, GPS168PCI * MCA bus: PS31 * ISA bus: PC31, PC32, GPS167PC * - * USB is not supported for some target environments, mainly because - * those operating systems don't provide full USB support. + * USB is not supported for all target environments, eventually + * because an operating systems doesn't provide full USB support, + * or USB support hasn't yet been implemented. * * PCI support is possible in two different ways. The preferred * functions are compiled in if one of the symbols _PCPS_USE_PCI_PNP @@ -42,12 +43,12 @@ * If _PCPS_USE_PCI_PNP is != 0 it is assumed that the operating * system's PCI layer detects a new PCI device and calls a driver's * add_device()/start_device() function to initialize the device. - * This new technique is supported with PNP operating systems - * (e.g. Win98, Win2K, newer Linux versions). + * This technique is supported with PNP operating systems + * (e.g. Windows versions after NT, Linux, *BSD). * * If _PCPS_USE_PCI_BIOS is != 0 the program scans the PCI bus * during startup to detect and initialize supported PCI devices. - * This techique is used with non-PNP operating systems. + * This techique is used with old non-PNP operating systems. * * The symbol _PCPS_USE_RSRCMGR must be defined != 0 to include * support of resource managers, if necessary. @@ -56,113 +57,75 @@ * detection (and therefore auto-detection of a MCA clock) is * supported. * - * MCA clocks are accessed using the same low level functions as - * ISA clocks, so if autodetection of MCA clocks is not supported - * then a MCA clock's known port number can be passed to - * pcps_detect_clocks() to let it be treated like an ISA clock. + * MCA devices are accessed using the same low level functions as + * ISA devices, so if autodetection of MCA clocks is not supported + * then a MCA device's known port number can be passed to + * pcps_detect_devices() to let it be treated like an ISA device. * * ----------------------------------------------------------------------- * $Log: pcpsdrvr.c $ - * Revision 1.46.2.48 2011/07/19 12:48:10 martin + * Revision 1.52 2017/07/04 16:45:36 martin + * Support GPS180AMC and GNS181PEX. + * Renamed some functions: Use _device instead of _clock, + * pcps_start_device() is now called pcps_probe_device(), etc. + * Runtime support for forcing I/O rather than MM access. + * Increase MAX_BOOT_TIME_PTP270PEX from 27 to 40 seconds + * to be safe in case a firmware update is applied at startup. + * Fixed type of a register address. + * Cleaned up I/O port usage. + * Older defines N_SUPP_DEV, PCPS_MAX_DDEVS, and MBG_MAX_DEVICES + * have been obsoleted by new defines N_SUPP_DEV_BUS, N_SUPP_DEV_EXT, + * and N_SUPP_DEV_TOTAL. + * Fixed DEBUG build under *BSD. + * Added DEBUG code dumping RECEIVER_INFO. + * Moved mbg_delta_sys_time_ms() to new module mbgsystm.c. + * Check for MBG_TGT_POSIX instead of MBG_TGT_UNIX. + * Provided a driver name string for debug build on direct-access targets. + * Avoid 'redundant redeclaration' warning under FreeBSD 8.2. + * Fixed macro definition syntax to avoid clang compiler warnings. + * Fixed some other warnings from clang. + * Attribute always_inline is now in __mbg_inline. + * Conditional USB debug code. + * Account for renamed symbols. + * Fixed typos, wording, and doxygen comments. + * Removed trailing white space. + * Revision 1.51 2013/10/01 14:19:03 martin + * Support GLN180PEX. + * Revision 1.50 2013/03/15 10:01:58 martin + * Modified/added some debug messages. + * Revision 1.49 2013/03/15 08:35:08 martin + * Account for PTP270PEX HW v2 cards which can indicate + * when they are ready to be accessed. + * Account for unified, renamed PLX symbols. + * Revision 1.48 2012/11/05 16:32:02Z martin + * Fixed and enhanced some timing DEBUG code. + * Rewrote report_uptime(). + * Revision 1.47 2012/10/15 14:12:08 martin + * Support GPS180PEX, TCR180PEX, and PZF180PEX. + * Support DCF600USB, TCR600USB, MSF600USB, and WVB600USB. + * Support FreeBSD and NetBSD. + * Support on-board event log. + * If required, wait until PTP270PEX has finished booting. + * Use USB micro frame timing conditionally only, yet disabled by default. + * Conditional debug code to test PCI access time and/or execution time + * of the low level functions. + * Always read the serial number directly from the device. * Unified low level functions and use 16 bit types for buffer sizes. - * Cleanup. - * Revision 1.46.2.47 2011/07/11 12:49:44 martin - * Revision 1.46.2.46 2011/07/11 11:00:42Z martin - * Modified some debug code. - * Revision 1.46.2.45 2011/07/05 10:44:22 martin - * Fixed build errors under Unix. - * Revision 1.46.2.44 2011/07/05 10:18:59 martin - * Fixed pcps_start_device() for USBv2 devices. - * Added warnings in case a device is not handled - * by chip setup or device feature check. - * Revision 1.46.2.43 2011/06/29 14:02:49Z martin - * Renamed PZF600PEX to PZF180PEX. - * Added support for TCR600USB, MSF600USB, and WVB600USB. - * Modified low level AMCC read functions for SPARC. - * Fixed handling of unaligned access for SPARC. - * Modified DEBUG_IO code. - * Added some debug messages. - * Updated some comments. - * Revision 1.46.2.42 2011/06/21 15:20:56 martin - * Fixed build under DOS. - * Revision 1.46.2.41 2011/06/20 16:53:34Z martin - * account for generic MBG_SYS_TIME with nanosecond resolution. - * Revision 1.46.2.40 2011/05/16 17:41:11 martin + * Added warnings in case a device is not handled by chip setup + * or device feature check. + * Modified low level AMCC read functions for SPARC to fix unaligned access. + * Added debug messages for generic I/O. * Initialize device semaphores only early at device initializition * if required, otherwise later, since early initialization can lead * to a trap e.g. under Windows. - * Revision 1.46.2.39 2011/05/06 13:47:39Z martin - * Support PZF600PEX. - * Revision 1.46.2.38 2011/04/19 15:06:56 martin - * Fixed build error on bigendian target. - * Revision 1.46.2.37 2011/04/12 15:28:56 martin + * Conditional code to test MM I/O for new PCI cards. * Use common mutex primitives from mbgmutex.h. - * Revision 1.46.2.36 2011/04/01 10:38:00 martin - * Modified mutex/spinlock initialization, and do deinitializaton. - * Fixed compiler warnings. - * Revision 1.46.2.35 2011/03/25 11:10:34 martin * Optionally support timespec for sys time (USE_TIMESPEC). - * Revision 1.46.2.34 2011/03/22 10:25:57 martin - * Modifications to support NetBSD. - * Revision 1.46.2.33 2011/03/21 16:26:03 martin - * Account for modified _pcps_kfree(). - * Revision 1.46.2.32 2011/02/16 10:14:37 martin * Set up basic default receiver info for devices which don't * support this structure. - * Revision 1.46.2.31 2011/02/15 14:24:57Z martin - * Revision 1.46.2.30 2011/02/10 09:18:07 martin - * Revision 1.46.2.29 2011/02/09 17:08:30Z martin - * Specify I/O range number when calling port I/O macros - * so they can be used for different ranges under BSD. - * Revision 1.46.2.28 2011/02/09 16:42:12 martin - * Revision 1.46.2.27 2011/02/09 15:27:49 martin - * Revision 1.46.2.26 2011/02/09 14:43:19Z martin - * Revision 1.46.2.25 2011/02/07 15:47:28 martin - * Fixed a potential trap in kernel messages. - * Revision 1.46.2.24 2011/02/04 14:44:45 martin - * Revision 1.46.2.23 2011/02/01 17:12:04 martin - * Revision 1.46.2.22 2011/02/01 15:08:34 martin - * Revision 1.46.2.21 2011/02/01 12:12:18 martin - * Revision 1.46.2.20 2011/01/31 17:30:28 martin - * Preliminary virt addr under *BSD. - * Revision 1.46.2.19 2011/01/28 10:34:06 martin * Moved MBG_TGT_SUPP_MEM_ACC definition to pcpsdev.h. - * Revision 1.46.2.18 2011/01/27 15:13:08 martin - * Added some debug messages in pcps_start_device(). - * Revision 1.46.2.17 2011/01/27 13:39:33 martin - * Revision 1.46.2.16 2011/01/27 11:01:48 martin - * Support static device list (no malloc) and use it under FreeBSD. - * Revision 1.46.2.15 2011/01/26 16:40:14 martin - * Fixed build under FreeBSD. - * Revision 1.46.2.14 2011/01/26 11:30:29 martin - * Fixed PTP270PEX boot delay. - * Revision 1.46.2.13 2011/01/07 14:00:58 daniel - * Re-enabled wait period for PTP270PEX - * Revision 1.46.2.12 2010/11/23 11:07:56Z martin - * Support memory mapped access under DOS. - * Revision 1.46.2.11 2010/11/22 14:19:27Z martin - * Support DCF600USB. - * Cleanup. - * Revision 1.46.2.10 2010/10/06 09:24:02 martin - * Revision 1.46.2.9 2010/09/27 13:09:22Z martin - * Revision 1.46.2.8 2010/09/21 13:10:15 daniel - * Check for raw IRIG data support in reciver info. - * Revision 1.46.2.7 2010/09/02 12:19:24Z martin * Introduced and use new function check_ri_feature(). * Also detect support for raw IRIG data from RECEIVER_INFO. - * Added debug code. - * Sleeping for PTP270PEX if uptime is too low needs to be fixed. - * Revision 1.46.2.6 2010/08/16 15:41:28 martin - * Revision 1.46.2.5 2010/08/13 11:56:49 martin - * Fixed build on WIN32_NON_PNP. - * Revision 1.46.2.4 2010/08/13 11:20:23Z martin - * If required, wait until PTP270PEX has finished booting. - * Revision 1.46.2.3 2010/08/11 13:41:47Z martin - * Code cleanup. - * Revision 1.46.2.2 2010/07/14 14:51:56 martin - * Use direct pointer to memory maopped timestamp. - * Revision 1.46.2.1 2010/06/30 15:02:12 martin - * Support GPS180PEX and TCR180PEX. * Revision 1.46 2009/12/15 14:45:33 daniel * Account for feature to read the raw IRIG bits. * Revision 1.45 2009/09/29 07:24:50Z martin @@ -184,17 +147,17 @@ * Revision 1.38 2009/03/17 15:33:53 martin * Support reading IRIG control function bits. * Revision 1.37 2009/03/13 09:17:00Z martin - * Bug fix: Hadn't checked whether TCR170PEX card provides the + * Bug fix: Hadn't checked whether TCR170PEX card provides the * programmable synthesizer. - * As a fix moved the code from the body of check_opt_features() - * into pcps_start_device() so that the check is done for every + * As a fix moved the code from the body of check_opt_features() + * into pcps_start_device() so that the check is done for every * type of card. * Swap receiver_info to make this work on non-x86 architectures. - * Support configurable time scales, and reading/writing GPS UTC + * Support configurable time scales, and reading/writing GPS UTC * parameters via the PC bus. * Use mbg_get_pc_cycles() instead of _pcps_get_cycles(). * Revision 1.36 2009/01/13 12:03:57Z martin - * Generate a separate warning message if the firmware could not + * Generate a separate warning message if the firmware could not * be read from an ISA card. * Care about "long long" in debug msg. * Revision 1.35 2008/12/16 14:38:49Z martin @@ -204,10 +167,10 @@ * Check whether PEX511 and PCI511 support HR time. * Moved initialization of common spinlocks and mutexes to pcps_start_device(). * Take access cycles count in the low level routines, with interrupts disabled. - * Cleanup for pcps_read_usb() which is now possible since access cycles count + * Cleanup for pcps_read_usb() which is now possible since access cycles count * is now taken inside the low evel routines. * Support mapped I/O resources, unaligned access and endianess conversion. - * Account for ASIC_FEATURES being coded as flags, and account for + * Account for ASIC_FEATURES being coded as flags, and account for * new symbol PCI_ASIC_HAS_MM_IO. * Account for new MBG_PC_CYCLES type. * Account for signed irq_num. @@ -215,8 +178,8 @@ * Use MBG_MEM_ADDR type for memory rather than split high/low types. * Distinguish device port variables for IRQ handling. * Preliminarily support USB latency compensation under Win32 PNP targets - * and account for USB EHCI microframe timing which requires a different - * latency compensation approach. This is useful if a USB 2.0 hub is connected + * and account for USB EHCI microframe timing which requires a different + * latency compensation approach. This is useful if a USB 2.0 hub is connected * between device and host. * Also read the ASIC version at device initialization. * pcps_alloc_ddev() does not take a parameter anymore. @@ -224,9 +187,9 @@ * Revision 1.34 2008/02/27 10:03:02 martin * Support TCR51USB and MSF51USB. * Preliminary support for mapped memory access under Windows and Linux. - * Enabled PCPS_IRQ_1_SEC for USB within WIN32 targets + * Enabled PCPS_IRQ_1_SEC for USB within WIN32 targets * in pcps_start_device(). - * Fixed a bug in pcps_write() where the error code + * Fixed a bug in pcps_write() where the error code * that was returned from a USB device was misinterpreted * due to a signed/unsigned mismatch (added typecast). * Removed obsolete function pcps_cleanup_all_devices(). @@ -271,7 +234,7 @@ * OS requirements, in order to avoid naming conflicts. * Revision 1.26 2006/06/19 15:28:52 martin * Added support for TCR511PCI. - * Modified parameters required to detect ISA cards. + * Modified parameters required to detect ISA cards. * The array of port addresses does no more require a 0 address * as last value. * Revision 1.25 2006/03/10 11:01:27 martin @@ -291,8 +254,8 @@ * Revision 1.19 2004/10/14 15:01:24 martin * Added support for TCR167PCI. * Revision 1.18 2004/09/06 15:16:57Z martin - * Support a GPS_DATA interface where sizes are specified - * by 16 instead of the original 8 bit quantities, thus allowing + * Support a GPS_DATA interface where sizes are specified + * by 16 instead of the original 8 bit quantities, thus allowing * to transfer data blocks which exceed 255 bytes. * Conditionally skip assertions under Linux. * Revision 1.17 2004/04/22 14:47:54 martin @@ -330,9 +293,9 @@ * Use new header mbg_tgt.h to check the target environment. * Removed function pcps_sn_str_from_ident(), use new * function mbg_gps_ident_decode() from identdec.c now. - * If a PCI clock's interface is not properly configured don't - * enable the device and set the read function to the new - * dummy function pcps_read_null() to prevent driver from + * If a PCI clock's interface is not properly configured don't + * enable the device and set the read function to the new + * dummy function pcps_read_null() to prevent driver from * accessing random ports. * Revision 1.5 2002/02/01 12:06:12 MARTIN * Added support for GPS168PCI. @@ -355,13 +318,12 @@ #include <pcpsdrvr.h> #undef _PCPSDRVR -#include <parmpcps.h> -#include <parmgps.h> #include <identdec.h> #include <mbgddmsg.h> #include <plxdefs.h> #include <pci_asic.h> #include <amccdefs.h> +#include <pcidefs.h> #if defined( MBG_TGT_WIN32_PNP ) #include <usbdrv.h> @@ -371,6 +333,8 @@ #elif defined( MBG_TGT_WIN32 ) #include <pcps_ioc.h> #include <stdio.h> +#elif defined( MBG_TGT_DOS ) + #include <mbgplx.h> #endif #if !defined( MBG_TGT_LINUX ) && !defined( MBG_TGT_BSD ) @@ -379,7 +343,6 @@ #if defined( MBG_TGT_FREEBSD ) #include <sys/rman.h> - #include <sys/libkern.h> #endif #if _PCPS_USE_MCA @@ -395,27 +358,109 @@ #endif -// time required for PTP270PEX to be ready after booting -#define MAX_BOOT_TIME_PTP270PEX 27 // [s] +// In NetBSD defining DEBUG to build a debug version of this driver +// would interfere with DEBUG being defined for the kernel sources, +// so we need to define MBG_DEBUG instead. For simplicity, we define +// DEBUG locally in this module if MBG_DEBUG is defined. +#if defined( MBG_TGT_NETBSD ) && defined( MBG_DEBUG ) + #undef DEBUG + #define DEBUG MBG_DEBUG +#endif + + +#if !defined( USE_CMD_PTR ) + #define USE_CMD_PTR 1 +#endif +#if !defined( DEBUG_ACCESS_TIMING ) + // test how much cycles it takes to read/write a register on the board + #if ( defined( DEBUG ) && ( DEBUG >= 10 ) ) + #define DEBUG_ACCESS_TIMING 1 + #else + #define DEBUG_ACCESS_TIMING 0 + #endif +#endif + +#if !defined( DEBUG_IO_TIMING ) + // test how much cycles it takes for a low level function to execute + #if ( defined( DEBUG ) && ( DEBUG >= 10 ) ) + #define DEBUG_IO_TIMING 1 + #else + #define DEBUG_IO_TIMING 0 + #endif +#endif #if !defined( DEBUG_IO ) - #if defined( MBG_TGT_NETBSD ) - #define DEBUG_IO ( defined( MBG_DEBUG ) && ( MBG_DEBUG >= DEBUG_LVL_IO ) ) + // debug which bytes are written to or read from the board + #if ( defined( DEBUG ) && ( DEBUG >= DEBUG_LVL_IO ) ) + #define DEBUG_IO 1 #else - #define DEBUG_IO ( defined( DEBUG ) && ( DEBUG >= DEBUG_LVL_IO ) ) + #define DEBUG_IO 0 #endif #endif #if !defined( DEBUG_PORTS ) - #define DEBUG_PORTS ( defined( DEBUG ) && ( DEBUG >= DEBUG_LVL_PORTS ) ) + #if ( defined( DEBUG ) && ( DEBUG >= DEBUG_LVL_PORTS ) ) + #define DEBUG_PORTS 1 + #else + #define DEBUG_PORTS 0 + #endif #endif #if !defined( DEBUG_SERNUM ) - #define DEBUG_SERNUM ( defined( DEBUG ) && ( DEBUG >= DEBUG_LVL_SERNUM ) ) + #if ( defined( DEBUG ) && ( DEBUG >= DEBUG_LVL_SERNUM ) ) + #define DEBUG_SERNUM 1 + #else + #define DEBUG_SERNUM 0 + #endif +#endif + +#if !defined( USE_USB_MICRO_FRAMES ) + #define USE_USB_MICRO_FRAMES 0 #endif -extern const char pcps_driver_name[]; + +/** + * @brief Max. time required for PTP270PEX v1 card to be ready after power-up. + * + * The PTP270PEX cards have an on-board Linux system which must have + * finished booting before the card can be accessed via the PCI bus. + * If the card is accessed earlier then the PCI bus and thus the computer + * may hang. + * + * There are 2 different hardware versions of the PTP270PEX card. + * PTP270PEX v2 hardware and firmware can flag via a bit in the PCI + * configuration space when the card is ready, so the driver can just + * wait until the card has flagged that it's ready. + * + * However, the PTP270PEX v1 hardware doesn't support this, so the driver + * checks the system uptime and waits until it is greater or equal the + * maximum time required for a PTP270PEX v1 card to finish booting. + * + * The nominal time is 27 s, but if a firmware update has been submitted + * then the update is applied first, which takes another few seconds. + * + * @see ::wait_ptp270pex_ready + * @see ::report_uptime + */ +#define MAX_BOOT_TIME_PTP270PEX 40 // [s] + + +#if defined( MBG_TGT_BSD ) + // Avoid compiler warnings "redundant redeclaration of ..." + // e.g. under FreeBSD 8.2 with gcc 4.2.1. + #define AVOID_REDUNDANT_REDECLARATION 1 +#endif + +#if defined( MBG_TGT_KERNEL ) + // Driver name defined by the skeleton driver for the target OS. + extern const char pcps_driver_name[]; +#else + // No skeleton driver, but we need a string to pass to debug messages. + #if DEBUG + const char pcps_driver_name[] = "pcpsdrvr"; + #endif +#endif // In some environments special far functions are are neither @@ -495,120 +540,505 @@ extern const char pcps_driver_name[]; #endif +#if defined( MBG_TGT_DOS ) || \ + defined( MBG_TGT_QNX ) + #define MBG_TGT_HAS_UPTIME 0 +#elif defined( MBG_TGT_FREEBSD ) + // Under FreeBSD (at least 8.2) the kernel calls to read uptime always + // return 1 when this driver is loaded automatically, so the system + // locks up if we wait util uptime has reached a certain value. + #define MBG_TGT_HAS_UPTIME 0 +#else + #define MBG_TGT_HAS_UPTIME 1 +#endif + + + +/** + * @brief A table used to map ::RECEIVER_INFO::features to ::PCPS_DEV_CFG::features + * + * The enumerated ::GPS_FEATURE_BITS can be used as index + * to this table, and the table entry contains a combination + * of associated @ref PCPS_FEATURE_MASKS, if there are any. + * + * @note Devices which support a configurable time scale do also + * support reading/writing the GPS %UTC parameters via the PC bus. + * This is not explicitly coded in the ::RECEIVER_INFO::features + * since the the ::RECEIVER_INFO structure can also be read via + * the serial port, and reading/writing the GPS %UTC parameters + * via the serial port is supported by all GPS devices anyway. + * + * @note Devices which support reading ::MBG_RAW_IRIG_DATA via the PC bus + * interface also support reading ::PCPS_IRIG_TIME. However, there is + * no associated flag in ::RECEIVER_INFO::features since this call + * is not supported via the serial interface. Thus we use the + * ::GPS_HAS_RAW_IRIG_DATA flag to check both features. + * + * @see ::GPS_FEATURE_BITS + * @see @ref PCPS_FEATURE_MASKS + */ +static uint32_t ri_feat_tbl[N_GPS_FEATURE] = +{ + 0, ///< see ::GPS_FEAT_PPS + 0, ///< see ::GPS_FEAT_PPM + PCPS_HAS_SYNTH, ///< see ::GPS_FEAT_SYNTH + 0, ///< see ::GPS_FEAT_DCFMARKS + PCPS_HAS_IRIG_TX, ///< see ::GPS_FEAT_IRIG_TX + 0, ///< see ::GPS_FEAT_IRIG_RX + PCPS_HAS_LAN_INTF, ///< see ::GPS_FEAT_LAN_IP4 + 0, ///< see ::GPS_FEAT_MULTI_REF + + 0, ///< see ::GPS_FEAT_RCV_TIMEOUT + 0, ///< see ::GPS_FEAT_IGNORE_LOCK + 0, ///< see ::GPS_FEAT_5_MHZ + 0, ///< see ::GPS_FEAT_XMULTI_REF + 0, ///< see ::GPS_FEAT_OPT_SETTINGS + PCPS_HAS_TIME_SCALE | PCPS_HAS_UTC_PARM, ///< see ::GPS_FEAT_TIME_SCALE + PCPS_HAS_IRIG_CTRL_BITS, ///< see ::GPS_FEAT_IRIG_CTRL_BITS + PCPS_HAS_PTP, ///< see ::GPS_FEAT_PTP + + 0, ///< see ::GPS_FEAT_NAV_ENGINE_SETTINGS + PCPS_HAS_IRIG_TIME | PCPS_HAS_RAW_IRIG_DATA, ///< see ::GPS_FEAT_RAW_IRIG_DATA + 0, ///< see ::GPS_FEAT_RAW_IRIG_TIME + 0, ///< see ::GPS_FEAT_PTP_UNICAST + 0, ///< see ::GPS_FEAT_GPIO + 0, ///< see ::GPS_FEAT_XMRS_MULT_INSTC + 0, ///< see ::GPS_FEAT_10MHZ_DISBD + PCPS_HAS_EVT_LOG, ///< see ::GPS_FEAT_EVT_LOG + + 0, ///< see ::GPS_FEAT_IMS + 0, ///< see ::GPS_FEAT_HAVEQUICK + 0, ///< see ::GPS_FEAT_NTP + 0, ///< see ::GPS_FEAT_NET_CFG + 0, ///< see ::GPS_FEAT_VST + 0, ///< see ::GPS_FEAT_SHS + 0 ///< see ::GPS_FEAT_XBP +}; + + + +#if defined( DEBUG ) + +/** + * @brief A table of name strings associated with ::GPS_FEATURE_BITS + */ +static const char *gps_ri_feature_names[N_GPS_FEATURE] = DEFAULT_GPS_FEATURE_NAMES; + +/** + * @brief A table of name strings associated with ::PCPS_FEATURE_BITS + */ +static const char *pcps_feature_names[N_PCPS_FEATURE_BITS] = PCPS_FEATURE_NAMES; + +#endif // defined( DEBUG ) + + + +static __mbg_inline /*HDR*/ +/** + * @brief Check if a device is a PTP270PEX card + */ +int pcps_ddev_is_ptp270pex( const PCPS_DDEV *pddev ) +{ + return _pcps_ddev_is_pci( pddev ) && + ( _pcps_ddev_dev_id( pddev ) == PCI_DEV_PTP270PEX ); + +} // pcps_ddev_is_ptp270pex + + + + +#if defined( MBG_TGT_LINUX ) static /*HDR*/ -long mbg_delta_sys_time_ms( const MBG_SYS_TIME *t2, const MBG_SYS_TIME *t1 ) +/** + * @brief Read a dword from a PLX PECS register + * + * @param[in] pNode Device structure + * @param[in] reg Number of the register to read + * @param[out] pval Pointer to a variable to take the value read from the register + * + * @return ::PCI_SUCCESS on success, else one of the PCI BIOS error codes + */ +int mbg_plx_read_pecs_reg( struct pci_dev *pNode, + uint16_t reg, uint32_t *pval ) { - #if USE_GENERIC_SYS_TIME - long dt = ( t2->sec - t1->sec ) * 1000; - #if defined ( MBG_TGT_LINUX ) && defined( MBG_TGT_KERNEL ) - int64_t tmp64 = t2->nsec - t1->nsec; - do_div( tmp64, 1000000 ); - dt += tmp64; - #else - dt += ( t2->nsec - t1->nsec ) / 1000000; - #endif - return dt; + int rc; + + if ( reg & 0x03 ) + return PCI_BAD_REGISTER_NUMB; + + if ( reg < 0x1000 ) + { + rc = pci_read_config_dword( pNode, reg, pval ); + } + else + { + uint32_t mcr_idx_sav = (uint32_t) -1; + + reg -= 0x1000; + + rc = pci_read_config_dword( pNode, PLX_PECS_MAININDEX, &mcr_idx_sav ); + + if ( rc != PCI_SUCCESS ) + goto done; + + rc = pci_write_config_dword( pNode, PLX_PECS_MAININDEX, reg ); + + if ( rc != PCI_SUCCESS ) + goto done; + + rc = pci_read_config_dword( pNode, PLX_PECS_MAINDATA, pval ); + + if ( rc != PCI_SUCCESS ) + goto done; + + rc = pci_write_config_dword( pNode, PLX_PECS_MAININDEX, mcr_idx_sav ); + } + +done: + return rc; + +} // mbg_plx_read_pecs_reg + +#endif + + + +static /*HDR*/ +/** + * @brief Check if a PTP270PEX card can indicate when it's ready + * + * A PTP270PEX card must be accessed by the driver only + * after it has finished booting. Otherwise the host system + * may be locked up. + * + * On HW v2 cards the firmware can indicate when the card is + * ready to be accessed, so this can be checked by the driver. + * On these cards the on-board GPIO3 pin is hardwired to 0 + * to indicate this is supported, whereas on older v1 cards + * the GPIO3 pin is pulled up to 1. + * + * @param[in] pddev Pointer to the device structure + * + * @return true if the card can flag "ready" + * + * @see ::ptp270pex_has_flagged_ready + */ +bool ptp270pex_can_flag_ready( const PCPS_DDEV *pddev ) +{ + // The GPIO3 input level can only be read via a register + // which is located inside the PCI configuration space + // of the built-in PLX8111 PCIe-to-PCI bridge. + // + // So we must first locate the PCI bridge associated with our device, + // read the PECS_GPIOCTL register and return 1 if the GPIO3 bit + // has been pulled down to 0. + + uint32_t reg_val = (uint32_t) -1; + int rc = -1; + + #if defined( MBG_TGT_LINUX ) + + struct pci_dev *bridge = NULL; + + // search for any PLX PCI bridge device + while ( ( bridge = pci_get_device( PCI_VENDOR_ID_PLX, + PCI_DEVICE_ID_PLX_8111, bridge ) ) != NULL ) + { + uint8_t uc; + + #if defined( DEBUG ) + printk( KERN_INFO "%s: Found bridge: %s\n", + pcps_driver_name, pci_name( bridge ) ); + #endif + + // Read the secondary bus number. + rc = pci_read_config_byte( bridge, 0x19, &uc ); + + if ( ( rc == PCI_SUCCESS ) && ( uc == pddev->dev.cfg.bus_num ) ) + { + #if defined( DEBUG ) + printk( KERN_INFO "%s: Found bridge associated with device %s\n", + pcps_driver_name, _pcps_ddev_type_name( pddev ) ); + #endif + break; + } + } + + if ( bridge ) // associated PCI bridge has been found + { + rc = mbg_plx_read_pecs_reg( bridge, PLX_PECS_GPIOCTL, ®_val ); + + #if defined( DEBUG ) + printk( KERN_INFO "%s: Read cfg dword %04lX: %08lX, rc: %i\n", + pcps_driver_name, (ulong) PLX_PECS_GPIOCTL, (ulong) reg_val, rc ); + #endif + + // The pci_get_device() calls above has increased the use count + // for the last device which has been found, so we need to decrease + // the use count if we don't need to access the device anymore. + // This is done by calling the complementary function. + pci_dev_put( bridge ); + } + #elif defined( MBG_TGT_WIN32 ) - return (long) ( ( t2->QuadPart - t1->QuadPart ) / HNS_PER_MS ); + + // We don't scan the PCI bus to find the associated bridge device + // but just assume the card can flag when it's ready. If the card + // actually can't then the driver just waits until the maximum + // required uptime has been reached or exceeded, so there's no danger + // that the system might lock up. + rc = PCI_SUCCESS; + reg_val = 0; + + #elif defined( MBG_TGT_DOS ) + + PLX_DEVICE_NODE dn_bridge = { 0 }; + + rc = mbg_find_plx8311_bridge( pddev->dev.cfg.bus_num, &dn_bridge ); + + if ( rc == PCI_SUCCESS ) + rc = mbg_plx_read_pecs_reg( &dn_bridge, PLX_PECS_GPIOCTL, ®_val ); + #else - return 0; + #endif -} // mbg_delta_sys_time_ms + // The device can indicate when it's ready if reg_val + // has been read successfully, and the GPIO3 bit is 0. + return ( rc == PCI_SUCCESS ) && ( ( reg_val & PLX_PECS_GPIOCTL_GPIO3_DATA ) == 0 ); + +} // ptp270pex_can_flag_ready + + + +static /*HDR*/ +/** + * @brief Check if a PTP270PEX card indicates it is ready + * + * A PTP270PEX card must be accessed by the driver only + * after it has finished booting. Otherwise the host system + * may be locked up. + * + * On HW v2 cards the firmware can indicate when the card is + * ready to be accessed, so the driver can call this function + * to check this. + * + * @note The function ::ptp270pex_can_flag_ready should + * have been called before to check if the card actually + * supports this. + * + * @param[in] pddev Pointer to the device structure + * + * @return true if the card has flagged "ready" + * + * @see ::ptp270pex_can_flag_ready + */ +bool ptp270pex_has_flagged_ready( const PCPS_DDEV *pddev ) +{ + // GPIO pin USERI is pulled down to 0 by the firmware + // as soon as the card is ready to be accessed. + // With PTP270PEX HW v1 cards this pin is always 1. + + // Read the LCS_CNTRL register and return 1 if the USERI + // bit is set. + + PCPS_IO_ADDR_MAPPED cntrl_reg = _pcps_ddev_io_base_mapped( pddev, 1 ) + + PLX_LCS_CNTRL; + uint32_t reg_val = _mbg_inp32_to_cpu( pddev, 0, cntrl_reg ); + + return ( reg_val & PLX_LCS_CNTRL_USERI ) == 0; + +} // ptp270pex_has_flagged_ready +#if MBG_TGT_HAS_UPTIME + static /*HDR*/ +/** + * @brief Report the system uptime + * + * This is mainly used for debugging, and informational. + * + * @param[in] p_uptime The system uptime + * + * @see ::wait_ptp270pex_ready + * @see ::MAX_BOOT_TIME_PTP270PEX + */ void report_uptime( const MBG_SYS_UPTIME *p_uptime ) { - #if defined( MBG_TGT_LINUX ) - printk( KERN_INFO "%s: system uptime %llu jiffies -> %llu s, required %u s\n", - pcps_driver_name, (unsigned long long) ( get_jiffies_64() - INITIAL_JIFFIES ), - (unsigned long long) *p_uptime, MAX_BOOT_TIME_PTP270PEX ); - #elif defined( MBG_TGT_BSD ) - printf( "%s: system uptime %llu s, required %u s\n", - pcps_driver_name, (unsigned long long) *p_uptime, MAX_BOOT_TIME_PTP270PEX ); - #elif defined( MBG_TGT_WIN32 ) + #if defined( MBG_TGT_WIN32 ) + // Simplified code for Windows since Windows doesn't provide + // snprintf() or an equivalent function in kernel mode. WCHAR wcs_msg[120]; swprintf( wcs_msg, L"system uptime: %I64u s, required %u s", (int64_t) *p_uptime, MAX_BOOT_TIME_PTP270PEX ); - _evt_msg( GlbDriverObject, wcs_msg ); + _evt_msg_w( GlbDriverObject, wcs_msg ); + + #else + + char ws[120]; + int l = sizeof( ws ); + int n = 0; + + n += snprintf( &ws[n], l - n, "%s: system uptime ", pcps_driver_name ); + + #if defined( MBG_TGT_LINUX ) + n += snprintf( &ws[n], l - n, "%llu jiffies -> ", + (unsigned long long) ( get_jiffies_64() - INITIAL_JIFFIES ) ); + #endif + + n += snprintf( &ws[n], l - n, "%llu", (unsigned long long) *p_uptime ); + n += snprintf( &ws[n], l - n, " s, required %u s", MAX_BOOT_TIME_PTP270PEX ); + + if ( *p_uptime < MAX_BOOT_TIME_PTP270PEX ) + { + int waiting = (int) ( MAX_BOOT_TIME_PTP270PEX - *p_uptime ); + n += snprintf( &ws[n], l - n, ", waiting %i s", waiting ); + } + else + n += snprintf( &ws[n], l - n, ", OK." ); + + #if defined( MBG_TGT_LINUX ) + printk( KERN_INFO "%s\n", ws ); + #elif defined( MBG_TGT_BSD ) + printf( "%s\n", ws ); + #endif + #endif } // report_uptime +#endif // MBG_TGT_HAS_UPTIME + static /*HDR*/ -void check_uptime( void ) +/** + * @brief Wait until a PTP270PEX card is ready after power-up + * + * A PTP270PEX card must be accessed by the driver only + * after it has finished booting. Otherwise the host system + * may be locked up. + * + * @param[in] pddev Pointer to the device structure + * + * @see ::ptp270pex_can_flag_ready + * @see ::ptp270pex_has_flagged_ready + * @see ::report_uptime + * @see ::MAX_BOOT_TIME_PTP270PEX + */ +void wait_ptp270pex_ready( const PCPS_DDEV *pddev ) { - #if !defined( MBG_TGT_DOS ) - MBG_SYS_TIME t1; - MBG_SYS_TIME t2; - MBG_SYS_UPTIME uptime; - int delayed = 0; + MBG_SYS_TIME t1; + MBG_SYS_TIME t2; + MBG_SYS_UPTIME uptime; + int delayed = 0; + bool can_flag_ready; + int i = 0; - mbg_get_sys_time( &t1 ); + // A newer PTP270PEX card (HW v2.0) can indicate if it has + // finished booting and thus is ready to be accessed, but + // older PTP270PEX cards (HW v1.0) don't support this. + can_flag_ready = ptp270pex_can_flag_ready( pddev ); - for (;;) - { - mbg_get_sys_uptime( &uptime ); + mbg_get_sys_time( &t1 ); + + for (;;) + { + mbg_get_sys_uptime( &uptime ); + #if MBG_TGT_HAS_UPTIME #if !defined( DEBUG ) - if ( !delayed ) + if ( delayed ) #endif report_uptime( &uptime ); + #endif - if ( uptime == 0 ) + if ( can_flag_ready ) + { + if ( ptp270pex_has_flagged_ready( pddev ) ) + break; + } + else + { + // If the card is unable to indicate when it is ready + // and the target system doesn't support uptime + // then it makes no sense to keep looping and waiting, + // so just stop waiting and hope the card is ready. + if ( uptime == 0 || uptime == -1 ) break; // assume uptime not supported + } - if ( uptime >= MAX_BOOT_TIME_PTP270PEX ) - break; + // If the target system supports uptime then + // keep looping until the system uptime exceeds + // the max. boot time required by the card. - mbg_sleep_sec( 1 ); - delayed = 1; - } + if ( uptime >= MAX_BOOT_TIME_PTP270PEX ) + break; - if ( delayed ) - { - long dt; + mbg_sleep_sec( 1 ); + delayed = 1; - mbg_get_sys_time( &t2 ); + if ( ++i >= MAX_BOOT_TIME_PTP270PEX ) + break; + } - dt = mbg_delta_sys_time_ms( &t2, &t1 ); + if ( delayed ) + { + long dt; - #if defined( MBG_TGT_LINUX ) - printk( KERN_INFO "PTP270PEX startup delay: %li.%03li s\n", - dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); - #elif defined( MBG_TGT_BSD ) - printf( "PTP270PEX startup delay: %li.%03li s\n", - dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); - #elif defined( MBG_TGT_WIN32 ) - { - WCHAR wcs_msg[128]; - swprintf( wcs_msg, L"PTP270PEX startup delay: %li.%03li s", + mbg_get_sys_time( &t2 ); + + dt = mbg_delta_sys_time_ms( &t2, &t1 ); + + #if defined( MBG_TGT_LINUX ) + printk( KERN_INFO "PTP270PEX startup delay: %li.%03li s\n", + dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); + #elif defined( MBG_TGT_BSD ) + printf( "PTP270PEX startup delay: %li.%03li s\n", + dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); + #elif defined( MBG_TGT_WIN32 ) + { + WCHAR wcs_msg[128]; + swprintf( wcs_msg, L"PTP270PEX startup delay: %li.%03li s", dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); - _evt_msg( GlbDriverObject, wcs_msg ); - } - #endif + _evt_msg_w( GlbDriverObject, wcs_msg ); } - #endif + #else + (void) dt; + #endif + } -} // check_uptime +} // wait_ptp270pex_ready static /*HDR*/ -int pcps_check_pex_irq_unsafe( PCPS_DDEV *pddev, uint16_t req_fw_ver, - uint8_t req_asic_ver_major, uint8_t req_asic_ver_minor ) +/** + * @brief Check if IRQ usage with a device is unsafe + * + * A few early PCI Express cards had a problem where usage + * of IRQs was unsafe. Firmware upgrades are available to fix this. + * See http://www.meinberg.de/english/info/pex-upgrades.htm + * + * @param[in] pddev Pointer to the device structure + * @param[in] req_fw_ver Required firmware version + * @param[in] req_asic_ver_major Required ASIC major version + * @param[in] req_asic_ver_minor Required ASIC major version + * + * @return true if IRQ operation is unsafe + */ +bool pcps_check_pex_irq_unsafe( PCPS_DDEV *pddev, uint16_t req_fw_ver, + uint8_t req_asic_ver_major, uint8_t req_asic_ver_minor ) { - int rc = !_pcps_pex_irq_is_safe( _pcps_ddev_fw_rev_num( pddev ), req_fw_ver, + bool b = !_pcps_pex_irq_is_safe( _pcps_ddev_fw_rev_num( pddev ), req_fw_ver, _pcps_ddev_asic_version( pddev ), req_asic_ver_major, req_asic_ver_minor ); - if ( rc ) + if ( b ) { pddev->irq_stat_info |= PCPS_IRQ_STAT_UNSAFE; @@ -618,7 +1048,7 @@ int pcps_check_pex_irq_unsafe( PCPS_DDEV *pddev, uint16_t req_fw_ver, pddev->irq_ack_mask = 0; } - return rc; + return b; } // pcps_check_pex_irq_unsafe @@ -627,26 +1057,49 @@ int pcps_check_pex_irq_unsafe( PCPS_DDEV *pddev, uint16_t req_fw_ver, #if MBG_TGT_SUPP_MEM_ACC static __mbg_inline /*HDR*/ +/** + * @brief Check if a virtual address has been mapped for a device + * + * @param[in] pddev Pointer to the device structure + * + * @return true if virtual address has been mapped + */ +bool has_mapped_sys_virtual_address( PCPS_DDEV *pddev ) +{ + return pddev->mm_addr != NULL; + +} // has_mapped_sys_virtual_address + + + +static __mbg_inline /*HDR*/ +/** + * @brief Map a virtual address for a device + * + * @param[in] pddev Pointer to the device structure + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ int map_sys_virtual_address( PCPS_DDEV *pddev ) { pddev->mm_tstamp_addr = NULL; // unless configured below - #if defined ( MBG_TGT_WIN32 ) + #if defined( MBG_TGT_WIN32 ) { PHYSICAL_ADDRESS pAD; pAD.QuadPart = pddev->rsrc_info.mem[0].start; pddev->mm_addr = MmMapIoSpace( pAD, sizeof( *pddev->mm_addr ), MmNonCached ); } - #elif defined ( MBG_TGT_LINUX ) + #elif defined( MBG_TGT_LINUX ) pddev->mm_addr = ioremap( ( (ulong) pddev->rsrc_info.mem[0].start ), sizeof( *pddev->mm_addr ) ); - #elif defined ( MBG_TGT_FREEBSD ) + #elif defined( MBG_TGT_FREEBSD ) pddev->mm_addr = rman_get_virtual( pddev->rsrc_info.mem[0].bsd.res ); - #elif defined ( MBG_TGT_NETBSD ) + #elif defined( MBG_TGT_NETBSD ) pddev->mm_addr = bus_space_vaddr( pddev->rsrc_info.mem[0].bsd.bst, pddev->rsrc_info.mem[0].bsd.bsh ); @@ -657,7 +1110,11 @@ int map_sys_virtual_address( PCPS_DDEV *pddev ) #endif // target specific code if ( pddev->mm_addr == NULL ) + { + _mbgddmsg_2( MBG_DBG_ERR, "%s: %s Failed to map virtual address", + pcps_driver_name, _pcps_ddev_type_name( pddev ) ); return -1; + } if ( _pcps_ddev_is_pci_mbgpex( pddev ) ) pddev->mm_tstamp_addr = &pddev->mm_addr->mbgpex.tstamp; @@ -665,24 +1122,32 @@ int map_sys_virtual_address( PCPS_DDEV *pddev ) if ( _pcps_ddev_is_pci_pex8311( pddev ) ) pddev->mm_tstamp_addr = &pddev->mm_addr->pex8311.tstamp; +#if 0 && defined( DEBUG ) // ### TODO _mbgddmsg_3( MBG_DBG_INIT_DEV, "MM addr: base: 0x%p, tstamp: 0x%p, offs: 0x%02lX", pddev->mm_addr, pddev->mm_tstamp_addr, - (ulong) pddev->mm_tstamp_addr - (ulong) pddev->mm_addr ); + (ulong) ( (uint8_t *) pddev->mm_tstamp_addr - (uint8_t *) pddev->mm_addr ) ); +#endif - return 0; + return MBG_SUCCESS; } // map_sys_virtual_address static __mbg_inline /*HDR*/ +/** + * @brief Unmap a virtual address for a device, if it has been mapped before + * + * @param[in] pddev Pointer to the device structure + */ void unmap_sys_virtual_address( PCPS_DDEV *pddev ) { - if ( pddev->mm_addr ) + + if ( has_mapped_sys_virtual_address( pddev ) ) { - #if defined ( MBG_TGT_WIN32 ) + #if defined( MBG_TGT_WIN32 ) MmUnmapIoSpace( pddev->mm_addr, sizeof( *pddev->mm_addr ) ); - #elif defined ( MBG_TGT_LINUX ) + #elif defined( MBG_TGT_LINUX ) iounmap( pddev->mm_addr ); #else // DOS, ... // nothing to do @@ -698,13 +1163,221 @@ void unmap_sys_virtual_address( PCPS_DDEV *pddev ) +#if ( DEBUG_ACCESS_TIMING || DEBUG_IO_TIMING ) + +#if ( 1 && defined( MBG_TGT_LINUX ) && defined( MBG_ARCH_X86 ) ) + #define DEBUG_PRINT_ACCESS_TIMES 1 +#else + #define DEBUG_PRINT_ACCESS_TIMES 0 +#endif + + +#if DEBUG_PRINT_ACCESS_TIMES + +static __mbg_inline /*HDR*/ +/** + * @brief Convert TSC cycles to picoseconds + * + * @note This has not yet been implemented for all target systems. + * + * A specific cycles frequency has to be provided by the target OS. + * + * @param[in] cyc The number of TSC cycles + * + * @return the computed number of picoseconds + */ +long long _cyc_to_ps( long long cyc ) +{ + cyc *= 1000000000UL; + + #if defined( MBG_TGT_LINUX ) + // The variable cpu_khz is exported by the kernel, and the + // do_div() function needs to be used in kernel space + // for the division. + do_div( cyc, cpu_khz ); + #else + cyc = 0; //### TODO FIXME for different targets + #endif + + return cyc; +} + +#endif // DEBUG_PRINT_ACCESS_TIMES + +#endif // ( DEBUG_ACCESS_TIMING || DEBUG_IO_TIMING ) + + + +#if DEBUG_ACCESS_TIMING + +static uint32_t debug_dummy_var; + +static /*HDR*/ +/** + * @brief Report access timing for a device + * + * This is only used for testing. + * + * @param[in] pddev Pointer to the device structure + * @param[in] info Informational string to be printed + * @param[in] t_after_cmd Cycles value taken after command code has been written + * @param[in] t_after_reread Cycles value taken after a data word has been re-read + */ +void report_access_timing( const PCPS_DDEV *pddev, const char *info, + MBG_PC_CYCLES t_after_cmd, MBG_PC_CYCLES t_after_reread ) +{ + #if defined( MBG_TGT_LINUX ) + long long delta_cyc_write = t_after_cmd - pddev->acc_cycles; + long long delta_cyc_read = t_after_reread - t_after_cmd; + + #if DEBUG_PRINT_ACCESS_TIMES + long long delta_t_write = _cyc_to_ps( delta_cyc_write ); + long long delta_t_read = _cyc_to_ps( delta_cyc_read ); + #endif + + printk( KERN_INFO "%s %s: %lli/%lli cyc" + #if DEBUG_PRINT_ACCESS_TIMES + ", %lli/%lli ps @ %lu kHz" + #endif + "\n", + _pcps_ddev_type_name( pddev ), info, + delta_cyc_write, delta_cyc_read + #if DEBUG_PRINT_ACCESS_TIMES + , delta_t_write, delta_t_read, (ulong) cpu_khz + #endif + ); + #endif + +} // report_access_timing + +#endif // DEBUG_ACCESS_TIMING + + + +#if DEBUG_IO_TIMING + +static /*HDR*/ +/** + * @brief Report I/O timing for a device + * + * This is only used for testing. + * + * @param[in] pddev Pointer to the device structure + * @param[in] info Informational string to be printed + * @param[in] cmd The command by tent to the device + * @param[in] count The number of bytes read from the device + * @param[in] t_after_cmd Cycles value taken after command code has been written + * @param[in] t_after_busy Cycles value taken after busy flag was cleard by the device + * @param[in] t_done Cycles value taken after bytes have been read + */ +void report_io_timing( const PCPS_DDEV *pddev, const char *info, + uint8_t cmd, uint16_t count, MBG_PC_CYCLES t_after_cmd, + MBG_PC_CYCLES t_after_busy, MBG_PC_CYCLES t_done ) +{ + #if defined( MBG_TGT_LINUX ) //##++++ TODO support other OSs + long long cmd_cycles = t_after_cmd - pddev->acc_cycles; + long long busy_cycles = t_after_busy - t_after_cmd; + long long read_cycles = t_done - t_after_busy; + long long cycles_per_read = 0; + + #if DEBUG_PRINT_ACCESS_TIMES + long long cmd_time = _cyc_to_ps( cmd_cycles ); + long long busy_time = _cyc_to_ps( busy_cycles ); + long long read_time = _cyc_to_ps( read_cycles ); + long long time_per_read = 0; + #endif + + if ( count ) + { + cycles_per_read = read_cycles; + do_div( cycles_per_read, count ); + + #if DEBUG_PRINT_ACCESS_TIMES + time_per_read = read_time; + do_div( time_per_read, count ); + #endif + } + + printk( KERN_INFO "%s %s cmd: 0x%02X (%u bytes), " + "write %lli cyc, busy: %lli cyc, read: %lli/%lli cyc" + #if DEBUG_PRINT_ACCESS_TIMES + ",\n write %lli ps, busy: %lli ps, read: %lli/%lli ps @ %lu kHz" + #endif + "\n", + _pcps_ddev_type_name( pddev ), info, cmd, count, + cmd_cycles, busy_cycles, read_cycles, cycles_per_read + #if DEBUG_PRINT_ACCESS_TIMES + , cmd_time, busy_time, read_time, time_per_read, (ulong) cpu_khz + #endif + ); + printk( KERN_ERR "cycles after cmd: %lli, after busy: %lli, when done: %lli\n", + (long long) t_after_cmd, + (long long) t_after_busy, + (long long) t_done ); + + #endif + +} // report_io_timing + +#endif // DEBUG_IO_TIMING + + + +#if DEBUG_USB_IO + +// This is the prototype of the standard usb_bulk_msg() prototype +// provided by the Linux kernel. We include it here to make sure +// our debug wrapper function usb_bulk_msg_dbg() has the same +// prototype, otherwise we'd expect a compiler warning. + +int usb_bulk_msg( struct usb_device *usb_dev, + unsigned int pipe, + void *data, + int len, + int *actual_length, + int timeout ); + + + /*HDR*/ //### TODO Do we need a prototype? +int usb_bulk_msg_dbg( struct usb_device *usb_dev, + unsigned int pipe, + void *data, + int len, + int *actual_length, + int timeout ) +{ + int rc = usb_bulk_msg( usb_dev, pipe, data, len, actual_length, timeout ); + + _mbgddmsg_6( MBG_DBG_ERR, "usb_bulk_msg: pipe %u, data %p, len %i, actual_len %i, timeout %i: returned %i", + pipe, data, len, *actual_length, timeout, rc ); + + return rc; + +} // usb_bulk_msg_dbg + +#endif // DEBUG_USB_IO + + + #if defined( __GNUC__ ) // Avoid "no previous prototype" with some gcc versions. __mbg_inline -int pcps_wait_busy( PCPS_DDEV *pddev ) __attribute__((always_inline)); +int pcps_wait_busy( PCPS_DDEV *pddev ); #endif __mbg_inline /*HDR*/ +/** + * @brief Wait as long as a device is busy, or until timeout + * + * Used by the @ref pcps_read_fncs to wait after the command byte has been + * written until the requested data has been made available by the device. + * + * @param[in] pddev Pointer to the device structure + * + * @return ::MBG_SUCCESS on success, or ::MBG_ERR_TIMEOUT + * + * @see @ref pcps_read_fncs + */ int pcps_wait_busy( PCPS_DDEV *pddev ) { if ( _pcps_ddev_status_busy( pddev ) ) @@ -740,56 +1413,81 @@ int pcps_wait_busy( PCPS_DDEV *pddev ) #endif } - return 0; + return MBG_SUCCESS; } // pcps_wait_busy -/*-------------------------------------------------------------- - * Name: pcps_read_null() - * pcps_read_std() - * pcps_read_amcc_s5933() - * pcps_read_amcc_s5920() - * pcps_read_asic() - * pcps_read_usb() - * - * Purpose: These functions are used for low level access - * to Meinberg plug-in devices. The function - * to be used depends on the clock's bus type and - * interface chip. - * - * Input: pcfg pointer to the clock's configuration - * cmd the command code for the board - * count the number of bytes to be read - * - * Output: buffer the bytes that could be read - * - * Ret value: MBG_SUCCESS no error - * MBG_ERR_TIMEOUT board is busy for too long - *-------------------------------------------------------------*/ +/** + * @defgroup pcps_read_fncs Device read functions + * + * These group of functions is used for low level access to Meinberg + * bus-level devices. Which of the function is actually to be used + * depends on the device's bus type and interface chip and is determined + * by the function ::pcps_probe_device which is called at device startup. + * + * @see ::pcps_read_null + * @see ::pcps_read_std + * @see ::pcps_read_amcc_s5933 + * @see ::pcps_read_amcc_s5920 + * @see ::pcps_read_asic + * @see ::pcps_read_usb + * + * @{ */ -// The dummy read function below is used if a clock is -// not properly initialized, in order to avoid I/O access -// on unspecified ports. -static /*HDR*/ /* PCPS_READ_FNC */ -short pcps_read_null( PCPS_DDEV *pddev, uint8_t cmd, - void FAR *buffer, uint16_t count ) +static /*HDR*/ +/** + * @brief Dummy read function + * + * Used if a clock is not properly initialized, in order to + * avoid I/O access on unspecified ports. + * + * @param[in] pddev Pointer to the device structure + * @param[in] cmd The command code for the board, see @ref PCPS_CMD_CODES + * @param[out] buffer A buffer to take the bytes to be read + * @param[in] count The number of bytes to be read into the buffer + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup pcps_read_fncs + * @see @ref pcps_read_fncs + */ +int pcps_read_null( PCPS_DDEV *pddev, uint8_t cmd, + void FAR *buffer, uint16_t count ) { + // avoid compiler warnings + (void) pddev; + (void) cmd; + (void) buffer; + (void) count; return MBG_ERR_TIMEOUT; } // pcps_read_null +#if !defined( AVOID_REDUNDANT_REDECLARATION ) + PCPS_READ_FNC pcps_read_null; +#endif -// The function below must be used to access a clock with -// standard ISA or micro channel bus. - -static /*HDR*/ /* PCPS_READ_FNC */ -short pcps_read_std( PCPS_DDEV *pddev, uint8_t cmd, - void FAR *buffer, uint16_t count ) +static /*HDR*/ +/** + * @brief Read function for devices with ISA or micro channel bus + * + * @param[in] pddev Pointer to the device structure + * @param[in] cmd The command code for the board, see @ref PCPS_CMD_CODES + * @param[out] buffer A buffer to take the bytes to be read + * @param[in] count The number of bytes to be read into the buffer + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup pcps_read_fncs + * @see @ref pcps_read_fncs + */ +int pcps_read_std( PCPS_DDEV *pddev, uint8_t cmd, + void FAR *buffer, uint16_t count ) { uint8_t FAR *p = (uint8_t FAR *) buffer; PCPS_IO_ADDR_MAPPED port = _pcps_ddev_io_base_mapped( pddev, 0 ); @@ -825,18 +1523,31 @@ short pcps_read_std( PCPS_DDEV *pddev, uint8_t cmd, return MBG_SUCCESS; -} // pcps_read_std +} // pcps_read_std +#if !defined( AVOID_REDUNDANT_REDECLARATION ) + PCPS_READ_FNC pcps_read_std; +#endif #if _PCPS_USE_PCI -// The function below must be used to access a clock with -// PCI bus and AMCC S5933 interface chip. - -static /*HDR*/ /* PCPS_READ_FNC */ -short pcps_read_amcc_s5933( PCPS_DDEV *pddev, uint8_t cmd, - void FAR *buffer, uint16_t count ) +static /*HDR*/ +/** + * @brief Read function for devices with AMCC S5933 PCI interface chip + * + * @param[in] pddev Pointer to the device structure + * @param[in] cmd The command code for the board, see @ref PCPS_CMD_CODES + * @param[out] buffer A buffer to take the bytes to be read + * @param[in] count The number of bytes to be read into the buffer + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup pcps_read_fncs + * @see @ref pcps_read_fncs + */ +int pcps_read_amcc_s5933( PCPS_DDEV *pddev, uint8_t cmd, + void FAR *buffer, uint16_t count ) { uint8_t FAR *p = (uint8_t FAR *) buffer; PCPS_IO_ADDR_MAPPED port = _pcps_ddev_io_base_mapped( pddev, 0 ); @@ -886,7 +1597,11 @@ short pcps_read_amcc_s5933( PCPS_DDEV *pddev, uint8_t cmd, return MBG_SUCCESS; -} /* pcps_read_amcc_s5933 */ +} // pcps_read_amcc_s5933 + +#if !defined( AVOID_REDUNDANT_REDECLARATION ) + PCPS_READ_FNC pcps_read_amcc_s5933; +#endif #endif /* _PCPS_USE_PCI */ @@ -894,12 +1609,22 @@ short pcps_read_amcc_s5933( PCPS_DDEV *pddev, uint8_t cmd, #if _PCPS_USE_PCI -// The function below must be used to access a clock with -// PCI bus and AMCC S5920 interface chip. - -static /*HDR*/ /* PCPS_READ_FNC */ -short pcps_read_amcc_s5920( PCPS_DDEV *pddev, uint8_t cmd, - void FAR *buffer, uint16_t count ) +static /*HDR*/ +/** + * @brief Read function for devices with AMCC S5920 PCI interface chip + * + * @param[in] pddev Pointer to the device structure + * @param[in] cmd The command code for the board, see @ref PCPS_CMD_CODES + * @param[out] buffer A buffer to take the bytes to be read + * @param[in] count The number of bytes to be read into the buffer + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup pcps_read_fncs + * @see @ref pcps_read_fncs + */ +int pcps_read_amcc_s5920( PCPS_DDEV *pddev, uint8_t cmd, + void FAR *buffer, uint16_t count ) { uint8_t FAR *p = (uint8_t FAR *) buffer; PCPS_IO_ADDR_MAPPED data_port = _pcps_ddev_io_base_mapped( pddev, 1 ); @@ -977,19 +1702,35 @@ short pcps_read_amcc_s5920( PCPS_DDEV *pddev, uint8_t cmd, } // pcps_read_amcc_s5920 +#if !defined( AVOID_REDUNDANT_REDECLARATION ) + PCPS_READ_FNC pcps_read_amcc_s5920; +#endif + #endif /* _PCPS_USE_PCI */ #if _PCPS_USE_PCI -// The function below must be used to access a clock with -// PCI bus and Meinberg PCI interface ASIC. - -static /*HDR*/ /* PCPS_READ_FNC */ -short pcps_read_asic( PCPS_DDEV *pddev, uint8_t cmd, - void FAR *buffer, uint16_t count ) +static /*HDR*/ +/** + * @brief Read function for devices with Meinberg PCI interface ASIC + * + * @param[in] pddev Pointer to the device structure + * @param[in] cmd The command code for the board, see @ref PCPS_CMD_CODES + * @param[out] buffer A buffer to take the bytes to be read + * @param[in] count The number of bytes to be read into the buffer + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup pcps_read_fncs + * @see ::pcps_read_asic_mm + * @see @ref pcps_read_fncs + */ +int pcps_read_asic( PCPS_DDEV *pddev, uint8_t cmd, + void FAR *buffer, uint16_t count ) { + short ret_val = MBG_SUCCESS; uint8_t FAR *p = (uint8_t FAR *) buffer; PCPS_IO_ADDR_MAPPED data_port; PCI_ASIC_REG ar; @@ -997,18 +1738,42 @@ short pcps_read_asic( PCPS_DDEV *pddev, uint8_t cmd, int dt_quot; int dt_rem; _pcps_irq_flags + #if DEBUG_ACCESS_TIMING || DEBUG_IO_TIMING + MBG_PC_CYCLES t_after_cmd = 0; + #endif + #if DEBUG_ACCESS_TIMING + MBG_PC_CYCLES t_after_reread = 0; + #endif + + #if DEBUG_IO_TIMING + MBG_PC_CYCLES t_after_busy = 0; + MBG_PC_CYCLES t_done = 0; + #endif #if DEBUG_IO - _mbgddmsg_3( MBG_DBG_INIT_DEV, "pcps_read_asic: cmd: 0x%02X (0x%08X), cnt: %u", + _mbgddmsg_3( MBG_DBG_INIT_DEV, "pcps_read_asic: cmd: 0x%02X (0x%08X), cnt: %u", cmd, _cpu_to_mbg32( cmd ), count ); #endif _pcps_disb_local_irq_save(); + + // get current cycles and write the command byte mbg_get_pc_cycles( &pddev->acc_cycles ); - // write the command byte _mbg_outp32( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 ) + offsetof( PCI_ASIC, pci_data ), cmd ); + + #if DEBUG_ACCESS_TIMING || DEBUG_IO_TIMING + mbg_get_pc_cycles( &t_after_cmd ); + #endif + + #if DEBUG_ACCESS_TIMING + debug_dummy_var = _mbg_inp32_to_cpu( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 ) + + offsetof( PCI_ASIC, addon_data ) ); + mbg_get_pc_cycles( &t_after_reread ); + #endif + + _pcps_local_irq_restore(); data_port = _pcps_ddev_io_base_mapped( pddev, 0 ) @@ -1018,9 +1783,19 @@ short pcps_read_asic( PCPS_DDEV *pddev, uint8_t cmd, // wait until BUSY flag goes low or timeout if ( pcps_wait_busy( pddev ) < 0 ) - return MBG_ERR_TIMEOUT; + { + #if DEBUG_IO_TIMING + mbg_get_pc_cycles( &t_after_busy ); + #endif + ret_val = MBG_ERR_TIMEOUT; + goto done; + } + #if DEBUG_IO_TIMING + mbg_get_pc_cycles( &t_after_busy ); + #endif + // no timeout: read bytes from the board's FIFO // first read full 32 bit words @@ -1050,21 +1825,190 @@ short pcps_read_asic( PCPS_DDEV *pddev, uint8_t cmd, } } - return MBG_SUCCESS; +done: + #if DEBUG_IO_TIMING + mbg_get_pc_cycles( &t_done ); + report_io_timing( pddev, "ASIC", cmd, count, t_after_cmd, t_after_busy, t_done ); + #endif + + #if DEBUG_ACCESS_TIMING + report_access_timing( pddev, "ASIC wr/rd", t_after_cmd, t_after_reread ); + #endif + + return ret_val; } // pcps_read_asic -#endif /* _PCPS_USE_PCI */ +#if !defined( AVOID_REDUNDANT_REDECLARATION ) + PCPS_READ_FNC pcps_read_asic; +#endif +#if _PCPS_USE_MM_IO -#if _PCPS_USE_USB +static /*HDR*/ +/** + * @brief Read function for devices with Meinberg PCI interface ASIC + * + * Unlike ::pcps_read_asic and most of the other read functions, + * this function accesses the memory mapped registers rather than + * the I/O ports, so this is significantly faster. + * + * @param[in] pddev Pointer to the device structure + * @param[in] cmd The command code for the board, see @ref PCPS_CMD_CODES + * @param[out] buffer A buffer to take the bytes to be read + * @param[in] count The number of bytes to be read into the buffer + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup pcps_read_fncs + * @see ::pcps_read_asic + * @see @ref pcps_read_fncs + */ +int pcps_read_asic_mm( PCPS_DDEV *pddev, uint8_t cmd, + void FAR *buffer, uint16_t count ) +{ + short ret_val = MBG_SUCCESS; + uint8_t FAR *p = (uint8_t FAR *) buffer; + volatile uint32_t *p_data_reg; + PCI_ASIC_REG ar; + int i; + int dt_quot; + int dt_rem; + _pcps_irq_flags + + #if DEBUG_ACCESS_TIMING || DEBUG_IO_TIMING + MBG_PC_CYCLES t_after_cmd = 0; + #endif + + #if DEBUG_ACCESS_TIMING + MBG_PC_CYCLES t_after_reread = 0; + #endif + + #if DEBUG_IO_TIMING + MBG_PC_CYCLES t_after_busy = 0; + MBG_PC_CYCLES t_done = 0; + #endif + + #if DEBUG_IO + _mbgddmsg_3( MBG_DBG_INIT_DEV, "pcps_read_asic_mm: cmd: 0x%02X (0x%08X), cnt: %u", + cmd, _cpu_to_mbg32( cmd ), count ); + #endif + + _pcps_disb_local_irq_save(); + + // get current cycles and write the command byte + #if USE_CMD_PTR + { + volatile uint32_t *p_cmd_reg = &pddev->mm_addr->mbgpex.asic.pci_data.ul; + mbg_get_pc_cycles( &pddev->acc_cycles ); + *p_cmd_reg = cmd; + } + #else + mbg_get_pc_cycles( &pddev->acc_cycles ); + pddev->mm_addr->mbgpex.asic.pci_data.ul = cmd; + #endif + + #if DEBUG_ACCESS_TIMING || DEBUG_IO_TIMING + mbg_get_pc_cycles( &t_after_cmd ); + #endif + + #if DEBUG_ACCESS_TIMING + debug_dummy_var = pddev->mm_addr->mbgpex.asic.pci_data.ul; + mbg_get_pc_cycles( &t_after_reread ); + #endif + + _pcps_local_irq_restore(); + + p_data_reg = &pddev->mm_addr->mbgpex.asic.addon_data.ul[0]; + dt_quot = count / 4; + dt_rem = count % 4; + + // wait until BUSY flag goes low or timeout + if ( pcps_wait_busy( pddev ) < 0 ) + { + #if DEBUG_IO_TIMING + mbg_get_pc_cycles( &t_after_busy ); + #endif + ret_val = MBG_ERR_TIMEOUT; + goto done; + } + + + #if DEBUG_IO_TIMING + mbg_get_pc_cycles( &t_after_busy ); + #endif + + // no timeout: read bytes from the board's FIFO -// The function below must be used to access a device connected via USB. + // first read full 32 bit words + for ( i = 0; i < dt_quot; i++ ) + { + ar.ul = *p_data_reg; + #if DEBUG_IO + _mbgddmsg_1( MBG_DBG_INIT_DEV, "pcps_read_asic_mm: %08X", ar.ul ); + #endif + _mbg_put_unaligned( ar.ul, (uint32_t FAR *) p ); + p += sizeof( ar.ul ); + p_data_reg++; + } + + // then read the remaining bytes, if required + if ( dt_rem ) + { + ar.ul = *p_data_reg; + + for ( i = 0; i < dt_rem; i++ ) + { + #if DEBUG_IO + #endif + + *p++ = ar.b[i]; + } + } + +done: + #if DEBUG_IO_TIMING + mbg_get_pc_cycles( &t_done ); + report_io_timing( pddev, "ASIC MM", cmd, count, t_after_cmd, t_after_busy, t_done ); + #endif + + #if DEBUG_ACCESS_TIMING + report_access_timing( pddev, "ASIC MM wr/rd", t_after_cmd, t_after_reread ); + #endif + + return ret_val; + +} // pcps_read_asic_mm -static /*HDR*/ /* PCPS_READ_FNC */ -short pcps_read_usb( PCPS_DDEV *pddev, uint8_t cmd, - void FAR *buffer, uint16_t count ) +#if !defined( AVOID_REDUNDANT_REDECLARATION ) + PCPS_READ_FNC pcps_read_asic_mm; +#endif + +#endif // _PCPS_USE_MM_IO + +#endif // _PCPS_USE_PCI + + + +#if _PCPS_USE_USB + +static /*HDR*/ +/** + * @brief Read function for USB devices + * + * @param[in] pddev Pointer to the device structure + * @param[in] cmd The command code for the board, see @ref PCPS_CMD_CODES + * @param[out] buffer A buffer to take the bytes to be read + * @param[in] count The number of bytes to be read into the buffer + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + * + * @ingroup pcps_read_fncs + * @see @ref pcps_read_fncs + */ +int pcps_read_usb( PCPS_DDEV *pddev, uint8_t cmd, + void FAR *buffer, uint16_t count ) { int actual_count = 0; short rc; @@ -1073,19 +2017,44 @@ short pcps_read_usb( PCPS_DDEV *pddev, uint8_t cmd, rc = _pcps_usb_write_var( pddev, &cmd ); - if ( ( rc == MBG_SUCCESS ) && ( count && buffer ) ) + #if DEBUG_USB_IO + if ( rc == 0 ) + _mbgddmsg_4( MBG_DBG_INFO, "%s: %s _pcps_usb_write_var cmd 0x%02X, %i bytes: succeeded", + pcps_driver_name, _pcps_ddev_type_name( pddev ), cmd, actual_count ); + else + _mbgddmsg_5( MBG_DBG_ERR, "%s: %s _pcps_usb_write_var cmd 0x%02X, %i bytes: failed with rc %i", + pcps_driver_name, _pcps_ddev_type_name( pddev ), cmd, actual_count, rc ); + #endif // DEBUG_USB_IO + + if ( ( rc == 0 ) && ( count && buffer ) ) { #if defined( MBG_TGT_WIN32_PNP ) - int temp_fn1 = frame_number_1; - int temp_fn2 = frame_number_2; + #if USE_USB_MICRO_FRAMES + int temp_fn1 = micro_frame_number_1 ? micro_frame_number_1 : frame_number_1; + int temp_fn2 = micro_frame_number_2 ? micro_frame_number_2 : frame_number_2; + #else + int temp_fn1 = frame_number_1; + int temp_fn2 = frame_number_2; + #endif + LARGE_INTEGER UsbPreCount = Count1; LARGE_INTEGER UsbPostCount = Count2; #endif rc = _pcps_usb_read( pddev, buffer, count ); + #if DEBUG_USB_IO + if ( rc == 0 ) + _mbgddmsg_4( MBG_DBG_INFO, "%s: %s _pcps_usb_read after cmd 0x%02X succeeded, bytes read: %i", + pcps_driver_name, _pcps_ddev_type_name( pddev ), cmd, actual_count ); + else + _mbgddmsg_5( MBG_DBG_ERR, "%s: %s _pcps_usb_read after cmd 0x%02X failed after with rc %i, bytes read: %i", + pcps_driver_name, _pcps_ddev_type_name( pddev ), cmd, rc, actual_count ); + #endif // DEBUG_USB_IO + #if defined( MBG_TGT_WIN32_PNP ) - if ( cmd == PCPS_GIVE_HR_TIME && rc == PCPS_SUCCESS ) + + if ( cmd == PCPS_GIVE_HR_TIME && rc == 0 ) { ULONGLONG usb_latency_cycles; ULONGLONG cycles_diff; @@ -1093,6 +2062,7 @@ short pcps_read_usb( PCPS_DDEV *pddev, uint8_t cmd, ULONGLONG frame_length_cycles; int FrameNumberDiff; + #if !USE_USB_MICRO_FRAMES if ( pddev->usb_20_mode ) { // USB 2.0 microframe timing. @@ -1101,6 +2071,7 @@ short pcps_read_usb( PCPS_DDEV *pddev, uint8_t cmd, usb_latency_cycles = ( (ULONGLONG) PerfFreq.QuadPart ) / 20000UL; // represents 50 us } else + #endif { // USB 1.1 mode with millisecond timing. // Compensate latency to millisecond frame boundaries. @@ -1111,12 +2082,20 @@ short pcps_read_usb( PCPS_DDEV *pddev, uint8_t cmd, FrameNumberDiff = temp_fn2 - temp_fn1; cycles_diff = (ULONGLONG) ( UsbPostCount.QuadPart - UsbPreCount.QuadPart ); - frame_length_cycles = (ULONGLONG) ( (ULONGLONG) PerfFreq.QuadPart ) / 1000UL; + + #if USE_USB_MICRO_FRAMES + if ( micro_frame_number_1 > 0 || micro_frame_number_2 > 0 ) + frame_length_cycles = (ULONGLONG) ( (ULONGLONG) PerfFreq.QuadPart ) / 8000UL; + else + frame_length_cycles = (ULONGLONG) ( (ULONGLONG) PerfFreq.QuadPart ) / 1000UL; + #else + frame_length_cycles = (ULONGLONG) ( (ULONGLONG) PerfFreq.QuadPart ) / 1000UL; + #endif if ( ( temp_fn1 == 0 ) && ( temp_fn2 == 0 ) ) { if ( cycles_diff > frame_length_cycles ) - usb_latency_cycles = cycles_diff - frame_length_cycles; + usb_latency_cycles = cycles_diff - frame_length_cycles; else usb_latency_cycles = frame_length_cycles - cycles_diff; } @@ -1126,7 +2105,7 @@ short pcps_read_usb( PCPS_DDEV *pddev, uint8_t cmd, #if defined( DEBUG ) swprintf( pddev->wcs_msg, L"FD %d CD %I64u l %I64u fl %I64u", FrameNumberDiff, cycles_diff, usb_latency_cycles, frame_length_cycles ); - _dbg_evt_msg( GlbDriverObject, pddev->wcs_msg ); + _dbg_evt_msg_w( GlbDriverObject, pddev->wcs_msg ); #endif } @@ -1139,36 +2118,38 @@ short pcps_read_usb( PCPS_DDEV *pddev, uint8_t cmd, } // pcps_read_usb +#if !defined( AVOID_REDUNDANT_REDECLARATION ) + PCPS_READ_FNC pcps_read_usb; #endif +#endif // _PCPS_USE_USB +/** @} defgroup group_pcps_read_fnc */ -/*-------------------------------------------------------------- - * Name: pcps_write() - * - * Purpose: Write data to a device. + + +/*HDR*/ +/** + * @brief Write data to a device * - * Input: pddev pointer to the device information - * cmd the address of buffer holding the - * date/time/status information - * read_fnc function to access the board + * @param[in] pddev Pointer to the device structure + * @param[in] cmd The command code for the board, see @ref PCPS_CMD_CODES + * @param[in] buffer A buffer with data to be written according to the cmd code + * @param[in] count The number of bytes to be written according to the cmd code * - * Output: -- + * @return ::MBG_SUCCESS on success, + * ::MBG_ERR_TIMEOUT if device didn't respond in time, + * ::MBG_ERR_NBYTES if the number of parameter bytes did not match + * the number of data bytes expected by the device, + * or one of the other @ref MBG_RETURN_CODES * - * Ret value: MBG_SUCCESS no error - * MBG_ERR_TIMEOUT board is busy for too long - * MBG_ERR_NBYTES the number of parameter bytes - * did not match the number of - * data bytes expected - * MBG_ERR_STIME the date, time or status - * has been invalid - *-------------------------------------------------------------*/ - -/*HDR*/ /* PCPS_WRITE_FNC */ -short pcps_write( PCPS_DDEV *pddev, uint8_t cmd, - const void FAR *buffer, uint16_t count ) + * @ingroup pcps_io_fncs + * @see @ref pcps_io_fncs + */ +int pcps_write( PCPS_DDEV *pddev, uint8_t cmd, + const void FAR *buffer, uint16_t count ) { - short rc; + int rc; #if _PCPS_USE_USB if ( _pcps_ddev_is_usb( pddev ) ) @@ -1262,46 +2243,59 @@ done: } // pcps_write +#if !defined( AVOID_REDUNDANT_REDECLARATION ) + PCPS_WRITE_FNC pcps_write; +#endif -/*-------------------------------------------------------------- - * Name: pcps_generic_io() - * - * Purpose: Write data to and/or read data from a device. + +/*HDR*/ +/** + * @brief Generic I/O function * - * Input: pddev pointer to the device information - * cmd the address of buffer holding the - * date/time/status information - * read_fnc function to access the board + * @param[in] pddev Pointer to the device structure + * @param[in] type The type of data to be read/written, see @ref PCPS_CMD_CODES + * @param[in] in_buff A buffer with data to be written according to the type code + * @param[in] in_cnt The number of bytes to be written according to the type code + * @param[out] out_buff A buffer with data to be read according to the type code + * @param[in] out_cnt The number of bytes to be read according to the type code * - * Output: -- + * @return ::MBG_SUCCESS on success, + * ::MBG_ERR_TIMEOUT if device didn't respond in time, + * ::MBG_ERR_NBYTES if the number of parameter bytes did not match + * the number of data bytes expected by the device, + * or one of the other @ref MBG_RETURN_CODES * - * Ret value: MBG_SUCCESS no error - * MBG_ERR_TIMEOUT board is busy for too long - * MBG_ERR_NBYTES the number of parameter bytes - * did not match the number of - * data bytes expected - * MBG_ERR_STIME the date, time or status - * has been invalid - *-------------------------------------------------------------*/ - -/*HDR*/ -short pcps_generic_io( PCPS_DDEV *pddev, uint8_t type, - const void FAR *in_buff, uint8_t in_cnt, - void FAR *out_buff, uint8_t out_cnt ) + * @ingroup pcps_io_fncs + * @see @ref pcps_io_fncs + */ +int pcps_generic_io( PCPS_DDEV *pddev, uint8_t type, + const void FAR *in_buff, uint8_t in_cnt, + void FAR *out_buff, uint8_t out_cnt ) { const uint8_t FAR *p; int i; - short rc; + int rc; uint8_t tmp_byte; int8_t data_read[PCPS_FIFO_SIZE]; uint8_t bytes_to_read; + #if DEBUG_IO + #if defined( MBG_TGT_DOS ) + #define FP_FMT "%Fp" + #else + #define FP_FMT "%p" + #endif + _mbgddmsg_5( MBG_DBG_DETAIL, "pcps_generic_io: type 0x%02X, in_buff: " FP_FMT + " (%u), out_buf " FP_FMT " (%u)", + type, in_buff, in_cnt, out_buff, out_cnt ); + #endif + // Write the command and read one byte which will contain // the number of data bytes that must follow. rc = _pcps_read_var( pddev, PCPS_GENERIC_IO, tmp_byte ); - if ( rc < 0 ) + if ( mbg_rc_is_error( rc ) ) return rc; @@ -1310,16 +2304,21 @@ short pcps_generic_io( PCPS_DDEV *pddev, uint8_t type, return MBG_ERR_NBYTES; + #if DEBUG_IO + _mbgddmsg_3( MBG_DBG_DETAIL, "pcps_generic_io: going to write type 0x%02X, in_sz %i, out_sz %i", + type, in_cnt, out_cnt ); + #endif + // Write the 3 bytes which are expected: rc = _pcps_write_byte( pddev, type ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto done; rc = _pcps_write_byte( pddev, in_cnt ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto done; @@ -1329,11 +2328,15 @@ short pcps_generic_io( PCPS_DDEV *pddev, uint8_t type, { rc = _pcps_write_byte( pddev, out_cnt ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) goto done; // Write the input parameters + #if DEBUG_IO + _mbgddmsg_0( MBG_DBG_DETAIL, "pcps_generic_io: going to write input bytes" ); + #endif + p = (const uint8_t FAR *) in_buff; tmp_byte = in_cnt - 1; @@ -1341,7 +2344,7 @@ short pcps_generic_io( PCPS_DDEV *pddev, uint8_t type, { rc = _pcps_write_byte( pddev, *p++ ); - if ( rc < 0 ) + if ( mbg_rc_is_error( rc ) ) goto done; } @@ -1358,8 +2361,8 @@ short pcps_generic_io( PCPS_DDEV *pddev, uint8_t type, // Write the last byte and read the completion code. rc = _pcps_read( pddev, tmp_byte, data_read, bytes_to_read ); - if ( out_cnt ) //##++ should do some more plausibility checks - if ( rc == MBG_SUCCESS ) + if ( out_cnt ) //### TODO should do some more plausibility checks + if ( mbg_rc_is_success( rc ) ) { _fmemcpy( out_buff, &data_read[2], out_cnt ); } @@ -1368,41 +2371,39 @@ done: // If an error code has been returned by the I/O function, // return that code, otherwise return the completion code // read from the board. - return ( rc < 0 ) ? rc : data_read[0]; + return mbg_rc_is_error( rc ) ? rc : data_read[0]; } // pcps_generic_io -/*-------------------------------------------------------------- - * Name: pcps_read_gps_block() - * - * Purpose: Get a block of data from GPS clock device. - * This is a local function which is called - * by pcps_read_gps(). +static /*HDR*/ +/** + * @brief Get a block of data from a GPS device * - * Input: pddev pointer to the device information - * data_type the code assigned to the data type - * buffer_size the size of the buffer - * block_num the number of the block to read - * block_size the size of the block to read + * This static function is used by ::pcps_read_gps. * - * Output: buffer filled with data + * @param[in] pddev Pointer to the device structure + * @param[in] data_type The code assigned to the dadta type, see @ref PC_GPS_CMD_CODES + * @param[out] buffer A buffer with data to be read according to the data_type + * @param[in] buffer_size The number of bytes to be read according to the data_type + * @param[in] block_num A buffer with data to be written according to the type code + * @param[in] block_size The number of bytes to be written according to the type code * - * Ret value: MBG_SUCCESS - * MBG_ERR_TIMEOUT - * MBG_ERR_NBYTES - *-------------------------------------------------------------*/ - -static /*HDR*/ -short pcps_read_gps_block( PCPS_DDEV *pddev, - uint8_t data_type, - void FAR *buffer, - uint16_t buffer_size, - uint8_t block_num, - uint8_t block_size ) + * @return ::MBG_SUCCESS on success, + * ::MBG_ERR_TIMEOUT if device didn't respond in time, + * ::MBG_ERR_NBYTES if the number of parameter bytes did not match + * the number of data bytes expected by the device, + * or one of the other @ref MBG_RETURN_CODES + */ +int pcps_read_gps_block( PCPS_DDEV *pddev, + uint8_t data_type, + void FAR *buffer, + uint16_t buffer_size, + uint8_t block_num, + uint8_t block_size ) { - short rc; + int rc; uint16_t n_bytes; uint8_t size_n_bytes; uint8_t uc; @@ -1429,7 +2430,7 @@ short pcps_read_gps_block( PCPS_DDEV *pddev, // Write the command, expect to read one byte. rc = _pcps_read_var( pddev, PCPS_READ_GPS_DATA, uc ); - if ( rc != MBG_SUCCESS ) // Error ... + if ( mbg_rc_is_error( rc ) ) return rc; if ( uc != 1 ) // The board doesn't expect exactly one more byte @@ -1459,17 +2460,17 @@ short pcps_read_gps_block( PCPS_DDEV *pddev, n_bytes = 0; rc = _pcps_read( pddev, data_type, &n_bytes, size_n_bytes ); - if ( rc != MBG_SUCCESS ) // Error ... + if ( mbg_rc_is_error( rc ) ) // Error ... return rc; #if defined( MBG_ARCH_BIG_ENDIAN ) - // Swap n_bytes regardless of whether we have actuall read 1 or 2 bytes. - // If we have read only 1 byte then the other one is 0. - n_bytes = _mbg16_to_cpu( n_bytes ); + // Swap n_bytes regardless of whether we have actually read 1 or 2 bytes. + // If we have read only 1 byte then the other one is 0 anyway. + n_bytes = _mbg16_to_cpu( n_bytes ); #endif #if DEBUG_IO - _mbgddmsg_2( MBG_DBG_DETAIL, "pcps_read_gps_block: board expects data size %u, buffer size %u", + _mbgddmsg_2( MBG_DBG_DETAIL, "pcps_read_gps_block: device expects data size %u, buffer size %u", n_bytes, buffer_size ); #endif @@ -1489,37 +2490,45 @@ short pcps_read_gps_block( PCPS_DDEV *pddev, -/*-------------------------------------------------------------- - * Name: pcps_read_gps() +/*HDR*/ +/** + * @brief Read a large data structure from a device * - * Purpose: Get a data structure from a GPS clock. + * Read data structures which exceed ::PCPS_FIFO_SIZE bytes. + * This can't be handled in a single read cycle, and due to + * limitations of the device's microprocessor the execution time + * can be up to 20 milliseconds, depending on the device type. + * This has been introduced with the first GPS devices but is + * now in fact also used with non-GPS devices. * - * Input: pddev pointer to the device information - * data_type the code assigned to the data type - * buffer_size the size of the buffer + * @param[in] pddev Pointer to the device structure + * @param[in] data_type The code assigned to the dadta type, see @ref PC_GPS_CMD_CODES + * @param[out] buffer A buffer with data to be read according to the data_type + * @param[in] buffer_size The number of bytes to be read according to the data_type * - * Output: buffer filled with data + * @return ::MBG_SUCCESS on success, + * ::MBG_ERR_TIMEOUT if device didn't respond in time, + * ::MBG_ERR_NBYTES if the number of parameter bytes did not match + * the number of data bytes expected by the device, + * or one of the other @ref MBG_RETURN_CODES * - * Ret value: MBG_SUCCESS - * MBG_ERR_TIMEOUT - * MBG_ERR_NBYTES - *-------------------------------------------------------------*/ - -/*HDR*/ /* PCPS_READ_FNC */ -short pcps_read_gps( PCPS_DDEV *pddev, - uint8_t data_type, - void FAR *buffer, - uint16_t buffer_size ) + * @ingroup pcps_io_fncs + * @see @ref pcps_io_fncs + */ +int pcps_read_gps( PCPS_DDEV *pddev, + uint8_t data_type, + void FAR *buffer, + uint16_t buffer_size ) { uint8_t FAR *p = (uint8_t FAR *) buffer; - short rc = 0; + int rc = 0; int dt_quot; int dt_rem; int block_num; #if DEBUG_IO - _mbgddmsg_3( MBG_DBG_DETAIL, "Going to read GPS data, type: %02X, addr: %p, size: %u", + _mbgddmsg_3( MBG_DBG_DETAIL, "Going to read GPS data, type: 0x%02X, addr: %p, size: %u", data_type, buffer, buffer_size ); #endif @@ -1534,7 +2543,7 @@ short pcps_read_gps( PCPS_DDEV *pddev, rc = pcps_read_gps_block( pddev, data_type, p, buffer_size, (uint8_t) block_num, PCPS_FIFO_SIZE ); - if ( rc != MBG_SUCCESS ) // Error ... + if ( mbg_rc_is_error( rc ) ) // Error ... goto done; // Move the destination pointer to the next free byte. @@ -1556,34 +2565,40 @@ done: } // pcps_read_gps +#if !defined( AVOID_REDUNDANT_REDECLARATION ) + PCPS_READ_FNC pcps_read_gps; +#endif -/*-------------------------------------------------------------- - * Name: pcps_write_gps() + +/*HDR*/ +/** + * @brief Write a large data structure to a device * - * Purpose: Write a data structure to a GPS clock. + * This has been introduced with the first GPS devices but is + * now in fact also used with non-GPS devices. * - * Input: pddev pointer to the device information - * data_type the code assigned to the data type - * buffer the data to write - * buffer_size the size of the buffer - * read_fnc function to access the board + * @param[in] pddev Pointer to the device structure + * @param[in] data_type The code assigned to the dadta type, see @ref PC_GPS_CMD_CODES + * @param[in] buffer A buffer with data to be written according to the data_type + * @param[in] buffer_size The number of bytes to be written according to the data_type * - * Output: -- + * @return ::MBG_SUCCESS on success, + * ::MBG_ERR_TIMEOUT if device didn't respond in time, + * ::MBG_ERR_NBYTES if the number of parameter bytes did not match + * the number of data bytes expected by the device, + * or one of the other @ref MBG_RETURN_CODES * - * Ret value: MBG_SUCCESS - * MBG_ERR_TIMEOUT - * MBG_ERR_NBYTES - *-------------------------------------------------------------*/ - -/*HDR*/ /* PCPS_WRITE_FNC */ -short pcps_write_gps( PCPS_DDEV *pddev, - uint8_t data_type, - const void FAR *buffer, - uint16_t buffer_size ) + * @ingroup pcps_io_fncs + * @see @ref pcps_io_fncs + */ +int pcps_write_gps( PCPS_DDEV *pddev, + uint8_t data_type, + const void FAR *buffer, + uint16_t buffer_size ) { const uint8_t FAR *p = (const uint8_t FAR *) buffer; - short rc; + int rc; short i; uint16_t n_bytes; uint8_t size_n_bytes; @@ -1609,7 +2624,7 @@ short pcps_write_gps( PCPS_DDEV *pddev, // Write the command, expect to read one byte. rc = _pcps_read_var( pddev, PCPS_WRITE_GPS_DATA, uc ); - if ( rc != MBG_SUCCESS ) // Error ... + if ( mbg_rc_is_error( rc ) ) // Error ... return rc; if ( uc != 1 ) // The board doesn't expect exactly one more byte @@ -1639,7 +2654,7 @@ short pcps_write_gps( PCPS_DDEV *pddev, n_bytes = 0; rc = _pcps_read( pddev, data_type, &n_bytes, size_n_bytes ); - if ( rc != MBG_SUCCESS ) // Error ... + if ( mbg_rc_is_error( rc ) ) // Error ... return rc; #if defined( MBG_ARCH_BIG_ENDIAN ) @@ -1649,12 +2664,12 @@ short pcps_write_gps( PCPS_DDEV *pddev, #endif #if DEBUG_IO - _mbgddmsg_2( MBG_DBG_DETAIL, "pcps_write_gps: board expects data size %u, buffer size %u", + _mbgddmsg_2( MBG_DBG_DETAIL, "pcps_write_gps: device expects data size %u, buffer size is %u", n_bytes, buffer_size ); #endif if ( n_bytes != buffer_size ) // The board doesn't expect the number - return MBG_ERR_NBYTES; // of bytes we were going to write. + return MBG_ERR_NBYTES; // of bytes we were going to write. // Write all bytes but the last one without reading. @@ -1664,7 +2679,7 @@ short pcps_write_gps( PCPS_DDEV *pddev, { rc = _pcps_write_byte( pddev, *p++ ); - if ( rc != MBG_SUCCESS ) // Error ... + if ( mbg_rc_is_error( rc ) ) // Error ... return rc; } @@ -1678,71 +2693,65 @@ short pcps_write_gps( PCPS_DDEV *pddev, } // pcps_write_gps +#if !defined( AVOID_REDUNDANT_REDECLARATION ) + PCPS_WRITE_FNC pcps_write_gps; +#endif -/*-------------------------------------------------------------- - * Name: pcps_get_fw_id() - * - * Purpose: This function tries to read the firmware ID - * from the board. It should be used to check - * if the board is properly installed and can - * be accessed without problems. + +static /*HDR*/ +/** + * @brief Read the firmware ID from a device * - * Input: pddev pointer to the device information + * This is usually done first when probing a device to check if the + * device is properly installed and can be accessed without problems. * - * Output: fw_id buffer filled with ASCIIZ string + * @param[in] pddev Pointer to a device structure + * @param[out] fw_id A buffer to be filled withtthe firmware ID * - * Ret value: MBG_SUCCESS no error - * MBG_ERR_TIMEOUT the board is busy for too long - *-------------------------------------------------------------*/ - -/*HDR*/ -short pcps_get_fw_id( PCPS_DDEV *pddev, PCPS_ID_STR FAR fw_id ) + * @return ::MBG_SUCCESS if the the signature was found, or signature was specified, or + * ::MBG_ERR_FW_ID if the firmware ID is unknown or invalid + */ +int pcps_get_fw_id( PCPS_DDEV *pddev, PCPS_ID_STR FAR fw_id ) { - short rc; + int rc; + memset( fw_id, 0, sizeof( PCPS_ID_STR ) ); // sizeof( fw_id ) would yield pointer size only - // read first part of the firmware ID + // read the first part of the firmware ID rc = _pcps_read( pddev, PCPS_GIVE_FW_ID_1, &fw_id[0], PCPS_FIFO_SIZE ); - if ( rc != MBG_SUCCESS ) - return rc; // may be timeout + if ( mbg_rc_is_error( rc ) ) + goto out; - - // read second part of the firmware ID + // read the second part of the firmware ID rc = _pcps_read( pddev, PCPS_GIVE_FW_ID_2, &fw_id[PCPS_FIFO_SIZE], PCPS_FIFO_SIZE ); - if ( rc != MBG_SUCCESS ) - return rc; // may be timeout - - - // terminate the string with 0 - + // force termination with 0 fw_id[PCPS_ID_SIZE - 1] = 0; - - return MBG_SUCCESS; +out: + return rc; } // pcps_get_fw_id -/*-------------------------------------------------------------- - * Name: pcps_check_id() - * - * Purpose: Check an ASCIIZ string for a valid signature. +static /*HDR*/ +/** + * @brief Check an ASCIIZ string for a valid signature. * - * Input: pddev pointer to the device information - * ref the reference signature + * This function is only used to determine the type of a legacy ISA card. + * For PCI and USB devices the type can be determined from the device ID. * - * Output: -- + * @param[in] pddev Pointer to a device structure + * @param[in] ref The reference signature, i.e. the expected signature + * at the beginning of the device's firmware ID * - * Ret value: MBG_SUCCESS no error - * MBG_ERR_FW_ID the firmware ID is not valid - *-------------------------------------------------------------*/ - -/*HDR*/ -short pcps_check_id( PCPS_DDEV *pddev, const char FAR *ref ) + * @return ::MBG_SUCCESS if a signature was specified and the signature was found, or + * ::MBG_ERR_FW_ID if the firmware ID is unknown or invalid + */ +int pcps_check_id( PCPS_DDEV *pddev, const char FAR *ref ) { // check if the first characters of the string match the reference @@ -1756,38 +2765,36 @@ short pcps_check_id( PCPS_DDEV *pddev, const char FAR *ref ) -/*-------------------------------------------------------------- - * Name: pcps_get_rev_num() - * - * Purpose: Get a version number from an ID string. - * - * Input: idstr the ID string +static /*HDR*/ +/** + * @brief Retrieve a version number from a firmware ID string * - * Output: -- + * @param[in] idstr The ID string, e.g. a ::PCPS_ID_STR * - * Ret value: on success: the version number in hex - * (e.g. 0x0270 for version 2.7) - * on error: 0 - *-------------------------------------------------------------*/ - -/*HDR*/ -short pcps_get_rev_num( char FAR *idstr ) + * @return A version number in hex format, e.g. 0x0270 for version 2.7, + * or 0 if no version number could be found. + */ +PCPS_FW_REV_NUM pcps_get_rev_num( char FAR *idstr ) { + int len = _fstrlen( idstr ); int i; - int len = _fstrlen( idstr ) - 2; - char c; - uchar rev_num_hi; - uchar rev_num_lo; + if ( len < 2 ) + goto no_rev_num; + + len -= 2; for ( i = 0; i < len; i++ ) { if ( idstr[i + 1] == '.' ) { - rev_num_hi = idstr[i] & 0x0F; - rev_num_lo = ( idstr[i + 2] & 0x0F ) << 4; + uint8_t rev_num_hi = idstr[i] & 0x0F; + uint8_t rev_num_lo = ( idstr[i + 2] & 0x0F ) << 4; + + // If the minor part of the version string has 2 digits + // then evaluate the 2nd digit, too. - c = idstr[i + 3]; + char c = idstr[i + 3]; if ( c >= '0' && c <= '9' ) rev_num_lo |= c & 0x0F; @@ -1796,27 +2803,24 @@ short pcps_get_rev_num( char FAR *idstr ) } } +no_rev_num: return 0; } // pcps_get_rev_num -/*-------------------------------------------------------------- - * Name: pcps_read_sernum() - * - * Purpose: This function tries to read the clock's S/N - * from the board, if supported by the clock. +/*HDR*/ +/** + * @brief Read the serial number from a device, if supported * - * Input: pddev pointer to the device information + * If the serial number could be read successfully then it is + * stored in one of the sub-structures of pddev. * - * Output: pddev sernum field filled with ASCIIZ + * @param[in,out] pddev Pointer to a device structure * - * Ret value: MBG_SUCCESS no error - * other error - *-------------------------------------------------------------*/ - -/*HDR*/ + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ int pcps_read_sernum( PCPS_DDEV *pddev ) { char *cp; @@ -1826,48 +2830,62 @@ int pcps_read_sernum( PCPS_DDEV *pddev ) memset( pddev->dev.cfg.sernum, 0, sizeof( pddev->dev.cfg.sernum ) ); - // There are different ways to read the clock's S/N. - // Check which way is supported by the clock, and - // read the S/N. - + // There are different ways to read the clock's S/N. Check which + // way is supported, and read the S/N from the device. + // + // Never just return a previous copy of the serial number which + // has been read earlier since the S/N may just have been set + // by a configuration API call. - // The S/N is part of the RECEIVER_INFO structure. If this - // structure is supported by the device then it should have - // already been set up, so we can simply copy the serial number. - if ( _pcps_ddev_has_receiver_info( pddev ) ) + // Read directly. This is supported by newer devices. + if ( _pcps_ddev_has_sernum( pddev ) ) { #if DEBUG_SERNUM - _mbgddmsg_0( MBG_DBG_DETAIL, "copying S/N from receiver info" ); + _mbgddmsg_0( MBG_DBG_DETAIL, "getting S/N via PCPS_GIVE_SERNUM cmd" ); #endif - strncpy( pddev->dev.cfg.sernum, pddev->ri.sernum, - sizeof( pddev->dev.cfg.sernum ) ); + rc = _pcps_read( pddev, PCPS_GIVE_SERNUM, pddev->dev.cfg.sernum, PCPS_FIFO_SIZE ); + + if ( mbg_rc_is_error( rc ) ) + { + _mbgddmsg_2( MBG_DBG_INIT_DEV, "PCPS read SERNUM %X: rc = %i", + _pcps_ddev_dev_id( pddev ), rc ); + goto fail; + } + goto check; } - // Read directly. This is supported by newer DCF77 clocks. - if ( _pcps_ddev_has_sernum( pddev ) ) + // The S/N is part of the RECEIVER_INFO structure, + // so use that one, if supported. + if ( _pcps_ddev_has_receiver_info( pddev ) ) { + RECEIVER_INFO *p_ri = _ri_addr( pddev ); + #if DEBUG_SERNUM - _mbgddmsg_0( MBG_DBG_DETAIL, "getting S/N via PCPS_GIVE_SERNUM cmd" ); + _mbgddmsg_0( MBG_DBG_DETAIL, "getting S/N from receiver info" ); #endif - rc = _pcps_read( pddev, PCPS_GIVE_SERNUM, pddev->dev.cfg.sernum, PCPS_FIFO_SIZE ); + rc = _pcps_read_gps_var( pddev, PC_GPS_RECEIVER_INFO, *p_ri ); - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) { - _mbgddmsg_2( MBG_DBG_INIT_DEV, "PCPS read SERNUM %X: rc = %i", + _mbgddmsg_2( MBG_DBG_INIT_DEV, "PCPS read GPS receiver info %X: rc = %i", _pcps_ddev_dev_id( pddev ), rc ); goto fail; } + _mbg_swab_receiver_info( p_ri ); + + strncpy( pddev->dev.cfg.sernum, p_ri->sernum, + sizeof( pddev->dev.cfg.sernum ) ); goto check; } // Older GPS clocks store the S/N in an IDENT structure - // which must be decoded to get the S/N. + // which needs to be decoded to get the S/N. if ( _pcps_ddev_has_ident( pddev ) ) { static_wc IDENT ident = { { 0 } }; @@ -1882,7 +2900,7 @@ int pcps_read_sernum( PCPS_DDEV *pddev ) assert( sizeof( ident ) < sizeof( pddev->dev.cfg.sernum ) ); #endif - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) { _mbgddmsg_2( MBG_DBG_INIT_DEV, "PCPS read GPS ident %X: rc = %i", _pcps_ddev_dev_id( pddev ), rc ); @@ -1899,6 +2917,26 @@ int pcps_read_sernum( PCPS_DDEV *pddev ) #endif mbg_gps_ident_decode( _pcps_ddev_sernum( pddev ), &ident ); + + #if DEBUG_SERNUM + _mbgddmsg_1( MBG_DBG_DETAIL, "S/N decoded from ident: %s (raw)", + _pcps_ddev_sernum( pddev ) ); + #endif + + // Some old devices may have non-digits appended + // to the S/N string. Truncate such a string. + for ( cp = _pcps_ddev_sernum( pddev ); *cp; cp++ ) + if ( ( *cp < '0' ) || ( *cp > '9' ) ) + { + *cp = 0; + break; + } + + #if DEBUG_SERNUM + _mbgddmsg_1( MBG_DBG_DETAIL, "S/N decoded from ident: %s", + _pcps_ddev_sernum( pddev ) ); + #endif + goto check; } @@ -1948,7 +2986,7 @@ fail: fail: // No valid serial number has been found, though the device - // should have one. In order to distinguish from devices which + // should have one. In order to distinguish from devices which // don't even support a serial number we return a number of '?' // rather than "N/A". memset( pddev->dev.cfg.sernum, '?', 8 ); @@ -1967,7 +3005,14 @@ done: #if _PCPS_USE_RSRCMGR -/*HDR*/ +static /*HDR*/ +/** + * @brief Try to claim an I/O port resource range + * + * @param[in,out] pddev The device structure + * + * @return ::MBG_SUCCESS if the port range could be claimed, else ::MBG_ERR_CLAIM_RSRC + */ int pcps_rsrc_claim( PCPS_DDEV *pddev ) { ushort decode_width; @@ -1986,38 +3031,40 @@ int pcps_rsrc_claim( PCPS_DDEV *pddev ) PCPS_IO_RSRC *p = &_pcps_ddev_io_rsrc( pddev, i ); ushort rc; - rc = _rsrc_alloc_ports( &pddev->rsrc, p->base_raw, p->num, decode_width ); //##++ + rc = _rsrc_alloc_ports( pddev, p->base_raw, p->num, decode_width ); // If the resource manager was unable to alloc the resources // then the selected range of ports is probably in use // by another hardware device and/or driver - if ( rc ) + if ( mbg_rc_is_error( rc ) ) { _pcps_ddev_set_err_flags( pddev, PCPS_EF_IO_RSRC ); return MBG_ERR_CLAIM_RSRC; } } - return 0; + return MBG_SUCCESS; } // pcps_rsrc_claim /*HDR*/ +/** + * @brief Release an I/O port resource range that has been claimed before + * + * @param[in,out] pddev The device structure + */ void pcps_rsrc_release( PCPS_DDEV *pddev ) { int i; - for ( i = 0; i < N_PCPS_PORT_RSRC; i++ ) + for ( i = 0; i < pddev->rsrc_info.num_rsrc_io; i++ ) { - PCPS_PORT_RSRC *p = &_pcps_ddev_port_rsrc( pddev, i ); - - if ( _pcps_port_rsrc_unused( p ) ) - continue; + PCPS_IO_RSRC *p = &_pcps_ddev_io_rsrc( pddev, i ); - // clean up if clock not found - _rsrc_dealloc_ports( &pddev->rsrc.hResource[i], p->base, p->num ); + if ( p->base_raw ) + _rsrc_dealloc_ports( pddev, p->base_raw, p->num ); } } // pcps_rsrc_release @@ -2027,6 +3074,11 @@ void pcps_rsrc_release( PCPS_DDEV *pddev ) #if defined( MBG_TGT_OS2 ) static /*HDR*/ +/** + * @brief Register a device under OS/2 + * + * @param[in] pddev The device structure + */ void pcps_rsrc_register_device( PCPS_DDEV *pddev ) { #define RSRC_BASE_NAME "RADIOCLK_# Meinberg Radio Clock " @@ -2091,14 +3143,17 @@ void pcps_rsrc_register_device( PCPS_DDEV *pddev ) * *-------------------------------------------------------------*/ -/*-------------------------------------------------------------- - * Convert the code read from PS/2 POS to the port base address. - *-------------------------------------------------------------*/ - -/*HDR*/ -ushort pcps_port_from_pos( ushort pos ) +static /*HDR*/ +/** + * @brief Convert the code read from PS/2 POS to the port base address + * + * @param[in] pos The POS code to be converted + * + * @return The decoded I/O port base address + */ +uint16_t pcps_port_from_pos( uint16_t pos ) { - ushort us = ( ( pos & 0x007E ) << 8 ) | 0x0100; + uint16_t us = ( ( pos & 0x007E ) << 8 ) | 0x0100; if ( pos & 0x0001 ) us |= 0x0010; @@ -2109,14 +3164,17 @@ ushort pcps_port_from_pos( ushort pos ) -/*-------------------------------------------------------------- - * Convert the port base address to a PS/2 POS code. - *-------------------------------------------------------------*/ - -/*HDR*/ -uchar pcps_pos_from_port( ushort port ) +static /*HDR*/ +/** + * @brief Convert the port base address to a PS/2 POS code + * + * @param[in] port The I/O port base address to be encoded + * + * @return The encoded POS code + */ +uint8_t pcps_pos_from_port( uint16_t port ) { - uchar uc; + uint8_t uc; uc = *( ( (uchar *) (&port) ) + 1 ) & 0x7E; @@ -2131,7 +3189,12 @@ uchar pcps_pos_from_port( ushort port ) static /*HDR*/ -void pcps_detect_mca_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg ) +/** + * @brief Detect MCA devices and allocate device info structures + * + * @param[in] alloc_fnc Pointer to function called to allocate a device structure for each detected device. + */ +void pcps_detect_mca_devices( PCPS_DDEV_ALLOC_FNC *alloc_fnc ) { short rc; ushort type_idx; @@ -2164,7 +3227,7 @@ void pcps_detect_mca_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg ) // New device found, try to add to list. - pddev = alloc_fnc( alloc_arg ); + pddev = alloc_fnc(); if ( pddev ) // Setup only if successful. { @@ -2175,24 +3238,33 @@ void pcps_detect_mca_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg ) //##++ Should try to read the interrupt line assigned to the clock. // The standard functions, however, don't use any interrupt. - pcps_start_device( pddev, 0, slot_num ); + pcps_probe_device( pddev, 0, slot_num ); } } mca_fnc_deinit(); -} // pcps_detect_mca_clocks +} // pcps_detect_mca_devices #endif /* _PCPS_USE_MCA */ -// The function below takes a bus flag and device ID to search -// the table of known devices for a device which matches the -// given criteria. - /*HDR*/ -PCPS_DEV_TYPE *pcps_get_dev_type( int bus_mask, ushort dev_id ) +/** + * @brief Lookup a specific device in the device table + * + * The function below takes a bus flag and device ID to search + * the table of known devices for a device which matches the + * given criteria. + * + * @param[in] bus_mask Mask of the bus type to look up, see @ref PCPS_BUS_FLAG_MASKS + * @param[in] dev_id The device ID to lookup, see @ref MEINBERG_PCI_DEVICE_IDS + * or @ref MBG_USB_DEVICE_IDS, depending on the bus_mask + * + * @return A pointer to the device table entry, or NULL if no entry found + */ +PCPS_DEV_TYPE *pcps_get_dev_type_table_entry( PCPS_BUS_FLAGS bus_mask, PCPS_DEV_ID dev_id ) { int i; @@ -2209,11 +3281,16 @@ PCPS_DEV_TYPE *pcps_get_dev_type( int bus_mask, ushort dev_id ) return NULL; -} // pcps_get_dev_type +} // pcps_get_dev_type_table_entry /*HDR*/ +/** + * @brief Allocate a device info structure for a device + * + * @return A pointer to the allocated structure, or NULL if failed + */ PCPS_DDEV *pcps_alloc_ddev( void ) { PCPS_DDEV *pddev; @@ -2221,7 +3298,7 @@ PCPS_DDEV *pcps_alloc_ddev( void ) #if !_PCPS_STATIC_DEV_LIST pddev = _pcps_kmalloc( sizeof( *pddev ) ); #else - if ( n_ddevs >= PCPS_MAX_DDEVS ) + if ( n_ddevs >= N_SUPP_DEV_BUS ) { _mbgddmsg_0( MBG_DBG_INIT_DEV, "Unable to add new device: max count reached" ); @@ -2260,6 +3337,11 @@ PCPS_DDEV *pcps_alloc_ddev( void ) /*HDR*/ +/** + * @brief Free a previously allocated device info structure + * + * @param[in] pddev Pointer to the device structure to be freed + */ void pcps_free_ddev( PCPS_DDEV *pddev ) { if ( pddev ) @@ -2287,16 +3369,33 @@ void pcps_free_ddev( PCPS_DDEV *pddev ) static /*HDR*/ -void rsrc_port_to_cfg_port( PCPS_PORT_RSRC *p_port_rsrc, const PCPS_IO_RSRC *p_io_rsrc ) +/** + * @brief Convert a raw I/O base address to a short format + * + * See notes for ::PCPS_SHORT_PORT_RSRC. + + * @param[out] p_short_port_rsrc Pointer to a variable that takes up the converted address + * @param[in] p_io_rsrc Pointer to a variable with the address to be converted + */ +void rsrc_port_to_cfg_port( PCPS_SHORT_PORT_RSRC *p_short_port_rsrc, const PCPS_IO_RSRC *p_io_rsrc ) { - p_port_rsrc->base = (PCPS_PORT_ADDR) p_io_rsrc->base_raw; - p_port_rsrc->num = p_io_rsrc->num; + p_short_port_rsrc->base = (PCPS_SHORT_PORT_ADDR) p_io_rsrc->base_raw; + p_short_port_rsrc->num = (uint16_t) p_io_rsrc->num; } // rsrc_port_to_cfg_port /*HDR*/ +/** + * @brief Add an I/O address range resource to the device structure + * + * @param[in,out] pddev Pointer to the device structure + * @param[in] base Base address of the I/O address range + * @param[in] num Number of addresses of the I/O address range + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ int pcps_add_rsrc_io( PCPS_DDEV *pddev, ulong base, ulong num ) { PCPS_RSRC_INFO *prsrci = &pddev->rsrc_info; @@ -2307,7 +3406,7 @@ int pcps_add_rsrc_io( PCPS_DDEV *pddev, ulong base, ulong num ) p->base_mapped = (PCPS_IO_ADDR_MAPPED) _pcps_ioremap( base, num ); p->base_raw = (PCPS_IO_ADDR_RAW) base; - p->num = (uint16_t) num; + p->num = num; prsrci->num_rsrc_io++; @@ -2324,6 +3423,15 @@ int pcps_add_rsrc_io( PCPS_DDEV *pddev, ulong base, ulong num ) /*HDR*/ +/** + * @brief Add a memory address range resource to the device structure + * + * @param[in,out] pddev Pointer to the device structure + * @param[in] start Start address of the memory range + * @param[in] len Size of the memory range + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ int pcps_add_rsrc_mem( PCPS_DDEV *pddev, MBG_MEM_ADDR start, ulong len ) { PCPS_RSRC_INFO *prsrci = &pddev->rsrc_info; @@ -2335,7 +3443,7 @@ int pcps_add_rsrc_mem( PCPS_DDEV *pddev, MBG_MEM_ADDR start, ulong len ) p->len = len; prsrci->num_rsrc_mem++; - #if defined( MBG_TGT_UNIX ) + #if defined( MBG_TGT_POSIX ) _mbgddmsg_3( MBG_DBG_INIT_DEV, "Adding mem rsrc #%i: %08llX(%lu)", prsrci->num_rsrc_mem, (unsigned long long) start, len ); #else @@ -2353,6 +3461,14 @@ int pcps_add_rsrc_mem( PCPS_DDEV *pddev, MBG_MEM_ADDR start, ulong len ) /*HDR*/ +/** + * @brief Add an IRQ number resource to the device structure + * + * @param[in,out] pddev Pointer to the device structure + * @param[in] irq_num Start address of the memory range + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ int pcps_add_rsrc_irq( PCPS_DDEV *pddev, int16_t irq_num ) { PCPS_RSRC_INFO *prsrci = &pddev->rsrc_info; @@ -2377,10 +3493,20 @@ int pcps_add_rsrc_irq( PCPS_DDEV *pddev, int16_t irq_num ) #if _PCPS_USE_PNP /*HDR*/ -int pcps_init_ddev( PCPS_DDEV *pddev, int bus_flags, ushort dev_id ) +/** + * @brief Initialize an allocated device structure for a specific device + * + * @param[in,out] pddev Pointer to the device structure + * @param[in] bus_mask Mask of the bus type to look up, see @ref PCPS_BUS_FLAG_MASKS + * @param[in] dev_id The device ID to lookup, see @ref MEINBERG_PCI_DEVICE_IDS + * or @ref MBG_USB_DEVICE_IDS, depending on the bus_mask + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ +int pcps_init_ddev( PCPS_DDEV *pddev, PCPS_BUS_FLAGS bus_mask, PCPS_DEV_ID dev_id ) { // First check if we really support the device to be added. - PCPS_DEV_TYPE *pdt = pcps_get_dev_type( bus_flags, dev_id ); + PCPS_DEV_TYPE *pdt = pcps_get_dev_type_table_entry( bus_mask, dev_id ); if ( pdt == NULL ) { @@ -2405,39 +3531,59 @@ int pcps_init_ddev( PCPS_DDEV *pddev, int bus_flags, ushort dev_id ) #if defined( DEBUG ) + static /*HDR*/ -const char *get_feature_name( PCPS_FEATURES flag ) +/** + * @brief Get the name assigned to one of the @ref PCPS_FEATURE_MASKS flags + * + * @param[in] flag_mask one of the @ref PCPS_FEATURE_MASKS flags + * + * @return The associated feature name, or "unknown" + * + * @see @ref PCPS_FEATURE_MASKS + */ +const char *get_pcps_feature_name( PCPS_FEATURES flag_mask ) { - static const char *pcps_feature_names[N_PCPS_FEATURE] = PCPS_FEATURE_NAMES; - int i; - for ( i = 0; i < N_PCPS_FEATURE; i++ ) - if ( ( 1UL << i ) == flag ) + for ( i = 0; i < N_PCPS_FEATURE_BITS; i++ ) + if ( ( 1UL << i ) == flag_mask ) return pcps_feature_names[i]; return "unknown"; -} // get_feature_name +} // get_pcps_feature_name #endif static /*HDR*/ +/** + * @brief Check the firmware to see if a specific feature is supported + * + * Some devices provide a specific feature only starting with a specific + * firmware version, but the device provides no way to test this, so + * the feature flag in the device structure is set if the firmware + * has the required version. + * + * @param[in,out] pddev Pointer to the device structure + * @param[in] req_rev_num Revision number required for the feature to be supported + * @param[in] flag_mask Flag mask of the feature to be tested + */ void check_feature( PCPS_DDEV *pddev, ushort req_rev_num, - PCPS_FEATURES flag ) + PCPS_FEATURES flag_mask ) { int supported = _pcps_ddev_fw_rev_num( pddev ) >= req_rev_num; if ( supported ) - pddev->dev.cfg.features |= flag; + pddev->dev.cfg.features |= flag_mask; #if defined( DEBUG ) _mbgddmsg_5( MBG_DBG_INIT_DEV, "%s v%03X: feature 0x%08lX (%s) %ssupported", _pcps_ddev_type_name( pddev ), _pcps_ddev_fw_rev_num( pddev ), - (ulong) flag, get_feature_name( flag ), + (ulong) flag_mask, get_pcps_feature_name( flag_mask ), supported ? "" : "not " ); #endif @@ -2446,31 +3592,196 @@ void check_feature( PCPS_DDEV *pddev, ushort req_rev_num, static /*HDR*/ -void check_ri_feature( PCPS_DDEV *pddev, const RECEIVER_INFO *p_ri, - RI_FEATURES ri_flag, PCPS_FEATURES flag ) +/** + * @brief Check the receiver info features to see if a specific feature is supported + * + * Some devices provide a ::RECEIVER_INFO which provides some flags that + * can be mapped to the feature flags we use internally, so we scan these features + * and update the internal features mask accordingly. + * + * @param[in,out] pddev Pointer to the device structure + */ +void check_ri_features( PCPS_DDEV *pddev ) { - int supported = ( p_ri->features & ri_flag ) != 0; + const RECEIVER_INFO *p_ri = _ri_addr( pddev ); + int gps_feat_bit; - if ( supported ) - pddev->dev.cfg.features |= flag; + for ( gps_feat_bit = 0; gps_feat_bit < N_GPS_FEATURE; gps_feat_bit++ ) + { + int supported = ( p_ri->features & ( 1UL << gps_feat_bit ) ) != 0; + PCPS_FEATURES pcps_flags = ri_feat_tbl[gps_feat_bit]; - #if defined( DEBUG ) - _mbgddmsg_5( MBG_DBG_INIT_DEV, "%s v%03X: feature 0x%08lX (%s) %ssupported according to RECEIVER_INFO", - _pcps_ddev_type_name( pddev ), - _pcps_ddev_fw_rev_num( pddev ), - (ulong) flag, get_feature_name( flag ), - supported ? "" : "not " ); - #endif + if ( supported ) + { + if ( pcps_flags ) + { + pddev->dev.cfg.features |= pcps_flags; + + #if defined( DEBUG ) + { + int i; + + for ( i = 0; i < 8 * sizeof( pcps_flags ); i++ ) + if ( pcps_flags & ( 1UL << i ) ) + _mbgddmsg_4( MBG_DBG_INIT_DEV, "%s v%03X: Supported RI feature \"%s\" maps to PCPS feature %s", + _pcps_ddev_type_name( pddev ), + _pcps_ddev_fw_rev_num( pddev ), + gps_ri_feature_names[gps_feat_bit], + pcps_feature_names[i] ); + } + #endif + } + else + { + #if defined( DEBUG ) + _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s v%03X: RI feature \"%s\" supported, but no corresponding PCPS feature", + _pcps_ddev_type_name( pddev ), + _pcps_ddev_fw_rev_num( pddev ), + gps_ri_feature_names[gps_feat_bit] ); + #endif + } + } + else + { + #if defined( DEBUG ) + _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s v%03X: RI feature \"%s\" not supported by device", + _pcps_ddev_type_name( pddev ), + _pcps_ddev_fw_rev_num( pddev ), + gps_ri_feature_names[gps_feat_bit] ); + #endif + } + } + +} // check_ri_features + + + +/*HDR*/ +/** + * @brief Check if a specific feature of a specific feature type is supported + * + * There are different structures where information can be stored + * if a specific feature is supported. All information is set up + * when the ::pcps_probe_device function is called to probe and + * initialize the device. + * This generic low-level function can be called by API functions + * to check if a specific feature is supported. + * + * @param[in] p_ddev Pointer to the device structure + * @param[in] feat_req_type See ::DEV_FEAT_REQ_TYPES + * @param[in] feat_num Number and range depending on feat_req_type value + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @see ::pcps_probe_device + */ +int pcps_chk_dev_feat( PCPS_DDEV *p_ddev, uint32_t feat_req_type, uint32_t feat_num ) +{ + // NOTE In the code below we currently check if the bit to be tested + // is really defined in an enumeration, and return an error if a bit + // is tested which is not defined. + // Alternatively we could instead just check if the bit number is valid + // according to the buffer size. + + switch ( feat_req_type ) + { + case DEV_FEAT_REQ_TYPE_BUILTIN: + _mbgddmsg_3( MBG_DBG_DETAIL, "%s: chk_dev_feat: builtin_feat %i/%i", + pcps_driver_name, feat_num, N_GPS_BUILTIN_FEATURE_BITS ); + + if ( feat_num < N_GPS_BUILTIN_FEATURE_BITS ) + return _check_feat_supp_bit( p_ddev->builtin_features, feat_num ); -} // check_ri_feature + break; // invalid + + + case DEV_FEAT_REQ_TYPE_REF_TYPE: + _mbgddmsg_3( MBG_DBG_DETAIL, "%s: chk_dev_feat: ref_type feat %i/%i", + pcps_driver_name, feat_num, N_PCPS_REF ); + + if ( feat_num < N_PCPS_REF ) + return ( feat_num == _pcps_ddev_ref_type( p_ddev ) ) ? MBG_SUCCESS : MBG_ERR_NOT_SUPP_BY_DEV; + + break; // invalid + + + case DEV_FEAT_REQ_TYPE_PCPS: + _mbgddmsg_3( MBG_DBG_DETAIL, "%s: chk_dev_feat: pcps_feat %i/%i", + pcps_driver_name, feat_num, N_PCPS_FEATURE_BITS ); + + if ( feat_num < N_PCPS_FEATURE_BITS ) + return _check_feat_supp_bit( p_ddev->dev.cfg.features, feat_num ); + + break; // invalid + + + case DEV_FEAT_REQ_TYPE_RI: + _mbgddmsg_3( MBG_DBG_DETAIL, "%s: chk_dev_feat: ri_feat %i/%i", + pcps_driver_name, feat_num, N_GPS_FEATURE ); + + if ( feat_num < N_GPS_FEATURE ) + return _check_feat_supp_bit( p_ddev->xdev_features.receiver_info.features, feat_num ); + + break; // invalid + + + + case DEV_FEAT_REQ_TYPE_XFEAT: + _mbgddmsg_3( MBG_DBG_DETAIL, "%s: chk_dev_feat: x_feat %i/%i", + pcps_driver_name, feat_num, N_MBG_XFEATURE ); + + if ( feat_num < N_MBG_XFEATURE ) + return check_feat_supp_byte_array( feat_num, p_ddev->xdev_features.xfeature_buffer.b, + sizeof( p_ddev->xdev_features.xfeature_buffer ) ); + break; // invalid + + + + case DEV_FEAT_REQ_TYPE_TLV_FEAT: + _mbgddmsg_3( MBG_DBG_DETAIL, "%s: chk_dev_feat: tlv_feat %i/%i", + pcps_driver_name, feat_num, N_MBG_TLV_FEAT_TYPES ); + + if ( feat_num < N_MBG_TLV_FEAT_TYPES ) + return check_feat_supp_byte_array( feat_num, p_ddev->xdev_features.tlv_info.supp_tlv_feat.b, + sizeof( p_ddev->xdev_features.tlv_info.supp_tlv_feat.b ) ); + break; // invalid + } + + _mbgddmsg_3( MBG_DBG_WARN, "%s: chk_dev_feat: *invalid* request %i:%i", + pcps_driver_name, feat_req_type, feat_num ); + + return MBG_ERR_INV_PARM; + +} // pcps_chk_dev_feat /*HDR*/ -int pcps_start_device( PCPS_DDEV *pddev, +/** + * @brief Probe if a device is supported, and allocate and setup the device structure + * + * This function should be called by the probe routines of any + * target-specific kernel drivers. + * If the device is supported then all specific information including + * supported features is read from the device and stored in sub-structures + * of the device structure addressed by pdev. + * + * @param[in,out] pddev Pointer to the device structure which has been initialized and will be set up + * @param[in] bus_num The bus number if supported (e.g. PCI), else 0 + * @param[in] dev_fnc_num The device/function number if supported (e.g. PCI), else 0 + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @see ::pcps_cleanup_device + * @see ::pcps_chk_dev_feat + */ +int pcps_probe_device( PCPS_DDEV *pddev, PCPS_BUS_NUM bus_num, PCPS_SLOT_NUM dev_fnc_num ) { + RECEIVER_INFO *p_ri = _ri_addr( pddev ); ushort port_rsrc_len[N_PCPS_PORT_RSRC] = { 0 }; int port_ranges_required = 0; ushort status_port_offs = 0; @@ -2513,6 +3824,9 @@ int pcps_start_device( PCPS_DDEV *pddev, #endif + // Next we do some setup depending on the interface type + // and chip. + switch ( _pcps_ddev_bus_flags( pddev ) ) { #if _PCPS_USE_USB @@ -2552,7 +3866,7 @@ int pcps_start_device( PCPS_DDEV *pddev, #error USB endpoint configuration can not be determined for this target. #endif - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) if ( pddev->n_usb_ep < MBGUSB_MIN_ENDPOINTS_REQUIRED ) { #if defined( MBG_TGT_LINUX ) @@ -2561,9 +3875,9 @@ int pcps_start_device( PCPS_DDEV *pddev, #elif defined( MBG_TGT_WIN32_PNP ) swprintf( pddev->wcs_msg, L"device supports only %d endpoints while %d are required", pddev->n_usb_ep, MBGUSB_MIN_ENDPOINTS_REQUIRED ); - _evt_msg( GlbDriverObject, pddev->wcs_msg ); + _evt_msg_w( GlbDriverObject, pddev->wcs_msg ); #else - //##++ + //##++ #endif rc = MBG_ERR_GENERIC; @@ -2584,14 +3898,11 @@ int pcps_start_device( PCPS_DDEV *pddev, // If access time is below 1 ms then there might be a V2.0 Hub between device and host. // In this case, you can expect that there is the 125 us microframe timing of USB 2.0. - if ( ( (ULONGLONG) ( Count2.QuadPart - Count1.QuadPart ) ) < ( (ULONGLONG) PerfFreq.QuadPart ) / 1000UL ) - pddev->usb_20_mode = 1; - else - pddev->usb_20_mode = 0; + pddev->usb_20_mode = ( (ULONGLONG) ( Count2.QuadPart - Count1.QuadPart ) ) < ( ( (ULONGLONG) PerfFreq.QuadPart ) / 1000UL ); } #endif - if ( rc != MBG_SUCCESS ) + if ( mbg_rc_is_error( rc ) ) { _pcps_ddev_set_err_flags( pddev, PCPS_EF_IO_INIT ); goto fail; @@ -2648,22 +3959,30 @@ int pcps_start_device( PCPS_DDEV *pddev, #elif defined( MBG_TGT_WIN32 ) swprintf( pddev->wcs_msg, L"unhandled bus flags %04X for device %S", _pcps_ddev_bus_flags( pddev ), _pcps_ddev_type_name( pddev ) ); - _evt_msg( GlbDriverObject, pddev->wcs_msg ); + _evt_msg_w( GlbDriverObject, pddev->wcs_msg ); #endif goto fail; } // switch ( _pcps_ddev_bus_flags( pddev ) ) - - // check if all required resources have been assigned - if ( pddev->rsrc_info.num_rsrc_io < port_ranges_required ) + #if _PCPS_USE_MM_IO + if ( !_pcps_ddev_is_pci_mbgpex( pddev ) || force_io_access ) + #endif { - _mbgddmsg_3( MBG_DBG_INIT_DEV, "PCPS start device %X fails: port ranges (%u) less than required (%u)", - _pcps_ddev_dev_id( pddev ), pddev->rsrc_info.num_rsrc_io, port_ranges_required ); - _pcps_ddev_set_err_flags( pddev, PCPS_EF_IO_INIT ); - goto fail; + // check if all required I/O resources have been assigned + if ( pddev->rsrc_info.num_rsrc_io < port_ranges_required ) + { + _mbgddmsg_3( MBG_DBG_INIT_DEV, "PCPS start device %X fails: port ranges (%u) less than required (%u)", + _pcps_ddev_dev_id( pddev ), pddev->rsrc_info.num_rsrc_io, port_ranges_required ); + _pcps_ddev_set_err_flags( pddev, PCPS_EF_IO_INIT ); + goto fail; + } } + #if _PCPS_USE_MM_IO + pddev->use_mm_io = 0; // default, eventually changed later + #endif + if ( _pcps_ddev_is_pci_mbgpex( pddev ) ) { pddev->irq_enb_disb_port = _pcps_ddev_io_base_mapped( pddev, 0 ) @@ -2673,12 +3992,48 @@ int pcps_start_device( PCPS_DDEV *pddev, pddev->irq_ack_port = pddev->irq_enb_disb_port; pddev->irq_ack_mask = PCI_ASIC_PCI_IRQF; + + _mbgddmsg_1( MBG_DBG_INIT_DEV, "%s: pcps_probe_device: interface is MBGPEX", + pcps_driver_name ); + + #if _PCPS_USE_MM_IO + if ( force_io_access ) + { + #if defined( MBG_TGT_LINUX ) //##+++++++++++++++++++++++ + printk( KERN_INFO "%s: Forced I/O access for %s\n", + pcps_driver_name, _pcps_ddev_type_name( pddev ) ); + #endif + } + else + { + if ( map_sys_virtual_address( pddev ) < 0 ) + goto fail_with_cleanup; + + #if DEBUG_IO && defined( MBG_TGT_LINUX ) + printk( KERN_ERR "io_addr: 0x%llX, cmd: 0x%llX\n", + (unsigned long long) _pcps_ddev_io_base_mapped( pddev, 0 ), + (unsigned long long) _pcps_ddev_io_base_mapped( pddev, 0 ) + offsetof( PCI_ASIC, pci_data ) + ); + + printk( KERN_ERR "mm_addr: %p, cmd: %p, tstamp: %p\n", + pddev->mm_addr, + &pddev->mm_addr->mbgpex.asic.pci_data.ul, + pddev->mm_tstamp_addr + ); + #endif + + pddev->read = pcps_read_asic_mm; + pddev->use_mm_io = 1; + } + #endif // _PCPS_USE_MM_IO + goto chip_setup_done; } - // setup additional properties depending on the - // type of bus interface chip + // Setup additional properties depending on the + // type of bus interface chip. + if ( _pcps_ddev_is_pci_pex8311( pddev ) ) { // I/O and memory ranges must be swapped for the @@ -2712,12 +4067,12 @@ int pcps_start_device( PCPS_DDEV *pddev, // Attention: the interrupt control/status register is located in // the PLX configuration space which is addressed by a different // port address range than the normal data ports !! - pddev->irq_enb_disb_port = _pcps_ddev_io_base_mapped( pddev, 1 ) + PLX8311_REG_INTCSR; - pddev->irq_enb_mask = PLX8311_INT_ENB; - pddev->irq_disb_mask = PLX8311_INT_ENB; + pddev->irq_enb_disb_port = _pcps_ddev_io_base_mapped( pddev, 1 ) + PLX_LCS_INTCSR; + pddev->irq_enb_mask = PLX_LCS_INTCSR_INT_ENB; + pddev->irq_disb_mask = PLX_LCS_INTCSR_INT_ENB; - pddev->irq_flag_port = _pcps_ddev_io_base_mapped( pddev, 1 ) + PLX8311_REG_INTCSR; - pddev->irq_flag_mask = PLX8311_INT_FLAG; + pddev->irq_flag_port = _pcps_ddev_io_base_mapped( pddev, 1 ) + PLX_LCS_INTCSR; + pddev->irq_flag_mask = PLX_LCS_INTCSR_INT_FLAG; pddev->irq_ack_port = _pcps_ddev_io_base_mapped( pddev, 0 ) + offsetof( PCI_ASIC, control_status ); pddev->irq_ack_mask = PCI_ASIC_PCI_IRQF; @@ -2753,6 +4108,8 @@ int pcps_start_device( PCPS_DDEV *pddev, chip_setup_done: + // Chip-specific setup done. Continue with common device setup. + pddev->status_port = _pcps_ddev_io_base_mapped( pddev, 0 ) + status_port_offs; // Set up the resource list in pddev->dev.cfg which @@ -2767,8 +4124,8 @@ chip_setup_done: prsrc = &pddev->rsrc_info.port[i]; - // if the resource len has not yet been set - // then use the default resource len + // If the resource len has not yet been set + // then use the default resource len. if ( prsrc->num == 0 ) prsrc->num = port_rsrc_len[i]; @@ -2777,7 +4134,7 @@ chip_setup_done: pddev->dev.cfg.irq_num = pddev->rsrc_info.num_rsrc_irq ? pddev->rsrc_info.irq.num : -1; - pddev->dev.cfg.status_port = _pcps_ddev_port_base( pddev, 0 ) + status_port_offs; + pddev->dev.cfg.short_status_port = _pcps_ddev_short_port_base( pddev, 0 ) + status_port_offs; pddev->dev.cfg.timeout_clk = PCPS_TIMEOUT_CNT; @@ -2801,7 +4158,7 @@ chip_setup_done: #if _PCPS_USE_RSRCMGR rc = pcps_rsrc_claim( pddev ); - if ( rc < 0 ) + if ( mbg_rc_is_error( rc ) ) { _mbgddmsg_1( MBG_DBG_INIT_DEV, "PCPS start device %X: failed to alloc resources", _pcps_ddev_dev_id( pddev ) ); @@ -2812,32 +4169,41 @@ chip_setup_done: // There are some BIOSs out there which don't configure some PEX cards // properly, and thus the cards can not be accessed properly. - // See note near the definition of _pcps_pci_cfg_err() for details. + // See note near the definition of ::_pcps_pci_cfg_err for details. if ( _pcps_ddev_pci_cfg_err( pddev ) ) { -#if 0 //##+++++++++++++++++++++++++ #if defined( MBG_TGT_LINUX ) - printk( KERN_WARNING "PTP270PEX startup delay: %li.%03li s\n", - dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); + printk( KERN_WARNING "%s: duplicate base address 0x%04lX, device %s will not work properly (BIOS faulty)\n", + pcps_driver_name, (ulong) _pcps_ddev_io_base_raw( pddev, 0 ), _pcps_ddev_type_name( pddev ) ); #elif defined( MBG_TGT_BSD ) - printf( "PTP270PEX startup delay: %li.%03li s\n", - dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); + printf( "%s: duplicate base address 0x%04lX, device %s will not work properly (BIOS faulty)\n", + pcps_driver_name, (ulong) _pcps_ddev_io_base_raw( pddev, 0 ), _pcps_ddev_type_name( pddev ) ); #elif defined( MBG_TGT_WIN32 ) - swprintf( wcs_msg, L"PTP270PEX startup delay: %li.%03li s", - dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); - _evt_msg( GlbDriverObject, wcs_msg ); + swprintf( pddev->wcs_msg, L"duplicate base address 0x%04lX, device %s will not work properly (BIOS faulty)", + (ulong) _pcps_ddev_io_base_raw( pddev, 0 ), _pcps_ddev_type_name( pddev ) ); + _evt_msg_w( GlbDriverObject, pddev->wcs_msg ); #endif -#endif } - // Make sure a PTP270PEX card has finished booting. - if ( _pcps_ddev_dev_id( pddev ) == PCI_DEV_PTP270PEX ) - check_uptime(); - // try to read EPROM ID + #if 0 && DEBUG //###++++++++++++++ TODO testing only + { + MBG_SYS_UPTIME uptime; + mbg_get_sys_uptime( &uptime ); + mbg_sleep_sec( 1 ); + mbg_get_sys_uptime( &uptime ); + } + #endif + + // A PTP270PEX card must have finished booting + // before it can be accessed. + if ( pcps_ddev_is_ptp270pex( pddev ) ) + wait_ptp270pex_ready( pddev ); + + // try to read firmware ID rc = pcps_get_fw_id( pddev, pddev->dev.cfg.fw_id ); - if ( rc < 0 ) + if ( mbg_rc_is_error( rc ) ) { if ( _pcps_ddev_is_isa( pddev ) ) { @@ -2845,12 +4211,12 @@ chip_setup_done: // a given port, so if the firmware ID could not be read then this // just means there is no device using the given port address. #if defined( MBG_TGT_WIN32 ) - swprintf( pddev->wcs_msg, L"No ISA card found at port %03lXh.", - (ulong) _pcps_ddev_port_base( pddev, 0 ) ); - _evt_msg( GlbDriverObject, pddev->wcs_msg ); + swprintf( pddev->wcs_msg, L"No ISA card found at port %03lXh.", + (ulong) _pcps_ddev_io_base_raw( pddev, 0 ) ); + _evt_msg_w( GlbDriverObject, pddev->wcs_msg ); #else _mbgddmsg_1( MBG_DBG_INIT_DEV, "No ISA card found at port %03lXh.", - (ulong) _pcps_ddev_port_base( pddev, 0 ) ); + (ulong) _pcps_ddev_io_base_raw( pddev, 0 ) ); #endif } else @@ -2858,7 +4224,7 @@ chip_setup_done: // Non-ISA devices are detected by some other means, so if the firmware // ID could not be read this is a serious error. #if defined( MBG_TGT_WIN32 ) //##+++ debug or not debug ... ;-) - _evt_msg( GlbDriverObject, L"StartDevice: failed to read firmware ID" ); + _evt_msg_w( GlbDriverObject, L"StartDevice: failed to read firmware ID" ); #else _mbgddmsg_1( MBG_DBG_INIT_DEV, "PCPS start device %X: failed to read firmware ID", _pcps_ddev_dev_id( pddev ) ); @@ -2879,7 +4245,7 @@ chip_setup_done: dev_type = PCPS_TYPE_GPS167PC; else { - if ( pcps_check_id( pddev, fw_id_ref_pcps ) == MBG_SUCCESS ) + if ( mbg_rc_is_success( pcps_check_id( pddev, fw_id_ref_pcps ) ) ) { // Device is a PC31, or a PC32 if it has signature code. // If no support for MCA has been compiled in, it may even @@ -2891,7 +4257,7 @@ chip_setup_done: } else { - _pcps_ddev_set_err_flags( pddev, PCPS_EF_INV_EPROM_ID ); + _pcps_ddev_set_err_flags( pddev, PCPS_EF_INV_FW_ID ); goto fail_with_cleanup; } } @@ -2909,21 +4275,35 @@ chip_setup_done: // If the device has an ASIC or EPLD read the ASIC version number if ( _pcps_ddev_has_asic_version( pddev ) ) { - pddev->raw_asic_version = _mbg_inp32_to_cpu( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 ) - + offsetof( PCI_ASIC, raw_version ) ); - - _mbg_swab_asic_version( &pddev->raw_asic_version ); + #if _PCPS_USE_MM_IO + if ( pddev->use_mm_io ) + { + pddev->raw_asic_version = pddev->mm_addr->mbgpex.asic.raw_version; + _mbg_swab_asic_version( &pddev->raw_asic_version ); + _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: pcps_probe_device: raw ASIC version %04X read via MM", + pcps_driver_name, pddev->raw_asic_version ); + } + else + #endif // _PCPS_USE_MM_IO + { + pddev->raw_asic_version = _mbg_inp32_to_cpu( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 ) + + offsetof( PCI_ASIC, raw_version ) ); + _mbg_swab_asic_version( &pddev->raw_asic_version ); + _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: pcps_probe_device: raw ASIC version %04X read via I/O", + pcps_driver_name, pddev->raw_asic_version ); + } pddev->asic_version = _convert_asic_version_number( pddev->raw_asic_version ); } - // Setup some feature flags which depend on the device type + // Setup some feature flags which depend on the device type // and firmware version. - switch( _pcps_ddev_type_num( pddev ) ) + switch ( _pcps_ddev_type_num( pddev ) ) { case PCPS_TYPE_PC31: case PCPS_TYPE_PS31_OLD: case PCPS_TYPE_PS31: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_PC31PS31; check_feature( pddev, REV_CAN_SET_TIME_PC31PS31, PCPS_CAN_SET_TIME ); check_feature( pddev, REV_HAS_SERIAL_PC31PS31, PCPS_HAS_SERIAL ); @@ -2932,20 +4312,24 @@ chip_setup_done: break; case PCPS_TYPE_PC32: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_PC32; break; case PCPS_TYPE_PCI32: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_PCI32; break; case PCPS_TYPE_GPS167PC: + pddev->builtin_features = BUILTIN_FEAT_GPS167PC; pddev->dev.cfg.features = PCPS_FEAT_GPS167PC; check_feature( pddev, REV_HAS_HR_TIME_GPS167PC, PCPS_HAS_HR_TIME ); check_feature( pddev, REV_HAS_CABLE_LEN_GPS167PC, PCPS_HAS_CABLE_LEN ); break; case PCPS_TYPE_GPS167PCI: + pddev->builtin_features = BUILTIN_FEAT_GPS167PCI; pddev->dev.cfg.features = PCPS_FEAT_GPS167PCI; check_feature( pddev, REV_HAS_CABLE_LEN_GPS167PCI, PCPS_HAS_CABLE_LEN ); check_feature( pddev, REV_CAN_CLR_UCAP_BUFF_GPS167PCI, PCPS_CAN_CLR_UCAP_BUFF ); @@ -2953,43 +4337,52 @@ chip_setup_done: break; case PCPS_TYPE_PCI509: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_PCI509; break; case PCPS_TYPE_GPS168PCI: + pddev->builtin_features = BUILTIN_FEAT_GPS168PCI; pddev->dev.cfg.features = PCPS_FEAT_GPS168PCI; check_feature( pddev, REV_CAN_CLR_UCAP_BUFF_GPS168PCI, PCPS_CAN_CLR_UCAP_BUFF ); check_feature( pddev, REV_HAS_UCAP_GPS168PCI, PCPS_HAS_UCAP ); break; case PCPS_TYPE_PCI510: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_PCI510; break; case PCPS_TYPE_GPS169PCI: + pddev->builtin_features = BUILTIN_FEAT_GPS169PCI; pddev->dev.cfg.features = PCPS_FEAT_GPS169PCI; check_feature( pddev, REV_HAS_GPS_DATA_16_GPS169PCI, PCPS_HAS_GPS_DATA_16 ); break; case PCPS_TYPE_TCR510PCI: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_TCR510PCI; check_feature( pddev, REV_HAS_HR_TIME_TCR510PCI, PCPS_HAS_HR_TIME ); break; case PCPS_TYPE_TCR167PCI: + pddev->builtin_features = BUILTIN_FEAT_TCR167PCI; pddev->dev.cfg.features = PCPS_FEAT_TCR167PCI; break; case PCPS_TYPE_GPS170PCI: + pddev->builtin_features = BUILTIN_FEAT_GPS170PCI; pddev->dev.cfg.features = PCPS_FEAT_GPS170PCI; break; case PCPS_TYPE_PCI511: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_PCI511; check_feature( pddev, REV_HAS_HR_TIME_PCI511, PCPS_HAS_HR_TIME ); break; case PCPS_TYPE_TCR511PCI: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_TCR511PCI; check_feature( pddev, REV_HAS_IRIG_CTRL_BITS_TCR511PCI, PCPS_HAS_IRIG_CTRL_BITS ); check_feature( pddev, REV_HAS_IRIG_TIME_TCR511PCI, PCPS_HAS_IRIG_TIME ); @@ -2997,8 +4390,9 @@ chip_setup_done: break; case PCPS_TYPE_PEX511: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_PEX511; - // HR time support for the PEX511 requires both a certain ASIC + // HR time support for the PEX511 requires both a certain ASIC // version plus a certain firmware version. if ( _pcps_asic_version_greater_equal( _pcps_ddev_asic_version( pddev ), PCI_ASIC_MAJOR_PEX511, PCI_ASIC_HR_TIME_MINOR_PEX511 ) ) @@ -3009,6 +4403,7 @@ chip_setup_done: break; case PCPS_TYPE_TCR511PEX: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_TCR511PEX; check_feature( pddev, REV_HAS_IRIG_CTRL_BITS_TCR511PEX, PCPS_HAS_IRIG_CTRL_BITS ); check_feature( pddev, REV_HAS_IRIG_TIME_TCR511PEX, PCPS_HAS_IRIG_TIME ); @@ -3018,16 +4413,19 @@ chip_setup_done: break; case PCPS_TYPE_GPS170PEX: + pddev->builtin_features = BUILTIN_FEAT_GPS170PEX; pddev->dev.cfg.features = PCPS_FEAT_GPS170PEX; pcps_check_pex_irq_unsafe( pddev, REV_HAS_IRQ_FIX_MINOR_GPS170PEX, PCI_ASIC_MAJOR_GPS170PEX, PCI_ASIC_FIX_IRQ_MINOR_GPS170PEX ); break; case PCPS_TYPE_USB5131: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_USB5131; break; case PCPS_TYPE_TCR51USB: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_TCR51USB; check_feature( pddev, REV_HAS_IRIG_CTRL_BITS_TCR51USB, PCPS_HAS_IRIG_CTRL_BITS ); check_feature( pddev, REV_HAS_IRIG_TIME_TCR51USB, PCPS_HAS_IRIG_TIME ); @@ -3035,53 +4433,80 @@ chip_setup_done: break; case PCPS_TYPE_MSF51USB: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_MSF51USB; break; case PCPS_TYPE_PTP270PEX: + pddev->builtin_features = BUILTIN_FEAT_PTP270PEX; pddev->dev.cfg.features = PCPS_FEAT_PTP270PEX; break; case PCPS_TYPE_FRC511PEX: + pddev->builtin_features = BUILTIN_FEAT_FRC511PEX; pddev->dev.cfg.features = PCPS_FEAT_FRC511PEX; break; case PCPS_TYPE_TCR170PEX: + pddev->builtin_features = BUILTIN_FEAT_TCR170PEX; pddev->dev.cfg.features = PCPS_FEAT_TCR170PEX; break; case PCPS_TYPE_WWVB51USB: + pddev->builtin_features = BUILTIN_FEAT_WWVB511; pddev->dev.cfg.features = PCPS_FEAT_WWVB51USB; break; case PCPS_TYPE_GPS180PEX: + pddev->builtin_features = BUILTIN_FEAT_GPS180PEX; pddev->dev.cfg.features = PCPS_FEAT_GPS180PEX; break; case PCPS_TYPE_TCR180PEX: + pddev->builtin_features = BUILTIN_FEAT_TCR180PEX; pddev->dev.cfg.features = PCPS_FEAT_TCR180PEX; break; case PCPS_TYPE_DCF600USB: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_DCF600USB; break; case PCPS_TYPE_PZF180PEX: + pddev->builtin_features = BUILTIN_FEAT_PZF180PEX; pddev->dev.cfg.features = PCPS_FEAT_PZF180PEX; break; case PCPS_TYPE_TCR600USB: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_TCR600USB; break; case PCPS_TYPE_MSF600USB: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_MSF600USB; break; case PCPS_TYPE_WVB600USB: + pddev->builtin_features = BUILTIN_FEAT_UNDEFINED; pddev->dev.cfg.features = PCPS_FEAT_WVB600USB; break; + case PCPS_TYPE_GLN180PEX: + pddev->builtin_features = BUILTIN_FEAT_GLN180PEX; + pddev->dev.cfg.features = PCPS_FEAT_GLN180PEX; + break; + + case PCPS_TYPE_GPS180AMC: + pddev->builtin_features = BUILTIN_FEAT_GPS180AMC; + pddev->dev.cfg.features = PCPS_FEAT_GPS180AMC; + break; + + case PCPS_TYPE_GNS181PEX: + pddev->builtin_features = BUILTIN_FEAT_GNS181PEX; + pddev->dev.cfg.features = PCPS_FEAT_GNS181PEX; + break; + default: #if defined( MBG_TGT_LINUX ) printk( KERN_WARNING "%s: no feature detection for device %s\n", @@ -3092,7 +4517,7 @@ chip_setup_done: #elif defined( MBG_TGT_WIN32 ) swprintf( pddev->wcs_msg, L"no feature detection for device %S", _pcps_ddev_type_name( pddev ) ); - _evt_msg( GlbDriverObject, pddev->wcs_msg ); + _evt_msg_w( GlbDriverObject, pddev->wcs_msg ); #endif goto fail_with_cleanup; @@ -3101,15 +4526,15 @@ chip_setup_done: if ( _pcps_ddev_has_receiver_info( pddev ) ) { - rc = _pcps_read_gps_var( pddev, PC_GPS_RECEIVER_INFO, pddev->ri ); + rc = _pcps_read_gps_var( pddev, PC_GPS_RECEIVER_INFO, *p_ri ); - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) { - _mbg_swab_receiver_info( &pddev->ri ); + _mbg_swab_receiver_info( p_ri ); _mbgddmsg_1( MBG_DBG_INIT_DEV, "Successfully read receiver info from dev %X", _pcps_ddev_dev_id( pddev ) ); - goto check; + goto receiver_info_done; } _mbgddmsg_1( MBG_DBG_INIT_DEV, "Failed to read receiver info from dev %X", @@ -3121,21 +4546,70 @@ chip_setup_done: _pcps_ddev_dev_id( pddev ) ); if ( _pcps_ddev_is_gps( pddev ) ) - _setup_default_receiver_info_gps( &pddev->ri ); + _setup_default_receiver_info_gps( p_ri ); else - _setup_default_receiver_info_dcf( &pddev->ri, &pddev->dev ); + _setup_default_receiver_info_dcf( p_ri, &pddev->dev ); +receiver_info_done: -check: - #if DEBUG_IO - _mbgddmsg_1( MBG_DBG_DETAIL, "ri.sw_rev.code: %04X", pddev->ri.sw_rev.code ); - _mbgddmsg_1( MBG_DBG_DETAIL, "ri.model_code: %04X", pddev->ri.model_code ); - _mbgddmsg_3( MBG_DBG_DETAIL, "ri.model_name: %-*.*s", (int) sizeof( pddev->ri.model_name ), - (int) sizeof( pddev->ri.model_name ), pddev->ri.model_name ); - #endif + #if defined( DEBUG ) + _mbgddmsg_1( MBG_DBG_DETAIL, "ri.model_code: 0x%04X", + p_ri->model_code ); + + _mbgddmsg_3( MBG_DBG_DETAIL, "ri.model_name: \"%-*.*s\"", + (int) sizeof( p_ri->model_name ), + (int) sizeof( p_ri->model_name ), + p_ri->model_name ); + + _mbgddmsg_4( MBG_DBG_DETAIL, "ri.sw_rev: code 0x%04X, name \"%-*.*s\"", + p_ri->sw_rev.code, + (int) sizeof( p_ri->sw_rev.name ), + (int) sizeof( p_ri->sw_rev.name ), + p_ri->sw_rev.name ); + + _mbgddmsg_3( MBG_DBG_DETAIL, "ri.sernum: \"%-*.*s\"", + (int) sizeof( p_ri->sernum ), + (int) sizeof( p_ri->sernum ), + p_ri->sernum ); + + _mbgddmsg_3( MBG_DBG_DETAIL, "ri.epld_name: \"%-*.*s\"", + (int) sizeof( p_ri->epld_name ), + (int) sizeof( p_ri->epld_name ), + p_ri->epld_name ); + + _mbgddmsg_1( MBG_DBG_DETAIL, "ri.n_channels: %u", + p_ri->n_channels ); + _mbgddmsg_1( MBG_DBG_DETAIL, "ri.ticks_per_sec: %lu", + (ulong) p_ri->ticks_per_sec ); -#if 0 //##+++++++++ check if this is reasonnable + _mbgddmsg_1( MBG_DBG_DETAIL, "ri.features: 0x%08lX", + (ulong) p_ri->features ); + + _mbgddmsg_2( MBG_DBG_DETAIL, "ri.fixed_freq: khz_val %u, range %i", + p_ri->fixed_freq.khz_val, + p_ri->fixed_freq.range ); + + _mbgddmsg_2( MBG_DBG_DETAIL, "ri.osc type: %u, flags: 0x%02X", + p_ri->osc_type, p_ri->osc_flags ); + + _mbgddmsg_1( MBG_DBG_DETAIL, "ri.n_ucaps: %u", + p_ri->n_ucaps ); + + _mbgddmsg_1( MBG_DBG_DETAIL, "ri.n_com_ports: %u", + p_ri->n_com_ports ); + + _mbgddmsg_1( MBG_DBG_DETAIL, "ri.n_str_type: %u", + p_ri->n_str_type ); + + _mbgddmsg_1( MBG_DBG_DETAIL, "ri.n_prg_out: %u", + p_ri->n_prg_out ); + + _mbgddmsg_1( MBG_DBG_DETAIL, "ri.flags: 0x%04X", + p_ri->flags ); +#endif + +#if 0 //###+++++++++ TODO check if this is reasonable // Make sure this program supports at least as many ports as // the current clock device. @@ -3156,43 +4630,67 @@ check: } #endif - // detect the presence of some optional features at run time _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s v%03X RECEIVER_INFO features: 0x%08lX", _pcps_ddev_type_name( pddev ), _pcps_ddev_fw_rev_num( pddev ), - (ulong) pddev->ri.features ); - - check_ri_feature( pddev, &pddev->ri, GPS_HAS_IRIG_TX, PCPS_HAS_IRIG_TX ); - check_ri_feature( pddev, &pddev->ri, GPS_HAS_IRIG_CTRL_BITS, PCPS_HAS_IRIG_CTRL_BITS ); - check_ri_feature( pddev, &pddev->ri, GPS_HAS_SYNTH, PCPS_HAS_SYNTH ); - check_ri_feature( pddev, &pddev->ri, GPS_HAS_TIME_SCALE, PCPS_HAS_TIME_SCALE ); - - // Devices which support a configurable time scale do also - // support reading/writing the GPS UTC parameters via the PC bus. - // This is not explicitely coded in the rcvr_info structure - // since the the rcvr_info structure can also be read via - // the serial port, and reading/writing the GPS UTC parameters - // via the serial port is supported by all GPS devices anyway. - check_ri_feature( pddev, &pddev->ri, GPS_HAS_TIME_SCALE, PCPS_HAS_UTC_PARM ); - - // Devices which support reading raw IRIG data via the PC interface also support - // reading the raw IRIG time. However, there is no receiver info feature flag - // since this call is not supported via the serial interface, so we use the - // GPS_HAS_RAW_IRIG_DATA flag to check both features. - check_ri_feature( pddev, &pddev->ri, GPS_HAS_RAW_IRIG_DATA, PCPS_HAS_IRIG_TIME ); - check_ri_feature( pddev, &pddev->ri, GPS_HAS_RAW_IRIG_DATA, PCPS_HAS_RAW_IRIG_DATA ); - - check_ri_feature( pddev, &pddev->ri, GPS_HAS_LAN_IP4, PCPS_HAS_LAN_INTF ); - check_ri_feature( pddev, &pddev->ri, GPS_HAS_PTP, PCPS_HAS_PTP ); - check_ri_feature( pddev, &pddev->ri, GPS_HAS_PTP_UNICAST, 0 ); // no equivalent in PCPS_DDEV features + (ulong) *_ri_addr( pddev ).features ); + + check_ri_features( pddev ); + + _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s v%03X actual features 1: 0x%08lX", + _pcps_ddev_type_name( pddev ), _pcps_ddev_fw_rev_num( pddev ), + (ulong) _pcps_ddev_features( pddev ) ); #if !defined( MBG_TGT_OS2 ) && !defined( MBG_TGT_BSD ) // Function strstr may not be supported at kernel level, - // but this is not required, in most cases, either. + // but this is not required, in most cases, anyway. if ( strstr( _pcps_ddev_fw_id( pddev ), "CERN" ) != NULL ) pddev->dev.cfg.features |= PCPS_HAS_EVENT_TIME; #endif + + // Check if the device supports extended features + + rc = pcps_chk_dev_feat( pddev, DEV_FEAT_REQ_TYPE_RI, GPS_FEAT_XFEATURE ); + + if ( mbg_rc_is_success( rc ) ) + { + _mbgddmsg_1( MBG_DBG_INIT_DEV, "%s going to read XFEATURE_BUFFER", _pcps_ddev_type_name( pddev ) ); + + rc = _pcps_read_gps_var( pddev, PC_GPS_XFEATURE_BUFFER, *_xfeat_addr( pddev ) ); + + if ( mbg_rc_is_error( rc ) ) + { + #if defined( MBG_TGT_LINUX ) + printk( KERN_ERR "%s: failed to read XFEATURE_BUFFER from device %s\n", + pcps_driver_name, _pcps_ddev_type_name( pddev ) ); + #endif + memset( _xfeat_addr( pddev ), 0, sizeof( *_xfeat_addr( pddev ) ) ); + } + } + + + // Check if the device supports the TLV API + + rc = pcps_chk_dev_feat( pddev, DEV_FEAT_REQ_TYPE_XFEAT, MBG_XFEATURE_TLV_API ); + + if ( mbg_rc_is_success( rc ) ) + { + _mbgddmsg_1( MBG_DBG_INIT_DEV, "%s going to read TLV_INFO", _pcps_ddev_type_name( pddev ) ); + + rc = _pcps_read_gps_var( pddev, PC_GPS_TLV_INFO, *_tlv_info_addr( pddev ) ); + + if ( mbg_rc_is_error( rc ) ) + { + #if defined( MBG_TGT_LINUX ) + printk( KERN_ERR "%s: failed to read TLV_INFO from device %s\n", + pcps_driver_name, _pcps_ddev_type_name( pddev ) ); + #endif + memset( _tlv_info_addr( pddev ), 0, sizeof( *_tlv_info_addr( pddev ) ) ); + } + } + + #if DEBUG_IO && defined( MBG_TGT_LINUX ) { PCPS_TIME t = { 0 }; @@ -3215,6 +4713,10 @@ check: _mbg_swab_asic_features( &pddev->asic_features ); + _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s v%03X asic_features: 0x%08lX", + _pcps_ddev_type_name( pddev ), _pcps_ddev_fw_rev_num( pddev ), + (ulong) pddev->asic_features ); + #if MBG_TGT_SUPP_MEM_ACC if ( pddev->asic_features & PCI_ASIC_HAS_MM_IO ) pddev->dev.cfg.features |= PCPS_HAS_FAST_HR_TSTAMP; @@ -3227,10 +4729,10 @@ check: "Warning: ASIC features don't reflect memory mapped time stamp support." ); } - if ( pddev->dev.cfg.features & PCPS_HAS_FAST_HR_TSTAMP ) - if ( map_sys_virtual_address( pddev ) < 0 ) - goto fail_with_cleanup; - + if ( !has_mapped_sys_virtual_address( pddev ) ) + if ( pddev->dev.cfg.features & PCPS_HAS_FAST_HR_TSTAMP ) + if ( map_sys_virtual_address( pddev ) < 0 ) + goto fail_with_cleanup; #endif } @@ -3249,11 +4751,18 @@ fail_with_cleanup: fail: return MBG_ERR_GENERIC; -} // pcps_start_device +} // pcps_probe_device /*HDR*/ +/** + * @brief Clean up function called by ::pcps_probe_device on error + * + * @param[in,out] pddev Pointer to the device structure + * + * @see ::pcps_probe_device + */ void pcps_cleanup_device( PCPS_DDEV *pddev ) { pddev->read = pcps_read_null; @@ -3270,17 +4779,27 @@ void pcps_cleanup_device( PCPS_DDEV *pddev ) -/*-------------------------------------------------------------- - * PCI functions - *-------------------------------------------------------------*/ - #if _PCPS_USE_PCI_BIOS static /*HDR*/ +/** + * @brief Read PCI recources for a PCI device on non-PnP systems + * + * This function should be called by the probe routines of any + * target-specific kernel drivers. + * If the device is supported then all specific information including + * supported features is read from the device and stored in sub-structures + * of the device structure addressed by pdev. + * + * @param[in] bus_num The PCI bus number + * @param[in] dev_fnc_num The PCI device/function number + * @param[in,out] pddev Pointer to the device structure to be set up + * + * @return 0 on success, or a combination of @ref PCPS_ERR_FLAG_MASKS masks on error + */ PCPS_ERR_FLAGS pcps_read_pci_rsrc( PCPS_BUS_NUM bus_num, PCPS_SLOT_NUM dev_fnc_num, - PCPS_DDEV *pddev, - PCPS_BUS_FLAGS bus_flags ) + PCPS_DDEV *pddev ) { PCPS_ERR_FLAGS err_flags = 0; uchar irq; @@ -3336,20 +4855,36 @@ done: static /*HDR*/ +/** + * @brief Enable a PCI device which has not yet been enabled + * + * In PnP systems only PCI devices that are required for booting + * are always enabled by the PCI BIOS. Other PCI devices may only + * be fully enabled if a PC BIOS setup option "PNP OS installed" + * is set to "NO". + * If this option is set to "YES" then I/O access to the board + * may still be disabled, and a PnP operating system is expected + * to enable remaining devices when it boots up. + * Drivers can call this function to enable I/O and memory access, + * if required, in case this hasn't been done by the PCI BIOS + * or operating system. + * + * @param[in] bus_num The PCI bus number + * @param[in] dev_fnc_num The PCI device/function number + * @param[in] num_rsrc_mem If != 0 then memory access is also enabled + * + * @return 0 on success, or a combination of @ref PCPS_ERR_FLAG_MASKS masks on error + */ PCPS_ERR_FLAGS pcps_enable_pci_dev( PCPS_BUS_NUM bus_num, PCPS_SLOT_NUM dev_fnc_num, int num_rsrc_mem ) { PCPS_ERR_FLAGS err_flags = 0; - uint16_t pci_command; - uint16_t new_pci_command; + uint16_t pci_command; // current value read from the PCI cfg "command" register + uint16_t new_pci_command; // new value to be written to the PCI cfg "command" register int rc; - // If the option "PNP OS installed" is set to "YES" in the - // PC's BIOS setup, then I/O access to the board may still - // be disabled, so check if the clock is enabled and enable - // access to the board, if nessessary. rc = _mbg_pci_read_cfg_word( bus_num, dev_fnc_num, PCI_CS_COMMAND, &pci_command ); new_pci_command = pci_command | PCI_CMD_ENB_IO_ACC; @@ -3377,13 +4912,19 @@ PCPS_ERR_FLAGS pcps_enable_pci_dev( PCPS_BUS_NUM bus_num, /*HDR*/ +/** + * @brief Setup and start a PCI device in a non-PnP system + * + * @param[in,out] pddev Pointer to the device structure to be set up + * @param[in] bus_num The PCI bus number returned by the PCI BIOS + * @param[in] dev_fnc_num The PCI device/function number returned by the PCI BIOS + */ void pcps_setup_and_start_pci_dev( PCPS_DDEV *pddev, PCPS_BUS_NUM bus_num, PCPS_SLOT_NUM dev_fnc_num ) { PCPS_ERR_FLAGS err_flags; - err_flags = pcps_read_pci_rsrc( bus_num, dev_fnc_num, - pddev, _pcps_ddev_bus_flags( pddev ) ); + err_flags = pcps_read_pci_rsrc( bus_num, dev_fnc_num, pddev ); _pcps_ddev_set_err_flags( pddev, err_flags ); if ( !( err_flags & PCPS_EF_IO_INIT ) ) @@ -3393,17 +4934,26 @@ void pcps_setup_and_start_pci_dev( PCPS_DDEV *pddev, _pcps_ddev_set_err_flags( pddev, err_flags ); } - pcps_start_device( pddev, bus_num, dev_fnc_num ); + pcps_probe_device( pddev, bus_num, dev_fnc_num ); } // pcps_setup_and_start_pci_dev /*HDR*/ -void pcps_detect_pci_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg, - PCPS_DDEV_CLEANUP_FNC cleanup_fnc, - ushort vendor_id, PCPS_DEV_TYPE dev_type[], - int n_dev_types ) +/** + * @brief Detect and initialize PCI devices in a non-PnP system + * + * @param[in] alloc_fnc Pointer to function called to allocate a device structure for each detected device. + * @param[in] cleanup_fnc Pointer to function called if the device structure needs to be de-allocated in case of error. + * @param[in] vendor_id The PCI vendor ID code. + * @param[in] dev_type An array with known PCI devices for the specified vendor ID + * @param[in] n_dev_types The number of entries in the PCI device table + */ +void pcps_detect_pci_devices( PCPS_DDEV_ALLOC_FNC *alloc_fnc, + PCPS_DDEV_CLEANUP_FNC *cleanup_fnc, + ushort vendor_id, PCPS_DEV_TYPE dev_type[], + int n_dev_types ) { #if defined( MBG_TGT_QNX ) #if defined( MBG_TGT_QNX_NTO ) @@ -3468,6 +5018,9 @@ void pcps_detect_pci_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg, break; // go to try next device ID + _mbgddmsg_2( MBG_DBG_INIT_DEV, "Found PCI device %s (0x%04X)", + p->name, p->dev_id ); + // New device found, try to add to list. pddev = alloc_fnc(); @@ -3493,6 +5046,8 @@ void pcps_detect_pci_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg, if ( cleanup_fnc ) cleanup_fnc( pddev ); } + #else + (void) cleanup_fnc; // avoid compiler warning #endif } } @@ -3503,24 +5058,29 @@ void pcps_detect_pci_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg, _mbg_pci_fnc_deinit(); #endif -} // pcps_detect_pci_clocks +} // pcps_detect_pci_devices #endif // _PCPS_USE_PCI_BIOS -/*-------------------------------------------------------------- - * Try to detect ISA clocks - *-------------------------------------------------------------*/ - #if !_PCPS_USE_ISA_PNP /*HDR*/ -void pcps_detect_isa_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, - PCPS_DDEV_CLEANUP_FNC cleanup_fnc, - PCPS_DDEV_REGISTER_FNC register_fnc, - int isa_ports[PCPS_MAX_ISA_CARDS], - int isa_irqs[PCPS_MAX_ISA_CARDS] ) +/** + * @brief Detect and initialize ISA devices in a non-PnP system + * + * @param[in] alloc_fnc Pointer to function called to allocate a device structure for each detected device. + * @param[in] cleanup_fnc Pointer to function called if the device structure needs to be de-allocated in case of error. + * @param[in] register_fnc Pointer to function called to register a detected device. + * @param[in] isa_ports An array with potential I/O base addresses for ISA devices. + * @param[in] isa_irqs An array with potential IRQ numbers assigned to ISA devices. + */ +void pcps_detect_isa_devices( PCPS_DDEV_ALLOC_FNC *alloc_fnc, + PCPS_DDEV_CLEANUP_FNC *cleanup_fnc, + PCPS_DDEV_REGISTER_FNC *register_fnc, + int isa_ports[PCPS_MAX_ISA_CARDS], + int isa_irqs[PCPS_MAX_ISA_CARDS] ) { int *p_port = isa_ports; int *p_irq = isa_irqs; @@ -3562,7 +5122,7 @@ void pcps_detect_isa_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, // Init the device structure. This includes registration // of I/O ports with the OS's resource manager (if supported), // and reading the firmware ID. - pcps_start_device( pddev, 0, 0 ); + pcps_probe_device( pddev, 0, 0 ); // If an error has occurred, then remove the last // device from the list and try next. @@ -3583,7 +5143,7 @@ void pcps_detect_isa_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, } } -} // pcps_detect_isa_clocks +} // pcps_detect_isa_devices #endif //!_PCPS_USE_ISA_PNP @@ -3591,48 +5151,60 @@ void pcps_detect_isa_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, #if !_PCPS_USE_PNP -/*-------------------------------------------------------------- - * Try to detect any plug-in device. If a DOS TSR is - * installed, be sure it is disabled (BUSY flag set) when - * this function is called. - *-------------------------------------------------------------*/ - -/*HDR*/ -void _MBG_INIT_CODE_ATTR pcps_detect_clocks_alloc( PCPS_DDEV_ALLOC_FNC alloc_fnc, - void *alloc_arg, - PCPS_DDEV_CLEANUP_FNC cleanup_fnc, - int isa_ports[PCPS_MAX_ISA_CARDS], - int isa_irqs[PCPS_MAX_ISA_CARDS] ) +static /*HDR*/ +/** + * @brief Detect all bus-level devices in a non-PnP system, use specific alloc/cleanup functions + * + * @note If a DOS TSR is installed, be sure it is disabled (BUSY flag set) + * when this function is called. + * + * @param[in] alloc_fnc Pointer to function called to allocate a device structure for each detected device. + * @param[in] cleanup_fnc Pointer to function called if the device structure needs to be de-allocated in case of error. + * @param[in] isa_ports An array with potential I/O base addresses for ISA devices. + * @param[in] isa_irqs An array with potential IRQ numbers assigned to ISA devices. + */ +void _MBG_INIT_CODE_ATTR pcps_detect_devices_alloc( PCPS_DDEV_ALLOC_FNC *alloc_fnc, + PCPS_DDEV_CLEANUP_FNC *cleanup_fnc, + int isa_ports[PCPS_MAX_ISA_CARDS], + int isa_irqs[PCPS_MAX_ISA_CARDS] ) { #if defined( MBG_TGT_OS2 ) rsrc_register_driver(); // register driver and init resource manager #endif #if _PCPS_USE_PCI_BIOS - pcps_detect_pci_clocks( alloc_fnc, alloc_arg, cleanup_fnc, - PCI_VENDOR_MEINBERG, pcps_dev_type, N_PCPS_DEV_TYPE ); + pcps_detect_pci_devices( alloc_fnc, cleanup_fnc, PCI_VENDOR_MEINBERG, + pcps_dev_type, N_PCPS_DEV_TYPE ); #endif #if _PCPS_USE_MCA - pcps_detect_mca_clocks( alloc_fnc, alloc_arg ); + pcps_detect_mca_devices( alloc_fnc ); #endif #if !_PCPS_USE_ISA_PNP - pcps_detect_isa_clocks( alloc_fnc, cleanup_fnc, NULL, isa_ports, isa_irqs ); + pcps_detect_isa_devices( alloc_fnc, cleanup_fnc, NULL, isa_ports, isa_irqs ); #endif -} // pcps_detect_clocks_alloc +} // pcps_detect_devices_alloc /*HDR*/ -void _MBG_INIT_CODE_ATTR pcps_detect_clocks( int isa_ports[PCPS_MAX_ISA_CARDS], - int isa_irqs[PCPS_MAX_ISA_CARDS] ) +/** + * @brief Detect all bus-level devices in a non-PnP system + * + * @note If a DOS TSR is installed, be sure it is disabled (BUSY flag set) + * when this function is called. + * + * @param[in] isa_ports An array with potential I/O base addresses for ISA devices. + * @param[in] isa_irqs An array with potential IRQ numbers assigned to ISA devices. + */ +void _MBG_INIT_CODE_ATTR pcps_detect_devices( int isa_ports[PCPS_MAX_ISA_CARDS], + int isa_irqs[PCPS_MAX_ISA_CARDS] ) { - pcps_detect_clocks_alloc( pcps_alloc_ddev, NULL, pcps_free_ddev, - isa_ports, isa_irqs ); + pcps_detect_devices_alloc( pcps_alloc_ddev, pcps_free_ddev, isa_ports, isa_irqs ); -} // pcps_detect_clocks +} // pcps_detect_devices #endif // !_PCPS_USE_PNP diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.h index 8f203c4..405002e 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pcpsdrvr.h 1.41.1.34 2011/07/19 12:48:39 martin TRASH $ + * $Id: pcpsdrvr.h 1.46 2017/07/04 16:50:48 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,79 +10,52 @@ * * ----------------------------------------------------------------------- * $Log: pcpsdrvr.h $ - * Revision 1.41.1.34 2011/07/19 12:48:39 martin + * Revision 1.46 2017/07/04 16:50:48 martin + * Support GPS180AMC and GNS181PEX. + * Support new module parameter force_io_access to provide + * runtime support for forcing I/O rather than MM access. + * Cleaned up I/O port usage. + * Added _pcps_ddev_has_xmr() macro. + * Older defines N_SUPP_DEV, PCPS_MAX_DDEVS, and MBG_MAX_DEVICES + * have been obsoleted by new defines N_SUPP_DEV_BUS, N_SUPP_DEV_EXT, + * and N_SUPP_DEV_TOTAL. + * Conditional USB debug code. + * Use more versatile types for function pointers. + * Fixed macro definition syntax to avoid clang compiler warnings. + * Prepare to use MBG_XDEV_FEATURES in PCPS_DDEV. + * Updated function prototypes. + * Revision 1.45 2013/09/26 09:08:09 martin + * Support GLN180PEX and GNSS API. + * Revision 1.44 2013/03/15 10:01:09 martin + * Optionally override setting to support memory mapped I/O. + * Revision 1.43 2012/11/02 09:48:04 martin + * Removed obsolete include. + * Revision 1.42 2012/10/02 19:09:20 martin + * Conditionally support memory mapped access for MBGPEX cards. + * Support on-board event logs. + * New macro _pcps_ddev_has_debug_status(). + * Added some macros to test if specific stat_info stuff is supported. * Updated function prototypes. - * Code cleanup. - * Revision 1.41.1.33 2011/07/06 11:23:09 martin * Added macros _pcps_ddev_has_corr_info() and _pcps_ddev_has_tr_distance(). - * Revision 1.41.1.32 2011/07/04 10:29:44 martin - * Modified a comment. - * Revision 1.41.1.31 2011/06/29 14:01:32 martin - * Renamed PZF600PEX to PZF180PEX. - * Added support for TCR600USB, MSF600USB, and WVB600USB. + * Support GPS180PEX, TCR180PEX, and PZF180PEX. + * Support DCF600USB, TCR600USB, MSF600USB, and WVB600USB. * New macros _pcps_ddev_is_usb_v2() and _pcps_ddev_has_pcf(). - * Updated some comments. - * Revision 1.41.1.30 2011/06/29 09:10:27 martin - * Renamed PZF600PEX to PZF180PEX. - * Revision 1.41.1.29 2011/05/31 14:24:18 martin - * Revision 1.41.1.28 2011/05/16 16:39:20 martin - * Allocate non-paged memory under Windows. - * Revision 1.41.1.27 2011/05/06 13:47:40Z martin - * Support PZF600PEX. - * Revision 1.41.1.26 2011/04/12 15:50:57 martin - * Revision 1.41.1.25 2011/04/12 15:26:10Z martin - * Moved mutex definitions to new mbgmutex.h. - * Revision 1.41.1.24 2011/04/01 13:32:45 martin - * Added missing mutex destroy for Windows. - * Revision 1.41.1.23 2011/04/01 10:38:42Z martin - * Support mutex/spinlock destroy. - * Revision 1.41.1.22 2011/03/31 10:35:57 martin - * Fixed a typo. - * Revision 1.41.1.21 2011/03/28 09:53:52Z martin - * Modifications for NetBSD from Frank Kardel. - * Revision 1.41.1.20 2011/03/25 11:11:44 martin * Optionally support timespec for sys time (USE_TIMESPEC). - * Started to support NetBSD. - * Revision 1.41.1.19 2011/02/15 14:24:58 martin - * Revision 1.41.1.18 2011/02/09 17:08:31 martin + * Support FreeBSD and NetBSD. * Specify I/O range number when calling port I/O macros * so they can be used for different ranges under BSD. - * Revision 1.41.1.17 2011/02/04 14:44:46 martin - * Revision 1.41.1.16 2011/02/04 10:10:18 martin - * Revision 1.41.1.15 2011/02/02 12:20:42 martin - * Revision 1.41.1.14 2011/02/01 17:12:05 martin - * Revision 1.41.1.13 2011/02/01 14:49:43 martin - * Revision 1.41.1.12 2011/02/01 12:12:19 martin - * Revision 1.41.1.11 2011/01/31 17:30:02 martin - * Modified resource storage for *BSD. - * Revision 1.41.1.10 2011/01/27 13:39:01 martin - * Revision 1.41.1.9 2011/01/27 11:04:45 martin - * Revision 1.41.1.8 2011/01/27 11:01:49 martin - * Support static device list (no malloc) and use it under FreeBSD. - * Revision 1.41.1.7 2011/01/26 16:42:07 martin - * Fixed build under FreeBSD. - * Revision 1.41.1.6 2011/01/25 09:47:27 martin - * Fixed build under FreeBSD. - * Revision 1.41.1.5 2010/11/23 11:07:57 martin - * Support memory mapped access under DOS. - * Revision 1.41.1.4 2010/11/11 09:15:39Z martin - * Added definitions to support DCF600USB. - * Revision 1.41.1.3 2010/08/20 09:35:12 martin * Added macro _pcps_ddev_features(). - * Revision 1.41.1.2 2010/07/14 14:52:12 martin - * Revision 1.41.1.1 2010/06/30 15:01:52 martin - * Support GPS180PEX and TCR180PEX. * Revision 1.41 2010/06/30 13:44:49 martin * Use new preprocessor symbol MBG_ARCH_X86. * Revision 1.40 2010/01/12 14:05:05 daniel - * Added macro to check if reading the + * Added macro to check if reading the * raw IRIG data bits is supported. * Revision 1.39 2009/09/29 07:24:51Z martin * Use standard feature flag to check if fast HR time is supported. * Revision 1.38 2009/06/19 12:13:05 martin * Added _pcps_ddev_has_irig_time() macro. * Revision 1.37 2009/06/09 10:13:59 daniel - * Added macros _pcps_ddev_has_lan_intf( _p ) and + * Added macros _pcps_ddev_has_lan_intf( _p ) and * _pcps_ddev_has_ptp_cfg( _p ). * Cleaned up the low level interface and provided a * possibility to override the macros for special purposes. @@ -95,13 +68,13 @@ * and replaced/merged them with mbg_get_pc_cycles...() functions. * Under Linux use own inline function to read TSC on x86 architectures. * Normally USB timeouts are short with retries in order to increase - * responsiveness. On some systems this may lead to problems, so + * responsiveness. On some systems this may lead to problems, so * optionally one long timeout can be used now by define. * Revision 1.34 2008/12/16 14:40:47 martin * Account for new devices PTP270PEX, FRC270PEX, TCR170PEX, and WWVB51USB. - * Added macros _pcps_ddev_is_ptp(), _pcps_ddev_is_frc(), + * Added macros _pcps_ddev_is_ptp(), _pcps_ddev_is_frc(), * and _pcps_ddev_is_wwvb(). - * Don't use pragma pack( 1 ) but use native alignment since structures + * Don't use pragma pack( 1 ) but use native alignment since structures * defined here are not used across system boundaries. * Added fields to PCPS_DDEV to store the ASIC version, and macros * _pcps_ddev_raw_asic_version() and _pcps_ddev_asic_version(). @@ -151,11 +124,11 @@ * Added macro _pcps_ddev_status_busy(). * Added kernel malloc/free macros and USB I/O macros. * Use PCPS_DDEV as private device data. - * Use ms values for USB timeouts also under Linux. This may not be + * Use ms values for USB timeouts also under Linux. This may not be * appropriate for older kernels. * Limited length of some older RCS log messages. * Revision 1.30 2007/07/25 14:22:23Z martin - * Under Linux include param.h for definition of HZ under + * Under Linux include param.h for definition of HZ under * kernels 2.6.21 and newer. * Revision 1.29 2007/07/17 08:22:48 martin * Added support for TCR511PEX and GPS170PEX. @@ -171,7 +144,7 @@ * Preliminary support for *BSD. * Preliminary support for USB. * Revision 1.26 2006/07/07 09:44:23 martin - * Fixed definition of control macros for the case where + * Fixed definition of control macros for the case where * _PCPS_USE_PCI_PNP is overridden from the command line. * Revision 1.25 2006/06/19 15:31:09 martin * Added support for TCR511PCI. @@ -193,8 +166,8 @@ * Revision 1.19 2004/10/14 15:01:24Z martin * Added support for TCR167PCI. * Revision 1.18 2004/09/06 15:11:04Z martin - * Support a GPS_DATA interface where sizes are specified - * by 16 instead of the original 8 bit quantities, thus allowing + * Support a GPS_DATA interface where sizes are specified + * by 16 instead of the original 8 bit quantities, thus allowing * to transfer data blocks which exceed 255 bytes. * Revision 1.17 2004/04/14 10:29:45Z martin * Pack structures 1 byte aligned. @@ -231,7 +204,7 @@ * New macro _pcps_ddev_has_mod(). * Revision 1.8 2002/02/26 09:34:03 MARTIN * Removed macro _pcps_read_sernum() which was replaced - * by a function pcps_read_sernum() which reads the S/N from + * by a function pcps_read_sernum() which reads the S/N from * any clock that supports a S/N. * Updated function prototypes. * Revision 1.7 2002/02/19 09:28:01 MARTIN @@ -242,12 +215,12 @@ * to follow naming conventions. * Source code cleanup. * Revision 1.5 2001/11/30 09:52:48 martin - * Added support for event_time which, however, requires + * Added support for event_time which, however, requires * a custom GPS firmware. * Revision 1.4 2001/10/16 10:15:44 MARTIN - * New Macro _pcps_ddev_has_serial_hs() which determines + * New Macro _pcps_ddev_has_serial_hs() which determines * whether DCF77 clock supports baud rate higher than default. - * Added some macros and comments corresponding to + * Added some macros and comments corresponding to * pcpsdev.h. * Revision 1.3 2001/09/18 06:53:57 MARTIN * Two sets of preprocessor symbols for Win9x/ME and WinNT/2k. @@ -273,7 +246,9 @@ #define DEBUG_LVL_IO 12 +/* Other headers to be included */ #include <mbg_tgt.h> +#include <xdevfeat.h> #if defined( MBG_TGT_NETWARE ) #define _DEFAULT_PCPS_USE_CLOCK_TICK 1 @@ -399,10 +374,17 @@ #define _MBG_INIT_CODE_ATTR #endif +#if !defined( DEBUG_USB_IO ) + #if ( 0 && defined( DEBUG ) && defined( MBG_TGT_LINUX ) ) + #define DEBUG_USB_IO 1 + #else + #define DEBUG_USB_IO 0 + #endif +#endif -/* Other headers to be included */ #include <pcpsdev.h> +#include <cfg_hlp.h> #include <mbgmutex.h> #include <pci_asic.h> #include <mbgerror.h> @@ -410,7 +392,6 @@ #include <mbggenio.h> #if defined( MBG_TGT_FREEBSD ) - #include <mbg_bsd.h> #include <sys/malloc.h> #include <sys/_null.h> #include <sys/param.h> @@ -432,6 +413,8 @@ #endif #if defined( MBG_TGT_LINUX ) + #include <linux/slab.h> // for kmalloc()/kfree() + #if _PCPS_USE_USB #include <linux/usb.h> #endif @@ -486,16 +469,47 @@ extern "C" { #endif +#define _DEFAULT_PCPS_USE_MM_IO ( MBG_TGT_SUPP_MEM_ACC && !MBG_USE_MM_IO_FOR_PCI ) + +#if !defined( _PCPS_USE_MM_IO ) + #define _PCPS_USE_MM_IO _DEFAULT_PCPS_USE_MM_IO +#endif + +#if _PCPS_USE_MM_IO + + #define _mbg_inp32_ex( _d, _i, _p, _r ) \ + ( (_d)->use_mm_io ? \ + (_d)->mm_addr->mbgpex.asic.control_status.ul : \ + _mbg_inp32( (_d), (_i), (_p) ) \ + ) + + #define _mbg_outp32_ex( _d, _i, _p, _r, _v ) \ + do \ + { \ + if ( (_d)->use_mm_io ) \ + (_d)->mm_addr->mbgpex.asic.control_status.ul = (_v); \ + else \ + _mbg_outp32( _d, _i, _p, _v ); \ + } while ( 0 ) + +#else + + #define _mbg_inp32_ex( _d, _i, _p, _r ) _mbg_inp32( _d, _i, _p ) + #define _mbg_outp32_ex( _d, _i, _p, _r, _v ) _mbg_outp32( _d, _i, _p, _v ) + +#endif + + + // Define some OS-specific primitives to alloc / free memory and handle // mutexes and spinlocks in kernel space. #if defined( MBG_TGT_LINUX ) - #define _pcps_kmalloc( _sz ) kmalloc( _sz, GFP_ATOMIC ) - #define _pcps_kfree( _p, _sz ) kfree( _p ) + #define _pcps_kmalloc( _sz ) kmalloc( _sz, GFP_ATOMIC ) + #define _pcps_kfree( _p, _sz ) kfree( _p ) - //##+++++++++++++++++++ - // The special versions of _pcps_sem_inc() and _pcps_sem_dec() below + // These special versions of _pcps_sem_inc() and _pcps_sem_dec() // are only required to prevent interference with the IRQ handler // under Linux which implements the serial port emulation for the // NTP parse driver. @@ -522,20 +536,31 @@ extern "C" { // See "man 9 malloc" for details. MALLOC_DECLARE( M_MBGCLOCK ); - #define _pcps_kmalloc( _sz ) malloc( _sz, M_MBGCLOCK, M_NOWAIT | M_ZERO ) - #define _pcps_kfree( _p, _sv ) free( _p, M_MBGCLOCK ) + #define _pcps_kmalloc( _sz ) malloc( _sz, M_MBGCLOCK, M_NOWAIT | M_ZERO ) + #define _pcps_kfree( _p, _sv ) free( _p, M_MBGCLOCK ) #elif defined( MBG_TGT_NETBSD ) // For older NetBSD versions which do not suppport the calls // used below, see 'man 9 malloc'. - #define _pcps_kmalloc( _sz ) kmem_alloc( _sz, KM_NOSLEEP ) - #define _pcps_kfree( _p, _sz ) kmem_free( _p, _sz ) + #define _pcps_kmalloc( _sz ) kmem_alloc( _sz, KM_NOSLEEP ) + #define _pcps_kfree( _p, _sz ) kmem_free( _p, _sz ) #elif defined( MBG_TGT_WIN32 ) - #define _pcps_kmalloc( _sz ) ExAllocatePool( NonPagedPool, _sz ) - #define _pcps_kfree( _p, _sz ) ExFreePool( _p ) + #define _pcps_kmalloc( _sz ) ExAllocatePool( NonPagedPool, _sz ) + #define _pcps_kfree( _p, _sz ) ExFreePool( _p ) + +#elif defined( MBG_TGT_DOS ) + + // No multitasking, no device driver, + // so we don't need this. + + #define _pcps_sem_inc( _pddev ) \ + _nop_macro_fnc() + + #define _pcps_sem_dec( _pddev ) \ + _nop_macro_fnc() #endif @@ -550,7 +575,7 @@ extern "C" { -// If the macros below have not yet been defined then define some dummies: +// If these macros have not yet been defined then define some dummies: #if !defined( _pcps_sem_inc ) || !defined( _pcps_sem_dec ) @@ -564,9 +589,7 @@ extern "C" { -/* ------ definitions used with PCI clocks -------------------------- */ - -/* Default timeout count accessing the board */ +// Default timeout count when accessing a device #if _PCPS_USE_CLOCK_TICK #if defined( MBG_TGT_NETWARE ) @@ -587,10 +610,10 @@ extern "C" { #endif -// The structures below are used to provide a consistent +// These structures are used to provide a consistent // resource handling across different platforms. -// This is kept completely inside the kernel drivers, so these -// structures can be modified safely to suit our needs. +// This is kept completely inside the kernel drivers, so the +// structures can be modified safely, as appropriate. #if MBG_USE_MM_IO_FOR_PCI @@ -610,7 +633,11 @@ extern "C" { #else - typedef PCPS_PORT_ADDR PCPS_IO_ADDR_RAW; + #if !defined( MBG_TGT_POSIX ) || defined( MBG_ARCH_X86 ) + typedef uint16_t PCPS_IO_ADDR_RAW; ///< ### TODO ::PCPS_PORT_ADDR_X + #else + typedef uint64_t PCPS_IO_ADDR_RAW; + #endif typedef PCPS_IO_ADDR_RAW PCPS_IO_ADDR_MAPPED; #if defined( MBG_TGT_BSD ) @@ -628,19 +655,19 @@ extern "C" { typedef struct { -#if defined ( MBG_TGT_FREEBSD ) +#if defined( MBG_TGT_FREEBSD ) int rid; /* resource ID */ - struct resource *res; - bus_space_tag_t bst; - bus_space_handle_t bsh; -#elif defined ( MBG_TGT_NETBSD ) - int reg; /* BAR */ - int type; /* type */ - int valid; /* valid flag */ - bus_space_tag_t bst; /* bus space tag */ - bus_space_handle_t bsh; /* bus space handle */ - bus_addr_t base; /* base address */ - bus_size_t size; /* size */ + struct resource *res; ///< Resource information + bus_space_tag_t bst; ///< Bus space tag + bus_space_handle_t bsh; ///< Bus space handle +#elif defined( MBG_TGT_NETBSD ) + int reg; ///< Base Address Register (BAR) + int type; ///< Type + int valid; ///< Valid flag + bus_space_tag_t bst; ///< Bus space tag + bus_space_handle_t bsh; ///< Bus space handle + bus_addr_t base; ///< Base address + bus_size_t size; ///< Size #endif } BSD_RSRC_INFO; @@ -649,27 +676,33 @@ typedef struct /** - The structure below describes an I/O port resource - used by a clock. -*/ + * @brief I/O port resource information for a device + * + * @see ::PCPS_MEM_RSRC + * @see ::PCPS_IRQ_RSRC + */ typedef struct { #if defined( MBG_TGT_BSD ) - BSD_RSRC_INFO bsd; + BSD_RSRC_INFO bsd; ///< *BSD-specific stuff #endif - PCPS_IO_ADDR_MAPPED base_mapped; - PCPS_IO_ADDR_RAW base_raw; - uint16_t num; -} PCPS_IO_RSRC; + PCPS_IO_ADDR_MAPPED base_mapped; ///< A mapped port base address + PCPS_IO_ADDR_RAW base_raw; ///< A raw port base address + ulong num; ///< Number of addresses in this range +} PCPS_IO_RSRC; -// The structure below describes a bus memory resource -// used by a clock. +/** + * @brief Bus memory resource information for a device + * + * @see ::PCPS_IO_RSRC + * @see ::PCPS_IRQ_RSRC + */ typedef struct { #if defined( MBG_TGT_BSD ) - BSD_RSRC_INFO bsd; + BSD_RSRC_INFO bsd; ///< *BSD-specific stuff #endif MBG_MEM_ADDR start; ulong len; @@ -677,84 +710,104 @@ typedef struct } PCPS_MEM_RSRC; - -// The structure below describes a bus IRQ resource -// used by a clock. - +/** + * @brief IRQ resource information for a device + * + * @see ::PCPS_IO_RSRC + * @see ::PCPS_MEM_RSRC + */ typedef struct { #if defined( MBG_TGT_BSD ) - BSD_RSRC_INFO bsd; + BSD_RSRC_INFO bsd; ///< *BSD-specific stuff #endif - ushort num; + uint16_t num; ///< The IRQ number } PCPS_IRQ_RSRC; -// The max number of bus memory resources used by a device. +/** + * @brief The max number of bus memory resources used by a device. + */ #define N_PCPS_MEM_RSRC 2 -// The max number of bus memory and I/O resources used by a device. + +/** + * @brief The max number of bus memory and I/O resources used by a device. + */ #define MAX_PCPS_RSRC ( N_PCPS_MEM_RSRC + N_PCPS_PORT_RSRC ) + +/** + * @brief Resource info summary for a device + */ typedef struct { - int num_rsrc_io; - int num_rsrc_mem; - int num_rsrc_irq; - PCPS_IO_RSRC port[N_PCPS_PORT_RSRC]; - PCPS_MEM_RSRC mem[N_PCPS_MEM_RSRC]; - PCPS_IRQ_RSRC irq; + int num_rsrc_io; ///< Number of actually assigned I/O address ranges + int num_rsrc_mem; ///< Number of actually assigned memory address ranges + int num_rsrc_irq; ///< Number of actually assigned IRQ numbers + PCPS_IO_RSRC port[N_PCPS_PORT_RSRC]; ///< Info on actually assigned port ranges + PCPS_MEM_RSRC mem[N_PCPS_MEM_RSRC]; ///< Info on actually assigned memory ranges + PCPS_IRQ_RSRC irq; ///< Info on actually assigned IRQ numbers + } PCPS_RSRC_INFO; #if _PCPS_USE_USB - typedef struct - { - uint8_t addr; - uint16_t max_packet_size; - } PCPS_USB_EP; +/** + * @brief Information on a USB endpoint + */ +typedef struct +{ + uint8_t addr; + uint16_t max_packet_size; +} PCPS_USB_EP; - #if defined( MBG_TGT_LINUX ) - // definitions used to control the cyclic USB read thread +#if defined( MBG_TGT_LINUX ) + + // definitions used to control the cyclic USB read thread - #if _PCPS_USE_LINUX_KTHREAD + #if _PCPS_USE_LINUX_KTHREAD - // use kthread_run() / kthread_stop() - typedef struct task_struct *PCPS_THREAD_INFO; + // Used by kthread_run() / kthread_stop() + typedef struct task_struct *PCPS_THREAD_INFO; - #else + #else + + // Used by kernel_thread() / daemonize() / kill_proc() + typedef struct + { + pid_t pid; + char name[17]; // 16 chars as supported by the kernel, plus trailing 0 + struct completion exit; - // use kernel_thread() / daemonize() / kill_proc() - typedef struct - { - pid_t pid; - char name[17]; // 16 chars as supported by the kernel, plus trailing 0 - struct completion exit; - } PCPS_THREAD_INFO; + } PCPS_THREAD_INFO; - #endif // _PCPS_USE_LINUX_KTHREAD + #endif // _PCPS_USE_LINUX_KTHREAD - #endif // defined( MBG_TGT_LINUX ) +#endif // defined( MBG_TGT_LINUX ) #endif // _PCPS_USE_USB +/** + * @brief Memory layout of Meinberg PCI interface register + */ typedef union { - struct + struct pex8311 { PCI_ASIC asic; PCPS_TIME_STAMP tstamp; } pex8311; - struct + struct mbgpex { PCI_ASIC asic; uint8_t b[256 - sizeof( PCI_ASIC ) ]; @@ -765,100 +818,102 @@ typedef union } PCPS_MM_LAYOUT; + struct PCPS_DDEV_s; +typedef struct PCPS_DDEV_s PCPS_DDEV; -typedef short (*PCPS_READ_FNC)( struct PCPS_DDEV_s *pddev, uint8_t cmd, void FAR *buffer, uint16_t count ); -typedef short (*PCPS_WRITE_FNC)( struct PCPS_DDEV_s *pddev, uint8_t cmd, const void FAR *buffer, uint16_t count ); -typedef struct PCPS_DDEV_s *(*PCPS_DDEV_ALLOC_FNC)( void ); -typedef void (*PCPS_DDEV_CLEANUP_FNC)( struct PCPS_DDEV_s * ); -typedef int (*PCPS_DDEV_REGISTER_FNC)( struct PCPS_DDEV_s * ); +typedef int PCPS_READ_FNC( PCPS_DDEV *pddev, uint8_t cmd, void FAR *buffer, uint16_t count ); +typedef int PCPS_WRITE_FNC( PCPS_DDEV *pddev, uint8_t cmd, const void FAR *buffer, uint16_t count ); +typedef PCPS_DDEV *PCPS_DDEV_ALLOC_FNC( void ); +typedef void PCPS_DDEV_CLEANUP_FNC( PCPS_DDEV *pddev ); +typedef int PCPS_DDEV_REGISTER_FNC( PCPS_DDEV *pddev ); -typedef struct PCPS_DDEV_s +struct PCPS_DDEV_s { - // the device info data - PCPS_DEV dev; + PCPS_DEV dev; ///< Device info data that can be passed to user space - PCPS_READ_FNC read; + PCPS_READ_FNC *read; ///< Pointer to the read function depending on the PCI interface type - PCPS_IO_ADDR_MAPPED status_port; - PCPS_IO_ADDR_MAPPED irq_enb_disb_port; - PCPS_IO_ADDR_MAPPED irq_flag_port; - PCPS_IO_ADDR_MAPPED irq_ack_port; - uint32_t irq_enb_mask; - uint32_t irq_disb_mask; - uint32_t irq_flag_mask; - uint32_t irq_ack_mask; + PCPS_IO_ADDR_MAPPED status_port; ///< Address of the status port register + PCPS_IO_ADDR_MAPPED irq_enb_disb_port; ///< Address of the IRQ control register + PCPS_IO_ADDR_MAPPED irq_flag_port; ///< Address of the IRQ status register + PCPS_IO_ADDR_MAPPED irq_ack_port; ///< Address of the register to acknowledge an IRQ + uint32_t irq_enb_mask; ///< Bit mask to be set to enable IRQs + uint32_t irq_disb_mask; ///< Bit mask to be cleared to disable IRQs + uint32_t irq_flag_mask; ///< Bit mask used to check if device has generated an IRQ + uint32_t irq_ack_mask; ///< Bit mask to be set to acknowledge an IRQ - PCI_ASIC_VERSION raw_asic_version; - PCI_ASIC_VERSION asic_version; - PCI_ASIC_FEATURES asic_features; - PCPS_RSRC_INFO rsrc_info; + PCI_ASIC_VERSION raw_asic_version; ///< Raw ASIC version + PCI_ASIC_VERSION asic_version; ///< ASIC version + PCI_ASIC_FEATURES asic_features; ///< ASIC feature mask + PCPS_RSRC_INFO rsrc_info; ///< Summary of resources used by the device - MBG_PC_CYCLES acc_cycles; + MBG_PC_CYCLES acc_cycles; ///< Cycles count taken when device was accessed last time #if defined( _MBG_MUTEX_DEFINED ) - MBG_MUTEX dev_mutex; + MBG_MUTEX dev_mutex; ///< Mutex used for device access serialization #endif - PCPS_MM_LAYOUT FAR *mm_addr; - volatile PCPS_TIME_STAMP FAR *mm_tstamp_addr; + PCPS_MM_LAYOUT FAR *mm_addr; ///< Base address of the memory-mapped register block + volatile PCPS_TIME_STAMP FAR *mm_tstamp_addr; ///< Memory mapped address of the timestamp register #if defined( _MBG_SPINLOCK_DEFINED ) - MBG_SPINLOCK mm_lock; - MBG_SPINLOCK irq_lock; + MBG_SPINLOCK mm_lock; ///< Spinlock used to protect memory mapped access + MBG_SPINLOCK irq_lock; ///< Spinlock used to protect access to data updated by IRQ handler #endif - // The flag below holds IRQ information, e.g. whether the device's - // IRQ is possibly unsafe, and whether IRQ has been enabled on the device. + /// IRQ status information, e.g. whether the device's IRQ is + /// possibly unsafe, and whether IRQ has been enabled on the device. PCPS_IRQ_STAT_INFO irq_stat_info; - RECEIVER_INFO ri; + BUILTIN_FEATURE_MASK builtin_features; ///< Mask of builtin features, depending on device type + MBG_XDEV_FEATURES xdev_features; ///< Receiver info plus extended device features + + #if _PCPS_USE_MM_IO + int use_mm_io; ///< Flag indicating if memory mapped I/O is being used + #endif #if _PCPS_USE_USB - int n_usb_ep; // number of endpoints supp. by the device - PCPS_USB_EP ep[MBGUSB_MAX_ENDPOINTS]; - uint8_t usb_20_mode; + int n_usb_ep; ///< Number of USB endpoints supported by the device + PCPS_USB_EP ep[MBGUSB_MAX_ENDPOINTS]; ///< Array of actual USB endpoints + bool usb_20_mode; ///< Flag indicating if USB 2.0 microframing is supported #endif #if defined( MBG_TGT_WIN32 ) - _pcps_ddev_data_win + _pcps_ddev_data_win ///< Some windows-specific stuff #endif #if defined( MBG_TGT_LINUX ) - atomic_t connected; - atomic_t access_in_progress; - atomic_t data_avail; - unsigned long jiffies_at_irq; - struct fasync_struct *fasyncptr; - PCPS_TIME t; + atomic_t connected; ///< Flag indicating if the device is "connected" + atomic_t access_in_progress; ///< Flag indicating if device access is currently in progress + atomic_t data_avail; ///< Flag indicating if data has been made available by IRQ handler + unsigned long jiffies_at_irq; ///< Set by IRQ handler, used to check if cyclic IRQs still occur + struct fasync_struct *fasyncptr; ///< Used for asynchronous signalling when data is available + PCPS_TIME t; ///< Date and time read by IRQ handler #if NEW_WAIT_QUEUE - wait_queue_head_t wait_queue; + wait_queue_head_t wait_queue; ///< Used for asynchronous I/O (newer kernel API) #else - struct wait_queue *wait_queue; + struct wait_queue *wait_queue; ///< Used for asynchronous I/O (older kernel API) #endif - dev_t lx_dev; - atomic_t open_count; + atomic_t open_count; ///< Number of processes that have opened this device - #if _PCPS_USE_LINUX_CHRDEV - struct cdev cdev; - #elif _PCPS_USE_LINUX_MISC_DEV - struct miscdevice mdev; - #endif + struct cdev cdev; ///< Linux device class + dev_t lx_dev; ///< Linux device associated with this device #if _PCPS_USE_USB - struct usb_device *udev; - struct usb_interface *intf; - PCPS_THREAD_INFO usb_read_thread; - struct semaphore sem_usb_cyclic; + struct usb_device *udev; ///< Linux USB device associated with this device + struct usb_interface *intf; ///< Linux USB interface associated with this device + PCPS_THREAD_INFO usb_read_thread; ///< Kernel thread to receive cyclic USB messages + struct semaphore sem_usb_cyclic; ///< Semaphore used for cyclic USB messages #endif #endif #if defined( MBG_TGT_BSD ) - int connected; - int open_count; + int connected; ///< BSD flag indicating if the device is "connected" + int open_count; ///< BSD number of processes that have opened this device #endif #if _PCPS_USE_RSRCMGR @@ -867,64 +922,83 @@ typedef struct PCPS_DDEV_s RSRC_LIST rsrc; #endif #endif - -} PCPS_DDEV; +}; -/* The PCI vendor ID and device ID numbers are used to detect a - * PCI clock in a system and query which resources have been - * assigned by the BIOS. - * (PCI vendor ID and PCI device IDs are defined in PCPSDEFS.H) +/** + * @brief The number of address lines decoded by a PCI clock */ - -/* the number of address lines decoded by a PCI clock */ #define PCPS_DECODE_WIDTH_PCI 16 /* ------ definitions used with MCA clocks -------------------------- */ -/* The MCA adapter ID number is used to detect a MCA clock in a +/* + * The MCA adapter ID number is used to detect a MCA clock in a * system and query which resources have been assigned by the * system's POS (programmable option select). */ -/* MCA Adapter ID numbers */ -#define MCA_ID_PS31 0x6AAC /* assigned by IBM */ -#define MCA_ID_PS31_OLD 0x6303 /* assigned by Meinberg, used with */ - /* the first series of PS31 boards */ +#define MCA_ID_PS31 0x6AAC ///< MCA adapter ID assigned by IBM +#define MCA_ID_PS31_OLD 0x6303 ///< MCA adapter ID assigned by Meinberg, used with the first series of PS31 boards -/* the total number of ports acquired by a MCA clock */ +/** + * @brief The total number of ports acquired by an MCA device + */ #define PCPS_NUM_PORTS_MCA 16 -/* the number of address lines decoded by a MCA clock */ +/** + * @brief The number of address lines decoded by an MCA device + */ #define PCPS_DECODE_WIDTH_MCA 16 /* ------ definitions used with ISA clocks -------------------------- */ -/* A board ID for the newer clocks with ISA bus. The number can - * be read at port_base+2 (low byte) and port_base+3 (high byte) - * of ISA clocks. This ID number matches the MCA adapter ID - * defined above and is not available on PC31 clocks. +/** + * @brief A board ID for later ISA bus devices + * + * The number can be read at port_base + 2 (low byte), and + * port_base + 3 (high byte) of ISA devices. This ID number + * matches the MCA adapter ID ::MCA_ID_PS31 and is not + * provided by PC31 devices. */ #define ISA_ID_PCPS MCA_ID_PS31 -/* The default port base address for ISA clocks. - * Some programs assume a default port for an ISA clock, - * others do not but require a cmd line parameter. + +/** + * @brief The default port base address for ISA bus devices + * + * Some programs assume a default port for an ISA default, + * but others do not but require a cmd line parameter. */ #define PCPS_DEFAULT_PORT 0x0300 -/* the total number of ports acquired by a ISA clock */ + +/** + * @brief The total number of I/O ports used by an ISA bus device + */ #define PCPS_NUM_PORTS_ISA 4 -/* the number of address lines decoded by a ISA clock */ + +/** + * @brief The number of address lines decoded by an ISA bus device + */ #define PCPS_DECODE_WIDTH_ISA 10 /* ------ common definitions -------------------------- */ +#if defined( DEBUG ) + _ext int debug + #ifdef _DO_INIT + = DEBUG + #endif + ; +#endif + + _ext PCPS_DEV_TYPE pcps_dev_type[N_PCPS_DEV_TYPE] #ifdef _DO_INIT = { // attention, the name is limited to PCPS_CLOCK_NAME_SZ, including terminating 0 @@ -960,32 +1034,32 @@ _ext PCPS_DEV_TYPE pcps_dev_type[N_PCPS_DEV_TYPE] { PCPS_TYPE_PZF180PEX, "PZF180PEX", PCI_DEV_PZF180PEX, PCPS_REF_DCF, PCPS_BUS_PCI_MBGPEX }, { PCPS_TYPE_TCR600USB, "TCR600USB", USB_DEV_TCR600USB, PCPS_REF_IRIG, PCPS_BUS_USB_V2 }, { PCPS_TYPE_MSF600USB, "MSF600USB", USB_DEV_MSF600USB, PCPS_REF_MSF, PCPS_BUS_USB_V2 }, - { PCPS_TYPE_WVB600USB, "WVB600USB", USB_DEV_WVB600USB, PCPS_REF_WWVB, PCPS_BUS_USB_V2 } + { PCPS_TYPE_WVB600USB, "WVB600USB", USB_DEV_WVB600USB, PCPS_REF_WWVB, PCPS_BUS_USB_V2 }, + { PCPS_TYPE_GLN180PEX, "GLN180PEX", PCI_DEV_GLN180PEX, PCPS_REF_GPS, PCPS_BUS_PCI_MBGPEX }, + { PCPS_TYPE_GPS180AMC, "GPS180AMC", PCI_DEV_GPS180AMC, PCPS_REF_GPS, PCPS_BUS_PCI_MBGPEX }, + { PCPS_TYPE_GNS181PEX, "GNS181PEX", PCI_DEV_GNS181PEX, PCPS_REF_GPS, PCPS_BUS_PCI_MBGPEX } // If a new device is added here, don't forget to add it also - // to the Windows .inf file of supported PCI an USB devices, - // and in case of USB to the Linux driver file mbgdrvr.c. + // to the Windows .inf file of supported PCI and USB devices, + // and in case of USB to the table mbgclock_usb_tbl of the Linux + // driver file mbgclock_main.c. } #endif ; -#if !defined( PCPS_MAX_DDEVS ) - #define PCPS_MAX_DDEVS 4 -#endif - #if !defined( PCPS_MAX_ISA_CARDS ) - #define PCPS_MAX_ISA_CARDS PCPS_MAX_DDEVS // the number of ISA cards supported + #define PCPS_MAX_ISA_CARDS N_SUPP_DEV_BUS // the number of ISA cards supported #endif _ext int pcps_isa_ports[PCPS_MAX_ISA_CARDS + 1]; #if _PCPS_STATIC_DEV_LIST - _ext PCPS_DDEV pcps_ddev[PCPS_MAX_DDEVS]; + _ext PCPS_DDEV pcps_ddev[N_SUPP_DEV_BUS]; _ext int n_ddevs; #endif -#if defined( MBG_TGT_DOS ) || defined( MBG_TGT_NETWARE ) //##++ +#if defined( MBG_TGT_DOS ) || defined( MBG_TGT_NETWARE ) //##++ _ext int curr_ddev_num; _ext PCPS_DDEV *curr_ddev #ifdef _DO_INIT @@ -994,14 +1068,16 @@ _ext int pcps_isa_ports[PCPS_MAX_ISA_CARDS + 1]; ; #endif -/* the first characters of a valid EPROM ID */ +/** + * @brief The first characters of a valid firmware ID + */ _ext const char *fw_id_ref[] #ifdef _DO_INIT = { "PC3", // PC31, PS31, PC32 "PCI", // PCI32, PCI509, PCI510, PCI511 - "GPS", // GPS167PC, GPS167PCI, GPS168PCI, GPS169PCI, GPS170PCI, GPS170PEX, GPS180PEX + "GPS", // GPS167PC, GPS167PCI, GPS168PCI, GPS169PCI, GPS170PCI, GPS170PEX, GPS180PEX, GPS180AMC "TCR", // TCR510PCI, TCR167PCI, TCR511PCI, TCR511PEX, TCR51USB, TCR170PEX, TCR180PEX "PEX", // PEX511 "USB", // USB5131 @@ -1009,20 +1085,25 @@ _ext const char *fw_id_ref[] "WWVB", // WWVB51USB, WVB600USB "DCF", // DCF600USB "PZF", // PZF180PEX + "GLN", // GLN180PEX + "GNS", // GNS181PEX NULL } #endif ; -// The macros below are used to distinguish ISA cards: - +// These macros are used to distinguish ISA cards: #define fw_id_ref_pcps fw_id_ref[0] #define fw_id_ref_gps fw_id_ref[2] +#if _PCPS_USE_MM_IO + _ext int force_io_access; +#endif -// The macros below accept a (PCPS_DDEV *) for easy access + +// These macros accept a (PCPS_DDEV *) for easy access // to the information stored in PCPS_DDEV structures. // Access device type information: @@ -1033,6 +1114,7 @@ _ext const char *fw_id_ref[] #define _pcps_ddev_bus_flags( _p ) _pcps_bus_flags( &(_p)->dev ) // Query device type features: + #define _pcps_ddev_is_gps( _p ) _pcps_is_gps( &(_p)->dev ) #define _pcps_ddev_is_dcf( _p ) _pcps_is_dcf( &(_p)->dev ) #define _pcps_ddev_is_msf( _p ) _pcps_is_msf( &(_p)->dev ) @@ -1042,6 +1124,8 @@ _ext const char *fw_id_ref[] #define _pcps_ddev_is_frc( _p ) _pcps_is_frc( &(_p)->dev ) #define _pcps_ddev_is_lwr( _p ) _pcps_is_lwr( &(_p)->dev ) +#define _pcps_ddev_is_gnss( _p ) _pcps_is_gnss( &(_p)->dev ) + // Generic bus types: #define _pcps_ddev_is_isa( _p ) _pcps_is_isa( &(_p)->dev ) @@ -1063,12 +1147,14 @@ _ext const char *fw_id_ref[] #define _pcps_ddev_bus_num( _p ) _pcps_bus_num( &(_p)->dev ) #define _pcps_ddev_slot_num( _p ) _pcps_slot_num( &(_p)->dev ) -#define _pcps_ddev_port_rsrc( _p, _n ) _pcps_port_rsrc( &(_p)->dev, _n ) -#define _pcps_ddev_port_base( _p, _n ) _pcps_port_base( &(_p)->dev, _n ) -#define _pcps_ddev_io_rsrc( _p, _n ) ( (_p)->rsrc_info.port[_n] ) -#define _pcps_ddev_io_base_mapped( _p, _n ) ( _pcps_ddev_io_rsrc( _p, _n ).base_mapped ) -#define _pcps_ddev_irq_num( _p ) _pcps_irq_num( &(_p)->dev ) -#define _pcps_ddev_timeout_clk( _p ) _pcps_timeout_clk( &(_p)->dev ) +#define _pcps_ddev_short_port_rsrc( _p, _n ) _pcps_short_port_rsrc( &(_p)->dev, _n ) +#define _pcps_ddev_short_port_base( _p, _n ) _pcps_short_port_base( &(_p)->dev, _n ) + +#define _pcps_ddev_io_rsrc( _p, _n ) ( (_p)->rsrc_info.port[_n] ) +#define _pcps_ddev_io_base_raw( _p, _n ) ( _pcps_ddev_io_rsrc( _p, _n ).base_raw ) +#define _pcps_ddev_io_base_mapped( _p, _n ) ( _pcps_ddev_io_rsrc( _p, _n ).base_mapped ) +#define _pcps_ddev_irq_num( _p ) _pcps_irq_num( &(_p)->dev ) +#define _pcps_ddev_timeout_clk( _p ) _pcps_timeout_clk( &(_p)->dev ) #define _pcps_ddev_fw_rev_num( _p ) _pcps_fw_rev_num( &(_p)->dev ) #define _pcps_ddev_features( _p ) _pcps_features( &(_p)->dev ) @@ -1078,7 +1164,7 @@ _ext const char *fw_id_ref[] #define _pcps_ddev_raw_asic_version( _p ) ( (_p)->raw_asic_version ) #define _pcps_ddev_asic_version( _p ) ( (_p)->asic_version ) -// The macros below handle the device's err_flags. +// These macros handle the device's err_flags: #define _pcps_ddev_chk_err_flags( _p, _msk ) \ _pcps_chk_err_flags( &(_p)->dev, _msk ) @@ -1089,9 +1175,7 @@ _ext const char *fw_id_ref[] _pcps_clr_err_flags( &(_p)->dev, _msk ) -// Query whether a special feature is supported: -#define _pcps_ddev_has_feature( _p, _f ) _pcps_has_feature( &(_p)->dev, _f ) - +// Query whether a specific feature is supported: #define _pcps_ddev_can_set_time( _p ) _pcps_can_set_time( &(_p)->dev ) #define _pcps_ddev_has_serial( _p ) _pcps_has_serial( &(_p)->dev ) #define _pcps_ddev_has_sync_time( _p ) _pcps_has_sync_time( &(_p)->dev ) @@ -1111,7 +1195,7 @@ _ext const char *fw_id_ref[] #define _pcps_ddev_has_ucap( _p ) _pcps_has_ucap( &(_p)->dev ) #define _pcps_ddev_has_irig_tx( _p ) _pcps_has_irig_tx( &(_p)->dev ) -// The macro below determines whether a DCF77 clock +// This macro determines whether a DCF77 clock // supports a higher baud rate than standard #define _pcps_ddev_has_serial_hs( _p ) \ _pcps_has_serial_hs( &(_p)->dev ) @@ -1175,7 +1259,7 @@ _ext const char *fw_id_ref[] _pcps_has_ptp( &(_p)->dev ) #define _pcps_ddev_has_ptp_unicast( _p ) \ - _pcps_has_ri_ptp_unicast( &(_p)->ri ) + _pcps_has_ri_ptp_unicast( _ri_addr( _p ) ) #define _pcps_ddev_has_pzf( _p ) \ _pcps_has_pzf( &(_p)->dev ) @@ -1186,14 +1270,35 @@ _ext const char *fw_id_ref[] #define _pcps_ddev_has_tr_distance( _p ) \ _pcps_has_tr_distance( &(_p)->dev ) +#define _pcps_ddev_has_evt_log( _p ) \ + _pcps_has_evt_log( &(_p)->dev ) + +#define _pcps_ddev_has_debug_status( _p ) \ + _pcps_has_debug_status( &(_p)->dev ) + +#define _pcps_ddev_has_stat_info( _p ) \ + _pcps_has_stat_info( &(_p)->dev ) + +#define _pcps_ddev_has_stat_info_mode( _p ) \ + _pcps_has_stat_info_mode( &(_p)->dev ) \ + +#define _pcps_ddev_has_stat_info_svs( _p ) \ + _pcps_has_stat_info_svs( &(_p)->dev ) \ + #define _pcps_ddev_incoming_tfom_ignored( _p ) \ _pcps_incoming_tfom_ignored( &(_p)->dev ) #define _pcps_ddev_pci_cfg_err( _p ) \ _pcps_pci_cfg_err( &(_p)->dev ) +#define _pcps_ddev_has_gpio( _p ) \ + _pcps_has_ri_gpio( _ri_addr( _p ) ) -// The macros below simplify read/write access to the clocks. +#define _pcps_ddev_has_xmr( _p ) \ + _pcps_has_ri_xmr( _ri_addr( _p ) ) + + +// These macros simplify read/write access to the clocks. // Call the device's read function to write the command byte _cmd // and read _n bytes to buffer _s. @@ -1203,7 +1308,8 @@ _ext const char *fw_id_ref[] #endif // Write a byte _b to a device. This is typically done by just writing -// the command byte from inside the read function. +// the command byte from within the read function, without actually +// reading any data bytes. #if !defined( _pcps_write_byte ) #define _pcps_write_byte( _pddev, _b ) \ _pcps_read( (_pddev), (_b), NULL, 0 ) @@ -1217,21 +1323,22 @@ _ext const char *fw_id_ref[] pcps_write( (_pddev), (_cmd), (uchar FAR *)(_p), (_n) ) #endif -// Read data structures which exceed PCPS_FIFO_SIZE bytes. -// This can't be handled in a single read cycle and due to limitations -// of the clock's microprocessor these calls can up to 20 milliseconds. -// Currently these function is only used to read GPS specific data -// from GPS clocks. +// Read data structures which exceed ::PCPS_FIFO_SIZE bytes. +// This can't be handled in a single read cycle and due to +// limitations of the device's microprocessor the execution time +// can be up to 20 milliseconds, depending on the device type. +// This has been introduced with the first GPS devices but is +// now in fact also used with non-GPS devices. #define _pcps_read_gps( _pddev, _cmd, _p, _n ) \ pcps_read_gps( (_pddev), (_cmd), (uchar FAR *) (_p), (_n) ) -// The write function opposite to the read function above. +// The complementary write function for the read function above. #define _pcps_write_gps( _pddev, _cmd, _p, _n ) \ pcps_write_gps( (_pddev), (_cmd), (uchar FAR *) (_p), (_n) ) -// The macros below simplify reading/writing typed variables by +// These macros simplify reading/writing typed variables by // determining the size automatically from the type of the variable. // Read data from a device to variable _s. @@ -1255,7 +1362,7 @@ _ext const char *fw_id_ref[] #define _pcps_read_gps_var( _pddev, _cmd, _s ) \ _pcps_read_gps( (_pddev), (_cmd), &(_s), sizeof( (_s) ) ) -// The write function opposite to the read function above. +// The complementary write function for the read function above. #define _pcps_write_gps_var( _pddev, _cmd, _s ) \ _pcps_write_gps( (_pddev), (_cmd), &(_s), sizeof( (_s) ) ) @@ -1267,18 +1374,32 @@ _ext const char *fw_id_ref[] _pcps_write_byte( (_pddev), PCPS_FORCE_RESET ) -// The macro below reads a device's status port which includes -// the BUSY flag and the modulation signal of DCF77 receivers. +// This macro reads a device's status port which includes +// the BUSY flag (::PCPS_ST_BUSY )and the modulation signal +// of DCF77 and other long wave receivers. // The macro takes a (PCPS_DDEV *) as argument. -#define _pcps_ddev_read_status_port( _d ) \ - _mbg_inp8( (_d), 0, (_d)->status_port ) +#if _PCPS_USE_MM_IO + + #define _pcps_ddev_read_status_port( _d ) \ + ( (_d)->use_mm_io ? \ + (uint8_t) (_d)->mm_addr->mbgpex.asic.status_port.ul : \ + _mbg_inp8( (_d), 0, (_d)->status_port ) \ + ) + +#else + + #define _pcps_ddev_read_status_port( _d ) \ + _mbg_inp8( (_d), 0, (_d)->status_port ) + +#endif + #define _pcps_ddev_status_busy( _d ) \ ( _pcps_ddev_read_status_port( pddev ) & PCPS_ST_BUSY ) -// The macro below checks whether a workaround is required to get/set -// IRIG cfg from a GPS169PCI with IRIG output and early firmware version +// This macro checks whether a workaround is required to get/set +// IRIG cfg from a GPS169PCI with IRIG output and early firmware version. // This is handled in mbgdevio.c for direct access environments, and in // macioctl.h for kernel device drivers. #define _pcps_ddev_requires_irig_workaround( _d ) \ @@ -1352,19 +1473,31 @@ _ext const char *fw_id_ref[] _pcps_usb_read_ep_tmo( _d, _p, _sz, MBGUSB_EP_IDX_HOST_IN_CYCLIC, MBGUSB_TIMEOUT_RECEIVE_CYCLIC, _irp ) #define _pcps_usb_read_var_cyclic( _d, _p, _irp ) \ - _pcps_usb_read_cyclic( _d, _p, sizeof( *(_p) ), _irp ) + _pcps_usb_read_cyclic( _d, _p, sizeof( *(_p) ), _irp ) #elif defined( MBG_TGT_LINUX ) - #define _pcps_usb_write_ep_tmo( _d, _p, _sz, _ep_idx, _tmo ) \ - usb_bulk_msg( (_d)->udev, \ - usb_sndbulkpipe( (_d)->udev, (_d)->ep[_ep_idx].addr ), \ - _p, _sz, &actual_count, _tmo ) + #if DEBUG_USB_IO + #define _pcps_usb_write_ep_tmo( _d, _p, _sz, _ep_idx, _tmo ) \ + usb_bulk_msg_dbg( (_d)->udev, \ + usb_sndbulkpipe( (_d)->udev, (_d)->ep[_ep_idx].addr ), \ + _p, _sz, &actual_count, _tmo ) - #define _pcps_usb_read_ep_tmo( _d, _p, _sz, _ep_idx, _tmo ) \ - usb_bulk_msg( (_d)->udev, \ - usb_rcvbulkpipe( (_d)->udev, (_d)->ep[_ep_idx].addr ), \ - _p, _sz, &actual_count, _tmo ) + #define _pcps_usb_read_ep_tmo( _d, _p, _sz, _ep_idx, _tmo ) \ + usb_bulk_msg_dbg( (_d)->udev, \ + usb_rcvbulkpipe( (_d)->udev, (_d)->ep[_ep_idx].addr ), \ + _p, _sz, &actual_count, _tmo ) + #else + #define _pcps_usb_write_ep_tmo( _d, _p, _sz, _ep_idx, _tmo ) \ + usb_bulk_msg( (_d)->udev, \ + usb_sndbulkpipe( (_d)->udev, (_d)->ep[_ep_idx].addr ), \ + _p, _sz, &actual_count, _tmo ) + + #define _pcps_usb_read_ep_tmo( _d, _p, _sz, _ep_idx, _tmo ) \ + usb_bulk_msg( (_d)->udev, \ + usb_rcvbulkpipe( (_d)->udev, (_d)->ep[_ep_idx].addr ), \ + _p, _sz, &actual_count, _tmo ) + #endif #define _pcps_usb_write( _d, _p, _sz ) \ _pcps_usb_write_ep_tmo( _d, _p, _sz, MBGUSB_EP_IDX_HOST_OUT, MBGUSB_TIMEOUT_SEND ) @@ -1376,7 +1509,7 @@ _ext const char *fw_id_ref[] _pcps_usb_read_ep_tmo( _d, _p, _sz, MBGUSB_EP_IDX_HOST_IN_CYCLIC, MBGUSB_TIMEOUT_RECEIVE_CYCLIC ) #define _pcps_usb_read_var_cyclic( _d, _p ) \ - _pcps_usb_read_cyclic( _d, _p, sizeof( *(_p) ) ) + _pcps_usb_read_cyclic( _d, _p, sizeof( *(_p) ) ) #endif // target specific definitions @@ -1390,44 +1523,289 @@ _ext const char *fw_id_ref[] #endif +/** + * @defgroup pcps_io_fncs Low level functions used to access the hardware device + */ + /* ----- function prototypes begin ----- */ /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ -/* PCPS_WRITE_FNC */ - short pcps_write( PCPS_DDEV *pddev, uint8_t cmd, const void FAR *buffer, uint16_t count ) ; + /** + * @brief Write data to a device + * + * @param[in] pddev Pointer to the device structure + * @param[in] cmd The command code for the board, see @ref PCPS_CMD_CODES + * @param[in] buffer A buffer with data to be written according to the cmd code + * @param[in] count The number of bytes to be written according to the cmd code + * + * @return ::MBG_SUCCESS on success, + * ::MBG_ERR_TIMEOUT if device didn't respond in time, + * ::MBG_ERR_NBYTES if the number of parameter bytes did not match + * the number of data bytes expected by the device, + * or one of the other @ref MBG_RETURN_CODES + * + * @ingroup pcps_io_fncs + * @see @ref pcps_io_fncs + */ + int pcps_write( PCPS_DDEV *pddev, uint8_t cmd, const void FAR *buffer, uint16_t count ) ; - short pcps_generic_io( PCPS_DDEV *pddev, uint8_t type, const void FAR *in_buff, uint8_t in_cnt, void FAR *out_buff, uint8_t out_cnt ) ; -/* PCPS_READ_FNC */ - short pcps_read_gps( PCPS_DDEV *pddev, uint8_t data_type, void FAR *buffer, uint16_t buffer_size ) ; + /** + * @brief Generic I/O function + * + * @param[in] pddev Pointer to the device structure + * @param[in] type The type of data to be read/written, see @ref PCPS_CMD_CODES + * @param[in] in_buff A buffer with data to be written according to the type code + * @param[in] in_cnt The number of bytes to be written according to the type code + * @param[out] out_buff A buffer with data to be read according to the type code + * @param[in] out_cnt The number of bytes to be read according to the type code + * + * @return ::MBG_SUCCESS on success, + * ::MBG_ERR_TIMEOUT if device didn't respond in time, + * ::MBG_ERR_NBYTES if the number of parameter bytes did not match + * the number of data bytes expected by the device, + * or one of the other @ref MBG_RETURN_CODES + * + * @ingroup pcps_io_fncs + * @see @ref pcps_io_fncs + */ + int pcps_generic_io( PCPS_DDEV *pddev, uint8_t type, const void FAR *in_buff, uint8_t in_cnt, void FAR *out_buff, uint8_t out_cnt ) ; -/* PCPS_WRITE_FNC */ - short pcps_write_gps( PCPS_DDEV *pddev, uint8_t data_type, const void FAR *buffer, uint16_t buffer_size ) ; + /** + * @brief Read a large data structure from a device + * + * Read data structures which exceed ::PCPS_FIFO_SIZE bytes. + * This can't be handled in a single read cycle, and due to + * limitations of the device's microprocessor the execution time + * can be up to 20 milliseconds, depending on the device type. + * This has been introduced with the first GPS devices but is + * now in fact also used with non-GPS devices. + * + * @param[in] pddev Pointer to the device structure + * @param[in] data_type The code assigned to the dadta type, see @ref PC_GPS_CMD_CODES + * @param[out] buffer A buffer with data to be read according to the data_type + * @param[in] buffer_size The number of bytes to be read according to the data_type + * + * @return ::MBG_SUCCESS on success, + * ::MBG_ERR_TIMEOUT if device didn't respond in time, + * ::MBG_ERR_NBYTES if the number of parameter bytes did not match + * the number of data bytes expected by the device, + * or one of the other @ref MBG_RETURN_CODES + * + * @ingroup pcps_io_fncs + * @see @ref pcps_io_fncs + */ + int pcps_read_gps( PCPS_DDEV *pddev, uint8_t data_type, void FAR *buffer, uint16_t buffer_size ) ; + + /** + * @brief Write a large data structure to a device + * + * This has been introduced with the first GPS devices but is + * now in fact also used with non-GPS devices. + * + * @param[in] pddev Pointer to the device structure + * @param[in] data_type The code assigned to the dadta type, see @ref PC_GPS_CMD_CODES + * @param[in] buffer A buffer with data to be written according to the data_type + * @param[in] buffer_size The number of bytes to be written according to the data_type + * + * @return ::MBG_SUCCESS on success, + * ::MBG_ERR_TIMEOUT if device didn't respond in time, + * ::MBG_ERR_NBYTES if the number of parameter bytes did not match + * the number of data bytes expected by the device, + * or one of the other @ref MBG_RETURN_CODES + * + * @ingroup pcps_io_fncs + * @see @ref pcps_io_fncs + */ + int pcps_write_gps( PCPS_DDEV *pddev, uint8_t data_type, const void FAR *buffer, uint16_t buffer_size ) ; - short pcps_get_fw_id( PCPS_DDEV *pddev, PCPS_ID_STR FAR fw_id ) ; - short pcps_check_id( PCPS_DDEV *pddev, const char FAR *ref ) ; - short pcps_get_rev_num( char FAR *idstr ) ; + /** + * @brief Read the serial number from a device, if supported + * + * If the serial number could be read successfully then it is + * stored in one of the sub-structures of pddev. + * + * @param[in,out] pddev Pointer to a device structure + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ int pcps_read_sernum( PCPS_DDEV *pddev ) ; - int pcps_rsrc_claim( PCPS_DDEV *pddev ) ; + + /** + * @brief Release an I/O port resource range that has been claimed before + * + * @param[in,out] pddev The device structure + */ void pcps_rsrc_release( PCPS_DDEV *pddev ) ; - ushort pcps_port_from_pos( ushort pos ) ; - uchar pcps_pos_from_port( ushort port ) ; - PCPS_DEV_TYPE *pcps_get_dev_type( int bus_mask, ushort dev_id ) ; + + /** + * @brief Lookup a specific device in the device table + * + * The function below takes a bus flag and device ID to search + * the table of known devices for a device which matches the + * given criteria. + * + * @param[in] bus_mask Mask of the bus type to look up, see @ref PCPS_BUS_FLAG_MASKS + * @param[in] dev_id The device ID to lookup, see @ref MEINBERG_PCI_DEVICE_IDS + * or @ref MBG_USB_DEVICE_IDS, depending on the bus_mask + * + * @return A pointer to the device table entry, or NULL if no entry found + */ + PCPS_DEV_TYPE *pcps_get_dev_type_table_entry( PCPS_BUS_FLAGS bus_mask, PCPS_DEV_ID dev_id ) ; + + /** + * @brief Allocate a device info structure for a device + * + * @return A pointer to the allocated structure, or NULL if failed + */ PCPS_DDEV *pcps_alloc_ddev( void ) ; + + /** + * @brief Free a previously allocated device info structure + * + * @param[in] pddev Pointer to the device structure to be freed + */ void pcps_free_ddev( PCPS_DDEV *pddev ) ; + + /** + * @brief Add an I/O address range resource to the device structure + * + * @param[in,out] pddev Pointer to the device structure + * @param[in] base Base address of the I/O address range + * @param[in] num Number of addresses of the I/O address range + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ int pcps_add_rsrc_io( PCPS_DDEV *pddev, ulong base, ulong num ) ; + + /** + * @brief Add a memory address range resource to the device structure + * + * @param[in,out] pddev Pointer to the device structure + * @param[in] start Start address of the memory range + * @param[in] len Size of the memory range + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ int pcps_add_rsrc_mem( PCPS_DDEV *pddev, MBG_MEM_ADDR start, ulong len ) ; + + /** + * @brief Add an IRQ number resource to the device structure + * + * @param[in,out] pddev Pointer to the device structure + * @param[in] irq_num Start address of the memory range + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ int pcps_add_rsrc_irq( PCPS_DDEV *pddev, int16_t irq_num ) ; - int pcps_init_ddev( PCPS_DDEV *pddev, int bus_flags, ushort dev_id ) ; - int pcps_start_device( PCPS_DDEV *pddev, PCPS_BUS_NUM bus_num, PCPS_SLOT_NUM dev_fnc_num ) ; + + /** + * @brief Initialize an allocated device structure for a specific device + * + * @param[in,out] pddev Pointer to the device structure + * @param[in] bus_mask Mask of the bus type to look up, see @ref PCPS_BUS_FLAG_MASKS + * @param[in] dev_id The device ID to lookup, see @ref MEINBERG_PCI_DEVICE_IDS + * or @ref MBG_USB_DEVICE_IDS, depending on the bus_mask + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ + int pcps_init_ddev( PCPS_DDEV *pddev, PCPS_BUS_FLAGS bus_mask, PCPS_DEV_ID dev_id ) ; + + /** + * @brief Check if a specific feature of a specific feature type is supported + * + * There are different structures where information can be stored + * if a specific feature is supported. All information is set up + * when the ::pcps_probe_device function is called to probe and + * initialize the device. + * This generic low-level function can be called by API functions + * to check if a specific feature is supported. + * + * @param[in] p_ddev Pointer to the device structure + * @param[in] feat_req_type See ::DEV_FEAT_REQ_TYPES + * @param[in] feat_num Number and range depending on feat_req_type value + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @see ::pcps_probe_device + */ + int pcps_chk_dev_feat( PCPS_DDEV *p_ddev, uint32_t feat_req_type, uint32_t feat_num ) ; + + /** + * @brief Probe if a device is supported, and allocate and setup the device structure + * + * This function should be called by the probe routines of any + * target-specific kernel drivers. + * If the device is supported then all specific information including + * supported features is read from the device and stored in sub-structures + * of the device structure addressed by pdev. + * + * @param[in,out] pddev Pointer to the device structure which has been initialized and will be set up + * @param[in] bus_num The bus number if supported (e.g. PCI), else 0 + * @param[in] dev_fnc_num The device/function number if supported (e.g. PCI), else 0 + * + * @return ::MBG_SUCCESS if the requested feature is supported, ::MBG_ERR_NOT_SUPP_BY_DEV + * if not supported, or one of the other @ref MBG_ERROR_CODES + * + * @see ::pcps_cleanup_device + * @see ::pcps_chk_dev_feat + */ + int pcps_probe_device( PCPS_DDEV *pddev, PCPS_BUS_NUM bus_num, PCPS_SLOT_NUM dev_fnc_num ) ; + + /** + * @brief Clean up function called by ::pcps_probe_device on error + * + * @param[in,out] pddev Pointer to the device structure + * + * @see ::pcps_probe_device + */ void pcps_cleanup_device( PCPS_DDEV *pddev ) ; + + /** + * @brief Setup and start a PCI device in a non-PnP system + * + * @param[in,out] pddev Pointer to the device structure to be set up + * @param[in] bus_num The PCI bus number returned by the PCI BIOS + * @param[in] dev_fnc_num The PCI device/function number returned by the PCI BIOS + */ void pcps_setup_and_start_pci_dev( PCPS_DDEV *pddev, PCPS_BUS_NUM bus_num, PCPS_SLOT_NUM dev_fnc_num ) ; - void pcps_detect_pci_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg, PCPS_DDEV_CLEANUP_FNC cleanup_fnc, ushort vendor_id, PCPS_DEV_TYPE dev_type[], int n_dev_types ) ; - void pcps_detect_isa_clocks( PCPS_DDEV_ALLOC_FNC alloc_fnc, PCPS_DDEV_CLEANUP_FNC cleanup_fnc, PCPS_DDEV_REGISTER_FNC register_fnc, int isa_ports[PCPS_MAX_ISA_CARDS], int isa_irqs[PCPS_MAX_ISA_CARDS] ) ; - void _MBG_INIT_CODE_ATTR pcps_detect_clocks_alloc( PCPS_DDEV_ALLOC_FNC alloc_fnc, void *alloc_arg, PCPS_DDEV_CLEANUP_FNC cleanup_fnc, int isa_ports[PCPS_MAX_ISA_CARDS], int isa_irqs[PCPS_MAX_ISA_CARDS] ) ; - void _MBG_INIT_CODE_ATTR pcps_detect_clocks( int isa_ports[PCPS_MAX_ISA_CARDS], int isa_irqs[PCPS_MAX_ISA_CARDS] ) ; + + /** + * @brief Detect and initialize PCI devices in a non-PnP system + * + * @param[in] alloc_fnc Pointer to function called to allocate a device structure for each detected device. + * @param[in] cleanup_fnc Pointer to function called if the device structure needs to be de-allocated in case of error. + * @param[in] vendor_id The PCI vendor ID code. + * @param[in] dev_type An array with known PCI devices for the specified vendor ID + * @param[in] n_dev_types The number of entries in the PCI device table + */ + void pcps_detect_pci_devices( PCPS_DDEV_ALLOC_FNC *alloc_fnc, PCPS_DDEV_CLEANUP_FNC *cleanup_fnc, ushort vendor_id, PCPS_DEV_TYPE dev_type[], int n_dev_types ) ; + + /** + * @brief Detect and initialize ISA devices in a non-PnP system + * + * @param[in] alloc_fnc Pointer to function called to allocate a device structure for each detected device. + * @param[in] cleanup_fnc Pointer to function called if the device structure needs to be de-allocated in case of error. + * @param[in] register_fnc Pointer to function called to register a detected device. + * @param[in] isa_ports An array with potential I/O base addresses for ISA devices. + * @param[in] isa_irqs An array with potential IRQ numbers assigned to ISA devices. + */ + void pcps_detect_isa_devices( PCPS_DDEV_ALLOC_FNC *alloc_fnc, PCPS_DDEV_CLEANUP_FNC *cleanup_fnc, PCPS_DDEV_REGISTER_FNC *register_fnc, int isa_ports[PCPS_MAX_ISA_CARDS], int isa_irqs[PCPS_MAX_ISA_CARDS] ) ; + + /** + * @brief Detect all bus-level devices in a non-PnP system + * + * @note If a DOS TSR is installed, be sure it is disabled (BUSY flag set) + * when this function is called. + * + * @param[in] isa_ports An array with potential I/O base addresses for ISA devices. + * @param[in] isa_irqs An array with potential IRQ numbers assigned to ISA devices. + */ + void _MBG_INIT_CODE_ATTR pcps_detect_devices( int isa_ports[PCPS_MAX_ISA_CARDS], int isa_irqs[PCPS_MAX_ISA_CARDS] ) ; + /* ----- function prototypes end ----- */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsirq.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpsirq.h index 7bb2b1f..8156f87 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pcpsirq.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsirq.h @@ -1,16 +1,23 @@ /************************************************************************** * - * $Id: pcpsirq.h 1.7 2008/12/05 12:20:36 martin REL_M $ + * $Id: pcpsirq.h 1.8 2012/10/15 09:50:44 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * * Description: * OS independent definitions used to handle interrupts from - * Meinberg radio clock devices. + * Meinberg PCI devices. * * ----------------------------------------------------------------------- * $Log: pcpsirq.h $ + * Revision 1.8 2012/10/15 09:50:44 martin + * Account for modified low level macros. + * Revision 1.7.1.3 2011/12/20 13:46:07 martin + * Conditionally support memory mapped access for MBGPEX cards. + * Revision 1.7.1.2 2011/06/29 11:03:28 martin + * Updated a comment. + * Revision 1.7.1.1 2011/02/09 17:22:36 martin * Revision 1.7 2008/12/05 12:20:36 martin * Protect HW access to enable/disable IRQ by mutex. * Support mapped I/O resources. @@ -41,13 +48,6 @@ #include <pci_asic.h> -#define _set_port_bit( _d, _adr, _msk ) \ - _mbg_outp8( (_d), _adr, _mbg_inp8( (_d), _adr ) | (_msk) ) - -#define _clear_port_bit( _d, _adr, _msk ) \ - _mbg_outp8( (_d), _adr, _mbg_inp8( (_d), _adr ) & ~(_msk) ) - - // Each of the macros below expects a parameter _d which is // a pointer to the PCPS_DDEV structure which represents the // hardware device. @@ -55,6 +55,12 @@ // The macros below generate code only if MCA support is enabled. #if _PCPS_USE_MCA + #define _set_mca_port_bit( _d, _adr, _msk ) \ + _mbg_outp8( (_d), 0, _adr, _mbg_inp8( (_d), 0, _adr ) | (_msk) ) + + #define _clear_mca_port_bit( _d, _adr, _msk ) \ + _mbg_outp8( (_d), 0, _adr, _mbg_inp8( (_d), 0, _adr ) & ~(_msk) ) + #define MCIC_IRQ 0x04 #define _mcic_enb_reg( _r ) ( (_r) + 0x0A ) #define _mcic_ack_reg( _r ) ( (_r) + 0x0B ) @@ -68,7 +74,7 @@ if ( _pcps_ddev_is_mca( _d ) ) \ { \ PCPS_IO_ADDR_MAPPED port = _mcic_ack_reg( _pcps_ddev_io_base_mapped( _d, 0 ) ); \ - _set_port_bit( (_d), port, MCIC_IRQ ); \ + _set_mca_port_bit( (_d), port, MCIC_IRQ ); \ } // In IRQ init function, enable IRQ on the @@ -78,7 +84,7 @@ { \ uint16_t port = _mcic_enb_reg( _pcps_ddev_io_base_mapped( _d, 0 ) ); \ set_pos_reg( 4, _pcps_ddev_slot_num( _d ), active_irq.map_code ); \ - _set_port_bit( (_d), port, MCIC_IRQ ); \ + _set_mca_port_bit( (_d), port, MCIC_IRQ ); \ } // In IRQ de-init function, disable IRQ on the @@ -87,15 +93,15 @@ if ( _pcps_ddev_is_mca( _d ) ) \ { \ uint16_t port = _mcic_enb_reg( _pcps_ddev_io_base_mapped( _d, 0 ) ); \ - _clear_port_bit( (_d), port, MCIC_IRQ ); \ + _clear_mca_port_bit( (_d), port, MCIC_IRQ ); \ } #else // Do nothing if MCA not supported. - #define _pcps_ddev_enb_irq_mca( _d ); - #define _pcps_ddev_disb_irq_mca( _d ); - #define _pcps_ddev_ack_irq_mca( _d ); + #define _pcps_ddev_enb_irq_mca( _d ) _nop_macro_fnc() + #define _pcps_ddev_disb_irq_mca( _d ) _nop_macro_fnc() + #define _pcps_ddev_ack_irq_mca( _d ) _nop_macro_fnc() #endif @@ -110,41 +116,44 @@ // 2.) Clear interrupt source, deassert INTA# signal // and leave interrupt enabled by writing '1's to // the interrupt flag and interrupt enable bits. - #define _pcps_ddev_ack_irq_pci( _d ) \ - if ( (_d)->irq_ack_mask ) \ - { \ - if ( _pcps_ddev_is_pci_amcc( _d ) ) \ - _mbg_inp32( (_d), _pcps_ddev_io_base_mapped( _d, 0 ) \ - + AMCC_OP_REG_IMB4 ); \ - \ - _mbg_outp32( (_d), (_d)->irq_ack_port, (_d)->irq_ack_mask ); \ + #define _pcps_ddev_ack_irq_pci( _d ) \ + if ( (_d)->irq_ack_mask ) \ + { \ + if ( _pcps_ddev_is_pci_amcc( _d ) ) \ + _mbg_inp32( (_d), 0, _pcps_ddev_io_base_mapped( _d, 0 ) \ + + AMCC_OP_REG_IMB4 ); \ + \ + _mbg_outp32_ex( (_d), 0, (_d)->irq_ack_port, control_status, \ + (_d)->irq_ack_mask ); \ } // In IRQ init function, enable IRQ on the // interface chip. - #define _pcps_ddev_enb_irq_pci( _d ) \ - if ( (_d)->irq_enb_mask ) \ - { \ - uint32_t intcsr = _mbg_inp32_to_cpu( (_d), (_d)->irq_enb_disb_port ); \ - _mbg_outp32( (_d), (_d)->irq_enb_disb_port, \ - intcsr | (_d)->irq_enb_mask ); \ + #define _pcps_ddev_enb_irq_pci( _d ) \ + if ( (_d)->irq_enb_mask ) \ + { \ + uint32_t intcsr = _mbg32_to_cpu( _mbg_inp32_ex( (_d), 0, \ + (_d)->irq_enb_disb_port, control_status ) ); \ + _mbg_outp32_ex( (_d), 0, (_d)->irq_enb_disb_port, control_status, \ + intcsr | (_d)->irq_enb_mask ); \ } // In IRQ de-init function, disable IRQ on the // interface chip. - #define _pcps_ddev_disb_irq_pci( _d ) \ - if ( (_d)->irq_disb_mask ) \ - { \ - uint32_t intcsr = _mbg_inp32_to_cpu( (_d), (_d)->irq_enb_disb_port ); \ - _mbg_outp32( (_d), (_d)->irq_enb_disb_port, \ - intcsr & ~(_d)->irq_disb_mask ); \ + #define _pcps_ddev_disb_irq_pci( _d ) \ + if ( (_d)->irq_disb_mask ) \ + { \ + uint32_t intcsr = _mbg32_to_cpu( _mbg_inp32_ex( (_d), 0, \ + (_d)->irq_enb_disb_port, control_status ) ); \ + _mbg_outp32_ex( (_d), 0, (_d)->irq_enb_disb_port, control_status, \ + intcsr & ~(_d)->irq_disb_mask ); \ } #else // Do nothing if PCI not supported. - #define _pcps_ddev_enb_irq_pci( _d ); - #define _pcps_ddev_disb_irq_pci( _d ); - #define _pcps_ddev_ack_irq_pci( _d ); + #define _pcps_ddev_enb_irq_pci( _d ) _nop_macro_fnc() + #define _pcps_ddev_disb_irq_pci( _d ) _nop_macro_fnc() + #define _pcps_ddev_ack_irq_pci( _d ) _nop_macro_fnc() #endif @@ -155,10 +164,10 @@ // For non-PCI devices check the IRQ flag of the clock's // status port. #if ( _PCPS_USE_PCI ) - #define _pcps_ddev_has_gen_irq( _d ) \ - ( ( (_d)->irq_flag_mask ) ? \ - ( _mbg_inp32( (_d), (_d)->irq_flag_port ) & (_d)->irq_flag_mask ) : \ - ( _pcps_ddev_read_status_port( _d ) & PCPS_ST_IRQF ) \ + #define _pcps_ddev_has_gen_irq( _d ) \ + ( ( (_d)->irq_flag_mask ) ? \ + ( _mbg_inp32_ex( (_d), 0, (_d)->irq_flag_port, control_status ) & (_d)->irq_flag_mask ) : \ + ( _pcps_ddev_read_status_port( _d ) & PCPS_ST_IRQF ) \ ) #else diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.c b/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.c index 944cee0..151a0e0 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.c +++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pcpslstr.c 1.22.1.4 2011/02/07 10:34:59 martin TEST $ + * $Id: pcpslstr.c 1.25 2017/07/05 07:43:53 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,13 +11,16 @@ * * ----------------------------------------------------------------------- * $Log: pcpslstr.c $ - * Revision 1.22.1.4 2011/02/07 10:34:59 martin + * Revision 1.25 2017/07/05 07:43:53 martin + * Use safe string functions from str_util.c. + * Started to add doxygen comments. + * Revision 1.24 2014/03/13 14:32:27 martin + * Fixed compiler warning. + * Revision 1.23 2012/10/15 13:09:35Z martin + * Added function sprint_utc_offs(). + * Cleaned up get_tz_name(). * Fixed potential compiler warning for sprintf(). - * Revision 1.22.1.3 2011/01/28 09:34:20 martin * Fixed build under FreeBSD. - * Revision 1.22.1.2 2010/11/05 12:55:10 martin - * Revision 1.22.1.1 2010/07/15 12:39:34 martin - * Added function sprint_utc_offs(). * Revision 1.22 2010/06/25 13:57:57Z daniel * Account for time zone offsets with minutes other than 0. * Revision 1.21 2009/03/19 08:06:58Z daniel @@ -40,7 +43,7 @@ * Revision 1.15 2007/07/20 10:55:27Z martin * Some modifications to avoid compiler warnings. * Revision 1.14 2007/03/30 13:23:42 martin - * In pcps_status_strs() handle case where time has been + * In pcps_status_strs() handle case where time has been * set manually. * Revision 1.13 2007/03/29 12:58:18Z martin * Moved some definitions to the header file to make them public. @@ -108,26 +111,41 @@ typedef struct } CLSTR_STATUS; -static const char *tz_name_utc = TZ_NAME_UTC; +static const char tz_name_utc[] = TZ_NAME_UTC; static CLSTR str_dst = { "DST", "Sommerzeit" }; /*HDR*/ +/** + * @brief Return a language dependend string for "invalid" + * + * @return A language dependend string for "invalid" + */ const char *inv_str( void ) { static CLSTR s = { "** invalid **", "** ung" LCUE "ltig **" }; return _lstr( s ); -} /* inv_str */ +} // inv_str /*HDR*/ -int sprint_utc_offs( char *s, const char *info, long utc_offs ) +/** + * @brief Print the UTC offset into a string + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] info An optional info string to be prepended, may be NULL + * @param[in] utc_offs UTC offset in [s] + * + * @return Number of characters written to the output buffer, except the terminating 0 + */ +size_t snprint_utc_offs( char *s, size_t max_len, const char *info, long utc_offs ) { - int n = 0; + size_t n = 0; // utc_offs is in [s] char utc_offs_sign = ( utc_offs < 0 ) ? '-' : '+'; @@ -138,17 +156,17 @@ int sprint_utc_offs( char *s, const char *info, long utc_offs ) ulong utc_offs_secs = tmp % MINS_PER_HOUR; if ( info ) - n += sprintf( &s[n], "%s", info ); + n += snprintf_safe( &s[n], max_len - n, "%s", info ); - n += sprintf( &s[n], "%c%lu", utc_offs_sign, utc_offs_hours ); + n += snprintf_safe( &s[n], max_len - n, "%c%lu", utc_offs_sign, utc_offs_hours ); if ( utc_offs_mins || utc_offs_secs ) - n += sprintf( &s[n], ":%02lu", utc_offs_mins ); + n += snprintf_safe( &s[n], max_len - n, ":%02lu", utc_offs_mins ); if ( utc_offs_secs ) - n += sprintf( &s[n], ":%02lu", utc_offs_secs ); + n += snprintf_safe( &s[n], max_len - n, ":%02lu", utc_offs_secs ); - n += sprintf( &s[n], "h" ); + n += sn_cpy_str_safe( &s[n], max_len - n, "h" ); return n; @@ -157,12 +175,28 @@ int sprint_utc_offs( char *s, const char *info, long utc_offs ) static /*HDR*/ +/** + * @brief Return a static string with the name of the timezone, depending on the UTC offset + * + * @param[in] pcps_status Status flags read from a clock device + * @param[in] utc_offs UTC offset in [s] + * @param[in] flags A combination of ::PCPS_TZ_NAME_FLAGS contolling the output string format + * @param[in] is_msf A Flag used to indicate if the clock is an MSF receiver + * + * @return Pointer to a static string which has been set up + * + * @see ::pcps_tz_name + * @see ::pcps_tz_name_from_hr_time + * @see ::pcps_tz_name_hr_status + * @see ::pcps_tz_name_from_status + * @see ::PCPS_TZ_NAME_FLAGS + */ const char *get_tz_name( PCPS_TIME_STATUS_X pcps_status, long utc_offs, ushort flags, int is_msf ) { static char ws[40]; const char *cp = NULL; - int n = 0; + size_t n = 0; if ( ( pcps_status & PCPS_UTC ) && ( utc_offs == 0 ) ) return tz_name_utc; // no offset, no DST @@ -197,7 +231,7 @@ const char *get_tz_name( PCPS_TIME_STATUS_X pcps_status, long utc_offs, } } - n = sprint_utc_offs( ws, tz_name_utc, utc_offs ); + n = snprint_utc_offs( ws, sizeof( ws ), tz_name_utc, utc_offs ); check_flags: if ( cp ) @@ -205,30 +239,45 @@ check_flags: if ( flags == 0 ) return cp; - strcpy( ws, cp ); + n = sn_cpy_str_safe( ws, sizeof( ws ), cp ); if ( flags & PCPS_TZ_NAME_FORCE_UTC_OFFS ) { - n = strlen( ws ); - n += sprintf( &ws[n], "%*c(", pcps_time_tz_dist, ' ' ); - n += sprint_utc_offs( &ws[n], tz_name_utc, utc_offs ); - sprintf( &ws[n], ")" ); + n += snprintf_safe( &ws[n], sizeof( ws ) - n, "%*c(", pcps_time_tz_dist, ' ' ); + n += snprint_utc_offs( &ws[n], sizeof( ws ) - n, tz_name_utc, utc_offs ); + n += sn_cpy_char_safe( &ws[n], sizeof( ws ) - n, ')' ); } } if ( flags & PCPS_TZ_NAME_APP_DST ) { if ( pcps_status & PCPS_DL_ENB ) - sprintf( _eos( ws ), ",%*c%s", pcps_time_tz_dist, - ' ', _lstr( str_dst ) ); + snprintf_safe( &ws[n], sizeof( ws ) - n, ",%*c%s", pcps_time_tz_dist, + ' ', _lstr( str_dst ) ); } return ws; -} + +} // get_tz_name /*HDR*/ +/** + * @brief Return a static time zone string depending on the UTC offset from a ::PCPS_TIME structure + * + * @param[in] t A ::PCPS_TIME structure read from a clock device + * @param[in] flags A combination of ::PCPS_TZ_NAME_FLAGS contolling the output string format + * @param[in] is_msf A Flag used to indicate if the clock is an MSF receiver + * + * @return Pointer to a static string which has been set up + * + * @see ::pcps_tz_name_from_hr_time + * @see ::pcps_tz_name_hr_status + * @see ::pcps_tz_name_from_status + * @see ::get_tz_name + * @see ::PCPS_TZ_NAME_FLAGS + */ const char *pcps_tz_name( const PCPS_TIME *t, ushort flags, int is_msf ) { return get_tz_name( t->status, t->offs_utc * SECS_PER_HOUR, flags, is_msf ); @@ -238,6 +287,21 @@ const char *pcps_tz_name( const PCPS_TIME *t, ushort flags, int is_msf ) /*HDR*/ +/** + * @brief Return a static time zone string depending on the UTC offset from a ::PCPS_HR_TIME structure + * + * @param[in] hrt A ::PCPS_HR_TIME structure read from a clock device + * @param[in] flags A combination of ::PCPS_TZ_NAME_FLAGS contolling the output string format + * @param[in] is_msf A Flag used to indicate if the clock is an MSF receiver + * + * @return Pointer to a static string which has been set up + * + * @see ::pcps_tz_name + * @see ::pcps_tz_name_hr_status + * @see ::pcps_tz_name_from_status + * @see ::get_tz_name + * @see ::PCPS_TZ_NAME_FLAGS + */ const char *pcps_tz_name_from_hr_time( const PCPS_HR_TIME *hrt, ushort flags, int is_msf ) { return get_tz_name( hrt->status, hrt->utc_offs, flags, is_msf ); @@ -246,22 +310,36 @@ const char *pcps_tz_name_from_hr_time( const PCPS_HR_TIME *hrt, ushort flags, in -// The function below can be used to build a name for -// the time zone if the TIMESCALE, the UTC/DST status and the -// UTC offset are known, e.g. from plug-in clocks. - /*HDR*/ +/** + * @brief Return a static time zone string depending on the UTC offset from a ::PCPS_HR_TIME structure + * + * This function can be used to build a name for the time zone if the timescale, + * the %UTC/DST status and the %UTC offset are known, e.g. from plug-in clock devices. + * + * @param[in] t A ::PCPS_HR_TIME structure read from a clock device + * @param[in] flags A combination of ::PCPS_TZ_NAME_FLAGS contolling the output string format + * @param[in] is_msf A Flag used to indicate if the clock is an MSF receiver + * + * @return Pointer to a static string which has been set up + * + * @see ::pcps_tz_name + * @see ::pcps_tz_name_from_hr_time + * @see ::pcps_tz_name_from_status + * @see ::get_tz_name + * @see ::PCPS_TZ_NAME_FLAGS + */ const char *pcps_tz_name_hr_status( const PCPS_HR_TIME *t, ushort flags, int is_msf ) { static char ws[40]; if ( t->status & PCPS_SCALE_GPS ) - strcpy( ws, "GPS" ); + strncpy_safe( ws, "GPS", sizeof( ws ) ); else if ( t->status & PCPS_SCALE_TAI ) - strcpy( ws, "TAI" ); + strncpy_safe( ws, "TAI", sizeof( ws ) ); else - return pcps_tz_name_from_hr_time( t, flags, is_msf); + return pcps_tz_name_from_hr_time( t, flags, is_msf ); return ws; @@ -269,13 +347,25 @@ const char *pcps_tz_name_hr_status( const PCPS_HR_TIME *t, ushort flags, int is_ -// The function below can be used to build a name for -// the time zone if only the UTC/DST status is known -// but the UTC offset is not. This is the case, for example, -// if the Meinberg standard time string is decoded. - /*HDR*/ -const char *pcps_tz_name_from_status( ushort status ) +/** + * @brief Return a static time zone string depending on the UTC offset from a ::PCPS_HR_TIME structure + * + * This function can be used to build a name for the time zone + * if only the %UTC/DST status is known, but the UTC offset is not. + * This is the case, for example, if the Meinberg standard time string is decoded. + * + * @param[in] status Clock status in ::PCPS_TIME_STATUS_X format + * + * @return Pointer to a static string which has been set up + * + * @see ::pcps_tz_name + * @see ::pcps_tz_name_from_hr_time + * @see ::pcps_tz_name_hr_status + * @see ::get_tz_name + * @see ::PCPS_TZ_NAME_FLAGS + */ +const char *pcps_tz_name_from_status( PCPS_TIME_STATUS_X status ) { if ( status & PCPS_UTC ) return tz_name_utc; @@ -287,33 +377,39 @@ const char *pcps_tz_name_from_status( ushort status ) /*HDR*/ -char *pcps_date_time_str( char *s, const PCPS_TIME *t, +char *pcps_date_time_str( char *s, size_t max_len, const PCPS_TIME *t, ushort year_limit, const char *tz_str ) { if ( !_pcps_time_is_read( t ) ) - strcpy( s, str_not_avail ); + strncpy_safe( s, str_not_avail, max_len ); else { - char *cp; + size_t n; int i; - _pcps_sprint_wday( s, t, language ); - cp = _eos( s ); - *cp++ = ','; + _pcps_snprint_wday( s, max_len, t, language ); + n = strlen( s ); + + n += sn_cpy_char_safe( &s[n], max_len - n, ',' ); + for ( i = 0; i < pcps_wday_date_dist; i++ ) - *cp++ = ' '; - _pcps_sprint_date( cp, t, year_limit ); - cp = _eos( s ); + n += sn_cpy_char_safe( &s[n], max_len - n, ' ' ); + + _pcps_snprint_date( &s[n], max_len - n, t, year_limit ); + n = strlen( s ); + for ( i = 0; i < pcps_date_time_dist; i++ ) - *cp++ = ' '; - _pcps_sprint_time_long( cp, t ); + n += sn_cpy_char_safe( &s[n], max_len - n, ' ' ); + + _pcps_snprint_time_long( &s[n], max_len - n, t ); + n = strlen( s ); if ( tz_str ) { - cp = _eos( s ); for ( i = 0; i < pcps_time_tz_dist; i++ ) - *cp++ = ' '; - strcpy( cp, tz_str ); + n += sn_cpy_char_safe( &s[n], max_len - n, ' ' ); + + n += sn_cpy_str_safe( &s[n], max_len - n, tz_str ); } } @@ -326,34 +422,22 @@ char *pcps_date_time_str( char *s, const PCPS_TIME *t, #if MBG_TGT_HAS_WCHAR_T && defined( MBG_TGT_WIN32 ) /*HDR*/ -wchar_t *pcps_date_time_wstr( wchar_t *ws, const PCPS_TIME *t, +wchar_t *pcps_date_time_wstr( wchar_t *ws, size_t count, const PCPS_TIME *t, ushort year_limit, const wchar_t *tz_str ) { - char stemp[80]; - wchar_t wstemp[80]; - - if ( !_pcps_time_is_read( t ) ) - mbstowcs( ws, str_not_avail, 32 ); - else - { - char *cp; - int i; + //#error Remove this error directive and check if the function works properly. + char tmp_str[80]; - _pcps_sprint_wday( stemp, t, language ); - cp = _eos( stemp ); - *cp++ = ','; - for ( i = 0; i < pcps_wday_date_dist; i++ ) - *cp++ = ' '; - _pcps_sprint_date( cp, t, year_limit ); - cp = _eos( stemp ); - for ( i = 0; i < pcps_date_time_dist; i++ ) - *cp++ = ' '; - _pcps_sprint_time_long( cp, t ); + pcps_date_time_str( tmp_str, sizeof( tmp_str ), t, year_limit, NULL ); - mbstowcs( wstemp, stemp, sizeof( wstemp ) ); + mbstowcs( ws, tmp_str, count ); + ws[count - 1] = L'0'; // force terminating 0 - if ( tz_str ) - _snwprintf( ws, sizeof( wstemp ) + 32, L"%s %s", wstemp, tz_str ); + if ( tz_str ) + { + size_t n = wcslen( ws ); + _snwprintf( &ws[n], count - n, L" %s", tz_str ); + ws[count - 1] = L'0'; // force terminating 0 } return ws; @@ -447,16 +531,16 @@ void pcps_status_strs( ushort status, int status_is_read, /*HDR*/ -char *pcps_port_str( char *s, const PCPS_DEV *pdev ) +char *pcps_port_str( char *s, size_t max_len, const PCPS_DEV *pdev ) { - ushort port = _pcps_port_base( pdev, 0 ); + ushort port = _pcps_short_port_base( pdev, 0 ); - ushort n = sprintf( s, "%3Xh", port ); + size_t n = snprintf_safe( s, max_len, "%3Xh", port ); - port = _pcps_port_base( pdev, 1 ); + port = _pcps_short_port_base( pdev, 1 ); if ( port ) - sprintf( &s[n], ", %3Xh", port ); + snprintf_safe( &s[n], max_len - n, ", %3Xh", port ); return s; @@ -477,25 +561,26 @@ const char *pcps_tzcode_str( PCPS_TZCODE tzcode ) /*HDR*/ -char *pcps_serial_str( char *s, int i, const RECEIVER_PORT_CFG *p, +char *pcps_serial_str( char *s, size_t max_len, int i, const RECEIVER_PORT_CFG *p, const RECEIVER_INFO *p_ri, int short_strs ) { const PORT_SETTINGS *p_ps = &p->pii[i].port_info.port_settings; const STR_TYPE_INFO *p_sti = &p->stii[p_ps->str_type].str_type_info; + size_t n; - sprintf( s, "%lu,%s", (ulong) p_ps->parm.baud_rate, p_ps->parm.framing ); + n = snprintf_safe( s, max_len, "%lu,%s", (ulong) p_ps->parm.baud_rate, p_ps->parm.framing ); if ( short_strs ) - sprintf( _eos( s ), ",%s", short_mode_name[p_ps->mode] ); + n += snprintf_safe( &s[n], max_len - n, ",%s", short_mode_name[p_ps->mode] ); else { if ( p_ri->n_str_type > 1 ) - sprintf( _eos( s ), ", %s", p_sti->long_name ); + n += snprintf_safe( &s[n], max_len - n, ", %s", p_sti->long_name ); - sprintf( _eos( s ), ", %s", _lstr( mode_name[p_ps->mode] ) ); + n += snprintf_safe( &s[n], max_len - n, ", %s", _lstr( mode_name[p_ps->mode] ) ); } - return( s ); + return s; } // pcps_serial_str diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.h index adf4b5e..241364c 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpslstr.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pcpslstr.h 1.27.1.5 2011/02/16 09:34:23 martin TRASH $ + * $Id: pcpslstr.h 1.30 2017/07/05 17:37:03 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,14 +10,23 @@ * * ----------------------------------------------------------------------- * $Log: pcpslstr.h $ - * Revision 1.27.1.5 2011/02/16 09:34:23 martin + * Revision 1.30 2017/07/05 17:37:03 martin + * Check for MBG_TGT_POSIX instead of MBG_TGT_UNIX. + * Account for new modes for programmable pulse outputs. + * Started to add doxygen comments. + * Fixed typos, wording, and doxygen comments. + * Updated function prototypes. + * Revision 1.29 2012/11/20 10:47:29 martin + * Moved some code definitions for special chars + * to new header charcode.h. + * Revision 1.28 2012/10/15 13:01:23 martin + * Include cfg_hlp.h. + * Made all declarations extern C. * Added menu titles for PTP and PTP Unicast configuration. - * Revision 1.27.1.4 2011/02/09 14:43:42Z martin - * Revision 1.27.1.3 2011/01/28 09:34:38 martin - * Fixed build under FreeBSD. - * Revision 1.27.1.2 2010/11/22 15:23:06 martin + * Added DEFAULT_OPT_NAME_TR_DISTANCE. + * Support time slots mode for programmable pulse outputs. * Added strings for programmable output synthesizer mode. - * Revision 1.27.1.1 2010/07/15 13:02:16 martin + * Fixed build under FreeBSD. * Also use ANSI umlauts under QNX. * Updated function prototypes. * Revision 1.27 2010/06/28 08:28:17Z stefan @@ -80,7 +89,7 @@ * Updated function prototypes. * Revision 1.6 2002/12/18 13:57:53 martin * Some definitions and variables made global. - * Added some new macros _pcps_sprint_vernum...() + * Added some new macros _pcps_sprint_vernum...() * and _pcps_sprint_dev_id(). * Revision 1.5 2002/02/19 10:01:36Z MARTIN * New initializers for string mode names. @@ -108,14 +117,13 @@ /* Other headers to be included */ -#include <mbg_tgt.h> -#include <parmpcps.h> +#include <str_util.h> +#include <charcode.h> +#include <cfg_hlp.h> +#include <pcpsdev.h> #include <ctrydttm.h> #include <cnv_wday.h> -#if MBG_TGT_HAS_WCHAR_T - #include <wchar.h> -#endif #ifdef _PCPSLSTR #define _ext @@ -127,92 +135,57 @@ /* Start of header body */ -// upper case 'A' umlaut -#define ANSI_UC_A_UML '\xC4' // single char -#define ANSI_US_A_UML "\xC4" // string - -// upper case 'O' umlaut -#define ANSI_UC_O_UML '\xD6' // single char -#define ANSI_US_O_UML "\xD6" // string - -// upper case 'U' umlaut -#define ANSI_UC_U_UML '\xDC' // single char -#define ANSI_US_U_UML "\xDC" // string - -// lower case 'a' umlaut -#define ANSI_LC_A_UML '\xE4' // single char -#define ANSI_LS_A_UML "\xE4" // string - -// lower case 'o' umlaut -#define ANSI_LC_O_UML '\xF6' // single char -#define ANSI_LS_O_UML "\xF6" // string - -// lower case 'u' umlaut -#define ANSI_LC_U_UML '\xFC' // single char -#define ANSI_LS_U_UML "\xFC" // string - -// 'sz' umlaut -#define ANSI_LC_SZ_UML '\xDF' // single char -#define ANSI_LS_SZ_UML "\xDF" // string - -// degree character -#define ANSI_C_DEGREE '\xB0' // single char -#define ANSI_S_DEGREE "\xB0" // string +#ifdef __cplusplus +extern "C" { +#endif -// greek mu character -#define ANSI_C_MU '\xB5' //single char -#define ANSI_S_MU "\xB5" //string #if defined( MBG_TGT_WIN32 ) \ - || defined( MBG_TGT_UNIX ) \ + || defined( MBG_TGT_POSIX ) \ || defined( MBG_TGT_QNX ) + #define DEFAULT_PCPS_WDAY_DATE_DIST 1 #define DEFAULT_PCPS_DATE_TIME_DIST 2 #define DEFAULT_PCPS_TIME_TZ_DIST 1 - #define UCAE ANSI_US_A_UML - #define UCOE ANSI_US_O_UML - #define UCUE ANSI_US_U_UML - - #define LCAE ANSI_LS_A_UML - #define LCOE ANSI_LS_O_UML - #define LCUE ANSI_LS_U_UML - - #define LCSZ ANSI_LS_SZ_UML - #define DEG ANSI_S_DEGREE - #define MU ANSI_S_MU #else + #define DEFAULT_PCPS_WDAY_DATE_DIST 1 #define DEFAULT_PCPS_DATE_TIME_DIST 2 #define DEFAULT_PCPS_TIME_TZ_DIST 1 - #define UCAE "\x8E" - #define UCOE "\x99" - #define UCUE "\x9A" - - #define LCAE "\x84" - #define LCOE "\x94" - #define LCUE "\x81" - - #define LCSZ "\xE1" - #define DEG "\xF8" - #define MU "\xE6" #endif -// The flags defined below can be passed to pcps_tz_name() -// in order to control the generation of time zone names -enum +/** + * @brief Flag bits used to define ::PCPS_TZ_NAME_FLAGS + * + * @see ::PCPS_TZ_NAME_FLAGS + */ +enum PCPS_TZ_NAME_BITS { - PCPS_TZ_NAME_BIT_FORCE_UTC_OFFS, // always print "UTC+offs" - PCPS_TZ_NAME_BIT_APP_DST, // append DST status + PCPS_TZ_NAME_BIT_FORCE_UTC_OFFS, ///< always print "UTC+offs" + PCPS_TZ_NAME_BIT_APP_DST, ///< append DST status N_PCPS_TZ_NAME_FLAG }; -// bit masks corresponding to the flags above -#define PCPS_TZ_NAME_FORCE_UTC_OFFS ( 1UL << PCPS_TZ_NAME_BIT_FORCE_UTC_OFFS ) -#define PCPS_TZ_NAME_APP_DST ( 1UL << PCPS_TZ_NAME_BIT_APP_DST ) + +/** + * @brief Flag bits used to control the string generated by ::pcps_tz_name + * + * The flags defined below can be passed to ::pcps_tz_name + * to control the formatting of the generated time zone names + * + * @see ::pcps_tz_name + * @see ::PCPS_TZ_NAME_BITS + */ +enum PCPS_TZ_NAME_FLAGS +{ + PCPS_TZ_NAME_FORCE_UTC_OFFS = ( 1UL << PCPS_TZ_NAME_BIT_FORCE_UTC_OFFS ), ///< see ::PCPS_TZ_NAME_FORCE_UTC_OFFS + PCPS_TZ_NAME_APP_DST = ( 1UL << PCPS_TZ_NAME_BIT_APP_DST ), ///< see ::PCPS_TZ_NAME_APP_DST +}; + // The definitions below are used with pcps_get_status_strs(). @@ -467,7 +440,7 @@ typedef struct #define DEFAULT_TZCODE_HINT_CET_CEST \ { \ - "Central European Time or Summer Time, as broadcasted by DCF77", \ + "Central European Time or Summer Time, as broadcast by DCF77", \ "Mitteleurop" LCAE "ische Zeit oder Sommerzeit, wie von DCF77 gesendet" \ } @@ -479,7 +452,7 @@ typedef struct #define DEFAULT_TZCODE_HINT_GMT_BST \ { \ - "Greenwich Mean Time or British Summer Time, as broadcasted by MSF", \ + "Greenwich Mean Time or British Summer Time, as broadcast by MSF", \ "Westeurop" LCAE "ische Zeit oder britische Sommerzeit, wie von MSF gesendet" \ } @@ -568,6 +541,15 @@ typedef struct } +// menu option: setup distance from transmitter + +#define DEFAULT_OPT_NAME_TR_DISTANCE \ +{ \ + "Distance from Transmitter", \ + "Senderentfernung" \ +} + + // menu option: setup IRIG config #define DEFAULT_OPT_NAME_IRIG_TX_EN "IRIG Output" @@ -791,12 +773,16 @@ typedef struct #define GER_POUT_NAME_DCF77 "DCF77-Zeitmarken" #define GER_POUT_NAME_POS_OK "Position OK" #define GER_POUT_NAME_TIME_SYNC "Zeit synchron" -#define GER_POUT_NAME_ALL_SYNC "alles synchron" +#define GER_POUT_NAME_ALL_SYNC "Alles synchron" #define GER_POUT_NAME_TIMECODE "DCLS-Zeitcode" -#define GER_POUT_NAME_TIMESTR "COM-Zeittelegramm" +#define GER_POUT_NAME_TIMESTR "Serielles Zeittelegramm" #define GER_POUT_NAME_10MHZ "Festfrequenz 10 MHz" #define GER_POUT_NAME_DCF77_M59 "DCF77-Zeitmarken mit 59. Impuls" -#define GER_POUT_NAME_SYNTH "Frequenz-Synthesizer" +#define GER_POUT_NAME_SYNTH "Synthesizer-Frequenz" +#define GER_POUT_NAME_TIME_SLOTS "Zeitschlitze pro Minute" +#define GER_POUT_NAME_GPIO "GPIO-Signal" +#define GER_POUT_PTTI_PPS "PTTI 1 PPS" +#define GER_POUT_HAVEQUICK "HaveQuick" #define DEFAULT_GER_POUT_NAMES \ { \ @@ -815,7 +801,11 @@ typedef struct GER_POUT_NAME_TIMESTR, \ GER_POUT_NAME_10MHZ, \ GER_POUT_NAME_DCF77_M59, \ - GER_POUT_NAME_SYNTH \ + GER_POUT_NAME_SYNTH, \ + GER_POUT_NAME_TIME_SLOTS, \ + GER_POUT_NAME_GPIO, \ + GER_POUT_PTTI_PPS, \ + GER_POUT_HAVEQUICK \ } /* @@ -838,6 +828,10 @@ typedef struct #define GER_POUT_HINT_10MHZ "Feste Ausgangsfrequenz 10 MHz" #define GER_POUT_HINT_DCF77_M59 "Zeitmarken wie DCF77, aber mit 500 ms Impuls in 59. Sekunde" #define GER_POUT_HINT_SYNTH "Durch programmierbaren Synthesizer erzeugte Frequenz" +#define GER_POUT_HINT_TIME_SLOTS "Programmierbare Zeitslots, die in jeder Minute aktiviert werden" +#define GER_POUT_HINT_GPIO "Signal des spezifizierten GPIO-Ein- oder Ausgangs" +#define GER_POUT_HINT_PTTI_PPS "20 us-Impuls zum Sekundenbeginn" +#define GER_POUT_HINT_HAVEQUICK "Dupliziertes HaveQuick-Signal" #define DEFAULT_GER_POUT_HINTS \ { \ @@ -856,83 +850,80 @@ typedef struct GER_POUT_HINT_TIMESTR, \ GER_POUT_HINT_10MHZ, \ GER_POUT_HINT_DCF77_M59, \ - GER_POUT_HINT_SYNTH \ + GER_POUT_HINT_SYNTH, \ + GER_POUT_HINT_TIME_SLOTS, \ + GER_POUT_HINT_GPIO, \ + GER_POUT_HINT_PTTI_PPS, \ + GER_POUT_HINT_HAVEQUICK \ } // some macros which generate proper function calls -#define _pcps_sprint_vernum_dec( _s, _v ) \ - sprintf( (_s), "v%u.%02u", \ - ( (unsigned) (_v) ) / 100, \ - ( (unsigned) (_v) ) % 100 ) +#define _pcps_snprint_vernum_dec( _s, _sz, _v ) \ + snprintf_safe( (_s), (_sz), "v%u.%02u", \ + ( (unsigned) (_v) ) / 100, \ + ( (unsigned) (_v) ) % 100 ) -#define _pcps_sprint_vernum_hex( _s, _v ) \ - sprintf( (_s), "v%X.%02X", \ - ( (unsigned) (_v) ) >> 8, \ +#define _pcps_snprint_vernum_hex( _s, _sz, _v ) \ + snprintf_safe( (_s), (_sz), "v%X.%02X", \ + ( (unsigned) (_v) ) >> 8, \ ( (unsigned) (_v) ) & 0xFF ) #if defined( MBG_TGT_WIN32 ) - #define _pcps_sprint_vernum _pcps_sprint_vernum_dec + #define _pcps_snprint_vernum _pcps_snprint_vernum_dec #else - #define _pcps_sprint_vernum _pcps_sprint_vernum_hex + #define _pcps_snprint_vernum _pcps_snprint_vernum_hex #endif -#define _pcps_sprint_dev_id( _s, _n ) \ - sprintf( (_s), "%04Xh", _n ) +#define _pcps_snprint_dev_id( _s, _sz, _n ) \ + snprintf_safe( (_s), (_sz), "%04Xh", _n ) -#define _pcps_sprint_wday( _s, _t, _l ) \ - sprint_ctry_wday( (_s), _wday_mon17_to_sun06( (_t)->wday ), (_l) ) +#define _pcps_snprint_wday( _s, _sz, _t, _l ) \ + snprint_ctry_wday( (_s), (_sz), _wday_mon17_to_sun06( (_t)->wday ), (_l) ) -#define _pcps_sprint_date( _s, _t, _yl ) \ - sprint_ctry_dt( (_s), (_t)->mday, (_t)->month, \ +#define _pcps_snprint_date( _s, _sz, _t, _yl ) \ + snprint_ctry_dt( (_s), (_sz), (_t)->mday, (_t)->month, \ pcps_exp_year( (_t)->year, (_yl) ) ) -#define _pcps_sprint_time( _s, _t ) \ - sprint_ctry_tm( (_s), (_t)->hour, (_t)->min, (_t)->sec ) +#define _pcps_snprint_time( _s, _sz, _t ) \ + snprint_ctry_tm( (_s), (_sz), (_t)->hour, (_t)->min, (_t)->sec ) -#define _pcps_sprint_time_long( _s, _t ) \ - sprint_ctry_tm_long( (_s), (_t)->hour, (_t)->min, (_t)->sec, (_t)->sec100, 2 ) +#define _pcps_snprint_time_long( _s, _sz, _t ) \ + snprint_ctry_tm_long( (_s), (_sz), (_t)->hour, (_t)->min, (_t)->sec, (_t)->sec100, 2 ) -#define _cput_pcps_date( _t, _yl ) \ -{ \ - char s[80]; \ - _pcps_sprint_date( s, (_t), (_yl) ); \ - cputs( s ); \ +#define _cput_pcps_date( _t, _yl ) \ +{ \ + char s[80]; \ + _pcps_snprint_date( s, sizeof( s ), (_t), (_yl) ); \ + cputs( s ); \ } -#define _cput_pcps_time( _t ) \ -{ \ - char s[80]; \ - _pcps_sprint_time( s, (_t) ); \ - cputs( s ); \ +#define _cput_pcps_time( _t ) \ +{ \ + char s[80]; \ + _pcps_snprint_time( s, sizeof( s ), (_t) ); \ + cputs( s ); \ } -#define _cput_pcps_time_long( _t ) \ -{ \ - char s[80]; \ - _pcps_sprint_time_long( s, (_t) ); \ - cputs( s ); \ +#define _cput_pcps_time_long( _t ) \ +{ \ + char s[80]; \ + _pcps_snprint_time_long( s, sizeof( s ), (_t) ); \ + cputs( s ); \ } -#define _cput_pcps_date_and_time( _t, _yl, _tz ) \ -{ \ - char s[80]; \ - cputs( pcps_date_time_str( s, (_t), (_yl), (_tz) ) ); \ +#define _cput_pcps_date_and_time( _t, _yl, _tz ) \ +{ \ + char s[80]; \ + cputs( pcps_date_time_str( s, sizeof( s ), (_t), (_yl), (_tz) ) ); \ } -_ext const char *str_not_avail -#ifdef _DO_INIT - = "N/A" -#endif -; - - _ext CLSTR lstr_cet #ifdef _DO_INIT = { TZ_NAME_CET, TZ_NAME_MEZ } @@ -1001,27 +992,109 @@ _ext const char *short_mode_name[N_STR_MODE] ; -#ifdef __cplusplus -extern "C" { -#endif - /* ----- function prototypes begin ----- */ /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ + /** + * @brief Return a language dependend string for "invalid" + * + * @return A language dependend string for "invalid" + */ const char *inv_str( void ) ; - int sprint_utc_offs( char *s, const char *info, long utc_offs ) ; + + /** + * @brief Print the UTC offset into a string + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] info An optional info string to be prepended, may be NULL + * @param[in] utc_offs UTC offset in [s] + * + * @return Number of characters written to the output buffer, except the terminating 0 + */ + size_t snprint_utc_offs( char *s, size_t max_len, const char *info, long utc_offs ) ; + + /** + * @brief Return a static time zone string depending on the UTC offset from a ::PCPS_TIME structure + * + * @param[in] t A ::PCPS_TIME structure read from a clock device + * @param[in] flags A combination of ::PCPS_TZ_NAME_FLAGS contolling the output string format + * @param[in] is_msf A Flag used to indicate if the clock is an MSF receiver + * + * @return Pointer to a static string which has been set up + * + * @see ::pcps_tz_name_from_hr_time + * @see ::pcps_tz_name_hr_status + * @see ::pcps_tz_name_from_status + * @see ::get_tz_name + * @see ::PCPS_TZ_NAME_FLAGS + */ const char *pcps_tz_name( const PCPS_TIME *t, ushort flags, int is_msf ) ; + + /** + * @brief Return a static time zone string depending on the UTC offset from a ::PCPS_HR_TIME structure + * + * @param[in] hrt A ::PCPS_HR_TIME structure read from a clock device + * @param[in] flags A combination of ::PCPS_TZ_NAME_FLAGS contolling the output string format + * @param[in] is_msf A Flag used to indicate if the clock is an MSF receiver + * + * @return Pointer to a static string which has been set up + * + * @see ::pcps_tz_name + * @see ::pcps_tz_name_hr_status + * @see ::pcps_tz_name_from_status + * @see ::get_tz_name + * @see ::PCPS_TZ_NAME_FLAGS + */ const char *pcps_tz_name_from_hr_time( const PCPS_HR_TIME *hrt, ushort flags, int is_msf ) ; + + /** + * @brief Return a static time zone string depending on the UTC offset from a ::PCPS_HR_TIME structure + * + * This function can be used to build a name for the time zone if the timescale, + * the %UTC/DST status and the %UTC offset are known, e.g. from plug-in clock devices. + * + * @param[in] t A ::PCPS_HR_TIME structure read from a clock device + * @param[in] flags A combination of ::PCPS_TZ_NAME_FLAGS contolling the output string format + * @param[in] is_msf A Flag used to indicate if the clock is an MSF receiver + * + * @return Pointer to a static string which has been set up + * + * @see ::pcps_tz_name + * @see ::pcps_tz_name_from_hr_time + * @see ::pcps_tz_name_from_status + * @see ::get_tz_name + * @see ::PCPS_TZ_NAME_FLAGS + */ const char *pcps_tz_name_hr_status( const PCPS_HR_TIME *t, ushort flags, int is_msf ) ; - const char *pcps_tz_name_from_status( ushort status ) ; - char *pcps_date_time_str( char *s, const PCPS_TIME *t, ushort year_limit, const char *tz_str ) ; - wchar_t *pcps_date_time_wstr( wchar_t *ws, const PCPS_TIME *t, ushort year_limit, const wchar_t *tz_str ) ; + + /** + * @brief Return a static time zone string depending on the UTC offset from a ::PCPS_HR_TIME structure + * + * This function can be used to build a name for the time zone + * if only the %UTC/DST status is known, but the UTC offset is not. + * This is the case, for example, if the Meinberg standard time string is decoded. + * + * @param[in] status Clock status in ::PCPS_TIME_STATUS_X format + * + * @return Pointer to a static string which has been set up + * + * @see ::pcps_tz_name + * @see ::pcps_tz_name_from_hr_time + * @see ::pcps_tz_name_hr_status + * @see ::get_tz_name + * @see ::PCPS_TZ_NAME_FLAGS + */ + const char *pcps_tz_name_from_status( PCPS_TIME_STATUS_X status ) ; + + char *pcps_date_time_str( char *s, size_t max_len, const PCPS_TIME *t, ushort year_limit, const char *tz_str ) ; + wchar_t *pcps_date_time_wstr( wchar_t *ws, size_t count, const PCPS_TIME *t, ushort year_limit, const wchar_t *tz_str ) ; void pcps_status_strs( ushort status, int status_is_read, int is_gps, PCPS_STATUS_STRS *pstrs ) ; - char *pcps_port_str( char *s, const PCPS_DEV *pdev ) ; + char *pcps_port_str( char *s, size_t max_len, const PCPS_DEV *pdev ) ; const char *pcps_tzcode_str( PCPS_TZCODE tzcode ) ; - char *pcps_serial_str( char *s, int i, const RECEIVER_PORT_CFG *p, const RECEIVER_INFO *p_ri, int short_strs ) ; + char *pcps_serial_str( char *s, size_t max_len, int i, const RECEIVER_PORT_CFG *p, const RECEIVER_INFO *p_ri, int short_strs ) ; /* ----- function prototypes end ----- */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.c b/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.c index 212dfb3..b26b1a8 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.c +++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pcpsmktm.c 1.4 2006/12/14 15:27:49 martin REL_M $ + * $Id: pcpsmktm.c 1.5 2017/07/05 08:05:11 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,10 @@ * * ----------------------------------------------------------------------- * $Log: pcpsmktm.c $ + * Revision 1.5 2017/07/05 08:05:11 martin + * Let pcps_mktime() return a 'time_t' instead of 'long', and made + * the PCPS_TIME pointer parameter 'const'. + * Added doxygen comments. * Revision 1.4 2006/12/14 15:27:49 martin * Include time.h. * Revision 1.3 2006/08/22 09:10:03 martin @@ -27,25 +31,40 @@ #include <mbgmktm.h> -#include <time.h> /*HDR*/ -long pcps_mktime( PCPS_TIME *tp ) +/** + * @brief Compute a linear time_t value from ::PCPS_TIME + * + * This function works like the standard mktime() function but does not + * account for a timezone setting configured for the standard C library. + * Instead, since ::PCPS_TIME contains local time with specified UTC offset + * the UTC offset is removed to yield UTC time. + * + * @param[in] tp A timestamp in ::PCPS_TIME format + * + * @return seconds since 1970-01-01 (Unix time_t format) or ((time_t) -1) if range overflow + */ +time_t pcps_mktime( const PCPS_TIME *tp ) { time_t secs; int year = tp->year; + // Expand 2 digit year number (year of the century) to 4 digits + // including the century. if ( year < 70 ) year += 100; + // Plausibility checks are made by mbg_mktime(). secs = mbg_mktime( year, tp->month - 1, tp->mday - 1, tp->hour, tp->min, tp->sec ); - if ( secs != -1 ) - secs -= tp->offs_utc * 3600; + // Convert to UTC if result is valid. + if ( secs != ( (time_t) -1 ) ) + secs -= tp->offs_utc * 3600UL; - return( secs ); + return secs; } // pcps_mktime diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.h index efcc2df..eb4c05b 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsmktm.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pcpsmktm.h 1.1 2001/02/02 15:31:07 MARTIN REL_M $ + * $Id: pcpsmktm.h 1.2 2017/07/05 08:18:54 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,9 @@ * * ----------------------------------------------------------------------- * $Log: pcpsmktm.h $ + * Revision 1.2 2017/07/05 08:18:54 martin + * Cleaned up to conform to standard header file format. + * Updated function prototypes. * Revision 1.1 2001/02/02 15:31:07 MARTIN * **************************************************************************/ @@ -22,9 +25,12 @@ #include <pcpsdefs.h> +#include <time.h> + #ifdef _PCPSMKTM #define _ext + #define _DO_INIT #else #define _ext extern #endif @@ -32,25 +38,31 @@ /* Start of header body */ -//_ext PCPS_TIME tx; - -/* End of header body */ - -#undef _ext - - -/* function prototypes: */ - #ifdef __cplusplus extern "C" { #endif + + /* ----- function prototypes begin ----- */ /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ - long pcps_mktime( PCPS_TIME *tp ) ; + /** + * @brief Compute a linear time_t value from ::PCPS_TIME + * + * This function works like the standard mktime() function but does not + * account for a timezone setting configured for the standard C library. + * Instead, since ::PCPS_TIME contains local time with specified UTC offset + * the UTC offset is removed to yield UTC time. + * + * @param[in] tp A timestamp in ::PCPS_TIME format + * + * @return seconds since 1970-01-01 (Unix time_t format) or ((time_t) -1) if range overflow + */ + time_t pcps_mktime( const PCPS_TIME *tp ) ; + /* ----- function prototypes end ----- */ @@ -58,5 +70,9 @@ extern "C" { } #endif +/* End of header body */ + +#undef _ext +#undef _DO_INIT #endif /* _PCPSMKTM_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.c b/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.c deleted file mode 100755 index 0dcf53d..0000000 --- a/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.c +++ /dev/null @@ -1,162 +0,0 @@ - -/************************************************************************** - * - * $Id: pcpsutil.c 1.14 2011/06/29 11:03:44 martin TRASH $ - * - * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany - * - * Description: - * Utility functions used with programs for Meinberg devices. - * - * ----------------------------------------------------------------------- - * $Log: pcpsutil.c $ - * Revision 1.14 2011/06/29 11:03:44 martin - * Updated a comment. - * Revision 1.13 2009/03/09 13:39:45 martin - * Made pcps_exp_year() an inline function. - * Revision 1.12 2008/12/10 19:59:48 martin - * Made frac_sec_from_bin() an inline function. - * Revision 1.11 2008/11/25 10:00:25 martin - * Use new definitions of fraction conversion type and scale - * from pcpsdefs.h. - * Revision 1.10 2006/06/29 10:38:24Z martin - * New function pcps_time_is_valid(). - * Modified pcps_str_to_port(), doesn't add a 0 entry to the list anymore. - * Fixed a compiler warning related to type conversion. - * Revision 1.9 2005/01/14 10:14:31Z martin - * Changed type of ISA port addr to int. - * Revision 1.8 2004/11/09 14:29:27Z martin - * Rewrote functions using C99 fixed-size definitions. - * Revision 1.7 2003/04/17 10:08:59Z martin - * Added some type casts to fix compiler warnings. - * Revision 1.6 2001/11/28 14:39:16Z MARTIN - * In frac_sec_from_bin(), define the divisor as floating point - * constant to avoid a domain errors on 16 bit systems. - * Revision 1.5 2001/09/17 07:28:01 MARTIN - * New function frac_sec_from_bin() to convert - * PCPS_HR_TIME fractions. - * Revision 1.4 2001/03/01 14:01:09 MARTIN - * Modified parameters for pcps_setup_isa_ports(). - * Revision 1.3 2000/08/31 14:05:30 MARTIN - * Replaced pcps_str_to_port() by pcps_setup_isa_ports(). - * Revision 1.2 2000/07/21 13:42:54 MARTIN - * Initial revision - * - **************************************************************************/ - -#define _PCPSUTIL - #include <pcpsutil.h> -#undef _PCPSUTIL - -#include <stdlib.h> - - -/*-------------------------------------------------------------- - * Name: pcps_time_is_valid() - * - * Purpose: Pack a structure with serial port parameters - * - * Input/Output: p address of a structure holding both the - * packed and unpacked information - * - * Ret value: -- - *-------------------------------------------------------------*/ - -/*HDR*/ -int pcps_time_is_valid( const PCPS_TIME *p ) -{ - return ( p->sec100 <= 99 ) - && ( p->sec <= 60 ) /* allow for leap second */ - && ( p->min <= 59 ) - && ( p->hour <= 23 ) - && ( p->mday >= 1 ) && ( p->mday <= 31 ) - && ( p->wday >= 1 ) && ( p->wday <= 7 ) - && ( p->month >= 1 ) && ( p->month <= 12 ) - && ( p->year <= 99 ); - -} /* pcps_time_is_valid */ - - - -/*-------------------------------------------------------------- - * Name: pcps_str_to_port() - * - * Purpose: Try to convert a string to a valid port - * address. - * - * Input: s the string - * - * Output: -- - * - * Ret value: a valid port number or 0 - *+-------------------------------------------------------------*/ - -/*HDR*/ -void pcps_setup_isa_ports( char *s, - int *port_vals, - int n_vals ) -{ - ushort i; - - - for ( i = 0; i < n_vals; i++ ) - { - if ( *s == 0 ) - break; - - *port_vals++ = (uint16_t) strtoul( s, &s, 16 ); - - if ( *s == ',' ) - s++; - } - -} // pcps_setup_isa_ports - - - -/*-------------------------------------------------------------- - * Name: pcps_unpack_serial() - * - * Purpose: Unpack a structure with serial port parameters - * - * Input/Output: p address of a structure holding both the - * packed and unpacked information - * - * Ret value: -- - *-------------------------------------------------------------*/ - -/*HDR*/ -void pcps_unpack_serial( PCPS_SER_PACK *p ) -{ - uint8_t pack = p->pack; - - p->baud = (uint8_t) ( pack & BITMASK( PCPS_BD_BITS ) ); - p->frame = (uint8_t) ( ( pack >> PCPS_FR_SHIFT ) & BITMASK( PCPS_FR_BITS ) ); - p->mode = (uint8_t) ( ( pack >> PCPS_MOD_SHIFT ) & BITMASK( PCPS_MOD_BITS ) ); - -} // pcps_unpack_serial - - - -/*-------------------------------------------------------------- - * Name: pcps_pack_serial() - * - * Purpose: Pack a structure with serial port parameters - * - * Input/Output: p address of a structure holding both the - * packed and unpacked information - * - * Ret value: -- - *-------------------------------------------------------------*/ - -/*HDR*/ -void pcps_pack_serial( PCPS_SER_PACK *p ) -{ - p->pack = (uint8_t) ( ( p->baud & BITMASK( PCPS_BD_BITS ) ) - | ( ( p->frame & BITMASK( PCPS_FR_BITS ) ) << PCPS_FR_SHIFT ) - | ( ( p->mode & BITMASK( PCPS_MOD_BITS ) ) << PCPS_MOD_SHIFT ) ); - -} /* pcps_pack_serial */ - - - diff --git a/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.h b/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.h index e5cab81..29dfdc7 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/pcpsutil.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pcpsutil.h 1.14 2009/03/09 13:39:45 martin REL_M $ + * $Id: pcpsutil.h 1.23 2017/05/10 15:26:09 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,6 +10,27 @@ * * ----------------------------------------------------------------------- * $Log: pcpsutil.h $ + * Revision 1.23 2017/05/10 15:26:09 martin + * Tiny cleanup. + * Revision 1.22 2017/03/17 11:45:51 martin + * Moved binary fraction conversion functions to cfg_hlp.h. + * Revision 1.21 2015/10/26 16:09:58 martin + * Moved definition of PCPS_SER_PACK to deviohlp.h. + * The .c file is now obsolete, so there are no prototypes anymore. + * Revision 1.20 2014/07/22 12:22:27Z martin + * Fixed a compiler warning. + * Revision 1.19 2014/07/14 15:43:23Z martin + * Updated doxygen comment. + * Revision 1.18 2014/06/26 14:52:50 martin + * Fixed build on targets not supporting 64 bit types. + * Updated some comments to doxygen format. + * Revision 1.17 2014/05/27 10:39:33Z martin + * More inline functions to convert binary fractions by thomas-b. + * Moved definitions of some signal constants to pcpsdefs.h. + * Revision 1.16 2013/03/04 15:51:02Z martin + * Added dfrac_sec_from_bin(). + * Revision 1.15 2012/10/15 09:41:32 martin + * Cleaned up handling of pragma pack(). * Revision 1.14 2009/03/09 13:39:45 martin * Made pcps_exp_year() an inline function. * Revision 1.13 2008/12/10 19:59:48 martin @@ -63,48 +84,27 @@ /* Start of header body */ -#if defined( _USE_PACK ) // set byte alignment - #pragma pack( 1 ) +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT #endif - -// The following constants are used to draw a signal bar -// depending on a DCF77 clock's signal value: -#define PCPS_SIG_BIAS 55 -#define PCPS_SIG_ERR 1 -#define PCPS_SIG_MIN 20 -#define PCPS_SIG_MAX 68 - - -// the structure below is used with a DCF77 clock's serial interface -typedef struct -{ - PCPS_SERIAL pack; // this byte is passed to the board as parameter - - uint8_t baud; // the other bytes can hold the unpacked values - uint8_t frame; - uint8_t mode; - -} PCPS_SER_PACK; - +#ifdef __cplusplus +extern "C" { +#endif -/*-------------------------------------------------------------- - * Name: pcps_exp_year() - * - * Purpose: Convert a 2-digit year number to a 4-digit - * year number. The resulting year number is in - * the range [year_lim ... ( year_lim + 99 )]. +/** + * @brief Expand a 2-digit year number to a 4-digit year number * - * Input: year the 2-digit year number - * year_lim the smallest 4-digit year number - * to be returned + * The resulting year number includes the century and is + * in the range [year_lim ... ( year_lim + 99 )]. * - * Output: -- + * @param[in] year The 2-digit year number to be converted + * @param[in] year_lim The smallest 4-digit year number to be returned * - * Ret value: the calculated 4-digit year num - *+-------------------------------------------------------------*/ - + * @return The resulting 4 digit year number including century + */ static __mbg_inline uint16_t pcps_exp_year( uint8_t year, uint16_t year_lim ) { @@ -120,21 +120,12 @@ uint16_t pcps_exp_year( uint8_t year, uint16_t year_lim ) -/* function prototypes: */ - -#ifdef __cplusplus -extern "C" { -#endif - /* ----- function prototypes begin ----- */ /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ - int pcps_time_is_valid( const PCPS_TIME *p ) ; - void pcps_setup_isa_ports( char *s, int *port_vals, int n_vals ) ; - void pcps_unpack_serial( PCPS_SER_PACK *p ) ; - void pcps_pack_serial( PCPS_SER_PACK *p ) ; +/* (no header definitions found) */ /* ----- function prototypes end ----- */ @@ -143,36 +134,10 @@ extern "C" { #endif -/*-------------------------------------------------------------- - * Name: frac_sec_from_bin() - * - * Purpose: Convert a fraction of a second from binary - * format (as returned in a PCPS_HR_TIME structure - * to a decimal fraction, using a specified scale - * factor. See also the definitions of - * PCPS_HRT_FRAC_SCALE and PCPS_HRT_FRAC_SCALE_FMT - * in the header file. - * - * Input: b the binary fraction - * scale the scale factor - * - * Output: -- - * - * Ret value: the calculated number - *+-------------------------------------------------------------*/ - -static __mbg_inline -uint32_t frac_sec_from_bin( uint32_t b, uint32_t scale ) -{ - return (uint32_t) ( (PCPS_HRT_FRAC_CONVERSION_TYPE) b * scale - / PCPS_HRT_BIN_FRAC_SCALE ); - -} // frac_sec_from_bin - - -#if defined( _USE_PACK ) // set default alignment - #pragma pack() +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT #endif /* End of header body */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/plxdefs.h b/src/external/bsd/meinberg/dist/mbglib/common/plxdefs.h index ba1ce53..f59cc0d 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/plxdefs.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/plxdefs.h @@ -1,16 +1,36 @@ /************************************************************************** * - * $Id: plxdefs.h 1.2 2010/01/28 15:46:31 martin REL_M $ + * $Id: plxdefs.h 1.5 2017/05/10 15:26:09 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * * Description: - * Definitions to be used with PLX PCIexpress interface chips. + * Definitions to be used with PLX PCI Express interface chips. + * Some Meinberg cards use the PLX8311 chip in endpoint mode. + * + * The PLX8311 chip is combined of a PLX8111 PCIe-to-PCI bridge + * plus a PCI-to-Local bus interface combined in a single package. + * Thus each card using a PLX8311 implements an additional internal + * PCI bus with a single device connected to this bus. + * + * Each of these devices are individually visible from the PC's + * PCI bus and thus provide their own configuration spaces, + * configuration EEPROM, etc. + * + * Care must be taken not to confuse the registers of the PLX8311 + * with the correspondent registers of the built-in PLX8111 bridge. * * ----------------------------------------------------------------------- * $Log: plxdefs.h $ - * Revision 1.2 2010/01/28 15:46:31 martin + * Revision 1.5 2017/05/10 15:26:09 martin + * Tiny cleanup. + * Revision 1.4 2013/03/15 10:24:09 martin + * Renamed register and bit mask definitions to match the names in the data sheet. + * Added doxygen comments. + * Revision 1.3 2012/10/15 09:21:42Z martin + * Added some mailbox register addresses. + * Revision 1.2 2010/01/28 15:46:31Z martin * Added PLX8311_REG_CTRL. * Revision 1.1 2007/06/08 07:46:56Z martin * Initial revision. @@ -20,7 +40,6 @@ #ifndef _PLXDEFS_H #define _PLXDEFS_H - /* Other headers to be included */ @@ -33,31 +52,113 @@ /* Start of header body */ -// The following PLX8311 operation registers can -// be accessed via port I/O or memory mapped: -#define PLX8311_REG_INTCSR 0x68 +#ifdef __cplusplus +extern "C" { +#endif -// The following bits must be set in the INTCSR register -// to let the local microcontroller be able to generate -// interrupts on the PCI bus via the chip's LINTi# line: -#define PLX8311_INT_ENB ( (1UL << 11) | (1UL << 8) ) +/** + * PCI device ID of the PCI bridge also built into the PLX8311 + */ +#define PCI_DEVICE_ID_PLX_8111 0x8111 -// The bit below signals if an LINTi# interrupt is active: -#define PLX8311_INT_FLAG (1UL << 15) -#define PLX8311_REG_CNTRL 0x6C +/** + * @brief PLX PCI Express Configuration Space (PECS) registers + * + * These registers are located in the PCI configuration space + * and can be accessed using standard PCI configuration register + * access functions. + * + * In addition the PECS registers are mirrored into the 64k + * memory space addressed via PCI base register 0, and thus + * can be accessed using memory reads or writes via the PCI bus. + * + * The default values of these registers can be overwritten + * by the PCI Express interface serial EEPROM. + * + * Care must be taken not to confuse the registers of the PLX8311 + * with the correspondent registers of the built-in PLX8111. + * Similarly the serial EEPROM for the PLX8311 must not be confused + * with the serial EEPROM for the built-in PEX8111 PCI bridge. + * + * Address Offset: + * 0000h - 0FFFh PCI compatible configuration registers + * 1000h - 1FFFh Main configuration registers + * 2000h - 2FFFh Memory mapped indirect access (PLX8311 only, see manual) + * 8000h - 9FFFh 8k internal shared memory + * + * See chapter 19 of the PLX8311 manual. + */ +enum PLX_PECS_REGS +{ + PLX_PECS_PCICAPPTR = 0x34, ///< PCI capabilities pointer + // PLX_PECS_LINKSTAT = 0x72, ///< Link status + PLX_PECS_MAININDEX = 0x84, ///< Main Control Register index + PLX_PECS_MAINDATA = 0x88, ///< Main Control Register data + + PLX_PECS_EECTL = 0x1004, ///< Serial EEPROM control + PLX_PECS_EECLKFREQ = 0x1008, ///< Serial EEPROM clock frequency control + PLX_PECS_GPIOCTL = 0x1020, ///< General Purpose I/O control + PLX_PECS_GPIOSTAT = 0x1024, ///< General Purpose I/O status + PLX_PECS_TLPCFG0 = 0x1048, ///< TLP controller configuration 0 + + N_PLX_PECS_REGS // dummy +}; + + +// Bit masks used with the PLX_PECS_EECTL register. +// See chap 18.10 of the manual +#define PLX_PECS_EECTL_WRITE_DATA_SHIFT 0 +#define PLX_PECS_EECTL_READ_DATA_SHIFT 8 +#define PLX_PECS_EECTL_WRITE_START ( 1UL << 16 ) +#define PLX_PECS_EECTL_READ_START ( 1UL << 17 ) +#define PLX_PECS_EECTL_CS_ENB ( 1UL << 18 ) +#define PLX_PECS_EECTL_BUSY ( 1UL << 19 ) +#define PLX_PECS_EECTL_VALID ( 1UL << 20 ) +#define PLX_PECS_EECTL_PRESENT ( 1UL << 21 ) +#define PLX_PECS_EECTL_CS_ACTIVE ( 1UL << 22 ) +#define PLX_PECS_EECTL_RELOAD ( 1UL << 31 ) + +// Bit masks used with the PLX_PECS_EECLKFREQ register. +#define PLX_PECS_EECLKFREQ_8_3_MHZ 0x02 // 3 LSBs + +// Bit masks used with the PLX_PECS_GPIOCTL register. +#define PLX_PECS_GPIOCTL_GPIO3_DATA ( 1UL << 3 ) + + + +/** + * @brief Local Configuration Space (LCS) registers + * + * These registers are accessed with different addresses from + * local or PCI, and these addresses are to be used from PCI. + * See chapter 20 of the PLX8311 manual. + */ +enum PLX_LCS_REGS_PCI +{ + PLX_LCS_INTCSR = 0x68, ///< Interrupt control / status + PLX_LCS_CNTRL = 0x6C, ///< 0xEC from local + + N_PLX_LCS_REGS_PCI // dummy +}; -/* End of header body */ +// Bit masks used with the PLX_LCS_CNTRL register. +#define PLX_LCS_CNTRL_USERO ( 1UL << 16 ) +#define PLX_LCS_CNTRL_USERI ( 1UL << 17 ) -#undef _ext +// The following bits must be set in the INTCSR register +// to let the local microcontroller be able to generate +// interrupts on the PCI bus via the chip's LINTi# line: +#define PLX_LCS_INTCSR_INT_ENB ( ( 1UL << 11 ) /* Local Interrupt Input Enable */ \ + | ( 1UL << 8 ) /* Internal PCI Wire Interrupt Enable */ \ + ) + +// The bit below signals if an LINTi# interrupt is active: +#define PLX_LCS_INTCSR_INT_FLAG ( 1UL << 15 ) /* Local Interrupt Input Active */ -/* function prototypes: */ -#ifdef __cplusplus -extern "C" { -#endif /* ----- function prototypes begin ----- */ @@ -72,5 +173,8 @@ extern "C" { } #endif +/* End of header body */ + +#undef _ext #endif /* _PLXDEFS_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/ptp_util.h b/src/external/bsd/meinberg/dist/mbglib/common/ptp_util.h new file mode 100755 index 0000000..0b4c099 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/ptp_util.h @@ -0,0 +1,190 @@ + +/************************************************************************** + * + * $Id: ptp_util.h 1.6 2017/05/10 15:26:10 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for ptp_util.c. + * + * ----------------------------------------------------------------------- + * $Log: ptp_util.h $ + * Revision 1.6 2017/05/10 15:26:10 martin + * Tiny cleanup. + * Revision 1.5 2017/04/25 12:54:21 gregoire.diehl + * Merge changes from 1.3.1.7 & 1.4 + * Revision 1.4 2016/11/10 09:05:26Z martin + * Support for PTP Time Monitor role added by udo. + * Support for NTP modes added by daniel. + * Updated some comments. + * Revision 1.3 2013/09/12 11:05:44 martin + * Added inline function get_supp_ptp_role_mask(). + * Revision 1.2 2013/08/06 12:08:06 udo + * new ptp_clock_id_from_str() + * Revision 1.1 2011/11/14 16:03:39 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _PTP_UTIL_H +#define _PTP_UTIL_H + + +/* Other headers to be included */ +#include <stdio.h> +#include <lan_util.h> +#include <gpsdefs.h> + + +#ifdef _PTP_UTIL + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#if defined( _USE_PACK ) + #pragma pack( 1 ) // set byte alignment + #define _USING_BYTE_ALIGNMENT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Derive a "supported PTP roles" bit mask from ::PTP_CFG_INFO::supp_flags + * + * The relevant bits used with ::PTP_CFG_INFO::supp_flags have not been + * defined sequentially, so we need to test them individually to put a + * supported roles bit mask together. + * + * @note Originally, all devices supported the multicast slave role, so + * there was no extra flag to indicate this. However, some newer devices + * may not support the multicast slave role, so two new flags have been + * introduced to cope with this:<br> + * If ::PTP_CFG_SUPP_MCAST_SLAVE_FLAG is set then a different flag + * ::PTP_CFG_CAN_BE_MULTICAST_SLAVE needs to be checked to tell if + * the multicast slave role is supported, or not.<br> + * If ::PTP_CFG_SUPP_MCAST_SLAVE_FLAG is not set then the device + * definitely supports the multicast slave role. + * + * @param flags bit mask from ::PTP_CFG_INFO::supp_flags, see @ref PTP_CFG_FLAG_MASKS + * + * @return bit mask of supported PTP roles, see ::PTP_ROLE_MASKS + */ +static __mbg_inline +uint32_t get_supp_ptp_role_mask( uint32_t flags ) +{ + uint32_t role_mask = 0; + + if ( flags & PTP_CFG_MSK_SUPP_MCAST_SLAVE_FLAG ) + { + // multicast slave role is only supported + // if a different flag is also set + if ( flags & PTP_CFG_MSK_CAN_BE_MULTICAST_SLAVE ) + role_mask |= PTP_ROLE_MSK_MULTICAST_SLAVE; + } + else // multicast slave role is definitely supported + role_mask |= PTP_ROLE_MSK_MULTICAST_SLAVE; + + if ( flags & PTP_CFG_MSK_CAN_BE_UNICAST_SLAVE ) + role_mask |= PTP_ROLE_MSK_UNICAST_SLAVE; + + if ( flags & PTP_CFG_MSK_CAN_BE_MULTICAST_MASTER ) + role_mask |= PTP_ROLE_MSK_MULTICAST_MASTER; + + if ( flags & PTP_CFG_MSK_CAN_BE_UNICAST_MASTER ) + role_mask |= PTP_ROLE_MSK_UNICAST_MASTER; + + if ( flags & PTP_CFG_MSK_CAN_BE_MULTICAST_AUTO ) + role_mask |= PTP_ROLE_MSK_MULTICAST_AUTO; + + if ( flags & PTP_CFG_MSK_CAN_BE_BOTH_MASTER ) + role_mask |= PTP_ROLE_MSK_BOTH_MASTER; + + if ( flags & PTP_CFG_MSK_NTP_HW_TS_MASTER ) + role_mask |= PTP_ROLE_MSK_NTP_SERVER; + + if ( flags & PTP_CFG_MSK_NTP_HW_TS_SLAVE ) + role_mask |= PTP_ROLE_MSK_NTP_CLIENT; + + if ( flags & PTP_CFG_MSK_CAN_BE_TIME_MONITOR ) + role_mask |= PTP_ROLE_MSK_TIME_MONITOR; + + if ( flags & PTP_CFG_MSK_CAN_BE_V1_MASTER ) + role_mask |= PTP_ROLE_MSK_V1_MASTER; + + if ( flags & PTP_CFG_MSK_CAN_BE_V1_SLAVE ) + role_mask |= PTP_ROLE_MSK_V1_SLAVE; + + return role_mask; + +} // get_supp_ptp_role_mask + + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + /** + * @brief Get the MAC addr from a PTP clock ID + * + * The clock ID is usually the MAC ID with 2 octets + * 0xFF and 0xFE inserted in the middle. + * + * @param p_mac_addr The MAC ID to be filled up + * @param p_clock_id The PTP clock ID + */ + void mac_from_ptp_clock_id( MBG_MAC_ADDR *p_mac_addr, const PTP_CLOCK_ID *p_clock_id ) ; + + /** + * @brief Get the PTP clock ID from the MAC addr + * + * The clock ID is usually the MAC ID with 2 octets + * 0xFF and 0xFE inserted in the middle. + * + * @param p_clock_id The PTP clock ID + * @param p_mac_addr The MAC ID to be filled up + */ + void ptp_clock_id_from_mac( PTP_CLOCK_ID *p_clock_id, const MBG_MAC_ADDR *p_mac_addr ) ; + + /** + * @brief Get the PTP clock ID from a string + * + * The clock ID is usually the MAC ID with 2 octets + * 0xFF and 0xFE inserted in the middle. + * + * @param p_clock_id The PTP clock ID + * @param p_str The UUID as string with format e.g. 0050C2FFFED287DE + */ + void ptp_clock_id_from_str( PTP_CLOCK_ID *p_clock_id, const char *p_str ) ; + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +#if defined( _USING_BYTE_ALIGNMENT ) + #pragma pack() // set default alignment + #undef _USING_BYTE_ALIGNMENT +#endif + +/* End of header body */ + + +#undef _ext +#undef _DO_INIT + +#endif /* _PTP_UTIL_H */ + diff --git a/src/external/bsd/meinberg/dist/mbglib/common/rsrc.h b/src/external/bsd/meinberg/dist/mbglib/common/rsrc.h index 744e443..cc97d76 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/rsrc.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/rsrc.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: rsrc.h 1.4.1.1 2006/09/19 14:52:02 martin TEST $ + * $Id: rsrc.h 1.6 2017/05/10 15:26:10 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,8 +11,10 @@ * * ----------------------------------------------------------------------- * $Log: rsrc.h $ - * Revision 1.4.1.1 2006/09/19 14:52:02 martin - * Preliminary support for *BSD. + * Revision 1.6 2017/05/10 15:26:10 martin + * Tiny cleanup. + * Revision 1.5 2012/10/12 11:25:14 martin + * Support *BSD. * Revision 1.4 2001/02/28 15:45:11 MARTIN * Modified preprocessor syntax. * Revision 1.3 2001/02/05 10:22:24 MARTIN @@ -51,6 +53,10 @@ /* Start of header body */ +#ifdef __cplusplus +extern "C" { +#endif + enum { RSRC_BUS_ISA, @@ -60,17 +66,6 @@ enum }; -/* End of header body */ - -#undef _ext - - -/* function prototypes: */ - -#ifdef __cplusplus -extern "C" { -#endif - /* ----- function prototypes begin ----- */ /* This section was generated automatically */ @@ -85,5 +80,9 @@ extern "C" { #endif +/* End of header body */ + +#undef _ext + #endif /* _RSRC_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/str_util.c b/src/external/bsd/meinberg/dist/mbglib/common/str_util.c new file mode 100755 index 0000000..c3c89cb --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/str_util.c @@ -0,0 +1,449 @@ + +/************************************************************************** + * + * $Id: str_util.c 1.3 2016/10/24 08:10:04 thomas-b REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Meinberg Library module providing portable, safe string functions. + * + * ----------------------------------------------------------------------- + * $Log: str_util.c $ + * Revision 1.3 2016/10/24 08:10:04 thomas-b + * Fixed counter var check in mbg_memcpy_reversed + * Revision 1.2 2016/08/05 12:31:04 martin + * New functions mbg_memcpy() and mbg_memcpy_reversed(). + * Moved string trim functions from cfg_util module here. + * Fixed some compiler warnings. + * Revision 1.1 2015/08/25 15:57:21 martin + * Initial revision. + * + **************************************************************************/ + +#define _STR_UTIL + #include <str_util.h> +#undef _STR_UTIL + +#include <stdio.h> +#include <string.h> + + +#if defined( MBG_TGT_WIN32 ) && !defined( MBG_TGT_CVI ) + #define mbg_vsnprintf _vsnprintf +#else + #define mbg_vsnprintf vsnprintf +#endif + + +#if defined( MBG_TGT_DOS ) + +static /*HDR*/ +// Under DOS we use the Borland C/C++ v3.1 compiler by default, which +// doesn't provide a vsnprintf() function, so we use a simple replacement +// here. Since we share most of the source code between several target +// systems we assume that if it our code works properly for other targets +// which really provide a vsnprintf() function then it also works properly +// under DOS. ;-) +int vsnprintf( char *s, size_t max_len, const char *fmt, va_list arg_list ) +{ + (void) max_len; // quiet compiler warning "not used" + + return vsprintf( s, fmt, arg_list ); + +} // vsnprintf + +#endif + + + +/*HDR*/ +/** + * @brief A portable, safe implementation of vsnprintf() + * + * Unfortunately the behaviour of vsnprintf() and thus snprintf() + * differs in detail across various build environments and run time + * libraries. + * + * If the output exceeds the buffer size and thus is truncated then:<br> + * + * - Under Windows a negative value is returned and eventually *no* + * terminating 0 is written to the output buffer, so the output string + * may not be terminated properly. + * + * - Some versions of glibc return the number of bytes that *would* + * have been written to the buffer *if* the buffer would have been + * large enough, instead of the true number of characters that have + * been written to the buffer. + * + * So subsequent calls like + * + * n = snprintf( s, max_len, ... ); + * n += snprintf( &s[n], max_len - n, ... ); + * + * may always work properly, or fail with buffer overruns or stack + * corruption depending on the build environment. + * This wrapper function takes care that strings are always terminated + * properly, and that the returned value always matches the number of + * characters really written to the string buffer, excluding the + * terminating 0 + * + * @note The "size_t" type parameter used to specify the buffer size + * can be larger (e.g. "unsigned long") than the "int" type returned + * by mostly all functions of the printf() family. So if a very large + * buffer is specified, and a large number of characters (more than + * MAXINT) are written to that buffer then how can an "int" type + * return the large number of characters written to the buffer? + * We also try to workaround this here. + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] fmt Format string according to subsequent parameters + * @param[in] ap Variable argument list in va_list format + * + * @return Number of characters written to the output buffer, except the terminating 0 + * + * @see ::snprintf_safe + * @see ::strncpy_safe + * @see ::sn_cpy_str_safe + * @see ::sn_cpy_char_safe + */ +size_t __attribute__( ( format( printf, 3, 0 ) ) ) +vsnprintf_safe( char *s, size_t max_len, const char *fmt, va_list ap ) +{ + if ( s == NULL || max_len == 0 ) + return 0; // nothing to do anyway + + + mbg_vsnprintf( s, max_len, fmt, ap ); + + // Force proper worst-case termination of the output string. + s[max_len - 1] = 0; + + // The return type of strlen() is usually size_t, so + // we can safely return the true length of the string + // written to the buffer. + return strlen( s ); + +} // vsnprintf_safe + + + +/*HDR*/ +/** + * @brief A portable, safe implementation of snprintf() + * + * For a detailed description see ::vsnprintf_safe + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] fmt Format string according to subsequent parameters + * @param[in] ... Variable argument list according to the format string + * + * @return Number of characters written to the output buffer, except the terminating 0 + * + * @see ::vsnprintf_safe + * @see ::strncpy_safe + * @see ::sn_cpy_str_safe + * @see ::sn_cpy_char_safe + */ +size_t __attribute__( ( format( printf, 3, 4 ) ) ) +snprintf_safe( char *s, size_t max_len, const char * fmt, ... ) +{ + va_list ap; + size_t len; + + va_start( ap, fmt ); + + len = vsnprintf_safe( s, max_len, fmt, ap ); + + va_end( ap ); + + return len; + +} // snprintf_safe + + + +static __mbg_inline +/* (explicitly excluded from doxygen) + * @brief A portable, safe implementation of a copy function + * + * This is the basic function used to implemment ::strncpy_safe and + * ::sn_cpy_safe. This function takes care that the copied string + * is always terminated by 0, but any remaining buffer space + * is *not* filled up with '0' characters. + * + * @param[out] dst Pointer to the output buffer + * @param[in] src Pointer to the input buffer + * @param[in] n Number of characters to copy at most + * @param[in,out] p_i Pointer to a counter variable + * + * @see ::vsnprintf_safe + * @see ::snprintf_safe + * @see ::strncpy_safe + * @see ::sn_cpy_str_safe + * @see ::sn_cpy_char_safe + */ +void do_str_copy_safe( char *dst, const char *src, size_t n, size_t *p_i ) +{ + *p_i = 0; + + if ( n > 0 ) + { + for (;;) + { + *dst = *src; + + if ( *dst == 0 ) + break; // just copied the terminating 0, done + + if ( --n == 0 ) // no more space left in buffer + { + *dst = 0; // force terminating 0 + break; + } + + (*p_i)++; // count normal characters + src++; + dst++; + } + } + +} // do_str_copy_safe + + + +/*HDR*/ +/** + * @brief A portable, safe implementation of strncpy() + * + * In the original implementation of strncpy(), if the length of the + * string to be copied into the destination buffer exceeds the specified + * buffer length then the string in the output buffer is not 0-terminated. + * + * Our implementation always forces a proper termination by 0, but unlike + * the original implementation of strncpy() it does *not* fill the whole + * remaining buffer space with '0' characters. + * + * @param[out] dst Pointer to the output buffer + * @param[in] src Pointer to the input buffer + * @param[in] max_len Size of the output buffer for 0-terminated string + * + * @return Pointer to the destination buffer + * + * @see ::vsnprintf_safe + * @see ::snprintf_safe + * @see ::sn_cpy_str_safe + * @see ::sn_cpy_char_safe + */ +char *strncpy_safe( char *dst, const char *src, size_t max_len ) +{ + size_t i = 0; + + do_str_copy_safe( dst, src, max_len, &i ); + + return dst; + +} // strncpy_safe + + + +/*HDR*/ +/** + * @brief A function to copy a string safely, returning the number of characters copied + * + * This basically works like ::strncpy_safe but instead of a pointer to + * the destination buffer it returns the number of characters copied + * to the destination buffer. + * + * @param[out] dst Pointer to the output buffer + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] src Pointer to the input buffer + * + * @return Number of characters copied to the destination buffer + * + * @see ::vsnprintf_safe + * @see ::snprintf_safe + * @see ::strncpy_safe + * @see ::sn_cpy_char_safe + */ +size_t sn_cpy_str_safe( char *dst, size_t max_len, const char *src ) +{ + size_t i = 0; + + do_str_copy_safe( dst, src, max_len, &i ); + + return i; + +} // sn_cpy_str_safe + + + +/*HDR*/ +/** + * @brief A function to copy a character safely to a string buffer + * + * This basically works like ::sn_cpy_str_safe but expects a character + * to be copied to the destination buffer. Appends a terminating 0 to + * the string buffer and returns the number of characters copied to + * the destination buffer, usually 0 or 1. + * + * @param[out] dst Pointer to the output buffer + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] c Character to be copied to the destination buffer + * + * @return Number of characters copied to the destination buffer, without the terminating 0 + * + * @see ::vsnprintf_safe + * @see ::snprintf_safe + * @see ::strncpy_safe + * @see ::sn_cpy_str_safe + */ +size_t sn_cpy_char_safe( char *dst, size_t max_len, char c ) +{ + size_t i = 0; + char tmp_str[2]; + + tmp_str[0] = c; + tmp_str[1] = 0; + + do_str_copy_safe( dst, tmp_str, max_len, &i ); + + return i; + +} // sn_cpy_char_safe + + + +/*HDR*/ +/** + * @brief Trim whitespace at the end of a string + * + * @param[in,out] s The string to be trimmed + */ +void trim_trailing_whitespace( char *s ) +{ + char *cp; + + // set all trailing spaces to 0 + for ( cp = &s[strlen( s )]; cp > s; ) + { + --cp; + + if ( *cp >= ' ' ) + break; + + *cp = 0; + } + +} // trim_trailing_whitespace + + + +/*HDR*/ +/** + * @brief Trim whitespace at the beginning of a string + * + * @param[in,out] s The string to be trimmed + */ +void trim_leading_whitespace( char *s ) +{ + char *srcp; + char *dstp; + + // Search the first non-space character. + for ( srcp = s; *srcp; srcp++ ) + if ( *srcp > ' ' ) + break; + + // If there are leading spaces then srcp now + // points behind the beginning of the string, + // otherwise there's nothing to do. + if ( srcp > s ) + { + // Copy the remaining string. + dstp = s; + + while ( *srcp ) + *dstp++ = *srcp++; + + *dstp = 0; + } + +} // trim_leading_whitespace + + + +/*HDR*/ +/** + * @brief Trim both leading and trailing whitespace from a string + * + * @param[in,out] s The string to be trimmed + */ +void trim_whitespace( char *s ) +{ + trim_trailing_whitespace( s ); + trim_leading_whitespace( s ); + +} // trim_whitespace + + + +/*HDR*/ +/** + * @brief Copy array of bytes starting at beginning of buffer + * + * Can be used if the destination address is in the same buffer + * in front of the source address. Even though you would expect + * that memcpy() would also work for this properly, we have seen + * cases where it didn't, and only memmove() worked correctly. + * Anyway, we try to avoid the overhead of memmove(). + * + * @param[out] dst Destination address behind the source address + * @param[in] src Source address + * @param[in] n_bytes Number of bytes to copy + * + * @see ::mbg_memcpy_reversed + */ +void mbg_memcpy( void *dst, const void *src, size_t n_bytes ) +{ + uint8_t *dstp = (uint8_t *) dst; + uint8_t *srcp = (uint8_t *) src; + + while ( n_bytes-- ) + *dstp++ = *srcp++; + +} // mbg_memcpy + + + +/*HDR*/ +/** + * @brief Copy an array of bytes in reversed order, starting at end of buffer + * + * Can be used if the destination address is in the same buffer + * behind the source address, so the source address would be + * overwritten by a normal memcpy(). + * + * @param[out] dst Destination address behind the source address + * @param[in] src Source address + * @param[in] n_bytes Number of bytes to copy + * + * @see ::mbg_memcpy + */ +void mbg_memcpy_reversed( void *dst, const void *src, size_t n_bytes ) +{ + if ( n_bytes ) // just to be sure it isn't 0 + { + uint8_t *dstp = ( (uint8_t *) dst ) + n_bytes; + uint8_t *srcp = ( (uint8_t *) src ) + n_bytes; + + while ( n_bytes-- ) + *(--dstp) = *(--srcp); + } + +} // mbg_memcpy_reversed + + + diff --git a/src/external/bsd/meinberg/dist/mbglib/common/str_util.h b/src/external/bsd/meinberg/dist/mbglib/common/str_util.h new file mode 100755 index 0000000..3b49318 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/str_util.h @@ -0,0 +1,269 @@ + +/************************************************************************** + * + * $Id: str_util.h 1.4 2017/05/10 15:26:10 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for str_util.c + * + * ----------------------------------------------------------------------- + * $Log: str_util.h $ + * Revision 1.4 2017/05/10 15:26:10 martin + * Tiny cleanup. + * Revision 1.3 2016/12/14 16:22:24 martin + * Added macro _sn_cpy_str_safe() to simplify calls. + * Revision 1.2 2016/08/05 12:33:17 martin + * Moved string trim functions from cfg_util module here. + * Added variable str_not_avail. + * Fixed some spelling. + * Updated function prototypes. + * Revision 1.1 2015/08/25 15:57:43 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _STR_UTIL_H +#define _STR_UTIL_H + +/* Other headers to be included */ + +#include <words.h> // implicitly includes mbg_tgt.h for non-firmware projects + +#include <stdlib.h> +#include <stdarg.h> + + +#ifdef _STR_UTIL + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + + +_ext const char *str_not_avail +#ifdef _DO_INIT + = "N/A" +#endif +; + +#define _sn_cpy_str_safe( _dst, _src ) sn_cpy_str_safe( _dst, sizeof( _dst ), _src ) + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + /** + * @brief A portable, safe implementation of vsnprintf() + * + * Unfortunately the behaviour of vsnprintf() and thus snprintf() + * differs in detail across various build environments and run time + * libraries. + * + * If the output exceeds the buffer size and thus is truncated then:<br> + * + * - Under Windows a negative value is returned and eventually *no* + * terminating 0 is written to the output buffer, so the output string + * may not be terminated properly. + * + * - Some versions of glibc return the number of bytes that *would* + * have been written to the buffer *if* the buffer would have been + * large enough, instead of the true number of characters that have + * been written to the buffer. + * + * So subsequent calls like + * + * n = snprintf( s, max_len, ... ); + * n += snprintf( &s[n], max_len - n, ... ); + * + * may always work properly, or fail with buffer overruns or stack + * corruption depending on the build environment. + * This wrapper function takes care that strings are always terminated + * properly, and that the returned value always matches the number of + * characters really written to the string buffer, excluding the + * terminating 0 + * + * @note The "size_t" type parameter used to specify the buffer size + * can be larger (e.g. "unsigned long") than the "int" type returned + * by mostly all functions of the printf() family. So if a very large + * buffer is specified, and a large number of characters (more than + * MAXINT) are written to that buffer then how can an "int" type + * return the large number of characters written to the buffer? + * We also try to workaround this here. + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] fmt Format string according to subsequent parameters + * @param[in] ap Variable argument list in va_list format + * + * @return Number of characters written to the output buffer, except the terminating 0 + * + * @see ::snprintf_safe + * @see ::strncpy_safe + * @see ::sn_cpy_str_safe + * @see ::sn_cpy_char_safe + */ + size_t __attribute__( ( format( printf, 3, 0 ) ) ) vsnprintf_safe( char *s, size_t max_len, const char *fmt, va_list ap ) ; + + /** + * @brief A portable, safe implementation of snprintf() + * + * For a detailed description see ::vsnprintf_safe + * + * @param[out] s The string buffer to be filled + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] fmt Format string according to subsequent parameters + * @param[in] ... Variable argument list according to the format string + * + * @return Number of characters written to the output buffer, except the terminating 0 + * + * @see ::vsnprintf_safe + * @see ::strncpy_safe + * @see ::sn_cpy_str_safe + * @see ::sn_cpy_char_safe + */ + size_t __attribute__( ( format( printf, 3, 4 ) ) ) snprintf_safe( char *s, size_t max_len, const char * fmt, ... ) ; + + /** + * @brief A portable, safe implementation of strncpy() + * + * In the original implementation of strncpy(), if the length of the + * string to be copied into the destination buffer exceeds the specified + * buffer length then the string in the output buffer is not 0-terminated. + * + * Our implementation always forces a proper termination by 0, but unlike + * the original implementation of strncpy() it does *not* fill the whole + * remaining buffer space with '0' characters. + * + * @param[out] dst Pointer to the output buffer + * @param[in] src Pointer to the input buffer + * @param[in] max_len Size of the output buffer for 0-terminated string + * + * @return Pointer to the destination buffer + * + * @see ::vsnprintf_safe + * @see ::snprintf_safe + * @see ::sn_cpy_str_safe + * @see ::sn_cpy_char_safe + */ + char *strncpy_safe( char *dst, const char *src, size_t max_len ) ; + + /** + * @brief A function to copy a string safely, returning the number of characters copied + * + * This basically works like ::strncpy_safe but instead of a pointer to + * the destination buffer it returns the number of characters copied + * to the destination buffer. + * + * @param[out] dst Pointer to the output buffer + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] src Pointer to the input buffer + * + * @return Number of characters copied to the destination buffer + * + * @see ::vsnprintf_safe + * @see ::snprintf_safe + * @see ::strncpy_safe + * @see ::sn_cpy_char_safe + */ + size_t sn_cpy_str_safe( char *dst, size_t max_len, const char *src ) ; + + /** + * @brief A function to copy a character safely to a string buffer + * + * This basically works like ::sn_cpy_str_safe but expects a character + * to be copied to the destination buffer. Appends a terminating 0 to + * the string buffer and returns the number of characters copied to + * the destination buffer, usually 0 or 1. + * + * @param[out] dst Pointer to the output buffer + * @param[in] max_len Size of the output buffer for 0-terminated string + * @param[in] c Character to be copied to the destination buffer + * + * @return Number of characters copied to the destination buffer, without the terminating 0 + * + * @see ::vsnprintf_safe + * @see ::snprintf_safe + * @see ::strncpy_safe + * @see ::sn_cpy_str_safe + */ + size_t sn_cpy_char_safe( char *dst, size_t max_len, char c ) ; + + /** + * @brief Trim whitespace at the end of a string + * + * @param[in,out] s The string to be trimmed + */ + void trim_trailing_whitespace( char *s ) ; + + /** + * @brief Trim whitespace at the beginning of a string + * + * @param[in,out] s The string to be trimmed + */ + void trim_leading_whitespace( char *s ) ; + + /** + * @brief Trim both leading and trailing whitespace from a string + * + * @param[in,out] s The string to be trimmed + */ + void trim_whitespace( char *s ) ; + + /** + * @brief Copy array of bytes starting at beginning of buffer + * + * Can be used if the destination address is in the same buffer + * in front of the source address. Even though you would expect + * that memcpy() would also work for this properly, we have seen + * cases where it didn't, and only memmove() worked correctly. + * Anyway, we try to avoid the overhead of memmove(). + * + * @param[out] dst Destination address behind the source address + * @param[in] src Source address + * @param[in] n_bytes Number of bytes to copy + * + * @see ::mbg_memcpy_reversed + */ + void mbg_memcpy( void *dst, const void *src, size_t n_bytes ) ; + + /** + * @brief Copy an array of bytes in reversed order, starting at end of buffer + * + * Can be used if the destination address is in the same buffer + * behind the source address, so the source address would be + * overwritten by a normal memcpy(). + * + * @param[out] dst Destination address behind the source address + * @param[in] src Source address + * @param[in] n_bytes Number of bytes to copy + * + * @see ::mbg_memcpy + */ + void mbg_memcpy_reversed( void *dst, const void *src, size_t n_bytes ) ; + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _STR_UTIL_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/timeutil.c b/src/external/bsd/meinberg/dist/mbglib/common/timeutil.c new file mode 100755 index 0000000..be65f18 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/timeutil.c @@ -0,0 +1,164 @@ + +/************************************************************************** + * + * $Id: timeutil.c 1.2 2017/07/05 07:10:48 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Meinberg Library module for safe time conversion routines. + * + * ----------------------------------------------------------------------- + * $Log: timeutil.c $ + * Revision 1.2 2017/07/05 07:10:48 martin + * Added mbg_clock_gettime(), mbg_clock_settime(), + * and check_precise_time_api() for Windows. + * Revision 1.1 2016/07/15 14:14:19Z martin + * Initial revision + * + **************************************************************************/ + +#define _TIMEUTIL + #include <timeutil.h> +#undef _TIMEUTIL + +#include <mbgtime.h> +#include <str_util.h> + +#if defined( MBG_TGT_WIN32 ) + #include <mbgerror.h> // NSECS_PER_SEC + #include <stdio.h> +#endif + + + +/*HDR*/ +size_t snprint_gmtime_error( char *s, size_t max_len, int mbg_errno, time_t t, const char *calling_fnc ) +{ + size_t n = snprintf_safe( s, max_len, "gmtime() call failed" ); + + if ( calling_fnc ) + n += snprintf_safe( &s[n], max_len - n, " in %s", calling_fnc ); + + #if defined( _MSC_VER ) && ( _MSC_VER < 1500 ) + //### TODO E.g. in VC6 time_t is only 32 bit anyway. + n += snprintf_safe( &s[n], max_len - n, " for time_t %lu: %s", + (unsigned long) t, mbg_strerror( mbg_errno ) ); + #else + n += snprintf_safe( &s[n], max_len - n, " for time_t %llu: %s", + (unsigned long long) t, mbg_strerror( mbg_errno ) ); + #endif + + return n; + +} // snprint_gmtime_error + + + +#if defined( MBG_TGT_WIN32 ) + +typedef int clockid_t; +#define clockid_t clockid_t + +#define CLOCK_REALTIME ( (clockid_t) 0 ) + +/*HDR*/ +int mbg_clock_gettime( clockid_t clock_id, struct timespec *tp ) +{ + if ( clock_id == CLOCK_REALTIME ) + { + #if defined( TIME_UTC ) // C11 / VS2015+ + int rc = timespec_get( tp, TIME_UTC ); // TODO Check this code + return ( rc == 0 ) ? -1 : 0 // rc == 0 means error + #else + #define EPOCH_HNS 116444736000000000i64 + FILETIME ft; + unsigned __int64 tmp; + gstaft_fnc( &ft ); + tmp = ( (__int64) ft.dwHighDateTime << 32 ) | ft.dwLowDateTime; + tmp -= EPOCH_HNS; // convert to Unix epoch + tmp *= 100; // convert to nanoseconds + tp->tv_sec = ( tmp / NSECS_PER_SEC ); + tp->tv_nsec = ( tmp % NSECS_PER_SEC ); + return 0; + #endif + } + else + return -1; // TODO this is e.g. in case of CLOCK_MONOTONIC, we could use QPC then. + +} // mbg_clock_gettime + + + +/*HDR*/ +int mbg_clock_settime( clockid_t clock_id, const struct timespec *tp ) +{ + if ( clock_id == CLOCK_REALTIME ) + { +#if 0 // ### TODO FIXME This needs to be implemented. + #if defined( TIME_UTC ) // C11 / VS2015+ + int rc = timespec_get( res, TIME_UTC ); // TODO Check this code + return ( rc == 0 ) ? -1 : 0 // rc == 0 means error + #else + #define EPOCH_HNS 116444736000000000i64 + FILETIME ft; + unsigned __int64 tmp; + gstaft_fnc( &ft ); + tmp = ( (__int64) ft.dwHighDateTime << 32 ) | ft.dwLowDateTime; + tmp -= EPOCH_HNS; // convert to Unix epoch + tmp *= 100; // convert to nanoseconds + res->tv_sec = ( tmp / NSECS_PER_SEC ); + res->tv_nsec = ( tmp % NSECS_PER_SEC ); + return 0; + #endif +#endif + + return 0; // FIXME this is actually not true + } + else + return -1; // TODO this is e.g. in case of CLOCK_MONOTONIC, we could use QPC then. + +} // mbg_clock_settime + + + +bool force_legacy_gstaft; + + +/*HDR*/ +void check_precise_time_api( void ) +{ + const char *info =""; + GSTAFT_FNC tmp_fnc; + HINSTANCE h = LoadLibrary( "kernel32.dll" ); + + if ( h == NULL ) + { + info = "Precise system time may not be supported; failed to get handle for kernel32.dll."; + goto out; + } + + tmp_fnc = (GSTAFT_FNC) GetProcAddress( h, "GetSystemTimePreciseAsFileTime" ); + + if ( tmp_fnc == NULL ) + { + info = "Precise system time NOT supported"; + goto out; + } + + if ( force_legacy_gstaft ) + { + info = "Precise system time is supported, but legacy function used by request"; + goto out; + } + + gstaft_fnc = tmp_fnc; + info = "Precise system time is supported and used"; + +out: + printf( "%s\n", info ); + +} // check_precise_time_api + +#endif + diff --git a/src/external/bsd/meinberg/dist/mbglib/common/timeutil.h b/src/external/bsd/meinberg/dist/mbglib/common/timeutil.h new file mode 100755 index 0000000..233c174 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/timeutil.h @@ -0,0 +1,129 @@ + +/************************************************************************** + * + * $Id: timeutil.h 1.3 2017/07/05 07:15:00 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for timeutil.c + * + * ----------------------------------------------------------------------- + * $Log: timeutil.h $ + * Revision 1.3 2017/07/05 07:15:00 martin + * Provide basic support for clock_gettime()/clock_settime() + * compatible functions for Windows. + * Updated function prototypes. + * Revision 1.1 2016/07/15 14:14:20Z martin + * Initial revision + * + **************************************************************************/ + +#ifndef _TIMEUTIL_H +#define _TIMEUTIL_H + +/* Other headers to be included */ + +#include <words.h> // implicitly includes mbg_tgt.h for non-firmware projects +#include <mbgerror.h> + +#include <time.h> +#include <stddef.h> + + +#ifdef _TIMEUTIL + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined( MBG_TGT_WIN32 ) || defined( MBG_TGT_DOS ) + +typedef int clockid_t; +#define clockid_t clockid_t + +#define CLOCK_REALTIME ( (clockid_t) 0 ) + +#endif + + + +#if defined( MBG_TGT_WIN32 ) + +#define __const__ const + +/** + * @brief A pointer to a function returning the system time as FILETIME + * + * This can be e.g. the standard Windows API call GetSystemTimeAsFileTime() + * or the GetSystemTimeAsPreciseFileTime() API call introduced with Windows 8. + */ +typedef VOID (WINAPI *GSTAFT_FNC)(LPFILETIME lpSystemTimeAsFileTime); + +_ext GSTAFT_FNC gstaft_fnc +#ifdef _DO_INIT + = GetSystemTimeAsFileTime +#endif +; + +#endif + + +static __mbg_inline +time_t cvt_to_time_t( time_t t ) +{ + // Eventually we can do some epoch check here. + return (time_t) t; + +} // cvt_to_time_t + + + +static __mbg_inline +int mbg_gmtime( struct tm *p_tm, const time_t *p_time ) +{ + struct tm *p_tm_tmp = gmtime( p_time ); + + if ( p_tm_tmp == NULL ) // conversion failed + return mbg_get_last_error( NULL ); + + *p_tm = *p_tm_tmp; + + return MBG_SUCCESS; + +} // mbg_gmtime + + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + size_t snprint_gmtime_error( char *s, size_t max_len, int mbg_errno, time_t t, const char *calling_fnc ) ; + int mbg_clock_gettime( clockid_t clock_id, struct timespec *tp ) ; + int mbg_clock_settime( clockid_t clock_id, const struct timespec *tp ) ; + void check_precise_time_api( void ) ; + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _TIMEUTIL_H */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/toolutil.c b/src/external/bsd/meinberg/dist/mbglib/common/toolutil.c index 717ed89..5657910 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/toolutil.c +++ b/src/external/bsd/meinberg/dist/mbglib/common/toolutil.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: toolutil.c 1.3.2.6 2011/07/08 11:39:00 martin TRASH $ + * $Id: toolutil.c 1.5 2017/07/05 07:32:38 martin REL_M $ * * Description: * Common functions which can be used with Meinberg command line @@ -9,15 +9,35 @@ * * ----------------------------------------------------------------------- * $Log: toolutil.c $ - * Revision 1.3.2.6 2011/07/08 11:39:00 martin - * Revision 1.3.2.5 2011/07/06 07:55:32 martin - * Revision 1.3.2.4 2011/07/05 15:35:56 martin - * Modified version handling. - * Revision 1.3.2.3 2011/07/05 14:36:47 martin - * New way to maintain version information. - * Revision 1.3.2.2 2011/06/27 13:02:11 martin + * Revision 1.5 2017/07/05 07:32:38 martin + * Renamed mbg_check_devices() to mbg_handle_devices() and added + * a new parameter which controls if only one or all devices + * should be handled if no device has been specified. + * New function mbg_open_device_by_param() which can be used e.g. to + * check if a parameter string is an device file name (MBG_DEV_FN), + * or a device index number, or a device name in MBG_DEV_NAME format, + * and calls the appropriate open function to open the device. + * Made mbg_snprint_hr_tstamp() more versatile by passing a new + * optional UTC offset parameter. + * Account for PCPS_HRT_BIN_FRAC_SCALE renamed to MBG_FRAC32_UNITS_PER_SEC. + * Account for frac_sec_from_bin() obsoleted by bin_frac_32_to_dec_frac(). + * Print device options with OS-specific device names. + * Print special firmware version info, if appropriate. + * Reworked error checking after opening device. + * mbg_print_program_info() which is usually called first after program + * start now makes stdout unbuffered if output is redirected. + * Use safe string functions from str_util.c. + * Support Windows and QNX Neutrino targets. + * Added doxygen comments. + * Revision 1.4 2012/10/15 09:33:48 martin + * Use common way to handle version information. * Open device with O_RDWR flag. - * Revision 1.3.2.1 2010/11/05 12:56:02 martin + * Fixed printing delta timestamps. + * Added function to print PCPS_TIME. + * Added function to show PZF correlation. + * Added function mbg_print_hr_time() which optionally prints hex status. + * Let the display functions for HR timestamps optionally show + * the raw (hex) timestamps. * Revision 1.3 2009/06/19 12:12:14 martin * Added function mbg_print_hr_timestamp(). * Revision 1.2 2009/02/18 09:15:55 martin @@ -34,30 +54,110 @@ #undef _TOOLUTIL // include Meinberg headers +#include <cfg_hlp.h> #include <pcpsutil.h> +#include <timeutil.h> +#include <str_util.h> // include system headers #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> + + + +#if defined( MBG_TGT_WIN32 ) + #define isatty _isatty + #define fileno _fileno +#endif + + + +static __mbg_inline +/** + * @brief Compute the difference between two ::PCPS_TIME_STAMP values + * + * @param[in] p_ts Pointer to the current time stamp. + * @param[in] p_prv_ts Pointer to a previous time stamp. + * + * @return The time difference as double, in microseconds. + */ +double delta_timestamps( const PCPS_TIME_STAMP *p_ts, const PCPS_TIME_STAMP *p_prv_ts ) +{ + uint64_t ts = pcps_time_stamp_to_uint64( p_ts ); + uint64_t prv_ts = pcps_time_stamp_to_uint64( p_prv_ts ); + + // We divide by MBG_FRAC32_UNITS_PER_SEC to get the correct fractions + // and we multiply by 1E6 to get the result in microseconds. + return (double) ( (int64_t) ( ts - prv_ts ) ) * 1E6 / MBG_FRAC32_UNITS_PER_SEC; + +} // delta_timestamps + /*HDR*/ +/** + * @brief Print the program version to a string buffer + * + * @param[out] s Address of a string buffer to be filled. + * @param[in] max_len Size of the string buffer. + * @param[in] micro_version Micro version code for the application. + * + * @return The number of characters printed to the buffer. + */ +int mbg_program_version_str( char *s, size_t max_len, int micro_version ) +{ + int n; + + #if defined( MBG_MICRO_VERSION_CODE_DEV ) + micro_version = MBG_MICRO_VERSION_CODE_DEV; + #endif + + n = snprintf_safe( s, max_len, "%i.%i.%i", MBG_MAJOR_VERSION_CODE, + MBG_MINOR_VERSION_CODE, micro_version ); + + return n; + +} // mbg_program_version_str + + + +/*HDR*/ +/** + * @brief Print some program info to a string buffer + * + * @param[out] s Address of a string buffer to be filled. + * @param[in] max_len Size of the string buffer. + * @param[in] pname The program name. + * @param[in] micro_version Micro version code for the application. + * @param[in] first_year First copyright year. + * @param[in] last_year Last copyright year. + * + * @return The number of characters printed to the buffer. + */ int mbg_program_info_str( char *s, size_t max_len, const char *pname, int micro_version, int first_year, int last_year ) { - int n; + int n = 0; + + #if defined( MBG_MICRO_VERSION_CODE_DEV ) + micro_version = MBG_MICRO_VERSION_CODE_DEV; + #endif if ( last_year == 0 ) last_year = MBG_CURRENT_COPYRIGHT_YEAR; - n = snprintf( s, max_len, "%s v%i.%i.%i Copyright Meinberg ", pname, - MBG_MAJOR_VERSION_CODE, MBG_MINOR_VERSION_CODE, micro_version ); + n += snprintf_safe( &s[n], max_len - n, "%s v", pname ); + + n += mbg_program_version_str( &s[n], max_len - n, micro_version ); + + n += snprintf_safe( &s[n], max_len - n, " copyright Meinberg " ); if ( first_year != last_year ) - n += snprintf( &s[n], max_len - n, "%04i-", first_year ); + n += snprintf_safe( &s[n], max_len - n, "%04i-", first_year ); - n += snprintf( &s[n], max_len - n, "%04i", last_year ); + n += snprintf_safe( &s[n], max_len - n, "%04i", last_year ); return n; @@ -66,12 +166,23 @@ int mbg_program_info_str( char *s, size_t max_len, const char *pname, /*HDR*/ +/** + * @brief Print program info to console + * + * @param[in] pname The program name. + * @param[in] micro_version Micro version code for the application. + * @param[in] first_year First copyright year. + * @param[in] last_year Last copyright year. + */ void mbg_print_program_info( const char *pname, int micro_version, int first_year, int last_year ) { char ws[256]; - #if defined( MBG_MICRO_VERSION_CODE_DEV ) - micro_version = MBG_MICRO_VERSION_CODE_DEV; - #endif + + // If the output has been redirected then make stdout unbuffered, + // e.g. to see the output immediately even though piped through 'tee'. + if ( !isatty( fileno( stdout ) ) ) + setvbuf( stdout, NULL, _IONBF, 0 ); + mbg_program_info_str( ws, sizeof( ws ), pname, micro_version, first_year, last_year ); printf( "\n%s\n\n", ws ); @@ -81,6 +192,12 @@ void mbg_print_program_info( const char *pname, int micro_version, int first_yea /*HDR*/ +/** + * @brief Print usage intro to console + * + * @param[in] pname The program name. + * @param[in] info An optional additional info string, may be NULL. + */ void mbg_print_usage_intro( const char *pname, const char *info ) { printf( "Usage: %s [[opt] [opt] ...] [[dev] [dev] ...]\n\n", pname ); @@ -94,23 +211,19 @@ void mbg_print_usage_intro( const char *pname, const char *info ) /*HDR*/ -void mbg_print_help_options( void ) -{ - puts( "where opt is one of the options:" ); - mbg_print_opt_info( "-? or -h", "print this usage information" ); - -} // mbg_print_help_options - - - -/*HDR*/ +/** + * @brief Print info on a single program option / argument + * + * @param[in] opt_name The option name, optional, may be NULL. + * @param[in] opt_info The option info, optional, may be NULL. + */ void mbg_print_opt_info( const char *opt_name, const char *opt_info ) { if ( opt_name == NULL ) - opt_name = ""; + opt_name = str_empty; if ( opt_info == NULL ) - opt_info = ""; + opt_info = str_empty; printf( " %8s %s\n", opt_name, opt_info ); @@ -119,17 +232,51 @@ void mbg_print_opt_info( const char *opt_name, const char *opt_info ) /*HDR*/ +/** + * @brief Print info on common program help arguments + * + * Lists program parameters causing printing + * of help / usage information. + */ +void mbg_print_help_options( void ) +{ + puts( "where \"opt\" is one of the options:" ); + mbg_print_opt_info( "-? or -h", "print this usage information" ); + +} // mbg_print_help_options + + + +/*HDR*/ +/** + * @brief Print common info on how to specify devices on the command line + */ void mbg_print_device_options( void ) { - puts( "\nwhere dev is the name of a device, e.g.:\n" - " /dev/mbgclock0" - ); + printf( "\n" ); + + puts( "where \"dev\" can be:" ); + + #if MBG_TGT_HAS_DEV_FN + printf( " a device file name, e.g. \"%s\" or \"%s\"\n", + EXAMPLE_DEV_FN_1, EXAMPLE_DEV_FN_2 ); + #endif + printf( " a device type name, with or with S/N appended, e.g. \"%s\" or \"%s\"\n", + EXAMPLE_DEV_NAME_1, EXAMPLE_DEV_NAME_2 ); + + printf( " a device index, e.g. \"0\", \"1\",\"2\", ...\n" ); } // mbg_print_device_options /*HDR*/ +/** + * @brief Print program info and default usage information + * + * @param[in] pname The program name. + * @param[in] prog_info An optional additional info string, may be NULL. + */ void mbg_print_default_usage( const char *pname, const char *prog_info ) { mbg_print_usage_intro( pname, prog_info ); @@ -141,30 +288,21 @@ void mbg_print_default_usage( const char *pname, const char *prog_info ) -// test if ioctl error and print msg if true - -/*HDR*/ -int mbg_ioctl_err( int rc, const char *descr ) -{ - if ( rc < 0 ) - { - fprintf( stderr, "** IOCTL error %i: ", rc ); - perror( descr ); - return -1; - } - - return 0; - -} // mbg_ioctl_err - - - /*HDR*/ +/** + * @brief Retrieve and print some common device info + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] dev_name A device name string to be printed + * @param[out] p_dev Pointer to a device info structure to be read from the device + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ int mbg_get_show_dev_info( MBG_DEV_HANDLE dh, const char *dev_name, PCPS_DEV *p_dev ) { - unsigned long long port; + RECEIVER_INFO ri; + unsigned long port; int irq_num; - int ret_val = 0; int rc; if ( dev_name ) @@ -173,31 +311,39 @@ int mbg_get_show_dev_info( MBG_DEV_HANDLE dh, const char *dev_name, PCPS_DEV *p_ // get information about the device rc = mbg_get_device_info( dh, p_dev ); - if ( mbg_ioctl_err( rc, "mbg_get_device_info" ) ) - goto fail; + if ( mbg_cond_err_msg( rc, "mbg_get_device_info" ) ) + goto out; + + rc = mbg_setup_receiver_info( dh, p_dev, &ri ); + + if ( mbg_cond_err_msg( rc, "mbg_setup_receiver_info" ) ) + goto out; printf( "%s", _pcps_type_name( p_dev ) ); - if ( strlen( _pcps_sernum( p_dev ) ) && + if ( strlen( _pcps_sernum( p_dev ) ) && strcmp( _pcps_sernum( p_dev ), "N/A" ) ) printf( " %s", _pcps_sernum( p_dev ) ); - printf( " (FW %X.%02X", + printf( " (FW %X.%02X", _pcps_fw_rev_num_major( _pcps_fw_rev_num( p_dev ) ), _pcps_fw_rev_num_minor( _pcps_fw_rev_num( p_dev ) ) ); + if ( chk_sw_rev_name( &ri.sw_rev, 0 ) ) + printf( " \"%s\"", ri.sw_rev.name ); + if ( _pcps_has_asic_version( p_dev ) ) { PCI_ASIC_VERSION av; int rc = mbg_get_asic_version( dh, &av ); - if ( rc == MBG_SUCCESS ) + if ( mbg_rc_is_success( rc ) ) { av = _convert_asic_version_number( av ); - printf( ", ASIC %X.%02X", + printf( ", ASIC %u.%02u", _pcps_asic_version_major( av ), _pcps_asic_version_minor( av ) ); @@ -206,148 +352,443 @@ int mbg_get_show_dev_info( MBG_DEV_HANDLE dh, const char *dev_name, PCPS_DEV *p_ printf( ")" ); - port = _pcps_port_base( p_dev, 0 ); + port = _pcps_short_port_base( p_dev, 0 ); if ( port ) - printf( " at port 0x%03LX", port ); + printf( " at port 0x%03lX", port ); - port = _pcps_port_base( p_dev, 1 ); + port = _pcps_short_port_base( p_dev, 1 ); if ( port ) - printf( "/0x%03LX", port ); + printf( "/0x%03lX", port ); irq_num = _pcps_irq_num( p_dev ); if ( irq_num != -1 ) printf( ", irq %i", irq_num ); - goto done; + rc = MBG_SUCCESS; -fail: - ret_val = -1; - -done: - puts( "" ); - return ret_val; +out: + puts( str_empty ); + return rc; } // mbg_get_show_dev_info /*HDR*/ -int mbg_check_device( MBG_DEV_HANDLE dh, const char *dev_name, - int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) ) +/** + * @brief Print device info and take some action on a specific device + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] dev_name A device name string to be printed. + * @param[in] fnc Pointer to a callback function that actually takes the action. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ +int mbg_handle_device( MBG_DEV_HANDLE dh, const char *dev_name, + MBG_DEV_HANDLER_FNC *fnc ) { PCPS_DEV dev; - int ret_val = 0; + int rc; - if ( dh == MBG_INVALID_DEV_HANDLE ) - { - if ( dev_name ) - fprintf( stderr, "%s: ", dev_name ); + rc = mbg_get_show_dev_info( dh, dev_name, &dev ); - perror( "Unable to open device" ); - return -1; - } + if ( mbg_rc_is_success( rc ) ) + if ( fnc ) + rc = fnc( dh, &dev ); + + mbg_close_device( &dh ); - if ( mbg_get_show_dev_info( dh, dev_name, &dev ) < 0 ) - goto fail; + puts( "" ); - if ( fnc ) - ret_val = fnc( dh, &dev ); + return rc; - goto done; +} // mbg_handle_device -fail: - ret_val = -1; -done: - mbg_close_device( &dh ); - puts( "" ); - return ret_val; +/*HDR*/ +/** + * @brief Get the number of devices actually present + * + * Do a real search only when called for the first time. + * + * @return The number of devices currently present. + */ +int chk_get_num_devices( void ) +{ + static int num_devices; + static bool has_searched_devices; + + if ( !has_searched_devices ) + { + num_devices = mbg_find_devices(); + has_searched_devices = true; + } + + return num_devices; -} // mbg_check_device +} // chk_get_num_devices /*HDR*/ -int mbg_check_devices( int argc, char *argv[], int optind, int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) ) +int mbg_open_device_by_param( MBG_DEV_HANDLE *p_dh, const char *dev_param_str, + int dev_idx, int devices_specified, + char *dev_name_buffer, size_t dev_name_buffer_size, + int chk_dev_flags ) { - MBG_DEV_HANDLE dh; - int ret_val = 0; - int num_devices = argc - optind; + MBG_DEV_HANDLE dh = MBG_INVALID_DEV_HANDLE; + int devices_found; + int rc = MBG_ERR_GENERIC; + + if ( dev_name_buffer_size ) // This should always be the case + dev_name_buffer[0] = 0; // Make string empty - if ( num_devices == 0 ) // no device name given on the command line + if ( dev_param_str ) { - // No devices specified on the command line, so - // try to find devices. - int devices = mbg_find_devices(); + // A device parameter string has been specified. + // This can be: + // - A device file name, see ::MBG_DEV_FN + // - A device model name like "GPS180PEX", eventually with the serial number + // appended after an underscore, as in "GPS180PEX_029511026220". + // See ::MBG_DEV_NAME. + // - A device index number as string, e.g "0" or "3". + + char *endptr; + long l; + + #if MBG_TGT_HAS_DEV_FN + // Check if the device parameter represents a device file name + if ( strncmp( dev_param_str, mbg_dev_fn_base, strlen( mbg_dev_fn_base ) ) == 0 ) + { + snprintf_safe( dev_name_buffer, dev_name_buffer_size, "%s", dev_param_str ); + dh = mbg_open_device_by_dev_fn( dev_param_str ); + goto out_chk; + } + #endif + + + // Check if the device parameter string is an index number. + endptr = NULL; + l = strtol( dev_param_str, &endptr, 0 ); + + // If endptr now points past the string then the + // whole string has been interpreted as number. + if ( endptr == &dev_param_str[strlen( dev_param_str )] ) + { + long l_max = (long) ( ( (unsigned int) -1 ) >> 1 ); + + if ( l > l_max ) + { + // The decoded number exceeds the maximum number + // that can be passed to ::mbg_open_device. + rc = MBG_ERR_RANGE; + goto out; + } + + // We use the decoded number as device index. + dev_idx = (int) l; + goto open_dev_with_idx; + } + + + // Finally assume the device name is a model name, eventually + // with serial number appended. + snprintf_safe( dev_name_buffer, dev_name_buffer_size, "%s", dev_param_str ); + dh = mbg_open_device_by_name( dev_param_str, MBG_MATCH_MODEL ); + goto out_chk; + } + - if ( devices == 0 ) + // No device has been specified on the command line. + +#if 0 // TODO + if ( chk_dev_flags & CHK_DEV_WITHOUT_DEV ) + { + // TODO Check if this branch is useful + // We have been called without a device to be used. + // This may be useful e.g. if we just want to print + // some general usage information. + if ( fnc ) { - printf( "No device found.\n" ); - return 1; + *p_dh = MBG_INVALID_DEV_HANDLE; + rc = fnc( *p_dh, NULL ); } + else + { + // TODO Should we report an error if we have been called + // without callback function and without device? + } + goto out; + } +#endif + - // Handle only first device found. - dh = mbg_open_device( 0 ); - ret_val = mbg_check_device( dh, NULL, fnc ); +open_dev_with_idx: + devices_found = chk_get_num_devices(); + + if ( devices_found == 0 ) // no device found + { + // Don't continue without any device, unless + // explicitly requested to do so. + if ( !( chk_dev_flags & CHK_DEV_WITHOUT_DEV ) ) + return MBG_ERR_NO_DEV; + + // We may continue even if no device is available, + // but have to process the callback loop only once. + devices_found = 1; } - else + + // Unless explicitly requested to handle all devices + // we have found, we only handle the first one. + if ( !( chk_dev_flags & CHK_DEV_ALL_DEVICES ) ) + devices_found = 1; + + + // Try to open the device with the specified index number. + mbg_dev_fn_from_dev_idx( dev_name_buffer, dev_name_buffer_size, dev_idx ); + dh = mbg_open_device( dev_idx ); + +out_chk: + // Now check if the "open" function we've just called before + // was successful. + if ( dh == MBG_INVALID_DEV_HANDLE ) + { + char msg[256]; + int n = 0; + rc = mbg_get_last_error( NULL ); + + n = snprintf_safe( msg, sizeof( msg ), "** Failed to open device" ); + + if ( dev_name_buffer[0] ) // string not empty + n += snprintf_safe( &msg[n], sizeof( msg ) - n, " %s", dev_name_buffer ); + + n += snprintf_safe( &msg[n], sizeof( msg ) - n, ": %s", mbg_strerror( rc ) ); + fprintf( stderr, "%s\n\n", msg ); + goto out; + } + + rc = MBG_SUCCESS; + + +out: + *p_dh = dh; + + return rc; + +} // mbg_open_device_by_param + + + +/*HDR*/ +/** + * @brief Main action handler that can be called by utility programs + * + * This function checks the command line parameters passed to the program. + * Those which have not been evaluated before are interpreted as device specifiers. + * + * Device specifiers can be device file names like "/dev/mbgclock0" on target + * platforms that support such device names, see ::MBG_DEV_FN, + * or device type names like "GPS180PEX" which can optionally have a serial + * number appended, like "GPS180PEX_029511026220", to be able to distinguish + * between several devices of the same type (see ::MBG_DEV_NAME), + * or just an index number as required for the ::mbg_open_device call. + * + * For each of the specified devices the callback function @p fnc is called to + * take some specific action on the device. + * + * If no device has been specified in the argument list then ::mbg_find_devices + * is called to set up a device list, and depending on whether ::CHK_DEV_ALL_DEVICES + * is set in @p chk_dev_flags the callback function @p fnc is either called + * for every device from the list, or only for the first one. + * + * @param[in] argc Number of parameters of the program argument list. + * @param[in] argv Array of program argument strings. + * @param[in] optind Number of the command line arguments that have already been handled. + * @param[in] fnc Pointer to a callback function that actually takes an action on each specified device. + * @param[in] chk_dev_flags Bit mask controlling the behavior of the function, see ::CHK_DEV_FLAGS + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ +int mbg_handle_devices( int argc, char *argv[], int optind, + MBG_DEV_HANDLER_FNC *fnc, int chk_dev_flags ) +{ + MBG_DEV_FN tmp_dev_fn; + MBG_DEV_HANDLE dh; + int devices_specified = argc - optind; + int devices_found = 0; + const char *dev_param_str = NULL; + int rc = MBG_ERR_NO_DEV; + int i; + + if ( devices_specified ) { - int i; - // One or more device names have been specified + // One or more device names have been specified // on the command line, so handle each device. for ( i = optind; i < argc; i++ ) { - // Print device name only if output for several devices - // shall be displayed. - const char *fn = ( num_devices > 1 ) ? argv[i] : NULL; + dev_param_str = argv[i]; - dh = open( argv[i], O_RDWR ); - ret_val = mbg_check_device( dh, fn, fnc ); + rc = mbg_open_device_by_param( &dh, dev_param_str, 0, devices_specified, + tmp_dev_fn, sizeof( tmp_dev_fn ), chk_dev_flags ); - if ( ret_val ) + if ( mbg_rc_is_success( rc ) ) + rc = mbg_handle_device( dh, ( devices_specified > 1 ) ? tmp_dev_fn : NULL, fnc ); + + // Don't continue if one of the specified devices failed. + if ( mbg_rc_is_error( rc ) ) break; } + + goto out; + } + + + // No device has been specified on the command line. + + if ( chk_dev_flags & CHK_DEV_WITHOUT_DEV ) + { + // TODO Check if this branch is useful + // We have been called without a device to be used. + // This may be useful e.g. if we just want to print + // some general usage information. + if ( fnc ) + { + dh = MBG_INVALID_DEV_HANDLE; + rc = fnc( dh, NULL ); + } + else + { + // TODO Should we report an error if we have been called + // without callback function and without device? + } + goto out; + } + + + devices_found = chk_get_num_devices(); + + if ( devices_found == 0 ) // no device found + { + // Don't continue without any device, unless + // explicitly requested to do so. + if ( !( chk_dev_flags & CHK_DEV_WITHOUT_DEV ) ) + { + printf( "No device found.\n" ); // TODO + rc = MBG_ERR_NO_DEV; + goto out; + } + + // We may continue even if no device is available, + // but must process the callback loop only once. + devices_found = 1; } - return ret_val; + // Unless explicitly requested to handle all devices + // we have found, we only handle the first one. + if ( !( chk_dev_flags & CHK_DEV_ALL_DEVICES ) ) + devices_found = 1; -} // mbg_check_devices + for ( i = 0; i < devices_found; i++ ) + { + rc = mbg_open_device_by_param( &dh, NULL, i, 0, tmp_dev_fn, + sizeof( tmp_dev_fn ), chk_dev_flags ); + + if ( mbg_rc_is_success( rc ) ) + rc = mbg_handle_device( dh, ( devices_found > 1 ) ? tmp_dev_fn : NULL, fnc ); + + // If one of the unspecified devices failed we continue anyway + // and don't break here. + } + + +out: + return rc; + +} // mbg_handle_devices /*HDR*/ -int mbg_snprint_hr_tstamp( char *s, int len_s, const PCPS_TIME_STAMP *p ) +/** + * @brief Print date and time from a ::PCPS_TIME structure to a string + * + * @param[out] s Address of a string buffer to be filled. + * @param[in] max_len Size of the string buffer. + * @param[in] p Pointer to a ::PCPS_TIME structure to be evaluated. + * @param[in] verbose Increase verbosity of the output:<br> + * > 0: append UTC offset and status<br> + * > 1: append signal value + * + * @return The number of characters printed to the buffer. + */ +size_t mbg_snprint_date_time( char *s, size_t max_len, const PCPS_TIME *p, int verbose ) { - int n = 0; + size_t n = 0; + + n += snprintf_safe( &s[n], max_len - n, "%04u-%02u-%02u %02u:%02u:%02u.%02u", + pcps_exp_year( p->year, mbg_exp_year_limit ), p->month, p->mday, + p->hour, p->min, p->sec, p->sec100 ); + + if ( verbose > 0 ) + n += snprintf_safe( &s[n], max_len - n, " (UTC%+ih), st: %02Xh", + p->offs_utc, p->status ); + + if ( verbose > 1 ) + n += snprintf_safe( &s[n], max_len - n, ", sig: %i", p->signal ); + + return n; + +} // mbg_snprint_date_time + + + +/*HDR*/ +/** + * @brief Print date and time from a ::PCPS_TIME_STAMP structure to a string + * + * @param[out] s Address of a string buffer to be filled. + * @param[in] max_len Size of the string buffer. + * @param[in] p Pointer to a ::PCPS_TIME_STAMP structure to be evaluated. + * @param[in] utc_offs A local time offset added to the time stamp before converted to date and time. + * @param[in] show_raw Flag indicating if a raw timestamp (hex) is to be printed, too. + * + * @return The number of characters printed to the buffer. + */ +size_t mbg_snprint_hr_tstamp( char *s, size_t max_len, const PCPS_TIME_STAMP *p, + long utc_offs, int show_raw ) +{ + long l; + time_t t; + struct tm tm = { 0 }; + size_t n = 0; + int rc; + + if ( show_raw ) + n += snprintf_safe( &s[n], max_len - n, "raw: 0x%08lX.%08lX, ", + (ulong) p->sec, (ulong) p->frac ); // We'll use the standard C library functions to convert the seconds // to broken-down calendar date and time. - time_t t = p->sec; + l = (long) p->sec + utc_offs; + t = cvt_to_time_t( l ); // Our time stamp may be UTC, or have been converted to local time. - // Anyway, since we don't want to account for the system's time zone - // settings, we always use the gmtime() function for conversion: - struct tm *tmp = gmtime( &t ); - - #if defined( DEBUG ) - n += snprintf( s + n, len_s - n, "raw: %08lX.%08lX, ", - (ulong) p->sec, - (ulong) p->frac ); - #endif - - n += snprintf( s + n, len_s - n, "%04i-%02i-%02i %02i:%02i:%02i." PCPS_HRT_FRAC_SCALE_FMT, - tmp->tm_year + 1900, - tmp->tm_mon + 1, - tmp->tm_mday, - tmp->tm_hour, - tmp->tm_min, - tmp->tm_sec, - (ulong) frac_sec_from_bin( p->frac, PCPS_HRT_FRAC_SCALE ) - ); + // Anyway, since we don't want to account for the system's time zone + // settings, we always use the gmtime() function for conversion, + // or our own wrapper, respectively: + rc = mbg_gmtime( &tm, &t ); + + if ( mbg_rc_is_success( rc ) ) + n += snprintf_safe( &s[n], max_len - n, "%04i-%02i-%02i %02i:%02i:%02i." PCPS_HRT_FRAC_SCALE_FMT, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, + (ulong) bin_frac_32_to_dec_frac( p->frac, PCPS_HRT_FRAC_SCALE ) ); + else + n += snprint_gmtime_error( &s[n], max_len - n, rc, t, __func__ ); return n; @@ -356,11 +797,24 @@ int mbg_snprint_hr_tstamp( char *s, int len_s, const PCPS_TIME_STAMP *p ) /*HDR*/ -int mbg_snprint_hr_time( char *s, int len_s, const PCPS_HR_TIME *p ) +/** + * @brief Print date and time from a ::PCPS_HR_TIME structure to a string + * + * Converts the UTC timestamp first to local time according to + * the ::PCPS_HR_TIME::utc_offs value. + * + * @param[out] s Address of a string buffer to be filled. + * @param[in] max_len Size of the string buffer. + * @param[in] p Pointer to a ::PCPS_HR_TIME structure to be evaluated. + * @param[in] show_raw Flag indicating if a raw timestamp (hex) is to be printed, too. + * + * @return The number of characters printed to the buffer. + */ +size_t mbg_snprint_hr_time( char *s, int max_len, const PCPS_HR_TIME *p, int show_raw ) { char ws[80]; PCPS_TIME_STAMP ts = p->tstamp; - int n; + size_t n; const char *time_scale_name; const char *cp; @@ -368,19 +822,13 @@ int mbg_snprint_hr_time( char *s, int len_s, const PCPS_HR_TIME *p ) // and set up a string telling the offset. if ( p->utc_offs ) { - ldiv_t ldt; - - ts.sec += p->utc_offs; - // The local time offset is in seconds and may be negative, so we // convert to absolute hours and minutes first. - ldt = ldiv( labs( p->utc_offs ) / 60, 60 ); + ldiv_t ldt = ldiv( labs( p->utc_offs ) / 60, 60 ); - snprintf( ws, sizeof( ws ), "%c%lu:%02luh", - ( p->utc_offs < 0 ) ? '-' : '+', - ldt.quot, - ldt.rem - ); + snprintf_safe( ws, sizeof( ws ), "%c%lu:%02luh", + ( p->utc_offs < 0 ) ? '-' : '+', + ldt.quot, ldt.rem ); cp = ws; } else @@ -388,7 +836,7 @@ int mbg_snprint_hr_time( char *s, int len_s, const PCPS_HR_TIME *p ) // Convert the local time stamp to calendar date and time. - n = mbg_snprint_hr_tstamp( s, len_s, &ts ); + n = mbg_snprint_hr_tstamp( s, max_len, &ts, p->utc_offs, show_raw ); // By default the time stamp represents UTC plus an optional local time offset. time_scale_name = "UTC"; @@ -400,7 +848,7 @@ int mbg_snprint_hr_time( char *s, int len_s, const PCPS_HR_TIME *p ) if ( p->status & PCPS_SCALE_GPS ) time_scale_name = "GPS"; // time stamp represents GPS system time - n += snprintf( s + n, len_s - n, " %s%s", time_scale_name, cp ); + n += snprintf_safe( &s[n], max_len - n, " %s%s", time_scale_name, cp ); return n; @@ -409,30 +857,154 @@ int mbg_snprint_hr_time( char *s, int len_s, const PCPS_HR_TIME *p ) /*HDR*/ -void mbg_print_hr_timestamp( PCPS_TIME_STAMP *p_ts, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, int raw ) +/** + * @brief Print date and time from a ::PCPS_TIME_STAMP structure + * + * First the HR timestamp passed by parameter @p p_ts is printed. + * + * If the parameter @p p_prv_ts is not NULL then it should specify + * an earlier timestamp, and the elapsed time since @p p_ts + * is appended. + * + * Finally the latency value is printed in microseconds, unless + * parameter @p no_latency is != 0. + * + * @param[in] p_ts Pointer to a ::PCPS_TIME_STAMP structure to be evaluated. + * @param[in] hns_latency A latency number in hectonanoseconds, i.e. 100 ns units. + * @param[in] p_prv_ts Pointer to a ::PCPS_TIME_STAMP structure to be evaluated, may be NULL + * @param[in] no_latency A flag indicating if printing the latency should be suppressed. + * @param[in] show_raw Flag indicating if a raw timestamp (hex) is to be printed, too. + * + * @see ::mbg_print_hr_time + */ +void mbg_print_hr_timestamp( PCPS_TIME_STAMP *p_ts, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, + int no_latency, int show_raw ) { char ws[80]; - mbg_snprint_hr_tstamp( ws, sizeof( ws ), p_ts ); - printf( "Fast HR time %s", ws ); + mbg_snprint_hr_tstamp( ws, sizeof( ws ), p_ts, 0, show_raw ); + printf( "HR time %s", ws ); if ( p_prv_ts ) - { - // print the difference between the current and the previous time stamp - uint64_t ts = pcps_time_stamp_to_uint64( p_ts ); - uint64_t prv_ts = pcps_time_stamp_to_uint64( p_prv_ts ); - // we divide by PCPS_HRT_BIN_FRAC_SCALE to get the correct fractions - // and we multiply by 1E6 to get the result in microseconds - double delta_t = (double) ( ts - prv_ts ) * 1E6 / PCPS_HRT_BIN_FRAC_SCALE; - printf( " (%+.1f us)", delta_t ); - } + printf( " (%+.1f us)", delta_timestamps( p_ts, p_prv_ts ) ); - if ( !raw ) + if ( !no_latency ) printf( ", latency: %.1f us", ( (double) hns_latency ) / 10 ); - puts( "" ); + puts( str_empty ); } // mbg_print_hr_timestamp +/*HDR*/ +/** + * @brief Print date and time from a ::PCPS_HR_TIME structure + * + * First the HR timestamp passed by parameter @p p_ht is printed. + * + * If the parameter @p p_prv_ts is not NULL then it should specify + * an earlier timestamp, and the elapsed time since @p p_ht + * is appended. + * + * Next the latency value is printed in microseconds, unless + * parameter @p no_latency is != 0. + * + * @param[in] p_ht Pointer to a ::PCPS_TIME_STAMP structure to be evaluated. + * @param[in] hns_latency A latency number in hectonanoseconds, i.e. 100 ns units. + * @param[in] p_prv_ts Pointer to a ::PCPS_TIME_STAMP structure to be evaluated, may be NULL + * @param[in] no_latency A flag indicating if printing the latency should be suppressed. + * @param[in] show_raw Flag indicating if a raw timestamp (hex) is to be printed, too. + * @param[in] verbose Increase verbosity of the output:<br> + * > 0: append status code<br> + * > 1: append signal value + * + * @see ::mbg_print_hr_timestamp + */ +void mbg_print_hr_time( PCPS_HR_TIME *p_ht, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, + int no_latency, int show_raw, int verbose ) +{ + char ws[80]; + + mbg_snprint_hr_time( ws, sizeof( ws ), p_ht, show_raw ); + printf( "HR time %s", ws ); + + if ( p_prv_ts ) + printf( " (%+.1f us)", delta_timestamps( &p_ht->tstamp, p_prv_ts ) ); + + if ( !no_latency ) + printf( ", latency: %.1f us", ( (double) hns_latency ) / 10 ); + + if ( verbose > 0 ) + printf( ", st: 0x%04lX", (ulong) p_ht->status ); + + if ( verbose > 1 ) + printf( ", sig: %i", p_ht->signal ); + + puts( "" ); + +} // mbg_print_hr_time + + + +/*HDR*/ +/** + * @brief Retrieve and print PZF correlation info for a device which supports this + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] show_corr_step A flag indicating if correlation step indicators are to be appended + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ +int mbg_show_pzf_corr_info( MBG_DEV_HANDLE dh, int show_corr_step ) +{ + CORR_INFO ci; + char ws[80]; + const char *cp; + + int rc = mbg_get_corr_info( dh, &ci ); + + if ( mbg_cond_err_msg( rc, "mbg_get_corr_info" ) ) + return rc; + + + if ( ci.status < N_PZF_CORR_STATE ) + cp = pzf_corr_state_name[ci.status]; + else + { + snprintf_safe( ws, sizeof( ws ), "unknown status code: 0x%02X", ci.status ); + cp = ws; + } + + printf( "%s, PZF correlation: %u%%", cp, ci.val ); + + if ( show_corr_step ) + if ( ci.corr_dir != ' ' ) + printf( " Shift: %c", ci.corr_dir ); + + return MBG_SUCCESS; + +} // mbg_show_pzf_corr_info + + + +/*HDR*/ +/** + * @brief Retrieve a ::MBG_GNSS_MODE_INFO structure from a device + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_GNSS_MODE_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ +int mbg_get_gps_gnss_mode_info_chk( MBG_DEV_HANDLE dh, MBG_GNSS_MODE_INFO *p ) +{ + int rc = mbg_get_gps_gnss_mode_info( dh, p ); + mbg_cond_err_msg( rc, "mbg_get_gps_gnss_mode_info" ); + + return rc; + +} // mbg_get_gps_gnss_mode_info_chk + + + diff --git a/src/external/bsd/meinberg/dist/mbglib/common/toolutil.h b/src/external/bsd/meinberg/dist/mbglib/common/toolutil.h index cef7d44..103e8af 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/toolutil.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/toolutil.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: toolutil.h 1.2.1.2 2011/07/05 15:35:56 martin TRASH martin $ + * $Id: toolutil.h 1.4 2017/07/05 07:38:06 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,10 +10,18 @@ * * ----------------------------------------------------------------------- * $Log: toolutil.h $ - * Revision 1.2.1.2 2011/07/05 15:35:56 martin - * Modified version handling. - * Revision 1.2.1.1 2011/07/05 14:36:42 martin - * New way to maintain version information. + * Revision 1.4 2017/07/05 07:38:06 martin + * Support Windows target. + * Defined function type MBG_DEV_HANDLER_FNC. + * Defined some OS-specific strings e.g. for example + * file and device names used in help messages. + * Check for MBG_TGT_POSIX instead of MBG_TGT_UNIX. + * Doxygen comments. + * Updated function prototypes. + * Revision 1.3 2012/10/15 09:36:22 martin + * Use common way to handle version information. + * Added string table with PZF state names. + * Updated function prototypes. * Revision 1.2 2009/06/19 12:11:35 martin * Updated function prototypes. * Revision 1.1 2008/12/17 10:45:14 martin @@ -32,6 +40,25 @@ #include <mbgdevio.h> #include <mbgversion.h> +#if defined( MBG_TGT_POSIX ) + + #include <unistd.h> + +#elif defined( MBG_TGT_WIN32 ) + + #include <io.h> + #include <fcntl.h> + #include <sys/types.h> + #include <sys/stat.h> + #include <wingetopt.h> + + #define open _open + #define snprintf _snprintf + #define sleep( _x ) Sleep( (_x) * 1000 ) + #define usleep( _x ) Sleep( (_x) / 1000 ) + +#endif + #ifdef _TOOLUTIL @@ -44,12 +71,85 @@ /* Start of header body */ +#ifdef __cplusplus +extern "C" { +#endif + + +enum CHK_DEV_FLAGS +{ + CHK_DEV_ALL_DEVICES = 0x0001, ///< call callback for all devices + CHK_DEV_WITHOUT_DEV = 0x0002 ///< call callback once if no device found +}; + + + +#if MBG_TGT_HAS_DEV_FN + #define EXAMPLE_DEV_FN_1 MBGCLOCK_DEV_FN_BASE "0" + #define EXAMPLE_DEV_FN_1_TCR EXAMPLE_DEV_FN_1 + #define EXAMPLE_DEV_FN_2 MBGCLOCK_DEV_FN_BASE "3" +#endif + +#define EXAMPLE_DEV_NAME_1 "gps180pex" +#define EXAMPLE_DEV_NAME_1_TCR "tcr167pci" +#define EXAMPLE_DEV_NAME_2 "tcr170pex_027911002000" + + +#if defined( MBG_TGT_POSIX ) + #define ROOT_PRIVILEGES_STR "with root privileges" +#else + #define ROOT_PRIVILEGES_STR "as administrator" +#endif + + +#if !defined( MBG_EXP_YEAR_LIMIT ) + #define MBG_EXP_YEAR_LIMIT 1980 +#endif + + +_ext uint16_t mbg_exp_year_limit +#ifdef _DO_INIT + = MBG_EXP_YEAR_LIMIT +#endif +; + _ext int must_print_usage; +_ext const char str_empty[] +#ifdef _DO_INIT + = "" +#endif +; -#ifdef __cplusplus -extern "C" { + +_ext const char *pzf_corr_state_name[N_PZF_CORR_STATE] +#ifdef _DO_INIT + = PZF_CORR_STATE_NAMES_ENG #endif +; + + + +/** + * @brief The type of functions to called to handle a device in a specific way. + */ +typedef int MBG_DEV_HANDLER_FNC( MBG_DEV_HANDLE, const PCPS_DEV *); + + + +/** + * @brief Exit codes returned by the command line tools + */ +enum MBG_EXIT_CODES +{ + MBG_EXIT_CODE_SUCCESS, ///< Device handled successfully for requested action + MBG_EXIT_CODE_USAGE, ///< Device not handled successfully, usage printed + MBG_EXIT_CODE_NOT_SUPP, ///< Not supported on the running OS + MBG_EXIT_CODE_FAIL, ///< Action failed for device + MBG_EXIT_CODE_INV_TIME, ///< Device has no valid time to set the system time with + N_MBG_EXIT_CODES +}; + /* ----- function prototypes begin ----- */ @@ -57,20 +157,250 @@ extern "C" { /* This section was generated automatically */ /* by MAKEHDR, do not remove the comments. */ + /** + * @brief Print the program version to a string buffer + * + * @param[out] s Address of a string buffer to be filled. + * @param[in] max_len Size of the string buffer. + * @param[in] micro_version Micro version code for the application. + * + * @return The number of characters printed to the buffer. + */ + int mbg_program_version_str( char *s, size_t max_len, int micro_version ) ; + + /** + * @brief Print some program info to a string buffer + * + * @param[out] s Address of a string buffer to be filled. + * @param[in] max_len Size of the string buffer. + * @param[in] pname The program name. + * @param[in] micro_version Micro version code for the application. + * @param[in] first_year First copyright year. + * @param[in] last_year Last copyright year. + * + * @return The number of characters printed to the buffer. + */ int mbg_program_info_str( char *s, size_t max_len, const char *pname, int micro_version, int first_year, int last_year ) ; + + /** + * @brief Print program info to console + * + * @param[in] pname The program name. + * @param[in] micro_version Micro version code for the application. + * @param[in] first_year First copyright year. + * @param[in] last_year Last copyright year. + */ void mbg_print_program_info( const char *pname, int micro_version, int first_year, int last_year ) ; + + /** + * @brief Print usage intro to console + * + * @param[in] pname The program name. + * @param[in] info An optional additional info string, may be NULL. + */ void mbg_print_usage_intro( const char *pname, const char *info ) ; - void mbg_print_help_options( void ) ; + + /** + * @brief Print info on a single program option / argument + * + * @param[in] opt_name The option name, optional, may be NULL. + * @param[in] opt_info The option info, optional, may be NULL. + */ void mbg_print_opt_info( const char *opt_name, const char *opt_info ) ; + + /** + * @brief Print info on common program help arguments + * + * Lists program parameters causing printing + * of help / usage information. + */ + void mbg_print_help_options( void ) ; + + /** + * @brief Print common info on how to specify devices on the command line + */ void mbg_print_device_options( void ) ; + + /** + * @brief Print program info and default usage information + * + * @param[in] pname The program name. + * @param[in] prog_info An optional additional info string, may be NULL. + */ void mbg_print_default_usage( const char *pname, const char *prog_info ) ; - int mbg_ioctl_err( int rc, const char *descr ) ; + + /** + * @brief Retrieve and print some common device info + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] dev_name A device name string to be printed + * @param[out] p_dev Pointer to a device info structure to be read from the device + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ int mbg_get_show_dev_info( MBG_DEV_HANDLE dh, const char *dev_name, PCPS_DEV *p_dev ) ; - int mbg_check_device( MBG_DEV_HANDLE dh, const char *dev_name, int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) ) ; - int mbg_check_devices( int argc, char *argv[], int optind, int (*fnc)( MBG_DEV_HANDLE, const PCPS_DEV *) ) ; - int mbg_snprint_hr_tstamp( char *s, int len_s, const PCPS_TIME_STAMP *p ) ; - int mbg_snprint_hr_time( char *s, int len_s, const PCPS_HR_TIME *p ) ; - void mbg_print_hr_timestamp( PCPS_TIME_STAMP *p_ts, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, int raw ) ; + + /** + * @brief Print device info and take some action on a specific device + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] dev_name A device name string to be printed. + * @param[in] fnc Pointer to a callback function that actually takes the action. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ + int mbg_handle_device( MBG_DEV_HANDLE dh, const char *dev_name, MBG_DEV_HANDLER_FNC *fnc ) ; + + /** + * @brief Get the number of devices actually present + * + * Do a real search only when called for the first time. + * + * @return The number of devices currently present. + */ + int chk_get_num_devices( void ) ; + + int mbg_open_device_by_param( MBG_DEV_HANDLE *p_dh, const char *dev_param_str, int dev_idx, int devices_specified, char *dev_name_buffer, size_t dev_name_buffer_size, int chk_dev_flags ) ; + /** + * @brief Main action handler that can be called by utility programs + * + * This function checks the command line parameters passed to the program. + * Those which have not been evaluated before are interpreted as device specifiers. + * + * Device specifiers can be device file names like "/dev/mbgclock0" on target + * platforms that support such device names, see ::MBG_DEV_FN, + * or device type names like "GPS180PEX" which can optionally have a serial + * number appended, like "GPS180PEX_029511026220", to be able to distinguish + * between several devices of the same type (see ::MBG_DEV_NAME), + * or just an index number as required for the ::mbg_open_device call. + * + * For each of the specified devices the callback function @p fnc is called to + * take some specific action on the device. + * + * If no device has been specified in the argument list then ::mbg_find_devices + * is called to set up a device list, and depending on whether ::CHK_DEV_ALL_DEVICES + * is set in @p chk_dev_flags the callback function @p fnc is either called + * for every device from the list, or only for the first one. + * + * @param[in] argc Number of parameters of the program argument list. + * @param[in] argv Array of program argument strings. + * @param[in] optind Number of the command line arguments that have already been handled. + * @param[in] fnc Pointer to a callback function that actually takes an action on each specified device. + * @param[in] chk_dev_flags Bit mask controlling the behavior of the function, see ::CHK_DEV_FLAGS + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ + int mbg_handle_devices( int argc, char *argv[], int optind, MBG_DEV_HANDLER_FNC *fnc, int chk_dev_flags ) ; + + /** + * @brief Print date and time from a ::PCPS_TIME structure to a string + * + * @param[out] s Address of a string buffer to be filled. + * @param[in] max_len Size of the string buffer. + * @param[in] p Pointer to a ::PCPS_TIME structure to be evaluated. + * @param[in] verbose Increase verbosity of the output:<br> + * > 0: append UTC offset and status<br> + * > 1: append signal value + * + * @return The number of characters printed to the buffer. + */ + size_t mbg_snprint_date_time( char *s, size_t max_len, const PCPS_TIME *p, int verbose ) ; + + /** + * @brief Print date and time from a ::PCPS_TIME_STAMP structure to a string + * + * @param[out] s Address of a string buffer to be filled. + * @param[in] max_len Size of the string buffer. + * @param[in] p Pointer to a ::PCPS_TIME_STAMP structure to be evaluated. + * @param[in] utc_offs A local time offset added to the time stamp before converted to date and time. + * @param[in] show_raw Flag indicating if a raw timestamp (hex) is to be printed, too. + * + * @return The number of characters printed to the buffer. + */ + size_t mbg_snprint_hr_tstamp( char *s, size_t max_len, const PCPS_TIME_STAMP *p, long utc_offs, int show_raw ) ; + + /** + * @brief Print date and time from a ::PCPS_HR_TIME structure to a string + * + * Converts the UTC timestamp first to local time according to + * the ::PCPS_HR_TIME::utc_offs value. + * + * @param[out] s Address of a string buffer to be filled. + * @param[in] max_len Size of the string buffer. + * @param[in] p Pointer to a ::PCPS_HR_TIME structure to be evaluated. + * @param[in] show_raw Flag indicating if a raw timestamp (hex) is to be printed, too. + * + * @return The number of characters printed to the buffer. + */ + size_t mbg_snprint_hr_time( char *s, int max_len, const PCPS_HR_TIME *p, int show_raw ) ; + + /** + * @brief Print date and time from a ::PCPS_TIME_STAMP structure + * + * First the HR timestamp passed by parameter @p p_ts is printed. + * + * If the parameter @p p_prv_ts is not NULL then it should specify + * an earlier timestamp, and the elapsed time since @p p_ts + * is appended. + * + * Finally the latency value is printed in microseconds, unless + * parameter @p no_latency is != 0. + * + * @param[in] p_ts Pointer to a ::PCPS_TIME_STAMP structure to be evaluated. + * @param[in] hns_latency A latency number in hectonanoseconds, i.e. 100 ns units. + * @param[in] p_prv_ts Pointer to a ::PCPS_TIME_STAMP structure to be evaluated, may be NULL + * @param[in] no_latency A flag indicating if printing the latency should be suppressed. + * @param[in] show_raw Flag indicating if a raw timestamp (hex) is to be printed, too. + * + * @see ::mbg_print_hr_time + */ + void mbg_print_hr_timestamp( PCPS_TIME_STAMP *p_ts, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, int no_latency, int show_raw ) ; + + /** + * @brief Print date and time from a ::PCPS_HR_TIME structure + * + * First the HR timestamp passed by parameter @p p_ht is printed. + * + * If the parameter @p p_prv_ts is not NULL then it should specify + * an earlier timestamp, and the elapsed time since @p p_ht + * is appended. + * + * Next the latency value is printed in microseconds, unless + * parameter @p no_latency is != 0. + * + * @param[in] p_ht Pointer to a ::PCPS_TIME_STAMP structure to be evaluated. + * @param[in] hns_latency A latency number in hectonanoseconds, i.e. 100 ns units. + * @param[in] p_prv_ts Pointer to a ::PCPS_TIME_STAMP structure to be evaluated, may be NULL + * @param[in] no_latency A flag indicating if printing the latency should be suppressed. + * @param[in] show_raw Flag indicating if a raw timestamp (hex) is to be printed, too. + * @param[in] verbose Increase verbosity of the output:<br> + * > 0: append status code<br> + * > 1: append signal value + * + * @see ::mbg_print_hr_timestamp + */ + void mbg_print_hr_time( PCPS_HR_TIME *p_ht, int32_t hns_latency, PCPS_TIME_STAMP *p_prv_ts, int no_latency, int show_raw, int verbose ) ; + + /** + * @brief Retrieve and print PZF correlation info for a device which supports this + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[in] show_corr_step A flag indicating if correlation step indicators are to be appended + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ + int mbg_show_pzf_corr_info( MBG_DEV_HANDLE dh, int show_corr_step ) ; + + /** + * @brief Retrieve a ::MBG_GNSS_MODE_INFO structure from a device + * + * @param[in] dh Valid ::MBG_DEV_HANDLE handle to a Meinberg device. + * @param[out] p Pointer to a ::MBG_GNSS_MODE_INFO structure to be filled up. + * + * @return ::MBG_SUCCESS on success, else one of the @ref MBG_ERROR_CODES + */ + int mbg_get_gps_gnss_mode_info_chk( MBG_DEV_HANDLE dh, MBG_GNSS_MODE_INFO *p ) ; + /* ----- function prototypes end ----- */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/usbdefs.h b/src/external/bsd/meinberg/dist/mbglib/common/usbdefs.h index 30a39e2..b69cbcb 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/usbdefs.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/usbdefs.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: usbdefs.h 1.13 2011/06/29 14:11:23 martin TRASH $ + * $Id: usbdefs.h 1.30 2017/05/17 09:52:53 thomas.fasse REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,7 +10,53 @@ * * ----------------------------------------------------------------------- * $Log: usbdefs.h $ - * Revision 1.13 2011/06/29 14:11:23 martin + * Revision 1.30 2017/05/17 09:52:53 thomas.fasse + * Device BITS was rennamed to LSG180. + * Revision 1.29 2017/05/16 07:19:40Z thomas.fasse + * Added ID, name string and table entry for LIU variant BITS by Paul + * Revision 1.28 2017/04/04 10:43:34Z paul.kretz + * Added ID, name string and table entry for FDM180M + * Added missing table entry for MicroSync power supply module + * Revision 1.27 2017/03/28 09:37:15Z paul.kretz + * Added ID, name string and table entry for MicroSync power supply module + * Revision 1.26 2017/02/13 09:57:45Z paul.kretz + * Added ID, name string and table entry for PZF180. + * Revision 1.25 2016/11/11 09:24:04Z lars.meihost + * Added ID, name string and table entry for TCR180. + * Revision 1.24 2016/11/04 11:49:15Z paul.kretz + * Added device ID and associated class code for MDU312 + * Revision 1.23 2016/09/26 07:28:10Z paul.kretz + * Added class code and device for N2X180 + * Revision 1.22 2016/07/06 13:55:15Z martin + * Definitions for IMS-SPT, REL1000, MDU300, and SDI added by stephan. + * Class code and device ID for LUE added by daniel-vdh. + * Class code and device ID for HPS added by daniel. + * Device IDs and associated class codes for SCG, FDM180, CPC180, + * VSG180, and GTS180 added by paul. + * Removed obsolete multiple definitions for FTDI serial interface chips. + * Added a new definition for unique FTDI chip. + * Added definitions for serial refclocks. + * Added definitions for LNE180SFP, GRC180 and GRC181. + * Added definitions USB_VENDOR_WILDCARD and USB_PROD_WILDCARD. + * Added device name string and string table initializers. + * Doxygen fixes. + * Revision 1.21 2014/01/16 15:26:09 daniel + * Added class codes and devices for USB to serial adapters and ASIX network chips + * Revision 1.20 2013/10/08 09:13:04 daniel + * Added definition and class code for RSC. + * Revision 1.19 2013/06/04 10:45:53 daniel + * Added class codes and device IDs for IMS devices MRI and BPE + * Revision 1.18 2013/01/24 11:29:21 joerg + * Added class code and device ID for LNE-GB + * Revision 1.17 2012/08/08 07:53:29Z daniel + * Added class code and device ID for LIU + * Revision 1.16 2012/02/13 09:29:59 paul + * added class code for LNO180 + * Revision 1.15 2011/10/11 06:21:04Z andre + * added class code for GPS180 + * Revision 1.14 2011/10/07 10:13:25Z daniel + * New class code and device id for CPE + * Revision 1.13 2011/06/29 14:11:23Z martin * Added device IDs for TCR600USB, MSF600USB, and WVB600USB. * Revision 1.12 2011/05/11 07:20:37 daniel * New class code and device id for fan control unit @@ -55,58 +101,305 @@ extern "C" { #endif -/* Meinberg's USB vendor ID number (assigned by USB-IF Administration) */ +/** Meinberg's USB vendor ID number (assigned by USB-IF administration) */ #define USB_VENDOR_MEINBERG 0x1938 +#define USB_VENDOR_WILDCARD 0 +#define USB_PROD_WILDCARD 0 -/* - * USB device class codes (assigned by Meinberg) + +/** + * @brief USB device class codes assigned by Meinberg */ -enum +enum MBG_USB_CLASS_CODES { - MBG_USB_CLASS_NONE, // (unknown or not defined) - MBG_USB_CLASS_CPC, // Control Panel Controller - MBG_USB_CLASS_TSU, // Time Stamp Unit - MBG_USB_CLASS_DCF, // DCF77 Radio Clock - MBG_USB_CLASS_CMC, // nCipher Crypto Module Carrier - MBG_USB_CLASS_TCR, // IRIG Time Code Receiver - MBG_USB_CLASS_MSF, // MSF Radio Clock - MBG_USB_CLASS_WWVB, // WWVB Radio Clock - MBG_USB_CLASS_SCU, // Meinberg Signal Changeover Unit - MBG_USB_CLASS_ESI, // External Synchronization Interface - MBG_USB_CLASS_FCU, // Fan Control Unit - N_MBG_USB_CLASS // number of known device class codes + MBG_USB_CLASS_NONE, ///< (unknown or not defined) + MBG_USB_CLASS_CPC, ///< Control Panel Controller + MBG_USB_CLASS_TSU, ///< Time Stamp Unit + MBG_USB_CLASS_DCF, ///< DCF77 Radio Clock + MBG_USB_CLASS_CMC, ///< nCipher Crypto Module Carrier + MBG_USB_CLASS_TCR, ///< IRIG Time Code Receiver + MBG_USB_CLASS_MSF, ///< MSF Radio Clock + MBG_USB_CLASS_WWVB, ///< WWVB Radio Clock + + MBG_USB_CLASS_SCU, ///< Meinberg Signal Changeover Unit + MBG_USB_CLASS_ESI, ///< External Synchronization Interface + MBG_USB_CLASS_FCU, ///< Fan Control Unit + MBG_USB_CLASS_CPE, ///< Configurable Port Expander + MBG_USB_CLASS_GPS, ///< GPS Receiver + MBG_USB_CLASS_LNO, ///< Low Phase Noise Option + MBG_USB_CLASS_LIU, ///< Line Interface Unit + MBG_USB_CLASS_LNE, ///< LNE-GB + + MBG_USB_CLASS_MRI, ///< MRS Input card for IMS + MBG_USB_CLASS_BPE, ///< IMS Backplane Port Expander + MBG_USB_CLASS_RSC, ///< RSC Redundant Switch Control + MBG_USB_CLASS_SERIAL, ///< USB to Serial controller, FTDI chip connected to Meinberg serial device + MBG_USB_CLASS_SCG, ///< Studio Clock Generator + MBG_USB_CLASS_SDI, ///< SDI Input card for IMS + MBG_USB_CLASS_FDM, ///< Frequency Deviation Monitor + MBG_USB_CLASS_NIC, ///< ASIX AX88179 Network interface chips on LNE, modified by Meinberg (this *must* be 0x17) + + MBG_USB_CLASS_MDU, ///< Modular Distribution Unit + MBG_USB_CLASS_SPT, ///< Single Path Through + MBG_USB_CLASS_REL, ///< Relais Error Card + MBG_USB_CLASS_LUE, ///< Lantime USB Expansion + MBG_USB_CLASS_HPS, ///< High Performance Synchronization Card (PTP/NTP) + MBG_USB_CLASS_VSG, ///< Video Sync Generator + MBG_USB_CLASS_GTS, ///< Greenwich Time Signal + MBG_USB_CLASS_GRC, ///< GNSS receivers (GPS, GLONASS, ... ) + + MBG_USB_CLASS_N2X, ///< NTP/PTP receiver + MBG_USB_CLASS_USYNC, ///< MicroSync + + N_MBG_USB_CLASS ///< number of known Meinberg USB device class codes }; -/* - * USB device ID numbers (assigned by Meinberg) - * High byte: USB device class as specified above - * Low byte: enumeration of device of a class +/** + * @brief USB device ID numbers assigned by Meinberg + * + * High byte: USB device class, see ::MBG_USB_CLASS_CODES<br> + * Low byte: enumeration of devices of a class + * + * @see @ref MBG_USB_DEVICE_NAMES + * @see ::DEFAULT_MBG_USB_DEVICE_NAMES + * @see ::MBG_USB_CLASS_CODES + * + * @anchor MBG_USB_DEVICE_IDS @{ */ -#define USB_DEV_CPC_01 ( ( MBG_USB_CLASS_CPC << 8 ) | 0x01 ) -#define USB_DEV_TSU_01 ( ( MBG_USB_CLASS_TSU << 8 ) | 0x01 ) +#define USB_DEV_CPC_01 ( ( MBG_USB_CLASS_CPC << 8 ) | 0x01 ) +#define USB_DEV_CPC180 ( ( MBG_USB_CLASS_CPC << 8 ) | 0x02 ) + +#define USB_DEV_TSU_01 ( ( MBG_USB_CLASS_TSU << 8 ) | 0x01 ) + +#define USB_DEV_USB5131 ( ( MBG_USB_CLASS_DCF << 8 ) | 0x01 ) +#define USB_DEV_DCF600USB ( ( MBG_USB_CLASS_DCF << 8 ) | 0x02 ) +#define USB_DEV_PZF180 ( ( MBG_USB_CLASS_DCF << 8 ) | 0x03 ) + +#define USB_DEV_CMC ( ( MBG_USB_CLASS_CMC << 8 ) | 0x01 ) + +#define USB_DEV_TCR51USB ( ( MBG_USB_CLASS_TCR << 8 ) | 0x01 ) +#define USB_DEV_TCR600USB ( ( MBG_USB_CLASS_TCR << 8 ) | 0x02 ) +#define USB_DEV_TCR180 ( ( MBG_USB_CLASS_TCR << 8 ) | 0x03 ) + +#define USB_DEV_MSF51USB ( ( MBG_USB_CLASS_MSF << 8 ) | 0x01 ) +#define USB_DEV_MSF600USB ( ( MBG_USB_CLASS_MSF << 8 ) | 0x02 ) + +#define USB_DEV_WWVB51USB ( ( MBG_USB_CLASS_WWVB << 8 ) | 0x01 ) +#define USB_DEV_WVB600USB ( ( MBG_USB_CLASS_WWVB << 8 ) | 0x02 ) + +#define USB_DEV_SCU_USB ( ( MBG_USB_CLASS_SCU << 8 ) | 0x01 ) + +#define USB_DEV_ESI_01 ( ( MBG_USB_CLASS_ESI << 8 ) | 0x01 ) + +#define USB_DEV_FCU_01 ( ( MBG_USB_CLASS_FCU << 8 ) | 0x01 ) + +#define USB_DEV_CPE_01 ( ( MBG_USB_CLASS_CPE << 8 ) | 0x01 ) + +#define USB_DEV_GPS180 ( ( MBG_USB_CLASS_GPS << 8 ) | 0x01 ) -#define USB_DEV_USB5131 ( ( MBG_USB_CLASS_DCF << 8 ) | 0x01 ) -#define USB_DEV_DCF600USB ( ( MBG_USB_CLASS_DCF << 8 ) | 0x02 ) +#define USB_DEV_LNO180 ( ( MBG_USB_CLASS_LNO << 8 ) | 0x01 ) -#define USB_DEV_CMC ( ( MBG_USB_CLASS_CMC << 8 ) | 0x01 ) +#define USB_DEV_LIU_01 ( ( MBG_USB_CLASS_LIU << 8 ) | 0x01 ) +#define USB_DEV_LSG180 ( ( MBG_USB_CLASS_LIU << 8 ) | 0x02 ) -#define USB_DEV_TCR51USB ( ( MBG_USB_CLASS_TCR << 8 ) | 0x01 ) -#define USB_DEV_TCR600USB ( ( MBG_USB_CLASS_TCR << 8 ) | 0x02 ) +#define USB_DEV_LNE_01 ( ( MBG_USB_CLASS_LNE << 8 ) | 0x01 ) // LNE with standard copper +#define USB_DEV_LNE180SFP ( ( MBG_USB_CLASS_LNE << 8 ) | 0x02 ) // LNE with SFP (fiber optic) -#define USB_DEV_MSF51USB ( ( MBG_USB_CLASS_MSF << 8 ) | 0x01 ) -#define USB_DEV_MSF600USB ( ( MBG_USB_CLASS_MSF << 8 ) | 0x02 ) +#define USB_DEV_MRI_01 ( ( MBG_USB_CLASS_MRI << 8 ) | 0x01 ) -#define USB_DEV_WWVB51USB ( ( MBG_USB_CLASS_WWVB << 8 ) | 0x01 ) -#define USB_DEV_WVB600USB ( ( MBG_USB_CLASS_WWVB << 8 ) | 0x02 ) +#define USB_DEV_BPE_01 ( ( MBG_USB_CLASS_BPE << 8 ) | 0x01 ) -#define USB_DEV_SCU_USB ( ( MBG_USB_CLASS_SCU << 8 ) | 0x01 ) +#define USB_DEV_RSC_01 ( ( MBG_USB_CLASS_RSC << 8 ) | 0x01 ) + +#define USB_DEV_SPT_01 ( ( MBG_USB_CLASS_SPT << 8 ) | 0x01 ) + +#define USB_DEV_REL_01 ( ( MBG_USB_CLASS_REL << 8 ) | 0x01 ) + +/// LANTIME CPU quad FTDI serial interface chip +#define USB_DEV_LAN_CPU_SERIAL ( ( MBG_USB_CLASS_SERIAL << 8 ) | 0x01 ) + +#define USB_DEV_SCG_01 ( ( MBG_USB_CLASS_SCG << 8 ) | 0x01 ) + +#define USB_DEV_SDI_01 ( ( MBG_USB_CLASS_SDI << 8 ) | 0x01 ) + +#define USB_DEV_FDM180 ( ( MBG_USB_CLASS_FDM << 8 ) | 0x01 ) // FDM for IMS Systems +#define USB_DEV_FDM180M ( ( MBG_USB_CLASS_FDM << 8 ) | 0x02 ) // FDM for old Lantime Systems (M300/M600/M900) + +#define USB_DEV_MDU300 ( ( MBG_USB_CLASS_MDU << 8 ) | 0x01 ) +#define USB_DEV_MDU312 ( ( MBG_USB_CLASS_MDU << 8 ) | 0x02 ) + +#define USB_DEV_LUE_01 ( ( MBG_USB_CLASS_LUE << 8 ) | 0x01 ) + +#define USB_DEV_HPS100 ( ( MBG_USB_CLASS_HPS << 8 ) | 0x01 ) + +#define USB_DEV_VSG180 ( ( MBG_USB_CLASS_VSG << 8 ) | 0x01 ) + +#define USB_DEV_GTS180 ( ( MBG_USB_CLASS_GTS << 8 ) | 0x01 ) + +#define USB_DEV_GRC180 ( ( MBG_USB_CLASS_GRC << 8 ) | 0x01 ) +#define USB_DEV_GRC181 ( ( MBG_USB_CLASS_GRC << 8 ) | 0x02 ) + +#define USB_DEV_N2X180 ( ( MBG_USB_CLASS_N2X << 8 ) | 0x01 ) + +#define USB_DEV_USYNCPWR ( ( MBG_USB_CLASS_USYNC << 8 ) | 0x01 ) // MicroSync Power Supply Module + +// If new devices are defined here then appropriate definitions should also +// be added to MBG_USB_DEVICE_NAMES and DEFAULT_MBG_USB_DEVICE_NAMES. + +/** @} anchor MBG_USB_DEVICE_IDS */ + + + +/** + * @brief Device name strings for Meinberg USB devices + * + * @see @ref MBG_USB_DEVICE_IDS + * @see ::DEFAULT_MBG_USB_DEVICE_NAMES + * + * @anchor MBG_USB_DEVICE_NAMES @{ + */ + +#define USB_DEV_NAME_CPC_01 "CPC_01" +#define USB_DEV_NAME_CPC180 "CPC180" + +#define USB_DEV_NAME_TSU_01 "TSU_01" + +#define USB_DEV_NAME_USB5131 "USB5131" +#define USB_DEV_NAME_DCF600USB "DCF600USB" +#define USB_DEV_NAME_PZF180 "PZF180" + +#define USB_DEV_NAME_CMC "CMC" + +#define USB_DEV_NAME_TCR51USB "TCR51USB" +#define USB_DEV_NAME_TCR600USB "TCR600USB" +#define USB_DEV_NAME_TCR180 "TCR180" + +#define USB_DEV_NAME_MSF51USB "MSF51USB" +#define USB_DEV_NAME_MSF600USB "MSF600USB" + +#define USB_DEV_NAME_WWVB51USB "WWVB51USB" +#define USB_DEV_NAME_WVB600USB "WVB600USB" + +#define USB_DEV_NAME_SCU_USB "SCU_USB" + +#define USB_DEV_NAME_ESI_01 "ESI_01" + +#define USB_DEV_NAME_FCU_01 "FCU_01" + +#define USB_DEV_NAME_CPE_01 "CPE_01" + +#define USB_DEV_NAME_GPS180 "GPS180" + +#define USB_DEV_NAME_LNO180 "LNO180" + +#define USB_DEV_NAME_LIU_01 "LIU_01" +#define USB_DEV_NAME_LSG180 "LSG180" + +#define USB_DEV_NAME_LNE_01 "LNE_01" +#define USB_DEV_NAME_LNE180SFP "LNE180SFP" + +#define USB_DEV_NAME_MRI_01 "MRI_01" + +#define USB_DEV_NAME_BPE_01 "BPE_01" + +#define USB_DEV_NAME_RSC_01 "RSC_01" + +#define USB_DEV_NAME_SPT_01 "SPT_01" + +#define USB_DEV_NAME_REL_01 "REL_01" + +#define USB_DEV_NAME_LAN_CPU_SERIAL "LAN_CPU_SERIAL" + +#define USB_DEV_NAME_SCG_01 "SCG_01" + +#define USB_DEV_NAME_SDI_01 "SDI_01" + +#define USB_DEV_NAME_FDM180 "FDM180" +#define USB_DEV_NAME_FDM180M "FDM180M" + +#define USB_DEV_NAME_MDU300 "MDU300" +#define USB_DEV_NAME_MDU312 "MDU312" + +#define USB_DEV_NAME_LUE_01 "LUE_01" + +#define USB_DEV_NAME_HPS100 "HPS100" + +#define USB_DEV_NAME_VSG180 "VSG180" + +#define USB_DEV_NAME_GTS180 "GTS180" + +#define USB_DEV_NAME_GRC180 "GRC180" +#define USB_DEV_NAME_GRC181 "GRC181" + +#define USB_DEV_NAME_N2X180 "N2X180" + +#define USB_DEV_NAME_USYNCPWR "MICROSYNC-PWR" + +/** @} anchor MBG_USB_DEVICE_NAMES */ + + + +/** + * @brief Initializer for a table of USB device ISs and name strings + * + * Can be used e.g. to initialize an array of ::MBG_CODE_NAME_TABLE_ENTRY. + * + * @see @ref MBG_USB_DEVICE_IDS + * @see @ref MBG_USB_DEVICE_NAMES + */ +#define DEFAULT_MBG_USB_DEVICE_NAMES \ +{ \ + { USB_DEV_CPC_01, USB_DEV_NAME_CPC_01 }, \ + { USB_DEV_CPC180, USB_DEV_NAME_CPC180 }, \ + { USB_DEV_TSU_01, USB_DEV_NAME_TSU_01 }, \ + { USB_DEV_USB5131, USB_DEV_NAME_USB5131 }, \ + { USB_DEV_DCF600USB, USB_DEV_NAME_DCF600USB }, \ + { USB_DEV_CMC, USB_DEV_NAME_CMC }, \ + { USB_DEV_TCR51USB, USB_DEV_NAME_TCR51USB }, \ + { USB_DEV_TCR600USB, USB_DEV_NAME_TCR600USB }, \ + { USB_DEV_TCR180, USB_DEV_NAME_TCR180 }, \ + { USB_DEV_MSF51USB, USB_DEV_NAME_MSF51USB }, \ + { USB_DEV_MSF600USB, USB_DEV_NAME_MSF600USB }, \ + { USB_DEV_WWVB51USB, USB_DEV_NAME_WWVB51USB }, \ + { USB_DEV_WVB600USB, USB_DEV_NAME_WVB600USB }, \ + { USB_DEV_SCU_USB, USB_DEV_NAME_SCU_USB }, \ + { USB_DEV_ESI_01, USB_DEV_NAME_ESI_01 }, \ + { USB_DEV_FCU_01, USB_DEV_NAME_FCU_01 }, \ + { USB_DEV_CPE_01, USB_DEV_NAME_CPE_01 }, \ + { USB_DEV_GPS180, USB_DEV_NAME_GPS180 }, \ + { USB_DEV_LNO180, USB_DEV_NAME_LNO180 }, \ + { USB_DEV_LIU_01, USB_DEV_NAME_LIU_01 }, \ + { USB_DEV_LNE_01, USB_DEV_NAME_LNE_01 }, \ + { USB_DEV_MRI_01, USB_DEV_NAME_MRI_01 }, \ + { USB_DEV_BPE_01, USB_DEV_NAME_BPE_01 }, \ + { USB_DEV_RSC_01, USB_DEV_NAME_RSC_01 }, \ + { USB_DEV_SPT_01, USB_DEV_NAME_SPT_01 }, \ + { USB_DEV_REL_01, USB_DEV_NAME_REL_01 }, \ + { USB_DEV_LAN_CPU_SERIAL, USB_DEV_NAME_LAN_CPU_SERIAL }, \ + { USB_DEV_SCG_01, USB_DEV_NAME_SCG_01 }, \ + { USB_DEV_SDI_01, USB_DEV_NAME_SDI_01 }, \ + { USB_DEV_FDM180, USB_DEV_NAME_FDM180 }, \ + { USB_DEV_MDU300, USB_DEV_NAME_MDU300 }, \ + { USB_DEV_LUE_01, USB_DEV_NAME_LUE_01 }, \ + { USB_DEV_HPS100, USB_DEV_NAME_HPS100 }, \ + { USB_DEV_VSG180, USB_DEV_NAME_VSG180 }, \ + { USB_DEV_LNE180SFP, USB_DEV_NAME_LNE180SFP }, \ + { USB_DEV_GTS180, USB_DEV_NAME_GTS180 }, \ + { USB_DEV_GRC180, USB_DEV_NAME_GRC180 }, \ + { USB_DEV_GRC181, USB_DEV_NAME_GRC181 }, \ + { USB_DEV_N2X180, USB_DEV_NAME_N2X180 }, \ + { USB_DEV_MDU312, USB_DEV_NAME_MDU312 }, \ + { USB_DEV_PZF180, USB_DEV_NAME_PZF180 }, \ + { USB_DEV_USYNCPWR, USB_DEV_NAME_USYNCPWR }, \ + { USB_DEV_FDM180M, USB_DEV_NAME_FDM180M }, \ + { USB_DEV_LSG180, USB_DEV_NAME_LSG180 }, \ + { 0, /* end of table */ NULL } \ +} -#define USB_DEV_ESI_01 ( ( MBG_USB_CLASS_ESI << 8 ) | 0x01 ) -#define USB_DEV_FCU_01 ( ( MBG_USB_CLASS_FCU << 8 ) | 0x01 ) enum { diff --git a/src/external/bsd/meinberg/dist/mbglib/common/use_pack.h b/src/external/bsd/meinberg/dist/mbglib/common/use_pack.h index aaacd42..5edcdfe 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/use_pack.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/use_pack.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: use_pack.h 1.3 2011/01/26 10:01:41 martin REL_M $ + * $Id: use_pack.h 1.5 2012/10/12 12:40:01 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -11,6 +11,10 @@ * * ----------------------------------------------------------------------- * $Log: use_pack.h $ + * Revision 1.5 2012/10/12 12:40:01 martin + * Removed temporary changes. + * Revision 1.4 2012/10/02 18:06:25 martin + * Temporary changes to test alignment under Linux/Sparc. * Revision 1.3 2011/01/26 10:01:41 martin * Provided a way to suppress packing of structures on a project base. * Revision 1.2 2002/02/25 08:50:33 Andre diff --git a/src/external/bsd/meinberg/dist/mbglib/common/words.h b/src/external/bsd/meinberg/dist/mbglib/common/words.h index 7fff493..9cbc841 100755 --- a/src/external/bsd/meinberg/dist/mbglib/common/words.h +++ b/src/external/bsd/meinberg/dist/mbglib/common/words.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: words.h 1.27 2011/07/18 10:21:38 martin TRASH $ + * $Id: words.h 1.42 2017/07/26 14:28:50 martin REL_M $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,7 +10,51 @@ * * ----------------------------------------------------------------------- * $Log: words.h $ - * Revision 1.27 2011/07/18 10:21:38 martin + * Revision 1.42 2017/07/26 14:28:50 martin + * Fixed build for NetBSD. + * Revision 1.41 2017/07/05 12:06:35 martin + * Moved macro _int_from_size_t() here. + * Revision 1.40 2017/06/12 11:14:25 martin + * Empty _DEPRECATED_BY definition for firmware targets. + * Revision 1.39 2017/03/15 10:01:09 martin + * Added comments how to represent negative numbers in NANO_TIME + * and NANO_TIME_64 structures. + * Added macros _nano_time_zero() and _nano_time_64_zero(). + * Revision 1.38 2017/02/22 11:56:33 martin + * Made MBG_CODE_NAME_TABLE_ENTRY::code signed to + * avoid signed/unsigned warnings with some code tables. + * Revision 1.37 2017/01/27 12:24:35Z martin + * Moved STRINGIFY() macro here. + * Revision 1.36 2017/01/27 08:59:43 martin + * Fixed macro syntax. + * Revision 1.35 2016/08/05 12:17:21 martin + * Moved definitions for NANO_TIME and NANO_TIME_64 here. + * New macro _nano_time_64_negative(). + * Conditionally define _abs64() macro. + * Include <inttypes.h> for Keil ARMCC target. + * Added some conditional debugging code. + * Fixed some spelling. + * Revision 1.34 2014/10/20 12:31:20 martin + * Moved macro _isdigit() here. + * Revision 1.33 2014/05/27 10:18:35Z martin + * Finer control of which types are required for or already + * available on particular target systems. + * Added macros helpful to simplify declarations of code/name tables. + * Revision 1.32 2014/01/07 15:43:52 martin + * Define __mbg_inline for ARM firmware targets. + * Revision 1.31 2012/11/29 11:54:39Z martin + * Removed #if sizeof() definitions which may cause build errors + * with some older compilers. + * Include stdbool.h for __ARMCC_VERSION targets. + * Moved _nop_macro_fnc() definition here. + * Revision 1.30 2012/11/02 09:12:29Z martin + * Moved most feature detection code to mbg_tgt.h. + * Tried to define missing features most flexibly and portably. + * Revision 1.29 2012/07/11 16:45:45Z martin + * New macros to access individual bytes of long constants. + * Revision 1.28 2012/04/05 14:36:18Z martin + * Support CVI 2010 compiler which provides C99 types. + * Revision 1.27 2011/07/18 10:21:38Z martin * Added definition for MBG_CODE_NAME_TABLE_ENTRY which can * be used to define tables assigning strings to numeric codes. * Revision 1.26 2011/04/06 10:23:03 martin @@ -85,23 +129,38 @@ #if !defined( _IS_MBG_FIRMWARE ) -#if defined( _C166 ) || \ - defined( _CC51 ) || \ - defined( __ARM ) || \ - defined( __ARMCC_VERSION ) - #define _IS_MBG_FIRMWARE 1 -#else - #define _IS_MBG_FIRMWARE 0 -#endif - + #if defined( _C166 ) || \ + defined( _CC51 ) || \ + defined( __ARM ) || \ + defined( __ARMCC_VERSION ) + #define _IS_MBG_FIRMWARE 1 + #else + #define _IS_MBG_FIRMWARE 0 + #endif #endif + #if !_IS_MBG_FIRMWARE #include <mbg_tgt.h> +#else + #if defined( __ARMCC_VERSION ) // Keil RealView Compiler for ARM + #define __mbg_inline __inline + #include <stdint.h> + #include <inttypes.h> + #include <stdbool.h> + #define MBG_TGT_HAS_EXACT_SIZE_TYPES 1 + #else + #define MBG_TGT_MISSING_64_BIT_TYPES 1 + #endif + + #if !defined( _DEPRECATED_BY ) + #define _DEPRECATED_BY( _s ) // empty definition + #endif #endif + #ifdef _WORDS #define _ext #else @@ -111,175 +170,261 @@ /* Start of header body */ - -// The compilers below support native bit types. - -#if defined( _C166 ) || defined( _CC51 ) - #define _BIT_DEFINED 1 +#if defined( _C166 ) \ + || defined( _CC51 ) + #define _BIT_DEFINED 1 // these compilers natively support the "bit" type + #define USE_LONG_FOR_INT32 1 #endif -// Check whether the target system supports C99 fixed-size types. +#if !defined( MBG_TGT_HAS_EXACT_SIZE_TYPES ) -#if defined( MBG_TGT_LINUX ) // any Linux target + #if defined( MBG_TGT_HAS_INT_8_16_32 ) - #if defined( __KERNEL__ ) - #include <linux/types.h> - #else - #include <stdint.h> - #include <sys/types.h> - #endif + // Define C99 exact size types using non-standard exact-size types + typedef __int8 int8_t; + typedef unsigned __int8 uint8_t; - #define _C99_BIT_TYPES_DEFINED 1 + typedef __int16 int16_t; + typedef unsigned __int16 uint16_t; -#elif defined( MBG_TGT_BSD ) + typedef __int32 int32_t; + typedef unsigned __int32 uint32_t; - #include <sys/types.h> - - #define _C99_BIT_TYPES_DEFINED 1 - - // avoid inclusion of stdbool.h later - #define bit int - #define _BIT_DEFINED 1 - -#elif defined( MBG_TGT_QNX ) // QNX 4.x or QNX 6.x - - #if defined( MBG_TGT_QNX_NTO ) // QNX 6.x (Neutrino) with gcc - #include <stdint.h> - #else // QNX 4.x with Watcom C 10.6 - #include <sys/types.h> // 64 bit types not supported - #endif + #else - #define _C99_BIT_TYPES_DEFINED 1 + // Assume a 16 or 32 bit compiler which doesn't + // support exact-size types. -#endif + typedef char int8_t; + typedef unsigned char uint8_t; + typedef short int16_t; + typedef unsigned short uint16_t; + // Using #if sizeof() to determine the size of a type may not + // be supported by all preprocessors, and may even result in + // build errors if used in a conditional preprocessor section, + // so we can't use this here without compatibility problems. -// If it's not yet clear whether fixed-size types are supported, -// check the build environment which may be multi-platform. + #if defined( USE_LONG_FOR_INT32 ) + typedef long int32_t; + typedef unsigned long uint32_t; + #elif defined( USE_INT_FOR_INT32 ) + typedef int int32_t; + typedef unsigned int uint32_t; + #else + #error Need to define int32_t and uint32_t + #endif -#if !defined( _C99_BIT_TYPES_DEFINED ) + #endif - #if defined( __WATCOMC__ ) - #if __WATCOMC__ > 1230 // Open Watcom C 1.3 and above - #include <stdint.h> - #define _C99_BIT_TYPES_DEFINED 1 - #elif defined( __WATCOM_INT64__ ) // Watcom C 11, non-QNX - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; + #if defined( MBG_TGT_MISSING_64_BIT_TYPES ) - #define _C99_BIT_TYPES_DEFINED 1 - #endif - #endif + // The build environment does not support 64 bit types. However, + // 64 bit types need to be defined to avoid build errors + // if these types are formally used in function prototypes. + // We explicitly use abnormal data types to hopefully + // cause compiler errors in case these types are + // unexpectedly used to generate real code for a target + // platform which does not support 64 bit types. + typedef void *int64_t; + typedef void *uint64_t; - #if defined( __BORLANDC__ ) - #if ( __BORLANDC__ >= 0x570 ) // at least Borland Developer Studio 2006 - #define _C99_BIT_TYPES_DEFINED 1 - #endif - #endif + #else - #if defined( __GNUC__ ) - #include <stdint.h> - #define _C99_BIT_TYPES_DEFINED 1 - #endif + // Define C99 types using non-standard exact-size types + // which are usually supported by build envonronments + // supporting 64 bit types but no C99 types. + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; - #if defined( __ARMCC_VERSION ) // Keil RealView Compiler for ARM - #include <stdint.h> - #define _C99_BIT_TYPES_DEFINED 1 #endif #endif -// If neither the target system nor the build environment define C99 fixed-size -// types define those types based on standard types with the proper sizes -// commonly used in 16/32 bit environments. -#if defined( _C99_BIT_TYPES_DEFINED ) +#if defined( MBG_TGT_MISSING_64_BIT_TYPES ) - #define MBG_TGT_HAS_64BIT_TYPES 1 + #define MBG_TGT_HAS_64BIT_TYPES 0 #else - typedef char int8_t; - typedef unsigned char uint8_t; - - typedef short int16_t; - typedef unsigned short uint16_t; + #define MBG_TGT_HAS_64BIT_TYPES 1 - typedef long int32_t; - typedef unsigned long uint32_t; + #if !defined( MBG_TGT_HAS_ABS64 ) + #define _abs64( _i ) ( (int64_t) ( ( (_i) < 0 ) ? -(_i) : (_i) ) ) + #endif +#endif - #if defined( MBG_TGT_WIN32 ) - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; - #define MBG_TGT_HAS_64BIT_TYPES 1 +// Some commonly used types - #else - // The types below are required to avoid build errors - // if these types are formally used in function prototypes. - // We explicitely use abnormal data types to hopefully - // cause compiler errors in case these types are - // unexpectedly used to generate real code for a target - // platform which does not support 64 bit types. - typedef void *int64_t; - typedef void *uint64_t; - #endif +#if !defined( _UCHAR_DEFINED ) + typedef unsigned char uchar; + #define uchar uchar +#endif +#if !defined( _USHORT_DEFINED ) + typedef unsigned short ushort; + #define ushort ushort #endif +#if !defined( _UINT_DEFINED ) + typedef unsigned int uint; + #define uint uint +#endif +#if !defined( _ULONG_DEFINED ) + typedef unsigned long ulong; + #define ulong ulong +#endif -#if !defined( MBG_TGT_HAS_64BIT_TYPES ) +#if !defined( _UDOUBLE_DEFINED ) + typedef double udouble; + #define udouble udouble +#endif - #define MBG_TGT_HAS_64BIT_TYPES 0 +#if !defined( _BYTE_DEFINED ) + typedef unsigned char byte; + #define byte byte +#endif +#if !defined( _WORD_DEFINED ) + typedef unsigned short word; + #define word word #endif +#if !defined( _LONGWORD_DEFINED ) + typedef unsigned long longword; + #define longword longword +#endif +#if !defined( _DWORD_DEFINED ) +// typedef unsigned long dword; +// #define dword dword +#endif -// Some commonly used types -typedef unsigned char uchar; +#if defined( MBG_TGT_MISSING_BOOL_TYPE ) + //#error MBG_TGT_MISSING_BOOL_TYPE is defined + // BDS/Borland C++ Builder 2006 (non-C++ mode) + // Borland C++ Builder 5 (non-C++ mode) + // BC 3.1 + // VC6 + // DDKbuild + // VS2008 +#endif -#if !defined( MBG_TGT_LINUX ) && !( defined ( MBG_TGT_NETBSD ) && defined ( MBG_TGT_KERNEL ) ) - typedef unsigned short ushort; - typedef unsigned int uint; - typedef unsigned long ulong; +#if defined( __cplusplus ) + //#error __cplusplus is defined #endif -typedef double udouble; +#if defined( __bool_true_false_are_defined ) + //#error __bool_true_false_are_defined is defined + // Keil armcc + // gcc / Linux user space + // clang / FreeBSD user space and kernel +#endif -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned long longword; -typedef unsigned long dword; -#if !defined( _BIT_DEFINED ) +#if defined( MBG_TGT_MISSING_BOOL_TYPE ) /* from mbg_tgt.h */ \ + || ( !defined( __cplusplus ) /* C++ */ \ + && !defined( __bool_true_false_are_defined ) /* C99 */ \ + && !defined( _LINUX_TYPES_H ) ) /* Linux kernel */ \ + && !( defined( MBG_TGT_NETBSD ) && defined( _SYS_TYPES_H_ ) ) /* NetBSD kernel */ - #if _C99_BIT_TYPES_DEFINED - #include <stdbool.h> + // There's no native support for a "bool" type, so we + // need a substitute. - typedef bool bit; + #if defined( _BIT_DEFINED ) + // A native "bit" type is supported, so we use it for bool. + //#error substituting bit for bool + // C166 + typedef bit bool; #else - typedef int bit; + // Fall back to "int". This is just a hack which + // may yield unexpected results with code like: + // return (bool) ( val & 0x10 ); + // A safe way of coding would be: + // return (bool) ( ( val & 0x10 ) != 0 ); + //#error substituting int for bool + // Borland C++ Builder 5 + // BC 3.1 + // VC6 + // DDKbuild + // VS2008 + typedef int bool; #endif + // Eventually provoke a build error if the build + // environment unexpectedly supports "bool" natively. + #define bool bool + #define true 1 + #define false 0 +#else + //#error native bool type supported + // Borland C++ Builder 5 and newer (C++ mode only) + // Keil armcc + // gcc / Linux user space + // gcc / Linux kernel + // clang / FreeBSD user space and kernel +#endif + + +#if !defined( _BIT_DEFINED ) + + // There's no native support for a "bit" type, so we + // need a substitute. The "bool" type would fit best + // and should be fine if it's supported natively. + // + // However, if "bool" has been substituted above + // by "int"then this is just a hack which may yield + // unexpected results with code like: + // return (bit) ( val & 0x10 ); + // A safe way of coding would be: + // return (bit) ( ( val & 0x10 ) != 0 ); + + //#error substituting bool for bit + // Keil armcc + // Borland C++ Builder 5 + // BC 3.1 + // VC6 + // DDKbuild + // VS2008 + // gcc / Linux user space + // gcc / Linux kernel + // clang / FreeBSD user space and kernel + typedef bool bit; + + // Eventually provoke a build error if the build + // environment unexpectedly supports "bit" natively. + #define bit bit + #define _BIT_REDEFINED 1 +#else + //#error native bit type supported + // C166 #endif -#define HI_BYTE( _x ) ( (_x) >> 8 ) -#define LO_BYTE( _x ) ( (_x) & 0xFF ) -#define HI_WORD( _x ) ( (_x) >> 16 ) -#define LO_WORD( _x ) ( (_x) & 0xFFFF ) +#define BYTE_0( _x ) ( (uint8_t ) ( (_x) & 0xFF ) ) +#define BYTE_1( _x ) ( (uint8_t ) ( ( ( (uint16_t) (_x) ) >> 8 ) & 0xFF ) ) +#define BYTE_2( _x ) ( (uint8_t ) ( ( ( (uint32_t) (_x) ) >> 16 ) & 0xFF ) ) +#define BYTE_3( _x ) ( (uint8_t ) ( ( ( (uint32_t) (_x) ) >> 24 ) & 0xFF ) ) + + +#define HI_BYTE( _x ) ( (uint8_t ) ( (_x) >> 8 ) ) +#define LO_BYTE( _x ) ( (uint8_t ) ( (_x) & 0xFF ) ) + +#define HI_WORD( _x ) ( (uint16_t ) ( (_x) >> 16 ) ) +#define LO_WORD( _x ) ( (uint16_t ) ( (_x) & 0xFFFF ) ) // the macros below assume little endianess // these macros expect the name of a variable @@ -336,15 +481,202 @@ typedef unsigned long dword; #endif + +#define _set_array_bit( _n, _byte_array, _max_bytes ) \ +do \ +{ \ + int byte_idx = (_n) >> 3; \ + \ + if ( byte_idx < _max_bytes ) \ + _byte_array[byte_idx] |= ( 1 << ( (_n) & 0x07 ) ); \ + \ +} while ( 0 ) + + +#define _clear_array_bit( _n, _byte_array, _max_bytes ) \ +do \ +{ \ + int byte_idx = (_n) >> 3; \ + \ + if ( byte_idx < _max_bytes ) \ + _byte_array[byte_idx] &= ~( 1 << ( (_n) & 0x07 ) ); \ + \ +} while ( 0 ) + + + +#define _isdigit( _c ) ( (_c) >= '0' && (_c) <= '9' ) + + +// A macro function which can safely be used without +// side effects as a macro doing nothing. +// This is useful to define debug macros away in +// release builds, etc. +#if !defined( _nop_macro_fnc ) + #define _nop_macro_fnc() do {} while (0) +#endif + + /** * @brief A table entry which can be used to map codes to names. */ typedef struct { - ulong code; + long code; const char *name; + } MBG_CODE_NAME_TABLE_ENTRY; +/** + * @brief A macro defining a ::MBG_CODE_NAME_TABLE_ENTRY + * + * The stringified parameter is used for the name. + * + * @param _n The symbolic name of the numeric code + */ +#define _mbg_cn_table_entry( _n ) { _n, #_n } + +/** + * @brief A macro defining an empty ::MBG_CODE_NAME_TABLE_ENTRY + * + * This is used to terminate a table. + */ +#define _mbg_cn_table_end() { 0, NULL } + + + +/** + * @brief A timestamp with nanosecond resolution + * + * @note If the structure is to represent a negative value then both the + * fields nano_secs and secs have to be set to the negative values. + * Otherwise the sign of the represented number was ambiguous if either + * of the fields was accidentally 0, and only the other field was not 0. + * The macro ::_nano_time_negative should always be used to determine + * if the sign of the represented value is negative, or not. + * + * @note The secs field will roll over on 2038-01-19 03:14:07 + * if used for the number of seconds since 1970-01-01, just like + * 32 bit POSIX time_t. + * + * @see ::_nano_time_negative + * @see ::_nano_time_zero + * @see ::NANO_TIME_64 + */ +typedef struct +{ + // ATTENTION: + // This structure is and has has been used in public API calls for a long time, + // so even though the order of member fields is different than in NANO_TIME_64 + // this must *NOT* be changed, or API compatibility will get lost! + int32_t nano_secs; ///< [nanoseconds] + int32_t secs; ///< [seconds], usually since 1970-01-01 00:00:00 + +} NANO_TIME; + +#define _mbg_swab_nano_time( _p ) \ +do \ +{ \ + _mbg_swab32( &(_p)->nano_secs ); \ + _mbg_swab32( &(_p)->secs ); \ +} while ( 0 ) + +/** + * Check if the value of the ::NANO_TIME structure _nt is negative + */ +#define _nano_time_negative( _nt ) \ + ( ( (_nt)->secs < 0 ) || ( (_nt)->nano_secs < 0 ) ) + +/** + * Check if the value of the ::NANO_TIME structure _nt is 0 + */ +#define _nano_time_zero( _nt ) \ + ( ( (_nt)->secs == 0 ) && ( (_nt)->nano_secs == 0 ) ) + + + +/** + * @brief A timestamp with nanosecond resolution, but 64 bit size + * + * @note If the structure is to represent a negative value then both the + * fields nano_secs and secs have to be set to the negative values. + * Otherwise the sign of the represented number was ambiguous if either + * of the fields was accidentally 0, and only the other field was not 0. + * The macro ::_nano_time_64_negative should always be used to determine + * if the sign of the represented value is negative, or not. + * + * @see ::_nano_time_64_negative + * @see ::_nano_time_64_zero + * @see ::NANO_TIME + */ +typedef struct +{ + // ATTENTION: + // This structure is and has been used in public API calls for a long time, + // so even though the order of member fields is different than in NANO_TIME + // this must *NOT* be changed, or API compatibility will get lost! + int64_t secs; ///< [seconds], usually since 1970-01-01 00:00:00 + int64_t nano_secs; ///< [nanoseconds] + +} NANO_TIME_64; + +#define _mbg_swab_nano_time_64( _p ) \ +do \ +{ \ + _mbg_swab64( &(_p)->secs ); \ + _mbg_swab64( &(_p)->nano_secs ); \ +} while ( 0 ) + +/** + * Check if the value of the ::NANO_TIME_64 structure _nt is negative + */ +#define _nano_time_64_negative( _nt ) \ + ( ( (_nt)->secs < 0 ) || ( (_nt)->nano_secs < 0 ) ) + +/** + * Check if the value of the ::NANO_TIME_64 structure _nt is 0 + */ +#define _nano_time_64_zero( _nt ) \ + ( ( (_nt)->secs == 0 ) && ( (_nt)->nano_secs == 0 ) ) + + + +// The size_t type can eventually be larger than an int type. +// However, some snprintf-like functions expect a size_t value +// to specify the buffer size, but just return an int value. +// So we take care that at least the return value is limited +// to MAXINT. +#if defined( MBG_TGT_WIN32 ) + #define _int_from_size_t( _n ) \ + ( ( (_n) > INT_MAX ) ? INT_MAX : (int) (_n) ) +#else + #define _int_from_size_t( _n ) (_n) +#endif + + + +/** + * @brief Make a string from a constant definition + * + * This macro can be used e.g. to define a constant string on the + * compiler's command line, e.g. like -DVERSION_STRING="v1.0 BETA". + * Source code like + * @code{.c} + const char version_string[] = VERSION_STRING; + * @endcode + * + * may not work for every compiler since the double quotes + * in VERSION_STRING may be removed when the definition is evaluated. + * A proper solution is to use the STRINGIFY() macro defined here: + * @code{.c} + const char version_string[] = STRINGIFY( VERSION_STRING ); + * @endcode + */ +#define STRINGIFY(x) XSTRINGIFY(x) + +// The XSTRINGIFY() macro is just a helper macro to implement STRINGIFY() +// and should not be used alone. +#define XSTRINGIFY(x) #x /* End of header body */ diff --git a/src/external/bsd/meinberg/dist/mbglib/common/xdevfeat.h b/src/external/bsd/meinberg/dist/mbglib/common/xdevfeat.h new file mode 100755 index 0000000..19cc633 --- /dev/null +++ b/src/external/bsd/meinberg/dist/mbglib/common/xdevfeat.h @@ -0,0 +1,893 @@ + +/************************************************************************** + * + * $Id: xdevfeat.h 1.2 2017/07/06 07:49:25 martin REL_M $ + * + * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany + * + * Description: + * Definitions and prototypes for xdevfeat.c. + * + * ----------------------------------------------------------------------- + * $Log: xdevfeat.h $ + * Revision 1.2 2017/07/06 07:49:25 martin + * Added some macros and inline function simplifying + * implementation of the individual check functions. + * Updated function prototypes. + * Revision 1.1 2016/03/16 14:32:52 martin + * Initial revision. + * + **************************************************************************/ + +#ifndef _XDEVFEAT_H +#define _XDEVFEAT_H + + +/* Other headers to be included */ + +#include <gpsdefs.h> +#include <mbgerror.h> + +#ifdef _XDEVFEAT + #define _ext + #define _DO_INIT +#else + #define _ext extern +#endif + + +/* Start of header body */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup chk_supp_fncs Groups of functions used to check if a particular feature is supported + * + * Each of these functions can be used to check if a device supports a particular + * feature. ::MBG_SUCCESS is returned if the requested feature is supported, + * otherwise one of the @ref MBG_ERROR_CODES is returned, as appropriate. + * + * Some features are supported by a device if an associated bit is set in the + * ::RECEIVER_INFO::features field, but since the number of bits in this field + * is limited, newer feature bits are defined in a ::MBG_XFEATURE_BUFFER. + * Finally there are some builtin features which may be implicitly supported + * by a particular device model, or not. + * + * These functions provide a unified API for all feature types to make + * application code more straightforward. + * + * If the mbgextio API is used then a ::MBG_XDEV_FEATURES structure embedded in + * the ::MBG_MSG_CTL structure is set up automatically when the device is opened, + * and there are mbgextio_... wrapper functions available which just expect the + * MBG_MSG_CTL * associated with the device to check if a feature is supported. + * See @ref mbgextio_chk_supp_fncs. + * + * Other implementations which retrieve the ::MBG_XDEV_FEATURES structure of + * a device in a different way can use some lower level functions. + * See @ref xdevfeat_chk_supp_fncs. + */ + + +/** + * @defgroup xdevfeat_chk_supp_fncs Low level functions used to check if a particular feature is supported + * @ingroup chk_supp_fncs + * + * @note Applications using the mbgextio API should use the mbgextio_ wrapper + * functions preferably. See @ref mbgextio_chk_supp_fncs. + */ + + +/** + * @brief A structure combining all device feature information + */ +typedef struct +{ + uint32_t reserved; ///< Currently reserved, unused, always 0 + RECEIVER_INFO receiver_info; ///< Receiver info provided by the device + MBG_XFEATURE_BUFFER xfeature_buffer; ///< Extended features provided by the device + MBG_TLV_INFO tlv_info; ///< TLV info provided by a device + +} MBG_XDEV_FEATURES; + + + +/** + * @brief Type of functions to check if a feature is supported + */ +typedef int _NO_MBG_API XDEVFEAT_CHK_SUPP_FNC( const MBG_XDEV_FEATURES *p_xdf ); + + + +/** + * @brief Check if all bits of a specific mask are set in an integer bit mask + * + * This macros checks if specific bits are set in an integer bit mask. + * This is implemented as macro since the macro works properly with + * all integer sizes. + * + * @param[in] _supp_msk An integer bit mask + * @param[in] _chk_msk The bit mask to be tested + * + * @return ::MBG_SUCCESS if all bits of the test mask are set, or + * ::MBG_ERR_NOT_SUPP_BY_DEV if not. + */ +#define _check_feat_supp_mask( _supp_msk, _chk_msk ) \ + ( ( ( (_supp_msk) & (_chk_msk) ) == (_chk_msk) ) ? \ + MBG_SUCCESS : MBG_ERR_NOT_SUPP_BY_DEV ) + + + +/** + * @brief Check if a bits with a specific number is set in an integer bit mask + * + * This macros checks if a bits with specific number is set in an integer bit mask. + * This is implemented as macro since the macro works properly with + * all integer sizes. + * + * @param[in] _supp_msk An integer bit mask + * @param[in] _bit_num The bit mask to be tested + * + * @return ::MBG_SUCCESS if all bits of the test mask are set, or + * ::MBG_ERR_NOT_SUPP_BY_DEV if not. + */ +#define _check_feat_supp_bit( _supp_msk, _bit_num ) \ + ( ( (_supp_msk) & ( 1UL << (_bit_num) ) ) ? \ + MBG_SUCCESS : MBG_ERR_NOT_SUPP_BY_DEV ) + + + +static __mbg_inline /*HDR*/ +/** + * @brief Check if a specific bit is set in a byte array + * + * This function checks if a specific bit is set in an array of bytes. + * Bits are counted starting from the least significant bit of the least + * significant byte. + * + * @param[in] bit_num Number of the bit to be tested, 0..(8*(max_bytes-1)) + * @param[in] p Pointer to a buffer with an array of bytes + * @param[in] max_bytes The number of bytes in the buffer p + * + * @return ::MBG_SUCCESS if the bit is set, ::MBG_ERR_NOT_SUPP_BY_DEV if not, + * or ::MBG_ERR_RANGE if the bit number is out of the range of the array + */ +int check_feat_supp_byte_array( int bit_num, const uint8_t *p, int max_bytes ) +{ + int byte_num = bit_num >> 3; + + if ( byte_num < max_bytes ) // the normal case + { + ulong bit_mask = 1UL << ( bit_num & 0x07 ); + + return ( p[byte_num] & bit_mask ) ? MBG_SUCCESS : MBG_ERR_NOT_SUPP_BY_DEV; + } + + return MBG_ERR_RANGE; + +} // check_feat_supp_byte_array + + + +/* ----- function prototypes begin ----- */ + +/* This section was generated automatically */ +/* by MAKEHDR, do not remove the comments. */ + + /** + * @brief Check if a device can receive the GPS satellite system + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_dev_is_gps + * @see ::mbg_chk_dev_is_gps + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_is_gps( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the GNSS API + * + * This is usually supported by devices which can receive signals + * from different satellite systems, e.g. GPS, GLONASS, ... + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_dev_is_gnss + * @see ::mbg_chk_dev_is_gnss + * @see ::MBG_GNSS_TYPES + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_is_gnss( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device is a time code receiver (IRIG or similar) + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_dev_is_tcr + * @see ::mbg_chk_dev_is_tcr + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_is_tcr( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device is a DCF77 AM receiver + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_dev_is_dcf + * @see ::mbg_chk_dev_is_dcf + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_is_dcf( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device can receive DCF77 PZF + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_dev_has_pzf + * @see ::mbg_chk_dev_has_pzf + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_pzf( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device is an MSF receiver + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_is_msf( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device is a JJY receiver + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_is_jjy( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device is a WWVB receiver + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_is_wwvb( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device is a bus level device + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_is_bus_lvl_dev( const MBG_XDEV_FEATURES *p_xdf ) ; + + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_ims( const MBG_XDEV_FEATURES *p_xdf ) ; + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_gpio( const MBG_XDEV_FEATURES *p_xdf ) ; + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_synth( const MBG_XDEV_FEATURES *p_xdf ) ; + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_prog_pulses( const MBG_XDEV_FEATURES *p_xdf ) ; + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_irig_tx( const MBG_XDEV_FEATURES *p_xdf ) ; + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_irig_rx( const MBG_XDEV_FEATURES *p_xdf ) ; + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_serouts( const MBG_XDEV_FEATURES *p_xdf ) ; + /** + * @brief Check if a device supports the ::BVAR_STAT structure and API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_bvar_stat( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports reading the position as ::XYZ array + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_pos_xyz( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports reading the position as ::LLA array + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_pos_lla( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if the device supports the builtin feature TIME + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_time_ttm( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the ::MBG_TIME_SCALE_INFO structure and API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_ri_feature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_get_time_scale_info + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_time_scale( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the ::TZDL structure and API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_tzdl( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the ::TZCODE API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_tzcode( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the ::ANT_INFO structure and API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_ant_info( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the ::ENABLE_FLAGS structure and API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_enable_flags( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the ::STAT_INFO structure and API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_gps_stat_info( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the ::ANT_CABLE_LEN structure and API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_ant_cable_length( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the ::IGNORE_LOCK structure and API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_gps_ignore_lock( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if the device supports the SCU_STAT structures + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + * @see @ref group_scu + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_scu_stat( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if the device supports the SV_INFO structures + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else ::MBG_ERR_NOT_SUPP_BY_DEV + * or ::MBG_ERR_DEV_NOT_SUPP (see @ref xdevfeat_chk_supp_fncs) + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_sv_info( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a timecode receiver provides ::MBG_RAW_IRIG_DATA + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_ri_feature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_get_raw_irig_data + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_raw_irig_data( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the old LAN_IP4 API + * + * The LAN_IP4 API provides structures and functions to configure + * parts of the networking of a device and is superseded by the + * NET_CFG API. Some devices combine NET_CFG and LAN_IP4. + * Therefore, ::mbgextio_get_all_net_cfg_info should be used + * preferably to read the network configuration. + * It will translate the old structures into the new ones. + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_ri_feature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_get_all_net_cfg_info + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_lan_ip4( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the new NET_CFG API + * + * The NET_CFG API provides structures and functions to configure + * the complete networking part of a device and supersedes the + * LAN_IP4 API. Not all devices support the whole feature set + * of the NET_CFG API or combine NET_CFG and LAN_IP4. + * Therefore, ::mbgextio_get_all_net_cfg_info should be used + * preferably to read the network configuration. + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_ri_feature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_get_all_net_cfg_info + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_net_cfg( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the PTP API + * + * The PTP API consists of different calls and associated structures + * which * have evolved over time. Not all devices support every call, + * so ::mbgextio_get_all_ptp_cfg_info takes care to check which parts are + * supported and thus should be used preferably to read PTP information. + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_ri_feature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_get_all_ptp_cfg_info + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_ptp( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the NTP API + * + * The NTP API consists of different calls and associated structures + * which have evolved over time. Not all devices support every call, + * so ::mbgextio_get_all_ntp_cfg_info takes care to check which parts are + * supported and thus should be used preferably to read NTP information. + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_ri_feature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_get_all_ntp_cfg_info + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_ntp( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the event log API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_ri_feature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_evt_log( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the USB lock feature, see ::MBG_XFEATURE_USB_LOCK + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_xfeature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref group_usb_lock + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_usb_lock( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the user capture API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_ri_feature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_ucap( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the user capture via network feature + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_xfeature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref group_ucap_net + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_ucap_net( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the TLV API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_xfeature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref group_tlv_api + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_tlv_api( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports a firmware update via TLV + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_tlv_feat_supp + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_xmt_fw_update + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_supp_tlv_fw_update( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports creating / sending a diagnostics file via TLV + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_tlv_feat_supp + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::TODO //refer to get diag function + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_supp_tlv_diag_file( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports PTPv2 license infos + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_tlv_feat_supp + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_supp_tlv_ptpv2_license( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports NTP license infos via TLV + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_tlv_feat_supp + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_supp_tlv_ntp_license( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports PTPv1 License Infos via TLV + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_tlv_feat_supp + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_supp_tlv_ptpv1_license( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports Time Monitor License infos via TLV + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_tlv_feat_supp + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_supp_tlv_time_monitor_license( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports UFU (Unified Firmware Update) via TLV + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_tlv_feat_supp + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_supp_tlv_ufu( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the ::GPS_SAVE_CFG command + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_xfeature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_cmd_save_cfg + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_cmd_save_cfg( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the extended feature monitoring + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_xfeature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_monitoring( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the LED API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_xfeature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::TODO ### + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_led_api( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the LNE API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_xfeature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::TODO ### + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_lne_api( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the power control API + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_xfeature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::TODO ### + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_pwr_ctl_api( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the ::MBG_EXT_SYS_INFO command + * + * @param[in,out] p_xdf Pointer to a valid message control structure + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_xfeature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::TODO ### + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_ext_sys_info( const MBG_XDEV_FEATURES *p_xdf ) ; + + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_io_ports( const MBG_XDEV_FEATURES *p_xdf ) ; + /** + * @brief Check if a device has ::MBG_XFEATURE_TRANSACTIONS + * + * @param[in,out] p_xdf Pointer to a valid message control structure + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_xfeature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::TODO ### + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_transactions( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device has ::MBG_XFEATURE_REBOOT + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_xfeature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_reboot( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device has ::MBG_XFEATURE_REQ_TTM + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_xfeature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + * @see mbgextio_get_time + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_req_ttm( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the extended multi ref features including multi instances + * + * The different multi ref feature and its appropriate flags have evolved over time. + * This function only checks the currently up-to-date GPS_HAS_XMRS_MULT_INSTC flag. + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_ri_feature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see ::mbgextio_get_all_xmulti_ref_info + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_xmulti_ref( const MBG_XDEV_FEATURES *p_xdf ) ; + + /** + * @brief Check if a device supports the extended binary protocol (XBP) feature + * + * @param[in,out] p_xdf Pointer to a ::MBG_XDEV_FEATURES buffer associated with the device + * + * @return ::MBG_SUCCESS if supported, else error code from ::check_ri_feature + * + * @ingroup xdevfeat_chk_supp_fncs + * @see @ref xdevfeat_chk_supp_fncs + */ + _NO_MBG_API_ATTR int _NO_MBG_API xdevfeat_has_xbp( const MBG_XDEV_FEATURES *p_xdf ) ; + + +/* ----- function prototypes end ----- */ + +#ifdef __cplusplus +} +#endif + +/* End of header body */ + +#undef _ext +#undef _DO_INIT + +#endif /* _XDEVFEAT_H */ diff --git a/src/external/bsd/meinberg/dist/mbgsetsystime/Makefile b/src/external/bsd/meinberg/dist/mbgsetsystime/Makefile index 07ec4e4..b0e6c89 100755 --- a/src/external/bsd/meinberg/dist/mbgsetsystime/Makefile +++ b/src/external/bsd/meinberg/dist/mbgsetsystime/Makefile @@ -1,15 +1,18 @@ ######################################################################### # -# $Id: Makefile 1.8.1.2 2010/08/30 09:05:23 martin TEST $ +# $Id: Makefile 1.9.1.1 2017/07/26 14:30:28 martin TEST $ # # Description: # Makefile for mbgsetsystime. # # ----------------------------------------------------------------------- # $Log: Makefile $ -# Revision 1.8.1.2 2010/08/30 09:05:23 martin -# Revision 1.8.1.1 2010/08/30 08:21:54 martin +# Revision 1.9.1.1 2017/07/26 14:30:28 martin +# Removed lines that are not required / supported with *BSD. +# Revision 1.9 2017/07/05 18:26:10 martin +# Updated list of object files and use top level +# Makefile properly. # Revision 1.8 2009/07/24 10:31:17 martin # Moved declarations to a common file which is now included. # Revision 1.7 2008/12/22 11:56:59 martin @@ -30,11 +33,15 @@ ######################################################################### TARGET = mbgsetsystime -INST_DIR = /usr/local/sbin +INST_TO_SBIN = 1 OBJS = $(TARGET).o OBJS += mbgdevio.o +OBJS += timeutil.o +OBJS += str_util.o OBJS += toolutil.o +OBJS += mbgerror.o +OBJS += cfg_hlp.o OBJS += gpsutils.o OBJS += mbgmktm.o OBJS += pcpsmktm.o diff --git a/src/external/bsd/meinberg/dist/mbgsetsystime/mbgsetsystime.c b/src/external/bsd/meinberg/dist/mbgsetsystime/mbgsetsystime.c index 62b57ac..62068be 100755 --- a/src/external/bsd/meinberg/dist/mbgsetsystime/mbgsetsystime.c +++ b/src/external/bsd/meinberg/dist/mbgsetsystime/mbgsetsystime.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgsetsystime.c 1.8.1.2 2011/07/05 15:35:55 martin TRASH martin $ + * $Id: mbgsetsystime.c 1.9 2017/07/05 18:24:44 martin REL_M $ * * Description: * Main file for mbgsetsystime program which reads the current date @@ -14,10 +14,14 @@ * * ----------------------------------------------------------------------- * $Log: mbgsetsystime.c $ - * Revision 1.8.1.2 2011/07/05 15:35:55 martin - * Modified version handling. - * Revision 1.8.1.1 2011/07/05 14:36:01 martin + * Revision 1.9 2017/07/05 18:24:44 martin * New way to maintain version information. + * Support build under Windows. + * Use high resolution time if the device supports it. + * Use codes and inline functions from mbgerror.h. + * Use functions from new module timeutil. + * Account for frac_sec_from_bin() obsoleted by bin_frac_32_to_dec_frac(). + * Proper return codes and exit codes. * Revision 1.8 2009/09/29 15:02:15 martin * Updated version number to 3.4.0. * Revision 1.7 2009/07/24 09:50:09 martin @@ -45,14 +49,16 @@ // include Meinberg headers #include <mbgdevio.h> #include <pcpsmktm.h> +#include <pcpsutil.h> #include <toolutil.h> +#include <timeutil.h> +#include <str_util.h> +#include <mbgerror.h> // include system headers #include <stdio.h> #include <stdlib.h> -#include <unistd.h> -#include <sys/time.h> #include <sys/types.h> @@ -65,66 +71,244 @@ static const char *pname = "mbgsetsystime"; static /*HDR*/ -void set_system_time( PCPS_TIME *tp ) +size_t sn_printf_timespec( char *s, size_t max_len, const struct timespec *p_ts ) { - struct timeval tv_set; + struct tm tm = { 0 }; + int rc = mbg_gmtime( &tm, &p_ts->tv_sec ); + if ( mbg_rc_is_error( rc ) ) // conversion failed + return sn_cpy_str_safe( s, max_len, "(invalid time)" ); - tv_set.tv_sec = pcps_mktime( tp ); - tv_set.tv_usec = (ulong) tp->sec100 * 10000; - settimeofday( &tv_set, NULL ); + return snprintf_safe( s, max_len, "%04i-%02i-%02i %02i:%02i:%02i.%09li UTC", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, + (long) p_ts->tv_nsec ); - printf( "Date/time set to %02u.%02u.%02u %02u:%02u:%02u.%02u (UTC %+02ih)\n", - tp->mday, tp->month, tp->year, - tp->hour, tp->min, tp->sec, tp->sec100, - tp->offs_utc - ); +} // sn_printf_timespec + + + +static /*HDR*/ +int set_system_time( const struct timespec *p_ts ) +{ + char ws[100]; + +#if defined( MBG_TGT_WIN32 ) + #define clock_settime mbg_clock_settime //### TODO cleanup +#endif + + int rc = clock_settime( CLOCK_REALTIME, p_ts ); + + sn_printf_timespec( ws, sizeof( ws ), p_ts ); + + if ( rc < 0 ) // usually 0 on success, -1 on error + { + rc = mbg_get_last_error( NULL ); + + fprintf( stderr, "Failed to set system time to %s: %s\n", ws, mbg_strerror( rc ) ); + return rc; + } + + printf( "Date/time set to %s\n", ws ); + + return MBG_SUCCESS; } // set_system_time static /*HDR*/ -int do_mbgsetsystime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) +int set_system_time_from_pcps_time( const PCPS_TIME *p_t ) { - static int system_time_has_been_set; - - PCPS_TIME t; - int ret_val = 0; + struct tm tm = { 0 }; + time_t t_rev; + time_t t; int rc; - if ( system_time_has_been_set ) - goto done; + t = pcps_mktime( p_t ); + + if ( t == (time_t) -1 ) // error + { + fprintf( stderr, "Failed to convert %02u.%02u.%02u %02u:%02u:%02u.%02u (UTC%+02ih) to system time\n", + p_t->mday, p_t->month, p_t->year, + p_t->hour, p_t->min, p_t->sec, p_t->sec100, + p_t->offs_utc + ); + return MBG_ERR_OVERFLOW; + } - rc = mbg_get_time( dh, &t ); + t_rev = t + p_t->offs_utc * SECS_PER_HOUR; - if ( mbg_ioctl_err( rc, "mbg_get_time" ) ) + rc = mbg_gmtime( &tm, &t_rev ); + + if ( mbg_rc_is_error( rc ) ) + return rc; + + if ( ( tm.tm_year % 100 != p_t->year ) || + ( tm.tm_mon + 1 != p_t->month ) || + ( tm.tm_mday != p_t->mday ) || + ( tm.tm_hour != p_t->hour ) || + ( tm.tm_min != p_t->min ) || + ( tm.tm_sec != p_t->sec ) ) { - ret_val = -2; - goto done; + fprintf( stderr, "reversely computed date/time differs from original\n" ); + return MBG_ERR_RANGE; + } + + #if defined( MBG_TGT_WIN32 ) + { + SYSTEMTIME st; + + union + { + FILETIME ft; + ULONGLONG ull; + } u; + + // Convert seconds and fractions to 100 ns units. + u.ull = FILETIME_1970 + + (ULONGLONG) t * 10 * 1000 * 1000 + + (ULONGLONG) (ulong) p_t->sec100 * 100000; + + if ( !FileTimeToSystemTime( &u.ft, &st ) ) + { + int err = mbg_win32_last_err_to_mbg( GetLastError(), NULL ); + + fprintf( stderr, "Failed to convert FILETIME to system time: %s\n", + mbg_strerror( err ) ); + return err; + } + + if ( !SetSystemTime( &st ) ) + { + #if 0 + LPVOID lpMsgBuf; + DWORD last_error = GetLastError(); + + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + last_error, + MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + fprintf( stderr, "Failed to set system time: %s (code 0x%08lX)\n", + lpMsgBuf, (ulong) last_error ); + + // Free the buffer. + LocalFree( lpMsgBuf ); + #else + int err = mbg_win32_last_err_to_mbg( GetLastError(), NULL ); + + fprintf( stderr, "Failed to set system time: err %i\n", err ); + #endif + return err; + } + + return MBG_SUCCESS; } + #else // assuming POSIX + { + struct timespec ts; + + ts.tv_sec = t; + ts.tv_nsec = (long) p_t->sec100 * ( NSECS_PER_SEC / 100 ); // convert to nanoseconds + + return set_system_time( &ts ); + } + #endif + +} // set_system_time_from_pcps_time + + + +static /*HDR*/ +int do_set_system_time_from_pcps_time( MBG_DEV_HANDLE dh ) +{ + PCPS_TIME t; + + int rc = mbg_get_time( dh, &t ); + + if ( mbg_cond_err_msg( rc, "mbg_get_time" ) ) + return rc; if ( t.status & PCPS_INVT ) { // This may happen if the radio clock's battery - // was low or disconnected. + // has been discharged or disconnected. printf( "Radio clock has no valid date/time.\n" ); - ret_val = -1; - goto done; + return MBG_ERR_INV_TIME; } - set_system_time( &t ); - system_time_has_been_set = 1; + rc = set_system_time_from_pcps_time( &t ); + + return rc; + +} // do_set_system_time_from_pcps_time + + + +static /*HDR*/ +int do_set_system_time_from_pcps_hr_time( MBG_DEV_HANDLE dh ) +{ + PCPS_HR_TIME ht; + struct timespec ts = { 0 }; + + int rc = mbg_get_hr_time( dh, &ht ); + + if ( mbg_cond_err_msg( rc, "mbg_get_hr_time" ) ) + return rc; + + if ( ht.status & PCPS_INVT ) + { + // This may happen if the radio clock's battery + // has been discharged or disconnected. + printf( "Radio clock has no valid date/time.\n" ); + return MBG_ERR_INV_TIME; + } + + ts.tv_sec = ht.tstamp.sec; + ts.tv_nsec = bin_frac_32_to_dec_frac( ht.tstamp.frac, NSECS_PER_SEC ); + + return set_system_time( &ts ); + +} // do_set_system_time_from_pcps_hr_time + + + +static /*HDR*/ +int do_mbgsetsystime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) +{ + static int system_time_has_been_set; + + int rc = MBG_SUCCESS; + + if ( system_time_has_been_set ) + goto done; + + rc = mbg_chk_dev_has_hr_time( dh ); + + if ( mbg_rc_is_success( rc ) ) + rc = do_set_system_time_from_pcps_hr_time( dh ); + else + rc = do_set_system_time_from_pcps_time( dh ); + + if ( mbg_rc_is_success( rc ) ) + system_time_has_been_set = 1; puts( "" ); done: - mbg_close_device( &dh ); - - return 0; + return rc; } // do_mbgsetsystime +static MBG_DEV_HANDLER_FNC do_mbgsetsystime; + static /*HDR*/ @@ -132,7 +316,8 @@ void usage( void ) { mbg_print_usage_intro( pname, "This program can be used to set the system time to the card's time.\n" - "This should be done only at boot time, before the NTP daemon is started." + "This should be done only at boot time, before the NTP daemon is started.\n" + "Please *don't* run this program while ntpd is already active." ); mbg_print_help_options(); mbg_print_device_options(); @@ -164,15 +349,19 @@ int main( int argc, char *argv[] ) if ( must_print_usage ) { usage(); - return 1; + return MBG_EXIT_CODE_USAGE; } - // The function below checks which devices have been specified - // on the command, and for each device - // - tries to open the device - // - shows basic device info - // - calls the function passed as last parameter - rc = mbg_check_devices( argc, argv, optind, do_mbgsetsystime ); + // Handle each of the specified devices. + rc = mbg_handle_devices( argc, argv, optind, do_mbgsetsystime, 0 ); + + // determine the exit code based on the return code + + if ( mbg_rc_is_success( rc ) ) + return MBG_EXIT_CODE_SUCCESS; // success + + if ( rc == MBG_ERR_INV_TIME ) + return MBG_EXIT_CODE_INV_TIME; // device has no valid time to set the system time with - return abs( rc ); + return MBG_EXIT_CODE_FAIL; // any error occurred } diff --git a/src/external/bsd/meinberg/dist/mbgshowsignal/Makefile b/src/external/bsd/meinberg/dist/mbgshowsignal/Makefile index c10b915..7bc355d 100755 --- a/src/external/bsd/meinberg/dist/mbgshowsignal/Makefile +++ b/src/external/bsd/meinberg/dist/mbgshowsignal/Makefile @@ -1,15 +1,16 @@ ######################################################################### # -# $Id: Makefile 1.7.1.2 2010/08/30 09:05:23 martin TEST $ +# $Id: Makefile 1.8 2017/07/05 18:26:51 martin REL_M $ # # Description: # Makefile for mbgshowsignal. # # ----------------------------------------------------------------------- # $Log: Makefile $ -# Revision 1.7.1.2 2010/08/30 09:05:23 martin -# Revision 1.7.1.1 2010/08/30 08:22:00 martin +# Revision 1.8 2017/07/05 18:26:51 martin +# Updated list of object files and use top level +# Makefile properly. # Revision 1.7 2009/07/24 10:31:17 martin # Moved declarations to a common file which is now included. # Revision 1.6 2008/12/22 11:56:59 martin @@ -28,11 +29,15 @@ ######################################################################### TARGET = mbgshowsignal -INST_DIR = /usr/local/bin +INST_TO_BIN = 1 OBJS = $(TARGET).o OBJS += mbgdevio.o +OBJS += timeutil.o +OBJS += str_util.o OBJS += toolutil.o +OBJS += mbgerror.o +OBJS += cfg_hlp.o OBJS += gpsutils.o BASEDIR := .. diff --git a/src/external/bsd/meinberg/dist/mbgshowsignal/mbgshowsignal.c b/src/external/bsd/meinberg/dist/mbgshowsignal/mbgshowsignal.c index d8f39c1..f08bd95 100755 --- a/src/external/bsd/meinberg/dist/mbgshowsignal/mbgshowsignal.c +++ b/src/external/bsd/meinberg/dist/mbgshowsignal/mbgshowsignal.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgshowsignal.c 1.8.1.3 2011/07/05 15:35:55 martin TRASH martin $ + * $Id: mbgshowsignal.c 1.9 2017/07/05 18:31:14 martin REL_M $ * * Description: * Main file for mbgshowsignal program which demonstrates how to @@ -10,12 +10,13 @@ * * ----------------------------------------------------------------------- * $Log: mbgshowsignal.c $ - * Revision 1.8.1.3 2011/07/05 15:35:55 martin - * Modified version handling. - * Revision 1.8.1.2 2011/07/05 14:35:19 martin + * Revision 1.9 2017/07/05 18:31:14 martin * New way to maintain version information. - * Revision 1.8.1.1 2011/07/04 13:19:04 martin + * Support build under Windows. * Update modulation status continuously. + * Show PZF correlation state. + * Use codes and inline functions from mbgerror.h. + * Proper return codes and exit codes. * Revision 1.8 2009/09/29 15:02:15 martin * Updated version number to 3.4.0. * Revision 1.7 2009/07/24 09:50:09 martin @@ -43,11 +44,9 @@ // include Meinberg headers #include <mbgdevio.h> -#include <pcpsutil.h> #include <toolutil.h> // common utility functions // include system headers -#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <time.h> @@ -69,10 +68,13 @@ int show_modulation( MBG_DEV_HANDLE dh ) PCPS_STATUS_PORT status_port; // current value of the clock's status port PCPS_TIME t; int signal; + + bool dev_has_pzf = mbg_chk_dev_has_pzf( dh ) == MBG_SUCCESS; + int rc = mbg_get_status_port( dh, &status_port ); // read status port - if ( mbg_ioctl_err( rc, "mbg_get_status_port" ) ) - return -1; + if ( mbg_cond_err_msg( rc, "mbg_get_status_port" ) ) + return rc; // show signal only once per second sys_t = time( NULL ); @@ -81,8 +83,8 @@ int show_modulation( MBG_DEV_HANDLE dh ) { rc = mbg_get_time( dh, &t ); - if ( mbg_ioctl_err( rc, "mbg_get_time" ) ) - return -1; + if ( mbg_cond_err_msg( rc, "mbg_get_time" ) ) + return rc; prv_sys_t = sys_t; } @@ -99,9 +101,14 @@ int show_modulation( MBG_DEV_HANDLE dh ) if ( signal > PCPS_SIG_MAX ) signal = PCPS_SIG_MAX; - printf( " Signal: %u%% ", signal * 100 / PCPS_SIG_MAX ); + printf( " Signal: %u%% ", signal * 100 / PCPS_SIG_MAX ); + + if ( dev_has_pzf ) + rc = mbg_show_pzf_corr_info( dh, 1 ); + + printf( " " ); - return 0; + return rc; } // show_modulation @@ -110,32 +117,27 @@ int show_modulation( MBG_DEV_HANDLE dh ) static /*HDR*/ int do_mbgshowsignal( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) { - int has_mod = 0; - int rc = mbg_dev_has_mod( dh, &has_mod ); + int rc = mbg_chk_dev_has_mod( dh ); - if ( mbg_ioctl_err( rc, "mbg_dev_has_mod" ) ) - goto fail; - - if ( !has_mod ) + if ( mbg_rc_is_error( rc ) ) { - printf( "This device does not support monitoring signal modulation.\n" ); - goto done; + mbg_cond_err_msg_info( rc, "mbg_dev_has_mod", + "support monitoring signal modulation" ); + return rc; } printf( "\nMonitoring signal modulation:\n" ); for (;;) - if ( show_modulation( dh ) < 0 ) - goto fail; - -done: - return 0; + if ( mbg_rc_is_error( rc = show_modulation( dh ) ) ) + break; -fail: - return -1; + return rc; } // do_mbgshowsignal +static MBG_DEV_HANDLER_FNC do_mbgshowsignal; + static /*HDR*/ @@ -175,15 +177,11 @@ int main( int argc, char *argv[] ) if ( must_print_usage ) { usage(); - return 1; + return MBG_EXIT_CODE_USAGE; } - // The function below checks which devices have been specified - // on the command, and for each device - // - tries to open the device - // - shows basic device info - // - calls the function passed as last parameter - rc = mbg_check_devices( argc, argv, optind, do_mbgshowsignal ); + // Handle each of the specified devices. + rc = mbg_handle_devices( argc, argv, optind, do_mbgshowsignal, 0 ); - return abs( rc ); + return mbg_rc_is_success( rc ) ? MBG_EXIT_CODE_SUCCESS : MBG_EXIT_CODE_FAIL; } diff --git a/src/external/bsd/meinberg/dist/mbgstatus/Makefile b/src/external/bsd/meinberg/dist/mbgstatus/Makefile index 3d86873..214c076 100755 --- a/src/external/bsd/meinberg/dist/mbgstatus/Makefile +++ b/src/external/bsd/meinberg/dist/mbgstatus/Makefile @@ -1,24 +1,16 @@ ######################################################################### # -# $Id: Makefile 1.7.1.4.1.2 2011/04/20 09:34:06 martin TRASH $ +# $Id: Makefile 1.8 2017/07/05 18:27:30 martin REL_M $ # # Description: # Makefile for mbgstatus. # # ----------------------------------------------------------------------- # $Log: Makefile $ -# Revision 1.7.1.4.1.2 2011/04/20 09:34:06 martin -# Added module lan_util. -# Revision 1.7.1.4.1.1 2010/09/20 12:07:06 stefan -# Updated for use with latest base Makefile. -# Revision 1.7.1.4 2010/08/30 09:05:24 martin -# Revision 1.7.1.3 2010/08/30 08:20:32 martin -# Revision 1.7.1.2 2010/08/24 08:35:11 martin -# This basically builds kernel modules and user space apps correctly. -# However, there's still an absolute path specification which needs -# to be resolved. -# Revision 1.7.1.1 2010/08/24 08:02:05 martin +# Revision 1.8 2017/07/05 18:27:30 martin +# Updated list of object files and use top level +# Makefile properly. # Revision 1.7 2009/07/24 10:31:17 martin # Moved declarations to a common file which is now included. # Revision 1.6 2008/12/22 11:54:32 martin @@ -40,16 +32,19 @@ INST_TO_BIN = 1 OBJS := $(TARGET).o OBJS += mbgdevio.o +OBJS += mbgutil.o +OBJS += timeutil.o +OBJS += str_util.o OBJS += toolutil.o +OBJS += mbgerror.o +OBJS += cfg_hlp.o OBJS += gpsutils.o -OBJS += pcpsutil.o -OBJS += mbgmktm.o OBJS += pcpslstr.o -OBJS += parmpcps.o -OBJS += parmgps.o +OBJS += deviohlp.o OBJS += ctrydttm.o OBJS += ctry.o OBJS += lan_util.o +OBJS += nanotime.o BASEDIR := .. include $(BASEDIR)/Makefile diff --git a/src/external/bsd/meinberg/dist/mbgstatus/mbgstatus.c b/src/external/bsd/meinberg/dist/mbgstatus/mbgstatus.c index 5517eb6..e801034 100755 --- a/src/external/bsd/meinberg/dist/mbgstatus/mbgstatus.c +++ b/src/external/bsd/meinberg/dist/mbgstatus/mbgstatus.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgstatus.c 1.13.1.12 2011/07/08 11:02:47 martin TRASH $ + * $Id: mbgstatus.c 1.14 2017/07/05 18:34:46 martin REL_M $ * * Description: * Main file for mbgstatus program which demonstrates how to @@ -10,27 +10,13 @@ * * ----------------------------------------------------------------------- * $Log: mbgstatus.c $ - * Revision 1.13.1.12 2011/07/08 11:02:47 martin - * Revision 1.13.1.11 2011/07/05 15:35:55 martin - * Modified version handling. - * Revision 1.13.1.10 2011/07/05 14:35:19 martin + * Revision 1.14 2017/07/05 18:34:46 martin * New way to maintain version information. - * Revision 1.13.1.9 2011/04/20 16:08:27 martin - * Use snprint_ip4_addr() from module lan_util. - * Revision 1.13.1.8 2011/03/03 10:01:23 daniel - * Indicate Unicast role in PTP port state - * Revision 1.13.1.7 2011/02/07 12:10:58 martin - * Use mbg_get_ptp_status() API call. - * Revision 1.13.1.6 2010/11/25 14:54:51 martin - * Revision 1.13.1.5 2010/11/05 12:54:22 martin - * Introduce "verbose" flag and associated command line parameter -v. - * Revision 1.13.1.4 2010/10/15 11:28:56 martin - * Display UTC offs from IRIG signal. - * Revision 1.13.1.3 2010/08/30 08:22:24 martin - * Revision 1.13.1.2 2010/08/11 15:06:49 martin - * Preliminarily display raw IRIG data, if supported by the device. - * Revision 1.13.1.1 2010/02/17 14:11:43 martin - * Cosmetics ... + * Support build under Windows. + * Show many more details, at different verbosity levels. + * Use more functions from common library modules. + * Use codes and inline functions from mbgerror.h. + * Proper return codes and exit codes. * Revision 1.13 2009/09/29 15:02:16 martin * Updated version number to 3.4.0. * Revision 1.12 2009/07/24 14:02:59 martin @@ -79,16 +65,19 @@ // include Meinberg headers #include <mbgdevio.h> +#include <mbgutil.h> #include <mbgtime.h> #include <pcpslstr.h> -#include <pcpsutil.h> #include <toolutil.h> // common utility functions #include <lan_util.h> +#include <deviohlp.h> +#include <timeutil.h> +#include <str_util.h> +#include <nanotime.h> // include system headers #include <stdio.h> #include <stdlib.h> -#include <unistd.h> #define MBG_MICRO_VERSION 0 @@ -98,6 +87,10 @@ static const char *pname = "mbgstatus"; +static int loops; +static int must_list_device_names; +static long sleep_secs; +static long sleep_usecs; static unsigned int verbose; static const char *ref_name[N_PCPS_REF]= PCPS_REF_NAMES_ENG; @@ -107,6 +100,9 @@ static const char *osc_name[N_GPS_OSC] = DEFAULT_GPS_OSC_NAMES; static int year_limit = 1990; static int max_ref_offs_h = MBG_REF_OFFS_MAX / MINS_PER_HOUR; +static int invt_reason; + +static const char *wdays[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; LANGUAGE language; CTRY ctry; @@ -114,6 +110,29 @@ CTRY ctry; static /*HDR*/ +void show_invt_reason( void ) +{ + static const char fmt[] = "\n** Warning: %s\nThe command %s.\n"; + + switch ( invt_reason ) + { + case 2: + printf( fmt, DEFAULT_STR_IRIG_NOT_CFGD_EN, + "\"mbgirigcfg\" can be used to change the settings" ); + break; + + case 1: + printf( fmt, DEFAULT_STR_IRIG_INVT_EN, + "\"mbgctrl DATE=...\" can be used to set the on-board date" ); + break; + + } // switch + +} // show_invt_reason + + + +static /*HDR*/ void print_pcps_time( const char *s, const PCPS_TIME *tp, const char *tail ) { const char *fmt = "%s"; @@ -122,9 +141,10 @@ void print_pcps_time( const char *s, const PCPS_TIME *tp, const char *tail ) if ( s ) printf( fmt, s ); - printf( fmt, pcps_date_time_str( ws, tp, year_limit, pcps_tz_name( tp, PCPS_TZ_NAME_FORCE_UTC_OFFS, 0 ) ) ); + printf( fmt, pcps_date_time_str( ws, sizeof( ws ), tp, year_limit, + pcps_tz_name( tp, PCPS_TZ_NAME_FORCE_UTC_OFFS, 0 ) ) ); - if ( verbose > 1 ) + if ( ( verbose > 0 ) && _pcps_time_is_read( tp ) ) printf( ", st: 0x%02lX", (ulong) tp->status ); if ( tail ) @@ -139,7 +159,7 @@ void print_dms( const char *s, const DMS *p, const char *tail ) { const char *fmt = "%s"; - printf( "%s %c %3i deg %02i min %05.2f sec", + printf( "%s %c %3i deg %02i min %06.3f sec", s, p->prefix, p->deg, @@ -162,9 +182,14 @@ void print_position( const char *s, const POS *p, const char *tail ) if ( s ) + { printf( fmt, s ); - if ( verbose > 0 ) + if ( verbose ) + printf( "\n" ); + } + + if ( verbose > 1 ) { printf( " x: %.0fm y: %.0fm z: %.0fm", p->xyz[XP], p->xyz[YP], p->xyz[ZP] ); @@ -180,57 +205,22 @@ void print_position( const char *s, const POS *p, const char *tail ) if ( tail ) printf( fmt, tail ); - print_dms( " latitude: ", &p->latitude, tail ); - print_dms( " longitude:", &p->longitude, tail ); + if ( verbose ) + { + print_dms( " latitude: ", &p->latitude, tail ); + print_dms( " longitude:", &p->longitude, tail ); + } + } // print_position static /*HDR*/ -void show_time_and_status( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, const char *tail ) +void show_signal( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, int signal ) { - const char *status_fmt = "Status info: %s%s\n"; - const char *status_err = "*** "; - const char *status_ok = ""; - PCPS_TIME t; - PCPS_STATUS_STRS strs; - int signal; int ref_type; - int i; - int rc = mbg_get_time( dh, &t ); - if ( mbg_ioctl_err( rc, "mbg_get_time" ) ) - return; - - - print_pcps_time( "Date/time: ", &t, tail ); - - if ( ( verbose > 0 ) && _pcps_has_hr_time( pdev ) ) - { - PCPS_HR_TIME ht; - char ws[80]; - - rc = mbg_get_hr_time( dh, &ht ); - - if ( mbg_ioctl_err( rc, "mbg_get_hr_time" ) ) - return; - - mbg_snprint_hr_time( ws, sizeof( ws ), &ht ); - printf( "Local HR time: %s", ws ); - - if ( verbose > 1 ) - printf( ", st: 0x%04lX", (ulong) ht.status ); - - printf( "%s", tail ); - } - - signal = t.signal - PCPS_SIG_BIAS; - - if ( signal < 0 ) - signal = 0; - else - if ( signal > PCPS_SIG_MAX ) - signal = PCPS_SIG_MAX; + int rc; ref_type = _pcps_ref_type( pdev ); @@ -274,35 +264,88 @@ void show_time_and_status( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, const char * } } } + else + if ( _pcps_has_pzf( pdev ) ) + printf( "/PZF" ); + + printf( ")\n" ); - puts( ")" ); +} // show_signal - if ( _pcps_has_irig_time( pdev ) ) + + +static /*HDR*/ +void show_time_and_status( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, const char *tail ) +{ + const char status_fmt[] = "Status info: %s%s\n"; + const char status_err[] = "*** "; + const char status_ok[] = ""; + const char *info_err = ( _pcps_is_gps( pdev ) || _pcps_is_lwr( pdev ) ) ? + "ANTENNA FAULTY" : "NO INPUT SIGNAL"; + const char info_ok[] = "Input signal available"; + PCPS_TIME t; + PCPS_STATUS_STRS strs; + int signal; + int i; + int rc = mbg_get_time( dh, &t ); + + if ( mbg_cond_err_msg( rc, "mbg_get_time" ) ) + return; + + + print_pcps_time( "Date/time: ", &t, tail ); + + if ( ( verbose > 0 ) && _pcps_has_hr_time( pdev ) ) { - PCPS_IRIG_TIME it; + PCPS_HR_TIME ht; + char ws[80]; - rc = mbg_get_irig_time( dh, &it ); + rc = mbg_get_hr_time( dh, &ht ); - if ( !mbg_ioctl_err( rc, "mbg_get_irig_time" ) ) - printf( "Raw IRIG time: yday %u, %02u:%02u:%02u\n", - it.yday, it.hour, it.min, it.sec ); + if ( mbg_cond_err_msg( rc, "mbg_get_hr_time" ) ) + return; + + mbg_snprint_hr_time( ws, sizeof( ws ), &ht, 0 ); // raw timestamp? + printf( "Local HR time: %s", ws ); + + if ( verbose > 0 ) + printf( ", st: 0x%04lX", (ulong) ht.status ); + + printf( "%s", tail ); } - if ( _pcps_is_irig_rx( pdev ) ) + signal = t.signal - PCPS_SIG_BIAS; + + if ( signal < 0 ) + signal = 0; + else + if ( signal > PCPS_SIG_MAX ) + signal = PCPS_SIG_MAX; + + if ( _pcps_has_signal( pdev ) ) + show_signal( dh, pdev, signal ); + + if ( _pcps_has_pzf( pdev ) ) { - printf( status_fmt, - ( signal < PCPS_SIG_ERR ) ? status_err : status_ok, - ( signal < PCPS_SIG_ERR ) ? "NO INPUT SIGNAL" - : "Input signal available" ); + mbg_show_pzf_corr_info( dh, 0 ); + printf( "\n" ); } - else + + if ( verbose && _pcps_has_irig_time( pdev ) ) { - printf( status_fmt, - ( signal < PCPS_SIG_ERR ) ? status_err : status_ok, - ( signal < PCPS_SIG_ERR ) ? "ANTENNA IS NOT CONNECTED" - : "Antenna is connected" ); + PCPS_IRIG_TIME it; + + rc = mbg_get_irig_time( dh, &it ); + + if ( !mbg_cond_err_msg( rc, "mbg_get_irig_time" ) ) + printf( "Raw IRIG time: yday %u, %02u:%02u:%02u\n", + it.yday, it.hour, it.min, it.sec ); } + printf( status_fmt, + ( signal < PCPS_SIG_ERR ) ? status_err : status_ok, + ( signal < PCPS_SIG_ERR ) ? info_err : info_ok ); + // Evaluate the status code and setup status messages. pcps_status_strs( t.status, _pcps_time_is_read( &t ), _pcps_is_gps( pdev ), &strs ); @@ -317,6 +360,23 @@ void show_time_and_status( MBG_DEV_HANDLE dh, const PCPS_DEV *pdev, const char * pstr->cp ); } + invt_reason = 0; + + if ( _pcps_is_irig_rx( pdev ) && ( t.status & PCPS_INVT ) ) + { + MBG_REF_OFFS ref_offs; + + rc = mbg_get_ref_offs( dh, &ref_offs ); + + if ( !mbg_cond_err_msg( rc, "mbg_get_ref_offs" ) ) + { + if ( _pcps_ref_offs_out_of_range( ref_offs ) ) + invt_reason = 2; + else + invt_reason = 1; + } + } + } // show_time_and_status @@ -327,7 +387,7 @@ void show_sync_time( MBG_DEV_HANDLE dh, const char *tail ) PCPS_TIME t; int rc = mbg_get_sync_time( dh, &t ); - if ( mbg_ioctl_err( rc, "mbg_get_sync_time" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_sync_time" ) ) return; print_pcps_time( "Last sync: ", &t, tail ); @@ -340,49 +400,133 @@ static /*HDR*/ void show_ext_stat_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev, const char *tail ) { const char *fmt = "%s"; - RECEIVER_INFO ri; - STAT_INFO si = { 0 }; + RECEIVER_INFO ri = { 0 }; + ALL_GNSS_INFO agi = { { 0 } }; + GNSS_SAT_INFO *p_gsi; char ws[80]; - char *mode_name; + const char *cp; + int i; + int rc; - int rc = mbg_setup_receiver_info( dh, p_dev, &ri ); + // first collect all information - if ( mbg_ioctl_err( rc, "mbg_get_gps_stat_info" ) ) - return; + rc = mbg_setup_receiver_info( dh, p_dev, &ri ); + if ( mbg_cond_err_msg( rc, "mbg_setup_receiver_info" ) ) + return; - if ( _pcps_is_gps( p_dev ) ) + if ( mbg_rc_is_success( mbg_chk_dev_is_gps( dh ) ) ) { - rc = mbg_get_gps_stat_info( dh, &si ); + rc = mbg_chk_get_all_gnss_info( dh, &agi ); - if ( mbg_ioctl_err( rc, "mbg_get_gps_stat_info" ) ) + if ( mbg_cond_err_msg( rc, "mbg_chk_get_gnss_info" ) ) return; + } + + // now print information + + if ( verbose ) + printf( "Feature mask: 0x%08lX\n", (ulong) ri.features ); - switch ( si.mode ) + if ( _pcps_has_stat_info( p_dev ) ) + { + if ( _pcps_has_stat_info_mode( p_dev ) ) { - case AUTO_166: mode_name = "Normal Operation"; break; - case WARM_166: mode_name = "Warm Boot"; break; - case COLD_166: mode_name = "Cold Boot"; break; + switch ( agi.stat_info.mode ) + { + case AUTO_166: cp = "Normal Operation"; break; + case WARM_166: cp = "Warm Boot"; break; + case COLD_166: cp = "Cold Boot"; break; - default: // This should never happen! - sprintf( ws, "Unknown mode of operation: %02Xh", si.mode ); - mode_name = ws; + default: // This should never happen! + snprintf_safe( ws, sizeof( ws ), "%s mode of operation: %02Xh", + str_unknown, agi.stat_info.mode ); + cp = ws; - } // switch + } // switch - printf( "%s, %i sats in view, %i sats used\n", mode_name, si.svs_in_view, si.good_svs ); + printf( "%s", cp ); + } } - printf( "Osc type: %s", osc_name[( ri.osc_type < N_GPS_OSC ) ? ri.osc_type : GPS_OSC_UNKNOWN] ); - - if ( _pcps_is_gps( p_dev ) ) + if ( agi.n_gnss_supp ) { - printf( ", DAC cal: %+i, fine: %+i", - (int) ( si.dac_cal - OSC_DAC_BIAS ), - (int) ( si.dac_val - OSC_DAC_BIAS ) ); + #if defined( DEBUG ) // TODO + int must_print_sv_list = _pcps_has_stat_info_svs( p_dev ) && verbose; + #else + int must_print_sv_list = _pcps_is_gnss( p_dev ) && verbose; + #endif + int print_multi_lines = ( agi.n_gnss_supp > 1 ) || must_print_sv_list; + + // print multiple lines + // otherwise append to line + printf( print_multi_lines ? ":\n" : ", " ); + + for ( i = 0; i < agi.n_gnss_supp; i++ ) + { + static const char * const gnss_type_names[N_GNSS_TYPES] = GNSS_TYPE_STRS; + int gnss_type; + + p_gsi = &agi.gnss_sat_info_idx[i].gnss_sat_info; + gnss_type = p_gsi->gnss_type; + + if ( gnss_type >= N_GNSS_TYPES ) + { + mbg_snprintf( ws, sizeof( ws ), "(%s GNSS type %i): ", str_unknown, gnss_type ); + cp = ws; + } + else + cp = gnss_type_names[gnss_type]; + + if ( print_multi_lines ) + printf( " " ); + + if ( agi.gnss_mode_info.settings.gnss_set & ( 1UL << gnss_type ) ) + { + printf( "%i %s sats tracked, %i expected to be visible\n", p_gsi->good_svs, cp, p_gsi->svs_in_view ); + + if ( must_print_sv_list ) + { + int sat_idx; + + for ( sat_idx = 0; sat_idx < MAX_USED_SATS; sat_idx++ ) + { + int sat_num = p_gsi->svs[sat_idx]; + + #if !defined( DEBUG ) + if ( sat_num == 0 ) + break; + #endif + + printf( "%s%i", ( sat_idx == 0 ) ? " Sats: " : ", ", sat_num ); + } + + if ( sat_idx ) // the satellite list has been printed + printf( "\n" ); + } + } + else + printf( "%s reception disabled by configuration\n", cp ); + } } - puts( "" ); + if ( verbose ) + { + #if 0 //##+++++++++++++++++++++++++ + printf( "Feature mask: 0x%08lX\n", (ulong) ri.features ); + #endif + + printf( "Osc type: %s", osc_name[( ri.osc_type < N_GPS_OSC ) ? ri.osc_type : GPS_OSC_UNKNOWN] ); + + if ( _pcps_has_stat_info( p_dev ) ) + { + printf( ", DAC cal: %+i, fine: %+i", + (int) ( agi.stat_info.dac_cal - OSC_DAC_BIAS ), + (int) ( agi.stat_info.dac_val - OSC_DAC_BIAS ) ); + } + + puts( "" ); + } if ( tail ) printf( fmt, tail ); @@ -397,10 +541,10 @@ void show_gps_pos( MBG_DEV_HANDLE dh, const char *tail ) POS pos; int rc = mbg_get_gps_pos( dh, &pos ); - if ( mbg_ioctl_err( rc, "mbg_get_gps_pos" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_gps_pos" ) ) return; - print_position( "Receiver Position:\n", &pos, tail ); + print_position( "Receiver Position:", &pos, tail ); } // show_gps_pos @@ -413,45 +557,59 @@ void show_utc_info( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) int rc = mbg_get_utc_parm( dh, &utc ); - if ( mbg_ioctl_err( rc, "mbg_get_utc_parm" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_utc_parm" ) ) return; - if ( !utc.valid ) - { - puts( "** UTC parameters not valid" ); - return; - } - if ( verbose > 1 ) + if ( utc.valid ) { - //##++++ utc.delta_tls = utc.delta_tlsf - 1; - - printf( "CSUM: %04X, valid: %04X\n", utc.csum, utc.valid ); - printf( "t0t: %u|%u.%07u, A0: %g A1: %g\n", - utc.t0t.wn, utc.t0t.sec, utc.t0t.tick, - utc.A0, utc.A1 ); - printf( "WNlsf: %u, DN: %u, offs: %i/%i\n", - utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf ); - } + char tmp_str[80]; + struct tm tm = { 0 }; - if ( utc.delta_tls != utc.delta_tlsf ) - { - // a leap second is currently being announced - time_t t_ls = (time_t) utc.WNlsf * SECS_PER_WEEK - + (time_t) utc.DNt * SECS_PER_DAY - + GPS_SEC_BIAS - 1; - - struct tm *tm = gmtime( &t_ls ); - - printf( "UTC offset transition from %is to %is due to leap second\n" - "%s at UTC midnight at the end of %04i-%02i-%02i.\n", - utc.delta_tls, utc.delta_tlsf, - ( utc.delta_tls < utc.delta_tlsf ) ? "insertion" : "deletion", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday - ); + long t_ls_long = (long) utc.WNlsf * SECS_PER_WEEK + + (long) utc.DNt * SECS_PER_DAY + + GPS_SEC_BIAS - 1; + time_t t_ls = cvt_to_time_t( t_ls_long ); + + rc = mbg_gmtime( &tm, &t_ls ); + + if ( mbg_rc_is_success( rc ) ) + mbg_snprintf( tmp_str, sizeof( tmp_str ), "at UTC midnight at the end of %s, %04i-%02i-%02i", + wdays[tm.tm_wday], tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday ); + else + snprint_gmtime_error( tmp_str, sizeof( tmp_str ), rc, t_ls, __func__ ); + + if ( verbose > 1 ) + { + //##++++++++++ utc.delta_tls = utc.delta_tlsf - 1; + + printf( "CSUM: %04X, valid: %04X\n", utc.csum, utc.valid ); + printf( "t0t: %u|%u.%07u, A0: %g A1: %g\n", + utc.t0t.wn, utc.t0t.sec, utc.t0t.tick, + utc.A0, utc.A1 ); + printf( "WNlsf: %u, DN: %u, offs: %i/%i\n", + utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf ); + } + + if ( utc.delta_tls != utc.delta_tlsf ) + { + // a leap second is currently being announced + printf( "UTC offset transition from %is to %is due to leap second\n" + "%s %s.\n", + utc.delta_tls, utc.delta_tlsf, + ( utc.delta_tls < utc.delta_tlsf ) ? "insertion" : "deletion", + tmp_str + ); + } + else + if ( verbose ) + printf( "Leap second eventually %s\n", tmp_str ); + else + printf( "UTC offset parameter: %is, no leap second announced.\n", utc.delta_tls ); } else - printf( "UTC offset parameter: %is, no leap second announced.\n", utc.delta_tls ); + puts( "** UTC parameters not valid" ); + } // show_utc_info @@ -464,7 +622,7 @@ void show_irig_ctrl_bits( MBG_DEV_HANDLE dh ) int rc = mbg_get_irig_ctrl_bits( dh, &irig_ctrl_bits ); - if ( mbg_ioctl_err( rc, "mbg_get_irig_ctrl_bits" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_irig_ctrl_bits" ) ) return; printf( "IRIG control bits: %08lX (hex, LSB first)", (ulong) irig_ctrl_bits ); @@ -484,10 +642,10 @@ char *str_raw_irig_utc_offs_hours( char *s, int max_len, const MBG_RAW_IRIG_DATA | ( ( p->data_bytes[8] >> 4 ) & 0x02 ) | ( ( p->data_bytes[8] >> 6 ) & 0x01 ); - n = snprintf( s, max_len, "%c%li", ( p->data_bytes[8] & 0x80 ) ? '-' : '+', offs ); + n = mbg_snprintf( s, max_len, "%c%li", ( p->data_bytes[8] & 0x80 ) ? '-' : '+', offs ); if ( p->data_bytes[8] & 0x02 ) - n += snprintf( &s[n], max_len - n, "%s", ".5" ); + n += mbg_snprintf( &s[n], max_len - n, "%s", ".5" ); return s; @@ -504,7 +662,7 @@ void show_raw_irig_data( MBG_DEV_HANDLE dh ) int rc = mbg_get_raw_irig_data( dh, &raw_irig_data ); - if ( mbg_ioctl_err( rc, "mbg_get_raw_irig_data" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_raw_irig_data" ) ) return; printf( "Raw IRIG data:" ); @@ -530,7 +688,7 @@ void show_irig_debug_status( MBG_DEV_HANDLE dh ) int i; int rc = _mbg_generic_read_var( dh, PCPS_GET_DEBUG_STATUS, st ); - if ( mbg_ioctl_err( rc, "show_irig_debug_status" ) ) + if ( mbg_cond_err_msg( rc, "show_irig_debug_status" ) ) return; printf( "Debug status (hex): %08lX\n", (ulong) st ); @@ -552,25 +710,18 @@ void show_lan_intf_state( MBG_DEV_HANDLE dh ) int rc = mbg_get_ip4_state( dh, &ip4_settings ); - if ( mbg_ioctl_err( rc, "mbg_get_ip4_state" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_ip4_state" ) ) return; rc = mbg_get_lan_if_info( dh, &lan_if_info ); - if ( mbg_ioctl_err( rc, "mbg_get_lan_if_info" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_lan_if_info" ) ) return; printf( "On-board LAN interface settings:\n" ); - snprintf( ws, sizeof( ws ), "%02X-%02X-%02X-%02X-%02X-%02X", - lan_if_info.mac_addr[0], - lan_if_info.mac_addr[1], - lan_if_info.mac_addr[2], - lan_if_info.mac_addr[3], - lan_if_info.mac_addr[4], - lan_if_info.mac_addr[5] - ); + snprint_mac_addr( ws, sizeof( ws ), &lan_if_info.mac_addr ); printf( " MAC Address: %s\n", ws ); snprint_ip4_addr( ws, sizeof( ws ), &ip4_settings.ip_addr, NULL ); @@ -595,58 +746,214 @@ void show_lan_intf_state( MBG_DEV_HANDLE dh ) static /*HDR*/ void show_ptp_state( MBG_DEV_HANDLE dh ) { - static const char *ptp_stat_str[N_PTP_PORT_STATE] = PTP_PORT_STATE_STRS; + static const char *ptp_role_strs[N_PTP_ROLES] = PTP_ROLE_STRS; + static const char *ptp_state_strs[N_PTP_PORT_STATE] = PTP_PORT_STATE_STRS; + static const char *ptp_nw_prot_strs[N_PTP_NW_PROT] = PTP_NW_PROT_STRS; + static const char *ptp_delay_mech_names[N_PTP_DELAY_MECH] = PTP_DELAY_MECH_NAMES; + static const PTP_TABLE ptp_time_source_tbl[] = PTP_TIME_SOURCE_TABLE; + static const char *ptp_clock_accuracy_strs[] = PTP_CLOCK_ACCURACY_STRS; + char ws[100]; const char *cp; - int ptp_state_available; + int must_show_slave_mode_info; + int must_show_master_mode_info; + int slave_mode_active; + int master_mode_active; + int any_mode_active; + int utc_offset_valid; PTP_STATE ptp_state; PTP_CFG_INFO ptp_info; + int tmp; int rc = mbg_get_ptp_state( dh, &ptp_state ); - if ( mbg_ioctl_err( rc, "mbg_get_ptp_state" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_ptp_state" ) ) return; rc = mbg_get_ptp_cfg_info( dh, &ptp_info ); - if ( mbg_ioctl_err( rc, "mbg_get_ptp_info" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_ptp_info" ) ) return; - printf( "PTP port status:\n" ); - ptp_state_available = ( ptp_state.port_state == PTP_PORT_STATE_SLAVE ); + // set up some flags controlling which information to be shown - printf( " Port mode: %s%s\n", ( ptp_state_available && ptp_info.settings.ptp_role == PTP_ROLE_UNICAST_SLAVE ) ? "Unicast" : "", - ( ptp_state.port_state < N_PTP_PORT_STATE ) ? ptp_stat_str[ptp_state.port_state] : "(undefined)" ); + must_show_slave_mode_info = ( verbose > 1 ) || + ( ( ( 1UL << ptp_info.settings.ptp_role ) & PTP_ROLE_MSK_SLAVES ) != 0 ); - cp = ptp_state_available ? ws : str_not_avail; + must_show_master_mode_info = ( verbose > 1 ) || + ( ( ( 1UL << ptp_info.settings.ptp_role ) & PTP_ROLE_MSK_MASTERS ) != 0 ); -//##++++++++++ - snprintf( ws, sizeof( ws ), "%02X-%02X-%02X-%02X-%02X-%02X", - ptp_state.gm_id.b[0], - ptp_state.gm_id.b[1], - ptp_state.gm_id.b[2], - ptp_state.gm_id.b[5], - ptp_state.gm_id.b[6], - ptp_state.gm_id.b[7] - ); - printf( " Grandmaster MAC: %s\n", cp ); + slave_mode_active = ( ptp_state.port_state == PTP_PORT_STATE_UNCALIBRATED ) + || ( ptp_state.port_state == PTP_PORT_STATE_SLAVE ); + master_mode_active = ( ptp_state.port_state == PTP_PORT_STATE_PRE_MASTER ) + || ( ptp_state.port_state == PTP_PORT_STATE_MASTER ) + || ( ptp_state.port_state == PTP_PORT_STATE_PASSIVE ); - snprintf( ws, sizeof( ws ), "%c%li.%09li s", - _nano_time_negative( &ptp_state.path_delay ) ? '-' : '+', - labs( (long) ptp_state.path_delay.secs ), - labs( (long) ptp_state.path_delay.nano_secs ) - ); - printf( " PTP path delay: %s\n", cp ); + any_mode_active = slave_mode_active || master_mode_active; + + + // PTP role and port state + + printf( "PTP port state:\n" ); + + printf( " Port mode: " ); + + if ( any_mode_active ) + printf( "%s", ( ptp_state.flags & PTP_FLAG_MSK_IS_UNICAST ) ? + "Unicast " : "Multicast " ); + + if ( ptp_state.port_state < N_PTP_PORT_STATE ) + printf( "%s", ptp_state_strs[ptp_state.port_state] ); + else + printf( "%s, code %i", str_undefined, ptp_state.port_state ); + + if ( !any_mode_active || ( verbose > 1 ) ) + printf( " in %s role", + ( ptp_info.settings.ptp_role < N_PTP_ROLES ) ? + ptp_role_strs[ptp_info.settings.ptp_role] : str_undefined ); + + printf( "\n" ); + + + if ( !any_mode_active || verbose ) + { + printf( " PTP protocol: " ); + + // If not fully synchronized then not all fields of the PTP_STATE + // structure may have been filled, so we show configuration settings + // in this case. + + if ( ptp_state.ptp_prot_version ) + printf( "v%i, ", ptp_state.ptp_prot_version ); + + tmp = any_mode_active ? ptp_state.nw_prot : ptp_info.settings.nw_prot; + printf( "%s", ( tmp < N_PTP_NW_PROT ) ? + ptp_nw_prot_strs[tmp] : str_undefined ); + + printf( ", %s step", + ( ptp_state.flags & PTP_FLAG_MSK_ONE_STEP ) ? "one" : "two" ); + + tmp = any_mode_active ? ptp_state.domain_number : ptp_info.settings.domain_number; + printf( ", domain %i", tmp ); + + tmp = any_mode_active ? ptp_state.delay_mech : ptp_info.settings.delay_mech; + printf( ", delay mech. %s", ( tmp < N_PTP_DELAY_MECH ) ? + ptp_delay_mech_names[tmp] : str_undefined ); + + tmp = any_mode_active ? ptp_state.log_delay_req_intv : ptp_info.settings.delay_req_intv; + printf( ", dly req. intv. 2^%i s", tmp ); + + printf( "\n" ); + } + + + if ( must_show_slave_mode_info ) + { + cp = ( slave_mode_active || ( verbose > 1 ) ) ? ws : str_not_avail; + + snprint_octets( ws, sizeof( ws ), ptp_state.gm_id.b, + sizeof( ptp_state.gm_id.b ), MAC_SEP_CHAR_ALT, NULL ); + printf( " Grandmaster ID: %s\n", cp ); + + snprint_nano_time( ws, sizeof( ws ), &ptp_state.offset ); + printf( " PTP time offset: %s\n", cp ); + + snprint_nano_time( ws, sizeof( ws ), &ptp_state.path_delay ); + printf( " PTP path delay: %s\n", cp ); + + if ( verbose > 1 ) + { + snprint_nano_time( ws, sizeof( ws ), &ptp_state.mean_path_delay ); + printf( " Mean path delay: %s\n", cp ); + + snprint_nano_time( ws, sizeof( ws ), &ptp_state.delay_asymmetry ); + printf( " Delay asymmetry: %s\n", cp ); + } + } + + + // PTP time scale + + cp = NULL; + + if ( ptp_state.flags & PTP_FLAG_MSK_TIMESCALE_IS_PTP ) // this is the default + { + if ( must_show_master_mode_info || verbose ) + cp = "TAI (standard)"; + } + else // unusual case, print info if available + if ( any_mode_active ) + cp = "arbitrary (non-standard)"; + + if ( cp ) + printf( " PTP time scale: %s\n", cp ); + + + // UTC offset and leap second status + + utc_offset_valid = ( ptp_state.flags & PTP_FLAG_MSK_UTC_VALID ) != 0; + + printf( " PTP UTC offset: " ); + + if ( !utc_offset_valid ) + printf( " %s", str_unknown ); // UTC offset not valid + + if ( utc_offset_valid || ( verbose > 1 ) ) + { + printf( utc_offset_valid ? " " : " (" ); + + printf( "%+i s", ptp_state.utc_offset ); + + if ( ptp_state.flags & PTP_FLAG_MSK_LS_ANN ) // leap second is announced + { + // distinguish between leap second insertion and deletion + printf( ", leap second %s scheduled", + ( ptp_state.flags & PTP_FLAG_MSK_LS_ANN_NEG ) ? "deletion" : "insertion" ); + } + + if ( !utc_offset_valid ) + printf( ")" ); + } + + printf( "\n" ); + + + if ( verbose > 1 ) + { + const PTP_TABLE *p_tbl; + + printf( "PTP clock state:\n" ); + + for ( p_tbl = ptp_time_source_tbl; p_tbl->name; p_tbl++ ) + if ( p_tbl->value == ptp_state.time_source ) + break; + + printf( " Time source: %s\n", p_tbl->name ? p_tbl->name : str_unknown ); + + printf( " Clock class: %i\n", ptp_state.clock_class ); + + tmp = N_PTP_CLOCK_ACCURACY - PTP_CLOCK_ACCURACY_NUM_BIAS; + + if ( ( ptp_state.clock_accuracy >= PTP_CLOCK_ACCURACY_NUM_BIAS ) && + ( ptp_state.clock_accuracy < N_PTP_CLOCK_ACCURACY ) ) + cp = ptp_clock_accuracy_strs[ptp_state.clock_accuracy - PTP_CLOCK_ACCURACY_NUM_BIAS]; + else + cp = str_undefined; + + printf( " Clock accuracy: %s\n", cp ); + +#if 0 + time_source + clock_class + clock_accuracy +#endif + printf( " Offs sc. log var: %u", ptp_state.clock_offset_scaled_log_variance ); + printf( "\n" ); + } - snprintf( ws, sizeof( ws ), "%c%li.%09li s", - _nano_time_negative( &ptp_state.offset ) ? '-' : '+', - labs( (long) ptp_state.offset.secs ), - labs( (long) ptp_state.offset.nano_secs ) - ); - printf( " PTP time offset: %s\n", cp ); } // show_ptp_state @@ -659,8 +966,8 @@ int check_irq_unsafe( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) int ret_val = 0; int rc = mbg_get_irq_stat_info( dh, &irq_stat_info ); - if ( mbg_ioctl_err( rc, "mbg_get_irq_stat_info" ) ) - return -1; + if ( mbg_cond_err_msg( rc, "mbg_get_irq_stat_info" ) ) + return rc; if ( irq_stat_info & PCPS_IRQ_STAT_UNSAFE ) { @@ -712,38 +1019,61 @@ int do_mbgstatus( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) if ( check_irq_unsafe( dh, p_dev ) < 0 ) goto done; - if ( _pcps_has_gps_data( p_dev ) ) - show_ext_stat_info( dh, p_dev, NULL ); + for (;;) + { + if ( _pcps_has_gps_data( p_dev ) ) + show_ext_stat_info( dh, p_dev, NULL ); + + show_time_and_status( dh, p_dev, "\n" ); + show_sync_time( dh, "\n" ); + + if ( _pcps_is_gps( p_dev ) ) + show_gps_pos( dh, "\n" ); + + if ( _pcps_has_utc_parm( p_dev ) && ( _pcps_is_gps( p_dev ) || ( verbose > 0 ) ) ) + show_utc_info( dh, p_dev ); - show_time_and_status( dh, p_dev, "\n" ); - show_sync_time( dh, "\n" ); + if ( verbose && _pcps_has_irig_ctrl_bits( p_dev ) ) + show_irig_ctrl_bits( dh ); - if ( _pcps_is_gps( p_dev ) ) - show_gps_pos( dh, "\n" ); + if ( verbose && ( mbg_chk_dev_has_raw_irig_data( dh ) == MBG_SUCCESS ) ) + show_raw_irig_data( dh ); - if ( _pcps_has_utc_parm( p_dev ) ) - show_utc_info( dh, p_dev ); + if ( verbose && _pcps_is_irig_rx( p_dev ) ) + show_irig_debug_status( dh ); - if ( _pcps_has_irig_ctrl_bits( p_dev ) ) - show_irig_ctrl_bits( dh ); + if ( mbg_chk_dev_has_lan_intf( dh ) == MBG_SUCCESS ) + show_lan_intf_state( dh ); - if ( _pcps_has_raw_irig_data( p_dev ) ) - show_raw_irig_data( dh ); + if ( _pcps_has_ptp( p_dev ) ) + show_ptp_state( dh ); - if ( _pcps_is_irig_rx( p_dev ) ) - show_irig_debug_status( dh ); + if ( loops > 0 ) + loops--; - if ( _pcps_has_lan_intf( p_dev ) ) - show_lan_intf_state( dh ); + if ( loops == 0 ) + break; - if ( _pcps_has_ptp( p_dev ) ) - show_ptp_state( dh ); + if ( sleep_secs ) + sleep( sleep_secs ); + else + if ( sleep_usecs ) + usleep( sleep_usecs ); + + printf( "\n" ); + + // if this_loops is < 0 then loop forever + } + + show_invt_reason(); done: return ret_val; } // do_mbgstatus +static MBG_DEV_HANDLER_FNC do_mbgstatus; + static /*HDR*/ @@ -754,6 +1084,12 @@ void usage( void ) "The displayed information depends on the type of the card." ); mbg_print_help_options(); + mbg_print_opt_info( "-c", "run continuously" ); + mbg_print_opt_info( "-l", "list device names" ); + mbg_print_opt_info( "-n num", "run num loops" ); + mbg_print_opt_info( "-s num", "sleep num seconds between calls (implies -c)" ); + mbg_print_opt_info( "-u num", "sleep num microseconds between calls (implies -c)" ); + mbg_print_opt_info( "-v", "increase verbosity" ); mbg_print_device_options(); puts( "" ); @@ -774,10 +1110,32 @@ int main( int argc, char *argv[] ) mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); // check command line parameters - while ( ( c = getopt( argc, argv, "vh?" ) ) != -1 ) + while ( ( c = getopt( argc, argv, "cln:s:u:vh?" ) ) != -1 ) { switch ( c ) { + case 'c': + loops = -1; + break; + + case 'l': + must_list_device_names = 1; + break; + + case 'n': + loops = atoi( optarg ); + break; + + case 's': + sleep_secs = atoi( optarg ); + loops = -1; + break; + + case 'u': + sleep_usecs = atoi( optarg ); + loops = -1; + break; + case 'v': verbose++; break; @@ -792,19 +1150,38 @@ int main( int argc, char *argv[] ) if ( must_print_usage ) { usage(); - return 1; + return MBG_EXIT_CODE_USAGE; } + if ( must_list_device_names ) + { + MBG_DEV_NAME_LIST_ENTRY *list_head = NULL; + int n_dev = mbg_find_devices_with_names( &list_head, N_SUPP_DEV_BUS ); + + if ( n_dev ) + { + MBG_DEV_NAME_LIST_ENTRY *pos; + + printf( "Unique names of devices found:\n" ); + + for ( pos = list_head; pos; pos = pos->next ) + printf( " %s\n", pos->dev_name ); + } + else + printf( "No device found.\n" ); + + mbg_free_device_name_list( list_head ); + printf( "\n" ); + + return MBG_EXIT_CODE_SUCCESS; + } + if ( verbose ) pcps_date_time_dist = 1; - // The function below checks which devices have been specified - // on the command, and for each device - // - tries to open the device - // - shows basic device info - // - calls the function passed as last parameter - rc = mbg_check_devices( argc, argv, optind, do_mbgstatus ); + // Handle each of the specified devices. + rc = mbg_handle_devices( argc, argv, optind, do_mbgstatus, CHK_DEV_ALL_DEVICES ); - return abs( rc ); + return mbg_rc_is_success( rc ) ? MBG_EXIT_CODE_SUCCESS : MBG_EXIT_CODE_FAIL; } diff --git a/src/external/bsd/meinberg/dist/mbgsvcd/Makefile b/src/external/bsd/meinberg/dist/mbgsvcd/Makefile index 1e940ae..74286eb 100755 --- a/src/external/bsd/meinberg/dist/mbgsvcd/Makefile +++ b/src/external/bsd/meinberg/dist/mbgsvcd/Makefile @@ -1,20 +1,21 @@ ######################################################################### # -# $Id: Makefile 1.1.1.2.1.2 2011/06/16 10:44:42 martin TRASH $ +# $Id: Makefile 1.3.1.1 2017/07/26 14:30:41 martin TEST $ # # Description: # Makefile for mbgsvcd. # # ----------------------------------------------------------------------- # $Log: Makefile $ -# Revision 1.1.1.2.1.2 2011/06/16 10:44:42 martin -# Install mbgsvcd to sbin. -# Revision 1.1.1.2.1.1 2010/09/20 12:07:10 stefan +# Revision 1.3.1.1 2017/07/26 14:30:41 martin +# Removed lines that are not required / supported with *BSD. +# Revision 1.3 2017/07/03 10:51:51 martin +# *** empty log message *** +# Revision 1.2 2017/01/27 12:19:47 martin # Updated for use with latest base Makefile. -# Revision 1.1.1.2 2010/08/30 09:05:24 martin -# Revision 1.1.1.1 2010/08/30 08:22:06 martin -# Revision 1.1 2010/02/03 16:07:18 daniel +# Updated list of object files. +# Support registering mbgsvcd with the init system. # Revision 1.1 2009/09/29 08:34:23 martin # ######################################################################### @@ -24,10 +25,15 @@ INST_TO_SBIN = 1 OBJS = $(TARGET).o OBJS += mbgdevio.o +OBJS += timeutil.o +OBJS += str_util.o OBJS += toolutil.o +OBJS += mbgerror.o +OBJS += cfg_hlp.o OBJS += gpsutils.o -OBJS += mbgmktm.o -OBJS += pcpsmktm.o +OBJS += chk_time_info.o +OBJS += ntp_shm.o BASEDIR := .. include $(BASEDIR)/Makefile + diff --git a/src/external/bsd/meinberg/dist/mbgsvcd/mbgsvcd.c b/src/external/bsd/meinberg/dist/mbgsvcd/mbgsvcd.c index af0dcab..b5f03d7 100755 --- a/src/external/bsd/meinberg/dist/mbgsvcd/mbgsvcd.c +++ b/src/external/bsd/meinberg/dist/mbgsvcd/mbgsvcd.c @@ -1,37 +1,35 @@ /************************************************************************** * - * $Id: mbgsvcd.c 1.3.1.10 2011/07/14 13:30:57 martin TRASH $ + * $Id: mbgsvcd.c 1.4 2017/07/05 18:45:29 martin REL_M $ * * Description: - * Main file for mbgsvcd which compares the system time to a PCI card's + * Main file for mbgsvcd which compares the system time to a PCI card's * time and transfers this data pair to the SHM driver of the ntpd. * * ----------------------------------------------------------------------- * $Log: mbgsvcd.c $ - * Revision 1.3.1.10 2011/07/14 13:30:57 martin - * Code cleanup. - * Eliminated some potential warnings due to ignored function return values. - * Revision 1.3.1.9 2011/07/05 15:35:55 martin - * Modified version handling. - * Revision 1.3.1.8 2011/07/05 14:35:19 martin + * Revision 1.4 2017/07/05 18:45:29 martin * New way to maintain version information. - * Revision 1.3.1.7 2011/06/23 15:35:40 martin - * Skip devices which don't support HR time immediately at startup. - * Revision 1.3.1.6 2011/06/23 15:02:55 martin + * Print PC cycles counter frequency at program start. + * Use /var/run as directory for the lockfile. + * Using generic MBG_SYS_TIME with nanosecond resolution. + * Workaround in case cycle frequency can not be determined. * Compute execution time limit in cycles instead of us so this can also * be done if the cycle counter clock rate can not be determined. - * Revision 1.3.1.5 2011/06/23 12:45:37 martin - * Workaround in case cycle frequency can not be determined. - * Revision 1.3.1.4 2011/06/20 15:10:22 martin - * Using generic MBG_SYS_TIME with nanosecond resolution. - * Revision 1.3.1.3 2011/03/25 11:05:24 martin - * Optionally support timespec for sys time. - * Cleanup. - * Revision 1.3.1.2 2011/03/23 16:30:40 martin - * Use /var/run as directory for the lockfile. - * Revision 1.3.1.1 2010/04/26 14:37:41 martin - * Print PC cycles counter frequency at program start. + * Skip devices which don't support HR time immediately at startup. + * Log reasons for error if function calls fail. + * Combined printf() and syslog() to mbg_log(). + * Added leap second support. + * Moved some code to some extra modules which can be shared. + * Use seconds for the trust time. + * Support options -q and -r. + * Use more functions from common library modules. + * Use codes and inline functions from mbgerror.h. + * Patch submitted by <juergen.perlinger@t-online.de>: + * Support variable number of SHM units and number + * of the first unit to use. + * Proper return codes and exit codes. * Revision 1.3 2010/03/03 14:59:36 martin * Support -p parameter to pretend sync. * Revision 1.2 2010/02/03 16:15:09 daniel @@ -43,7 +41,10 @@ #include <mbgdevio.h> #include <pcpsutil.h> #include <toolutil.h> // common utility functions +#include <mbgerror.h> #include <pcpsmktm.h> +#include <chk_time_info.h> +#include <ntp_shm.h> // include system headers #include <stdio.h> @@ -53,174 +54,71 @@ #include <arpa/inet.h> #include <sys/socket.h> #include <sys/types.h> -#include <sys/time.h> +#include <sys/time.h> #include <sys/stat.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> #include <signal.h> #include <syslog.h> - - +#include <stdarg.h> +#include <time.h> +#include <sys/time.h> #include <sys/ipc.h> #include <sys/shm.h> -#define NTPD_BASE 0x4e545030 /* "NTP0" */ -#define SHM_UNIT 0 /* SHM driver unit number (0..3) */ -#define MAX_SHM_REFCLOCKS 4 - -#define RUNNING_DIR "/var/run" -#define LOCK_FILE "mbgsvcd.pid" +#define RUNNING_DIR "/var/run" +#define LOCK_FILE "mbgsvcd.pid" #define MBG_MICRO_VERSION 0 -#define MBG_FIRST_COPYRIGHT_YEAR 2011 //##++++ 20101 -#define MBG_LAST_COPYRIGHT_YEAR 0 // use default +#define MBG_FIRST_COPYRIGHT_YEAR 2010 +#define MBG_LAST_COPYRIGHT_YEAR 0 // use default static const char *pname = "mbgsvcd"; -static int sleep_intv = 1; -static int pretend_sync; - - - -#define MAX_FILTER_ENTRIES 32 - -typedef struct -{ - MBG_PC_CYCLES cyc[MAX_FILTER_ENTRIES]; - MBG_PC_CYCLES sum; - int entries; - int index; -} FILTER; - -static FILTER filter; - - -/*HDR*/ static -MBG_PC_CYCLES do_filter( FILTER *p, MBG_PC_CYCLES cyc ) -{ - if ( p->entries < MAX_FILTER_ENTRIES ) - p->entries++; - - if ( ++( p->index ) >= MAX_FILTER_ENTRIES ) - p->index = 0; - - // update the sum of filter entries - p->sum -= p->cyc[p->index]; // subtract oldest sample - p->cyc[p->index] = cyc; // save new sample - p->sum += cyc; // add new sample - - return p->sum / p->entries; // return mean value - -} /* do_filter */ - - - -struct shmTime { - int mode; /* 0 - if valid set - * use values, - * clear valid - * 1 - if valid set - * if count before and after read of - * values is equal, - * use values - * clear valid - */ - int count; - time_t clockTimeStampSec; /* external clock */ - int clockTimeStampUSec; /* external clock */ - time_t receiveTimeStampSec; /* internal clock, when external value was received */ - int receiveTimeStampUSec; /* internal clock, when external value was received */ - int leap; - int precision; - int nsamples; - int valid; - int dummy[10]; -}; - -struct shmTime *shmTime[MAX_SHM_REFCLOCKS]; - - -static -struct shmTime *getShmTime(int unit) -{ - int shmid = shmget( (key_t) ( NTPD_BASE + unit ), - sizeof( struct shmTime ), IPC_CREAT | 0644 ); - - if ( shmid == -1 ) - { - syslog(LOG_ERR, "shmget failed\n"); - return NULL; - } - else - { - struct shmTime *p = ( struct shmTime * ) shmat( shmid, 0, 0); - - if ( (int) (long) p == -1 ) - { - syslog(LOG_ERR, "shmat failed\n" ); - return NULL; - } +static int foreground; // -f +static int quiet; // -q +static int pretend_sync; // -p +static int print_raw; // -r +static int sleep_intv = 1; // -s +static unsigned long trust_time_seconds; // -t +static int n_unit0 = 0; // -o +static int n_units = MAX_SHM_REFCLOCKS; // -n +static int frac_digits = 9; - syslog(LOG_INFO, "shmat(%d,0,0) succeeded\n", shmid); - return p; - } -} +MBG_PC_CYCLES_FREQUENCY cyc_freq; +static struct shmTime *shmTime[MAX_SHM_REFCLOCKS]; +static FILTER filter; //##++++ [MAX_SHM_REFCLOCKS] ? -static /*HDR*/ -void ntpshm_init( void ) -{ - int i = 0; - - syslog(LOG_INFO, "Initializing shared memory for ntpd"); +static int has_synced_after_reset[MAX_SHM_REFCLOCKS] = { 0 }; +static long int ref_trust_time_start[MAX_SHM_REFCLOCKS] = { 0 }; +static long int ref_trust_time_expire[MAX_SHM_REFCLOCKS] = { 0 }; - for ( i = 0; i< MAX_SHM_REFCLOCKS; i++ ) - shmTime[i] = getShmTime( i ); -} // ntpshm_init - - -static /*HDR*/ -int ntpshm_alloc( void ) +/*HDR*/ +void mbg_log( int lvl, const char *fmt, ... ) { - int i; - - for ( i = 0; i< MAX_SHM_REFCLOCKS; i++) - { - struct shmTime *p = shmTime[i]; - - if ( p ) - { - memset( p, 0, sizeof( *p ) ); - - p->mode = 1; - p->precision = -5; /* initially 0.5 sec */ - p->nsamples = 3; /* stages of median filter */ + char ws[256]; + va_list ap; - printf( "Shared memory %d initialized\n", i ); - } - } + va_start( ap, fmt ); + vsnprintf( ws, sizeof( ws ), fmt, ap ); + va_end( ap ); - return 0; + syslog( lvl, "%s", ws ); + fprintf( stdout, "%s\n", ws ); -} // ntpshm_alloc +} // mbg_log static /*HDR*/ int do_mbgsvctasks( void ) { - MBG_PC_CYCLES_FREQUENCY cyc_freq; - MBG_TIME_INFO_HRT hrti; - PCPS_TIME_STAMP *p_ref_ts; - MBG_PC_CYCLES *p_ref_cyc; - MBG_SYS_TIME_CYCLES *p_sys_tic; char ws[256]; - double d_ref; - double d_sys; int rc = 0; int n_devices_found; int n_devices; @@ -239,15 +137,15 @@ int do_mbgsvctasks( void ) if ( rc < 0 ) { - printf( "Failed to read device info from device #%i.\n", i ); + mbg_log( LOG_WARNING, "Failed to read device info from device #%i.", i ); mbg_close_device( &dh ); continue; } if ( !_pcps_has_hr_time( &dev_info ) ) { - printf( "Device %s does not support HR time stamps.\n", - _pcps_type_name( &dev_info ) ); + mbg_log( LOG_WARNING, "Device %s does not support HR time stamps.", + _pcps_type_name( &dev_info ) ); mbg_close_device( &dh ); continue; } @@ -255,151 +153,142 @@ int do_mbgsvctasks( void ) dhs[n_devices] = dh; devs[n_devices] = dev_info; - if ( ++n_devices >= MAX_SHM_REFCLOCKS ) + if ( ++n_devices >= n_units ) break; } if ( n_devices == 0 ) { - printf( "No usable devices found!\n" ); + mbg_log( LOG_WARNING, "No usable device found!" ); goto done; } - // Search for devices up to the maximum of supported NTP SHM refclocks + // Search for devices up to the maximum of supported number of NTP SHM refclocks if ( n_devices > MAX_SHM_REFCLOCKS ) n_devices = MAX_SHM_REFCLOCKS; - syslog( LOG_INFO, "Found %d devices usable for the NTP daemon", n_devices ); //##++++ + mbg_log( LOG_INFO, "Found %d devices usable for the NTP daemon", n_devices ); //##++++ rc = mbg_get_default_cycles_frequency_from_dev( dhs[0], &cyc_freq ); - if ( mbg_ioctl_err( rc, "mbg_get_default_cycles_frequency_from_dev" ) ) + if ( mbg_cond_err_msg( rc, "mbg_get_default_cycles_frequency_from_dev" ) ) goto done; - if ( cyc_freq == 0 ) - printf( "*** Warning: " ); - - printf( "PC cycles counter clock frequency: %Lu Hz\n", - (unsigned long long) cyc_freq ); + mbg_log( LOG_INFO, "%sPC cycles counter clock frequency: %Lu Hz", + ( cyc_freq == 0 ) ? "*** Warning: " : "", + (unsigned long long) cyc_freq ); // Initialize NTP shared memory area - ntpshm_init(); - ntpshm_alloc(); + ntpshm_init( shmTime, n_devices, n_unit0 ); for (;;) { for ( i = 0; i < n_devices; i++ ) { - double ltcy_sec; - double d_ref_comp; - MBG_PC_CYCLES ltcy_cyc; - MBG_PC_CYCLES exec_cyc; - MBG_PC_CYCLES exec_cyc_limit; - MBG_PC_CYCLES tmp; + MBG_CHK_TIME_INFO cti; const char *cp; + int leap; - rc = mbg_get_time_info_hrt( dhs[i], &hrti ); + rc = mbg_chk_time_info( dhs[i], &cti, &filter, 0 ); //##+++++ one or more filter instances ? - if ( mbg_ioctl_err( rc, "mbg_get_time_info_..." ) ) + if ( mbg_cond_err_msg( rc, "mbg_chk_time_info" ) ) continue; + cp = ""; + leap = 0; - p_ref_ts = &hrti.ref_hr_time_cycles.t.tstamp; - p_ref_cyc = &hrti.ref_hr_time_cycles.cycles; - p_sys_tic = &hrti.sys_time_cycles; - - d_ref = (double) p_ref_ts->sec + ( (double) p_ref_ts->frac ) / (double) PCPS_HRT_BIN_FRAC_SCALE; - d_sys = (double) p_sys_tic->sys_time.sec + (double) p_sys_tic->sys_time.nsec / 1e9; - - ltcy_cyc = mbg_delta_pc_cycles( p_ref_cyc, &p_sys_tic->cyc_after ); - exec_cyc = mbg_delta_pc_cycles( &p_sys_tic->cyc_after, &p_sys_tic->cyc_before ); - - ltcy_sec = cyc_freq ? ( ( (double) ltcy_cyc ) / (double) cyc_freq ) : 0.0; - - // Compensate latencies between time stamps -> - // normalize ref time to system time stamp - d_ref_comp = d_ref - ltcy_sec; - - exec_cyc_limit = do_filter( &filter, exec_cyc ); - - // Try to set the limit to 1.7 of the mean execution cycles. - tmp = ( 7 * exec_cyc_limit ) / 10; + if ( ( has_synced_after_reset[i] == 1 ) && ( ( ( cti.hrti.ref_hr_time_cycles.t.status & PCPS_FREER ) == 1 ) + || ( ( cti.hrti.ref_hr_time_cycles.t.status & PCPS_SYNCD ) == 0 ) )) + { + struct timespec ts; - // If execution takes only a few cycles make sure the limit - // is above the mean number of cycles. - if ( tmp == 0 ) - tmp++; + clock_gettime(CLOCK_MONOTONIC, &ts); - exec_cyc_limit += tmp; + if (ref_trust_time_start[i] == 0 ) + { + mbg_log( LOG_WARNING, "Device #%i, entering holdover mode", i ); + ref_trust_time_start[i] = ts.tv_sec; + ref_trust_time_expire[i] = ts.tv_sec + trust_time_seconds; + } - cp = ""; + if ( ts.tv_sec > ref_trust_time_expire[i] ) + { + mbg_log( LOG_WARNING, "Device #%i, trust time expired", i ); + has_synced_after_reset[i] = 0; + ref_trust_time_start[i] = 0; + ref_trust_time_expire[i] = 0; + } + } // check if refclock is sync and if exec time of the system time call was fast enough - if ( ( exec_cyc <= exec_cyc_limit ) && ( pretend_sync || ( - ( ( hrti.ref_hr_time_cycles.t.status & PCPS_FREER ) == 0 ) && - ( ( hrti.ref_hr_time_cycles.t.status & PCPS_SYNCD ) != 0 ) ) ) ) + if ( ( cti.exec_cyc <= cti.exec_cyc_limit ) && ( pretend_sync || has_synced_after_reset[i] || ( + ( ( cti.hrti.ref_hr_time_cycles.t.status & PCPS_FREER ) == 0 ) && + ( ( cti.hrti.ref_hr_time_cycles.t.status & PCPS_SYNCD ) != 0 ) ) ) ) { struct shmTime *p = shmTime[i]; - cp = " *"; - - // fill SHM structure - p->count++; - p->clockTimeStampSec = (time_t) d_ref_comp; - p->clockTimeStampUSec = (int) ( ( d_ref_comp - p->clockTimeStampSec ) * 1e6 ); // get µs from d_ref - p->receiveTimeStampSec = (time_t) p_sys_tic->sys_time.sec; - p->receiveTimeStampUSec = (int) ( p_sys_tic->sys_time.nsec / 1000 ); + has_synced_after_reset[i] = 1; - // patch precision value according to the ref time accuracy - if ( _pcps_is_lwr( &devs[i] ) ) - p->precision = -8; - else + if ( p ) { - if ( _pcps_is_irig_rx( &devs[i] ) ) + MBG_SYS_TIME_CYCLES *p_sys_tic = &cti.hrti.sys_time_cycles; + cp = " *"; + + // fill SHM structure + p->count++; + p->clockTimeStampSec = (time_t) cti.d_ref_comp; + p->clockTimeStampUSec = (int) ( ( cti.d_ref_comp - p->clockTimeStampSec ) * 1e6 ); // get microseconds from d_ref + p->receiveTimeStampSec = (time_t) p_sys_tic->sys_time.secs; + p->receiveTimeStampUSec = (int) ( p_sys_tic->sys_time.nano_secs / 1000 ); + + // These fields are only supported by newer versions of ntpd //##++++++++++++++++++ which versions ? + p->clockTimeStampNSec = (int) ( ( cti.d_ref_comp - p->clockTimeStampSec ) * 1e9 ); // get nanoseconds from d_ref + p->receiveTimeStampNSec = (int) ( p_sys_tic->sys_time.nano_secs ); + + // patch precision value according to the ref time accuracy + if ( _pcps_is_lwr( &devs[i] ) ) + p->precision = -8; + else { - if ( _pcps_is_usb( &devs[i] ) ) - p->precision = -10; + if ( _pcps_is_irig_rx( &devs[i] ) ) + { + if ( _pcps_is_usb( &devs[i] ) ) + p->precision = -10; + else + p->precision = -18; + } else - p->precision = -18; + p->precision = -20; } - else - p->precision = -20; - } - - p->count++; - p->valid = 1; - } - - mbg_snprint_hr_tstamp( ws, sizeof( ws ), p_ref_ts ); - printf( "%-9s: %s: %.7f-%.7f: %+.7f %+.7f, ltcy: ", - _pcps_type_name( &devs[i] ), ws, d_ref, d_sys, - d_ref - d_sys, d_ref_comp - d_sys ); + if ( cti.hrti.ref_hr_time_cycles.t.status & PCPS_LS_ANN_NEG ) + p->leap = LEAP_DELSECOND; + else + if ( cti.hrti.ref_hr_time_cycles.t.status & PCPS_LS_ANN ) + p->leap = LEAP_ADDSECOND; + else + p->leap = LEAP_NOWARNING; - if ( cyc_freq != 0 ) // print latency and execution time in microseconds - { - double exec_sec = (double) exec_cyc / (double) cyc_freq; - double exec_sec_limit = (double) exec_cyc_limit / (double) cyc_freq; + leap = p->leap; //##+++ - printf( "%.2f us, exec: %.2f us, limit: %.2f us", - ltcy_sec * 1e6, exec_sec * 1e6, exec_sec_limit * 1e6 ); + p->count++; + p->valid = 1; + } } - else // print latency and execution time in cycles only + + if ( !quiet ) { - printf( "%lli cyc, exec: %lli cyc, limit: %lli cyc", - (long long) ltcy_cyc, (long long) exec_cyc, - (long long) exec_cyc_limit ); + snprint_chk_time_info( ws, sizeof( ws ), &cti, &devs[i], frac_digits, print_raw ); + printf( "%s, leap: %02X%s\n", ws, leap, cp ); } - printf( "%s\n", cp ); - usleep( 10 ); } if ( n_devices > 1 ) - printf("\n"); + printf( "\n" ); if ( sleep_intv ) sleep( sleep_intv ); @@ -428,8 +317,13 @@ void usage( void ) ); mbg_print_help_options(); mbg_print_opt_info( "-f", "run program in foreground" ); + mbg_print_opt_info( "-q", "quiet, don't print time differences on stdout" ); + mbg_print_opt_info( "-r", "print raw time stamps when printing on stdout" ); mbg_print_opt_info( "-s num", "sleep num seconds between calls" ); mbg_print_opt_info( "-p", "pretend device is always synchronized" ); + mbg_print_opt_info( "-t num", "set num seconds for refclock trust time, default 4 days (345600 seconds)" ); + mbg_print_opt_info( "-n num", "number of SHM segments to use" ); + mbg_print_opt_info( "-o num", "SHM segment number offset (default 0)" ); mbg_print_device_options(); puts( "" ); @@ -448,7 +342,7 @@ void startup_daemon( void ) if ( getppid() == 1 ) return; /* already a daemon */ - printf( "Daemon mode, backgrounding ... \n" ); + mbg_log( LOG_INFO, "Daemon mode, backgrounding" ); i = fork(); if ( i < 0 ) @@ -477,9 +371,9 @@ void startup_daemon( void ) if ( lfp < 0 ) exit( 1 ); /* unable to open lock file */ - if ( lockf( lfp, F_TLOCK, 0 ) < 0 ) + if ( lockf( lfp, F_TLOCK, 0 ) < 0 ) { - syslog( LOG_ERR, "Lock file already exists, another instance of this daemon seems to be running" ); + mbg_log( LOG_ERR, "Lock file already exists, another instance of this daemon seems to be running" ); closelog(); exit( 0 ); /* can not lock */ } @@ -488,6 +382,8 @@ void startup_daemon( void ) snprintf( str, sizeof( str ), "%d\n", getpid() ); rc = write( lfp, str, strlen( str ) ); /* record pid to lockfile */ + (void) rc; // avoid warning "set but not used" + signal( SIGCHLD, SIG_IGN ); /* ignore child */ signal( SIGTSTP, SIG_IGN ); /* ignore tty signals */ signal( SIGTTOU, SIG_IGN ); @@ -501,12 +397,11 @@ int main( int argc, char *argv[] ) { int rc; int c; - int foreground = 0; mbg_print_program_info( pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); // check command line parameters - while ( ( c = getopt( argc, argv, "fps:h?" ) ) != -1 ) + while ( ( c = getopt( argc, argv, "fpqrst:n:o:h?" ) ) != -1 ) { switch ( c ) { @@ -518,10 +413,52 @@ int main( int argc, char *argv[] ) pretend_sync = 1; break; + case 'q': + quiet++; + break; + + case 'r': + print_raw = 1; + break; + case 's': sleep_intv = atoi( optarg ); break; + case 't': + { + long tt = atol( optarg ); + + if ( tt > 0 ) + trust_time_seconds = tt; + + break; + } + + case 'n': + n_units = atoi( optarg ); + + if ( n_units < 0 || n_units > MAX_SHM_REFCLOCKS ) + { + mbg_log( LOG_WARNING, "Configured number of SHM units %i out of range, truncating to %i", + n_units, MAX_SHM_REFCLOCKS ); + n_units = MAX_SHM_REFCLOCKS; + } + + break; + + case 'o': + n_unit0 = atoi( optarg ); + + if ( n_unit0 < 0 || n_unit0 >= MAX_SHM_UNIT_OFFSET ) + { + mbg_log( LOG_WARNING, "Configured SHM unit offset %i out of range %i to %i, truncating to %i", + n_unit0, 0, MAX_SHM_UNIT_OFFSET, 0 ); + n_unit0 = 0; + } + + break; + case 'h': case '?': default: @@ -532,7 +469,7 @@ int main( int argc, char *argv[] ) if ( must_print_usage ) { usage(); - return 1; + return MBG_EXIT_CODE_USAGE; } if ( foreground == 0 ) @@ -542,12 +479,15 @@ int main( int argc, char *argv[] ) mbg_program_info_str( ws, sizeof( ws ), pname, MBG_MICRO_VERSION, MBG_FIRST_COPYRIGHT_YEAR, MBG_LAST_COPYRIGHT_YEAR ); - syslog( LOG_INFO, "Starting Meinberg Service Daemon %s", ws ); + mbg_log( LOG_INFO, "Starting Meinberg Service Daemon %s", ws ); startup_daemon(); } + if ( trust_time_seconds ) + mbg_log( LOG_INFO, "refclock trust time: %ul seconds", trust_time_seconds ); + rc = do_mbgsvctasks(); - return abs( rc ); + return mbg_rc_is_success( rc ) ? MBG_EXIT_CODE_SUCCESS : MBG_EXIT_CODE_FAIL; } diff --git a/src/external/bsd/meinberg/dist/mbgversion.h b/src/external/bsd/meinberg/dist/mbgversion.h index a3a3300..f3ef207 100755 --- a/src/external/bsd/meinberg/dist/mbgversion.h +++ b/src/external/bsd/meinberg/dist/mbgversion.h @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgversion.h 1.1 2011/07/08 12:09:55 martin TRASH $ + * $Id: mbgversion.h 1.1.1.1 2017/07/26 14:21:26 martin TEST $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -10,13 +10,15 @@ * * ----------------------------------------------------------------------- * $Log: mbgversion.h $ + * Revision 1.1.1.1 2017/07/26 14:21:26 martin + * Updated copyright year to 2017. * Revision 1.1 2011/07/08 12:09:55 martin * Initial revision for pre-release. * **************************************************************************/ -#define MBG_CURRENT_COPYRIGHT_YEAR 2011 -#define MBG_CURRENT_COPYRIGHT_YEAR_STR "2011" +#define MBG_CURRENT_COPYRIGHT_YEAR 2017 +#define MBG_CURRENT_COPYRIGHT_YEAR_STR "2017" #define MBG_MAJOR_VERSION_CODE 0 #define MBG_MINOR_VERSION_CODE 9 diff --git a/src/external/bsd/meinberg/dist/mbgxhrtime/Makefile b/src/external/bsd/meinberg/dist/mbgxhrtime/Makefile index 75d6673..a507de6 100755 --- a/src/external/bsd/meinberg/dist/mbgxhrtime/Makefile +++ b/src/external/bsd/meinberg/dist/mbgxhrtime/Makefile @@ -1,17 +1,16 @@ ######################################################################### # -# $Id: Makefile 1.2.1.2.1.1 2010/09/20 12:07:14 stefan TEST $ +# $Id: Makefile 1.3 2017/07/05 18:36:06 martin REL_M $ # # Description: # Makefile for mbgxhrtime. # # ----------------------------------------------------------------------- # $Log: Makefile $ -# Revision 1.2.1.2.1.1 2010/09/20 12:07:14 stefan -# Updated for use with latest base Makefile. -# Revision 1.2.1.2 2010/08/30 09:05:24 martin -# Revision 1.2.1.1 2010/08/30 08:22:11 martin +# Revision 1.3 2017/07/05 18:36:06 martin +# Updated list of object files and use top level +# Makefile properly. # Revision 1.2 2009/07/24 10:31:17 martin # Moved declarations to a common file which is now included. # Revision 1.1 2008/12/22 11:05:24 martin @@ -26,7 +25,11 @@ USE_THREAD_API = 1 OBJS = $(TARGET).o OBJS += mbgdevio.o +OBJS += timeutil.o +OBJS += str_util.o OBJS += toolutil.o +OBJS += mbgerror.o +OBJS += cfg_hlp.o OBJS += gpsutils.o BASEDIR := .. diff --git a/src/external/bsd/meinberg/dist/mbgxhrtime/mbgxhrtime.c b/src/external/bsd/meinberg/dist/mbgxhrtime/mbgxhrtime.c index af26ece..c24b715 100755 --- a/src/external/bsd/meinberg/dist/mbgxhrtime/mbgxhrtime.c +++ b/src/external/bsd/meinberg/dist/mbgxhrtime/mbgxhrtime.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: mbgxhrtime.c 1.5.1.2 2011/07/05 15:35:56 martin TRASH martin $ + * $Id: mbgxhrtime.c 1.6 2017/07/05 18:38:18 martin REL_M $ * * Description: * Main file for mbgxhrtime program which demonstrates how to retrieve @@ -41,10 +41,12 @@ * * ----------------------------------------------------------------------- * $Log: mbgxhrtime.c $ - * Revision 1.5.1.2 2011/07/05 15:35:56 martin - * Modified version handling. - * Revision 1.5.1.1 2011/07/05 14:36:11 martin + * Revision 1.6 2017/07/05 18:38:18 martin * New way to maintain version information. + * Support build under Windows. + * Use more functions from common library modules. + * Use codes and inline functions from mbgerror.h. + * Proper return codes and exit codes. * Revision 1.5 2009/09/29 14:25:07 martin * Display measured and default PC cycles frequency. * Updated version number to 3.4.0. @@ -62,23 +64,24 @@ // include Meinberg headers #include <mbgdevio.h> -#include <pcpsutil.h> #include <toolutil.h> // common utility functions // include system headers #include <time.h> #include <stdio.h> #include <stdlib.h> -#include <unistd.h> -#include <pthread.h> -#include <sched.h> +#if !defined( MBG_TGT_WIN32 ) + #include <unistd.h> + #include <pthread.h> + #include <sched.h> +#endif #if !defined( MBGDEVIO_USE_THREAD_API ) #error Symbol MBGDEVIO_USE_THREAD_API needs to be defined, see the Makefile. #endif -#if !defined ( USE_PROCESS_AFFINITY ) +#if !defined( USE_PROCESS_AFFINITY ) #define USE_PROCESS_AFFINITY 1 #endif @@ -182,7 +185,7 @@ int do_mbgxhrtime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) rc = mbg_xhrt_poll_thread_create( &poll_thread_info, dh, 0, 0 ); if ( rc != MBG_SUCCESS ) - return -1; + return rc; for (;;) @@ -216,10 +219,10 @@ int do_mbgxhrtime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) { puts( "" ); - printf( "PC cycles freq: %.6f MHz", ( (double) freq_hz ) / 1E6 ); + printf( "PC cycles freq: %.6f MHz", ( (double) (int64_t) freq_hz ) / 1E6 ); if ( default_freq_hz ) - printf( ", default: %.6f MHz", ( (double) default_freq_hz ) / 1E6 ); + printf( ", default: %.6f MHz", ( (double) (int64_t) default_freq_hz ) / 1E6 ); printf( "\n" ); @@ -236,10 +239,10 @@ int do_mbgxhrtime( MBG_DEV_HANDLE dh, const PCPS_DEV *p_dev ) goto fail; // compute the latency - latency = ( (double) cyc_2 - (double) cyc_1 ) / (double) freq_hz * 1E6; + latency = ( (double) cyc_2 - (double) cyc_1 ) / (double) (int64_t) freq_hz * 1E6; // convert to human readable date and time - mbg_snprint_hr_time( ws, sizeof( ws ), &hrt ); + mbg_snprint_hr_time( ws, sizeof( ws ), &hrt, 0 ); // raw timestamp? printf( "t: %s (%.3f us)\n", ws, latency ); if ( this_loops > 0 ) @@ -259,12 +262,12 @@ fail: done: mbg_xhrt_poll_thread_stop( &poll_thread_info ); - mbg_close_device( &dh ); - return rc; } // do_mbgxhrtime +static MBG_DEV_HANDLER_FNC do_mbgxhrtime; + static /*HDR*/ @@ -322,7 +325,7 @@ int main( int argc, char *argv[] ) if ( must_print_usage ) { usage(); - return 1; + return MBG_EXIT_CODE_USAGE; } #if USE_PROCESS_AFFINITY @@ -330,12 +333,8 @@ int main( int argc, char *argv[] ) puts( "" ); #endif - // The function below checks which devices have been specified - // on the command, and for each device - // - tries to open the device - // - shows basic device info - // - calls the function passed as last parameter - rc = mbg_check_devices( argc, argv, optind, do_mbgxhrtime ); + // Handle each of the specified devices. + rc = mbg_handle_devices( argc, argv, optind, do_mbgxhrtime, 0 ); - return abs( rc ); + return mbg_rc_is_success( rc ) ? MBG_EXIT_CODE_SUCCESS : MBG_EXIT_CODE_FAIL; } diff --git a/src/external/bsd/meinberg/mbgclock/Makefile b/src/external/bsd/meinberg/mbgclock/Makefile new file mode 100755 index 0000000..85ad982 --- /dev/null +++ b/src/external/bsd/meinberg/mbgclock/Makefile @@ -0,0 +1 @@ +.include "Makefile.kmod"
\ No newline at end of file diff --git a/src/external/bsd/meinberg/mbgclock/Makefile.kmod b/src/external/bsd/meinberg/mbgclock/Makefile.kmod new file mode 100755 index 0000000..0136033 --- /dev/null +++ b/src/external/bsd/meinberg/mbgclock/Makefile.kmod @@ -0,0 +1,20 @@ +# $NetBSD: Makefile,v 1.1 2009/02/05 17:32:10 haad Exp $ + +.include "../Makefile.inc" + +.PATH: ${MBG_LIB_COMMON} ${MBG_LIB_BSD} + +MKMAN=no +# CFLAGS+=-D_HAVE_PPS_REF_EVENT -DPPS_SYNC + +KMOD= mbgclock +SRCS= mbgclock_main.c +SRCS+= pcpsdrvr.c +SRCS+= identdec.c +SRCS+= rsrc_bsd.c + +.if !defined (MKMODULAR) || ( defined(MKMODULAR) && (${MKMODULAR}!="no") ) +.include <bsd.kmodule.mk> +.else +.include <bsd.kmod.mk> +.endif diff --git a/src/external/bsd/meinberg/mbgclock/files.mbgclock b/src/external/bsd/meinberg/mbgclock/files.mbgclock new file mode 100755 index 0000000..94310bc --- /dev/null +++ b/src/external/bsd/meinberg/mbgclock/files.mbgclock @@ -0,0 +1,13 @@ +# $NetBSD: files.drm,v 1.6 2011/02/18 14:26:09 jmcneill Exp $ + +device mbgclock +attach mbgclock at pci +file external/bsd/meinberg/dist/mbglib/bsd/rsrc_bsd.c mbgclock +file external/bsd/meinberg/dist/mbglib/common/identdec.c mbgclock +file external/bsd/meinberg/dist/mbglib/common/pcpsdrvr.c mbgclock +file external/bsd/meinberg/mbgclock/mbgclock_main.c mbgclock + +makeoptions mbgclock CPPFLAGS+="-I$S/external/bsd/meinberg/dist/mbglib/common" +makeoptions mbgclock CPPFLAGS+="-I$S/external/bsd/meinberg/dist/mbglib/bsd" + + diff --git a/src/external/bsd/meinberg/mbgclock/mbgclock_main.c b/src/external/bsd/meinberg/mbgclock/mbgclock_main.c new file mode 100755 index 0000000..1eafb29 --- /dev/null +++ b/src/external/bsd/meinberg/mbgclock/mbgclock_main.c @@ -0,0 +1,1134 @@ +/* + * $Header: /repository/clkdrv/bsd/netbsd/soft/mbgtools-nbsd/mbgclock/RCS/mbgclock_main.c 1.1.1.13 2017/07/26 15:25:56 martin TEST $ + * + * NetBSD Meinberg mbgclock driver, Frank Kardel + * + * $Created: Sat Mar 26 15:03:37 2011 $ + * + */ + +#include <sys/param.h> +#include <sys/lwp.h> +#include <sys/callout.h> +#include <sys/device.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/fcntl.h> +#include <sys/kauth.h> +#include <dev/pci/pcidevs.h> +#include <dev/pci/pcivar.h> +#include <sys/timetc.h> +#include <sys/timepps.h> +#include <sys/errno.h> +#include <sys/atomic.h> + +#ifdef MBG_DEBUG + #define DEBUG MBG_DEBUG +#endif + +#include <pcpsdrvr.h> +#include <mbgddmsg.h> + +#ifndef PCI_BAR +#define PCI_BAR(__n) (0x10 + 4 * (__n)) +#endif + +#define REV_NUM 0x100 +#define REV_NUM_STR "1.00" +#define MBG_COPYRIGHT "(c) Meinberg 2011" +#define MBG_DRVR_NAME "mbgclock" +#define MBG_VENDOR "Meinberg Funkuhren" + +const char pcps_driver_name[] = MBG_DRVR_NAME; + +static MBG_DBG_DATA mbg_dbg_data; +static MBG_DBG_PORT mbg_dbg_port = 0x378 + 0; //##++ +static PCPS_IO_ADDR_MAPPED mbg_dbg_port_mapped; //##++ +static PCPS_DRVR_INFO drvr_info = { REV_NUM, 0, MBG_DRVR_NAME " radio clock driver" }; + +#ifndef MBG_PCPS_FMT_STATUS +#define MBG_PCPS_FMT_STATUS "\177\20b\0FREER\0b\1DL_ENB\0b\2SYNCD\0b\3DL_ANN\0b\4UTC\0b\5LS_ANN\0b\6IFTM\0b\7INVT\0b\x08LS_ENB\0b\11ANT_FAIL\0b\x0aLS_ANN_NEG\0b\x0bSCALE_GPS\0b\x0cSCALE_TAI\0\0" +#endif + +#include <macioctl.h> + +static dev_type_open(mbgclockopen); +static dev_type_close(mbgclockclose); +static dev_type_read(mbgclockread); +static dev_type_write(mbgclockwrite); +static dev_type_ioctl(mbgclockioctl); +static int mbgclock_match(device_t, cfdata_t, void *); +static void mbgclock_attach(device_t, device_t, void *); +static int mbgclock_detach(device_t, int); +static void mbgclock_tick(void *); +static timecounter_get_t mbgclock_get_timecount; + +struct mbgclock_softc +{ + device_t dev; /* device backling */ + struct pci_attach_args pa; /* attach argument */ + int isopen; /* openflag */ + PCPS_DDEV *pddev; /* driver handle */ + struct pps_state pps_state; /* pps state */ + kmutex_t mutex; /* callout termination */ + callout_t callout; /* callout structure */ + PCPS_TIME_STATUS_X last_status; /* last device status */ + struct timecounter tc; /* timecounter - if available */ +}; + +#define MBG_UNITBITS 6 /* up to 64 devices */ +#define MBG_UNITMASK ((1<<MBG_UNITBITS)-1) +#define MBG_UNIT(x) (minor(x) & MBG_UNITMASK) +#define MBG_UNITTYPE(x) (minor(x) >> MBG_UNITBITS) + +const struct cdevsw mbgclock_cdevsw = { + .d_open = mbgclockopen, + .d_close = mbgclockclose, + .d_read = mbgclockread, + .d_write = mbgclockwrite, + .d_ioctl = mbgclockioctl, + .d_stop = nostop, + .d_tty = notty, + .d_poll = nopoll, + .d_mmap = nommap, + .d_kqfilter = nokqfilter, + D_OTHER|D_MPSAFE +}; + +#ifdef CFATTACH_DECL3_NEW +CFATTACH_DECL3_NEW(mbgclock, + sizeof(struct mbgclock_softc), + mbgclock_match, + mbgclock_attach, + mbgclock_detach, + NULL, + NULL, + NULL, + DVF_DETACH_SHUTDOWN); +#else +CFATTACH_DECL2_NEW(mbgclock, + sizeof(struct mbgclock_softc), + mbgclock_match, + mbgclock_attach, + mbgclock_detach, + NULL, + NULL, + NULL); +#endif + +extern struct cfdriver mbgclock_cd; + +#undef DEBUG /* XXX for now */ + +#if defined( MBG_DEBUG ) +int debug = MBG_DEBUG; +#endif + +#if defined( DEBUG ) +static int mbgclockdebug = ~0; +#define DB_FOLLOW 0x00000001 +#define DPRINTF(_X_, _Y_) do { \ + if (mbgclockdebug & (_X_)) { \ + printf _Y_; \ + } \ + } \ + while (/*CONST_COND*/0) +#else +#define DPRINTF(_X_, _Y_) /* empty */ +#endif + +/*----- loadables -----*/ +#if defined (_LKM) || defined(_MODULE) + +static volatile uint32_t opencount = 0; /* number of open char drivers */ +#define INC_REF atomic_inc_32(&opencount) +#define DEC_REF atomic_dec_32(&opencount) + +CFDRIVER_DECL(mbgclock, DV_DULL, NULL); + +static int mbgclock_loc[] = { -1, -1 }; + +static struct cfparent pciparent = { + "pci", "pci", DVUNIT_ANY +}; + +static struct cfdata mbgclock_cfdata[] = { + { + .cf_name = "mbgclock", + .cf_atname = "mbgclock", + .cf_unit = 0, + .cf_fstate = FSTATE_STAR, + .cf_loc = mbgclock_loc, + .cf_flags = 0, + .cf_pspec = &pciparent, + }, + { NULL } +}; +#else +#define INC_REF +#define DEC_REF +#endif + +/*----- module -----*/ +#ifdef _MODULE + +#include <sys/module.h> + +MODULE(MODULE_CLASS_DRIVER, mbgclock, NULL); + +static int +mbgclock_modcmd(modcmd_t cmd, void *arg) +{ + int bmajor = -1, cmajor = -1, error = 0; + + switch (cmd) { + case MODULE_CMD_INIT: + DPRINTF(DB_FOLLOW, ("%s: MOD_CMD_INIT\n", mbgclock_cd.cd_name)); + + error = config_cfdriver_attach(&mbgclock_cd); + if (error) + break; + + error = config_cfattach_attach(mbgclock_cd.cd_name, &mbgclock_ca); + if (error) { + config_cfdriver_detach(&mbgclock_cd); + aprint_error("%s: unable to register cfattach\n", + mbgclock_cd.cd_name); + break; + } + + /* s = splaudio(); */ + error = config_cfdata_attach(mbgclock_cfdata, 1); + /* splx(s); */ + + if (error == 0) + { + error = devsw_attach("mbgclock", NULL, &bmajor, + &mbgclock_cdevsw, &cmajor); + } + + if (error) { + config_cfattach_detach(mbgclock_cd.cd_name, &mbgclock_ca); + config_cfdriver_detach(&mbgclock_cd); + break; + } else { + DPRINTF(DB_FOLLOW, ("%s: registered character major = %d\n", + mbgclock_cd.cd_name, cmajor)); + } + + break; + + case MODULE_CMD_FINI: + DPRINTF(DB_FOLLOW, ("%s: MOD_CMD_FINI\n", mbgclock_cd.cd_name)); + + if (opencount) { + error = EBUSY; + break; + } + + error = config_cfdata_detach(mbgclock_cfdata); + if (error) + break; + + error = config_cfattach_detach(mbgclock_cd.cd_name, &mbgclock_ca); + if (error) + break; + + config_cfdriver_detach(&mbgclock_cd); + devsw_detach(NULL, &mbgclock_cdevsw); + break; + + case MODULE_CMD_STAT: + error = ENOTTY; + break; + + default: + error = ENOTTY; + break; + } + + DPRINTF(DB_FOLLOW, ("modcmd rc = %d\n", error)); + + return error; +} +#endif + +/*------ LKM -----*/ +#if defined(_LKM) && !defined(_MODULE) + +#include <sys/lkm.h> + +int mbgclock_lkmentry(struct lkm_table *, int, int); + +static struct cfdriver *mbgclock_cfdrivers[] = { + &mbgclock_cd, + NULL +}; +static struct cfattach *mbgclock_cfattachs[] = { + &mbgclock_ca, + NULL +}; +static const struct cfattachlkminit mbgclock_cfattachinit[] = { + { "mbgclock", mbgclock_cfattachs }, + { NULL } +}; + +MOD_DRV("mbgclock", + mbgclock_cfdrivers, + mbgclock_cfattachinit, + mbgclock_cfdata); + +static int +mbgclock_lkmload(struct lkm_table *lkm, int cmd) +{ + int bmajor = -1; + int cmajor = -1; + int error; + + error = devsw_attach("mbgclock", NULL, &bmajor, + &mbgclock_cdevsw, &cmajor); + +#ifdef DEBUG + if (error == 0) { + DPRINTF(DB_FOLLOW, ("%s: registered character major = %d\n", + mbgclock_cd.cd_name, cmajor)); + } else { + DPRINTF(DB_FOLLOW, ("%s: device driver registry failed errno = %d\n", + mbgclock_cd.cd_name, error)); + } +#endif + return error; +} + +static int +mbgclock_lkmunload(struct lkm_table *lkm, int cmd) +{ + if (opencount) + return EBUSY; + + devsw_detach(NULL, &mbgclock_cdevsw); + return 0; +} + +int +mbgclock_lkmentry(struct lkm_table *lkmtp, int cmd, int ver) +{ + DISPATCH(lkmtp, cmd, ver, mbgclock_lkmload, mbgclock_lkmunload, lkm_nofunc); +} +#endif + +/*----- autoconf -----*/ + +/* PCI Support Functions */ + +static void +mbg_deallocate_resource( BSD_RSRC_INFO *p_ri ) +{ + if ( p_ri->valid ) + { + bus_space_unmap( p_ri->bst, p_ri->bsh, p_ri->size); + p_ri->valid = 0; + } +} + +/* + * deallocate resources + */ +static void +mbg_dealloc_rsrcs( struct mbgclock_softc *psc ) +{ + PCPS_DDEV *pddev = psc->pddev; + +/* mbg_deallocate_resource( device, &prsrci->irq.bsd, SYS_RES_IRQ ); */ + + if ( pddev != NULL ) + { + PCPS_RSRC_INFO *prsrci = &pddev->rsrc_info; + int i; + + for ( i = 0; i < N_PCPS_MEM_RSRC; i++ ) + mbg_deallocate_resource( &prsrci->mem[i].bsd ); + + for ( i = 0; i < N_PCPS_PORT_RSRC; i++ ) + mbg_deallocate_resource( &prsrci->port[i].bsd ); + } +} + +static void +mbg_alloc_rsrc( struct mbgclock_softc *psc , int reg, BSD_RSRC_INFO *p_ri, int type ) +{ + p_ri->reg = reg; + p_ri->type = type; + + if (!pci_mapreg_map(&psc->pa, reg, type, 0, + &p_ri->bst, &p_ri->bsh, + &p_ri->base, &p_ri->size)) + { + p_ri->valid = 1; + } else { + p_ri->valid = 0; + } +} + +static void +mbg_alloc_rsrcs( struct mbgclock_softc *psc ) +{ + PCPS_DDEV *pddev = psc->pddev; + PCPS_RSRC_INFO *prsrci = &pddev->rsrc_info; + BSD_RSRC_INFO ri; + int bar; + + /* clear valid flags */ + for ( bar = 0; bar < prsrci->num_rsrc_io; bar ++) + prsrci->port[bar].bsd.valid = 0; + + for ( bar = 0; bar < prsrci->num_rsrc_mem; bar ++) + prsrci->mem[bar].bsd.valid = 0; + + for ( bar = 0; bar < 6; bar ++ ) + { + int type; + int reg = PCI_BAR( bar ); + + _mbgddmsg_4( MBG_DBG_INIT_DEV, + "%s: alloc I/O range %i: PCI device 0x%04X:0x%04X supported", + pcps_driver_name, bar, PCI_VENDOR(psc->pa.pa_id), + PCI_PRODUCT(psc->pa.pa_id) ); + + switch ((type = pci_mapreg_type(psc->pa.pa_pc, psc->pa.pa_tag, reg))) + { + case PCI_MAPREG_TYPE_IO: + if ( prsrci->num_rsrc_io < N_PCPS_PORT_RSRC ) + { + mbg_alloc_rsrc( psc, reg, &ri, type ); + + if ( ri.valid ) + { + prsrci->port[prsrci->num_rsrc_io].bsd = ri; + pcps_add_rsrc_io( pddev, ri.base, ri.size ); + continue; + } + else + { + _mbgddmsg_2( MBG_DBG_INIT_DEV, + "%s: alloc I/O range %i failed", + pcps_driver_name, bar ); + } + } + break; + + case PCI_MAPREG_MEM_TYPE_64BIT: +#if __LP64__ +#if 0 + aprint_error_dev(psc->dev, + "WARNING: ignoring 64-bit BAR @ 0x%02x\n", reg); + continue; +#endif +#else + /*FALLTHROUGH*/ +#endif + case PCI_MAPREG_TYPE_MEM: + /* case PCI_MAPREG_TYPE_ROM: currently same as above */ + if ( prsrci->num_rsrc_mem < N_PCPS_MEM_RSRC ) + { + mbg_alloc_rsrc( psc, reg, &ri, type ); + + if ( ri.valid ) + { + prsrci->mem[prsrci->num_rsrc_mem].bsd = ri; + pcps_add_rsrc_mem( pddev, + (MBG_MEM_ADDR)bus_space_vaddr( ri.bst, ri.bsh), + ri.size ); + continue; + } + } + break; + + default: + printf("XXX unsupported type from pci_mapreg_type: %d\n", type); + break; + } + } + + /* single IRQ resource */ +#if 0 /* currently not used / required */ + mbg_alloc_rsrc( device, 0, &ri, SYS_RES_IRQ, RF_SHAREABLE | RF_ACTIVE ); + + if ( ri.res ) + { + prsrci->port[prsrci->num_rsrc_irq].bsd = ri; + pcps_add_rsrc_irq( pddev, rman_get_start( ri.res ) ); + } +#endif + +} + +static int +mbgclock_match(struct device *parent, struct cfdata *match, void *aux) +{ + struct pci_attach_args *pa; + int16_t vend_id; + int16_t dev_id; + + DPRINTF(DB_FOLLOW, ("mbgclock_match(0x%p, 0x%p, 0x%p)\n", parent, match, aux)); + + pa = aux; + vend_id = PCI_VENDOR(pa->pa_id); + dev_id = PCI_PRODUCT(pa->pa_id); + + if (vend_id == PCI_VENDOR_MEINBERG) + { + PCPS_DEV_TYPE *pdt; + + pdt = pcps_get_dev_type_table_entry( PCPS_BUS_PCI, dev_id ); + + if (pdt != NULL) + { + _mbgddmsg_3( MBG_DBG_INIT_DEV, + "%s: probe: PCI device 0x%04X:0x%04X supported", + pcps_driver_name, vend_id, dev_id ); + + return 1; + } + } + + _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s: probe: PCI device 0x%04X:0x%04X not supported", + pcps_driver_name, vend_id, dev_id ); + return 0; +} + + +static void +mbgclock_attach(struct device *parent, struct device *self, void *aux) +{ + int rc = 0; + int idx; + char devinfo[256]; + struct mbgclock_softc *psc = device_private(self); + struct pci_attach_args *pa = aux; + uint16_t dev_id = PCI_PRODUCT(pa->pa_id); + + DPRINTF(DB_FOLLOW, ("mbgclock_attach(0x%p, 0x%p, 0x%p)\n", parent, self, aux)); + + psc->dev = self; + psc->pa = *pa; + psc->last_status = 0; + + _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: attach for device 0x%04X", + pcps_driver_name, dev_id ); + + psc->pddev = pcps_alloc_ddev(); + + if ( psc->pddev == NULL ) + { + _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: attach device 0x%04X: pcps_alloc_ddev() failed", + pcps_driver_name, dev_id ); + goto fail; + } + + rc = pcps_init_ddev( psc->pddev, PCPS_BUS_PCI, dev_id ); + + if ( rc != PCPS_SUCCESS ) + { + _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s: attach device 0x%04X: pcps_init_ddev() failed, rc: %i", + pcps_driver_name, dev_id, rc ); + goto fail; + } + + mbg_alloc_rsrcs( psc ); + + rc = pcps_probe_device( psc->pddev, 0, 0 ); + + if ( rc != PCPS_SUCCESS ) + { + _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s: attach device 0x%04X: pcps_probe_device() failed, rc: %i", + pcps_driver_name, dev_id, rc ); + goto fail; + } + + idx = snprintf(devinfo, sizeof(devinfo) - idx, "%s", _pcps_type_name( &psc->pddev->dev ) ); + + if ( strlen( _pcps_sernum( &psc->pddev->dev ) ) && + strcmp( _pcps_sernum( &psc->pddev->dev ), "N/A" ) ) + idx += snprintf(devinfo + idx, sizeof(devinfo) - idx, " %s", _pcps_sernum( &psc->pddev->dev ) ); + + idx += snprintf(devinfo + idx, sizeof(devinfo) - idx, " (FW %X.%02X", + _pcps_fw_rev_num_major( _pcps_fw_rev_num( &psc->pddev->dev ) ), + _pcps_fw_rev_num_minor( _pcps_fw_rev_num( &psc->pddev->dev ) ) + ); + + if ( _pcps_has_asic_version( &psc->pddev->dev ) ) + { + PCI_ASIC_VERSION av; + av = _convert_asic_version_number( psc->pddev->raw_asic_version ); + + idx += snprintf(devinfo + idx, sizeof(devinfo) - idx, ", ASIC %X.%02X", + _pcps_asic_version_major( av ), + _pcps_asic_version_minor( av ) + ); + } + + idx += snprintf(devinfo + idx, sizeof(devinfo) - idx, ")" ); + + _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: device 0x%04X attached successfully", + pcps_driver_name, dev_id ); + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + + aprint_normal(": "MBG_VENDOR" %s (rev. 0x%02x)\n", devinfo, + PCI_REVISION(pa->pa_class)); + + mutex_init(&psc->mutex, MUTEX_DEFAULT, IPL_HIGH); + + psc->isopen = 0; + + /* + * prepare timecounter - to have a clean state + */ + psc->tc.tc_get_timecount = mbgclock_get_timecount; + psc->tc.tc_poll_pps = NULL; + psc->tc.tc_counter_mask = ~(uint)0; + /* actually 10 MHz as fraction counter covering 2^32 ticks */ + psc->tc.tc_frequency = 0x100000000ULL; + psc->tc.tc_name = NULL; /* NULL -> not enabled */ + psc->tc.tc_quality = -10000; + psc->tc.tc_priv = psc; + psc->tc.tc_next = NULL; + + /* if we have a counter source register the timecounter */ + if (_pcps_ddev_has_fast_hr_timestamp( psc->pddev )) { + psc->tc.tc_name = device_xname( psc->dev ); + + tc_init(&psc->tc); + } + + callout_init(&psc->callout, CALLOUT_MPSAFE); + + return; + +fail: + pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); + + aprint_normal(": %s (rev. 0x%02x) - not supported\n", devinfo, + PCI_REVISION(pa->pa_class)); + + mbg_dealloc_rsrcs( psc ); + + if ( psc->pddev != NULL ) + pcps_free_ddev( psc->pddev ); + + psc->pddev = NULL; + + _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: failed to attach device 0x%04X", + pcps_driver_name, dev_id ); + return; +} + +static int +mbgclock_detach(struct device *self, int flags) +{ + struct mbgclock_softc *psc = device_private(self); + PCPS_DDEV *pddev; + uint16_t dev_id; + + DPRINTF(DB_FOLLOW, ("mbgclock_detach(0x%p, 0x%x)\n", self, flags)); + + if (psc == NULL) + return ENXIO; + + (void)callout_halt(&psc->callout, &psc->mutex); + + if (psc->tc.tc_name != NULL) { + tc_detach(&psc->tc); + psc->tc.tc_name = NULL; + } + + pddev = psc->pddev; + + dev_id = PCI_PRODUCT(psc->pa.pa_id); + + _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: detach for device 0x%04X", + pcps_driver_name, dev_id ); + + /* XXX insure not outstanding requests */ + mbg_dealloc_rsrcs( psc ); + + if ( psc->pddev != NULL ) { + pcps_free_ddev( psc->pddev ); + pmf_device_deregister(self); + } + + psc->pddev = NULL; + + _mbgddmsg_2( MBG_DBG_INIT_DEV, "%s: device 0x%04X detached", + pcps_driver_name, dev_id ); + + callout_destroy(&psc->callout); + + mutex_destroy(&psc->mutex); + + return 0; +} + +/*------- driver -------*/ + +static +int mbgclockopen(dev_t dev, int flags, int mode, struct lwp *l) +{ + struct mbgclock_softc *psc = device_lookup_private(&mbgclock_cd, MBG_UNIT(dev)); + PCPS_DDEV *pddev; + + _mbgddmsg_1( MBG_DBG_INIT_DEV, "%s: open called", pcps_driver_name ); + DPRINTF(DB_FOLLOW, ("mbgclockopen(0x%"PRIx64", 0x%x, 0x%x, %p)\n", dev, flags, mode, l)); + + if (psc == NULL) + return ENXIO; + + pddev = psc->pddev; + + if (pddev == NULL) + return ENXIO; + + mutex_enter(&psc->mutex); + if (!psc->isopen) { + DPRINTF(DB_FOLLOW, ("mbgclockopen(0x%"PRIx64", 0x%x, 0x%x, %p): first open\n", dev, flags, mode, l)); + psc->isopen = 1; + + INC_REF; + + /* Clear PPS capture state on first open. */ + mutex_spin_enter(&timecounter_lock); + memset(&psc->pps_state, 0, sizeof(psc->pps_state)); + psc->pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; + pps_init(&psc->pps_state); + mutex_spin_exit(&timecounter_lock); + + callout_reset(&psc->callout, hz, mbgclock_tick, psc); + } + mutex_exit(&psc->mutex); + + return 0; +} + +static +int mbgclockclose(dev_t dev, int flags, int mode, struct lwp *l) +{ + struct mbgclock_softc *psc = device_lookup_private(&mbgclock_cd, MBG_UNIT(dev)); + PCPS_DDEV *pddev; + + _mbgddmsg_1( MBG_DBG_INIT_DEV, "%s: close called", pcps_driver_name ); + DPRINTF(DB_FOLLOW,("mbgclockclose(0x%"PRIx64", 0x%x, 0x%x, %p)\n", dev, flags, mode, l)); + + if (psc == NULL) + return ENXIO; + + pddev = psc->pddev; + + if (pddev == NULL) + return ENXIO; + + mutex_enter(&psc->mutex); + psc->isopen = 0; + DEC_REF; + callout_stop(&psc->callout); + mutex_exit(&psc->mutex); + + return 0; +} + +static +int mbgclockread(dev_t dev, struct uio *uio, int flags) +{ + struct mbgclock_softc *psc = device_lookup_private(&mbgclock_cd, MBG_UNIT(dev)); + PCPS_DDEV *pddev; + + _mbgddmsg_1( MBG_DBG_INIT_DEV, "%s: read called", pcps_driver_name ); + DPRINTF(DB_FOLLOW,("mbgclockread(0x%"PRIx64", %p)\n", dev, uio)); + + if (psc == NULL) + return ENXIO; + + pddev = psc->pddev; + + if (pddev == NULL) + return ENXIO; + + return 0; +} + +static +int mbgclockwrite(dev_t dev, struct uio *uio, int flags) +{ + struct mbgclock_softc *psc = device_lookup_private(&mbgclock_cd, MBG_UNIT(dev)); + PCPS_DDEV *pddev; + + _mbgddmsg_1( MBG_DBG_INIT_DEV, "%s: write called", pcps_driver_name ); + DPRINTF(DB_FOLLOW, ("mbgclockwrite(0x%"PRIx64", %p)\n", dev, uio)); + + if (psc == NULL) + return ENXIO; + + pddev = psc->pddev; + + if (pddev == NULL) + return ENXIO; + + return 0; +} + +#include <sys/ioctl.h> + +static +int mbgclockioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) +{ + struct mbgclock_softc *psc = device_lookup_private(&mbgclock_cd, MBG_UNIT(dev)); + PCPS_DDEV *pddev; + int rc; + + _mbgddmsg_1( MBG_DBG_INIT_DEV, "%s: ioctl called", pcps_driver_name ); + DPRINTF(DB_FOLLOW, ("mbgclockioctl(0x%"PRIx64", 0x%lx, %p, 0x%x, %p)\n", + dev, cmd, data, flag, l->l_proc)); + + if (psc == NULL) + return ENXIO; + + pddev = psc->pddev; + + if (pddev == NULL) + return ENXIO; + + switch ( cmd ) + { + case PPS_IOC_CREATE: /* handle PPSAPI */ + case PPS_IOC_DESTROY: + case PPS_IOC_GETPARAMS: + case PPS_IOC_SETPARAMS: + case PPS_IOC_GETCAP: + case PPS_IOC_FETCH: +#ifdef PPS_SYNC + case PPS_IOC_KCBIND: +#endif + mutex_spin_enter(&timecounter_lock); + + rc = pps_ioctl(cmd, data, &psc->pps_state); + + if ((rc == 0) && + (psc->pps_state.kcmode & PPS_CAPTUREBOTH) && + (!_pcps_ddev_has_hr_time( psc->pddev ))) { + psc->pps_state.kcmode = 0; + mutex_spin_exit(&timecounter_lock); + + aprint_error_dev(psc->dev, + "ioctl(KCBIND): high resolution time stamping not supported\n"); + rc = EOPNOTSUPP; + } else { + mutex_spin_exit(&timecounter_lock); + } + + break; + + default: /* handle clock ioctls */ + { + /* Find out which privilege level is required to execute this IOCTL command. */ + int priv_lvl = ioctl_get_required_privilege( cmd ); + + /* Check if the calling process has the required privilege. */ + switch ( priv_lvl ) + { + case MBG_REQ_PRIVL_NONE: + /* Always allow. */ + break; + + case MBG_REQ_PRIVL_EXT_STATUS: + /* This may require some privilege for the calling process. */ + if ((flag & FREAD) == 0 || + kauth_authorize_device_passthru(l->l_cred, + dev, + KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READ, + &cmd)) + { + _mbgddmsg_5( MBG_DBG_INFO, "%s: %p IOCTL 0x%02lX: READ/PASSTHRU READ permission denied, dev %s_%s", + pcps_driver_name, dev, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) ); + return EPERM; + } + break; + + case MBG_REQ_PRIVL_CFG_READ: + /* This may require some privilege for the calling process. */ + if ((flag & FREAD) == 0 || + kauth_authorize_device_passthru(l->l_cred, + dev, + KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF, + &cmd)) + { + _mbgddmsg_5( MBG_DBG_INFO, "%s: %p IOCTL 0x%02lX: READ/PASSTHRU_READCONF permission denied, dev %s_%s", + pcps_driver_name, dev, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) ); + return EPERM; + } + break; + + case MBG_REQ_PRIVL_SYSTEM: + if ((flag & FWRITE) == 0 || + kauth_authorize_device_passthru(l->l_cred, + dev, + KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITE, + &cmd)) + { + _mbgddmsg_5( MBG_DBG_INFO, "%s: %p IOCTL 0x%02lX: WRTIE/PASSTHRU_WRITE permission denied, dev %s_%s", + pcps_driver_name, dev, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) ); + return EPERM; + } + break; + + case MBG_REQ_PRIVL_CFG_WRITE: + if ((flag & FWRITE) == 0 || + kauth_authorize_device_passthru(l->l_cred, + dev, + KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_WRITECONF, + &cmd)) + { + _mbgddmsg_5( MBG_DBG_INFO, "%s: %p IOCTL 0x%02lX: WRITE/PASSTHRU_WRITECONF permission denied, dev %s_%s", + pcps_driver_name, dev, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) ); + return EPERM; + } + break; + + default: + _mbgddmsg_5( MBG_DBG_INFO, "%s: %p IOCTL 0x%02lX: unknown, permission denied, dev %s_%s", + pcps_driver_name, dev, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) ); + return EPERM; + } + + /* + * now do the actual work - access the device + */ + rc = ioctl_switch( pddev, cmd, (void *) data, (void *) data ); + + /* On success we return quickly.*/ + + if ( rc != MBG_SUCCESS ) + { + /* An error has occurred. */ + /* Generate an appropriate debug/error message */ + /* and return an error status. */ + + switch ( rc ) + { + case MBG_ERR_INV_DEV_REQUEST: + _mbgddmsg_7( MBG_DBG_WARN, "%s: %d,%d ioctl 0x%04lX: invalid cmd %04lX, dev %s_%s", + pcps_driver_name, major(dev), minor(dev), cmd, IOCBASECMD( cmd ), + _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) ); + rc = EINVAL; + break; + + + case MBG_ERR_NOT_SUPP_BY_DEV: + _mbgddmsg_6( MBG_DBG_WARN, "%s: %d,%d ioctl 0x%02lX: not supported by dev %s_%s", + pcps_driver_name, major(dev), minor(dev), cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) ); + rc = ENODEV; + break; + + + case MBG_ERR_NO_MEM: + _mbgddmsg_6( MBG_DBG_WARN, "%s: %d,%d ioctl 0x%02lX: unable to allocate buffer for dev %s_%s", + pcps_driver_name, major(dev), minor(dev), cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) ); + rc = ENOMEM; + break; + + + case MBG_ERR_IRQ_UNSAFE: + _mbgddmsg_6( MBG_DBG_DETAIL, "%s: %d,%d ioctl 0x%02lX: busy since unsafe IRQ enabled, dev %s_%s", + pcps_driver_name, major(dev), minor(dev), cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) ); + rc = EBUSY; + break; + + + default: /* any access error code returned by the low level routine */ + /* or copying from or to user space */ + _mbgddmsg_7( MBG_DBG_WARN, "%s: %d,%d ioctl 0x%02lX: error %i accessing dev %s_%s", + pcps_driver_name, major(dev), minor(dev), cmd, rc, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) ); + rc = EIO; + } + } else { + _mbgddmsg_6( MBG_DBG_INFO, "%s: %d,%d IOCTL 0x%02lX: success, dev %p_%s", + pcps_driver_name, major(dev), minor(dev), cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) ); + rc = 0; + } + } + } + + DPRINTF(DB_FOLLOW, ("mbgclockioctl(0x%"PRIx64", 0x%lx, %p, 0x%x, %p) return rc=\n", + dev, cmd, data, flag, l->l_proc, rc)); + + return rc; +} + +static uint +mbgclock_get_timecount(struct timecounter *tc) +{ + struct mbgclock_softc *psc = tc->tc_priv; + PCPS_TIME_STAMP ref_ts; + int s; + + /* pick up reference counter */ + /* + * XXX for now this counter is NOT free running and + * may be re-set at any time - so this is only proof + * of concept code until Meinberg devices provide + * a truely free running counter hanging off the + * frequency controlled oscillator + * also we should only pick up the fraction part saving + * a PCIe bus transaction and change the coordination + * scheme to a generation number base one + */ + s = splhigh(); + /* + * XXX splhigh() shouldn't be necessary, + * but ci_curspl seems to be high after following call + */ + /* + * we only need the fraction + * do_get_fast_hr_timestamp_fraction_safe( psc->pddev, &ref_ts ); + */ + do_get_fast_hr_timestamp_safe( psc->pddev, &ref_ts ); + splx(s); + + /* + * format is correct as it is a fraction counter thus + * our 'frequency' is nominally 0x100000000 Hz + */ + return ref_ts.frac; +} + +static void +mbgclock_tick(void *arg) +{ + struct mbgclock_softc *psc = arg; + struct timeval tv; + + /* + * TODO: should trigger poll machine + */ + +#ifdef _HAVE_PPS_REF_EVENT + /* start work only of we need to provide PPS simulation */ + if (psc->pps_state.ppsparam.mode & PPS_CAPTUREBOTH) { + do { + int rc; + struct pps_state *pps = &psc->pps_state; + struct bintime bintime_ref_ts; + PCPS_HR_TIME ht; + PCPS_TIME_STAMP ref_ts; + int valid; + + if (!_pcps_ddev_has_fast_hr_timestamp( psc->pddev )) { + /* + * pick up status and PPS simulated time stamps + * from HR_TIME operation + */ + mutex_spin_enter(&timecounter_lock); + + /* pick up first system timestamp */ + pps_capture(&psc->pps_state); /* picks up capcount + th */ + + _pcps_sem_inc( psc->pddev ); + rc = _pcps_read_var( psc->pddev, PCPS_GIVE_HR_TIME, ht ); + _pcps_sem_dec( psc->pddev ); + + valid = (rc == MBG_SUCCESS) && + !((ht.status & (PCPS_INVT|PCPS_IFTM|PCPS_FREER) != 0) || + ((ht.status & PCPS_SYNCD) == 0)); + + /* process reftime (picks up second system timestamp) */ + if (valid) { + bintime_ref_ts.sec = ref_ts.sec; + bintime_ref_ts.frac = (uint64_t)ref_ts.frac << 32; + + pps_ref_event(&psc->pps_state, + (psc->pps_state.ppsparam.mode & PPS_CAPTUREASSERT) ? + PPS_CAPTUREASSERT : PPS_CAPTURECLEAR, + &bintime_ref_ts); + } + + mutex_spin_exit(&timecounter_lock); + } else { + /* pick up fast time stamp when clock is ok */ + + _pcps_sem_inc( psc->pddev ); + rc = _pcps_read_var( psc->pddev, PCPS_GIVE_HR_TIME, ht ); + _pcps_sem_dec( psc->pddev ); + + valid = (rc == MBG_SUCCESS) && + !((ht.status & (PCPS_INVT|PCPS_IFTM|PCPS_FREER) != 0) || + ((ht.status & PCPS_SYNCD) == 0)); + + if (valid) { + mutex_spin_enter(&timecounter_lock); + + /* pick up first system timestamp */ + pps_capture(&psc->pps_state); /* picks up capcount + th */ + + /* pick up reference time */ + do_get_fast_hr_timestamp_safe( psc->pddev, &ref_ts ); + + bintime_ref_ts.sec = ref_ts.sec; + bintime_ref_ts.frac = (uint64_t)ref_ts.frac << 32; + + /* process reftime (picks up second system timestamp) */ + pps_ref_event(&psc->pps_state, + (psc->pps_state.ppsparam.mode & PPS_CAPTUREASSERT) ? + PPS_CAPTUREASSERT : PPS_CAPTURECLEAR, + &bintime_ref_ts); + + mutex_spin_exit(&timecounter_lock); + } + } + + /* leave when we cannot the the timestamp */ + if ( rc != MBG_SUCCESS ) { + aprint_error_dev(psc->dev, + "clock read failed\n"); + break; + } + + /* document status changes */ + if (!valid) { + if (ht.status != psc->last_status) { + char b[80]; + snprintb(b, sizeof b, MBG_PCPS_FMT_STATUS, ht.status); + + aprint_error_dev(psc->dev, + "clock nut synchronized: Status=%s\n", + b); + /* XXX kill timecounter - only needed while counter is linked to time */ + if (psc->tc.tc_name != NULL) { + tc_gonebad(&psc->tc); + } + } + psc->last_status = ht.status; + + break; + } + + if ((ht.status ^ psc->last_status) & + (PCPS_INVT|PCPS_IFTM|PCPS_FREER|PCPS_SYNCD)) { + char b[80]; + + snprintb(b, sizeof b, MBG_PCPS_FMT_STATUS, ht.status); + aprint_error_dev(psc->dev, + "clock synchronized: Status=%s\n", + b); + } + + psc->last_status = ht.status; + } while (0); /* for break instead of goto */ + } +#endif + + /* + * calculate next callout shortly after next second + */ + microtime(&tv); + callout_schedule(&psc->callout, hz - mstohz(tv.tv_usec / 1000)); +} |