aboutsummaryrefslogtreecommitdiff
path: root/ports/winnt/ppsapi/skelprov/skeleton-ppsapi-provider.c
diff options
context:
space:
mode:
Diffstat (limited to 'ports/winnt/ppsapi/skelprov/skeleton-ppsapi-provider.c')
-rw-r--r--ports/winnt/ppsapi/skelprov/skeleton-ppsapi-provider.c382
1 files changed, 382 insertions, 0 deletions
diff --git a/ports/winnt/ppsapi/skelprov/skeleton-ppsapi-provider.c b/ports/winnt/ppsapi/skelprov/skeleton-ppsapi-provider.c
new file mode 100644
index 000000000000..fe15d2972587
--- /dev/null
+++ b/ports/winnt/ppsapi/skelprov/skeleton-ppsapi-provider.c
@@ -0,0 +1,382 @@
+/*
+ * skeleton-ppsapi-provider.c - structure but no useful function
+ */
+
+/***********************************************************************
+ * *
+ * Copyright (c) David L. Mills 1999-2009 *
+ * *
+ * Permission to use, copy, modify, and distribute this software and *
+ * its documentation for any purpose and without fee is hereby *
+ * granted, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission *
+ * notice appear in supporting documentation, and that the name *
+ * University of Delaware not be used in advertising or publicity *
+ * pertaining to distribution of the software without specific, *
+ * written prior permission. The University of Delaware makes no *
+ * representations about the suitability this software for any *
+ * purpose. It is provided "as is" without express or implied *
+ * warranty. *
+ * *
+ ***********************************************************************
+ * *
+ * This header file complies with "Pulse-Per-Second API for UNIX-like *
+ * Operating Systems, Version 1.0", rfc2783. Credit is due Jeff Mogul *
+ * and Marc Brett, from whom much of this code was shamelessly stolen. *
+ * *
+ * This skeleton-ppsapi-provider.c implements the PPSAPI provider DLL *
+ * interface but has no actual timestamp-fetching code. It is *
+ * derived from serialpps-ppsapi-provider.c which was derived from *
+ * David L. Mills' timepps.h for Solaris. *
+ * *
+ ***********************************************************************
+ * *
+ * Some of this include file *
+ * Copyright (c) 1999 by Ulrich Windl, *
+ * based on code by Reg Clemens <reg@dwf.com> *
+ * based on code by Poul-Henning Kamp <phk@FreeBSD.org> *
+ * *
+ ***********************************************************************
+ * *
+ * "THE BEER-WARE LICENSE" (Revision 42): *
+ * <phk@FreeBSD.org> wrote this file. As long as you retain this *
+ * notice you can do whatever you want with this stuff. If we meet some*
+ * day, and you think this stuff is worth it, you can buy me a beer *
+ * in return. Poul-Henning Kamp *
+ * *
+ **********************************************************************/
+
+
+#include "skeleton-ppsapi-provider.h"
+
+pcreate_pps_handle p_create_pps_handle;
+ppps_ntp_timestamp_from_counter p_ntp_timestamp_from_counter;
+
+#define SKELPPS_CAPS (PPS_CAPTUREASSERT | PPS_OFFSETASSERT \
+ | PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)
+#define SKELPPS_RO (PPS_CANWAIT | PPS_CANPOLL)
+
+
+/*
+ * The ntp_timestamp_from_counter callback into timepps.h routines in
+ * the host is saved in each unit separately, so that binaries that
+ * inline timepps.h into multiple source files (such as refclock_atom.c
+ * and a number of other ntpd refclocks including refclock_nmea.c) will
+ * get called back in the correct instance for each unit. This assumes
+ * that ppsapi_prov_init for subsequent instances happens only after the
+ * first instance has completed all time_pps_create() calls it will
+ * invoke, which is a safe assumption at least for ntpd.
+ */
+typedef struct skel_unit_tag {
+ HANDLE device;
+ ppps_ntp_timestamp_from_counter p_ntp_timestamp_from_counter;
+} skel_unit;
+
+
+/*
+ * DllMain - DLL entrypoint, no-op.
+ */
+BOOL APIENTRY DllMain(
+ HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ UNUSED(hModule);
+ UNUSED(ul_reason_for_call);
+ UNUSED(lpReserved);
+
+ return TRUE;
+}
+
+
+/*
+ * prov_time_pps_create - create PPS handle given underlying device
+ */
+int WINAPI
+prov_time_pps_create(
+ HANDLE device, /* underlying device */
+ pps_handle_t * handle /* returned handle */
+ )
+{
+ skel_unit * pskelunit;
+ pps_unit_t * punit;
+
+ /*
+ * Allocate and initialize unit structure.
+ */
+
+ pskelunit = malloc(sizeof(*pskelunit));
+ if (NULL == pskelunit)
+ return ENOMEM;
+
+ pskelunit->device = device;
+ pskelunit->p_ntp_timestamp_from_counter = p_ntp_timestamp_from_counter;
+
+ *handle = (*p_create_pps_handle)(pskelunit);
+ if (*handle) {
+ punit = (pps_unit_t *)*handle;
+ punit->params.api_version = PPS_API_VERS_1;
+ punit->params.mode = PPS_CAPTUREASSERT | PPS_TSFMT_TSPEC;
+ }
+
+ return (*handle)
+ ? 0
+ : ENOMEM;
+}
+
+
+/*
+ * prov_time_pps_destroy - release PPS handle
+ */
+int WINAPI
+prov_time_pps_destroy(
+ pps_unit_t * unit,
+ void * context
+ )
+{
+ skel_unit *pskelunit;
+
+ UNUSED(unit);
+
+ pskelunit = context;
+ free(pskelunit);
+
+ return 0;
+}
+
+
+/*
+ * prov_time_pps_setparams - set parameters for handle
+ */
+int WINAPI
+prov_time_pps_setparams(
+ pps_unit_t * unit,
+ void * context,
+ const pps_params_t * params
+ )
+{
+ skel_unit *pskelunit;
+ int mode, mode_in;
+
+ pskelunit = context;
+
+ /*
+ * There was no reasonable consensus in the API working group.
+ * I require `api_version' to be set!
+ */
+
+ if (params->api_version != PPS_API_VERS_1)
+ return EINVAL;
+
+ /*
+ * The only settable modes are PPS_CAPTUREASSERT,
+ * PPS_OFFSETASSERT, and the timestamp formats.
+ */
+
+ mode_in = params->mode;
+
+ /*
+ * Only one of the time formats may be selected
+ * if a nonzero assert offset is supplied.
+ */
+ if ((mode_in & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP))
+ == (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) {
+
+ if (params->assert_offset.tv_sec ||
+ params->assert_offset.tv_nsec)
+ return EINVAL;
+
+ /*
+ * If no offset was specified but both time
+ * format flags are used consider it harmless
+ * but turn off PPS_TSFMT_NTPFP so getparams
+ * will not show both formats lit.
+ */
+ mode_in &= ~PPS_TSFMT_NTPFP;
+ }
+
+ /* turn off read-only bits */
+
+ mode_in &= ~SKELPPS_RO;
+
+ /*
+ * test remaining bits, should only have captureassert,
+ * offsetassert, and/or timestamp format bits.
+ */
+
+ if (mode_in & ~(PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
+ PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP))
+ return EOPNOTSUPP;
+
+ /*
+ * ok, ready to go.
+ */
+
+ mode = unit->params.mode;
+ unit->params = *params;
+ unit->params.mode = mode | mode_in;
+
+ return 0;
+}
+
+
+/*
+ * prov_time_pps_fetch - Fetch timestamps
+ */
+
+int WINAPI
+prov_time_pps_fetch(
+ pps_unit_t * unit,
+ void * context,
+ const int tsformat,
+ pps_info_t * pinfo,
+ const struct timespec * timeout
+ )
+{
+ ULONGLONG WindowsTimestamp;
+ ULONGLONG Counterstamp;
+ skel_unit *pskelunit;
+ pps_info_t infobuf;
+
+ /*
+ * nb. PPS_CANWAIT is NOT set by the implementation, we can totally
+ * ignore the timeout variable.
+ */
+ UNUSED(timeout);
+ pskelunit = context;
+
+ memset(&infobuf, 0, sizeof(infobuf));
+
+ /*
+ * if not captureassert, nothing to return.
+ */
+
+ if (!(unit->params.mode & PPS_CAPTUREASSERT)) {
+ *pinfo = infobuf;
+ return 0;
+ }
+
+ /*
+ * ADD CODE to retrieve timestamp here.
+ */
+ WindowsTimestamp = Counterstamp = 0;
+ /*
+ * ADD CODE to retrieve timestamp here.
+ */
+
+ /*
+ * pps_ntp_timestamp_from_counter takes the two flavors
+ * of timestamp we have (counter and system time) and
+ * uses whichever it can to give the best NTP fixed-point
+ * conversion. In ntpd the Counterstamp is typically
+ * used. A stub implementation in timepps.h simply
+ * converts from Windows timestamp to NTP fixed-point.
+ * We call through a pointer to get ntpd's version.
+ */
+ (*pskelunit->p_ntp_timestamp_from_counter)(
+ &infobuf.assert_timestamp_ntpfp,
+ WindowsTimestamp,
+ Counterstamp);
+
+ /*
+ * Note that only assert timestamps
+ * are captured by this interface.
+ */
+ infobuf.assert_sequence = 0; /* ADD CODE */
+
+ /*
+ * Apply offset and translate to specified format
+ */
+ switch (tsformat) {
+ case PPS_TSFMT_NTPFP: /* NTP format requires no translation */
+ if (unit->params.mode & PPS_OFFSETASSERT) {
+ NTPFP_L_ADDS(&infobuf.assert_timestamp_ntpfp,
+ &unit->params.assert_offset_ntpfp);
+ }
+ break;
+
+ case PPS_TSFMT_TSPEC: /* timespec format requires conversion to nsecs form */
+ PPS_NTPTOTSPEC(infobuf.assert_timestamp);
+ if (unit->params.mode & PPS_OFFSETASSERT) {
+ infobuf.assert_timestamp.tv_sec +=
+ unit->params.assert_offset.tv_sec;
+ infobuf.assert_timestamp.tv_nsec +=
+ unit->params.assert_offset.tv_nsec;
+ PPS_NORMALIZE(infobuf.assert_timestamp);
+ }
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ infobuf.current_mode = unit->params.mode;
+ *pinfo = infobuf;
+ return (0);
+}
+
+
+/*
+ * prov_time_pps_kcbind - specify kernel consumer
+ *
+ * Not supported so far by Windows.
+ */
+int WINAPI
+prov_time_pps_kcbind(
+ pps_unit_t * punit,
+ void * context,
+ const int kernel_consumer,
+ const int edge,
+ const int tsformat
+ )
+{
+ UNUSED(punit);
+ UNUSED(context);
+ UNUSED(kernel_consumer);
+ UNUSED(edge);
+ UNUSED(tsformat);
+
+ return EOPNOTSUPP;
+}
+
+
+/*
+ * prov_init - returns capabilities and provider name
+ */
+int WINAPI
+ppsapi_prov_init(
+ int ppsapi_timepps_prov_ver,
+ pcreate_pps_handle create_pps_handle,
+ ppps_ntp_timestamp_from_counter ntp_timestamp_from_counter,
+ char * short_name_buf,
+ size_t short_name_size,
+ char * full_name_buf,
+ size_t full_name_size
+ )
+{
+ ppsapi_provider test_prov;
+
+ if (ppsapi_timepps_prov_ver < PPSAPI_TIMEPPS_PROV_VER)
+ return 0;
+
+ p_create_pps_handle = create_pps_handle;
+ p_ntp_timestamp_from_counter = ntp_timestamp_from_counter;
+
+ strncpy(short_name_buf, "skeleton", short_name_size);
+ strncpy(full_name_buf,
+ "skeleton, ADD CODE to make useful",
+ full_name_size);
+
+ /*
+ * Use function pointer prototypes from timepps.h to verify
+ * our prototypes match with some otherwise pointless code.
+ */
+ test_prov.ptime_pps_create = &prov_time_pps_create;
+ test_prov.ptime_pps_destroy = &prov_time_pps_destroy;
+ test_prov.ptime_pps_fetch = &prov_time_pps_fetch;
+ test_prov.ptime_pps_kcbind = &prov_time_pps_kcbind;
+ test_prov.ptime_pps_setparams = &prov_time_pps_setparams;
+
+ return SKELPPS_CAPS;
+}