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>