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>