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