(root)/
strace-6.5/
src/
ptp.c
       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  }