2 * iplink_can.c CAN device support
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Wolfgang Grandegger <wg@grandegger.com>
16 #include <linux/can/netlink.h>
20 #include "ip_common.h"
22 static void usage(void)
25 "Usage: ip link set DEVICE type can\n"
26 "\t[ bitrate BITRATE [ sample-point SAMPLE-POINT] ] | \n"
27 "\t[ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1\n "
28 "\t phase-seg2 PHASE-SEG2 [ sjw SJW ] ]\n"
30 "\t[ loopback { on | off } ]\n"
31 "\t[ listen-only { on | off } ]\n"
32 "\t[ triple-sampling { on | off } ]\n"
33 "\t[ one-shot { on | off } ]\n"
34 "\t[ berr-reporting { on | off } ]\n"
36 "\t[ restart-ms TIME-MS ]\n"
39 "\tWhere: BITRATE := { 1..1000000 }\n"
40 "\t SAMPLE-POINT := { 0.000..0.999 }\n"
41 "\t TQ := { NUMBER }\n"
42 "\t PROP-SEG := { 1..8 }\n"
43 "\t PHASE-SEG1 := { 1..8 }\n"
44 "\t PHASE-SEG2 := { 1..8 }\n"
45 "\t SJW := { 1..4 }\n"
46 "\t RESTART-MS := { 0 | NUMBER }\n"
50 static int get_float(float *val
, const char *arg
)
57 res
= strtof(arg
, &ptr
);
58 if (!ptr
|| ptr
== arg
|| *ptr
)
64 static void set_ctrlmode(char* name
, char *arg
,
65 struct can_ctrlmode
*cm
, __u32 flags
)
67 if (strcmp(arg
, "on") == 0) {
69 } else if (strcmp(arg
, "off") != 0) {
71 "Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n",
78 static void print_ctrlmode(FILE *f
, __u32 cm
)
81 #define _PF(cmflag, cmname) \
84 fprintf(f, "%s%s", cmname, cm ? "," : ""); \
86 _PF(CAN_CTRLMODE_LOOPBACK
, "LOOPBACK");
87 _PF(CAN_CTRLMODE_LISTENONLY
, "LISTEN-ONLY");
88 _PF(CAN_CTRLMODE_3_SAMPLES
, "TRIPLE-SAMPLING");
89 _PF(CAN_CTRLMODE_ONE_SHOT
, "ONE-SHOT");
90 _PF(CAN_CTRLMODE_BERR_REPORTING
, "BERR-REPORTING");
97 static int can_parse_opt(struct link_util
*lu
, int argc
, char **argv
,
100 struct can_bittiming bt
;
101 struct can_ctrlmode cm
= {0, 0};
103 memset(&bt
, 0, sizeof(bt
));
105 if (matches(*argv
, "bitrate") == 0) {
107 if (get_u32(&bt
.bitrate
, *argv
, 0))
108 invarg("invalid \"bitrate\" value\n", *argv
);
109 } else if (matches(*argv
, "sample-point") == 0) {
113 if (get_float(&sp
, *argv
))
114 invarg("invalid \"sample-point\" value\n",
116 bt
.sample_point
= (__u32
)(sp
* 1000);
117 } else if (matches(*argv
, "tq") == 0) {
119 if (get_u32(&bt
.tq
, *argv
, 0))
120 invarg("invalid \"tq\" value\n", *argv
);
121 } else if (matches(*argv
, "prop-seg") == 0) {
123 if (get_u32(&bt
.prop_seg
, *argv
, 0))
124 invarg("invalid \"prop-seg\" value\n", *argv
);
125 } else if (matches(*argv
, "phase-seg1") == 0) {
127 if (get_u32(&bt
.phase_seg1
, *argv
, 0))
128 invarg("invalid \"phase-seg1\" value\n", *argv
);
129 } else if (matches(*argv
, "phase-seg2") == 0) {
131 if (get_u32(&bt
.phase_seg2
, *argv
, 0))
132 invarg("invalid \"phase-seg2\" value\n", *argv
);
133 } else if (matches(*argv
, "sjw") == 0) {
135 if (get_u32(&bt
.sjw
, *argv
, 0))
136 invarg("invalid \"sjw\" value\n", *argv
);
137 } else if (matches(*argv
, "loopback") == 0) {
139 set_ctrlmode("loopback", *argv
, &cm
,
140 CAN_CTRLMODE_LOOPBACK
);
141 } else if (matches(*argv
, "listen-only") == 0) {
143 set_ctrlmode("listen-only", *argv
, &cm
,
144 CAN_CTRLMODE_LISTENONLY
);
145 } else if (matches(*argv
, "triple-sampling") == 0) {
147 set_ctrlmode("triple-sampling", *argv
, &cm
,
148 CAN_CTRLMODE_3_SAMPLES
);
149 } else if (matches(*argv
, "one-shot") == 0) {
151 set_ctrlmode("one-shot", *argv
, &cm
,
152 CAN_CTRLMODE_ONE_SHOT
);
153 } else if (matches(*argv
, "berr-reporting") == 0) {
155 set_ctrlmode("berr-reporting", *argv
, &cm
,
156 CAN_CTRLMODE_BERR_REPORTING
);
157 } else if (matches(*argv
, "restart") == 0) {
160 addattr32(n
, 1024, IFLA_CAN_RESTART
, val
);
161 } else if (matches(*argv
, "restart-ms") == 0) {
165 if (get_u32(&val
, *argv
, 0))
166 invarg("invalid \"restart-ms\" value\n", *argv
);
167 addattr32(n
, 1024, IFLA_CAN_RESTART_MS
, val
);
168 } else if (matches(*argv
, "help") == 0) {
172 fprintf(stderr
, "can: unknown option \"%s\"\n", *argv
);
179 if (bt
.bitrate
|| bt
.tq
)
180 addattr_l(n
, 1024, IFLA_CAN_BITTIMING
, &bt
, sizeof(bt
));
182 addattr_l(n
, 1024, IFLA_CAN_CTRLMODE
, &cm
, sizeof(cm
));
187 static const char *can_state_names
[] = {
188 [CAN_STATE_ERROR_ACTIVE
] = "ERROR-ACTIVE",
189 [CAN_STATE_ERROR_WARNING
] = "ERROR-WARNING",
190 [CAN_STATE_ERROR_PASSIVE
] = "ERROR-PASSIVE",
191 [CAN_STATE_BUS_OFF
] = "BUS-OFF",
192 [CAN_STATE_STOPPED
] = "STOPPED",
193 [CAN_STATE_SLEEPING
] = "SLEEPING"
196 static void can_print_opt(struct link_util
*lu
, FILE *f
, struct rtattr
*tb
[])
201 if (tb
[IFLA_CAN_CTRLMODE
]) {
202 struct can_ctrlmode
*cm
= RTA_DATA(tb
[IFLA_CAN_CTRLMODE
]);
205 print_ctrlmode(f
, cm
->flags
);
208 if (tb
[IFLA_CAN_STATE
]) {
209 int *state
= RTA_DATA(tb
[IFLA_CAN_STATE
]);
211 fprintf(f
, "state %s ", *state
<= CAN_STATE_MAX
?
212 can_state_names
[*state
] : "UNKNOWN");
215 if (tb
[IFLA_CAN_BERR_COUNTER
]) {
216 struct can_berr_counter
*bc
=
217 RTA_DATA(tb
[IFLA_CAN_BERR_COUNTER
]);
219 fprintf(f
, "(berr-counter tx %d rx %d) ", bc
->txerr
, bc
->rxerr
);
222 if (tb
[IFLA_CAN_RESTART_MS
]) {
223 __u32
*restart_ms
= RTA_DATA(tb
[IFLA_CAN_RESTART_MS
]);
225 fprintf(f
, "restart-ms %d ", *restart_ms
);
228 if (tb
[IFLA_CAN_BITTIMING
]) {
229 struct can_bittiming
*bt
= RTA_DATA(tb
[IFLA_CAN_BITTIMING
]);
232 "bitrate %d sample-point %.3f ",
233 bt
->bitrate
, (float)bt
->sample_point
/ 1000.);
235 "tq %d prop-seg %d phase-seg1 %d phase-seg2 %d sjw %d",
236 bt
->tq
, bt
->prop_seg
, bt
->phase_seg1
, bt
->phase_seg2
,
240 if (tb
[IFLA_CAN_BITTIMING_CONST
]) {
241 struct can_bittiming_const
*btc
=
242 RTA_DATA(tb
[IFLA_CAN_BITTIMING_CONST
]);
245 "%s: tseg1 %d..%d tseg2 %d..%d "
246 "sjw 1..%d brp %d..%d brp-inc %d",
247 btc
->name
, btc
->tseg1_min
, btc
->tseg1_max
,
248 btc
->tseg2_min
, btc
->tseg2_max
, btc
->sjw_max
,
249 btc
->brp_min
, btc
->brp_max
, btc
->brp_inc
);
252 if (tb
[IFLA_CAN_CLOCK
]) {
253 struct can_clock
*clock
= RTA_DATA(tb
[IFLA_CAN_CLOCK
]);
255 fprintf(f
, "\n clock %d", clock
->freq
);
260 static void can_print_xstats(struct link_util
*lu
,
261 FILE *f
, struct rtattr
*xstats
)
263 struct can_device_stats
*stats
;
265 if (xstats
&& RTA_PAYLOAD(xstats
) == sizeof(*stats
)) {
266 stats
= RTA_DATA(xstats
);
268 "re-started bus-errors arbit-lost "
269 "error-warn error-pass bus-off");
270 fprintf(f
, "\n %-10d %-10d %-10d %-10d %-10d %-10d",
271 stats
->restarts
, stats
->bus_error
,
272 stats
->arbitration_lost
, stats
->error_warning
,
273 stats
->error_passive
, stats
->bus_off
);
277 struct link_util can_link_util
= {
279 .maxattr
= IFLA_CAN_MAX
,
280 .parse_opt
= can_parse_opt
,
281 .print_opt
= can_print_opt
,
282 .print_xstats
= can_print_xstats
,