(root)/
strace-6.5/
tests-mx32/
ioctl_ptp.c
       1  /*
       2   * Check decoding of PTP_* commands of ioctl syscall.
       3   *
       4   * Copyright (c) 2018 Harsha Sharma <harshasharmaiitr@gmail.com>
       5   * Copyright (c) 2018-2023 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include "tests.h"
      12  #include "scno.h"
      13  
      14  #include <fcntl.h>
      15  #include <inttypes.h>
      16  #include <stdio.h>
      17  #include <stdlib.h>
      18  #include <string.h>
      19  #include <unistd.h>
      20  #include <sys/ioctl.h>
      21  #include <linux/ptp_clock.h>
      22  
      23  #include "xlat.h"
      24  #include "xlat/ptp_extts_flags.h"
      25  #include "xlat/ptp_perout_flags.h"
      26  #include "xlat/ptp_pin_funcs.h"
      27  
      28  
      29  #ifdef INJECT_RETVAL
      30  # define INJ_STR " (INJECTED)"
      31  #else
      32  # define INJ_STR ""
      33  #endif
      34  
      35  #define ARRAY_END(a_) ((a_) + ARRAY_SIZE(a_))
      36  #define ARR_ITEM(arr_, idx_) ((arr_)[(idx_) % ARRAY_SIZE(arr_)])
      37  
      38  #if STRACE_SIZEOF_KERNEL_LONG_T == SIZEOF_KERNEL_LONG_T
      39  # define SAFE_TIME_T(t_) t_
      40  #else
      41  # define SAFE_TIME_T(t_) ((time_t) (t_))
      42  #endif
      43  
      44  static const char *errstr;
      45  
      46  static long
      47  sys_ioctl(kernel_long_t fd, kernel_ulong_t cmd, kernel_ulong_t arg)
      48  {
      49  #ifdef INJECT_RETVAL
      50  	static char buf[256];
      51  #endif
      52  	const long rc = syscall(__NR_ioctl, fd, cmd, arg);
      53  #ifdef INJECT_RETVAL
      54  	snprintf(buf, sizeof(buf), "%s (INJECTED)", sprintrc(rc));
      55  	errstr = buf;
      56  #else
      57  	errstr = sprintrc(rc);
      58  #endif
      59  	return rc;
      60  }
      61  
      62  static void
      63  print_lltime(const long long sec, const unsigned long long nsec)
      64  {
      65  #if !XLAT_RAW
      66  	if ((time_t) sec != sec)
      67  		return;
      68  
      69  	print_time_t_nsec(sec, nsec, 1);
      70  #endif
      71  }
      72  
      73  static void
      74  check_bad_ptr(const uint32_t ioc_val, const char *const ioc_str,
      75  	      const void *const p, const size_t sz)
      76  {
      77  	sys_ioctl(-1, ioc_val, (uintptr_t) NULL);
      78  	printf("ioctl(-1, " XLAT_FMT ", NULL) = %s\n",
      79  	       XLAT_SEL(ioc_val, ioc_str), errstr);
      80  
      81  	sys_ioctl(-1, ioc_val, (uintptr_t) p + sz);
      82  	printf("ioctl(-1, " XLAT_FMT ", %p) = %s\n",
      83  	       XLAT_SEL(ioc_val, ioc_str), p + sz, errstr);
      84  
      85  	sys_ioctl(-1, ioc_val, (uintptr_t) p + 1);
      86  	printf("ioctl(-1, " XLAT_FMT ", %p) = %s\n",
      87  	       XLAT_SEL(ioc_val, ioc_str), p + 1, errstr);
      88  }
      89  
      90  static void
      91  test_no_device(void)
      92  {
      93  	TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_clock_caps, caps);
      94  	TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_sys_offset, sysoff);
      95  	TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_sys_offset_extended, soext);
      96  	TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_sys_offset_precise, soprec);
      97  	TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_extts_request, extts);
      98  	TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_perout_request, perout);
      99  	TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_pin_desc, pindesc);
     100  	long rc;
     101  
     102  	/* unrecognized */
     103  	static const uint8_t unk_nums[] = { 0, 19, 20, 255 };
     104  
     105  	for (const uint8_t *p = unk_nums; p < ARRAY_END(unk_nums); p++) {
     106  		for (uint16_t sz = 0; sz < 1280; sz += 8) {
     107  			static const struct strval32 dirs[] = {
     108  				{ ARG_STR(_IOC_NONE) },
     109  				{ ARG_STR(_IOC_READ) },
     110  				{ ARG_STR(_IOC_WRITE) },
     111  				{ ARG_STR(_IOC_READ|_IOC_WRITE) },
     112  			};
     113  			for (const struct strval32 *d = dirs;
     114  			     d < ARRAY_END(dirs); d++) {
     115  				uint32_t ioc =
     116  					_IOC(d->val, PTP_CLK_MAGIC, *p, sz);
     117  				sys_ioctl(-1, ioc, 0);
     118  				printf("ioctl(-1, "
     119  				       XLAT_KNOWN_FMT("%#x",
     120  						      "_IOC(%s, %#x, %#x, %#x)")
     121  				       ", 0) = %s\n",
     122  				       NABBR(ioc,)
     123  				       NRAW(d->str, PTP_CLK_MAGIC, *p, sz,)
     124  				       errstr);
     125  
     126  				/* soprec is the biggest var, at 1216 bytes */
     127  				sys_ioctl(-1, ioc, (uintptr_t) soext);
     128  				printf("ioctl(-1, "
     129  				       XLAT_KNOWN_FMT("%#x",
     130  						      "_IOC(%s, %#x, %#x, %#x)")
     131  				       ", %p) = %s\n",
     132  				       NABBR(ioc,)
     133  				       NRAW(d->str, PTP_CLK_MAGIC, *p, sz,)
     134  				       soext, errstr);
     135  			}
     136  		}
     137  	}
     138  
     139  	/* PTP_CLOCK_GETCAPS{,2} */
     140  	static const struct strval32 ioc_caps[] = {
     141  		{ ARG_STR(PTP_CLOCK_GETCAPS) },
     142  		{ ARG_STR(PTP_CLOCK_GETCAPS2) },
     143  	};
     144  	for (const struct strval32 *c = ioc_caps; c < ARRAY_END(ioc_caps); c++)
     145  	{
     146  		check_bad_ptr(c->val, c->str, caps, sizeof(*caps));
     147  
     148  		memset(caps, 0, sizeof(*caps));
     149  		rc = sys_ioctl(-1, c->val, (uintptr_t) caps);
     150  		printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c->val, c->str));
     151  		if (rc >= 0) {
     152  			printf("{max_adj=0, n_alarm=0, n_ext_ts=0, n_per_out=0"
     153  			       ", pps=0, n_pins=0, cross_timestamping=0"
     154  			       ", adjust_phase=0, max_phase_adj=0}");
     155  		} else {
     156  			printf("%p", caps);
     157  		}
     158  		printf(") = %s\n", errstr);
     159  
     160  		fill_memory32_ex(caps, sizeof(*caps), 1000000, 1);
     161  		rc = sys_ioctl(-1, c->val, (uintptr_t) caps);
     162  		printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c->val, c->str));
     163  		if (rc >= 0) {
     164  			printf("{max_adj=1000000, n_alarm=1000000"
     165  			       ", n_ext_ts=1000000, n_per_out=1000000"
     166  			       ", pps=1000000, n_pins=1000000"
     167  			       ", cross_timestamping=1000000"
     168  			       ", adjust_phase=1000000, max_phase_adj=1000000"
     169  			       NRAW(" /* 0.001000000 s */")
     170  			       ", rsv=[0xf4240, 0xf4240, 0xf4240"
     171  			       ", 0xf4240, 0xf4240, 0xf4240, 0xf4240"
     172  			       ", 0xf4240, 0xf4240, 0xf4240, 0xf4240]}");
     173  		} else {
     174  			printf("%p", caps);
     175  		}
     176  		printf(") = %s\n", errstr);
     177  
     178  		fill_memory32(caps, sizeof(*caps));
     179  		rc = sys_ioctl(-1, c->val, (uintptr_t) caps);
     180  		printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c->val, c->str));
     181  		if (rc >= 0) {
     182  			printf("{max_adj=-2136948512, n_alarm=-2136948511"
     183  			       ", n_ext_ts=-2136948510, n_per_out=-2136948509"
     184  			       ", pps=-2136948508, n_pins=-2136948507"
     185  			       ", cross_timestamping=-2136948506"
     186  			       ", adjust_phase=-2136948505"
     187  			       ", max_phase_adj=-2136948504"
     188  			       NRAW(" /* -2.136948504 s */")
     189  			       ", rsv=[0x80a0c0e9, 0x80a0c0ea"
     190  			       ", 0x80a0c0eb, 0x80a0c0ec, 0x80a0c0ed"
     191  			       ", 0x80a0c0ee, 0x80a0c0ef, 0x80a0c0f0"
     192  			       ", 0x80a0c0f1, 0x80a0c0f2, 0x80a0c0f3]}");
     193  		} else {
     194  			printf("%p", caps);
     195  		}
     196  		printf(") = %s\n", errstr);
     197  	}
     198  
     199  	/* PTP_EXTTS_REQUEST{,2} */
     200  	static const struct strval32 ioc_extts[] = {
     201  		{ ARG_STR(PTP_EXTTS_REQUEST) },
     202  		{ ARG_STR(PTP_EXTTS_REQUEST2) },
     203  	};
     204  	static const struct strval32 extts_flags[] = {
     205  		{ ARG_XLAT_KNOWN(0x1, "PTP_ENABLE_FEATURE") },
     206  		{ ARG_XLAT_KNOWN(0xdeadbabe, "PTP_RISING_EDGE|PTP_FALLING_EDGE"
     207  					     "|PTP_STRICT_FLAGS|0xdeadbab0") },
     208  		{ ARG_XLAT_UNKNOWN(0xbadbeef0, "PTP_???") },
     209  		{ ARG_STR(0) },
     210  	};
     211  	for (const struct strval32 *c = ioc_extts; c < ARRAY_END(ioc_extts);
     212  	     c++) {
     213  		check_bad_ptr(c->val, c->str, extts, sizeof(*extts));
     214  
     215  		memset(extts, 0, sizeof(*extts));
     216  		sys_ioctl(-1, c->val, (uintptr_t) extts);
     217  		printf("ioctl(-1, " XLAT_FMT ", {index=0, flags=0}) = %s\n",
     218  		       XLAT_SEL(c->val, c->str), errstr);
     219  
     220  		extts->index = 3141592653;
     221  		for (size_t i = 0; i < ARRAY_SIZE(extts_flags); i++) {
     222  			extts->flags = extts_flags[i].val;
     223  			extts->rsv[0] = i & 1 ? 0xdeadc0de : 0;
     224  			extts->rsv[1] = i & 2 ? 0xcafebeef : 0;
     225  
     226  			sys_ioctl(-1, c->val, (uintptr_t) extts);
     227  			printf("ioctl(-1, " XLAT_FMT ", {index=3141592653"
     228  			       ", flags=%s",
     229  			       XLAT_SEL(c->val, c->str), extts_flags[i].str);
     230  			if (c->val == PTP_EXTTS_REQUEST2 && (i & 3)) {
     231  				printf(", rsv=[%#x, %#x]",
     232  				       i & 1 ? 0xdeadc0de : 0,
     233  				       i & 2 ? 0xcafebeef : 0);
     234  			}
     235  			printf("}) = %s\n", errstr);
     236  
     237  		}
     238  	}
     239  
     240  	/* PTP_PEROUT_REQUEST{,2} */
     241  	static const struct strval32 ioc_perout[] = {
     242  		{ ARG_STR(PTP_PEROUT_REQUEST) },
     243  		{ ARG_STR(PTP_PEROUT_REQUEST2) },
     244  	};
     245  	static const struct perout_flags {
     246  		uint32_t is_phase	:1,
     247  			 is_duty_cycle	:1;
     248  		uint32_t flags;
     249  		const char *str;
     250  	} perout_flags[] = {
     251  		{ false, false, ARG_STR(0) },
     252  		{ false, false, ARG_XLAT_KNOWN(0x1, "PTP_PEROUT_ONE_SHOT") },
     253  		{ false, true,  ARG_XLAT_KNOWN(0x3, "PTP_PEROUT_ONE_SHOT"
     254  						    "|PTP_PEROUT_DUTY_CYCLE") },
     255  		{ true,  false,
     256  		  ARG_XLAT_KNOWN(0xc0dedbad, "PTP_PEROUT_ONE_SHOT"
     257  					     "|PTP_PEROUT_PHASE|0xc0dedba8") },
     258  		{ true,  true,
     259  		  ARG_XLAT_KNOWN(0xdeadbeef,
     260  				 "PTP_PEROUT_ONE_SHOT|PTP_PEROUT_DUTY_CYCLE"
     261  				 "|PTP_PEROUT_PHASE|0xdeadbee8") },
     262  		{ false, false, ARG_XLAT_UNKNOWN(0xdeadbea8, "PTP_PEROUT_???") }
     263  	};
     264  	for (const struct strval32 *c = ioc_perout; c < ARRAY_END(ioc_perout);
     265  	     c++) {
     266  		check_bad_ptr(c->val, c->str, perout, sizeof(*perout));
     267  
     268  		memset(perout, 0, sizeof(*perout));
     269  		sys_ioctl(-1, c->val, (uintptr_t) perout);
     270  		printf("ioctl(-1, " XLAT_FMT ", {start={sec=0, nsec=0}"
     271  		       ", period={sec=0, nsec=0}, index=0, flags=0}) = %s\n",
     272  		       XLAT_SEL(c->val, c->str), errstr);
     273  
     274  		for (size_t i = 0; i < ARRAY_SIZE(perout_flags); i++) {
     275  			perout->start.sec = SAFE_TIME_T(0x123456789ULL);
     276  			perout->start.nsec = i & 1 ? 1234567890 : 123456789;
     277  			perout->start.reserved = i & 2 ? 2718281828 : 0;
     278  			perout->period.sec = 0xabcdef;
     279  			perout->period.nsec = i & 1 ? 123456789 : 0;
     280  			perout->period.reserved = i & 2 ? 0 : 2345678901;
     281  			perout->index = 3141592653U;
     282  			perout->flags= perout_flags[i].flags;
     283  			perout->on.sec = i & 3 ? 0xabcdef0123456789ULL : 0;
     284  			perout->on.nsec = i & 2 ? 123456789 : 0;
     285  			perout->on.reserved = i & 4 ? 2345678901U : 0;
     286  
     287  			sys_ioctl(-1, c->val, (uintptr_t) perout);
     288  			printf("ioctl(-1, " XLAT_FMT ", {%s={sec=%lld"
     289  			       ", nsec=%u%s}",
     290  			       XLAT_SEL(c->val, c->str),
     291  			       perout_flags[i].is_phase ? "phase" : "start",
     292  			       (long long) perout->start.sec,
     293  			       i & 1 ? 1234567890 : 123456789,
     294  			       i & 2 ? ", reserved=0xa205b064" : "");
     295  			if (!perout_flags[i].is_phase) {
     296  				print_lltime(perout->start.sec,
     297  					     perout->start.nsec);
     298  			}
     299  			printf(", period={sec=11259375, nsec=%u%s}"
     300  			       ", index=3141592653, flags=%s",
     301  			       i & 1 ? 123456789 : 0,
     302  			       i & 2 ? "" : ", reserved=0x8bd03835",
     303  			       perout_flags[i].str);
     304  			if (perout_flags[i].is_duty_cycle) {
     305  				printf(", on={sec=%lld, nsec=%u%s}",
     306  				       i & 3 ? 0xabcdef0123456789ULL : 0,
     307  				       i & 2 ? 123456789 : 0,
     308  				       i & 4 ? ", reserved=0x8bd03835" : "");
     309  			} else if (i && c->val == PTP_PEROUT_REQUEST2) {
     310  				printf(", rsv=[%#x, %#x, %#x, %#x]",
     311  				       i & 3 ? BE_LE(0xabcdef01, 0x23456789) : 0,
     312  				       i & 3 ? BE_LE(0x23456789, 0xabcdef01) : 0,
     313  				       i & 2 ? 123456789 : 0,
     314  				       i & 4 ? 2345678901U : 0);
     315  			}
     316  			printf("}) = %s\n", errstr);
     317  		}
     318  	}
     319  
     320  	/* PTP_ENABLE_PPS */
     321  	sys_ioctl(-1, PTP_ENABLE_PPS, 0);
     322  	printf("ioctl(-1, %s, 0) = %s\n",
     323  	       XLAT_STR(PTP_ENABLE_PPS), errstr);
     324  	sys_ioctl(-1, PTP_ENABLE_PPS, -1);
     325  	printf("ioctl(-1, %s, %#lx) = %s\n",
     326  	       XLAT_STR(PTP_ENABLE_PPS), (long int) -1, errstr);
     327  
     328  	/* PTP_ENABLE_PPS2 */
     329  	sys_ioctl(-1, PTP_ENABLE_PPS2, 0);
     330  	printf("ioctl(-1, %s, 0) = %s\n",
     331  	       XLAT_STR(PTP_ENABLE_PPS2), errstr);
     332  	sys_ioctl(-1, PTP_ENABLE_PPS2, -123456789);
     333  	printf("ioctl(-1, %s, %#lx) = %s\n",
     334  	       XLAT_STR(PTP_ENABLE_PPS2), (long int) -123456789, errstr);
     335  
     336  	/* PTP_SYS_OFFSET{,2} */
     337  	static const struct strval32 ioc_sysoff[] = {
     338  		{ ARG_STR(PTP_SYS_OFFSET) },
     339  		{ ARG_STR(PTP_SYS_OFFSET2) },
     340  	};
     341  	for (const struct strval32 *c = ioc_sysoff; c < ARRAY_END(ioc_sysoff);
     342  	     c++) {
     343  		check_bad_ptr(c->val, c->str, sysoff, sizeof(*sysoff));
     344  
     345  		memset(sysoff, 0, sizeof(*sysoff));
     346  		rc = sys_ioctl(-1, c->val, (uintptr_t) sysoff);
     347  		printf("ioctl(-1, " XLAT_FMT ", {n_samples=0%s}) = %s\n",
     348  		       XLAT_SEL(c->val, c->str),
     349  		       rc >= 0 ? ", ts=[{sec=0, nsec=0}]" : "", errstr);
     350  
     351  		for (size_t i = 0; i < 4; i++) {
     352  			sysoff->n_samples = i > 2 ? 0xdeadface : i * 12 + 1;
     353  			sysoff->rsv[0] = i & 1 ? 0xbadfaced : 0;
     354  			sysoff->rsv[2] = i & 2 ? 0xcafeface : 0;
     355  			for (size_t j = 0; j < 2 * PTP_MAX_SAMPLES + 1; j++) {
     356  				sysoff->ts[j].sec = SAFE_TIME_T(2345678901U + j);
     357  				sysoff->ts[j].nsec = 999999999 - i * 12 + j;
     358  				sysoff->ts[j].reserved = j & 1 ? 0xdeadface : 0;
     359  			}
     360  
     361  			rc = sys_ioctl(-1, c->val, (uintptr_t) sysoff);
     362  			printf("ioctl(-1, " XLAT_FMT ", {n_samples=%zu%s%s%s%s",
     363  			       XLAT_SEL(c->val, c->str),
     364  			       i > 2 ? 0xdeadface : i * 12 + 1,
     365  			       i & 3 ? ", rsv=[" : "",
     366  			       i & 3 ? i & 1 ? "0xbadfaced" : "0" : "",
     367  			       i & 3 ? ", 0, " : "",
     368  			       i & 3 ? i & 2 ? "0xcafeface]" : "0]" : "");
     369  			if (rc >= 0) {
     370  				for (size_t j = 0;
     371  				     j < MIN(i * 24 + 3,
     372  					     XLAT_RAW || XLAT_VERBOSE ? 51
     373  								      : 32);
     374  				     j++) {
     375  					printf("%s{sec=%lld, nsec=%u%s}",
     376  					       j ? ", " : ", ts=[",
     377  					       (long long) sysoff->ts[j].sec,
     378  					       sysoff->ts[j].nsec,
     379  					       j & 1 ? ", reserved=0xdeadface"
     380  						     : "");
     381  					print_lltime(sysoff->ts[j].sec,
     382  						     sysoff->ts[j].nsec);
     383  				}
     384  				printf("%s]",
     385  				       XLAT_RAW || XLAT_VERBOSE || i < 2
     386  					? "" : ", ...");
     387  			}
     388  			printf("}) = %s\n", errstr);
     389  		}
     390  	}
     391  
     392  	/* PTP_PIN_[GS]ETFUNC{,2} */
     393  	static const struct ioc_pin {
     394  		uint32_t is_get :1,
     395  			 is_v2  :1;
     396  		uint32_t val;
     397  		const char *str;
     398  	} ioc_pin[] = {
     399  		{ true,  false, ARG_STR(PTP_PIN_GETFUNC) },
     400  		{ true,  true,  ARG_STR(PTP_PIN_GETFUNC2) },
     401  		{ false, false, ARG_STR(PTP_PIN_SETFUNC) },
     402  		{ false, true,  ARG_STR(PTP_PIN_SETFUNC2) },
     403  	};
     404  	static const struct strval32 pin_funcs[] = {
     405  		{ ENUM_KNOWN(0x1, PTP_PF_EXTTS) },
     406  		{ ENUM_KNOWN(0x3, PTP_PF_PHYSYNC) },
     407  		{ ARG_XLAT_UNKNOWN(0x4, "PTP_PF_???") },
     408  		{ ARG_XLAT_UNKNOWN(0xdeadcafe, "PTP_PF_???") },
     409  	};
     410  	for (const struct ioc_pin *c = ioc_pin; c < ARRAY_END(ioc_pin); c++) {
     411  		check_bad_ptr(c->val, c->str, pindesc, sizeof(*pindesc));
     412  
     413  		memset(pindesc, 0, sizeof(*pindesc));
     414  		rc = sys_ioctl(-1, c->val, (uintptr_t) pindesc);
     415  		printf("ioctl(-1, " XLAT_FMT ", {index=0",
     416  		       XLAT_SEL(c->val, c->str));
     417  		if (rc >= 0 || !c->is_get) {
     418  			printf("%s, func=" XLAT_FMT ", chan=0",
     419  			       c->is_get ? ", name=\"\"" : "",
     420  			       XLAT_ARGS(PTP_PF_NONE));
     421  		}
     422  		printf("}) = %s\n", errstr);
     423  
     424  		for (size_t i = 0; i < ARRAY_SIZE(pin_funcs); i++) {
     425  			memcpy(pindesc->name,
     426  			       i & 1 ? "\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17"
     427  				       "OH HAI THAR\176\177\377\0\0\0\0\0\0\0"
     428  				       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
     429  				       "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
     430  				     : "abcdefghijklmnopqrstuvwxyz0123456789"
     431  				       "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
     432  			       sizeof(pindesc->name));
     433  			pindesc->index = 0xcafebabeU;
     434  			pindesc->func = pin_funcs[i].val;
     435  			pindesc->chan = 0xfeedbeefU;
     436  			pindesc->rsv[0] = i & 1 ? 0xbadc0ded : 0;
     437  			pindesc->rsv[4] = i & 2 ? 0 : 0xdadfaced;
     438  
     439  			rc = sys_ioctl(-1, c->val, (uintptr_t) pindesc);
     440  			printf("ioctl(-1, " XLAT_FMT ", {index=3405691582",
     441  			       XLAT_SEL(c->val, c->str));
     442  			if (c->is_get && c->is_v2 && (i & 3) != 2) {
     443  				printf(", rsv=[%#x, 0, 0, 0, %#x]",
     444  				       i & 1 ? 0xbadc0ded : 0,
     445  				       i & 2 ? 0 : 0xdadfaced);
     446  			}
     447  			if (rc >= 0 || !c->is_get) {
     448  				if (c->is_get) {
     449  					printf(", name=\"%s",
     450  					       i & 1 ? "\\1\\2\\3\\4\\5\\6\\7"
     451  						       "\\10\\t\\n\\v\\f\\r\\16"
     452  						       "\\17OH HAI THAR~\\177"
     453  						       "\\377\""
     454  						     : "abcdefghijklmnopqrstuvw"
     455  						       "xyz0123456789ABCDEFGHIJ"
     456  						       "KLMNOPQRSTUVWXYZ0\""
     457  						       "...");
     458  				}
     459  				printf(", func=%s, chan=4276993775",
     460  				       pin_funcs[i].str);
     461  				if (!c->is_get && c->is_v2
     462  				    && ((i & 1) || !(i & 2))) {
     463  					printf(", rsv=[%#x, 0, 0, 0, %#x]",
     464  					       i & 1 ? 0xbadc0ded : 0,
     465  					       i & 2 ? 0 : 0xdadfaced);
     466  				}
     467  			}
     468  			printf("}) = %s\n", errstr);
     469  		}
     470  	}
     471  
     472  	/* PTP_SYS_OFFSET_PRECISE{,2} */
     473  	static const struct strval32 ioc_soprec[] = {
     474  		{ ARG_STR(PTP_SYS_OFFSET_PRECISE) },
     475  		{ ARG_STR(PTP_SYS_OFFSET_PRECISE2) },
     476  	};
     477  	static const struct ptp_clock_time ts_vecs[] = {
     478  		{ 0, 123456789 },
     479  		{ 0x23456789, 0, 0xdeadface },
     480  		{ SAFE_TIME_T(0x123456789ab), 1234567890 },
     481  		{ SAFE_TIME_T(0x123456789abcd), 987654321, 0x1 },
     482  	};
     483  	for (const struct strval32 *c = ioc_soprec; c < ARRAY_END(ioc_soprec);
     484  	     c++) {
     485  		check_bad_ptr(c->val, c->str, soprec, sizeof(*soprec));
     486  
     487  		memset(soprec, 0, sizeof(*soprec));
     488  		rc = sys_ioctl(-1, c->val, (uintptr_t) soprec);
     489  		printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c->val, c->str));
     490  		if (rc >= 0) {
     491  			printf("{device={sec=0, nsec=0}"
     492  			       ", sys_realtime={sec=0, nsec=0}"
     493  			       ", sys_monoraw={sec=0, nsec=0}}");
     494  		} else {
     495  			printf("%p", soprec);
     496  		}
     497  		printf(") = %s\n", errstr);
     498  
     499  		for (size_t i = 0; i < ARRAY_SIZE(ts_vecs); i++) {
     500  			soprec->device = ts_vecs[i];
     501  			soprec->sys_realtime = ARR_ITEM(ts_vecs, i + 1);
     502  			soprec->sys_monoraw = ARR_ITEM(ts_vecs, i + 2);
     503  			soprec->rsv[0] = i & 1 ? 0 : 0xbadfaced;
     504  			soprec->rsv[3] = i & 2 ? 0 : 0xdeadbeef;
     505  
     506  			rc = sys_ioctl(-1, c->val, (uintptr_t) soprec);
     507  			printf("ioctl(-1, " XLAT_FMT ", ",
     508  			       XLAT_SEL(c->val, c->str));
     509  			if (rc >= 0) {
     510  				printf("{device={sec=%lld, nsec=%u",
     511  				       (long long) ts_vecs[i].sec,
     512  				       ts_vecs[i].nsec);
     513  				if (i & 1) {
     514  					printf(", reserved=%#x",
     515  					       ts_vecs[i].reserved);
     516  				}
     517  				printf("}");
     518  				print_lltime(ts_vecs[i].sec, ts_vecs[i].nsec);
     519  				printf(", sys_realtime={sec=%lld, nsec=%u",
     520  				       (long long) ARR_ITEM(ts_vecs, i + 1).sec,
     521  				       ARR_ITEM(ts_vecs, i + 1).nsec);
     522  				if (!(i & 1)) {
     523  					printf(", reserved=%#x",
     524  					       ARR_ITEM(ts_vecs, i + 1).reserved
     525  					       );
     526  				}
     527  				printf("}");
     528  				print_lltime(ARR_ITEM(ts_vecs, i + 1).sec,
     529  					     ARR_ITEM(ts_vecs, i + 1).nsec);
     530  				printf(", sys_monoraw={sec=%lld, nsec=%u",
     531  				       (long long) ARR_ITEM(ts_vecs, i + 2).sec,
     532  				       ARR_ITEM(ts_vecs, i + 2).nsec);
     533  				if (i & 1) {
     534  					printf(", reserved=%#x",
     535  					       ARR_ITEM(ts_vecs, i + 2).reserved
     536  					       );
     537  				}
     538  				printf("}");
     539  				if ((i & 3) != 3) {
     540  					printf(", rsv=[%#x, 0, 0, %#x]",
     541  					       i & 1 ? 0 : 0xbadfaced,
     542  					       i & 2 ? 0 : 0xdeadbeef);
     543  				}
     544  				printf("}");
     545  			} else {
     546  				printf("%p", soprec);
     547  			}
     548  			printf(") = %s\n", errstr);
     549  		}
     550  	}
     551  
     552  	/* PTP_SYS_OFFSET_EXTENDED{,2} */
     553  	static const struct strval32 ioc_soext[] = {
     554  		{ ARG_STR(PTP_SYS_OFFSET_EXTENDED) },
     555  		{ ARG_STR(PTP_SYS_OFFSET_EXTENDED2) },
     556  	};
     557  	for (const struct strval32 *c = ioc_soext; c < ARRAY_END(ioc_soext);
     558  	     c++) {
     559  		check_bad_ptr(c->val, c->str, soext, sizeof(*soext));
     560  
     561  		memset(soext, 0, sizeof(*soext));
     562  		rc = sys_ioctl(-1, c->val, (uintptr_t) soext);
     563  		printf("ioctl(-1, " XLAT_FMT ", {n_samples=0%s}) = %s\n",
     564  		       XLAT_SEL(c->val, c->str),
     565  		       rc >= 0 ? ", ts=[]" : "", errstr);
     566  
     567  		for (size_t i = 0; i < 4; i++) {
     568  			soext->n_samples = i > 2 ? 0xdeadface : i * 12 + 1;
     569  			soext->rsv[0] = i & 1 ? 0xbadfaced : 0;
     570  			soext->rsv[2] = i & 2 ? 0xcafeface : 0;
     571  			for (size_t j = 0; j < PTP_MAX_SAMPLES; j++) {
     572  				soext->ts[j][0].sec =
     573  						SAFE_TIME_T(2345678901U + j);
     574  				soext->ts[j][0].nsec = 999999999 - i * 12 + j;
     575  				soext->ts[j][0].reserved = j & 1 ? 0xbee : 0;
     576  
     577  				soext->ts[j][1].sec =
     578  						SAFE_TIME_T(-123456780123L + j);
     579  				soext->ts[j][1].nsec = -(i * 12) + j;
     580  				soext->ts[j][1].reserved = j & 2 ? 0xface : 0;
     581  
     582  				soext->ts[j][2].sec =
     583  						SAFE_TIME_T(j * (1 << 30));
     584  				soext->ts[j][2].nsec = j * (1 << 29);
     585  				soext->ts[j][2].reserved = j & 4 ? 0xbabe : 0;
     586  			}
     587  
     588  			rc = sys_ioctl(-1, c->val, (uintptr_t) soext);
     589  			printf("ioctl(-1, " XLAT_FMT ", {n_samples=%zu",
     590  			       XLAT_SEL(c->val, c->str),
     591  			       i > 2 ? 0xdeadface : i * 12 + 1);
     592  			if (i & 3) {
     593  				printf(", rsv=[%#x, 0, %#x]",
     594  				       i & 1 ? 0xbadfaced : 0,
     595  				       i & 2 ? 0xcafeface : 0);
     596  			}
     597  			if (rc >= 0) {
     598  				for (size_t j = 0; j < MIN(i * 12 + 1, 25); j++)
     599  				{
     600  					printf("%s", j ? "], " : ", ts=[");
     601  					for (size_t k = 0; k < 3; k++) {
     602  						printf("%s{sec=%lld, nsec=%u",
     603  						       k ? ", " : "[",
     604  						       (long long) soext->ts[j][k].sec,
     605  						       soext->ts[j][k].nsec);
     606  						if (soext->ts[j][k].reserved)
     607  							printf(", reserved=%#x",
     608  							       soext->ts[j][k]
     609  								     .reserved);
     610  						printf("}");
     611  						print_lltime(
     612  							soext->ts[j][k].sec,
     613  							soext->ts[j][k].nsec);
     614  					}
     615  				}
     616  				printf("]]");
     617  			}
     618  			printf("}) = %s\n", errstr);
     619  		}
     620  	}
     621  }
     622  
     623  int
     624  main(int argc, char *argv[])
     625  {
     626  #ifdef INJECT_RETVAL
     627  	unsigned long num_skip;
     628  	bool locked = false;
     629  
     630  	if (argc < 2)
     631  		error_msg_and_fail("Usage: %s NUM_SKIP", argv[0]);
     632  
     633  	num_skip = strtoul(argv[1], NULL, 0);
     634  	for (unsigned int i = 0; i < num_skip; i++) {
     635  		long rc = sys_ioctl(-1, PTP_CLOCK_GETCAPS, 0);
     636  		printf("ioctl(-1, %s, NULL) = %s%s\n",
     637  		       XLAT_STR(PTP_CLOCK_GETCAPS), sprintrc(rc),
     638  		       rc == 42 ? " (INJECTED)" : "");
     639  
     640  		if (rc != 42)
     641  			continue;
     642  
     643  		locked = true;
     644  		break;
     645  	}
     646  
     647  	if (!locked) {
     648  		error_msg_and_fail("Have not locked on ioctl(-1"
     649  				   ", PTP_CLOCK_GETCAPS, NULL) returning 42");
     650  	}
     651  #endif /* INJECT_RETVAL */
     652  
     653  	test_no_device();
     654  
     655  	puts("+++ exited with 0 +++");
     656  	return 0;
     657  }