1 /*
2  * Copyright (c) 2014 Stefan Sørensen <stefan.sorensen@spectralink.com>
3  * Copyright (c) 2014-2015 Dmitry V. Levin <ldv@altlinux.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "defs.h"
30 #include <linux/ioctl.h>
31 #include <linux/ptp_clock.h>
32 
33 #include "xlat/ptp_flags_options.h"
34 
35 int
ptp_ioctl(struct tcb * tcp,const unsigned int code,const long arg)36 ptp_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
37 {
38 	if (!verbose(tcp))
39 		return RVAL_DECODED;
40 
41 	switch (code) {
42 	case PTP_EXTTS_REQUEST: {
43 		struct ptp_extts_request extts;
44 
45 		tprints(", ");
46 		if (umove_or_printaddr(tcp, arg, &extts))
47 			break;
48 
49 		tprintf("{index=%d, flags=", extts.index);
50 		printflags(ptp_flags_options, extts.flags, "PTP_???");
51 		tprints("}");
52 		break;
53 	}
54 
55 	case PTP_PEROUT_REQUEST: {
56 		struct ptp_perout_request perout;
57 
58 		tprints(", ");
59 		if (umove_or_printaddr(tcp, arg, &perout))
60 			break;
61 
62 		tprintf("{start={%" PRId64 ", %" PRIu32 "}"
63 			   ", period={%" PRId64 ", %" PRIu32 "}"
64 			   ", index=%d, flags=",
65 			(int64_t)perout.start.sec, perout.start.nsec,
66 			(int64_t)perout.period.sec, perout.period.nsec,
67 			perout.index);
68 		printflags(ptp_flags_options, perout.flags, "PTP_???");
69 		tprints("}");
70 		break;
71 	}
72 
73 	case PTP_ENABLE_PPS:
74 		tprintf(", %ld", arg);
75 		break;
76 
77 	case PTP_SYS_OFFSET: {
78 		struct ptp_sys_offset sysoff;
79 
80 		if (entering(tcp)) {
81 			tprints(", ");
82 			if (umove_or_printaddr(tcp, arg, &sysoff))
83 				break;
84 
85 			tprintf("{n_samples=%u", sysoff.n_samples);
86 			return 1;
87 		} else {
88 			unsigned int n_samples, i;
89 
90 			if (syserror(tcp)) {
91 				tprints("}");
92 				break;
93 			}
94 
95 			tprints(", ");
96 			if (umove(tcp, arg, &sysoff) < 0) {
97 				tprints("???}");
98 				break;
99 			}
100 
101 			tprints("ts=[");
102 			n_samples = sysoff.n_samples > PTP_MAX_SAMPLES ?
103 				PTP_MAX_SAMPLES : sysoff.n_samples;
104 			for (i = 0; i < 2 * n_samples + 1; ++i) {
105 				if (i > 0)
106 					tprints(", ");
107 				tprintf("{%" PRId64 ", %" PRIu32 "}",
108 					(int64_t)sysoff.ts[i].sec,
109 					sysoff.ts[i].nsec);
110 			}
111 			if (sysoff.n_samples > PTP_MAX_SAMPLES)
112 				tprints(", ...");
113 			tprints("]}");
114 			break;
115 		}
116 	}
117 	case PTP_CLOCK_GETCAPS: {
118 		struct ptp_clock_caps caps;
119 
120 		if (entering(tcp))
121 			return 0;
122 
123 		tprints(", ");
124 		if (umove_or_printaddr(tcp, arg, &caps))
125 			break;
126 
127 		tprintf("{max_adj=%d, n_alarm=%d, n_ext_ts=%d, n_per_out=%d, pps=%d}",
128 			caps.max_adj, caps.n_alarm, caps.n_ext_ts,
129 			caps.n_per_out, caps.pps);
130 		break;
131 	}
132 
133 	default:
134 		return RVAL_DECODED;
135 	}
136 
137 	return RVAL_DECODED | 1;
138 }
139