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 }