27 #include <sys/ioctl.h>
31 #include <sys/timex.h>
32 #include <sys/types.h>
38 #define DEVICE "/dev/ptp0"
41 #define ADJ_SETOFFSET 0x0100
45 #define CLOCK_INVALID -1
49 #include <sys/syscall.h>
58 #define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD)
63 static void handle_alarm(
int s)
65 printf(
"received signal %d\n", s);
68 static int install_handler(
int signum,
void (*handler)(
int))
75 sigaddset(&mask, signum);
81 sigemptyset(&
action.sa_mask);
87 static long ppb_to_scaled_ppm(
int ppb)
100 return (
long) (ppb * 65.536);
103 static void usage(
char *progname)
106 "usage: %s [options]\n"
107 " -a val request a one-shot alarm after 'val' seconds\n"
108 " -A val request a periodic alarm every 'val' seconds\n"
109 " -c query the ptp clock's capabilities\n"
110 " -d name device to open\n"
111 " -e val read 'val' external time stamp events\n"
112 " -f val adjust the ptp clock frequency by 'val' ppb\n"
113 " -g get the ptp clock time\n"
114 " -h prints this message\n"
115 " -p val enable output with a period of 'val' nanoseconds\n"
116 " -P val enable or disable (val=1|0) the system clock PPS\n"
117 " -s set the ptp clock time from the system time\n"
118 " -S set the system time from the ptp clock time\n"
119 " -t val shift the ptp clock time by 'val' seconds\n",
141 int adjfreq = 0x7fffffff;
152 progname =
strrchr(argv[0],
'/');
153 progname = progname ? 1+progname : argv[0];
154 while (
EOF != (c = getopt(argc, argv,
"a:A:cd:e:f:ghp:P:sSt:v"))) {
157 oneshot = atoi(optarg);
160 periodic = atoi(optarg);
169 extts = atoi(optarg);
172 adjfreq = atoi(optarg);
178 perout = atoi(optarg);
190 adjtime = atoi(optarg);
208 clkid = get_clockid(fd);
210 fprintf(stderr,
"failed to read clock id\n");
216 perror(
"PTP_CLOCK_GETCAPS");
219 " %d maximum frequency adjustment (ppb)\n"
220 " %d programmable alarms\n"
221 " %d external time stamp channels\n"
222 " %d programmable periodic signals\n"
223 " %d pulse per second\n",
232 if (0x7fffffff != adjfreq) {
233 memset(&tx, 0,
sizeof(tx));
235 tx.
freq = ppb_to_scaled_ppm(adjfreq);
236 if (clock_adjtime(clkid, &tx)) {
237 perror(
"clock_adjtime");
239 puts(
"frequency adjustment okay");
244 memset(&tx, 0,
sizeof(tx));
246 tx.
time.tv_sec = adjtime;
248 if (clock_adjtime(clkid, &tx) < 0) {
249 perror(
"clock_adjtime");
251 puts(
"time shift okay");
257 perror(
"clock_gettime");
259 printf(
"clock time: %ld.%09ld or %s",
266 if (clock_settime(clkid, &ts)) {
267 perror(
"clock_settime");
269 puts(
"set time okay");
276 perror(
"clock_settime");
278 puts(
"set time okay");
283 memset(&extts_request, 0,
sizeof(extts_request));
284 extts_request.
index = 0;
287 perror(
"PTP_EXTTS_REQUEST");
290 puts(
"external time stamp request okay");
292 for (; extts; extts--) {
293 cnt =
read(fd, &event,
sizeof(event));
294 if (cnt !=
sizeof(event)) {
298 printf(
"event index %u at %lld.%09u\n", event.
index,
299 event.
t.sec, event.
t.nsec);
303 extts_request.
flags = 0;
305 perror(
"PTP_EXTTS_REQUEST");
310 install_handler(
SIGALRM, handle_alarm);
314 if (timer_create(clkid, &sigevent, &timerid)) {
315 perror(
"timer_create");
319 memset(&timeout, 0,
sizeof(timeout));
321 if (timer_settime(timerid, 0, &timeout,
NULL)) {
322 perror(
"timer_settime");
326 timer_delete(timerid);
330 install_handler(
SIGALRM, handle_alarm);
334 if (timer_create(clkid, &sigevent, &timerid)) {
335 perror(
"timer_create");
339 memset(&timeout, 0,
sizeof(timeout));
342 if (timer_settime(timerid, 0, &timeout,
NULL)) {
343 perror(
"timer_settime");
349 timer_delete(timerid);
354 perror(
"clock_gettime");
357 memset(&perout_request, 0,
sizeof(perout_request));
358 perout_request.
index = 0;
360 perout_request.
start.nsec = 0;
361 perout_request.
period.sec = 0;
362 perout_request.
period.nsec = perout;
364 perror(
"PTP_PEROUT_REQUEST");
366 puts(
"periodic output request okay");
373 perror(
"PTP_ENABLE_PPS");
375 puts(
"pps for system time request okay");