2 chronyd/chronyc - Programs for keeping computer clocks accurate.
4 **********************************************************************
5 * Copyright (C) Miroslav Lichvar 2009
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 **********************************************************************
22 =======================================================================
24 PPSAPI refclock driver.
34 #if defined(HAVE_SYS_TIMEPPS_H)
35 #include <sys/timepps.h>
36 #elif defined(HAVE_TIMEPPS_H)
50 static int pps_initialise(RCL_Instance instance
) {
51 const char *options
[] = {"clear", NULL
};
54 struct pps_instance
*pps
;
55 int fd
, edge_clear
, mode
;
58 RCL_CheckDriverOptions(instance
, options
);
60 path
= RCL_GetDriverParameter(instance
);
61 edge_clear
= RCL_GetDriverOption(instance
, "clear") ? 1 : 0;
63 fd
= open(path
, O_RDWR
);
65 LOG_FATAL("Could not open %s : %s", path
, strerror(errno
));
69 if (time_pps_create(fd
, &handle
) < 0)
70 LOG_FATAL("time_pps_create() failed on %s : %s", path
, strerror(errno
));
72 if (time_pps_getcap(handle
, &mode
) < 0)
73 LOG_FATAL("time_pps_getcap() failed on %s : %s", path
, strerror(errno
));
75 if (time_pps_getparams(handle
, ¶ms
) < 0)
76 LOG_FATAL("time_pps_getparams() failed on %s : %s", path
, strerror(errno
));
79 if (!(mode
& PPS_CAPTUREASSERT
))
80 LOG_FATAL("CAPTUREASSERT not supported on %s", path
);
82 params
.mode
|= PPS_CAPTUREASSERT
;
83 params
.mode
&= ~PPS_CAPTURECLEAR
;
85 if (!(mode
& PPS_CAPTURECLEAR
))
86 LOG_FATAL("CAPTURECLEAR not supported on %s", path
);
88 params
.mode
|= PPS_CAPTURECLEAR
;
89 params
.mode
&= ~PPS_CAPTUREASSERT
;
92 if (time_pps_setparams(handle
, ¶ms
) < 0)
93 LOG_FATAL("time_pps_setparams() failed on %s : %s", path
, strerror(errno
));
95 pps
= MallocNew(struct pps_instance
);
98 pps
->edge_clear
= edge_clear
;
100 RCL_SetDriverData(instance
, pps
);
104 static void pps_finalise(RCL_Instance instance
)
106 struct pps_instance
*pps
;
108 pps
= (struct pps_instance
*)RCL_GetDriverData(instance
);
109 time_pps_destroy(pps
->handle
);
113 static int pps_poll(RCL_Instance instance
)
115 struct pps_instance
*pps
;
120 pps
= (struct pps_instance
*)RCL_GetDriverData(instance
);
125 if (time_pps_fetch(pps
->handle
, PPS_TSFMT_TSPEC
, &pps_info
, &ts
) < 0) {
126 LOG(LOGS_ERR
, "time_pps_fetch() failed : %s", strerror(errno
));
130 if (!pps
->edge_clear
) {
131 seq
= pps_info
.assert_sequence
;
132 ts
= pps_info
.assert_timestamp
;
134 seq
= pps_info
.clear_sequence
;
135 ts
= pps_info
.clear_timestamp
;
138 if (seq
== pps
->last_seq
|| UTI_IsZeroTimespec(&ts
)) {
139 DEBUG_LOG("PPS sample ignored seq=%lu ts=%s",
140 (unsigned long)seq
, UTI_TimespecToString(&ts
));
146 return RCL_AddPulse(instance
, &ts
, 1.0e-9 * ts
.tv_nsec
);
149 RefclockDriver RCL_PPS_driver
= {
157 RefclockDriver RCL_PPS_driver
= { NULL
, NULL
, NULL
};