1 /*
2 * Copyright (c) 2014 Stefan Sørensen <stefan.sorensen@spectralink.com>
3 * Copyright (c) 2014-2015 Dmitry V. Levin <ldv@strace.io>
4 * Copyright (c) 2014-2023 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: LGPL-2.1-or-later
8 */
9
10 #include "defs.h"
11
12 #include <linux/ioctl.h>
13 #include <linux/ptp_clock.h>
14
15 #include "xlat/ptp_extts_flags.h"
16 #include "xlat/ptp_perout_flags.h"
17 #include "xlat/ptp_pin_funcs.h"
18
19 static void
20 print_ptp_clock_time(const struct ptp_clock_time *const p, bool rtc)
21 {
22 tprint_struct_begin();
23 PRINT_FIELD_D(*p, sec);
24 tprint_struct_next();
25 PRINT_FIELD_U(*p, nsec);
26 if (p->reserved) {
27 tprint_struct_next();
28 PRINT_FIELD_X(*p, reserved);
29 }
30 tprint_struct_end();
31
32 if (rtc && xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW)
33 tprints_comment(sprinttime_nsec(p->sec, p->nsec));
34 }
35
36 static bool
37 print_ptp_clock_time_am(struct tcb *tcp, void *elem_buf, size_t elem_size,
38 void *data)
39 {
40 print_ptp_clock_time(elem_buf, true);
41 return true;
42 }
43
44 static bool
45 print_ptp_clock_time3_am(struct tcb *tcp, void *elem_buf, size_t elem_size,
46 void *data)
47 {
48 const struct ptp_clock_time *const p = elem_buf;
49
50 tprint_array_begin();
51 print_ptp_clock_time(p, true);
52 tprint_array_next();
53 print_ptp_clock_time(p + 1, true);
54 tprint_array_next();
55 print_ptp_clock_time(p + 2, true);
56 tprint_array_end();
57
58 return true;
59 }
60
61 #define PRINT_RSV(where_, field_) \
62 do { \
63 if (!IS_ARRAY_ZERO(where_.field_)) { \
64 tprint_struct_next(); \
65 PRINT_FIELD_ARRAY(where_, field_, tcp, \
66 print_xint_array_member); \
67 } \
68 } while (0)
69
70 int
71 ptp_ioctl(struct tcb *const tcp, const unsigned int code,
72 const kernel_ulong_t arg)
73 {
74 if (!verbose(tcp))
75 return RVAL_DECODED;
76
77 switch (code) {
78 case PTP_CLOCK_GETCAPS:
79 case PTP_CLOCK_GETCAPS2: {
80 struct ptp_clock_caps caps;
81 CHECK_TYPE_SIZE(caps.rsv, sizeof(unsigned int) * 11);
82 CHECK_IOCTL_SIZE(PTP_CLOCK_GETCAPS, 80);
83 CHECK_IOCTL_SIZE(PTP_CLOCK_GETCAPS2, 80);
84
85 if (entering(tcp)) {
86 tprint_arg_next();
87 return 0;
88 }
89
90 if (umove_or_printaddr(tcp, arg, &caps))
91 break;
92
93 tprint_struct_begin();
94 PRINT_FIELD_D(caps, max_adj);
95 tprint_struct_next();
96 PRINT_FIELD_D(caps, n_alarm);
97 tprint_struct_next();
98 PRINT_FIELD_D(caps, n_ext_ts);
99 tprint_struct_next();
100 PRINT_FIELD_D(caps, n_per_out);
101 tprint_struct_next();
102 PRINT_FIELD_D(caps, pps);
103 tprint_struct_next();
104 PRINT_FIELD_D(caps, n_pins);
105 tprint_struct_next();
106 PRINT_FIELD_D(caps, cross_timestamping);
107 tprint_struct_next();
108 PRINT_FIELD_D(caps, adjust_phase);
109 tprint_struct_next();
110 PRINT_FIELD_TICKS_D(caps, max_phase_adj, 1000000000, 9);
111 PRINT_RSV(caps, rsv);
112 tprint_struct_end();
113 break;
114 }
115
116 case PTP_EXTTS_REQUEST:
117 case PTP_EXTTS_REQUEST2: {
118 struct ptp_extts_request extts;
119 CHECK_TYPE_SIZE(extts.rsv, sizeof(unsigned int) * 2);
120 CHECK_IOCTL_SIZE(PTP_EXTTS_REQUEST, 16);
121 CHECK_IOCTL_SIZE(PTP_EXTTS_REQUEST2, 16);
122
123 tprint_arg_next();
124 if (umove_or_printaddr(tcp, arg, &extts))
125 break;
126
127 tprint_struct_begin();
128 PRINT_FIELD_U(extts, index);
129 tprint_struct_next();
130 PRINT_FIELD_FLAGS(extts, flags, ptp_extts_flags, "PTP_???");
131 if (code == PTP_EXTTS_REQUEST2)
132 PRINT_RSV(extts, rsv);
133 tprint_struct_end();
134 break;
135 }
136
137 case PTP_PEROUT_REQUEST:
138 case PTP_PEROUT_REQUEST2: {
139 struct ptp_perout_request perout;
140 CHECK_TYPE_SIZE(perout.rsv, sizeof(unsigned int) * 4);
141 CHECK_IOCTL_SIZE(PTP_PEROUT_REQUEST, 56);
142 CHECK_IOCTL_SIZE(PTP_PEROUT_REQUEST2, 56);
143
144 tprint_arg_next();
145 if (umove_or_printaddr(tcp, arg, &perout))
146 break;
147
148 tprint_struct_begin();
149 if (perout.flags & PTP_PEROUT_PHASE) {
150 PRINT_FIELD_OBJ_PTR(perout, phase, print_ptp_clock_time,
151 false);
152 } else {
153 PRINT_FIELD_OBJ_PTR(perout, start, print_ptp_clock_time,
154 true);
155 }
156 tprint_struct_next();
157 PRINT_FIELD_OBJ_PTR(perout, period, print_ptp_clock_time,
158 false);
159 tprint_struct_next();
160 PRINT_FIELD_U(perout, index);
161 tprint_struct_next();
162 PRINT_FIELD_FLAGS(perout, flags, ptp_perout_flags,
163 "PTP_PEROUT_???");
164 if (perout.flags & PTP_PEROUT_DUTY_CYCLE) {
165 tprint_struct_next();
166 PRINT_FIELD_OBJ_PTR(perout, on, print_ptp_clock_time,
167 false);
168 } else if (code == PTP_PEROUT_REQUEST2) {
169 PRINT_RSV(perout, rsv);
170 }
171 tprint_struct_end();
172 break;
173 }
174
175 case PTP_ENABLE_PPS:
176 case PTP_ENABLE_PPS2:
177 tprint_arg_next();
178 PRINT_VAL_X(arg);
179 break;
180
181 case PTP_SYS_OFFSET:
182 case PTP_SYS_OFFSET2: {
183 struct ptp_sys_offset sysoff;
184 CHECK_TYPE_SIZE(sysoff.rsv, sizeof(unsigned int) * 3);
185 CHECK_IOCTL_SIZE(PTP_SYS_OFFSET, 832);
186 CHECK_IOCTL_SIZE(PTP_SYS_OFFSET2, 832);
187
188 if (entering(tcp)) {
189 tprint_arg_next();
190 if (umove_or_printaddr(tcp, arg, &sysoff))
191 break;
192
193 tprint_struct_begin();
194 PRINT_FIELD_U(sysoff, n_samples);
195 PRINT_RSV(sysoff, rsv);
196 return 0;
197 } else {
198 if (syserror(tcp)) {
199 /* ... */
200 } else if (!umove(tcp, arg, &sysoff)) {
201 unsigned int n_samples =
202 MIN(sysoff.n_samples, PTP_MAX_SAMPLES);
203 tprint_struct_next();
204 PRINT_FIELD_ARRAY_UPTO(sysoff, ts,
205 2 * n_samples + 1, tcp,
206 print_ptp_clock_time_am);
207 } else {
208 tprint_struct_next();
209 tprint_unavailable();
210 }
211 tprint_struct_end();
212 break;
213 }
214 }
215
216 case PTP_PIN_GETFUNC:
217 case PTP_PIN_GETFUNC2:
218 case PTP_PIN_SETFUNC:
219 case PTP_PIN_SETFUNC2: {
220 struct ptp_pin_desc pinfunc;
221 CHECK_TYPE_SIZE(pinfunc.rsv, sizeof(unsigned int) * 5);
222 CHECK_IOCTL_SIZE(PTP_PIN_GETFUNC, 96);
223 CHECK_IOCTL_SIZE(PTP_PIN_GETFUNC2, 96);
224 CHECK_IOCTL_SIZE(PTP_PIN_SETFUNC, 96);
225 CHECK_IOCTL_SIZE(PTP_PIN_SETFUNC2, 96);
226
227 if (entering(tcp)) {
228 tprint_arg_next();
229
230 if (umove_or_printaddr(tcp, arg, &pinfunc))
231 break;
232
233 tprint_struct_begin();
234 PRINT_FIELD_U(pinfunc, index);
235
236 switch (code) {
237 case PTP_PIN_GETFUNC2:
238 PRINT_RSV(pinfunc, rsv);
239 ATTRIBUTE_FALLTHROUGH;
240 case PTP_PIN_GETFUNC:
241 return 0;
242 }
243 } else /* getter syscall exit */ {
244 if (syserror(tcp)) {
245 tprint_struct_end();
246 break;
247 }
248
249 if (umove(tcp, arg, &pinfunc) < 0) {
250 tprint_arg_next();
251 tprint_unavailable();
252 tprint_struct_end();
253 break;
254 }
255 }
256
257 /* setter syscall enter or getter syscall exit */
258 switch (code) {
259 case PTP_PIN_GETFUNC:
260 case PTP_PIN_GETFUNC2:
261 tprint_struct_next();
262 PRINT_FIELD_CSTRING(pinfunc, name);
263 }
264 tprint_struct_next();
265 PRINT_FIELD_XVAL(pinfunc, func, ptp_pin_funcs, "PTP_PF_???");
266 tprint_struct_next();
267 PRINT_FIELD_U(pinfunc, chan);
268 if (code == PTP_PIN_SETFUNC2) {
269 PRINT_RSV(pinfunc, rsv);
270 }
271 tprint_struct_end();
272 break;
273 }
274
275 case PTP_SYS_OFFSET_PRECISE:
276 case PTP_SYS_OFFSET_PRECISE2: {
277 struct ptp_sys_offset_precise sysoff;
278 CHECK_TYPE_SIZE(sysoff.rsv, sizeof(unsigned int) * 4);
279 CHECK_IOCTL_SIZE(PTP_SYS_OFFSET_PRECISE, 64);
280 CHECK_IOCTL_SIZE(PTP_SYS_OFFSET_PRECISE2, 64);
281
282 if (entering(tcp)) {
283 tprint_arg_next();
284 return 0;
285 }
286
287 if (umove_or_printaddr(tcp, arg, &sysoff))
288 break;
289
290 tprint_struct_begin();
291 PRINT_FIELD_OBJ_PTR(sysoff, device, print_ptp_clock_time, true);
292 tprint_struct_next();
293 PRINT_FIELD_OBJ_PTR(sysoff, sys_realtime, print_ptp_clock_time,
294 true);
295 tprint_struct_next();
296 PRINT_FIELD_OBJ_PTR(sysoff, sys_monoraw, print_ptp_clock_time,
297 false);
298 PRINT_RSV(sysoff, rsv);
299 tprint_struct_end();
300 break;
301 }
302
303 case PTP_SYS_OFFSET_EXTENDED:
304 case PTP_SYS_OFFSET_EXTENDED2: {
305 struct ptp_sys_offset_extended sysoff;
306 CHECK_TYPE_SIZE(sysoff.rsv, sizeof(unsigned int) * 3);
307 CHECK_IOCTL_SIZE(PTP_SYS_OFFSET_EXTENDED, 1216);
308 CHECK_IOCTL_SIZE(PTP_SYS_OFFSET_EXTENDED2, 1216);
309
310 if (entering(tcp)) {
311 tprint_arg_next();
312 if (umove_or_printaddr(tcp, arg, &sysoff))
313 break;
314
315 tprint_struct_begin();
316 PRINT_FIELD_U(sysoff, n_samples);
317 PRINT_RSV(sysoff, rsv);
318 return 0;
319 }
320
321 if (syserror(tcp)) {
322 /* ... */
323 } else if (!umove(tcp, arg, &sysoff)) {
324 unsigned int n_samples =
325 MIN(sysoff.n_samples, PTP_MAX_SAMPLES);
326 tprint_struct_next();
327 PRINT_FIELD_ARRAY_UPTO(sysoff, ts,
328 n_samples, tcp,
329 print_ptp_clock_time3_am);
330 } else {
331 tprint_struct_next();
332 tprint_unavailable();
333 }
334 tprint_struct_end();
335 break;
336 }
337
338 default:
339 return RVAL_DECODED;
340 }
341
342 return RVAL_IOCTL_DECODED;
343 }