xref: /aosp_15_r20/external/iproute2/ip/iplink_can.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * iplink_can.c	CAN device support
3*de1e4e89SAndroid Build Coastguard Worker  *
4*de1e4e89SAndroid Build Coastguard Worker  *		This program is free software; you can redistribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker  *		modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker  *		as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker  *		2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker  *
9*de1e4e89SAndroid Build Coastguard Worker  * Authors:	Wolfgang Grandegger <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker  */
11*de1e4e89SAndroid Build Coastguard Worker 
12*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
13*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
15*de1e4e89SAndroid Build Coastguard Worker 
16*de1e4e89SAndroid Build Coastguard Worker #include <linux/can/netlink.h>
17*de1e4e89SAndroid Build Coastguard Worker 
18*de1e4e89SAndroid Build Coastguard Worker #include "rt_names.h"
19*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
20*de1e4e89SAndroid Build Coastguard Worker #include "ip_common.h"
21*de1e4e89SAndroid Build Coastguard Worker 
print_usage(FILE * f)22*de1e4e89SAndroid Build Coastguard Worker static void print_usage(FILE *f)
23*de1e4e89SAndroid Build Coastguard Worker {
24*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f,
25*de1e4e89SAndroid Build Coastguard Worker 		"Usage: ip link set DEVICE type can\n"
26*de1e4e89SAndroid Build Coastguard Worker 		"\t[ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |\n"
27*de1e4e89SAndroid Build Coastguard Worker 		"\t[ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1\n \t  phase-seg2 PHASE-SEG2 [ sjw SJW ] ]\n"
28*de1e4e89SAndroid Build Coastguard Worker 		"\n"
29*de1e4e89SAndroid Build Coastguard Worker 		"\t[ dbitrate BITRATE [ dsample-point SAMPLE-POINT] ] |\n"
30*de1e4e89SAndroid Build Coastguard Worker 		"\t[ dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1\n \t  dphase-seg2 PHASE-SEG2 [ dsjw SJW ] ]\n"
31*de1e4e89SAndroid Build Coastguard Worker 		"\n"
32*de1e4e89SAndroid Build Coastguard Worker 		"\t[ loopback { on | off } ]\n"
33*de1e4e89SAndroid Build Coastguard Worker 		"\t[ listen-only { on | off } ]\n"
34*de1e4e89SAndroid Build Coastguard Worker 		"\t[ triple-sampling { on | off } ]\n"
35*de1e4e89SAndroid Build Coastguard Worker 		"\t[ one-shot { on | off } ]\n"
36*de1e4e89SAndroid Build Coastguard Worker 		"\t[ berr-reporting { on | off } ]\n"
37*de1e4e89SAndroid Build Coastguard Worker 		"\t[ fd { on | off } ]\n"
38*de1e4e89SAndroid Build Coastguard Worker 		"\t[ fd-non-iso { on | off } ]\n"
39*de1e4e89SAndroid Build Coastguard Worker 		"\t[ presume-ack { on | off } ]\n"
40*de1e4e89SAndroid Build Coastguard Worker 		"\n"
41*de1e4e89SAndroid Build Coastguard Worker 		"\t[ restart-ms TIME-MS ]\n"
42*de1e4e89SAndroid Build Coastguard Worker 		"\t[ restart ]\n"
43*de1e4e89SAndroid Build Coastguard Worker 		"\n"
44*de1e4e89SAndroid Build Coastguard Worker 		"\t[ termination { 0..65535 } ]\n"
45*de1e4e89SAndroid Build Coastguard Worker 		"\n"
46*de1e4e89SAndroid Build Coastguard Worker 		"\tWhere: BITRATE	:= { 1..1000000 }\n"
47*de1e4e89SAndroid Build Coastguard Worker 		"\t	  SAMPLE-POINT	:= { 0.000..0.999 }\n"
48*de1e4e89SAndroid Build Coastguard Worker 		"\t	  TQ		:= { NUMBER }\n"
49*de1e4e89SAndroid Build Coastguard Worker 		"\t	  PROP-SEG	:= { 1..8 }\n"
50*de1e4e89SAndroid Build Coastguard Worker 		"\t	  PHASE-SEG1	:= { 1..8 }\n"
51*de1e4e89SAndroid Build Coastguard Worker 		"\t	  PHASE-SEG2	:= { 1..8 }\n"
52*de1e4e89SAndroid Build Coastguard Worker 		"\t	  SJW		:= { 1..4 }\n"
53*de1e4e89SAndroid Build Coastguard Worker 		"\t	  RESTART-MS	:= { 0 | NUMBER }\n"
54*de1e4e89SAndroid Build Coastguard Worker 		);
55*de1e4e89SAndroid Build Coastguard Worker }
56*de1e4e89SAndroid Build Coastguard Worker 
usage(void)57*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
58*de1e4e89SAndroid Build Coastguard Worker {
59*de1e4e89SAndroid Build Coastguard Worker 	print_usage(stderr);
60*de1e4e89SAndroid Build Coastguard Worker }
61*de1e4e89SAndroid Build Coastguard Worker 
get_float(float * val,const char * arg)62*de1e4e89SAndroid Build Coastguard Worker static int get_float(float *val, const char *arg)
63*de1e4e89SAndroid Build Coastguard Worker {
64*de1e4e89SAndroid Build Coastguard Worker 	float res;
65*de1e4e89SAndroid Build Coastguard Worker 	char *ptr;
66*de1e4e89SAndroid Build Coastguard Worker 
67*de1e4e89SAndroid Build Coastguard Worker 	if (!arg || !*arg)
68*de1e4e89SAndroid Build Coastguard Worker 		return -1;
69*de1e4e89SAndroid Build Coastguard Worker 	res = strtof(arg, &ptr);
70*de1e4e89SAndroid Build Coastguard Worker 	if (!ptr || ptr == arg || *ptr)
71*de1e4e89SAndroid Build Coastguard Worker 		return -1;
72*de1e4e89SAndroid Build Coastguard Worker 	*val = res;
73*de1e4e89SAndroid Build Coastguard Worker 	return 0;
74*de1e4e89SAndroid Build Coastguard Worker }
75*de1e4e89SAndroid Build Coastguard Worker 
set_ctrlmode(char * name,char * arg,struct can_ctrlmode * cm,__u32 flags)76*de1e4e89SAndroid Build Coastguard Worker static void set_ctrlmode(char *name, char *arg,
77*de1e4e89SAndroid Build Coastguard Worker 			 struct can_ctrlmode *cm, __u32 flags)
78*de1e4e89SAndroid Build Coastguard Worker {
79*de1e4e89SAndroid Build Coastguard Worker 	if (strcmp(arg, "on") == 0) {
80*de1e4e89SAndroid Build Coastguard Worker 		cm->flags |= flags;
81*de1e4e89SAndroid Build Coastguard Worker 	} else if (strcmp(arg, "off") != 0) {
82*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr,
83*de1e4e89SAndroid Build Coastguard Worker 			"Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n",
84*de1e4e89SAndroid Build Coastguard Worker 			name, arg);
85*de1e4e89SAndroid Build Coastguard Worker 		exit(-1);
86*de1e4e89SAndroid Build Coastguard Worker 	}
87*de1e4e89SAndroid Build Coastguard Worker 	cm->mask |= flags;
88*de1e4e89SAndroid Build Coastguard Worker }
89*de1e4e89SAndroid Build Coastguard Worker 
print_ctrlmode(FILE * f,__u32 cm)90*de1e4e89SAndroid Build Coastguard Worker static void print_ctrlmode(FILE *f, __u32 cm)
91*de1e4e89SAndroid Build Coastguard Worker {
92*de1e4e89SAndroid Build Coastguard Worker 	open_json_array(PRINT_ANY, is_json_context() ? "ctrlmode" : "<");
93*de1e4e89SAndroid Build Coastguard Worker #define _PF(cmflag, cmname)						\
94*de1e4e89SAndroid Build Coastguard Worker 	if (cm & cmflag) {						\
95*de1e4e89SAndroid Build Coastguard Worker 		cm &= ~cmflag;						\
96*de1e4e89SAndroid Build Coastguard Worker 		print_string(PRINT_ANY, NULL, cm ? "%s," : "%s", cmname); \
97*de1e4e89SAndroid Build Coastguard Worker 	}
98*de1e4e89SAndroid Build Coastguard Worker 	_PF(CAN_CTRLMODE_LOOPBACK, "LOOPBACK");
99*de1e4e89SAndroid Build Coastguard Worker 	_PF(CAN_CTRLMODE_LISTENONLY, "LISTEN-ONLY");
100*de1e4e89SAndroid Build Coastguard Worker 	_PF(CAN_CTRLMODE_3_SAMPLES, "TRIPLE-SAMPLING");
101*de1e4e89SAndroid Build Coastguard Worker 	_PF(CAN_CTRLMODE_ONE_SHOT, "ONE-SHOT");
102*de1e4e89SAndroid Build Coastguard Worker 	_PF(CAN_CTRLMODE_BERR_REPORTING, "BERR-REPORTING");
103*de1e4e89SAndroid Build Coastguard Worker 	_PF(CAN_CTRLMODE_FD, "FD");
104*de1e4e89SAndroid Build Coastguard Worker 	_PF(CAN_CTRLMODE_FD_NON_ISO, "FD-NON-ISO");
105*de1e4e89SAndroid Build Coastguard Worker 	_PF(CAN_CTRLMODE_PRESUME_ACK, "PRESUME-ACK");
106*de1e4e89SAndroid Build Coastguard Worker #undef _PF
107*de1e4e89SAndroid Build Coastguard Worker 	if (cm)
108*de1e4e89SAndroid Build Coastguard Worker 		print_hex(PRINT_ANY, NULL, "%x", cm);
109*de1e4e89SAndroid Build Coastguard Worker 	close_json_array(PRINT_ANY, "> ");
110*de1e4e89SAndroid Build Coastguard Worker }
111*de1e4e89SAndroid Build Coastguard Worker 
can_parse_opt(struct link_util * lu,int argc,char ** argv,struct nlmsghdr * n)112*de1e4e89SAndroid Build Coastguard Worker static int can_parse_opt(struct link_util *lu, int argc, char **argv,
113*de1e4e89SAndroid Build Coastguard Worker 			 struct nlmsghdr *n)
114*de1e4e89SAndroid Build Coastguard Worker {
115*de1e4e89SAndroid Build Coastguard Worker 	struct can_bittiming bt = {}, dbt = {};
116*de1e4e89SAndroid Build Coastguard Worker 	struct can_ctrlmode cm = {0, 0};
117*de1e4e89SAndroid Build Coastguard Worker 
118*de1e4e89SAndroid Build Coastguard Worker 	while (argc > 0) {
119*de1e4e89SAndroid Build Coastguard Worker 		if (matches(*argv, "bitrate") == 0) {
120*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
121*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&bt.bitrate, *argv, 0))
122*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"bitrate\" value\n", *argv);
123*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "sample-point") == 0) {
124*de1e4e89SAndroid Build Coastguard Worker 			float sp;
125*de1e4e89SAndroid Build Coastguard Worker 
126*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
127*de1e4e89SAndroid Build Coastguard Worker 			if (get_float(&sp, *argv))
128*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"sample-point\" value\n",
129*de1e4e89SAndroid Build Coastguard Worker 				       *argv);
130*de1e4e89SAndroid Build Coastguard Worker 			bt.sample_point = (__u32)(sp * 1000);
131*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "tq") == 0) {
132*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
133*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&bt.tq, *argv, 0))
134*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"tq\" value\n", *argv);
135*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "prop-seg") == 0) {
136*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
137*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&bt.prop_seg, *argv, 0))
138*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"prop-seg\" value\n", *argv);
139*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "phase-seg1") == 0) {
140*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
141*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&bt.phase_seg1, *argv, 0))
142*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"phase-seg1\" value\n", *argv);
143*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "phase-seg2") == 0) {
144*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
145*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&bt.phase_seg2, *argv, 0))
146*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"phase-seg2\" value\n", *argv);
147*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "sjw") == 0) {
148*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
149*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&bt.sjw, *argv, 0))
150*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"sjw\" value\n", *argv);
151*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "dbitrate") == 0) {
152*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
153*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&dbt.bitrate, *argv, 0))
154*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"dbitrate\" value\n", *argv);
155*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "dsample-point") == 0) {
156*de1e4e89SAndroid Build Coastguard Worker 			float sp;
157*de1e4e89SAndroid Build Coastguard Worker 
158*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
159*de1e4e89SAndroid Build Coastguard Worker 			if (get_float(&sp, *argv))
160*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"dsample-point\" value\n", *argv);
161*de1e4e89SAndroid Build Coastguard Worker 			dbt.sample_point = (__u32)(sp * 1000);
162*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "dtq") == 0) {
163*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
164*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&dbt.tq, *argv, 0))
165*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"dtq\" value\n", *argv);
166*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "dprop-seg") == 0) {
167*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
168*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&dbt.prop_seg, *argv, 0))
169*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"dprop-seg\" value\n", *argv);
170*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "dphase-seg1") == 0) {
171*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
172*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&dbt.phase_seg1, *argv, 0))
173*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"dphase-seg1\" value\n", *argv);
174*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "dphase-seg2") == 0) {
175*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
176*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&dbt.phase_seg2, *argv, 0))
177*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"dphase-seg2\" value\n", *argv);
178*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "dsjw") == 0) {
179*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
180*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&dbt.sjw, *argv, 0))
181*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"dsjw\" value\n", *argv);
182*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "loopback") == 0) {
183*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
184*de1e4e89SAndroid Build Coastguard Worker 			set_ctrlmode("loopback", *argv, &cm,
185*de1e4e89SAndroid Build Coastguard Worker 				     CAN_CTRLMODE_LOOPBACK);
186*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "listen-only") == 0) {
187*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
188*de1e4e89SAndroid Build Coastguard Worker 			set_ctrlmode("listen-only", *argv, &cm,
189*de1e4e89SAndroid Build Coastguard Worker 				     CAN_CTRLMODE_LISTENONLY);
190*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "triple-sampling") == 0) {
191*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
192*de1e4e89SAndroid Build Coastguard Worker 			set_ctrlmode("triple-sampling", *argv, &cm,
193*de1e4e89SAndroid Build Coastguard Worker 				     CAN_CTRLMODE_3_SAMPLES);
194*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "one-shot") == 0) {
195*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
196*de1e4e89SAndroid Build Coastguard Worker 			set_ctrlmode("one-shot", *argv, &cm,
197*de1e4e89SAndroid Build Coastguard Worker 				     CAN_CTRLMODE_ONE_SHOT);
198*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "berr-reporting") == 0) {
199*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
200*de1e4e89SAndroid Build Coastguard Worker 			set_ctrlmode("berr-reporting", *argv, &cm,
201*de1e4e89SAndroid Build Coastguard Worker 				     CAN_CTRLMODE_BERR_REPORTING);
202*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "fd") == 0) {
203*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
204*de1e4e89SAndroid Build Coastguard Worker 			set_ctrlmode("fd", *argv, &cm,
205*de1e4e89SAndroid Build Coastguard Worker 				     CAN_CTRLMODE_FD);
206*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "fd-non-iso") == 0) {
207*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
208*de1e4e89SAndroid Build Coastguard Worker 			set_ctrlmode("fd-non-iso", *argv, &cm,
209*de1e4e89SAndroid Build Coastguard Worker 				     CAN_CTRLMODE_FD_NON_ISO);
210*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "presume-ack") == 0) {
211*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
212*de1e4e89SAndroid Build Coastguard Worker 			set_ctrlmode("presume-ack", *argv, &cm,
213*de1e4e89SAndroid Build Coastguard Worker 				     CAN_CTRLMODE_PRESUME_ACK);
214*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "restart") == 0) {
215*de1e4e89SAndroid Build Coastguard Worker 			__u32 val = 1;
216*de1e4e89SAndroid Build Coastguard Worker 
217*de1e4e89SAndroid Build Coastguard Worker 			addattr32(n, 1024, IFLA_CAN_RESTART, val);
218*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "restart-ms") == 0) {
219*de1e4e89SAndroid Build Coastguard Worker 			__u32 val;
220*de1e4e89SAndroid Build Coastguard Worker 
221*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
222*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&val, *argv, 0))
223*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"restart-ms\" value\n", *argv);
224*de1e4e89SAndroid Build Coastguard Worker 			addattr32(n, 1024, IFLA_CAN_RESTART_MS, val);
225*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "termination") == 0) {
226*de1e4e89SAndroid Build Coastguard Worker 			__u16 val;
227*de1e4e89SAndroid Build Coastguard Worker 
228*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
229*de1e4e89SAndroid Build Coastguard Worker 			if (get_u16(&val, *argv, 0))
230*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid \"termination\" value\n",
231*de1e4e89SAndroid Build Coastguard Worker 				       *argv);
232*de1e4e89SAndroid Build Coastguard Worker 			addattr16(n, 1024, IFLA_CAN_TERMINATION, val);
233*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "help") == 0) {
234*de1e4e89SAndroid Build Coastguard Worker 			usage();
235*de1e4e89SAndroid Build Coastguard Worker 			return -1;
236*de1e4e89SAndroid Build Coastguard Worker 		} else {
237*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "can: unknown option \"%s\"\n", *argv);
238*de1e4e89SAndroid Build Coastguard Worker 			usage();
239*de1e4e89SAndroid Build Coastguard Worker 			return -1;
240*de1e4e89SAndroid Build Coastguard Worker 		}
241*de1e4e89SAndroid Build Coastguard Worker 		argc--, argv++;
242*de1e4e89SAndroid Build Coastguard Worker 	}
243*de1e4e89SAndroid Build Coastguard Worker 
244*de1e4e89SAndroid Build Coastguard Worker 	if (bt.bitrate || bt.tq)
245*de1e4e89SAndroid Build Coastguard Worker 		addattr_l(n, 1024, IFLA_CAN_BITTIMING, &bt, sizeof(bt));
246*de1e4e89SAndroid Build Coastguard Worker 	if (dbt.bitrate || dbt.tq)
247*de1e4e89SAndroid Build Coastguard Worker 		addattr_l(n, 1024, IFLA_CAN_DATA_BITTIMING, &dbt, sizeof(dbt));
248*de1e4e89SAndroid Build Coastguard Worker 	if (cm.mask)
249*de1e4e89SAndroid Build Coastguard Worker 		addattr_l(n, 1024, IFLA_CAN_CTRLMODE, &cm, sizeof(cm));
250*de1e4e89SAndroid Build Coastguard Worker 
251*de1e4e89SAndroid Build Coastguard Worker 	return 0;
252*de1e4e89SAndroid Build Coastguard Worker }
253*de1e4e89SAndroid Build Coastguard Worker 
254*de1e4e89SAndroid Build Coastguard Worker static const char *can_state_names[CAN_STATE_MAX] = {
255*de1e4e89SAndroid Build Coastguard Worker 	[CAN_STATE_ERROR_ACTIVE] = "ERROR-ACTIVE",
256*de1e4e89SAndroid Build Coastguard Worker 	[CAN_STATE_ERROR_WARNING] = "ERROR-WARNING",
257*de1e4e89SAndroid Build Coastguard Worker 	[CAN_STATE_ERROR_PASSIVE] = "ERROR-PASSIVE",
258*de1e4e89SAndroid Build Coastguard Worker 	[CAN_STATE_BUS_OFF] = "BUS-OFF",
259*de1e4e89SAndroid Build Coastguard Worker 	[CAN_STATE_STOPPED] = "STOPPED",
260*de1e4e89SAndroid Build Coastguard Worker 	[CAN_STATE_SLEEPING] = "SLEEPING"
261*de1e4e89SAndroid Build Coastguard Worker };
262*de1e4e89SAndroid Build Coastguard Worker 
can_print_json_timing_min_max(const char * attr,int min,int max)263*de1e4e89SAndroid Build Coastguard Worker static void can_print_json_timing_min_max(const char *attr, int min, int max)
264*de1e4e89SAndroid Build Coastguard Worker {
265*de1e4e89SAndroid Build Coastguard Worker 	open_json_object(attr);
266*de1e4e89SAndroid Build Coastguard Worker 	print_int(PRINT_JSON, "min", NULL, min);
267*de1e4e89SAndroid Build Coastguard Worker 	print_int(PRINT_JSON, "max", NULL, max);
268*de1e4e89SAndroid Build Coastguard Worker 	close_json_object();
269*de1e4e89SAndroid Build Coastguard Worker }
270*de1e4e89SAndroid Build Coastguard Worker 
can_print_opt(struct link_util * lu,FILE * f,struct rtattr * tb[])271*de1e4e89SAndroid Build Coastguard Worker static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
272*de1e4e89SAndroid Build Coastguard Worker {
273*de1e4e89SAndroid Build Coastguard Worker 	if (!tb)
274*de1e4e89SAndroid Build Coastguard Worker 		return;
275*de1e4e89SAndroid Build Coastguard Worker 
276*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_CAN_CTRLMODE]) {
277*de1e4e89SAndroid Build Coastguard Worker 		struct can_ctrlmode *cm = RTA_DATA(tb[IFLA_CAN_CTRLMODE]);
278*de1e4e89SAndroid Build Coastguard Worker 
279*de1e4e89SAndroid Build Coastguard Worker 		if (cm->flags)
280*de1e4e89SAndroid Build Coastguard Worker 			print_ctrlmode(f, cm->flags);
281*de1e4e89SAndroid Build Coastguard Worker 	}
282*de1e4e89SAndroid Build Coastguard Worker 
283*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_CAN_STATE]) {
284*de1e4e89SAndroid Build Coastguard Worker 		uint32_t state = rta_getattr_u32(tb[IFLA_CAN_STATE]);
285*de1e4e89SAndroid Build Coastguard Worker 
286*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "state %s ", state < CAN_STATE_MAX ?
287*de1e4e89SAndroid Build Coastguard Worker 			can_state_names[state] : "UNKNOWN");
288*de1e4e89SAndroid Build Coastguard Worker 	}
289*de1e4e89SAndroid Build Coastguard Worker 
290*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_CAN_BERR_COUNTER]) {
291*de1e4e89SAndroid Build Coastguard Worker 		struct can_berr_counter *bc =
292*de1e4e89SAndroid Build Coastguard Worker 			RTA_DATA(tb[IFLA_CAN_BERR_COUNTER]);
293*de1e4e89SAndroid Build Coastguard Worker 
294*de1e4e89SAndroid Build Coastguard Worker 		if (is_json_context()) {
295*de1e4e89SAndroid Build Coastguard Worker 			open_json_object("berr_counter");
296*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "tx", NULL, bc->txerr);
297*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "rx", NULL, bc->rxerr);
298*de1e4e89SAndroid Build Coastguard Worker 			close_json_object();
299*de1e4e89SAndroid Build Coastguard Worker 		} else {
300*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "(berr-counter tx %d rx %d) ",
301*de1e4e89SAndroid Build Coastguard Worker 				bc->txerr, bc->rxerr);
302*de1e4e89SAndroid Build Coastguard Worker 		}
303*de1e4e89SAndroid Build Coastguard Worker 	}
304*de1e4e89SAndroid Build Coastguard Worker 
305*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_CAN_RESTART_MS]) {
306*de1e4e89SAndroid Build Coastguard Worker 		__u32 *restart_ms = RTA_DATA(tb[IFLA_CAN_RESTART_MS]);
307*de1e4e89SAndroid Build Coastguard Worker 
308*de1e4e89SAndroid Build Coastguard Worker 		print_int(PRINT_ANY,
309*de1e4e89SAndroid Build Coastguard Worker 			  "restart_ms",
310*de1e4e89SAndroid Build Coastguard Worker 			  "restart-ms %d ",
311*de1e4e89SAndroid Build Coastguard Worker 			  *restart_ms);
312*de1e4e89SAndroid Build Coastguard Worker 	}
313*de1e4e89SAndroid Build Coastguard Worker 
314*de1e4e89SAndroid Build Coastguard Worker 	/* bittiming is irrelevant if fixed bitrate is defined */
315*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_CAN_BITTIMING] && !tb[IFLA_CAN_BITRATE_CONST]) {
316*de1e4e89SAndroid Build Coastguard Worker 		struct can_bittiming *bt = RTA_DATA(tb[IFLA_CAN_BITTIMING]);
317*de1e4e89SAndroid Build Coastguard Worker 
318*de1e4e89SAndroid Build Coastguard Worker 		if (is_json_context()) {
319*de1e4e89SAndroid Build Coastguard Worker 			open_json_object("bittiming");
320*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate);
321*de1e4e89SAndroid Build Coastguard Worker 			jsonw_float_field_fmt(get_json_writer(),
322*de1e4e89SAndroid Build Coastguard Worker 					      "sample_point", "%.3f",
323*de1e4e89SAndroid Build Coastguard Worker 					      (float) bt->sample_point / 1000.);
324*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_ANY, "tq", NULL, bt->tq);
325*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_ANY, "prop_seg", NULL, bt->prop_seg);
326*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_ANY, "phase_seg1",
327*de1e4e89SAndroid Build Coastguard Worker 				  NULL, bt->phase_seg1);
328*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_ANY, "phase_seg2",
329*de1e4e89SAndroid Build Coastguard Worker 				  NULL, bt->phase_seg2);
330*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_ANY, "sjw", NULL, bt->sjw);
331*de1e4e89SAndroid Build Coastguard Worker 			close_json_object();
332*de1e4e89SAndroid Build Coastguard Worker 		} else {
333*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n	  bitrate %d sample-point %.3f ",
334*de1e4e89SAndroid Build Coastguard Worker 				bt->bitrate, (float) bt->sample_point / 1000.);
335*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f,
336*de1e4e89SAndroid Build Coastguard Worker 				"\n	  tq %d prop-seg %d phase-seg1 %d phase-seg2 %d sjw %d",
337*de1e4e89SAndroid Build Coastguard Worker 				bt->tq, bt->prop_seg,
338*de1e4e89SAndroid Build Coastguard Worker 				bt->phase_seg1, bt->phase_seg2,
339*de1e4e89SAndroid Build Coastguard Worker 				bt->sjw);
340*de1e4e89SAndroid Build Coastguard Worker 		}
341*de1e4e89SAndroid Build Coastguard Worker 	}
342*de1e4e89SAndroid Build Coastguard Worker 
343*de1e4e89SAndroid Build Coastguard Worker 	/* bittiming const is irrelevant if fixed bitrate is defined */
344*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_CAN_BITTIMING_CONST] && !tb[IFLA_CAN_BITRATE_CONST]) {
345*de1e4e89SAndroid Build Coastguard Worker 		struct can_bittiming_const *btc =
346*de1e4e89SAndroid Build Coastguard Worker 			RTA_DATA(tb[IFLA_CAN_BITTIMING_CONST]);
347*de1e4e89SAndroid Build Coastguard Worker 
348*de1e4e89SAndroid Build Coastguard Worker 		if (is_json_context()) {
349*de1e4e89SAndroid Build Coastguard Worker 			open_json_object("bittiming_const");
350*de1e4e89SAndroid Build Coastguard Worker 			print_string(PRINT_JSON, "name", NULL, btc->name);
351*de1e4e89SAndroid Build Coastguard Worker 			can_print_json_timing_min_max("tseg1",
352*de1e4e89SAndroid Build Coastguard Worker 						      btc->tseg1_min,
353*de1e4e89SAndroid Build Coastguard Worker 						      btc->tseg1_max);
354*de1e4e89SAndroid Build Coastguard Worker 			can_print_json_timing_min_max("tseg2",
355*de1e4e89SAndroid Build Coastguard Worker 						      btc->tseg2_min,
356*de1e4e89SAndroid Build Coastguard Worker 						      btc->tseg2_max);
357*de1e4e89SAndroid Build Coastguard Worker 			can_print_json_timing_min_max("sjw", 1, btc->sjw_max);
358*de1e4e89SAndroid Build Coastguard Worker 			can_print_json_timing_min_max("brp",
359*de1e4e89SAndroid Build Coastguard Worker 						      btc->brp_min,
360*de1e4e89SAndroid Build Coastguard Worker 						      btc->brp_max);
361*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "brp_inc", NULL, btc->brp_inc);
362*de1e4e89SAndroid Build Coastguard Worker 			close_json_object();
363*de1e4e89SAndroid Build Coastguard Worker 		} else {
364*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n	  %s: tseg1 %d..%d tseg2 %d..%d "
365*de1e4e89SAndroid Build Coastguard Worker 				"sjw 1..%d brp %d..%d brp-inc %d",
366*de1e4e89SAndroid Build Coastguard Worker 				btc->name, btc->tseg1_min, btc->tseg1_max,
367*de1e4e89SAndroid Build Coastguard Worker 				btc->tseg2_min, btc->tseg2_max, btc->sjw_max,
368*de1e4e89SAndroid Build Coastguard Worker 				btc->brp_min, btc->brp_max, btc->brp_inc);
369*de1e4e89SAndroid Build Coastguard Worker 		}
370*de1e4e89SAndroid Build Coastguard Worker 	}
371*de1e4e89SAndroid Build Coastguard Worker 
372*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_CAN_BITRATE_CONST]) {
373*de1e4e89SAndroid Build Coastguard Worker 		__u32 *bitrate_const = RTA_DATA(tb[IFLA_CAN_BITRATE_CONST]);
374*de1e4e89SAndroid Build Coastguard Worker 		int bitrate_cnt = RTA_PAYLOAD(tb[IFLA_CAN_BITRATE_CONST]) /
375*de1e4e89SAndroid Build Coastguard Worker 			sizeof(*bitrate_const);
376*de1e4e89SAndroid Build Coastguard Worker 		int i;
377*de1e4e89SAndroid Build Coastguard Worker 		__u32 bitrate = 0;
378*de1e4e89SAndroid Build Coastguard Worker 
379*de1e4e89SAndroid Build Coastguard Worker 		if (tb[IFLA_CAN_BITTIMING]) {
380*de1e4e89SAndroid Build Coastguard Worker 			struct can_bittiming *bt =
381*de1e4e89SAndroid Build Coastguard Worker 				RTA_DATA(tb[IFLA_CAN_BITTIMING]);
382*de1e4e89SAndroid Build Coastguard Worker 			bitrate = bt->bitrate;
383*de1e4e89SAndroid Build Coastguard Worker 		}
384*de1e4e89SAndroid Build Coastguard Worker 
385*de1e4e89SAndroid Build Coastguard Worker 		if (is_json_context()) {
386*de1e4e89SAndroid Build Coastguard Worker 			print_uint(PRINT_JSON,
387*de1e4e89SAndroid Build Coastguard Worker 				   "bittiming_bitrate",
388*de1e4e89SAndroid Build Coastguard Worker 				   NULL, bitrate);
389*de1e4e89SAndroid Build Coastguard Worker 			open_json_array(PRINT_JSON, "bitrate_const");
390*de1e4e89SAndroid Build Coastguard Worker 			for (i = 0; i < bitrate_cnt; ++i)
391*de1e4e89SAndroid Build Coastguard Worker 				print_uint(PRINT_JSON, NULL, NULL,
392*de1e4e89SAndroid Build Coastguard Worker 					   bitrate_const[i]);
393*de1e4e89SAndroid Build Coastguard Worker 			close_json_array(PRINT_JSON, NULL);
394*de1e4e89SAndroid Build Coastguard Worker 		} else {
395*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n	  bitrate %u", bitrate);
396*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n	     [");
397*de1e4e89SAndroid Build Coastguard Worker 
398*de1e4e89SAndroid Build Coastguard Worker 			for (i = 0; i < bitrate_cnt - 1; ++i) {
399*de1e4e89SAndroid Build Coastguard Worker 				/* This will keep lines below 80 signs */
400*de1e4e89SAndroid Build Coastguard Worker 				if (!(i % 6) && i)
401*de1e4e89SAndroid Build Coastguard Worker 					fprintf(f, "\n	      ");
402*de1e4e89SAndroid Build Coastguard Worker 
403*de1e4e89SAndroid Build Coastguard Worker 				fprintf(f, "%8u, ", bitrate_const[i]);
404*de1e4e89SAndroid Build Coastguard Worker 			}
405*de1e4e89SAndroid Build Coastguard Worker 
406*de1e4e89SAndroid Build Coastguard Worker 			if (!(i % 6) && i)
407*de1e4e89SAndroid Build Coastguard Worker 				fprintf(f, "\n	      ");
408*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "%8u ]", bitrate_const[i]);
409*de1e4e89SAndroid Build Coastguard Worker 		}
410*de1e4e89SAndroid Build Coastguard Worker 	}
411*de1e4e89SAndroid Build Coastguard Worker 
412*de1e4e89SAndroid Build Coastguard Worker 	/* data bittiming is irrelevant if fixed bitrate is defined */
413*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_CAN_DATA_BITTIMING] && !tb[IFLA_CAN_DATA_BITRATE_CONST]) {
414*de1e4e89SAndroid Build Coastguard Worker 		struct can_bittiming *dbt =
415*de1e4e89SAndroid Build Coastguard Worker 			RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
416*de1e4e89SAndroid Build Coastguard Worker 
417*de1e4e89SAndroid Build Coastguard Worker 		if (is_json_context()) {
418*de1e4e89SAndroid Build Coastguard Worker 			open_json_object("data_bittiming");
419*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "bitrate", NULL, dbt->bitrate);
420*de1e4e89SAndroid Build Coastguard Worker 			jsonw_float_field_fmt(get_json_writer(),
421*de1e4e89SAndroid Build Coastguard Worker 					      "sample_point",
422*de1e4e89SAndroid Build Coastguard Worker 					      "%.3f",
423*de1e4e89SAndroid Build Coastguard Worker 					      (float) dbt->sample_point / 1000.);
424*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "tq", NULL, dbt->tq);
425*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "prop_seg", NULL, dbt->prop_seg);
426*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "phase_seg1",
427*de1e4e89SAndroid Build Coastguard Worker 				  NULL, dbt->phase_seg1);
428*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "phase_seg2",
429*de1e4e89SAndroid Build Coastguard Worker 				  NULL, dbt->phase_seg2);
430*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "sjw", NULL, dbt->sjw);
431*de1e4e89SAndroid Build Coastguard Worker 			close_json_object();
432*de1e4e89SAndroid Build Coastguard Worker 		} else {
433*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n	  dbitrate %d dsample-point %.3f ",
434*de1e4e89SAndroid Build Coastguard Worker 				dbt->bitrate,
435*de1e4e89SAndroid Build Coastguard Worker 				(float) dbt->sample_point / 1000.);
436*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n	  dtq %d dprop-seg %d dphase-seg1 %d "
437*de1e4e89SAndroid Build Coastguard Worker 				"dphase-seg2 %d dsjw %d",
438*de1e4e89SAndroid Build Coastguard Worker 				dbt->tq, dbt->prop_seg, dbt->phase_seg1,
439*de1e4e89SAndroid Build Coastguard Worker 				dbt->phase_seg2, dbt->sjw);
440*de1e4e89SAndroid Build Coastguard Worker 		}
441*de1e4e89SAndroid Build Coastguard Worker 	}
442*de1e4e89SAndroid Build Coastguard Worker 
443*de1e4e89SAndroid Build Coastguard Worker 	/* data bittiming const is irrelevant if fixed bitrate is defined */
444*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_CAN_DATA_BITTIMING_CONST] &&
445*de1e4e89SAndroid Build Coastguard Worker 	    !tb[IFLA_CAN_DATA_BITRATE_CONST]) {
446*de1e4e89SAndroid Build Coastguard Worker 		struct can_bittiming_const *dbtc =
447*de1e4e89SAndroid Build Coastguard Worker 			RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING_CONST]);
448*de1e4e89SAndroid Build Coastguard Worker 
449*de1e4e89SAndroid Build Coastguard Worker 		if (is_json_context()) {
450*de1e4e89SAndroid Build Coastguard Worker 			open_json_object("data_bittiming_const");
451*de1e4e89SAndroid Build Coastguard Worker 			print_string(PRINT_JSON, "name", NULL, dbtc->name);
452*de1e4e89SAndroid Build Coastguard Worker 			can_print_json_timing_min_max("tseg1",
453*de1e4e89SAndroid Build Coastguard Worker 						      dbtc->tseg1_min,
454*de1e4e89SAndroid Build Coastguard Worker 						      dbtc->tseg1_max);
455*de1e4e89SAndroid Build Coastguard Worker 			can_print_json_timing_min_max("tseg2",
456*de1e4e89SAndroid Build Coastguard Worker 						      dbtc->tseg2_min,
457*de1e4e89SAndroid Build Coastguard Worker 						      dbtc->tseg2_max);
458*de1e4e89SAndroid Build Coastguard Worker 			can_print_json_timing_min_max("sjw", 1, dbtc->sjw_max);
459*de1e4e89SAndroid Build Coastguard Worker 			can_print_json_timing_min_max("brp",
460*de1e4e89SAndroid Build Coastguard Worker 						      dbtc->brp_min,
461*de1e4e89SAndroid Build Coastguard Worker 						      dbtc->brp_max);
462*de1e4e89SAndroid Build Coastguard Worker 
463*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "brp_inc", NULL, dbtc->brp_inc);
464*de1e4e89SAndroid Build Coastguard Worker 			close_json_object();
465*de1e4e89SAndroid Build Coastguard Worker 		} else {
466*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n	  %s: dtseg1 %d..%d dtseg2 %d..%d "
467*de1e4e89SAndroid Build Coastguard Worker 				"dsjw 1..%d dbrp %d..%d dbrp-inc %d",
468*de1e4e89SAndroid Build Coastguard Worker 				dbtc->name, dbtc->tseg1_min, dbtc->tseg1_max,
469*de1e4e89SAndroid Build Coastguard Worker 				dbtc->tseg2_min, dbtc->tseg2_max, dbtc->sjw_max,
470*de1e4e89SAndroid Build Coastguard Worker 				dbtc->brp_min, dbtc->brp_max, dbtc->brp_inc);
471*de1e4e89SAndroid Build Coastguard Worker 		}
472*de1e4e89SAndroid Build Coastguard Worker 	}
473*de1e4e89SAndroid Build Coastguard Worker 
474*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_CAN_DATA_BITRATE_CONST]) {
475*de1e4e89SAndroid Build Coastguard Worker 		__u32 *dbitrate_const =
476*de1e4e89SAndroid Build Coastguard Worker 			RTA_DATA(tb[IFLA_CAN_DATA_BITRATE_CONST]);
477*de1e4e89SAndroid Build Coastguard Worker 		int dbitrate_cnt =
478*de1e4e89SAndroid Build Coastguard Worker 			RTA_PAYLOAD(tb[IFLA_CAN_DATA_BITRATE_CONST]) /
479*de1e4e89SAndroid Build Coastguard Worker 			sizeof(*dbitrate_const);
480*de1e4e89SAndroid Build Coastguard Worker 		int i;
481*de1e4e89SAndroid Build Coastguard Worker 		__u32 dbitrate = 0;
482*de1e4e89SAndroid Build Coastguard Worker 
483*de1e4e89SAndroid Build Coastguard Worker 		if (tb[IFLA_CAN_DATA_BITTIMING]) {
484*de1e4e89SAndroid Build Coastguard Worker 			struct can_bittiming *dbt =
485*de1e4e89SAndroid Build Coastguard Worker 				RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
486*de1e4e89SAndroid Build Coastguard Worker 			dbitrate = dbt->bitrate;
487*de1e4e89SAndroid Build Coastguard Worker 		}
488*de1e4e89SAndroid Build Coastguard Worker 
489*de1e4e89SAndroid Build Coastguard Worker 		if (is_json_context()) {
490*de1e4e89SAndroid Build Coastguard Worker 			print_uint(PRINT_JSON, "data_bittiming_bitrate",
491*de1e4e89SAndroid Build Coastguard Worker 				   NULL, dbitrate);
492*de1e4e89SAndroid Build Coastguard Worker 			open_json_array(PRINT_JSON, "data_bitrate_const");
493*de1e4e89SAndroid Build Coastguard Worker 			for (i = 0; i < dbitrate_cnt; ++i)
494*de1e4e89SAndroid Build Coastguard Worker 				print_uint(PRINT_JSON, NULL, NULL,
495*de1e4e89SAndroid Build Coastguard Worker 					   dbitrate_const[i]);
496*de1e4e89SAndroid Build Coastguard Worker 			close_json_array(PRINT_JSON, NULL);
497*de1e4e89SAndroid Build Coastguard Worker 		} else {
498*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n	  dbitrate %u", dbitrate);
499*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n	     [");
500*de1e4e89SAndroid Build Coastguard Worker 
501*de1e4e89SAndroid Build Coastguard Worker 			for (i = 0; i < dbitrate_cnt - 1; ++i) {
502*de1e4e89SAndroid Build Coastguard Worker 				/* This will keep lines below 80 signs */
503*de1e4e89SAndroid Build Coastguard Worker 				if (!(i % 6) && i)
504*de1e4e89SAndroid Build Coastguard Worker 					fprintf(f, "\n	      ");
505*de1e4e89SAndroid Build Coastguard Worker 
506*de1e4e89SAndroid Build Coastguard Worker 				fprintf(f, "%8u, ", dbitrate_const[i]);
507*de1e4e89SAndroid Build Coastguard Worker 			}
508*de1e4e89SAndroid Build Coastguard Worker 
509*de1e4e89SAndroid Build Coastguard Worker 			if (!(i % 6) && i)
510*de1e4e89SAndroid Build Coastguard Worker 				fprintf(f, "\n	      ");
511*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "%8u ]", dbitrate_const[i]);
512*de1e4e89SAndroid Build Coastguard Worker 		}
513*de1e4e89SAndroid Build Coastguard Worker 	}
514*de1e4e89SAndroid Build Coastguard Worker 
515*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_CAN_TERMINATION_CONST] && tb[IFLA_CAN_TERMINATION]) {
516*de1e4e89SAndroid Build Coastguard Worker 		__u16 *trm = RTA_DATA(tb[IFLA_CAN_TERMINATION]);
517*de1e4e89SAndroid Build Coastguard Worker 		__u16 *trm_const = RTA_DATA(tb[IFLA_CAN_TERMINATION_CONST]);
518*de1e4e89SAndroid Build Coastguard Worker 		int trm_cnt = RTA_PAYLOAD(tb[IFLA_CAN_TERMINATION_CONST]) /
519*de1e4e89SAndroid Build Coastguard Worker 			sizeof(*trm_const);
520*de1e4e89SAndroid Build Coastguard Worker 		int i;
521*de1e4e89SAndroid Build Coastguard Worker 
522*de1e4e89SAndroid Build Coastguard Worker 		if (is_json_context()) {
523*de1e4e89SAndroid Build Coastguard Worker 			print_hu(PRINT_JSON, "termination", NULL, *trm);
524*de1e4e89SAndroid Build Coastguard Worker 			open_json_array(PRINT_JSON, "termination_const");
525*de1e4e89SAndroid Build Coastguard Worker 			for (i = 0; i < trm_cnt; ++i)
526*de1e4e89SAndroid Build Coastguard Worker 				print_hu(PRINT_JSON, NULL, NULL, trm_const[i]);
527*de1e4e89SAndroid Build Coastguard Worker 			close_json_array(PRINT_JSON, NULL);
528*de1e4e89SAndroid Build Coastguard Worker 		} else {
529*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n	  termination %hu [ ", *trm);
530*de1e4e89SAndroid Build Coastguard Worker 
531*de1e4e89SAndroid Build Coastguard Worker 			for (i = 0; i < trm_cnt - 1; ++i)
532*de1e4e89SAndroid Build Coastguard Worker 				fprintf(f, "%hu, ", trm_const[i]);
533*de1e4e89SAndroid Build Coastguard Worker 
534*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "%hu ]", trm_const[i]);
535*de1e4e89SAndroid Build Coastguard Worker 		}
536*de1e4e89SAndroid Build Coastguard Worker 	}
537*de1e4e89SAndroid Build Coastguard Worker 
538*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_CAN_CLOCK]) {
539*de1e4e89SAndroid Build Coastguard Worker 		struct can_clock *clock = RTA_DATA(tb[IFLA_CAN_CLOCK]);
540*de1e4e89SAndroid Build Coastguard Worker 
541*de1e4e89SAndroid Build Coastguard Worker 		print_int(PRINT_ANY,
542*de1e4e89SAndroid Build Coastguard Worker 			  "clock",
543*de1e4e89SAndroid Build Coastguard Worker 			  "\n	  clock %d",
544*de1e4e89SAndroid Build Coastguard Worker 			  clock->freq);
545*de1e4e89SAndroid Build Coastguard Worker 	}
546*de1e4e89SAndroid Build Coastguard Worker 
547*de1e4e89SAndroid Build Coastguard Worker }
548*de1e4e89SAndroid Build Coastguard Worker 
can_print_xstats(struct link_util * lu,FILE * f,struct rtattr * xstats)549*de1e4e89SAndroid Build Coastguard Worker static void can_print_xstats(struct link_util *lu,
550*de1e4e89SAndroid Build Coastguard Worker 			     FILE *f, struct rtattr *xstats)
551*de1e4e89SAndroid Build Coastguard Worker {
552*de1e4e89SAndroid Build Coastguard Worker 	struct can_device_stats *stats;
553*de1e4e89SAndroid Build Coastguard Worker 
554*de1e4e89SAndroid Build Coastguard Worker 	if (xstats && RTA_PAYLOAD(xstats) == sizeof(*stats)) {
555*de1e4e89SAndroid Build Coastguard Worker 		stats = RTA_DATA(xstats);
556*de1e4e89SAndroid Build Coastguard Worker 
557*de1e4e89SAndroid Build Coastguard Worker 		if (is_json_context()) {
558*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "restarts",
559*de1e4e89SAndroid Build Coastguard Worker 				  NULL, stats->restarts);
560*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "bus_error",
561*de1e4e89SAndroid Build Coastguard Worker 				  NULL, stats->bus_error);
562*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "arbitration_lost",
563*de1e4e89SAndroid Build Coastguard Worker 				  NULL, stats->arbitration_lost);
564*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "error_warning",
565*de1e4e89SAndroid Build Coastguard Worker 				  NULL, stats->error_warning);
566*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "error_passive",
567*de1e4e89SAndroid Build Coastguard Worker 				  NULL, stats->error_passive);
568*de1e4e89SAndroid Build Coastguard Worker 			print_int(PRINT_JSON, "bus_off", NULL, stats->bus_off);
569*de1e4e89SAndroid Build Coastguard Worker 		} else {
570*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n	  re-started bus-errors arbit-lost "
571*de1e4e89SAndroid Build Coastguard Worker 				"error-warn error-pass bus-off");
572*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, "\n	  %-10d %-10d %-10d %-10d %-10d %-10d",
573*de1e4e89SAndroid Build Coastguard Worker 				stats->restarts, stats->bus_error,
574*de1e4e89SAndroid Build Coastguard Worker 				stats->arbitration_lost, stats->error_warning,
575*de1e4e89SAndroid Build Coastguard Worker 				stats->error_passive, stats->bus_off);
576*de1e4e89SAndroid Build Coastguard Worker 		}
577*de1e4e89SAndroid Build Coastguard Worker 	}
578*de1e4e89SAndroid Build Coastguard Worker }
579*de1e4e89SAndroid Build Coastguard Worker 
can_print_help(struct link_util * lu,int argc,char ** argv,FILE * f)580*de1e4e89SAndroid Build Coastguard Worker static void can_print_help(struct link_util *lu, int argc, char **argv,
581*de1e4e89SAndroid Build Coastguard Worker 			   FILE *f)
582*de1e4e89SAndroid Build Coastguard Worker {
583*de1e4e89SAndroid Build Coastguard Worker 	print_usage(f);
584*de1e4e89SAndroid Build Coastguard Worker }
585*de1e4e89SAndroid Build Coastguard Worker 
586*de1e4e89SAndroid Build Coastguard Worker struct link_util can_link_util = {
587*de1e4e89SAndroid Build Coastguard Worker 	.id		= "can",
588*de1e4e89SAndroid Build Coastguard Worker 	.maxattr	= IFLA_CAN_MAX,
589*de1e4e89SAndroid Build Coastguard Worker 	.parse_opt	= can_parse_opt,
590*de1e4e89SAndroid Build Coastguard Worker 	.print_opt	= can_print_opt,
591*de1e4e89SAndroid Build Coastguard Worker 	.print_xstats	= can_print_xstats,
592*de1e4e89SAndroid Build Coastguard Worker 	.print_help	= can_print_help,
593*de1e4e89SAndroid Build Coastguard Worker };
594