diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | src/ptp.c | 247 | ||||
-rw-r--r-- | src/xlat/ptp_pin_funcs.in | 6 | ||||
-rw-r--r-- | tests/.gitignore | 7 | ||||
-rw-r--r-- | tests/Makefile.am | 4 | ||||
-rw-r--r-- | tests/gen_tests.in | 9 | ||||
-rw-r--r-- | tests/ioctl_ptp-Xabbrev.c | 2 | ||||
-rw-r--r-- | tests/ioctl_ptp-Xraw.c | 2 | ||||
-rw-r--r-- | tests/ioctl_ptp-Xverbose.c | 2 | ||||
-rw-r--r-- | tests/ioctl_ptp-success-Xabbrev.c | 2 | ||||
-rw-r--r-- | tests/ioctl_ptp-success-Xraw.c | 2 | ||||
-rw-r--r-- | tests/ioctl_ptp-success-Xverbose.c | 2 | ||||
-rw-r--r-- | tests/ioctl_ptp-success.c | 2 | ||||
-rw-r--r-- | tests/ioctl_ptp.c | 683 | ||||
-rwxr-xr-x | tests/pure_executables.list | 3 |
15 files changed, 854 insertions, 120 deletions
@@ -2,6 +2,7 @@ Noteworthy changes in release ?.?? (????-??-??) =============================================== * Improvements + * Enhanced decoding of PTP_* ioctl commands. * Bug fixes @@ -14,26 +14,59 @@ # include "xlat/ptp_extts_flags.h" # include "xlat/ptp_perout_flags.h" +# include "xlat/ptp_pin_funcs.h" static void -print_ptp_clock_time(const struct ptp_clock_time *const p) +print_ptp_clock_time(const struct ptp_clock_time *const p, bool rtc) { tprint_struct_begin(); PRINT_FIELD_D(*p, sec); tprint_struct_next(); PRINT_FIELD_U(*p, nsec); + if (p->reserved) { + tprint_struct_next(); + PRINT_FIELD_X(*p, reserved); + } tprint_struct_end(); - tprints_comment(sprinttime_nsec(p->sec, p->nsec)); + + if (rtc && xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW) + tprints_comment(sprinttime_nsec(p->sec, p->nsec)); } static bool print_ptp_clock_time_am(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) { - print_ptp_clock_time(elem_buf); + print_ptp_clock_time(elem_buf, true); return true; } +static bool +print_ptp_clock_time3_am(struct tcb *tcp, void *elem_buf, size_t elem_size, + void *data) +{ + const struct ptp_clock_time *const p = elem_buf; + + tprint_array_begin(); + print_ptp_clock_time(p, true); + tprint_array_next(); + print_ptp_clock_time(p + 1, true); + tprint_array_next(); + print_ptp_clock_time(p + 2, true); + tprint_array_end(); + + return true; +} + +#define PRINT_RSV(where_, field_) \ + do { \ + if (!IS_ARRAY_ZERO(where_.field_)) { \ + tprint_struct_next(); \ + PRINT_FIELD_ARRAY(where_, field_, tcp, \ + print_xint_array_member); \ + } \ + } while (0) + int ptp_ioctl(struct tcb *const tcp, const unsigned int code, const kernel_ulong_t arg) @@ -42,18 +75,59 @@ ptp_ioctl(struct tcb *const tcp, const unsigned int code, return RVAL_DECODED; switch (code) { + case PTP_CLOCK_GETCAPS: + case PTP_CLOCK_GETCAPS2: { + struct ptp_clock_caps caps; + CHECK_TYPE_SIZE(caps.rsv, sizeof(unsigned int) * 12); + CHECK_IOCTL_SIZE(PTP_CLOCK_GETCAPS, 80); + CHECK_IOCTL_SIZE(PTP_CLOCK_GETCAPS2, 80); + + if (entering(tcp)) { + tprint_arg_next(); + return 0; + } + + if (umove_or_printaddr(tcp, arg, &caps)) + break; + + tprint_struct_begin(); + PRINT_FIELD_D(caps, max_adj); + tprint_struct_next(); + PRINT_FIELD_D(caps, n_alarm); + tprint_struct_next(); + PRINT_FIELD_D(caps, n_ext_ts); + tprint_struct_next(); + PRINT_FIELD_D(caps, n_per_out); + tprint_struct_next(); + PRINT_FIELD_D(caps, pps); + tprint_struct_next(); + PRINT_FIELD_D(caps, n_pins); + tprint_struct_next(); + PRINT_FIELD_D(caps, cross_timestamping); + tprint_struct_next(); + PRINT_FIELD_D(caps, adjust_phase); + PRINT_RSV(caps, rsv); + tprint_struct_end(); + break; + } + case PTP_EXTTS_REQUEST: case PTP_EXTTS_REQUEST2: { struct ptp_extts_request extts; + CHECK_TYPE_SIZE(extts.rsv, sizeof(unsigned int) * 2); + CHECK_IOCTL_SIZE(PTP_EXTTS_REQUEST, 16); + CHECK_IOCTL_SIZE(PTP_EXTTS_REQUEST2, 16); tprint_arg_next(); if (umove_or_printaddr(tcp, arg, &extts)) break; tprint_struct_begin(); - PRINT_FIELD_D(extts, index); + PRINT_FIELD_U(extts, index); tprint_struct_next(); PRINT_FIELD_FLAGS(extts, flags, ptp_extts_flags, "PTP_???"); + if (code == PTP_EXTTS_REQUEST2) + PRINT_RSV(extts, rsv); tprint_struct_end(); break; } @@ -61,20 +135,37 @@ ptp_ioctl(struct tcb *const tcp, const unsigned int code, case PTP_PEROUT_REQUEST: case PTP_PEROUT_REQUEST2: { struct ptp_perout_request perout; + CHECK_TYPE_SIZE(perout.rsv, sizeof(unsigned int) * 4); + CHECK_IOCTL_SIZE(PTP_PEROUT_REQUEST, 56); + CHECK_IOCTL_SIZE(PTP_PEROUT_REQUEST2, 56); tprint_arg_next(); if (umove_or_printaddr(tcp, arg, &perout)) break; tprint_struct_begin(); - PRINT_FIELD_OBJ_PTR(perout, start, print_ptp_clock_time); + if (perout.flags & PTP_PEROUT_PHASE) { + PRINT_FIELD_OBJ_PTR(perout, phase, print_ptp_clock_time, + false); + } else { + PRINT_FIELD_OBJ_PTR(perout, start, print_ptp_clock_time, + true); + } tprint_struct_next(); - PRINT_FIELD_OBJ_PTR(perout, period, print_ptp_clock_time); + PRINT_FIELD_OBJ_PTR(perout, period, print_ptp_clock_time, + false); tprint_struct_next(); - PRINT_FIELD_D(perout, index); + PRINT_FIELD_U(perout, index); tprint_struct_next(); PRINT_FIELD_FLAGS(perout, flags, ptp_perout_flags, - "PTP_???"); + "PTP_PEROUT_???"); + if (perout.flags & PTP_PEROUT_DUTY_CYCLE) { + tprint_struct_next(); + PRINT_FIELD_OBJ_PTR(perout, on, print_ptp_clock_time, + false); + } else if (code == PTP_PEROUT_REQUEST2) { + PRINT_RSV(perout, rsv); + } tprint_struct_end(); break; } @@ -82,12 +173,15 @@ ptp_ioctl(struct tcb *const tcp, const unsigned int code, case PTP_ENABLE_PPS: case PTP_ENABLE_PPS2: tprint_arg_next(); - PRINT_VAL_D(arg); + PRINT_VAL_X(arg); break; case PTP_SYS_OFFSET: case PTP_SYS_OFFSET2: { struct ptp_sys_offset sysoff; + CHECK_TYPE_SIZE(sysoff.rsv, sizeof(unsigned int) * 3); + CHECK_IOCTL_SIZE(PTP_SYS_OFFSET, 832); + CHECK_IOCTL_SIZE(PTP_SYS_OFFSET2, 832); if (entering(tcp)) { tprint_arg_next(); @@ -96,42 +190,145 @@ ptp_ioctl(struct tcb *const tcp, const unsigned int code, tprint_struct_begin(); PRINT_FIELD_U(sysoff, n_samples); + PRINT_RSV(sysoff, rsv); return 0; } else { - if (tfetch_mem(tcp, arg, sizeof(sysoff), &sysoff)) { + if (syserror(tcp)) { + /* ... */ + } else if (!umove(tcp, arg, &sysoff)) { unsigned int n_samples = - sysoff.n_samples > PTP_MAX_SAMPLES - ? PTP_MAX_SAMPLES : sysoff.n_samples; + MIN(sysoff.n_samples, PTP_MAX_SAMPLES); tprint_struct_next(); PRINT_FIELD_ARRAY_UPTO(sysoff, ts, 2 * n_samples + 1, tcp, print_ptp_clock_time_am); + } else { + tprint_struct_next(); + tprint_unavailable(); } tprint_struct_end(); break; } } - case PTP_CLOCK_GETCAPS: - case PTP_CLOCK_GETCAPS2: { - struct ptp_clock_caps caps; - if (entering(tcp)) + case PTP_PIN_GETFUNC: + case PTP_PIN_GETFUNC2: + case PTP_PIN_SETFUNC: + case PTP_PIN_SETFUNC2: { + struct ptp_pin_desc pinfunc; + CHECK_TYPE_SIZE(pinfunc.rsv, sizeof(unsigned int) * 5); + CHECK_IOCTL_SIZE(PTP_PIN_GETFUNC, 96); + CHECK_IOCTL_SIZE(PTP_PIN_GETFUNC2, 96); + CHECK_IOCTL_SIZE(PTP_PIN_SETFUNC, 96); + CHECK_IOCTL_SIZE(PTP_PIN_SETFUNC2, 96); + + if (entering(tcp)) { + tprint_arg_next(); + + if (umove_or_printaddr(tcp, arg, &pinfunc)) + break; + + tprint_struct_begin(); + PRINT_FIELD_U(pinfunc, index); + + switch (code) { + case PTP_PIN_GETFUNC2: + PRINT_RSV(pinfunc, rsv); + ATTRIBUTE_FALLTHROUGH; + case PTP_PIN_GETFUNC: + return 0; + } + } else /* getter syscall exit */ { + if (syserror(tcp)) { + tprint_struct_end(); + break; + } + + if (umove(tcp, arg, &pinfunc) < 0) { + tprint_arg_next(); + tprint_unavailable(); + tprint_struct_end(); + break; + } + } + + /* setter syscall enter or getter syscall exit */ + switch (code) { + case PTP_PIN_GETFUNC: + case PTP_PIN_GETFUNC2: + tprint_struct_next(); + PRINT_FIELD_CSTRING(pinfunc, name); + } + tprint_struct_next(); + PRINT_FIELD_XVAL(pinfunc, func, ptp_pin_funcs, "PTP_PF_???"); + tprint_struct_next(); + PRINT_FIELD_U(pinfunc, chan); + if (code == PTP_PIN_SETFUNC2) { + PRINT_RSV(pinfunc, rsv); + } + tprint_struct_end(); + break; + } + + case PTP_SYS_OFFSET_PRECISE: + case PTP_SYS_OFFSET_PRECISE2: { + struct ptp_sys_offset_precise sysoff; + CHECK_TYPE_SIZE(sysoff.rsv, sizeof(unsigned int) * 4); + CHECK_IOCTL_SIZE(PTP_SYS_OFFSET_PRECISE, 64); + CHECK_IOCTL_SIZE(PTP_SYS_OFFSET_PRECISE2, 64); + + if (entering(tcp)) { + tprint_arg_next(); return 0; + } - tprint_arg_next(); - if (umove_or_printaddr(tcp, arg, &caps)) + if (umove_or_printaddr(tcp, arg, &sysoff)) break; tprint_struct_begin(); - PRINT_FIELD_D(caps, max_adj); - tprint_struct_next(); - PRINT_FIELD_D(caps, n_alarm); + PRINT_FIELD_OBJ_PTR(sysoff, device, print_ptp_clock_time, true); tprint_struct_next(); - PRINT_FIELD_D(caps, n_ext_ts); - tprint_struct_next(); - PRINT_FIELD_D(caps, n_per_out); + PRINT_FIELD_OBJ_PTR(sysoff, sys_realtime, print_ptp_clock_time, + true); tprint_struct_next(); - PRINT_FIELD_D(caps, pps); + PRINT_FIELD_OBJ_PTR(sysoff, sys_monoraw, print_ptp_clock_time, + false); + PRINT_RSV(sysoff, rsv); + tprint_struct_end(); + break; + } + + case PTP_SYS_OFFSET_EXTENDED: + case PTP_SYS_OFFSET_EXTENDED2: { + struct ptp_sys_offset_extended sysoff; + CHECK_TYPE_SIZE(sysoff.rsv, sizeof(unsigned int) * 3); + CHECK_IOCTL_SIZE(PTP_SYS_OFFSET_EXTENDED, 1216); + CHECK_IOCTL_SIZE(PTP_SYS_OFFSET_EXTENDED2, 1216); + + if (entering(tcp)) { + tprint_arg_next(); + if (umove_or_printaddr(tcp, arg, &sysoff)) + break; + + tprint_struct_begin(); + PRINT_FIELD_U(sysoff, n_samples); + PRINT_RSV(sysoff, rsv); + return 0; + } + + if (syserror(tcp)) { + /* ... */ + } else if (!umove(tcp, arg, &sysoff)) { + unsigned int n_samples = + MIN(sysoff.n_samples, PTP_MAX_SAMPLES); + tprint_struct_next(); + PRINT_FIELD_ARRAY_UPTO(sysoff, ts, + n_samples, tcp, + print_ptp_clock_time3_am); + } else { + tprint_struct_next(); + tprint_unavailable(); + } tprint_struct_end(); break; } diff --git a/src/xlat/ptp_pin_funcs.in b/src/xlat/ptp_pin_funcs.in new file mode 100644 index 000000000..7226b9279 --- /dev/null +++ b/src/xlat/ptp_pin_funcs.in @@ -0,0 +1,6 @@ +#enum +#value_indexed +PTP_PF_NONE 0 +PTP_PF_EXTTS 1 +PTP_PF_PEROUT 2 +PTP_PF_PHYSYNC 3 diff --git a/tests/.gitignore b/tests/.gitignore index 62c0844be..a8d2ffa94 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -349,6 +349,13 @@ ioctl_nsfs ioctl_perf ioctl_perf-success ioctl_ptp +ioctl_ptp-Xabbrev +ioctl_ptp-Xraw +ioctl_ptp-Xverbose +ioctl_ptp-success +ioctl_ptp-success-Xabbrev +ioctl_ptp-success-Xraw +ioctl_ptp-success-Xverbose ioctl_random ioctl_rtc ioctl_rtc-success diff --git a/tests/Makefile.am b/tests/Makefile.am index 452fcfa76..9ef7d751a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -216,6 +216,10 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ ioctl_mtd-success \ ioctl_nsfs \ ioctl_perf-success \ + ioctl_ptp-success \ + ioctl_ptp-success-Xabbrev \ + ioctl_ptp-success-Xraw \ + ioctl_ptp-success-Xverbose \ ioctl_rtc-success \ ioctl_rtc-v \ ioctl_seccomp \ diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 5a7074dd8..5c059e0ac 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -366,7 +366,14 @@ ioctl_nbd +ioctl.test -y ioctl_nsfs +ioctl.test -esignal=none ioctl_perf +ioctl.test ioctl_perf-success +ioctl-success.sh -a35 -ioctl_ptp +ioctl.test +ioctl_ptp +ioctl.test -a29 +ioctl_ptp-Xabbrev +ioctl.test -a29 -Xabbrev +ioctl_ptp-Xraw +ioctl.test -a20 -s51 -Xraw +ioctl_ptp-Xverbose +ioctl.test -a46 -s51 -Xverbose +ioctl_ptp-success +ioctl-success.sh -a29 +ioctl_ptp-success-Xabbrev +ioctl-success.sh -a29 -Xabbrev +ioctl_ptp-success-Xraw +ioctl-success.sh -a20 -s51 -Xraw +ioctl_ptp-success-Xverbose +ioctl-success.sh -a46 -s51 -Xverbose ioctl_random +ioctl.test ioctl_rtc +ioctl.test ioctl_rtc-success +ioctl-success.sh -a22 diff --git a/tests/ioctl_ptp-Xabbrev.c b/tests/ioctl_ptp-Xabbrev.c new file mode 100644 index 000000000..6b1a92ef1 --- /dev/null +++ b/tests/ioctl_ptp-Xabbrev.c @@ -0,0 +1,2 @@ +#define XLAT_ABBREV 1 +#include "ioctl_ptp.c" diff --git a/tests/ioctl_ptp-Xraw.c b/tests/ioctl_ptp-Xraw.c new file mode 100644 index 000000000..471dfe590 --- /dev/null +++ b/tests/ioctl_ptp-Xraw.c @@ -0,0 +1,2 @@ +#define XLAT_RAW 1 +#include "ioctl_ptp.c" diff --git a/tests/ioctl_ptp-Xverbose.c b/tests/ioctl_ptp-Xverbose.c new file mode 100644 index 000000000..3182564dc --- /dev/null +++ b/tests/ioctl_ptp-Xverbose.c @@ -0,0 +1,2 @@ +#define XLAT_VERBOSE 1 +#include "ioctl_ptp.c" diff --git a/tests/ioctl_ptp-success-Xabbrev.c b/tests/ioctl_ptp-success-Xabbrev.c new file mode 100644 index 000000000..4ad4140f3 --- /dev/null +++ b/tests/ioctl_ptp-success-Xabbrev.c @@ -0,0 +1,2 @@ +#define XLAT_ABBREV 1 +#include "ioctl_ptp-success.c" diff --git a/tests/ioctl_ptp-success-Xraw.c b/tests/ioctl_ptp-success-Xraw.c new file mode 100644 index 000000000..4091833d8 --- /dev/null +++ b/tests/ioctl_ptp-success-Xraw.c @@ -0,0 +1,2 @@ +#define XLAT_RAW 1 +#include "ioctl_ptp-success.c" diff --git a/tests/ioctl_ptp-success-Xverbose.c b/tests/ioctl_ptp-success-Xverbose.c new file mode 100644 index 000000000..0fde98ea1 --- /dev/null +++ b/tests/ioctl_ptp-success-Xverbose.c @@ -0,0 +1,2 @@ +#define XLAT_VERBOSE 1 +#include "ioctl_ptp-success.c" diff --git a/tests/ioctl_ptp-success.c b/tests/ioctl_ptp-success.c new file mode 100644 index 000000000..6f2161be0 --- /dev/null +++ b/tests/ioctl_ptp-success.c @@ -0,0 +1,2 @@ +#define INJECT_RETVAL 42 +#include "ioctl_ptp.c" diff --git a/tests/ioctl_ptp.c b/tests/ioctl_ptp.c index 349b6e364..f5afef663 100644 --- a/tests/ioctl_ptp.c +++ b/tests/ioctl_ptp.c @@ -9,11 +9,13 @@ */ #include "tests.h" +#include "scno.h" #include <fcntl.h> #include <inttypes.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/ptp_clock.h> @@ -21,119 +23,612 @@ #include "xlat.h" #include "xlat/ptp_extts_flags.h" #include "xlat/ptp_perout_flags.h" +#include "xlat/ptp_pin_funcs.h" + + +#ifdef INJECT_RETVAL +# define INJ_STR " (INJECTED)" +#else +# define INJ_STR "" +#endif + +#define ARRAY_END(a_) ((a_) + ARRAY_SIZE(a_)) +#define ARR_ITEM(arr_, idx_) ((arr_)[(idx_) % ARRAY_SIZE(arr_)]) + +#if STRACE_SIZEOF_KERNEL_LONG_T == SIZEOF_KERNEL_LONG_T +# define SAFE_TIME_T(t_) t_ +#else +# define SAFE_TIME_T(t_) ((time_t) (t_)) +#endif + +static const char *errstr; + +static long +sys_ioctl(kernel_long_t fd, kernel_ulong_t cmd, kernel_ulong_t arg) +{ +#ifdef INJECT_RETVAL + static char buf[256]; +#endif + const long rc = syscall(__NR_ioctl, fd, cmd, arg); +#ifdef INJECT_RETVAL + snprintf(buf, sizeof(buf), "%s (INJECTED)", sprintrc(rc)); + errstr = buf; +#else + errstr = sprintrc(rc); +#endif + return rc; +} static void -test_no_device(void) +print_lltime(const long long sec, const unsigned long long nsec) { - const char *errstr; +#if !XLAT_RAW + if ((time_t) sec != sec) + return; - TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_clock_caps, caps); - fill_memory(caps, sizeof(*caps)); + print_time_t_nsec(sec, nsec, 1); +#endif +} - TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_sys_offset, sysoff); - fill_memory(sysoff, sizeof(*sysoff)); +static void +check_bad_ptr(const uint32_t ioc_val, const char *const ioc_str, + const void *const p, const size_t sz) +{ + sys_ioctl(-1, ioc_val, (uintptr_t) NULL); + printf("ioctl(-1, " XLAT_FMT ", NULL) = %s\n", + XLAT_SEL(ioc_val, ioc_str), errstr); - TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_extts_request, extts); - fill_memory(extts, sizeof(*extts)); + sys_ioctl(-1, ioc_val, (uintptr_t) p + sz); + printf("ioctl(-1, " XLAT_FMT ", %p) = %s\n", + XLAT_SEL(ioc_val, ioc_str), p + sz, errstr); + sys_ioctl(-1, ioc_val, (uintptr_t) p + 1); + printf("ioctl(-1, " XLAT_FMT ", %p) = %s\n", + XLAT_SEL(ioc_val, ioc_str), p + 1, errstr); +} + +static void +test_no_device(void) +{ + TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_clock_caps, caps); + TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_sys_offset, sysoff); + TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_sys_offset_extended, soext); + TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_sys_offset_precise, soprec); + TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_extts_request, extts); TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_perout_request, perout); - fill_memory(perout, sizeof(*perout)); + TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_pin_desc, pindesc); + long rc; + + /* unrecognized */ + static const uint8_t unk_nums[] = { 0, 19, 20, 255 }; + + for (const uint8_t *p = unk_nums; p < ARRAY_END(unk_nums); p++) { + for (uint16_t sz = 0; sz < 1280; sz += 8) { + static const struct strval32 dirs[] = { + { ARG_STR(_IOC_NONE) }, + { ARG_STR(_IOC_READ) }, + { ARG_STR(_IOC_WRITE) }, + { ARG_STR(_IOC_READ|_IOC_WRITE) }, + }; + for (const struct strval32 *d = dirs; + d < ARRAY_END(dirs); d++) { + uint32_t ioc = + _IOC(d->val, PTP_CLK_MAGIC, *p, sz); + sys_ioctl(-1, ioc, 0); + printf("ioctl(-1, " + XLAT_KNOWN_FMT("%#x", + "_IOC(%s, %#x, %#x, %#x)") + ", 0) = %s\n", + NABBR(ioc,) + NRAW(d->str, PTP_CLK_MAGIC, *p, sz,) + errstr); + + /* soprec is the biggest var, at 1216 bytes */ + sys_ioctl(-1, ioc, (uintptr_t) soext); + printf("ioctl(-1, " + XLAT_KNOWN_FMT("%#x", + "_IOC(%s, %#x, %#x, %#x)") + ", %p) = %s\n", + NABBR(ioc,) + NRAW(d->str, PTP_CLK_MAGIC, *p, sz,) + soext, errstr); + } + } + } + + /* PTP_CLOCK_GETCAPS{,2} */ + static const struct strval32 ioc_caps[] = { + { ARG_STR(PTP_CLOCK_GETCAPS) }, + { ARG_STR(PTP_CLOCK_GETCAPS2) }, + }; + for (const struct strval32 *c = ioc_caps; c < ARRAY_END(ioc_caps); c++) + { + check_bad_ptr(c->val, c->str, caps, sizeof(*caps)); + + memset(caps, 0, sizeof(*caps)); + rc = sys_ioctl(-1, c->val, (uintptr_t) caps); + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c->val, c->str)); + if (rc >= 0) { + printf("{max_adj=0, n_alarm=0, n_ext_ts=0, n_per_out=0" + ", pps=0, n_pins=0, cross_timestamping=0" + ", adjust_phase=0}"); + } else { + printf("%p", caps); + } + printf(") = %s\n", errstr); + + fill_memory32(caps, sizeof(*caps)); + rc = sys_ioctl(-1, c->val, (uintptr_t) caps); + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c->val, c->str)); + if (rc >= 0) { + printf("{max_adj=-2136948512, n_alarm=-2136948511" + ", n_ext_ts=-2136948510, n_per_out=-2136948509" + ", pps=-2136948508, n_pins=-2136948507" + ", cross_timestamping=-2136948506" + ", adjust_phase=-2136948505" + ", rsv=[0x80a0c0e8, 0x80a0c0e9, 0x80a0c0ea" + ", 0x80a0c0eb, 0x80a0c0ec, 0x80a0c0ed" + ", 0x80a0c0ee, 0x80a0c0ef, 0x80a0c0f0" + ", 0x80a0c0f1, 0x80a0c0f2, 0x80a0c0f3]}"); + } else { + printf("%p", caps); + } + printf(") = %s\n", errstr); + } + + /* PTP_EXTTS_REQUEST{,2} */ + static const struct strval32 ioc_extts[] = { + { ARG_STR(PTP_EXTTS_REQUEST) }, + { ARG_STR(PTP_EXTTS_REQUEST2) }, + }; + static const struct strval32 extts_flags[] = { + { ARG_XLAT_KNOWN(0x1, "PTP_ENABLE_FEATURE") }, + { ARG_XLAT_KNOWN(0xdeadbabe, "PTP_RISING_EDGE|PTP_FALLING_EDGE" + "|PTP_STRICT_FLAGS|0xdeadbab0") }, + { ARG_XLAT_UNKNOWN(0xbadbeef0, "PTP_???") }, + { ARG_STR(0) }, + }; + for (const struct strval32 *c = ioc_extts; c < ARRAY_END(ioc_extts); + c++) { + check_bad_ptr(c->val, c->str, extts, sizeof(*extts)); - /* PTP_CLOCK_GETCAPS */ - errstr = sprintrc(ioctl(-1, PTP_CLOCK_GETCAPS, NULL)); - printf("ioctl(-1, PTP_CLOCK_GETCAPS, NULL) = %s\n", errstr); - errstr = sprintrc(ioctl(-1, PTP_CLOCK_GETCAPS, caps)); - printf("ioctl(-1, PTP_CLOCK_GETCAPS, %p) = %s\n", caps, errstr); + memset(extts, 0, sizeof(*extts)); + sys_ioctl(-1, c->val, (uintptr_t) extts); + printf("ioctl(-1, " XLAT_FMT ", {index=0, flags=0}) = %s\n", + XLAT_SEL(c->val, c->str), errstr); - /* PTP_SYS_OFFSET */ - errstr = sprintrc(ioctl(-1, PTP_SYS_OFFSET, NULL)); - printf("ioctl(-1, PTP_SYS_OFFSET, NULL) = %s\n", errstr); - errstr = sprintrc(ioctl(-1, PTP_SYS_OFFSET, sysoff)); - printf("ioctl(-1, PTP_SYS_OFFSET, {n_samples=%u}) = %s\n", - sysoff->n_samples, errstr); + extts->index = 3141592653; + for (size_t i = 0; i < ARRAY_SIZE(extts_flags); i++) { + extts->flags = extts_flags[i].val; + extts->rsv[0] = i & 1 ? 0xdeadc0de : 0; + extts->rsv[1] = i & 2 ? 0xcafebeef : 0; + + sys_ioctl(-1, c->val, (uintptr_t) extts); + printf("ioctl(-1, " XLAT_FMT ", {index=3141592653" + ", flags=%s", + XLAT_SEL(c->val, c->str), extts_flags[i].str); + if (c->val == PTP_EXTTS_REQUEST2 && (i & 3)) { + printf(", rsv=[%#x, %#x]", + i & 1 ? 0xdeadc0de : 0, + i & 2 ? 0xcafebeef : 0); + } + printf("}) = %s\n", errstr); + + } + } + + /* PTP_PEROUT_REQUEST{,2} */ + static const struct strval32 ioc_perout[] = { + { ARG_STR(PTP_PEROUT_REQUEST) }, + { ARG_STR(PTP_PEROUT_REQUEST2) }, + }; + static const struct perout_flags { + uint32_t is_phase :1, + is_duty_cycle :1; + uint32_t flags; + const char *str; + } perout_flags[] = { + { false, false, ARG_STR(0) }, + { false, false, ARG_XLAT_KNOWN(0x1, "PTP_PEROUT_ONE_SHOT") }, + { false, true, ARG_XLAT_KNOWN(0x3, "PTP_PEROUT_ONE_SHOT" + "|PTP_PEROUT_DUTY_CYCLE") }, + { true, false, + ARG_XLAT_KNOWN(0xc0dedbad, "PTP_PEROUT_ONE_SHOT" + "|PTP_PEROUT_PHASE|0xc0dedba8") }, + { true, true, + ARG_XLAT_KNOWN(0xdeadbeef, + "PTP_PEROUT_ONE_SHOT|PTP_PEROUT_DUTY_CYCLE" + "|PTP_PEROUT_PHASE|0xdeadbee8") }, + { false, false, ARG_XLAT_UNKNOWN(0xdeadbea8, "PTP_PEROUT_???") } + }; + for (const struct strval32 *c = ioc_perout; c < ARRAY_END(ioc_perout); + c++) { + check_bad_ptr(c->val, c->str, perout, sizeof(*perout)); + + memset(perout, 0, sizeof(*perout)); + sys_ioctl(-1, c->val, (uintptr_t) perout); + printf("ioctl(-1, " XLAT_FMT ", {start={sec=0, nsec=0}" + ", period={sec=0, nsec=0}, index=0, flags=0}) = %s\n", + XLAT_SEL(c->val, c->str), errstr); + + for (size_t i = 0; i < ARRAY_SIZE(perout_flags); i++) { + perout->start.sec = SAFE_TIME_T(0x123456789ULL); + perout->start.nsec = i & 1 ? 1234567890 : 123456789; + perout->start.reserved = i & 2 ? 2718281828 : 0; + perout->period.sec = 0xabcdef; + perout->period.nsec = i & 1 ? 123456789 : 0; + perout->period.reserved = i & 2 ? 0 : 2345678901; + perout->index = 3141592653U; + perout->flags= perout_flags[i].flags; + perout->on.sec = i & 3 ? 0xabcdef0123456789ULL : 0; + perout->on.nsec = i & 2 ? 123456789 : 0; + perout->on.reserved = i & 4 ? 2345678901U : 0; + + sys_ioctl(-1, c->val, (uintptr_t) perout); + printf("ioctl(-1, " XLAT_FMT ", {%s={sec=%lld" + ", nsec=%u%s}", + XLAT_SEL(c->val, c->str), + perout_flags[i].is_phase ? "phase" : "start", + perout->start.sec, + i & 1 ? 1234567890 : 123456789, + i & 2 ? ", reserved=0xa205b064" : ""); + if (!perout_flags[i].is_phase) { + print_lltime(perout->start.sec, + perout->start.nsec); + } + printf(", period={sec=11259375, nsec=%u%s}" + ", index=3141592653, flags=%s", + i & 1 ? 123456789 : 0, + i & 2 ? "" : ", reserved=0x8bd03835", + perout_flags[i].str); + if (perout_flags[i].is_duty_cycle) { + printf(", on={sec=%lld, nsec=%u%s}", + i & 3 ? 0xabcdef0123456789ULL : 0, + i & 2 ? 123456789 : 0, + i & 4 ? ", reserved=0x8bd03835" : ""); + } else if (i && c->val == PTP_PEROUT_REQUEST2) { + printf(", rsv=[%#x, %#x, %#x, %#x]", + i & 3 ? BE_LE(0xabcdef01, 0x23456789) : 0, + i & 3 ? BE_LE(0x23456789, 0xabcdef01) : 0, + i & 2 ? 123456789 : 0, + i & 4 ? 2345678901U : 0); + } + printf("}) = %s\n", errstr); + } + } /* PTP_ENABLE_PPS */ - errstr = sprintrc(ioctl(-1, PTP_ENABLE_PPS, 0)); - printf("ioctl(-1, PTP_ENABLE_PPS, 0) = %s\n", errstr); - errstr = sprintrc(ioctl(-1, PTP_ENABLE_PPS, 1)); - printf("ioctl(-1, PTP_ENABLE_PPS, 1) = %s\n", errstr); - - /* PTP_EXTTS_REQUEST */ - errstr = sprintrc(ioctl(-1, PTP_EXTTS_REQUEST, NULL)); - printf("ioctl(-1, PTP_EXTTS_REQUEST, NULL) = %s\n", errstr); - errstr = sprintrc(ioctl(-1, PTP_EXTTS_REQUEST, extts)); - printf("ioctl(-1, PTP_EXTTS_REQUEST, {index=%d, flags=", extts->index); - printflags(ptp_extts_flags, extts->flags, "PTP_???"); - printf("}) = %s\n", errstr); - - /* PTP_PEROUT_REQUEST */ - errstr = sprintrc(ioctl(-1, PTP_PEROUT_REQUEST, NULL)); - printf("ioctl(-1, PTP_PEROUT_REQUEST, NULL) = %s\n", errstr); - errstr = sprintrc(ioctl(-1, PTP_PEROUT_REQUEST, perout)); - printf("ioctl(-1, PTP_PEROUT_REQUEST" - ", {start={sec=%" PRId64 ", nsec=%" PRIu32 "}", - (int64_t) perout->start.sec, perout->start.nsec); - print_time_t_nsec(perout->start.sec, perout->start.nsec, 1); - printf(", period={sec=%" PRId64 ", nsec=%" PRIu32 "}", - (int64_t)perout->period.sec, perout->period.nsec); - print_time_t_nsec(perout->period.sec, perout->period.nsec, 1); - printf(", index=%d, flags=", perout->index); - printflags(ptp_perout_flags, perout->flags, "PTP_???"); - printf("}) = %s\n", errstr); - - /* PTP_CLOCK_GETCAPS2 */ - errstr = sprintrc(ioctl(-1, PTP_CLOCK_GETCAPS2, NULL)); - printf("ioctl(-1, PTP_CLOCK_GETCAPS2, NULL) = %s\n", errstr); - errstr = sprintrc(ioctl(-1, PTP_CLOCK_GETCAPS2, caps)); - printf("ioctl(-1, PTP_CLOCK_GETCAPS2, %p) = %s\n", caps, errstr); - - /* PTP_SYS_OFFSET2 */ - errstr = sprintrc(ioctl(-1, PTP_SYS_OFFSET2, NULL)); - printf("ioctl(-1, PTP_SYS_OFFSET2, NULL) = %s\n", errstr); - errstr = sprintrc(ioctl(-1, PTP_SYS_OFFSET2, sysoff)); - printf("ioctl(-1, PTP_SYS_OFFSET2, {n_samples=%u}) = %s\n", - sysoff->n_samples, errstr); + sys_ioctl(-1, PTP_ENABLE_PPS, 0); + printf("ioctl(-1, %s, 0) = %s\n", + XLAT_STR(PTP_ENABLE_PPS), errstr); + sys_ioctl(-1, PTP_ENABLE_PPS, -1); + printf("ioctl(-1, %s, %#lx) = %s\n", + XLAT_STR(PTP_ENABLE_PPS), (long int) -1, errstr); /* PTP_ENABLE_PPS2 */ - errstr = sprintrc(ioctl(-1, PTP_ENABLE_PPS2, 0)); - printf("ioctl(-1, PTP_ENABLE_PPS2, 0) = %s\n", errstr); - errstr = sprintrc(ioctl(-1, PTP_ENABLE_PPS2, 1)); - printf("ioctl(-1, PTP_ENABLE_PPS2, 1) = %s\n", errstr); - - /* PTP_EXTTS_REQUEST2 */ - errstr = sprintrc(ioctl(-1, PTP_EXTTS_REQUEST2, NULL)); - printf("ioctl(-1, PTP_EXTTS_REQUEST2, NULL) = %s\n", errstr); - errstr = sprintrc(ioctl(-1, PTP_EXTTS_REQUEST2, extts)); - printf("ioctl(-1, PTP_EXTTS_REQUEST2, {index=%d, flags=", extts->index); - printflags(ptp_extts_flags, extts->flags, "PTP_???"); - printf("}) = %s\n", errstr); - - /* PTP_PEROUT_REQUEST2 */ - errstr = sprintrc(ioctl(-1, PTP_PEROUT_REQUEST2, NULL)); - printf("ioctl(-1, PTP_PEROUT_REQUEST2, NULL) = %s\n", errstr); - errstr = sprintrc(ioctl(-1, PTP_PEROUT_REQUEST2, perout)); - printf("ioctl(-1, PTP_PEROUT_REQUEST2, {start={sec=%" PRId64 - ", nsec=%" PRIu32 "}, period={sec=%" PRId64 ", nsec=%" PRIu32 "}" - ", index=%d, flags=", - (int64_t) perout->start.sec, perout->start.nsec, - (int64_t)perout->period.sec, perout->period.nsec, perout->index); - printflags(ptp_perout_flags, perout->flags, "PTP_???"); - printf("}) = %s\n", errstr); + sys_ioctl(-1, PTP_ENABLE_PPS2, 0); + printf("ioctl(-1, %s, 0) = %s\n", + XLAT_STR(PTP_ENABLE_PPS2), errstr); + sys_ioctl(-1, PTP_ENABLE_PPS2, -123456789); + printf("ioctl(-1, %s, %#lx) = %s\n", + XLAT_STR(PTP_ENABLE_PPS2), (long int) -123456789, errstr); - /* unrecognized */ - ioctl(-1, _IOC(_IOC_READ, PTP_CLK_MAGIC, 0xff, 0xfe), 0); - printf("ioctl(-1, _IOC(_IOC_READ, %#x, 0xff, 0xfe), 0) = %s\n", - PTP_CLK_MAGIC, errstr); - - const unsigned long arg = (unsigned long) 0xfacefeeddeadbeefULL; - ioctl(-1, _IOC(_IOC_WRITE, PTP_CLK_MAGIC, 0xfd, 0xfc), arg); - printf("ioctl(-1, _IOC(_IOC_WRITE, %#x, 0xfd, 0xfc), %#lx)" - " = %s\n", PTP_CLK_MAGIC, arg, errstr); + /* PTP_SYS_OFFSET{,2} */ + static const struct strval32 ioc_sysoff[] = { + { ARG_STR(PTP_SYS_OFFSET) }, + { ARG_STR(PTP_SYS_OFFSET2) }, + }; + for (const struct strval32 *c = ioc_sysoff; c < ARRAY_END(ioc_sysoff); + c++) { + check_bad_ptr(c->val, c->str, sysoff, sizeof(*sysoff)); + + memset(sysoff, 0, sizeof(*sysoff)); + rc = sys_ioctl(-1, c->val, (uintptr_t) sysoff); + printf("ioctl(-1, " XLAT_FMT ", {n_samples=0%s}) = %s\n", + XLAT_SEL(c->val, c->str), + rc >= 0 ? ", ts=[{sec=0, nsec=0}]" : "", errstr); + + for (size_t i = 0; i < 4; i++) { + sysoff->n_samples = i > 2 ? 0xdeadface : i * 12 + 1; + sysoff->rsv[0] = i & 1 ? 0xbadfaced : 0; + sysoff->rsv[2] = i & 2 ? 0xcafeface : 0; + for (size_t j = 0; j < 2 * PTP_MAX_SAMPLES + 1; j++) { + sysoff->ts[j].sec = SAFE_TIME_T(2345678901U + j); + sysoff->ts[j].nsec = 999999999 - i * 12 + j; + sysoff->ts[j].reserved = j & 1 ? 0xdeadface : 0; + } + + rc = sys_ioctl(-1, c->val, (uintptr_t) sysoff); + printf("ioctl(-1, " XLAT_FMT ", {n_samples=%zu%s%s%s%s", + XLAT_SEL(c->val, c->str), + i > 2 ? 0xdeadface : i * 12 + 1, + i & 3 ? ", rsv=[" : "", + i & 3 ? i & 1 ? "0xbadfaced" : "0" : "", + i & 3 ? ", 0, " : "", + i & 3 ? i & 2 ? "0xcafeface]" : "0]" : ""); + if (rc >= 0) { + for (size_t j = 0; + j < MIN(i * 24 + 3, + XLAT_RAW || XLAT_VERBOSE ? 51 + : 32); + j++) { + printf("%s{sec=%lld, nsec=%u%s}", + j ? ", " : ", ts=[", + sysoff->ts[j].sec, + sysoff->ts[j].nsec, + j & 1 ? ", reserved=0xdeadface" + : ""); + print_lltime(sysoff->ts[j].sec, + sysoff->ts[j].nsec); + } + printf("%s]", + XLAT_RAW || XLAT_VERBOSE || i < 2 + ? "" : ", ..."); + } + printf("}) = %s\n", errstr); + } + } + + /* PTP_PIN_[GS]ETFUNC{,2} */ + static const struct ioc_pin { + uint32_t is_get :1, + is_v2 :1; + uint32_t val; + const char *str; + } ioc_pin[] = { + { true, false, ARG_STR(PTP_PIN_GETFUNC) }, + { true, true, ARG_STR(PTP_PIN_GETFUNC2) }, + { false, false, ARG_STR(PTP_PIN_SETFUNC) }, + { false, true, ARG_STR(PTP_PIN_SETFUNC2) }, + }; + static const struct strval32 pin_funcs[] = { + { ENUM_KNOWN(0x1, PTP_PF_EXTTS) }, + { ENUM_KNOWN(0x3, PTP_PF_PHYSYNC) }, + { ARG_XLAT_UNKNOWN(0x4, "PTP_PF_???") }, + { ARG_XLAT_UNKNOWN(0xdeadcafe, "PTP_PF_???") }, + }; + for (const struct ioc_pin *c = ioc_pin; c < ARRAY_END(ioc_pin); c++) { + check_bad_ptr(c->val, c->str, pindesc, sizeof(*pindesc)); + + memset(pindesc, 0, sizeof(*pindesc)); + rc = sys_ioctl(-1, c->val, (uintptr_t) pindesc); + printf("ioctl(-1, " XLAT_FMT ", {index=0", + XLAT_SEL(c->val, c->str)); + if (rc >= 0 || !c->is_get) { + printf("%s, func=" XLAT_FMT ", chan=0", + c->is_get ? ", name=\"\"" : "", + XLAT_ARGS(PTP_PF_NONE)); + } + printf("}) = %s\n", errstr); + + for (size_t i = 0; i < ARRAY_SIZE(pin_funcs); i++) { + memcpy(pindesc->name, + i & 1 ? "\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17" + "OH HAI THAR\176\177\377\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + : "abcdefghijklmnopqrstuvwxyz0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", + sizeof(pindesc->name)); + pindesc->index = 0xcafebabeU; + pindesc->func = pin_funcs[i].val; + pindesc->chan = 0xfeedbeefU; + pindesc->rsv[0] = i & 1 ? 0xbadc0ded : 0; + pindesc->rsv[4] = i & 2 ? 0 : 0xdadfaced; + + rc = sys_ioctl(-1, c->val, (uintptr_t) pindesc); + printf("ioctl(-1, " XLAT_FMT ", {index=3405691582", + XLAT_SEL(c->val, c->str)); + if (c->is_get && c->is_v2 && (i & 3) != 2) { + printf(", rsv=[%#x, 0, 0, 0, %#x]", + i & 1 ? 0xbadc0ded : 0, + i & 2 ? 0 : 0xdadfaced); + } + if (rc >= 0 || !c->is_get) { + if (c->is_get) { + printf(", name=\"%s", + i & 1 ? "\\1\\2\\3\\4\\5\\6\\7" + "\\10\\t\\n\\v\\f\\r\\16" + "\\17OH HAI THAR~\\177" + "\\377\"" + : "abcdefghijklmnopqrstuvw" + "xyz0123456789ABCDEFGHIJ" + "KLMNOPQRSTUVWXYZ0\"" + "..."); + } + printf(", func=%s, chan=4276993775", + pin_funcs[i].str); + if (!c->is_get && c->is_v2 + && ((i & 1) || !(i & 2))) { + printf(", rsv=[%#x, 0, 0, 0, %#x]", + i & 1 ? 0xbadc0ded : 0, + i & 2 ? 0 : 0xdadfaced); + } + } + printf("}) = %s\n", errstr); + } + } + + /* PTP_SYS_OFFSET_PRECISE{,2} */ + static const struct strval32 ioc_soprec[] = { + { ARG_STR(PTP_SYS_OFFSET_PRECISE) }, + { ARG_STR(PTP_SYS_OFFSET_PRECISE2) }, + }; + static const struct ptp_clock_time ts_vecs[] = { + { 0, 123456789 }, + { 0x23456789, 0, 0xdeadface }, + { SAFE_TIME_T(0x123456789ab), 1234567890 }, + { SAFE_TIME_T(0x123456789abcd), 987654321, 0x1 }, + }; + for (const struct strval32 *c = ioc_soprec; c < ARRAY_END(ioc_soprec); + c++) { + check_bad_ptr(c->val, c->str, soprec, sizeof(*soprec)); + + memset(soprec, 0, sizeof(*soprec)); + rc = sys_ioctl(-1, c->val, (uintptr_t) soprec); + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c->val, c->str)); + if (rc >= 0) { + printf("{device={sec=0, nsec=0}" + ", sys_realtime={sec=0, nsec=0}" + ", sys_monoraw={sec=0, nsec=0}}"); + } else { + printf("%p", soprec); + } + printf(") = %s\n", errstr); + + for (size_t i = 0; i < ARRAY_SIZE(ts_vecs); i++) { + soprec->device = ts_vecs[i]; + soprec->sys_realtime = ARR_ITEM(ts_vecs, i + 1); + soprec->sys_monoraw = ARR_ITEM(ts_vecs, i + 2); + soprec->rsv[0] = i & 1 ? 0 : 0xbadfaced; + soprec->rsv[3] = i & 2 ? 0 : 0xdeadbeef; + + rc = sys_ioctl(-1, c->val, (uintptr_t) soprec); + printf("ioctl(-1, " XLAT_FMT ", ", + XLAT_SEL(c->val, c->str)); + if (rc >= 0) { + printf("{device={sec=%lld, nsec=%u", + ts_vecs[i].sec, ts_vecs[i].nsec); + if (i & 1) { + printf(", reserved=%#x", + ts_vecs[i].reserved); + } + printf("}"); + print_lltime(ts_vecs[i].sec, ts_vecs[i].nsec); + printf(", sys_realtime={sec=%lld, nsec=%u", + ARR_ITEM(ts_vecs, i + 1).sec, + ARR_ITEM(ts_vecs, i + 1).nsec); + if (!(i & 1)) { + printf(", reserved=%#x", + ARR_ITEM(ts_vecs, i + 1).reserved + ); + } + printf("}"); + print_lltime(ARR_ITEM(ts_vecs, i + 1).sec, + ARR_ITEM(ts_vecs, i + 1).nsec); + printf(", sys_monoraw={sec=%lld, nsec=%u", + ARR_ITEM(ts_vecs, i + 2).sec, + ARR_ITEM(ts_vecs, i + 2).nsec); + if (i & 1) { + printf(", reserved=%#x", + ARR_ITEM(ts_vecs, i + 2).reserved + ); + } + printf("}"); + if ((i & 3) != 3) { + printf(", rsv=[%#x, 0, 0, %#x]", + i & 1 ? 0 : 0xbadfaced, + i & 2 ? 0 : 0xdeadbeef); + } + printf("}"); + } else { + printf("%p", soprec); + } + printf(") = %s\n", errstr); + } + } + + /* PTP_SYS_OFFSET_EXTENDED{,2} */ + static const struct strval32 ioc_soext[] = { + { ARG_STR(PTP_SYS_OFFSET_EXTENDED) }, + { ARG_STR(PTP_SYS_OFFSET_EXTENDED2) }, + }; + for (const struct strval32 *c = ioc_soext; c < ARRAY_END(ioc_soext); + c++) { + check_bad_ptr(c->val, c->str, soext, sizeof(*soext)); + + memset(soext, 0, sizeof(*soext)); + rc = sys_ioctl(-1, c->val, (uintptr_t) soext); + printf("ioctl(-1, " XLAT_FMT ", {n_samples=0%s}) = %s\n", + XLAT_SEL(c->val, c->str), + rc >= 0 ? ", ts=[]" : "", errstr); + + for (size_t i = 0; i < 4; i++) { + soext->n_samples = i > 2 ? 0xdeadface : i * 12 + 1; + soext->rsv[0] = i & 1 ? 0xbadfaced : 0; + soext->rsv[2] = i & 2 ? 0xcafeface : 0; + for (size_t j = 0; j < PTP_MAX_SAMPLES; j++) { + soext->ts[j][0].sec = + SAFE_TIME_T(2345678901U + j); + soext->ts[j][0].nsec = 999999999 - i * 12 + j; + soext->ts[j][0].reserved = j & 1 ? 0xbee : 0; + + soext->ts[j][1].sec = + SAFE_TIME_T(-123456780123L + j); + soext->ts[j][1].nsec = -(i * 12) + j; + soext->ts[j][1].reserved = j & 2 ? 0xface : 0; + + soext->ts[j][2].sec = + SAFE_TIME_T(j * (1 << 30)); + soext->ts[j][2].nsec = j * (1 << 29); + soext->ts[j][2].reserved = j & 4 ? 0xbabe : 0; + } + + rc = sys_ioctl(-1, c->val, (uintptr_t) soext); + printf("ioctl(-1, " XLAT_FMT ", {n_samples=%zu", + XLAT_SEL(c->val, c->str), + i > 2 ? 0xdeadface : i * 12 + 1); + if (i & 3) { + printf(", rsv=[%#x, 0, %#x]", + i & 1 ? 0xbadfaced : 0, + i & 2 ? 0xcafeface : 0); + } + if (rc >= 0) { + for (size_t j = 0; j < MIN(i * 12 + 1, 25); j++) + { + printf("%s", j ? "], " : ", ts=["); + for (size_t k = 0; k < 3; k++) { + printf("%s{sec=%lld, nsec=%u", + k ? ", " : "[", + soext->ts[j][k].sec, + soext->ts[j][k].nsec); + if (soext->ts[j][k].reserved) + printf(", reserved=%#x", + soext->ts[j][k] + .reserved); + printf("}"); + print_lltime( + soext->ts[j][k].sec, + soext->ts[j][k].nsec); + } + } + printf("]]"); + } + printf("}) = %s\n", errstr); + } + } } int -main(void) +main(int argc, char *argv[]) { +#ifdef INJECT_RETVAL + unsigned long num_skip; + bool locked = false; + + if (argc < 2) + error_msg_and_fail("Usage: %s NUM_SKIP", argv[0]); + + num_skip = strtoul(argv[1], NULL, 0); + for (unsigned int i = 0; i < num_skip; i++) { + long rc = sys_ioctl(-1, PTP_CLOCK_GETCAPS, 0); + printf("ioctl(-1, %s, NULL) = %s%s\n", + XLAT_STR(PTP_CLOCK_GETCAPS), sprintrc(rc), + rc == 42 ? " (INJECTED)" : ""); + + if (rc != 42) + continue; + + locked = true; + break; + } + + if (!locked) { + error_msg_and_fail("Have not locked on ioctl(-1" + ", PTP_CLOCK_GETCAPS, NULL) returning 42"); + } +#endif /* INJECT_RETVAL */ + test_no_device(); puts("+++ exited with 0 +++"); diff --git a/tests/pure_executables.list b/tests/pure_executables.list index e794602dc..451c476f0 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -230,6 +230,9 @@ ioctl_mtd ioctl_nbd ioctl_perf ioctl_ptp +ioctl_ptp-Xabbrev +ioctl_ptp-Xraw +ioctl_ptp-Xverbose ioctl_random ioctl_rtc ioctl_scsi |