diff --git a/phc.c b/phc.c index de5eeb8..4b9347c 100644 --- a/phc.c +++ b/phc.c @@ -51,15 +51,23 @@ void phc_close(clockid_t clkid) close(CLOCKID_TO_FD(clkid)); } +static int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps) +{ + int fd = CLOCKID_TO_FD(clkid), err; + + err = ioctl(fd, PTP_CLOCK_GETCAPS, caps); + if (err) + perror("PTP_CLOCK_GETCAPS"); + return err; +} + int phc_max_adj(clockid_t clkid) { - int fd = CLOCKID_TO_FD(clkid), max; + int max; struct ptp_clock_caps caps; - if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) { - perror("PTP_CLOCK_GETCAPS"); + if (phc_get_caps(clkid, &caps)) return 0; - } max = caps.max_adj; @@ -68,3 +76,12 @@ int phc_max_adj(clockid_t clkid) return max; } + +int phc_has_pps(clockid_t clkid) +{ + struct ptp_clock_caps caps; + + if (phc_get_caps(clkid, &caps)) + return 0; + return caps.pps; +} diff --git a/phc.h b/phc.h index 5eb775d..154e35e 100644 --- a/phc.h +++ b/phc.h @@ -46,4 +46,14 @@ void phc_close(clockid_t clkid); */ int phc_max_adj(clockid_t clkid); +/** + * Checks whether the given PTP hardware clock device supports PPS output. + * + * @param clkid A clock ID obtained using phc_open(). + * + * @return Zero if PPS output is not supported by the clock, non-zero + * otherwise. + */ +int phc_has_pps(clockid_t clkid); + #endif diff --git a/phc2sys.c b/phc2sys.c index 93495a4..7649c8a 100644 --- a/phc2sys.c +++ b/phc2sys.c @@ -206,6 +206,16 @@ static void update_clock(struct clock *clock, } } +static void enable_pps_output(clockid_t src) +{ + int enable = 1; + + if (!phc_has_pps(src)) + return; + if (ioctl(CLOCKID_TO_FD(src), PTP_ENABLE_PPS, enable) < 0) + pr_warning("failed to enable PPS output"); +} + static int read_pps(int fd, int64_t *offset, uint64_t *ts) { struct pps_fdata pfd; @@ -236,9 +246,12 @@ static int do_pps_loop(struct clock *clock, int fd, clock->source_label = "pps"; - /* The sync offset can't be applied with PPS alone. */ - if (src == CLOCK_INVALID) + if (src == CLOCK_INVALID) { + /* The sync offset can't be applied with PPS alone. */ clock->sync_offset_direction = 0; + } else { + enable_pps_output(src); + } while (1) { if (!read_pps(fd, &pps_offset, &pps_ts)) {