Annotation of embedaddon/ntp/ports/winnt/ppsapi/skelprov/skeleton-ppsapi-provider.c, revision 1.1.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>