1*8dbbf854SShuah Khan /* 2*8dbbf854SShuah Khan * PTP 1588 clock support - User space test program 3*8dbbf854SShuah Khan * 4*8dbbf854SShuah Khan * Copyright (C) 2010 OMICRON electronics GmbH 5*8dbbf854SShuah Khan * 6*8dbbf854SShuah Khan * This program is free software; you can redistribute it and/or modify 7*8dbbf854SShuah Khan * it under the terms of the GNU General Public License as published by 8*8dbbf854SShuah Khan * the Free Software Foundation; either version 2 of the License, or 9*8dbbf854SShuah Khan * (at your option) any later version. 10*8dbbf854SShuah Khan * 11*8dbbf854SShuah Khan * This program is distributed in the hope that it will be useful, 12*8dbbf854SShuah Khan * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*8dbbf854SShuah Khan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*8dbbf854SShuah Khan * GNU General Public License for more details. 15*8dbbf854SShuah Khan * 16*8dbbf854SShuah Khan * You should have received a copy of the GNU General Public License 17*8dbbf854SShuah Khan * along with this program; if not, write to the Free Software 18*8dbbf854SShuah Khan * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*8dbbf854SShuah Khan */ 20*8dbbf854SShuah Khan #define _GNU_SOURCE 21*8dbbf854SShuah Khan #define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */ 22*8dbbf854SShuah Khan #include <errno.h> 23*8dbbf854SShuah Khan #include <fcntl.h> 24*8dbbf854SShuah Khan #include <inttypes.h> 25*8dbbf854SShuah Khan #include <math.h> 26*8dbbf854SShuah Khan #include <signal.h> 27*8dbbf854SShuah Khan #include <stdio.h> 28*8dbbf854SShuah Khan #include <stdlib.h> 29*8dbbf854SShuah Khan #include <string.h> 30*8dbbf854SShuah Khan #include <sys/ioctl.h> 31*8dbbf854SShuah Khan #include <sys/mman.h> 32*8dbbf854SShuah Khan #include <sys/stat.h> 33*8dbbf854SShuah Khan #include <sys/time.h> 34*8dbbf854SShuah Khan #include <sys/timex.h> 35*8dbbf854SShuah Khan #include <sys/types.h> 36*8dbbf854SShuah Khan #include <time.h> 37*8dbbf854SShuah Khan #include <unistd.h> 38*8dbbf854SShuah Khan 39*8dbbf854SShuah Khan #include <linux/ptp_clock.h> 40*8dbbf854SShuah Khan 41*8dbbf854SShuah Khan #define DEVICE "/dev/ptp0" 42*8dbbf854SShuah Khan 43*8dbbf854SShuah Khan #ifndef ADJ_SETOFFSET 44*8dbbf854SShuah Khan #define ADJ_SETOFFSET 0x0100 45*8dbbf854SShuah Khan #endif 46*8dbbf854SShuah Khan 47*8dbbf854SShuah Khan #ifndef CLOCK_INVALID 48*8dbbf854SShuah Khan #define CLOCK_INVALID -1 49*8dbbf854SShuah Khan #endif 50*8dbbf854SShuah Khan 51*8dbbf854SShuah Khan /* clock_adjtime is not available in GLIBC < 2.14 */ 52*8dbbf854SShuah Khan #if !__GLIBC_PREREQ(2, 14) 53*8dbbf854SShuah Khan #include <sys/syscall.h> 54*8dbbf854SShuah Khan static int clock_adjtime(clockid_t id, struct timex *tx) 55*8dbbf854SShuah Khan { 56*8dbbf854SShuah Khan return syscall(__NR_clock_adjtime, id, tx); 57*8dbbf854SShuah Khan } 58*8dbbf854SShuah Khan #endif 59*8dbbf854SShuah Khan 60*8dbbf854SShuah Khan static clockid_t get_clockid(int fd) 61*8dbbf854SShuah Khan { 62*8dbbf854SShuah Khan #define CLOCKFD 3 63*8dbbf854SShuah Khan #define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD) 64*8dbbf854SShuah Khan 65*8dbbf854SShuah Khan return FD_TO_CLOCKID(fd); 66*8dbbf854SShuah Khan } 67*8dbbf854SShuah Khan 68*8dbbf854SShuah Khan static void handle_alarm(int s) 69*8dbbf854SShuah Khan { 70*8dbbf854SShuah Khan printf("received signal %d\n", s); 71*8dbbf854SShuah Khan } 72*8dbbf854SShuah Khan 73*8dbbf854SShuah Khan static int install_handler(int signum, void (*handler)(int)) 74*8dbbf854SShuah Khan { 75*8dbbf854SShuah Khan struct sigaction action; 76*8dbbf854SShuah Khan sigset_t mask; 77*8dbbf854SShuah Khan 78*8dbbf854SShuah Khan /* Unblock the signal. */ 79*8dbbf854SShuah Khan sigemptyset(&mask); 80*8dbbf854SShuah Khan sigaddset(&mask, signum); 81*8dbbf854SShuah Khan sigprocmask(SIG_UNBLOCK, &mask, NULL); 82*8dbbf854SShuah Khan 83*8dbbf854SShuah Khan /* Install the signal handler. */ 84*8dbbf854SShuah Khan action.sa_handler = handler; 85*8dbbf854SShuah Khan action.sa_flags = 0; 86*8dbbf854SShuah Khan sigemptyset(&action.sa_mask); 87*8dbbf854SShuah Khan sigaction(signum, &action, NULL); 88*8dbbf854SShuah Khan 89*8dbbf854SShuah Khan return 0; 90*8dbbf854SShuah Khan } 91*8dbbf854SShuah Khan 92*8dbbf854SShuah Khan static long ppb_to_scaled_ppm(int ppb) 93*8dbbf854SShuah Khan { 94*8dbbf854SShuah Khan /* 95*8dbbf854SShuah Khan * The 'freq' field in the 'struct timex' is in parts per 96*8dbbf854SShuah Khan * million, but with a 16 bit binary fractional field. 97*8dbbf854SShuah Khan * Instead of calculating either one of 98*8dbbf854SShuah Khan * 99*8dbbf854SShuah Khan * scaled_ppm = (ppb / 1000) << 16 [1] 100*8dbbf854SShuah Khan * scaled_ppm = (ppb << 16) / 1000 [2] 101*8dbbf854SShuah Khan * 102*8dbbf854SShuah Khan * we simply use double precision math, in order to avoid the 103*8dbbf854SShuah Khan * truncation in [1] and the possible overflow in [2]. 104*8dbbf854SShuah Khan */ 105*8dbbf854SShuah Khan return (long) (ppb * 65.536); 106*8dbbf854SShuah Khan } 107*8dbbf854SShuah Khan 108*8dbbf854SShuah Khan static int64_t pctns(struct ptp_clock_time *t) 109*8dbbf854SShuah Khan { 110*8dbbf854SShuah Khan return t->sec * 1000000000LL + t->nsec; 111*8dbbf854SShuah Khan } 112*8dbbf854SShuah Khan 113*8dbbf854SShuah Khan static void usage(char *progname) 114*8dbbf854SShuah Khan { 115*8dbbf854SShuah Khan fprintf(stderr, 116*8dbbf854SShuah Khan "usage: %s [options]\n" 117*8dbbf854SShuah Khan " -a val request a one-shot alarm after 'val' seconds\n" 118*8dbbf854SShuah Khan " -A val request a periodic alarm every 'val' seconds\n" 119*8dbbf854SShuah Khan " -c query the ptp clock's capabilities\n" 120*8dbbf854SShuah Khan " -d name device to open\n" 121*8dbbf854SShuah Khan " -e val read 'val' external time stamp events\n" 122*8dbbf854SShuah Khan " -f val adjust the ptp clock frequency by 'val' ppb\n" 123*8dbbf854SShuah Khan " -g get the ptp clock time\n" 124*8dbbf854SShuah Khan " -h prints this message\n" 125*8dbbf854SShuah Khan " -i val index for event/trigger\n" 126*8dbbf854SShuah Khan " -k val measure the time offset between system and phc clock\n" 127*8dbbf854SShuah Khan " for 'val' times (Maximum 25)\n" 128*8dbbf854SShuah Khan " -l list the current pin configuration\n" 129*8dbbf854SShuah Khan " -L pin,val configure pin index 'pin' with function 'val'\n" 130*8dbbf854SShuah Khan " the channel index is taken from the '-i' option\n" 131*8dbbf854SShuah Khan " 'val' specifies the auxiliary function:\n" 132*8dbbf854SShuah Khan " 0 - none\n" 133*8dbbf854SShuah Khan " 1 - external time stamp\n" 134*8dbbf854SShuah Khan " 2 - periodic output\n" 135*8dbbf854SShuah Khan " -p val enable output with a period of 'val' nanoseconds\n" 136*8dbbf854SShuah Khan " -P val enable or disable (val=1|0) the system clock PPS\n" 137*8dbbf854SShuah Khan " -s set the ptp clock time from the system time\n" 138*8dbbf854SShuah Khan " -S set the system time from the ptp clock time\n" 139*8dbbf854SShuah Khan " -t val shift the ptp clock time by 'val' seconds\n" 140*8dbbf854SShuah Khan " -T val set the ptp clock time to 'val' seconds\n", 141*8dbbf854SShuah Khan progname); 142*8dbbf854SShuah Khan } 143*8dbbf854SShuah Khan 144*8dbbf854SShuah Khan int main(int argc, char *argv[]) 145*8dbbf854SShuah Khan { 146*8dbbf854SShuah Khan struct ptp_clock_caps caps; 147*8dbbf854SShuah Khan struct ptp_extts_event event; 148*8dbbf854SShuah Khan struct ptp_extts_request extts_request; 149*8dbbf854SShuah Khan struct ptp_perout_request perout_request; 150*8dbbf854SShuah Khan struct ptp_pin_desc desc; 151*8dbbf854SShuah Khan struct timespec ts; 152*8dbbf854SShuah Khan struct timex tx; 153*8dbbf854SShuah Khan 154*8dbbf854SShuah Khan static timer_t timerid; 155*8dbbf854SShuah Khan struct itimerspec timeout; 156*8dbbf854SShuah Khan struct sigevent sigevent; 157*8dbbf854SShuah Khan 158*8dbbf854SShuah Khan struct ptp_clock_time *pct; 159*8dbbf854SShuah Khan struct ptp_sys_offset *sysoff; 160*8dbbf854SShuah Khan 161*8dbbf854SShuah Khan 162*8dbbf854SShuah Khan char *progname; 163*8dbbf854SShuah Khan unsigned int i; 164*8dbbf854SShuah Khan int c, cnt, fd; 165*8dbbf854SShuah Khan 166*8dbbf854SShuah Khan char *device = DEVICE; 167*8dbbf854SShuah Khan clockid_t clkid; 168*8dbbf854SShuah Khan int adjfreq = 0x7fffffff; 169*8dbbf854SShuah Khan int adjtime = 0; 170*8dbbf854SShuah Khan int capabilities = 0; 171*8dbbf854SShuah Khan int extts = 0; 172*8dbbf854SShuah Khan int gettime = 0; 173*8dbbf854SShuah Khan int index = 0; 174*8dbbf854SShuah Khan int list_pins = 0; 175*8dbbf854SShuah Khan int oneshot = 0; 176*8dbbf854SShuah Khan int pct_offset = 0; 177*8dbbf854SShuah Khan int n_samples = 0; 178*8dbbf854SShuah Khan int periodic = 0; 179*8dbbf854SShuah Khan int perout = -1; 180*8dbbf854SShuah Khan int pin_index = -1, pin_func; 181*8dbbf854SShuah Khan int pps = -1; 182*8dbbf854SShuah Khan int seconds = 0; 183*8dbbf854SShuah Khan int settime = 0; 184*8dbbf854SShuah Khan 185*8dbbf854SShuah Khan int64_t t1, t2, tp; 186*8dbbf854SShuah Khan int64_t interval, offset; 187*8dbbf854SShuah Khan 188*8dbbf854SShuah Khan progname = strrchr(argv[0], '/'); 189*8dbbf854SShuah Khan progname = progname ? 1+progname : argv[0]; 190*8dbbf854SShuah Khan while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghi:k:lL:p:P:sSt:T:v"))) { 191*8dbbf854SShuah Khan switch (c) { 192*8dbbf854SShuah Khan case 'a': 193*8dbbf854SShuah Khan oneshot = atoi(optarg); 194*8dbbf854SShuah Khan break; 195*8dbbf854SShuah Khan case 'A': 196*8dbbf854SShuah Khan periodic = atoi(optarg); 197*8dbbf854SShuah Khan break; 198*8dbbf854SShuah Khan case 'c': 199*8dbbf854SShuah Khan capabilities = 1; 200*8dbbf854SShuah Khan break; 201*8dbbf854SShuah Khan case 'd': 202*8dbbf854SShuah Khan device = optarg; 203*8dbbf854SShuah Khan break; 204*8dbbf854SShuah Khan case 'e': 205*8dbbf854SShuah Khan extts = atoi(optarg); 206*8dbbf854SShuah Khan break; 207*8dbbf854SShuah Khan case 'f': 208*8dbbf854SShuah Khan adjfreq = atoi(optarg); 209*8dbbf854SShuah Khan break; 210*8dbbf854SShuah Khan case 'g': 211*8dbbf854SShuah Khan gettime = 1; 212*8dbbf854SShuah Khan break; 213*8dbbf854SShuah Khan case 'i': 214*8dbbf854SShuah Khan index = atoi(optarg); 215*8dbbf854SShuah Khan break; 216*8dbbf854SShuah Khan case 'k': 217*8dbbf854SShuah Khan pct_offset = 1; 218*8dbbf854SShuah Khan n_samples = atoi(optarg); 219*8dbbf854SShuah Khan break; 220*8dbbf854SShuah Khan case 'l': 221*8dbbf854SShuah Khan list_pins = 1; 222*8dbbf854SShuah Khan break; 223*8dbbf854SShuah Khan case 'L': 224*8dbbf854SShuah Khan cnt = sscanf(optarg, "%d,%d", &pin_index, &pin_func); 225*8dbbf854SShuah Khan if (cnt != 2) { 226*8dbbf854SShuah Khan usage(progname); 227*8dbbf854SShuah Khan return -1; 228*8dbbf854SShuah Khan } 229*8dbbf854SShuah Khan break; 230*8dbbf854SShuah Khan case 'p': 231*8dbbf854SShuah Khan perout = atoi(optarg); 232*8dbbf854SShuah Khan break; 233*8dbbf854SShuah Khan case 'P': 234*8dbbf854SShuah Khan pps = atoi(optarg); 235*8dbbf854SShuah Khan break; 236*8dbbf854SShuah Khan case 's': 237*8dbbf854SShuah Khan settime = 1; 238*8dbbf854SShuah Khan break; 239*8dbbf854SShuah Khan case 'S': 240*8dbbf854SShuah Khan settime = 2; 241*8dbbf854SShuah Khan break; 242*8dbbf854SShuah Khan case 't': 243*8dbbf854SShuah Khan adjtime = atoi(optarg); 244*8dbbf854SShuah Khan break; 245*8dbbf854SShuah Khan case 'T': 246*8dbbf854SShuah Khan settime = 3; 247*8dbbf854SShuah Khan seconds = atoi(optarg); 248*8dbbf854SShuah Khan break; 249*8dbbf854SShuah Khan case 'h': 250*8dbbf854SShuah Khan usage(progname); 251*8dbbf854SShuah Khan return 0; 252*8dbbf854SShuah Khan case '?': 253*8dbbf854SShuah Khan default: 254*8dbbf854SShuah Khan usage(progname); 255*8dbbf854SShuah Khan return -1; 256*8dbbf854SShuah Khan } 257*8dbbf854SShuah Khan } 258*8dbbf854SShuah Khan 259*8dbbf854SShuah Khan fd = open(device, O_RDWR); 260*8dbbf854SShuah Khan if (fd < 0) { 261*8dbbf854SShuah Khan fprintf(stderr, "opening %s: %s\n", device, strerror(errno)); 262*8dbbf854SShuah Khan return -1; 263*8dbbf854SShuah Khan } 264*8dbbf854SShuah Khan 265*8dbbf854SShuah Khan clkid = get_clockid(fd); 266*8dbbf854SShuah Khan if (CLOCK_INVALID == clkid) { 267*8dbbf854SShuah Khan fprintf(stderr, "failed to read clock id\n"); 268*8dbbf854SShuah Khan return -1; 269*8dbbf854SShuah Khan } 270*8dbbf854SShuah Khan 271*8dbbf854SShuah Khan if (capabilities) { 272*8dbbf854SShuah Khan if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) { 273*8dbbf854SShuah Khan perror("PTP_CLOCK_GETCAPS"); 274*8dbbf854SShuah Khan } else { 275*8dbbf854SShuah Khan printf("capabilities:\n" 276*8dbbf854SShuah Khan " %d maximum frequency adjustment (ppb)\n" 277*8dbbf854SShuah Khan " %d programmable alarms\n" 278*8dbbf854SShuah Khan " %d external time stamp channels\n" 279*8dbbf854SShuah Khan " %d programmable periodic signals\n" 280*8dbbf854SShuah Khan " %d pulse per second\n" 281*8dbbf854SShuah Khan " %d programmable pins\n" 282*8dbbf854SShuah Khan " %d cross timestamping\n", 283*8dbbf854SShuah Khan caps.max_adj, 284*8dbbf854SShuah Khan caps.n_alarm, 285*8dbbf854SShuah Khan caps.n_ext_ts, 286*8dbbf854SShuah Khan caps.n_per_out, 287*8dbbf854SShuah Khan caps.pps, 288*8dbbf854SShuah Khan caps.n_pins, 289*8dbbf854SShuah Khan caps.cross_timestamping); 290*8dbbf854SShuah Khan } 291*8dbbf854SShuah Khan } 292*8dbbf854SShuah Khan 293*8dbbf854SShuah Khan if (0x7fffffff != adjfreq) { 294*8dbbf854SShuah Khan memset(&tx, 0, sizeof(tx)); 295*8dbbf854SShuah Khan tx.modes = ADJ_FREQUENCY; 296*8dbbf854SShuah Khan tx.freq = ppb_to_scaled_ppm(adjfreq); 297*8dbbf854SShuah Khan if (clock_adjtime(clkid, &tx)) { 298*8dbbf854SShuah Khan perror("clock_adjtime"); 299*8dbbf854SShuah Khan } else { 300*8dbbf854SShuah Khan puts("frequency adjustment okay"); 301*8dbbf854SShuah Khan } 302*8dbbf854SShuah Khan } 303*8dbbf854SShuah Khan 304*8dbbf854SShuah Khan if (adjtime) { 305*8dbbf854SShuah Khan memset(&tx, 0, sizeof(tx)); 306*8dbbf854SShuah Khan tx.modes = ADJ_SETOFFSET; 307*8dbbf854SShuah Khan tx.time.tv_sec = adjtime; 308*8dbbf854SShuah Khan tx.time.tv_usec = 0; 309*8dbbf854SShuah Khan if (clock_adjtime(clkid, &tx) < 0) { 310*8dbbf854SShuah Khan perror("clock_adjtime"); 311*8dbbf854SShuah Khan } else { 312*8dbbf854SShuah Khan puts("time shift okay"); 313*8dbbf854SShuah Khan } 314*8dbbf854SShuah Khan } 315*8dbbf854SShuah Khan 316*8dbbf854SShuah Khan if (gettime) { 317*8dbbf854SShuah Khan if (clock_gettime(clkid, &ts)) { 318*8dbbf854SShuah Khan perror("clock_gettime"); 319*8dbbf854SShuah Khan } else { 320*8dbbf854SShuah Khan printf("clock time: %ld.%09ld or %s", 321*8dbbf854SShuah Khan ts.tv_sec, ts.tv_nsec, ctime(&ts.tv_sec)); 322*8dbbf854SShuah Khan } 323*8dbbf854SShuah Khan } 324*8dbbf854SShuah Khan 325*8dbbf854SShuah Khan if (settime == 1) { 326*8dbbf854SShuah Khan clock_gettime(CLOCK_REALTIME, &ts); 327*8dbbf854SShuah Khan if (clock_settime(clkid, &ts)) { 328*8dbbf854SShuah Khan perror("clock_settime"); 329*8dbbf854SShuah Khan } else { 330*8dbbf854SShuah Khan puts("set time okay"); 331*8dbbf854SShuah Khan } 332*8dbbf854SShuah Khan } 333*8dbbf854SShuah Khan 334*8dbbf854SShuah Khan if (settime == 2) { 335*8dbbf854SShuah Khan clock_gettime(clkid, &ts); 336*8dbbf854SShuah Khan if (clock_settime(CLOCK_REALTIME, &ts)) { 337*8dbbf854SShuah Khan perror("clock_settime"); 338*8dbbf854SShuah Khan } else { 339*8dbbf854SShuah Khan puts("set time okay"); 340*8dbbf854SShuah Khan } 341*8dbbf854SShuah Khan } 342*8dbbf854SShuah Khan 343*8dbbf854SShuah Khan if (settime == 3) { 344*8dbbf854SShuah Khan ts.tv_sec = seconds; 345*8dbbf854SShuah Khan ts.tv_nsec = 0; 346*8dbbf854SShuah Khan if (clock_settime(clkid, &ts)) { 347*8dbbf854SShuah Khan perror("clock_settime"); 348*8dbbf854SShuah Khan } else { 349*8dbbf854SShuah Khan puts("set time okay"); 350*8dbbf854SShuah Khan } 351*8dbbf854SShuah Khan } 352*8dbbf854SShuah Khan 353*8dbbf854SShuah Khan if (extts) { 354*8dbbf854SShuah Khan memset(&extts_request, 0, sizeof(extts_request)); 355*8dbbf854SShuah Khan extts_request.index = index; 356*8dbbf854SShuah Khan extts_request.flags = PTP_ENABLE_FEATURE; 357*8dbbf854SShuah Khan if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) { 358*8dbbf854SShuah Khan perror("PTP_EXTTS_REQUEST"); 359*8dbbf854SShuah Khan extts = 0; 360*8dbbf854SShuah Khan } else { 361*8dbbf854SShuah Khan puts("external time stamp request okay"); 362*8dbbf854SShuah Khan } 363*8dbbf854SShuah Khan for (; extts; extts--) { 364*8dbbf854SShuah Khan cnt = read(fd, &event, sizeof(event)); 365*8dbbf854SShuah Khan if (cnt != sizeof(event)) { 366*8dbbf854SShuah Khan perror("read"); 367*8dbbf854SShuah Khan break; 368*8dbbf854SShuah Khan } 369*8dbbf854SShuah Khan printf("event index %u at %lld.%09u\n", event.index, 370*8dbbf854SShuah Khan event.t.sec, event.t.nsec); 371*8dbbf854SShuah Khan fflush(stdout); 372*8dbbf854SShuah Khan } 373*8dbbf854SShuah Khan /* Disable the feature again. */ 374*8dbbf854SShuah Khan extts_request.flags = 0; 375*8dbbf854SShuah Khan if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) { 376*8dbbf854SShuah Khan perror("PTP_EXTTS_REQUEST"); 377*8dbbf854SShuah Khan } 378*8dbbf854SShuah Khan } 379*8dbbf854SShuah Khan 380*8dbbf854SShuah Khan if (list_pins) { 381*8dbbf854SShuah Khan int n_pins = 0; 382*8dbbf854SShuah Khan if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) { 383*8dbbf854SShuah Khan perror("PTP_CLOCK_GETCAPS"); 384*8dbbf854SShuah Khan } else { 385*8dbbf854SShuah Khan n_pins = caps.n_pins; 386*8dbbf854SShuah Khan } 387*8dbbf854SShuah Khan for (i = 0; i < n_pins; i++) { 388*8dbbf854SShuah Khan desc.index = i; 389*8dbbf854SShuah Khan if (ioctl(fd, PTP_PIN_GETFUNC, &desc)) { 390*8dbbf854SShuah Khan perror("PTP_PIN_GETFUNC"); 391*8dbbf854SShuah Khan break; 392*8dbbf854SShuah Khan } 393*8dbbf854SShuah Khan printf("name %s index %u func %u chan %u\n", 394*8dbbf854SShuah Khan desc.name, desc.index, desc.func, desc.chan); 395*8dbbf854SShuah Khan } 396*8dbbf854SShuah Khan } 397*8dbbf854SShuah Khan 398*8dbbf854SShuah Khan if (oneshot) { 399*8dbbf854SShuah Khan install_handler(SIGALRM, handle_alarm); 400*8dbbf854SShuah Khan /* Create a timer. */ 401*8dbbf854SShuah Khan sigevent.sigev_notify = SIGEV_SIGNAL; 402*8dbbf854SShuah Khan sigevent.sigev_signo = SIGALRM; 403*8dbbf854SShuah Khan if (timer_create(clkid, &sigevent, &timerid)) { 404*8dbbf854SShuah Khan perror("timer_create"); 405*8dbbf854SShuah Khan return -1; 406*8dbbf854SShuah Khan } 407*8dbbf854SShuah Khan /* Start the timer. */ 408*8dbbf854SShuah Khan memset(&timeout, 0, sizeof(timeout)); 409*8dbbf854SShuah Khan timeout.it_value.tv_sec = oneshot; 410*8dbbf854SShuah Khan if (timer_settime(timerid, 0, &timeout, NULL)) { 411*8dbbf854SShuah Khan perror("timer_settime"); 412*8dbbf854SShuah Khan return -1; 413*8dbbf854SShuah Khan } 414*8dbbf854SShuah Khan pause(); 415*8dbbf854SShuah Khan timer_delete(timerid); 416*8dbbf854SShuah Khan } 417*8dbbf854SShuah Khan 418*8dbbf854SShuah Khan if (periodic) { 419*8dbbf854SShuah Khan install_handler(SIGALRM, handle_alarm); 420*8dbbf854SShuah Khan /* Create a timer. */ 421*8dbbf854SShuah Khan sigevent.sigev_notify = SIGEV_SIGNAL; 422*8dbbf854SShuah Khan sigevent.sigev_signo = SIGALRM; 423*8dbbf854SShuah Khan if (timer_create(clkid, &sigevent, &timerid)) { 424*8dbbf854SShuah Khan perror("timer_create"); 425*8dbbf854SShuah Khan return -1; 426*8dbbf854SShuah Khan } 427*8dbbf854SShuah Khan /* Start the timer. */ 428*8dbbf854SShuah Khan memset(&timeout, 0, sizeof(timeout)); 429*8dbbf854SShuah Khan timeout.it_interval.tv_sec = periodic; 430*8dbbf854SShuah Khan timeout.it_value.tv_sec = periodic; 431*8dbbf854SShuah Khan if (timer_settime(timerid, 0, &timeout, NULL)) { 432*8dbbf854SShuah Khan perror("timer_settime"); 433*8dbbf854SShuah Khan return -1; 434*8dbbf854SShuah Khan } 435*8dbbf854SShuah Khan while (1) { 436*8dbbf854SShuah Khan pause(); 437*8dbbf854SShuah Khan } 438*8dbbf854SShuah Khan timer_delete(timerid); 439*8dbbf854SShuah Khan } 440*8dbbf854SShuah Khan 441*8dbbf854SShuah Khan if (perout >= 0) { 442*8dbbf854SShuah Khan if (clock_gettime(clkid, &ts)) { 443*8dbbf854SShuah Khan perror("clock_gettime"); 444*8dbbf854SShuah Khan return -1; 445*8dbbf854SShuah Khan } 446*8dbbf854SShuah Khan memset(&perout_request, 0, sizeof(perout_request)); 447*8dbbf854SShuah Khan perout_request.index = index; 448*8dbbf854SShuah Khan perout_request.start.sec = ts.tv_sec + 2; 449*8dbbf854SShuah Khan perout_request.start.nsec = 0; 450*8dbbf854SShuah Khan perout_request.period.sec = 0; 451*8dbbf854SShuah Khan perout_request.period.nsec = perout; 452*8dbbf854SShuah Khan if (ioctl(fd, PTP_PEROUT_REQUEST, &perout_request)) { 453*8dbbf854SShuah Khan perror("PTP_PEROUT_REQUEST"); 454*8dbbf854SShuah Khan } else { 455*8dbbf854SShuah Khan puts("periodic output request okay"); 456*8dbbf854SShuah Khan } 457*8dbbf854SShuah Khan } 458*8dbbf854SShuah Khan 459*8dbbf854SShuah Khan if (pin_index >= 0) { 460*8dbbf854SShuah Khan memset(&desc, 0, sizeof(desc)); 461*8dbbf854SShuah Khan desc.index = pin_index; 462*8dbbf854SShuah Khan desc.func = pin_func; 463*8dbbf854SShuah Khan desc.chan = index; 464*8dbbf854SShuah Khan if (ioctl(fd, PTP_PIN_SETFUNC, &desc)) { 465*8dbbf854SShuah Khan perror("PTP_PIN_SETFUNC"); 466*8dbbf854SShuah Khan } else { 467*8dbbf854SShuah Khan puts("set pin function okay"); 468*8dbbf854SShuah Khan } 469*8dbbf854SShuah Khan } 470*8dbbf854SShuah Khan 471*8dbbf854SShuah Khan if (pps != -1) { 472*8dbbf854SShuah Khan int enable = pps ? 1 : 0; 473*8dbbf854SShuah Khan if (ioctl(fd, PTP_ENABLE_PPS, enable)) { 474*8dbbf854SShuah Khan perror("PTP_ENABLE_PPS"); 475*8dbbf854SShuah Khan } else { 476*8dbbf854SShuah Khan puts("pps for system time request okay"); 477*8dbbf854SShuah Khan } 478*8dbbf854SShuah Khan } 479*8dbbf854SShuah Khan 480*8dbbf854SShuah Khan if (pct_offset) { 481*8dbbf854SShuah Khan if (n_samples <= 0 || n_samples > 25) { 482*8dbbf854SShuah Khan puts("n_samples should be between 1 and 25"); 483*8dbbf854SShuah Khan usage(progname); 484*8dbbf854SShuah Khan return -1; 485*8dbbf854SShuah Khan } 486*8dbbf854SShuah Khan 487*8dbbf854SShuah Khan sysoff = calloc(1, sizeof(*sysoff)); 488*8dbbf854SShuah Khan if (!sysoff) { 489*8dbbf854SShuah Khan perror("calloc"); 490*8dbbf854SShuah Khan return -1; 491*8dbbf854SShuah Khan } 492*8dbbf854SShuah Khan sysoff->n_samples = n_samples; 493*8dbbf854SShuah Khan 494*8dbbf854SShuah Khan if (ioctl(fd, PTP_SYS_OFFSET, sysoff)) 495*8dbbf854SShuah Khan perror("PTP_SYS_OFFSET"); 496*8dbbf854SShuah Khan else 497*8dbbf854SShuah Khan puts("system and phc clock time offset request okay"); 498*8dbbf854SShuah Khan 499*8dbbf854SShuah Khan pct = &sysoff->ts[0]; 500*8dbbf854SShuah Khan for (i = 0; i < sysoff->n_samples; i++) { 501*8dbbf854SShuah Khan t1 = pctns(pct+2*i); 502*8dbbf854SShuah Khan tp = pctns(pct+2*i+1); 503*8dbbf854SShuah Khan t2 = pctns(pct+2*i+2); 504*8dbbf854SShuah Khan interval = t2 - t1; 505*8dbbf854SShuah Khan offset = (t2 + t1) / 2 - tp; 506*8dbbf854SShuah Khan 507*8dbbf854SShuah Khan printf("system time: %lld.%u\n", 508*8dbbf854SShuah Khan (pct+2*i)->sec, (pct+2*i)->nsec); 509*8dbbf854SShuah Khan printf("phc time: %lld.%u\n", 510*8dbbf854SShuah Khan (pct+2*i+1)->sec, (pct+2*i+1)->nsec); 511*8dbbf854SShuah Khan printf("system time: %lld.%u\n", 512*8dbbf854SShuah Khan (pct+2*i+2)->sec, (pct+2*i+2)->nsec); 513*8dbbf854SShuah Khan printf("system/phc clock time offset is %" PRId64 " ns\n" 514*8dbbf854SShuah Khan "system clock time delay is %" PRId64 " ns\n", 515*8dbbf854SShuah Khan offset, interval); 516*8dbbf854SShuah Khan } 517*8dbbf854SShuah Khan 518*8dbbf854SShuah Khan free(sysoff); 519*8dbbf854SShuah Khan } 520*8dbbf854SShuah Khan 521*8dbbf854SShuah Khan close(fd); 522*8dbbf854SShuah Khan return 0; 523*8dbbf854SShuah Khan } 524