Annotation of embedaddon/ntp/ports/winnt/ppsapi/skelprov/skeleton-ppsapi-provider.c, revision 1.1
1.1 ! misho 1: /*
! 2: * skeleton-ppsapi-provider.c - structure but no useful function
! 3: */
! 4:
! 5: /***********************************************************************
! 6: * *
! 7: * Copyright (c) David L. Mills 1999-2009 *
! 8: * *
! 9: * Permission to use, copy, modify, and distribute this software and *
! 10: * its documentation for any purpose and without fee is hereby *
! 11: * granted, provided that the above copyright notice appears in all *
! 12: * copies and that both the copyright notice and this permission *
! 13: * notice appear in supporting documentation, and that the name *
! 14: * University of Delaware not be used in advertising or publicity *
! 15: * pertaining to distribution of the software without specific, *
! 16: * written prior permission. The University of Delaware makes no *
! 17: * representations about the suitability this software for any *
! 18: * purpose. It is provided "as is" without express or implied *
! 19: * warranty. *
! 20: * *
! 21: ***********************************************************************
! 22: * *
! 23: * This header file complies with "Pulse-Per-Second API for UNIX-like *
! 24: * Operating Systems, Version 1.0", rfc2783. Credit is due Jeff Mogul *
! 25: * and Marc Brett, from whom much of this code was shamelessly stolen. *
! 26: * *
! 27: * This skeleton-ppsapi-provider.c implements the PPSAPI provider DLL *
! 28: * interface but has no actual timestamp-fetching code. It is *
! 29: * derived from serialpps-ppsapi-provider.c which was derived from *
! 30: * David L. Mills' timepps.h for Solaris. *
! 31: * *
! 32: ***********************************************************************
! 33: * *
! 34: * Some of this include file *
! 35: * Copyright (c) 1999 by Ulrich Windl, *
! 36: * based on code by Reg Clemens <reg@dwf.com> *
! 37: * based on code by Poul-Henning Kamp <phk@FreeBSD.org> *
! 38: * *
! 39: ***********************************************************************
! 40: * *
! 41: * "THE BEER-WARE LICENSE" (Revision 42): *
! 42: * <phk@FreeBSD.org> wrote this file. As long as you retain this *
! 43: * notice you can do whatever you want with this stuff. If we meet some*
! 44: * day, and you think this stuff is worth it, you can buy me a beer *
! 45: * in return. Poul-Henning Kamp *
! 46: * *
! 47: **********************************************************************/
! 48:
! 49:
! 50: #include "skeleton-ppsapi-provider.h"
! 51:
! 52: pcreate_pps_handle p_create_pps_handle;
! 53: ppps_ntp_timestamp_from_counter p_ntp_timestamp_from_counter;
! 54:
! 55: #define SKELPPS_CAPS (PPS_CAPTUREASSERT | PPS_OFFSETASSERT \
! 56: | PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)
! 57: #define SKELPPS_RO (PPS_CANWAIT | PPS_CANPOLL)
! 58:
! 59:
! 60: /*
! 61: * The ntp_timestamp_from_counter callback into timepps.h routines in
! 62: * the host is saved in each unit separately, so that binaries that
! 63: * inline timepps.h into multiple source files (such as refclock_atom.c
! 64: * and a number of other ntpd refclocks including refclock_nmea.c) will
! 65: * get called back in the correct instance for each unit. This assumes
! 66: * that ppsapi_prov_init for subsequent instances happens only after the
! 67: * first instance has completed all time_pps_create() calls it will
! 68: * invoke, which is a safe assumption at least for ntpd.
! 69: */
! 70: typedef struct skel_unit_tag {
! 71: HANDLE device;
! 72: ppps_ntp_timestamp_from_counter p_ntp_timestamp_from_counter;
! 73: } skel_unit;
! 74:
! 75:
! 76: /*
! 77: * DllMain - DLL entrypoint, no-op.
! 78: */
! 79: BOOL APIENTRY DllMain(
! 80: HMODULE hModule,
! 81: DWORD ul_reason_for_call,
! 82: LPVOID lpReserved
! 83: )
! 84: {
! 85: UNUSED(hModule);
! 86: UNUSED(ul_reason_for_call);
! 87: UNUSED(lpReserved);
! 88:
! 89: return TRUE;
! 90: }
! 91:
! 92:
! 93: /*
! 94: * prov_time_pps_create - create PPS handle given underlying device
! 95: */
! 96: int WINAPI
! 97: prov_time_pps_create(
! 98: HANDLE device, /* underlying device */
! 99: pps_handle_t * handle /* returned handle */
! 100: )
! 101: {
! 102: skel_unit * pskelunit;
! 103: pps_unit_t * punit;
! 104:
! 105: /*
! 106: * Allocate and initialize unit structure.
! 107: */
! 108:
! 109: pskelunit = malloc(sizeof(*pskelunit));
! 110: if (NULL == pskelunit)
! 111: return ENOMEM;
! 112:
! 113: pskelunit->device = device;
! 114: pskelunit->p_ntp_timestamp_from_counter = p_ntp_timestamp_from_counter;
! 115:
! 116: *handle = (*p_create_pps_handle)(pskelunit);
! 117: if (*handle) {
! 118: punit = (pps_unit_t *)*handle;
! 119: punit->params.api_version = PPS_API_VERS_1;
! 120: punit->params.mode = PPS_CAPTUREASSERT | PPS_TSFMT_TSPEC;
! 121: }
! 122:
! 123: return (*handle)
! 124: ? 0
! 125: : ENOMEM;
! 126: }
! 127:
! 128:
! 129: /*
! 130: * prov_time_pps_destroy - release PPS handle
! 131: */
! 132: int WINAPI
! 133: prov_time_pps_destroy(
! 134: pps_unit_t * unit,
! 135: void * context
! 136: )
! 137: {
! 138: skel_unit *pskelunit;
! 139:
! 140: UNUSED(unit);
! 141:
! 142: pskelunit = context;
! 143: free(pskelunit);
! 144:
! 145: return 0;
! 146: }
! 147:
! 148:
! 149: /*
! 150: * prov_time_pps_setparams - set parameters for handle
! 151: */
! 152: int WINAPI
! 153: prov_time_pps_setparams(
! 154: pps_unit_t * unit,
! 155: void * context,
! 156: const pps_params_t * params
! 157: )
! 158: {
! 159: skel_unit *pskelunit;
! 160: int mode, mode_in;
! 161:
! 162: pskelunit = context;
! 163:
! 164: /*
! 165: * There was no reasonable consensus in the API working group.
! 166: * I require `api_version' to be set!
! 167: */
! 168:
! 169: if (params->api_version != PPS_API_VERS_1)
! 170: return EINVAL;
! 171:
! 172: /*
! 173: * The only settable modes are PPS_CAPTUREASSERT,
! 174: * PPS_OFFSETASSERT, and the timestamp formats.
! 175: */
! 176:
! 177: mode_in = params->mode;
! 178:
! 179: /*
! 180: * Only one of the time formats may be selected
! 181: * if a nonzero assert offset is supplied.
! 182: */
! 183: if ((mode_in & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP))
! 184: == (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) {
! 185:
! 186: if (params->assert_offset.tv_sec ||
! 187: params->assert_offset.tv_nsec)
! 188: return EINVAL;
! 189:
! 190: /*
! 191: * If no offset was specified but both time
! 192: * format flags are used consider it harmless
! 193: * but turn off PPS_TSFMT_NTPFP so getparams
! 194: * will not show both formats lit.
! 195: */
! 196: mode_in &= ~PPS_TSFMT_NTPFP;
! 197: }
! 198:
! 199: /* turn off read-only bits */
! 200:
! 201: mode_in &= ~SKELPPS_RO;
! 202:
! 203: /*
! 204: * test remaining bits, should only have captureassert,
! 205: * offsetassert, and/or timestamp format bits.
! 206: */
! 207:
! 208: if (mode_in & ~(PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
! 209: PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP))
! 210: return EOPNOTSUPP;
! 211:
! 212: /*
! 213: * ok, ready to go.
! 214: */
! 215:
! 216: mode = unit->params.mode;
! 217: unit->params = *params;
! 218: unit->params.mode = mode | mode_in;
! 219:
! 220: return 0;
! 221: }
! 222:
! 223:
! 224: /*
! 225: * prov_time_pps_fetch - Fetch timestamps
! 226: */
! 227:
! 228: int WINAPI
! 229: prov_time_pps_fetch(
! 230: pps_unit_t * unit,
! 231: void * context,
! 232: const int tsformat,
! 233: pps_info_t * pinfo,
! 234: const struct timespec * timeout
! 235: )
! 236: {
! 237: ULONGLONG WindowsTimestamp;
! 238: ULONGLONG Counterstamp;
! 239: skel_unit *pskelunit;
! 240: pps_info_t infobuf;
! 241:
! 242: /*
! 243: * nb. PPS_CANWAIT is NOT set by the implementation, we can totally
! 244: * ignore the timeout variable.
! 245: */
! 246: UNUSED(timeout);
! 247: pskelunit = context;
! 248:
! 249: memset(&infobuf, 0, sizeof(infobuf));
! 250:
! 251: /*
! 252: * if not captureassert, nothing to return.
! 253: */
! 254:
! 255: if (!(unit->params.mode & PPS_CAPTUREASSERT)) {
! 256: *pinfo = infobuf;
! 257: return 0;
! 258: }
! 259:
! 260: /*
! 261: * ADD CODE to retrieve timestamp here.
! 262: */
! 263: WindowsTimestamp = Counterstamp = 0;
! 264: /*
! 265: * ADD CODE to retrieve timestamp here.
! 266: */
! 267:
! 268: /*
! 269: * pps_ntp_timestamp_from_counter takes the two flavors
! 270: * of timestamp we have (counter and system time) and
! 271: * uses whichever it can to give the best NTP fixed-point
! 272: * conversion. In ntpd the Counterstamp is typically
! 273: * used. A stub implementation in timepps.h simply
! 274: * converts from Windows timestamp to NTP fixed-point.
! 275: * We call through a pointer to get ntpd's version.
! 276: */
! 277: (*pskelunit->p_ntp_timestamp_from_counter)(
! 278: &infobuf.assert_timestamp_ntpfp,
! 279: WindowsTimestamp,
! 280: Counterstamp);
! 281:
! 282: /*
! 283: * Note that only assert timestamps
! 284: * are captured by this interface.
! 285: */
! 286: infobuf.assert_sequence = 0; /* ADD CODE */
! 287:
! 288: /*
! 289: * Apply offset and translate to specified format
! 290: */
! 291: switch (tsformat) {
! 292: case PPS_TSFMT_NTPFP: /* NTP format requires no translation */
! 293: if (unit->params.mode & PPS_OFFSETASSERT) {
! 294: NTPFP_L_ADDS(&infobuf.assert_timestamp_ntpfp,
! 295: &unit->params.assert_offset_ntpfp);
! 296: }
! 297: break;
! 298:
! 299: case PPS_TSFMT_TSPEC: /* timespec format requires conversion to nsecs form */
! 300: PPS_NTPTOTSPEC(infobuf.assert_timestamp);
! 301: if (unit->params.mode & PPS_OFFSETASSERT) {
! 302: infobuf.assert_timestamp.tv_sec +=
! 303: unit->params.assert_offset.tv_sec;
! 304: infobuf.assert_timestamp.tv_nsec +=
! 305: unit->params.assert_offset.tv_nsec;
! 306: PPS_NORMALIZE(infobuf.assert_timestamp);
! 307: }
! 308: break;
! 309:
! 310: default:
! 311: return EINVAL;
! 312: }
! 313:
! 314: infobuf.current_mode = unit->params.mode;
! 315: *pinfo = infobuf;
! 316: return (0);
! 317: }
! 318:
! 319:
! 320: /*
! 321: * prov_time_pps_kcbind - specify kernel consumer
! 322: *
! 323: * Not supported so far by Windows.
! 324: */
! 325: int WINAPI
! 326: prov_time_pps_kcbind(
! 327: pps_unit_t * punit,
! 328: void * context,
! 329: const int kernel_consumer,
! 330: const int edge,
! 331: const int tsformat
! 332: )
! 333: {
! 334: UNUSED(punit);
! 335: UNUSED(context);
! 336: UNUSED(kernel_consumer);
! 337: UNUSED(edge);
! 338: UNUSED(tsformat);
! 339:
! 340: return EOPNOTSUPP;
! 341: }
! 342:
! 343:
! 344: /*
! 345: * prov_init - returns capabilities and provider name
! 346: */
! 347: int WINAPI
! 348: ppsapi_prov_init(
! 349: int ppsapi_timepps_prov_ver,
! 350: pcreate_pps_handle create_pps_handle,
! 351: ppps_ntp_timestamp_from_counter ntp_timestamp_from_counter,
! 352: char * short_name_buf,
! 353: size_t short_name_size,
! 354: char * full_name_buf,
! 355: size_t full_name_size
! 356: )
! 357: {
! 358: ppsapi_provider test_prov;
! 359:
! 360: if (ppsapi_timepps_prov_ver < PPSAPI_TIMEPPS_PROV_VER)
! 361: return 0;
! 362:
! 363: p_create_pps_handle = create_pps_handle;
! 364: p_ntp_timestamp_from_counter = ntp_timestamp_from_counter;
! 365:
! 366: strncpy(short_name_buf, "skeleton", short_name_size);
! 367: strncpy(full_name_buf,
! 368: "skeleton, ADD CODE to make useful",
! 369: full_name_size);
! 370:
! 371: /*
! 372: * Use function pointer prototypes from timepps.h to verify
! 373: * our prototypes match with some otherwise pointless code.
! 374: */
! 375: test_prov.ptime_pps_create = &prov_time_pps_create;
! 376: test_prov.ptime_pps_destroy = &prov_time_pps_destroy;
! 377: test_prov.ptime_pps_fetch = &prov_time_pps_fetch;
! 378: test_prov.ptime_pps_kcbind = &prov_time_pps_kcbind;
! 379: test_prov.ptime_pps_setparams = &prov_time_pps_setparams;
! 380:
! 381: return SKELPPS_CAPS;
! 382: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>