diff options
Diffstat (limited to 'Documentation/ptp/testptp.c')
| -rw-r--r-- | Documentation/ptp/testptp.c | 154 | 
1 files changed, 146 insertions, 8 deletions
diff --git a/Documentation/ptp/testptp.c b/Documentation/ptp/testptp.c index f59ded06610..ba1d50200c4 100644 --- a/Documentation/ptp/testptp.c +++ b/Documentation/ptp/testptp.c @@ -17,8 +17,10 @@   *  along with this program; if not, write to the Free Software   *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */ +#define _GNU_SOURCE  #include <errno.h>  #include <fcntl.h> +#include <inttypes.h>  #include <math.h>  #include <signal.h>  #include <stdio.h> @@ -45,12 +47,14 @@  #define CLOCK_INVALID -1  #endif -/* When glibc offers the syscall, this will go away. */ +/* clock_adjtime is not available in GLIBC < 2.14 */ +#if !__GLIBC_PREREQ(2, 14)  #include <sys/syscall.h>  static int clock_adjtime(clockid_t id, struct timex *tx)  {  	return syscall(__NR_clock_adjtime, id, tx);  } +#endif  static clockid_t get_clockid(int fd)  { @@ -100,6 +104,11 @@ static long ppb_to_scaled_ppm(int ppb)  	return (long) (ppb * 65.536);  } +static int64_t pctns(struct ptp_clock_time *t) +{ +	return t->sec * 1000000000LL + t->nsec; +} +  static void usage(char *progname)  {  	fprintf(stderr, @@ -112,11 +121,22 @@ static void usage(char *progname)  		" -f val     adjust the ptp clock frequency by 'val' ppb\n"  		" -g         get the ptp clock time\n"  		" -h         prints this message\n" +		" -i val     index for event/trigger\n" +		" -k val     measure the time offset between system and phc clock\n" +		"            for 'val' times (Maximum 25)\n" +		" -l         list the current pin configuration\n" +		" -L pin,val configure pin index 'pin' with function 'val'\n" +		"            the channel index is taken from the '-i' option\n" +		"            'val' specifies the auxiliary function:\n" +		"            0 - none\n" +		"            1 - external time stamp\n" +		"            2 - periodic output\n"  		" -p val     enable output with a period of 'val' nanoseconds\n"  		" -P val     enable or disable (val=1|0) the system clock PPS\n"  		" -s         set the ptp clock time from the system time\n"  		" -S         set the system time from the ptp clock time\n" -		" -t val     shift the ptp clock time by 'val' seconds\n", +		" -t val     shift the ptp clock time by 'val' seconds\n" +		" -T val     set the ptp clock time to 'val' seconds\n",  		progname);  } @@ -126,6 +146,7 @@ int main(int argc, char *argv[])  	struct ptp_extts_event event;  	struct ptp_extts_request extts_request;  	struct ptp_perout_request perout_request; +	struct ptp_pin_desc desc;  	struct timespec ts;  	struct timex tx; @@ -133,8 +154,12 @@ int main(int argc, char *argv[])  	struct itimerspec timeout;  	struct sigevent sigevent; +	struct ptp_clock_time *pct; +	struct ptp_sys_offset *sysoff; + +  	char *progname; -	int c, cnt, fd; +	int i, c, cnt, fd;  	char *device = DEVICE;  	clockid_t clkid; @@ -143,15 +168,24 @@ int main(int argc, char *argv[])  	int capabilities = 0;  	int extts = 0;  	int gettime = 0; +	int index = 0; +	int list_pins = 0;  	int oneshot = 0; +	int pct_offset = 0; +	int n_samples = 0;  	int periodic = 0;  	int perout = -1; +	int pin_index = -1, pin_func;  	int pps = -1; +	int seconds = 0;  	int settime = 0; +	int64_t t1, t2, tp; +	int64_t interval, offset; +  	progname = strrchr(argv[0], '/');  	progname = progname ? 1+progname : argv[0]; -	while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghp:P:sSt:v"))) { +	while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghi:k:lL:p:P:sSt:T:v"))) {  		switch (c) {  		case 'a':  			oneshot = atoi(optarg); @@ -174,6 +208,23 @@ int main(int argc, char *argv[])  		case 'g':  			gettime = 1;  			break; +		case 'i': +			index = atoi(optarg); +			break; +		case 'k': +			pct_offset = 1; +			n_samples = atoi(optarg); +			break; +		case 'l': +			list_pins = 1; +			break; +		case 'L': +			cnt = sscanf(optarg, "%d,%d", &pin_index, &pin_func); +			if (cnt != 2) { +				usage(progname); +				return -1; +			} +			break;  		case 'p':  			perout = atoi(optarg);  			break; @@ -189,6 +240,10 @@ int main(int argc, char *argv[])  		case 't':  			adjtime = atoi(optarg);  			break; +		case 'T': +			settime = 3; +			seconds = atoi(optarg); +			break;  		case 'h':  			usage(progname);  			return 0; @@ -220,12 +275,14 @@ int main(int argc, char *argv[])  			       "  %d programmable alarms\n"  			       "  %d external time stamp channels\n"  			       "  %d programmable periodic signals\n" -			       "  %d pulse per second\n", +			       "  %d pulse per second\n" +			       "  %d programmable pins\n",  			       caps.max_adj,  			       caps.n_alarm,  			       caps.n_ext_ts,  			       caps.n_per_out, -			       caps.pps); +			       caps.pps, +			       caps.n_pins);  		}  	} @@ -279,9 +336,19 @@ int main(int argc, char *argv[])  		}  	} +	if (settime == 3) { +		ts.tv_sec = seconds; +		ts.tv_nsec = 0; +		if (clock_settime(clkid, &ts)) { +			perror("clock_settime"); +		} else { +			puts("set time okay"); +		} +	} +  	if (extts) {  		memset(&extts_request, 0, sizeof(extts_request)); -		extts_request.index = 0; +		extts_request.index = index;  		extts_request.flags = PTP_ENABLE_FEATURE;  		if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {  			perror("PTP_EXTTS_REQUEST"); @@ -306,6 +373,24 @@ int main(int argc, char *argv[])  		}  	} +	if (list_pins) { +		int n_pins = 0; +		if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) { +			perror("PTP_CLOCK_GETCAPS"); +		} else { +			n_pins = caps.n_pins; +		} +		for (i = 0; i < n_pins; i++) { +			desc.index = i; +			if (ioctl(fd, PTP_PIN_GETFUNC, &desc)) { +				perror("PTP_PIN_GETFUNC"); +				break; +			} +			printf("name %s index %u func %u chan %u\n", +			       desc.name, desc.index, desc.func, desc.chan); +		} +	} +  	if (oneshot) {  		install_handler(SIGALRM, handle_alarm);  		/* Create a timer. */ @@ -355,7 +440,7 @@ int main(int argc, char *argv[])  			return -1;  		}  		memset(&perout_request, 0, sizeof(perout_request)); -		perout_request.index = 0; +		perout_request.index = index;  		perout_request.start.sec = ts.tv_sec + 2;  		perout_request.start.nsec = 0;  		perout_request.period.sec = 0; @@ -367,6 +452,18 @@ int main(int argc, char *argv[])  		}  	} +	if (pin_index >= 0) { +		memset(&desc, 0, sizeof(desc)); +		desc.index = pin_index; +		desc.func = pin_func; +		desc.chan = index; +		if (ioctl(fd, PTP_PIN_SETFUNC, &desc)) { +			perror("PTP_PIN_SETFUNC"); +		} else { +			puts("set pin function okay"); +		} +	} +  	if (pps != -1) {  		int enable = pps ? 1 : 0;  		if (ioctl(fd, PTP_ENABLE_PPS, enable)) { @@ -376,6 +473,47 @@ int main(int argc, char *argv[])  		}  	} +	if (pct_offset) { +		if (n_samples <= 0 || n_samples > 25) { +			puts("n_samples should be between 1 and 25"); +			usage(progname); +			return -1; +		} + +		sysoff = calloc(1, sizeof(*sysoff)); +		if (!sysoff) { +			perror("calloc"); +			return -1; +		} +		sysoff->n_samples = n_samples; + +		if (ioctl(fd, PTP_SYS_OFFSET, sysoff)) +			perror("PTP_SYS_OFFSET"); +		else +			puts("system and phc clock time offset request okay"); + +		pct = &sysoff->ts[0]; +		for (i = 0; i < sysoff->n_samples; i++) { +			t1 = pctns(pct+2*i); +			tp = pctns(pct+2*i+1); +			t2 = pctns(pct+2*i+2); +			interval = t2 - t1; +			offset = (t2 + t1) / 2 - tp; + +			printf("system time: %" PRId64 ".%u\n", +				(pct+2*i)->sec, (pct+2*i)->nsec); +			printf("phc    time: %" PRId64 ".%u\n", +				(pct+2*i+1)->sec, (pct+2*i+1)->nsec); +			printf("system time: %" PRId64 ".%u\n", +				(pct+2*i+2)->sec, (pct+2*i+2)->nsec); +			printf("system/phc clock time offset is %" PRId64 " ns\n" +			       "system     clock time delay  is %" PRId64 " ns\n", +				offset, interval); +		} + +		free(sysoff); +	} +  	close(fd);  	return 0;  }  | 
