diff --git a/configure b/configure index eefe5de..efca3b9 100755 --- a/configure +++ b/configure @@ -839,6 +839,9 @@ if [ $feat_rtc = "1" ] && [ $try_rtc = "1" ] && \ then EXTRA_OBJECTS="$EXTRA_OBJECTS rtc_linux.o" add_def FEAT_RTC + if [ $feat_refclock = "1" ]; then + EXTRA_OBJECTS="$EXTRA_OBJECTS refclock_rtc.o" + fi fi if [ $feat_refclock = "1" ] && [ $feat_phc = "1" ] && [ $try_phc = "1" ] && \ diff --git a/doc/chrony.conf.adoc b/doc/chrony.conf.adoc index 95c7f0f..a32e87b 100644 --- a/doc/chrony.conf.adoc +++ b/doc/chrony.conf.adoc @@ -478,7 +478,7 @@ the driver-specific parameter using the *:* character. + This directive can be used multiple times to specify multiple reference clocks. + -There are four drivers included in *chronyd*: +There are five drivers included in *chronyd*: + *PPS*::: Driver for the kernel PPS (pulse per second) API. The parameter is the path to @@ -596,6 +596,25 @@ refclock PHC /dev/ptp1:nocrossts poll 3 pps refclock PHC /dev/ptp2:extpps:pin=1 width 0.2 poll 2 ---- + +*RTC*::: +Driver for using the Real Time Clock (RTC) as reference clock. +The parameter is the path to the RTC character device which should be used +as a time source. +This cannot be used cannot be used with the <> or +<> directive. +The driver supports the following options: ++ +*utc*:::: +Assume that RTC keeps Universal Coordinated Time (UTC) instead of local +time. +{blank}::: ++ +Examples: ++ +---- +refclock RTC /dev/rtc0:utc +---- ++ {blank}:: The *refclock* directive supports the following options: + @@ -2203,7 +2222,8 @@ The directive takes no arguments. It is equivalent to specifying the *-u* switch to the Linux *hwclock* program. + Note that this setting is overridden by the <> file -and is not relevant for the <> directive. +and is not relevant for the <> directive or when the RTC +is used as clock reference. [[rtcsync]]*rtcsync*:: The *rtcsync* directive enables a mode where the system time is periodically diff --git a/refclock.c b/refclock.c index 22d775a..5917d0b 100644 --- a/refclock.c +++ b/refclock.c @@ -48,6 +48,7 @@ extern RefclockDriver RCL_SHM_driver; extern RefclockDriver RCL_SOCK_driver; extern RefclockDriver RCL_PPS_driver; extern RefclockDriver RCL_PHC_driver; +extern RefclockDriver RCL_RTC_driver; struct FilterSample { double offset; @@ -63,6 +64,7 @@ struct RCL_Instance_Record { int driver_poll; int driver_polled; int poll; + int inpoll; int leap_status; int local; int pps_forced; @@ -159,6 +161,8 @@ RCL_AddRefclock(RefclockParameters *params) inst->driver = &RCL_PPS_driver; } else if (strcmp(params->driver_name, "PHC") == 0) { inst->driver = &RCL_PHC_driver; + } else if (strcmp(params->driver_name, "RTC") == 0) { + inst->driver = &RCL_RTC_driver; } else { LOG_FATAL("unknown refclock driver %s", params->driver_name); } @@ -174,6 +178,7 @@ RCL_AddRefclock(RefclockParameters *params) inst->driver_parameter_length = 0; inst->driver_poll = params->driver_poll; inst->poll = params->poll; + inst->inpoll = 0; inst->driver_polled = 0; inst->leap_status = LEAP_Normal; inst->local = params->local; @@ -502,7 +507,7 @@ RCL_AddSample(RCL_Instance instance, struct timespec *sample_time, log_sample(instance, &cooked_time, 0, 0, raw_offset, offset, dispersion); /* for logging purposes */ - if (!instance->driver->poll) + if (!instance->inpoll) instance->driver_polled++; return 1; @@ -659,7 +664,7 @@ RCL_AddCookedPulse(RCL_Instance instance, struct timespec *cooked_time, offset, dispersion); /* for logging purposes */ - if (!instance->driver->poll) + if (!instance->inpoll) instance->driver_polled++; return 1; @@ -785,7 +790,9 @@ poll_timeout(void *arg) if (inst->driver->poll) { poll = inst->driver_poll; + inst->inpoll = 1; inst->driver->poll(inst); + inst->inpoll = 0; inst->driver_polled++; } diff --git a/refclock_rtc.c b/refclock_rtc.c new file mode 100644 index 0000000..9209b63 --- /dev/null +++ b/refclock_rtc.c @@ -0,0 +1,162 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) 2021 Uwe Kleine-König, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + ********************************************************************** + + ======================================================================= + + RTC refclock driver. + + */ + +#include + +#include "config.h" + +#include "conf.h" +#include "refclock.h" +#include "local.h" + +#include "logging.h" +#include "memory.h" +#include "sched.h" +#include "util.h" +#include "rtc_linux.h" + +struct refrtc_instance { + int fd; + int polling; + int utc; +}; + +static int refrtc_add_sample(RCL_Instance instance, struct timespec *now, + time_t rtc_sec, long rtc_nsec) +{ + struct timespec rtc_ts; + int status; + + rtc_ts.tv_sec = rtc_sec; + rtc_ts.tv_nsec = rtc_nsec; + + status = RCL_AddSample(instance, now, &rtc_ts, LEAP_Normal); + if (status == 0) + DEBUG_LOG("rtc_sec = %s, now = %s", + UTI_TimespecToString(&rtc_ts), UTI_TimespecToString(now)); + + return status; +} + +static void refrtc_read_after_uie(int rtcfd, int event, void *data) +{ + RCL_Instance instance = (RCL_Instance)data; + struct refrtc_instance *rtc = RCL_GetDriverData(instance); + time_t rtc_sec; + struct timespec now; + int status; + + status = RTC_Linux_CheckInterrupt(rtcfd); + if (status <= -1) { + SCH_RemoveFileHandler(rtcfd); + RTC_Linux_SwitchInterrupt(rtcfd, 0); /* Likely to raise error too, but just to be sure... */ + close(rtcfd); + rtc->fd = -1; + return; + } else if (status == 0) { + /* Wait for the next interrupt, this one may be bogus */ + return; + } + + rtc_sec = RTC_Linux_ReadTime_AfterInterrupt(rtcfd, rtc->utc, NULL, &now); + if (rtc_sec == (time_t)-1) + return; + + refrtc_add_sample(instance, &now, rtc_sec, 0); +} + +static int refrtc_initialise(RCL_Instance instance) +{ + const char *options[] = {"utc", NULL}; + int rtcfd; + const char *path; + struct refrtc_instance *rtc; + int status; + + RCL_CheckDriverOptions(instance, options); + + if (CNF_GetRtcSync() || CNF_GetRtcFile()) + LOG_FATAL("refclock RTC cannot be used together with rtcsync or rtcfile"); + + path = RCL_GetDriverParameter(instance); + + rtcfd = open(path, O_RDONLY); + if (rtcfd < 0) + LOG_FATAL("Could not open RTC device %s : %m", path); + + /* Close on exec */ + UTI_FdSetCloexec(rtcfd); + + rtc = MallocNew(struct refrtc_instance); + rtc->fd = rtcfd; + rtc->utc = RCL_GetDriverOption(instance, "utc") ? 1 : 0; + + RCL_SetDriverData(instance, rtc); + + /* Try to enable update interrupts */ + status = RTC_Linux_SwitchInterrupt(rtcfd, 1); + if (status == 1) { + SCH_AddFileHandler(rtcfd, SCH_FILE_INPUT, refrtc_read_after_uie, instance); + rtc->polling = 0; + } else { + LOG(LOGS_INFO, "Falling back to polling for %s", path); + rtc->polling = 1; + } + + return 1; +} + +static void refrtc_finalise(RCL_Instance instance) +{ + struct refrtc_instance *rtc; + + rtc = RCL_GetDriverData(instance); + + if (!rtc->polling) { + SCH_RemoveFileHandler(rtc->fd); + RTC_Linux_SwitchInterrupt(rtc->fd, 0); + } + + close(rtc->fd); + Free(rtc); +} + +static int refrtc_poll(RCL_Instance instance) +{ + struct refrtc_instance *rtc; + struct timespec now; + time_t rtc_sec; + + rtc = RCL_GetDriverData(instance); + + if (!rtc->polling) + return 0; + + rtc_sec = RTC_Linux_ReadTime_Now(rtc->fd, rtc->utc, NULL, &now); + if (rtc_sec == (time_t)-1) + return 0; + + /* As the rtc has a resolution of 1s, only add half a second */ + return refrtc_add_sample(instance, &now, rtc_sec, 500000000); +} + +RefclockDriver RCL_RTC_driver = { + refrtc_initialise, + refrtc_finalise, + refrtc_poll +}; diff --git a/rtc_linux.c b/rtc_linux.c index 8c42840..8a55f8b 100644 --- a/rtc_linux.c +++ b/rtc_linux.c @@ -296,14 +296,25 @@ slew_samples corresponding real time clock 'DMY HMS' form, taking account of whether the user runs his RTC on the local time zone or UTC */ -static struct tm * -rtc_from_t(const time_t *t) +static void +rtc_from_t(const time_t *t, struct rtc_time *rtc_raw, int utc) { - if (rtc_on_utc) { - return gmtime(t); + struct tm *rtc_tm; + if (utc) { + rtc_tm = gmtime(t); } else { - return localtime(t); + rtc_tm = localtime(t); } + + rtc_raw->tm_sec = rtc_tm->tm_sec; + rtc_raw->tm_min = rtc_tm->tm_min; + rtc_raw->tm_hour = rtc_tm->tm_hour; + rtc_raw->tm_mday = rtc_tm->tm_mday; + rtc_raw->tm_mon = rtc_tm->tm_mon; + rtc_raw->tm_year = rtc_tm->tm_year; + rtc_raw->tm_wday = rtc_tm->tm_wday; + rtc_raw->tm_yday = rtc_tm->tm_yday; + rtc_raw->tm_isdst = rtc_tm->tm_isdst; } /* ================================================== */ @@ -341,17 +352,27 @@ rtc_from_t(const time_t *t) */ static time_t -t_from_rtc(struct tm *stm) { - struct tm temp1, temp2, *tm; +t_from_rtc(struct rtc_time *rtc_raw, int utc) +{ + struct tm rtc_tm, temp1, temp2, *tm; long diff; time_t t1, t2; - temp1 = *stm; + /* Convert to seconds since 1970 */ + rtc_tm.tm_sec = rtc_raw->tm_sec; + rtc_tm.tm_min = rtc_raw->tm_min; + rtc_tm.tm_hour = rtc_raw->tm_hour; + rtc_tm.tm_mday = rtc_raw->tm_mday; + rtc_tm.tm_mon = rtc_raw->tm_mon; + rtc_tm.tm_year = rtc_raw->tm_year; + rtc_tm.tm_wday = 0; + + temp1 = rtc_tm; temp1.tm_isdst = 0; - + t1 = mktime(&temp1); - tm = rtc_on_utc ? gmtime(&t1) : localtime(&t1); + tm = utc ? gmtime(&t1) : localtime(&t1); if (!tm) { DEBUG_LOG("gmtime()/localtime() failed"); return -1; @@ -476,8 +497,8 @@ write_coefs_to_file(int valid,time_t ref_time,double offset,double rate) /* ================================================== */ -static int -switch_interrupts(int on_off) +int +RTC_Linux_SwitchInterrupt(int fd, int on_off) { if (ioctl(fd, on_off ? RTC_UIE_ON : RTC_UIE_OFF, 0) < 0) { LOG(LOGS_ERR, "Could not %s RTC interrupt : %s", @@ -508,7 +529,7 @@ RTC_Linux_Initialise(void) } /* Make sure the RTC supports interrupts */ - if (!switch_interrupts(1) || !switch_interrupts(0)) { + if (!RTC_Linux_SwitchInterrupt(fd, 1) || !RTC_Linux_SwitchInterrupt(fd, 0)) { close(fd); return 0; } @@ -557,7 +578,7 @@ RTC_Linux_Finalise(void) /* Remove input file handler */ if (fd >= 0) { SCH_RemoveFileHandler(fd); - switch_interrupts(0); + RTC_Linux_SwitchInterrupt(fd, 0); close(fd); /* Save the RTC data */ @@ -578,7 +599,7 @@ static void measurement_timeout(void *any) { timeout_id = 0; - switch_interrupts(1); + RTC_Linux_SwitchInterrupt(fd, 1); } /* ================================================== */ @@ -586,21 +607,10 @@ measurement_timeout(void *any) static void set_rtc(time_t new_rtc_time) { - struct tm rtc_tm; struct rtc_time rtc_raw; int status; - rtc_tm = *rtc_from_t(&new_rtc_time); - - rtc_raw.tm_sec = rtc_tm.tm_sec; - rtc_raw.tm_min = rtc_tm.tm_min; - rtc_raw.tm_hour = rtc_tm.tm_hour; - rtc_raw.tm_mday = rtc_tm.tm_mday; - rtc_raw.tm_mon = rtc_tm.tm_mon; - rtc_raw.tm_year = rtc_tm.tm_year; - rtc_raw.tm_wday = rtc_tm.tm_wday; - rtc_raw.tm_yday = rtc_tm.tm_yday; - rtc_raw.tm_isdst = rtc_tm.tm_isdst; + rtc_from_t(&new_rtc_time, &rtc_raw, rtc_on_utc); status = ioctl(fd, RTC_SET_TIME, &rtc_raw); if (status < 0) { @@ -750,16 +760,11 @@ process_reading(time_t rtc_time, struct timespec *system_time) /* ================================================== */ -static void -read_from_device(int fd_, int event, void *any) +int +RTC_Linux_CheckInterrupt(int fd) { int status; unsigned long data; - struct timespec sys_time; - struct rtc_time rtc_raw; - struct tm rtc_tm; - time_t rtc_t; - int error = 0; status = read(fd, &data, sizeof(data)); @@ -767,64 +772,80 @@ read_from_device(int fd_, int event, void *any) /* This looks like a bad error : the file descriptor was indicating it was * ready to read but we couldn't read anything. Give up. */ LOG(LOGS_ERR, "Could not read flags %s : %s", CNF_GetRtcDevice(), strerror(errno)); - SCH_RemoveFileHandler(fd); - switch_interrupts(0); /* Likely to raise error too, but just to be sure... */ - close(fd); - fd = -1; - return; - } + return -1; + } if (skip_interrupts > 0) { /* Wait for the next interrupt, this one may be bogus */ skip_interrupts--; - return; + return 0; } - if ((data & RTC_UF) == RTC_UF) { - /* Update interrupt detected */ - - /* Read RTC time, sandwiched between two polls of the system clock - so we can bound any error. */ + /* Update interrupt detected? */ + return (data & RTC_UF) == RTC_UF; +} - SCH_GetLastEventTime(&sys_time, NULL, NULL); +time_t +RTC_Linux_ReadTime_AfterInterrupt(int fd, int utc, + struct timespec *sys_time_cooked, + struct timespec *sys_time_raw) +{ + int status; + struct rtc_time rtc_raw; - status = ioctl(fd, RTC_RD_TIME, &rtc_raw); - if (status < 0) { - LOG(LOGS_ERR, "Could not read time from %s : %s", CNF_GetRtcDevice(), strerror(errno)); - error = 1; - goto turn_off_interrupt; - } + /* Read RTC time, sandwiched between two polls of the system clock + so we can bound any error. */ - /* Convert RTC time into a struct timespec */ - rtc_tm.tm_sec = rtc_raw.tm_sec; - rtc_tm.tm_min = rtc_raw.tm_min; - rtc_tm.tm_hour = rtc_raw.tm_hour; - rtc_tm.tm_mday = rtc_raw.tm_mday; - rtc_tm.tm_mon = rtc_raw.tm_mon; - rtc_tm.tm_year = rtc_raw.tm_year; - rtc_tm.tm_wday = 0; + SCH_GetLastEventTime(sys_time_cooked, NULL, sys_time_raw); - rtc_t = t_from_rtc(&rtc_tm); + status = ioctl(fd, RTC_RD_TIME, &rtc_raw); + if (status < 0) { + LOG(LOGS_ERR, "Could not read time from %s : %s", CNF_GetRtcDevice(), strerror(errno)); + return -1; + } - if (rtc_t == (time_t)(-1)) { - error = 1; - goto turn_off_interrupt; - } + /* Convert RTC time into a struct timespec */ + return t_from_rtc(&rtc_raw, utc); +} - process_reading(rtc_t, &sys_time); +static void +read_from_device(int fd_, int event, void *any) +{ + int status; + struct timespec sys_time; + time_t rtc_t; + int error = 0; - if (n_samples < 4) { - measurement_period = LOWEST_MEASUREMENT_PERIOD; - } else if (n_samples < 6) { - measurement_period = LOWEST_MEASUREMENT_PERIOD << 1; - } else if (n_samples < 10) { - measurement_period = LOWEST_MEASUREMENT_PERIOD << 2; - } else if (n_samples < 14) { - measurement_period = LOWEST_MEASUREMENT_PERIOD << 3; - } else { - measurement_period = LOWEST_MEASUREMENT_PERIOD << 4; - } + status = RTC_Linux_CheckInterrupt(fd); + if (status == -1) { + SCH_RemoveFileHandler(fd); + RTC_Linux_SwitchInterrupt(fd, 0); /* Likely to raise error too, but just to be sure... */ + close(fd); + fd = -1; + return; + } else if (status == 0) { + /* Wait for the next interrupt, this one may be bogus */ + return; + } + rtc_t = RTC_Linux_ReadTime_AfterInterrupt(fd, rtc_on_utc, &sys_time, NULL); + if (rtc_t == (time_t)-1) { + error = 1; + goto turn_off_interrupt; + } + + process_reading(rtc_t, &sys_time); + + if (n_samples < 4) { + measurement_period = LOWEST_MEASUREMENT_PERIOD; + } else if (n_samples < 6) { + measurement_period = LOWEST_MEASUREMENT_PERIOD << 1; + } else if (n_samples < 10) { + measurement_period = LOWEST_MEASUREMENT_PERIOD << 2; + } else if (n_samples < 14) { + measurement_period = LOWEST_MEASUREMENT_PERIOD << 3; + } else { + measurement_period = LOWEST_MEASUREMENT_PERIOD << 4; } turn_off_interrupt: @@ -836,7 +857,7 @@ turn_off_interrupt: operating_mode = OM_NORMAL; (after_init_hook)(after_init_hook_arg); - switch_interrupts(0); + RTC_Linux_SwitchInterrupt(fd, 0); timeout_id = SCH_AddTimeoutByDelay((double) measurement_period, measurement_timeout, NULL); } @@ -848,7 +869,7 @@ turn_off_interrupt: DEBUG_LOG("Could not complete after trim relock due to errors"); operating_mode = OM_NORMAL; - switch_interrupts(0); + RTC_Linux_SwitchInterrupt(fd, 0); timeout_id = SCH_AddTimeoutByDelay((double) measurement_period, measurement_timeout, NULL); } @@ -856,7 +877,7 @@ turn_off_interrupt: break; case OM_NORMAL: - switch_interrupts(0); + RTC_Linux_SwitchInterrupt(fd, 0); timeout_id = SCH_AddTimeoutByDelay((double) measurement_period, measurement_timeout, NULL); @@ -878,7 +899,7 @@ RTC_Linux_TimeInit(void (*after_hook)(void *), void *anything) operating_mode = OM_INITIAL; timeout_id = 0; - switch_interrupts(1); + RTC_Linux_SwitchInterrupt(fd, 1); } /* ================================================== */ @@ -911,6 +932,33 @@ RTC_Linux_WriteParameters(void) return(retval); } +time_t +RTC_Linux_ReadTime_Now(int fd, int utc, + struct timespec *old_sys_cooked, + struct timespec *old_sys_raw) +{ + struct rtc_time rtc_raw, rtc_raw_retry; + int status; + + /* Retry reading the rtc until both read attempts give the same sec value. + This way the race condition is prevented that the RTC has updated itself + during the first read operation. */ + do { + status = ioctl(fd, RTC_RD_TIME, &rtc_raw); + if (status >= 0) { + status = ioctl(fd, RTC_RD_TIME, &rtc_raw_retry); + } + } while (status >= 0 && rtc_raw.tm_sec != rtc_raw_retry.tm_sec); + + /* Read system clock */ + if (old_sys_raw) + LCL_ReadRawTime(old_sys_raw); + if (old_sys_cooked) + LCL_ReadCookedTime(old_sys_cooked, NULL); + + return status >= 0 ? t_from_rtc(&rtc_raw, utc) : -1; +} + /* ================================================== */ /* Try to set the system clock from the RTC, in the same manner as /sbin/hwclock -s would do. We're not as picky about OS version @@ -920,9 +968,7 @@ RTC_Linux_WriteParameters(void) int RTC_Linux_TimePreInit(time_t driftfile_time) { - int fd, status; - struct rtc_time rtc_raw, rtc_raw_retry; - struct tm rtc_tm; + int fd; time_t rtc_t; double accumulated_error, sys_offset; struct timespec new_sys_time, old_sys_time; @@ -938,66 +984,41 @@ RTC_Linux_TimePreInit(time_t driftfile_time) return 0; /* Can't open it, and won't be able to later */ } - /* Retry reading the rtc until both read attempts give the same sec value. - This way the race condition is prevented that the RTC has updated itself - during the first read operation. */ - do { - status = ioctl(fd, RTC_RD_TIME, &rtc_raw); - if (status >= 0) { - status = ioctl(fd, RTC_RD_TIME, &rtc_raw_retry); - } - } while (status >= 0 && rtc_raw.tm_sec != rtc_raw_retry.tm_sec); - - /* Read system clock */ - LCL_ReadCookedTime(&old_sys_time, NULL); + rtc_t = RTC_Linux_ReadTime_Now(fd, rtc_on_utc, &old_sys_time, NULL); close(fd); - if (status >= 0) { - /* Convert to seconds since 1970 */ - rtc_tm.tm_sec = rtc_raw.tm_sec; - rtc_tm.tm_min = rtc_raw.tm_min; - rtc_tm.tm_hour = rtc_raw.tm_hour; - rtc_tm.tm_mday = rtc_raw.tm_mday; - rtc_tm.tm_mon = rtc_raw.tm_mon; - rtc_tm.tm_year = rtc_raw.tm_year; - - rtc_t = t_from_rtc(&rtc_tm); + if (rtc_t != (time_t)(-1)) { - if (rtc_t != (time_t)(-1)) { - - /* Work out approximatation to correct time (to about the - nearest second) */ - if (valid_coefs_from_file) { - accumulated_error = file_ref_offset + - (rtc_t - file_ref_time) * 1.0e-6 * file_rate_ppm; - } else { - accumulated_error = 0.0; - } - - /* Correct time */ - - new_sys_time.tv_sec = rtc_t; - /* Average error in the RTC reading */ - new_sys_time.tv_nsec = 500000000; - - UTI_AddDoubleToTimespec(&new_sys_time, -accumulated_error, &new_sys_time); - - if (new_sys_time.tv_sec < driftfile_time) { - LOG(LOGS_WARN, "RTC time before last driftfile modification (ignored)"); - return 0; - } - - sys_offset = UTI_DiffTimespecsToDouble(&old_sys_time, &new_sys_time); - - /* Set system time only if the step is larger than 1 second */ - if (fabs(sys_offset) >= 1.0) { - if (LCL_ApplyStepOffset(sys_offset)) - LOG(LOGS_INFO, "System time set from RTC"); - } + /* Work out approximatation to correct time (to about the + nearest second) */ + if (valid_coefs_from_file) { + accumulated_error = file_ref_offset + + (rtc_t - file_ref_time) * 1.0e-6 * file_rate_ppm; } else { + accumulated_error = 0.0; + } + + /* Correct time */ + + new_sys_time.tv_sec = rtc_t; + /* Average error in the RTC reading */ + new_sys_time.tv_nsec = 500000000; + + UTI_AddDoubleToTimespec(&new_sys_time, -accumulated_error, &new_sys_time); + + if (new_sys_time.tv_sec < driftfile_time) { + LOG(LOGS_WARN, "RTC time before last driftfile modification (ignored)"); return 0; } + + sys_offset = UTI_DiffTimespecsToDouble(&old_sys_time, &new_sys_time); + + /* Set system time only if the step is larger than 1 second */ + if (fabs(sys_offset) >= 1.0) { + if (LCL_ApplyStepOffset(sys_offset)) + LOG(LOGS_INFO, "System time set from RTC"); + } } else { return 0; } @@ -1065,7 +1086,7 @@ RTC_Linux_Trim(void) /* And start rapid sampling, interrupts on now */ SCH_RemoveTimeout(timeout_id); timeout_id = 0; - switch_interrupts(1); + RTC_Linux_SwitchInterrupt(fd, 1); } return 1; diff --git a/rtc_linux.h b/rtc_linux.h index fa33ef1..d34f697 100644 --- a/rtc_linux.h +++ b/rtc_linux.h @@ -42,4 +42,13 @@ extern int RTC_Linux_Trim(void); extern void RTC_Linux_CycleLogFile(void); +extern int RTC_Linux_SwitchInterrupt(int fd, int on_off); +extern int RTC_Linux_CheckInterrupt(int fd); +extern time_t RTC_Linux_ReadTime_AfterInterrupt(int fd, int utc, + struct timespec *sys_time_cooked, + struct timespec *sys_time_raw); +extern time_t RTC_Linux_ReadTime_Now(int fd, int utc, + struct timespec *sys_time_cooked, + struct timespec *sys_time_raw); + #endif /* _GOT_RTC_LINUX_H */