1ea906c41SOllivier Robert /***********************************************************************
2ea906c41SOllivier Robert * *
3ea906c41SOllivier Robert * Copyright (c) David L. Mills 1999-2000 *
4ea906c41SOllivier Robert * *
5ea906c41SOllivier Robert * Permission to use, copy, modify, and distribute this software and *
6*2b15cb3dSCy Schubert * its documentation for any purpose and with or without fee is hereby *
7ea906c41SOllivier Robert * granted, provided that the above copyright notice appears in all *
8ea906c41SOllivier Robert * copies and that both the copyright notice and this permission *
9ea906c41SOllivier Robert * notice appear in supporting documentation, and that the name *
10ea906c41SOllivier Robert * University of Delaware not be used in advertising or publicity *
11ea906c41SOllivier Robert * pertaining to distribution of the software without specific, *
12ea906c41SOllivier Robert * written prior permission. The University of Delaware makes no *
13ea906c41SOllivier Robert * representations about the suitability this software for any *
14ea906c41SOllivier Robert * purpose. It is provided "as is" without express or implied *
15ea906c41SOllivier Robert * warranty. *
16ea906c41SOllivier Robert * *
17ea906c41SOllivier Robert ***********************************************************************
18ea906c41SOllivier Robert * *
19ea906c41SOllivier Robert * This header file complies with "Pulse-Per-Second API for UNIX-like *
20ea906c41SOllivier Robert * Operating Systems, Version 1.0", rfc2783. Credit is due Jeff Mogul *
21ea906c41SOllivier Robert * and Marc Brett, from whom much of this code was shamelessly stolen. *
22ea906c41SOllivier Robert * *
23ea906c41SOllivier Robert * this modified timepps.h can be used to provide a PPSAPI interface *
24ea906c41SOllivier Robert * to a machine running SunOS. *
25ea906c41SOllivier Robert * *
26ea906c41SOllivier Robert ***********************************************************************
27ea906c41SOllivier Robert * *
28ea906c41SOllivier Robert * A full PPSAPI interface to the SunOS kernel would be better, but *
29ea906c41SOllivier Robert * this at least removes the necessity for special coding from the NTP *
30ea906c41SOllivier Robert * NTP drivers. *
31ea906c41SOllivier Robert * *
32ea906c41SOllivier Robert ***********************************************************************
33ea906c41SOllivier Robert * *
34ea906c41SOllivier Robert * Some of this include file *
35ea906c41SOllivier Robert * Copyright (c) 1999 by Ulrich Windl, *
36ea906c41SOllivier Robert * based on code by Reg Clemens <reg@dwf.com> *
37ea906c41SOllivier Robert * based on code by Poul-Henning Kamp <phk@FreeBSD.org> *
38ea906c41SOllivier Robert * *
39ea906c41SOllivier Robert ***********************************************************************
40ea906c41SOllivier Robert * *
41ea906c41SOllivier Robert * "THE BEER-WARE LICENSE" (Revision 42): *
42ea906c41SOllivier Robert * <phk@FreeBSD.org> wrote this file. As long as you retain this *
43ea906c41SOllivier Robert * notice you can do whatever you want with this stuff. If we meet some*
44ea906c41SOllivier Robert * day, and you think this stuff is worth it, you can buy me a beer *
45ea906c41SOllivier Robert * in return. Poul-Henning Kamp *
46ea906c41SOllivier Robert * *
47ea906c41SOllivier Robert **********************************************************************/
48ea906c41SOllivier Robert
49ea906c41SOllivier Robert /* SunOS version, CIOGETEV assumed to exist for SunOS */
50ea906c41SOllivier Robert
51ea906c41SOllivier Robert #ifndef _SYS_TIMEPPS_H_
52ea906c41SOllivier Robert #define _SYS_TIMEPPS_H_
53ea906c41SOllivier Robert
54ea906c41SOllivier Robert #include <termios.h> /* to get CIOGETEV */
55ea906c41SOllivier Robert
56ea906c41SOllivier Robert /* Implementation note: the logical states ``assert'' and ``clear''
57ea906c41SOllivier Robert * are implemented in terms of the UART register, i.e. ``assert''
58ea906c41SOllivier Robert * means the bit is set.
59ea906c41SOllivier Robert */
60ea906c41SOllivier Robert
61ea906c41SOllivier Robert /*
62ea906c41SOllivier Robert * The following definitions are architecture independent
63ea906c41SOllivier Robert */
64ea906c41SOllivier Robert
65ea906c41SOllivier Robert #define PPS_API_VERS_1 1 /* API version number */
66ea906c41SOllivier Robert #define PPS_JAN_1970 2208988800UL /* 1970 - 1900 in seconds */
67ea906c41SOllivier Robert #define PPS_NANOSECOND 1000000000L /* one nanosecond in decimal */
68ea906c41SOllivier Robert #define PPS_FRAC 4294967296. /* 2^32 as a double */
69ea906c41SOllivier Robert
70ea906c41SOllivier Robert #define PPS_NORMALIZE(x) /* normalize timespec */ \
71ea906c41SOllivier Robert do { \
72ea906c41SOllivier Robert if ((x).tv_nsec >= PPS_NANOSECOND) { \
73ea906c41SOllivier Robert (x).tv_nsec -= PPS_NANOSECOND; \
74ea906c41SOllivier Robert (x).tv_sec++; \
75ea906c41SOllivier Robert } else if ((x).tv_nsec < 0) { \
76ea906c41SOllivier Robert (x).tv_nsec += PPS_NANOSECOND; \
77ea906c41SOllivier Robert (x).tv_sec--; \
78ea906c41SOllivier Robert } \
79ea906c41SOllivier Robert } while (0)
80ea906c41SOllivier Robert
81ea906c41SOllivier Robert #define PPS_TSPECTONTP(x) /* convert timespec to l_fp */ \
82ea906c41SOllivier Robert do { \
83ea906c41SOllivier Robert double d_temp; \
84ea906c41SOllivier Robert \
85ea906c41SOllivier Robert (x).integral += (unsigned int)PPS_JAN_1970; \
86ea906c41SOllivier Robert d_temp = (x).fractional * PPS_FRAC / PPS_NANOSECOND; \
87ea906c41SOllivier Robert if (d_temp >= PPS_FRAC) \
88ea906c41SOllivier Robert (x).integral++; \
89ea906c41SOllivier Robert (x).fractional = (unsigned int)d_temp; \
90ea906c41SOllivier Robert } while (0)
91ea906c41SOllivier Robert
92ea906c41SOllivier Robert /*
93ea906c41SOllivier Robert * Device/implementation parameters (mode)
94ea906c41SOllivier Robert */
95ea906c41SOllivier Robert
96ea906c41SOllivier Robert #define PPS_CAPTUREASSERT 0x01 /* capture assert events */
97ea906c41SOllivier Robert #define PPS_CAPTURECLEAR 0x02 /* capture clear events */
98ea906c41SOllivier Robert #define PPS_CAPTUREBOTH 0x03 /* capture assert and clear events */
99ea906c41SOllivier Robert
100ea906c41SOllivier Robert #define PPS_OFFSETASSERT 0x10 /* apply compensation for assert ev. */
101ea906c41SOllivier Robert #define PPS_OFFSETCLEAR 0x20 /* apply compensation for clear ev. */
102ea906c41SOllivier Robert #define PPS_OFFSETBOTH 0x30 /* apply compensation for both */
103ea906c41SOllivier Robert
104ea906c41SOllivier Robert #define PPS_CANWAIT 0x100 /* Can we wait for an event? */
105ea906c41SOllivier Robert #define PPS_CANPOLL 0x200 /* "This bit is reserved for */
106ea906c41SOllivier Robert
107ea906c41SOllivier Robert /*
108ea906c41SOllivier Robert * Kernel actions (mode)
109ea906c41SOllivier Robert */
110ea906c41SOllivier Robert
111ea906c41SOllivier Robert #define PPS_ECHOASSERT 0x40 /* feed back assert event to output */
112ea906c41SOllivier Robert #define PPS_ECHOCLEAR 0x80 /* feed back clear event to output */
113ea906c41SOllivier Robert
114ea906c41SOllivier Robert /*
115ea906c41SOllivier Robert * Timestamp formats (tsformat)
116ea906c41SOllivier Robert */
117ea906c41SOllivier Robert
118ea906c41SOllivier Robert #define PPS_TSFMT_TSPEC 0x1000 /* select timespec format */
119ea906c41SOllivier Robert #define PPS_TSFMT_NTPFP 0x2000 /* select NTP format */
120ea906c41SOllivier Robert
121ea906c41SOllivier Robert /*
122ea906c41SOllivier Robert * Kernel discipline actions (not used in SunOS)
123ea906c41SOllivier Robert */
124ea906c41SOllivier Robert
125ea906c41SOllivier Robert #define PPS_KC_HARDPPS 0 /* enable kernel consumer */
126ea906c41SOllivier Robert #define PPS_KC_HARDPPS_PLL 1 /* phase-lock mode */
127ea906c41SOllivier Robert #define PPS_KC_HARDPPS_FLL 2 /* frequency-lock mode */
128ea906c41SOllivier Robert
129ea906c41SOllivier Robert /*
130ea906c41SOllivier Robert * Type definitions
131ea906c41SOllivier Robert */
132ea906c41SOllivier Robert
133ea906c41SOllivier Robert typedef unsigned long pps_seq_t; /* sequence number */
134ea906c41SOllivier Robert
135ea906c41SOllivier Robert typedef struct ntp_fp {
136ea906c41SOllivier Robert unsigned int integral;
137ea906c41SOllivier Robert unsigned int fractional;
138ea906c41SOllivier Robert } ntp_fp_t; /* NTP-compatible time stamp */
139ea906c41SOllivier Robert
140ea906c41SOllivier Robert typedef union pps_timeu { /* timestamp format */
141ea906c41SOllivier Robert struct timespec tspec;
142ea906c41SOllivier Robert ntp_fp_t ntpfp;
143ea906c41SOllivier Robert unsigned long longpad[3];
144ea906c41SOllivier Robert } pps_timeu_t; /* generic data type to represent time stamps */
145ea906c41SOllivier Robert
146ea906c41SOllivier Robert /*
147ea906c41SOllivier Robert * Timestamp information structure
148ea906c41SOllivier Robert */
149ea906c41SOllivier Robert
150ea906c41SOllivier Robert typedef struct pps_info {
151ea906c41SOllivier Robert pps_seq_t assert_sequence; /* seq. num. of assert event */
152ea906c41SOllivier Robert pps_seq_t clear_sequence; /* seq. num. of clear event */
153ea906c41SOllivier Robert pps_timeu_t assert_tu; /* time of assert event */
154ea906c41SOllivier Robert pps_timeu_t clear_tu; /* time of clear event */
155ea906c41SOllivier Robert int current_mode; /* current mode bits */
156ea906c41SOllivier Robert } pps_info_t;
157ea906c41SOllivier Robert
158ea906c41SOllivier Robert #define assert_timestamp assert_tu.tspec
159ea906c41SOllivier Robert #define clear_timestamp clear_tu.tspec
160ea906c41SOllivier Robert
161ea906c41SOllivier Robert #define assert_timestamp_ntpfp assert_tu.ntpfp
162ea906c41SOllivier Robert #define clear_timestamp_ntpfp clear_tu.ntpfp
163ea906c41SOllivier Robert
164ea906c41SOllivier Robert /*
165ea906c41SOllivier Robert * Parameter structure
166ea906c41SOllivier Robert */
167ea906c41SOllivier Robert
168ea906c41SOllivier Robert typedef struct pps_params {
169ea906c41SOllivier Robert int api_version; /* API version # */
170ea906c41SOllivier Robert int mode; /* mode bits */
171ea906c41SOllivier Robert pps_timeu_t assert_off_tu; /* offset compensation for assert */
172ea906c41SOllivier Robert pps_timeu_t clear_off_tu; /* offset compensation for clear */
173ea906c41SOllivier Robert } pps_params_t;
174ea906c41SOllivier Robert
175ea906c41SOllivier Robert #define assert_offset assert_off_tu.tspec
176ea906c41SOllivier Robert #define clear_offset clear_off_tu.tspec
177ea906c41SOllivier Robert
178ea906c41SOllivier Robert #define assert_offset_ntpfp assert_off_tu.ntpfp
179ea906c41SOllivier Robert #define clear_offset_ntpfp clear_off_tu.ntpfp
180ea906c41SOllivier Robert
181ea906c41SOllivier Robert /*
182ea906c41SOllivier Robert * The following definitions are architecture-dependent
183ea906c41SOllivier Robert */
184ea906c41SOllivier Robert
185ea906c41SOllivier Robert #define PPS_CAP (PPS_CAPTUREASSERT | PPS_OFFSETASSERT | PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)
186ea906c41SOllivier Robert #define PPS_RO (PPS_CANWAIT | PPS_CANPOLL | PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)
187ea906c41SOllivier Robert
188ea906c41SOllivier Robert typedef struct {
189ea906c41SOllivier Robert int filedes; /* file descriptor */
190ea906c41SOllivier Robert pps_params_t params; /* PPS parameters set by user */
191ea906c41SOllivier Robert } pps_unit_t;
192ea906c41SOllivier Robert
193ea906c41SOllivier Robert typedef pps_unit_t* pps_handle_t; /* pps handlebars */
194ea906c41SOllivier Robert
195ea906c41SOllivier Robert /*
196ea906c41SOllivier Robert *------ Here begins the implementation-specific part! ------
197ea906c41SOllivier Robert */
198ea906c41SOllivier Robert
199ea906c41SOllivier Robert #include <errno.h>
200ea906c41SOllivier Robert
201ea906c41SOllivier Robert /*
202ea906c41SOllivier Robert * create PPS handle from file descriptor
203ea906c41SOllivier Robert */
204ea906c41SOllivier Robert
205ea906c41SOllivier Robert static inline int
time_pps_create(int filedes,pps_handle_t * handle)206ea906c41SOllivier Robert time_pps_create(
207ea906c41SOllivier Robert int filedes, /* file descriptor */
208ea906c41SOllivier Robert pps_handle_t *handle /* returned handle */
209ea906c41SOllivier Robert )
210ea906c41SOllivier Robert {
211ea906c41SOllivier Robert /*
212ea906c41SOllivier Robert * Check for valid arguments and attach PPS signal.
213ea906c41SOllivier Robert */
214ea906c41SOllivier Robert
215ea906c41SOllivier Robert if (!handle) {
216ea906c41SOllivier Robert errno = EFAULT;
217ea906c41SOllivier Robert return (-1); /* null pointer */
218ea906c41SOllivier Robert }
219ea906c41SOllivier Robert
220ea906c41SOllivier Robert if (ioctl(filedes, I_PUSH, "ppsclock") < 0) {
221ea906c41SOllivier Robert perror("time_pps_create: I_PUSH ppsclock failed");
222ea906c41SOllivier Robert return (-1);
223ea906c41SOllivier Robert }
224ea906c41SOllivier Robert
225ea906c41SOllivier Robert /*
226ea906c41SOllivier Robert * Allocate and initialize default unit structure.
227ea906c41SOllivier Robert */
228ea906c41SOllivier Robert
229ea906c41SOllivier Robert *handle = malloc(sizeof(pps_unit_t));
230ea906c41SOllivier Robert if (!(*handle)) {
231ea906c41SOllivier Robert errno = EBADF;
232ea906c41SOllivier Robert return (-1); /* what, no memory? */
233ea906c41SOllivier Robert }
234ea906c41SOllivier Robert
235ea906c41SOllivier Robert memset(*handle, 0, sizeof(pps_unit_t));
236ea906c41SOllivier Robert (*handle)->filedes = filedes;
237ea906c41SOllivier Robert (*handle)->params.api_version = PPS_API_VERS_1;
238ea906c41SOllivier Robert (*handle)->params.mode = PPS_CAPTUREASSERT | PPS_TSFMT_TSPEC;
239ea906c41SOllivier Robert return (0);
240ea906c41SOllivier Robert }
241ea906c41SOllivier Robert
242ea906c41SOllivier Robert /*
243ea906c41SOllivier Robert * release PPS handle
244ea906c41SOllivier Robert */
245ea906c41SOllivier Robert
246ea906c41SOllivier Robert static inline int
time_pps_destroy(pps_handle_t handle)247ea906c41SOllivier Robert time_pps_destroy(
248ea906c41SOllivier Robert pps_handle_t handle
249ea906c41SOllivier Robert )
250ea906c41SOllivier Robert {
251ea906c41SOllivier Robert /*
252ea906c41SOllivier Robert * Check for valid arguments and detach PPS signal.
253ea906c41SOllivier Robert */
254ea906c41SOllivier Robert
255ea906c41SOllivier Robert if (!handle) {
256ea906c41SOllivier Robert errno = EBADF;
257ea906c41SOllivier Robert return (-1); /* bad handle */
258ea906c41SOllivier Robert }
259ea906c41SOllivier Robert free(handle);
260ea906c41SOllivier Robert return (0);
261ea906c41SOllivier Robert }
262ea906c41SOllivier Robert
263ea906c41SOllivier Robert /*
264ea906c41SOllivier Robert * set parameters for handle
265ea906c41SOllivier Robert */
266ea906c41SOllivier Robert
267ea906c41SOllivier Robert static inline int
time_pps_setparams(pps_handle_t handle,const pps_params_t * params)268ea906c41SOllivier Robert time_pps_setparams(
269ea906c41SOllivier Robert pps_handle_t handle,
270ea906c41SOllivier Robert const pps_params_t *params
271ea906c41SOllivier Robert )
272ea906c41SOllivier Robert {
273ea906c41SOllivier Robert int mode, mode_in;
274ea906c41SOllivier Robert /*
275ea906c41SOllivier Robert * Check for valid arguments and set parameters.
276ea906c41SOllivier Robert */
277ea906c41SOllivier Robert
278ea906c41SOllivier Robert if (!handle) {
279ea906c41SOllivier Robert errno = EBADF;
280ea906c41SOllivier Robert return (-1); /* bad handle */
281ea906c41SOllivier Robert }
282ea906c41SOllivier Robert
283ea906c41SOllivier Robert if (!params) {
284ea906c41SOllivier Robert errno = EFAULT;
285ea906c41SOllivier Robert return (-1); /* bad argument */
286ea906c41SOllivier Robert }
287ea906c41SOllivier Robert
288ea906c41SOllivier Robert /*
289ea906c41SOllivier Robert * There was no reasonable consensu in the API working group.
290ea906c41SOllivier Robert * I require `api_version' to be set!
291ea906c41SOllivier Robert */
292ea906c41SOllivier Robert
293ea906c41SOllivier Robert if (params->api_version != PPS_API_VERS_1) {
294ea906c41SOllivier Robert errno = EINVAL;
295ea906c41SOllivier Robert return(-1);
296ea906c41SOllivier Robert }
297ea906c41SOllivier Robert
298ea906c41SOllivier Robert /*
299ea906c41SOllivier Robert * only settable modes are PPS_CAPTUREASSERT and PPS_OFFSETASSERT
300ea906c41SOllivier Robert */
301ea906c41SOllivier Robert
302ea906c41SOllivier Robert mode_in = params->mode;
303ea906c41SOllivier Robert
304ea906c41SOllivier Robert /* turn off read-only bits */
305ea906c41SOllivier Robert
306ea906c41SOllivier Robert mode_in &= ~PPS_RO;
307ea906c41SOllivier Robert
308ea906c41SOllivier Robert /* test remaining bits, should only have captureassert and/or offsetassert */
309ea906c41SOllivier Robert
310ea906c41SOllivier Robert if (mode_in & ~(PPS_CAPTUREASSERT | PPS_OFFSETASSERT)) {
311ea906c41SOllivier Robert errno = EOPNOTSUPP;
312ea906c41SOllivier Robert return(-1);
313ea906c41SOllivier Robert }
314ea906c41SOllivier Robert
315ea906c41SOllivier Robert /*
316ea906c41SOllivier Robert * ok, ready to go.
317ea906c41SOllivier Robert */
318ea906c41SOllivier Robert
319ea906c41SOllivier Robert mode = handle->params.mode;
320ea906c41SOllivier Robert memcpy(&handle->params, params, sizeof(pps_params_t));
321ea906c41SOllivier Robert handle->params.api_version = PPS_API_VERS_1;
322ea906c41SOllivier Robert handle->params.mode = mode | mode_in;
323ea906c41SOllivier Robert return (0);
324ea906c41SOllivier Robert }
325ea906c41SOllivier Robert
326ea906c41SOllivier Robert /*
327ea906c41SOllivier Robert * get parameters for handle
328ea906c41SOllivier Robert */
329ea906c41SOllivier Robert
330ea906c41SOllivier Robert static inline int
time_pps_getparams(pps_handle_t handle,pps_params_t * params)331ea906c41SOllivier Robert time_pps_getparams(
332ea906c41SOllivier Robert pps_handle_t handle,
333ea906c41SOllivier Robert pps_params_t *params
334ea906c41SOllivier Robert )
335ea906c41SOllivier Robert {
336ea906c41SOllivier Robert /*
337ea906c41SOllivier Robert * Check for valid arguments and get parameters.
338ea906c41SOllivier Robert */
339ea906c41SOllivier Robert
340ea906c41SOllivier Robert if (!handle) {
341ea906c41SOllivier Robert errno = EBADF;
342ea906c41SOllivier Robert return (-1); /* bad handle */
343ea906c41SOllivier Robert }
344ea906c41SOllivier Robert
345ea906c41SOllivier Robert if (!params) {
346ea906c41SOllivier Robert errno = EFAULT;
347ea906c41SOllivier Robert return (-1); /* bad argument */
348ea906c41SOllivier Robert }
349ea906c41SOllivier Robert
350ea906c41SOllivier Robert memcpy(params, &handle->params, sizeof(pps_params_t));
351ea906c41SOllivier Robert return (0);
352ea906c41SOllivier Robert }
353ea906c41SOllivier Robert
354ea906c41SOllivier Robert /* (
355ea906c41SOllivier Robert * get capabilities for handle
356ea906c41SOllivier Robert */
357ea906c41SOllivier Robert
358ea906c41SOllivier Robert static inline int
time_pps_getcap(pps_handle_t handle,int * mode)359ea906c41SOllivier Robert time_pps_getcap(
360ea906c41SOllivier Robert pps_handle_t handle,
361ea906c41SOllivier Robert int *mode
362ea906c41SOllivier Robert )
363ea906c41SOllivier Robert {
364ea906c41SOllivier Robert /*
365ea906c41SOllivier Robert * Check for valid arguments and get capabilities.
366ea906c41SOllivier Robert */
367ea906c41SOllivier Robert
368ea906c41SOllivier Robert if (!handle) {
369ea906c41SOllivier Robert errno = EBADF;
370ea906c41SOllivier Robert return (-1); /* bad handle */
371ea906c41SOllivier Robert }
372ea906c41SOllivier Robert
373ea906c41SOllivier Robert if (!mode) {
374ea906c41SOllivier Robert errno = EFAULT;
375ea906c41SOllivier Robert return (-1); /* bad argument */
376ea906c41SOllivier Robert }
377ea906c41SOllivier Robert *mode = PPS_CAP;
378ea906c41SOllivier Robert return (0);
379ea906c41SOllivier Robert }
380ea906c41SOllivier Robert
381ea906c41SOllivier Robert /*
382ea906c41SOllivier Robert * Fetch timestamps
383ea906c41SOllivier Robert */
384ea906c41SOllivier Robert
385ea906c41SOllivier Robert static inline int
time_pps_fetch(pps_handle_t handle,const int tsformat,pps_info_t * ppsinfo,const struct timespec * timeout)386ea906c41SOllivier Robert time_pps_fetch(
387ea906c41SOllivier Robert pps_handle_t handle,
388ea906c41SOllivier Robert const int tsformat,
389ea906c41SOllivier Robert pps_info_t *ppsinfo,
390ea906c41SOllivier Robert const struct timespec *timeout
391ea906c41SOllivier Robert )
392ea906c41SOllivier Robert {
393ea906c41SOllivier Robert struct ppsclockev {
394ea906c41SOllivier Robert struct timeval tv;
395ea906c41SOllivier Robert u_int serial;
396ea906c41SOllivier Robert } ev;
397ea906c41SOllivier Robert pps_info_t infobuf;
398ea906c41SOllivier Robert
399ea906c41SOllivier Robert /*
400ea906c41SOllivier Robert * Check for valid arguments and fetch timestamps
401ea906c41SOllivier Robert */
402ea906c41SOllivier Robert
403ea906c41SOllivier Robert if (!handle) {
404ea906c41SOllivier Robert errno = EBADF;
405ea906c41SOllivier Robert return (-1); /* bad handle */
406ea906c41SOllivier Robert }
407ea906c41SOllivier Robert
408ea906c41SOllivier Robert if (!ppsinfo) {
409ea906c41SOllivier Robert errno = EFAULT;
410ea906c41SOllivier Robert return (-1); /* bad argument */
411ea906c41SOllivier Robert }
412ea906c41SOllivier Robert
413ea906c41SOllivier Robert /*
414ea906c41SOllivier Robert * nb. PPS_CANWAIT is NOT set by the implementation, we can totally
415ea906c41SOllivier Robert * ignore the timeout variable.
416ea906c41SOllivier Robert */
417ea906c41SOllivier Robert
418ea906c41SOllivier Robert memset(&infobuf, 0, sizeof(infobuf));
419ea906c41SOllivier Robert
420ea906c41SOllivier Robert /*
421ea906c41SOllivier Robert * if not captureassert, nothing to return.
422ea906c41SOllivier Robert */
423ea906c41SOllivier Robert
424ea906c41SOllivier Robert if (!handle->params.mode & PPS_CAPTUREASSERT) {
425ea906c41SOllivier Robert memcpy(ppsinfo, &infobuf, sizeof(pps_info_t));
426ea906c41SOllivier Robert return (0);
427ea906c41SOllivier Robert }
428ea906c41SOllivier Robert
429ea906c41SOllivier Robert #if defined(__STDC__)
430ea906c41SOllivier Robert #define CIOGETEV _IOR('C', 0, struct ppsclockev) /* get last pps event */
431ea906c41SOllivier Robert #else
432ea906c41SOllivier Robert #define CIOGETEV _IOR(C, 0, struct ppsclockev) /* get last pps event */
433ea906c41SOllivier Robert #endif
434ea906c41SOllivier Robert
435ea906c41SOllivier Robert if (ioctl(handle->filedes, CIOGETEV, (caddr_t) &ev) < 0) {
436ea906c41SOllivier Robert perror("time_pps_fetch:");
437ea906c41SOllivier Robert errno = EOPNOTSUPP;
438ea906c41SOllivier Robert return(-1);
439ea906c41SOllivier Robert }
440ea906c41SOllivier Robert
441ea906c41SOllivier Robert /*
442ea906c41SOllivier Robert * Apply offsets as specified. Note that only assert timestamps
443ea906c41SOllivier Robert * are captured by this interface.
444ea906c41SOllivier Robert */
445ea906c41SOllivier Robert
446ea906c41SOllivier Robert infobuf.assert_sequence = ev.serial;
447ea906c41SOllivier Robert infobuf.assert_timestamp.tv_sec = ev.tv.tv_sec;
448ea906c41SOllivier Robert infobuf.assert_timestamp.tv_nsec = ev.tv.tv_usec * 1000;
449ea906c41SOllivier Robert
450ea906c41SOllivier Robert if (handle->params.mode & PPS_OFFSETASSERT) {
451ea906c41SOllivier Robert infobuf.assert_timestamp.tv_sec += handle->params.assert_offset.tv_sec;
452ea906c41SOllivier Robert infobuf.assert_timestamp.tv_nsec += handle->params.assert_offset.tv_nsec;
453ea906c41SOllivier Robert PPS_NORMALIZE(infobuf.assert_timestamp);
454ea906c41SOllivier Robert }
455ea906c41SOllivier Robert
456ea906c41SOllivier Robert /*
457ea906c41SOllivier Robert * Translate to specified format
458ea906c41SOllivier Robert */
459ea906c41SOllivier Robert
460ea906c41SOllivier Robert switch (tsformat) {
461ea906c41SOllivier Robert case PPS_TSFMT_TSPEC:
462ea906c41SOllivier Robert break; /* timespec format requires no translation */
463ea906c41SOllivier Robert
464ea906c41SOllivier Robert case PPS_TSFMT_NTPFP: /* NTP format requires conversion to fraction form */
465ea906c41SOllivier Robert PPS_TSPECTONTP(infobuf.assert_timestamp_ntpfp);
466ea906c41SOllivier Robert break;
467ea906c41SOllivier Robert
468ea906c41SOllivier Robert default:
469ea906c41SOllivier Robert errno = EINVAL;
470ea906c41SOllivier Robert return (-1);
471ea906c41SOllivier Robert }
472ea906c41SOllivier Robert
473ea906c41SOllivier Robert infobuf.current_mode = handle->params.mode;
474ea906c41SOllivier Robert memcpy(ppsinfo, &infobuf, sizeof(pps_info_t));
475ea906c41SOllivier Robert return (0);
476ea906c41SOllivier Robert }
477ea906c41SOllivier Robert
478ea906c41SOllivier Robert /*
479ea906c41SOllivier Robert * specify kernel consumer
480ea906c41SOllivier Robert */
481ea906c41SOllivier Robert
482ea906c41SOllivier Robert static inline int
time_pps_kcbind(pps_handle_t handle,const int kernel_consumer,const int edge,const int tsformat)483ea906c41SOllivier Robert time_pps_kcbind(
484ea906c41SOllivier Robert pps_handle_t handle,
485ea906c41SOllivier Robert const int kernel_consumer,
486ea906c41SOllivier Robert const int edge, const int tsformat
487ea906c41SOllivier Robert )
488ea906c41SOllivier Robert {
489ea906c41SOllivier Robert /*
490ea906c41SOllivier Robert * Check for valid arguments and bind kernel consumer
491ea906c41SOllivier Robert */
492ea906c41SOllivier Robert if (!handle) {
493ea906c41SOllivier Robert errno = EBADF;
494ea906c41SOllivier Robert return (-1); /* bad handle */
495ea906c41SOllivier Robert }
496ea906c41SOllivier Robert if (geteuid() != 0) {
497ea906c41SOllivier Robert errno = EPERM;
498ea906c41SOllivier Robert return (-1); /* must be superuser */
499ea906c41SOllivier Robert }
500ea906c41SOllivier Robert errno = EOPNOTSUPP;
501ea906c41SOllivier Robert return(-1);
502ea906c41SOllivier Robert }
503ea906c41SOllivier Robert
504ea906c41SOllivier Robert #endif /* _SYS_TIMEPPS_H_ */
505