1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3 * Copyright (c) 2012 Benedikt Spranger <[email protected]>
4 */
5
6 /**
7 * @ingroup link
8 * @defgroup can CAN
9 * Controller Area Network link module
10 *
11 * @details
12 * \b Link Type Name: "can"
13 *
14 * @route_doc{link_can, CAN Documentation}
15 *
16 * @{
17 */
18
19 #include "nl-default.h"
20
21 #include <linux/can/netlink.h>
22
23 #include <netlink/netlink.h>
24 #include <netlink/attr.h>
25 #include <netlink/utils.h>
26 #include <netlink/object.h>
27 #include <netlink/route/rtnl.h>
28 #include <netlink/route/link/can.h>
29
30 #include "nl-route.h"
31 #include "link-api.h"
32
33 /** @cond SKIP */
34 #define CAN_HAS_BITTIMING (1<<0)
35 #define CAN_HAS_BITTIMING_CONST (1<<1)
36 #define CAN_HAS_CLOCK (1<<2)
37 #define CAN_HAS_STATE (1<<3)
38 #define CAN_HAS_CTRLMODE (1<<4)
39 #define CAN_HAS_RESTART_MS (1<<5)
40 #define CAN_HAS_RESTART (1<<6)
41 #define CAN_HAS_BERR_COUNTER (1<<7)
42 #define CAN_HAS_DATA_BITTIMING (1<<8)
43 #define CAN_HAS_DATA_BITTIMING_CONST (1<<9)
44 #define CAN_HAS_DEVICE_STATS (1<<10)
45
46 struct can_info {
47 uint32_t ci_state;
48 uint32_t ci_restart;
49 uint32_t ci_restart_ms;
50 struct can_ctrlmode ci_ctrlmode;
51 struct can_bittiming ci_bittiming;
52 struct can_bittiming_const ci_bittiming_const;
53 struct can_clock ci_clock;
54 struct can_berr_counter ci_berr_counter;
55 uint32_t ci_mask;
56 struct can_bittiming ci_data_bittiming;
57 struct can_bittiming_const ci_data_bittiming_const;
58 struct can_device_stats ci_device_stats;
59 };
60
61 /** @endcond */
62
63 static struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
64 [IFLA_CAN_STATE] = { .type = NLA_U32 },
65 [IFLA_CAN_CTRLMODE] = { .minlen = sizeof(struct can_ctrlmode) },
66 [IFLA_CAN_RESTART_MS] = { .type = NLA_U32 },
67 [IFLA_CAN_RESTART] = { .type = NLA_U32 },
68 [IFLA_CAN_BITTIMING] = { .minlen = sizeof(struct can_bittiming) },
69 [IFLA_CAN_BITTIMING_CONST]
70 = { .minlen = sizeof(struct can_bittiming_const) },
71 [IFLA_CAN_CLOCK] = { .minlen = sizeof(struct can_clock) },
72 [IFLA_CAN_BERR_COUNTER] = { .minlen = sizeof(struct can_berr_counter) },
73 [IFLA_CAN_DATA_BITTIMING]
74 = { .minlen = sizeof(struct can_bittiming) },
75 [IFLA_CAN_DATA_BITTIMING_CONST]
76 = { .minlen = sizeof(struct can_bittiming_const) },
77 };
78
can_alloc(struct rtnl_link * link)79 static int can_alloc(struct rtnl_link *link)
80 {
81 struct can_info *ci;
82
83 if (link->l_info)
84 memset(link->l_info, 0, sizeof(*ci));
85 else {
86 ci = calloc(1, sizeof(*ci));
87 if (!ci)
88 return -NLE_NOMEM;
89
90 link->l_info = ci;
91 }
92
93 return 0;
94 }
95
can_parse(struct rtnl_link * link,struct nlattr * data,struct nlattr * xstats)96 static int can_parse(struct rtnl_link *link, struct nlattr *data,
97 struct nlattr *xstats)
98 {
99 struct nlattr *tb[IFLA_CAN_MAX+1];
100 struct can_info *ci;
101 int err;
102
103 NL_DBG(3, "Parsing CAN link info\n");
104
105 if ((err = nla_parse_nested(tb, IFLA_CAN_MAX, data, can_policy)) < 0)
106 goto errout;
107
108 if ((err = can_alloc(link)) < 0)
109 goto errout;
110
111 ci = link->l_info;
112
113 if (tb[IFLA_CAN_STATE]) {
114 ci->ci_state = nla_get_u32(tb[IFLA_CAN_STATE]);
115 ci->ci_mask |= CAN_HAS_STATE;
116 }
117
118 if (tb[IFLA_CAN_RESTART]) {
119 ci->ci_restart = nla_get_u32(tb[IFLA_CAN_RESTART]);
120 ci->ci_mask |= CAN_HAS_RESTART;
121 }
122
123 if (tb[IFLA_CAN_RESTART_MS]) {
124 ci->ci_restart_ms = nla_get_u32(tb[IFLA_CAN_RESTART_MS]);
125 ci->ci_mask |= CAN_HAS_RESTART_MS;
126 }
127
128 if (tb[IFLA_CAN_CTRLMODE]) {
129 nla_memcpy(&ci->ci_ctrlmode, tb[IFLA_CAN_CTRLMODE],
130 sizeof(ci->ci_ctrlmode));
131 ci->ci_mask |= CAN_HAS_CTRLMODE;
132 }
133
134 if (tb[IFLA_CAN_BITTIMING]) {
135 nla_memcpy(&ci->ci_bittiming, tb[IFLA_CAN_BITTIMING],
136 sizeof(ci->ci_bittiming));
137 ci->ci_mask |= CAN_HAS_BITTIMING;
138 }
139
140 if (tb[IFLA_CAN_BITTIMING_CONST]) {
141 nla_memcpy(&ci->ci_bittiming_const,
142 tb[IFLA_CAN_BITTIMING_CONST],
143 sizeof(ci->ci_bittiming_const));
144 ci->ci_mask |= CAN_HAS_BITTIMING_CONST;
145 }
146
147 if (tb[IFLA_CAN_CLOCK]) {
148 nla_memcpy(&ci->ci_clock, tb[IFLA_CAN_CLOCK],
149 sizeof(ci->ci_clock));
150 ci->ci_mask |= CAN_HAS_CLOCK;
151 }
152
153 if (tb[IFLA_CAN_BERR_COUNTER]) {
154 nla_memcpy(&ci->ci_berr_counter, tb[IFLA_CAN_BERR_COUNTER],
155 sizeof(ci->ci_berr_counter));
156 ci->ci_mask |= CAN_HAS_BERR_COUNTER;
157 }
158
159 if (tb[IFLA_CAN_DATA_BITTIMING]) {
160 nla_memcpy(&ci->ci_data_bittiming, tb[IFLA_CAN_DATA_BITTIMING],
161 sizeof(ci->ci_data_bittiming));
162 ci->ci_mask |= CAN_HAS_DATA_BITTIMING;
163 }
164
165 if (tb[IFLA_CAN_DATA_BITTIMING_CONST]) {
166 nla_memcpy(&ci->ci_data_bittiming_const, tb[IFLA_CAN_DATA_BITTIMING_CONST],
167 sizeof(ci->ci_data_bittiming_const));
168 ci->ci_mask |= CAN_HAS_DATA_BITTIMING_CONST;
169 }
170
171 if (xstats && _nla_len(xstats) >= sizeof(ci->ci_device_stats)) {
172 nla_memcpy(&ci->ci_device_stats, xstats, sizeof(ci->ci_device_stats));
173 ci->ci_mask |= CAN_HAS_DEVICE_STATS;
174 }
175
176 err = 0;
177 errout:
178 return err;
179 }
180
can_free(struct rtnl_link * link)181 static void can_free(struct rtnl_link *link)
182 {
183 struct can_info *ci = link->l_info;
184
185 free(ci);
186 link->l_info = NULL;
187 }
188
print_can_state(uint32_t state)189 static char *print_can_state (uint32_t state)
190 {
191 char *text;
192
193 switch (state)
194 {
195 case CAN_STATE_ERROR_ACTIVE:
196 text = "error active";
197 break;
198 case CAN_STATE_ERROR_WARNING:
199 text = "error warning";
200 break;
201 case CAN_STATE_ERROR_PASSIVE:
202 text = "error passive";
203 break;
204 case CAN_STATE_BUS_OFF:
205 text = "bus off";
206 break;
207 case CAN_STATE_STOPPED:
208 text = "stopped";
209 break;
210 case CAN_STATE_SLEEPING:
211 text = "sleeping";
212 break;
213 default:
214 text = "unknown state";
215 }
216
217 return text;
218 }
219
can_dump_line(struct rtnl_link * link,struct nl_dump_params * p)220 static void can_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
221 {
222 struct can_info *ci = link->l_info;
223 char buf [64];
224
225 rtnl_link_can_ctrlmode2str(ci->ci_ctrlmode.flags, buf, sizeof(buf));
226 nl_dump(p, "bitrate %d %s <%s>",
227 ci->ci_bittiming.bitrate, print_can_state(ci->ci_state), buf);
228 }
229
can_dump_details(struct rtnl_link * link,struct nl_dump_params * p)230 static void can_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
231 {
232 struct can_info *ci = link->l_info;
233
234 can_dump_line(link, p);
235
236 if (ci->ci_mask & CAN_HAS_RESTART) {
237 if (ci->ci_restart)
238 nl_dump_line(p," restarting\n");
239 }
240
241 if (ci->ci_mask & CAN_HAS_RESTART_MS) {
242 nl_dump_line(p," restart interval %d ms\n",
243 ci->ci_restart_ms);
244 }
245
246 if (ci->ci_mask & CAN_HAS_BITTIMING) {
247 nl_dump_line(p," sample point %f %%\n",
248 ((float) ci->ci_bittiming.sample_point)/10);
249 nl_dump_line(p," time quanta %d ns\n",
250 ci->ci_bittiming.tq);
251 nl_dump_line(p," propagation segment %d tq\n",
252 ci->ci_bittiming.prop_seg);
253 nl_dump_line(p," phase buffer segment1 %d tq\n",
254 ci->ci_bittiming.phase_seg1);
255 nl_dump_line(p," phase buffer segment2 %d tq\n",
256 ci->ci_bittiming.phase_seg2);
257 nl_dump_line(p," synchronisation jump width %d tq\n",
258 ci->ci_bittiming.sjw);
259 nl_dump_line(p," bitrate prescaler %d\n",
260 ci->ci_bittiming.brp);
261 }
262
263 if (ci->ci_mask & CAN_HAS_BITTIMING_CONST) {
264 nl_dump_line(p," minimum tsig1 %d tq\n",
265 ci->ci_bittiming_const.tseg1_min);
266 nl_dump_line(p," maximum tsig1 %d tq\n",
267 ci->ci_bittiming_const.tseg1_max);
268 nl_dump_line(p," minimum tsig2 %d tq\n",
269 ci->ci_bittiming_const.tseg2_min);
270 nl_dump_line(p," maximum tsig2 %d tq\n",
271 ci->ci_bittiming_const.tseg2_max);
272 nl_dump_line(p," maximum sjw %d tq\n",
273 ci->ci_bittiming_const.sjw_max);
274 nl_dump_line(p," minimum brp %d\n",
275 ci->ci_bittiming_const.brp_min);
276 nl_dump_line(p," maximum brp %d\n",
277 ci->ci_bittiming_const.brp_max);
278 nl_dump_line(p," brp increment %d\n",
279 ci->ci_bittiming_const.brp_inc);
280 }
281
282 if (ci->ci_mask & CAN_HAS_CLOCK) {
283 nl_dump_line(p," base freq %u Hz\n", ci->ci_clock.freq);
284
285 }
286
287 if (ci->ci_mask & CAN_HAS_BERR_COUNTER) {
288 nl_dump_line(p," bus error RX %d\n",
289 ci->ci_berr_counter.rxerr);
290 nl_dump_line(p," bus error TX %d\n",
291 ci->ci_berr_counter.txerr);
292 }
293 }
294
can_dump_stats(struct rtnl_link * link,struct nl_dump_params * p)295 static void can_dump_stats(struct rtnl_link *link, struct nl_dump_params *p)
296 {
297 struct can_info *ci = link->l_info;
298
299 can_dump_details(link, p);
300
301 if (ci->ci_mask & CAN_HAS_DEVICE_STATS) {
302 nl_dump_line(p," bus errors %d\n",
303 ci->ci_device_stats.bus_error);
304 nl_dump_line(p," error warning state changes %d\n",
305 ci->ci_device_stats.error_warning);
306 nl_dump_line(p," error passive state changes %d\n",
307 ci->ci_device_stats.error_passive);
308 nl_dump_line(p," bus off state changes %d\n",
309 ci->ci_device_stats.bus_off);
310 nl_dump_line(p," arbitration lost errors %d\n",
311 ci->ci_device_stats.arbitration_lost);
312 nl_dump_line(p," restarts %d\n",
313 ci->ci_device_stats.restarts);
314 }
315 }
316
can_clone(struct rtnl_link * dst,struct rtnl_link * src)317 static int can_clone(struct rtnl_link *dst, struct rtnl_link *src)
318 {
319 struct can_info *cdst, *csrc = src->l_info;
320 int ret;
321
322 dst->l_info = NULL;
323 ret = rtnl_link_set_type(dst, "can");
324 if (ret < 0)
325 return ret;
326
327 cdst = malloc(sizeof(*cdst));
328 if (!cdst)
329 return -NLE_NOMEM;
330
331 *cdst = *csrc;
332 dst->l_info = cdst;
333
334 return 0;
335 }
336
can_put_attrs(struct nl_msg * msg,struct rtnl_link * link)337 static int can_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
338 {
339 struct can_info *ci = link->l_info;
340 struct nlattr *data;
341
342 data = nla_nest_start(msg, IFLA_INFO_DATA);
343 if (!data)
344 return -NLE_MSGSIZE;
345
346 if (ci->ci_mask & CAN_HAS_RESTART)
347 NLA_PUT_U32(msg, IFLA_CAN_RESTART, ci->ci_restart);
348
349 if (ci->ci_mask & CAN_HAS_RESTART_MS)
350 NLA_PUT_U32(msg, IFLA_CAN_RESTART_MS, ci->ci_restart_ms);
351
352 if (ci->ci_mask & CAN_HAS_CTRLMODE)
353 NLA_PUT(msg, IFLA_CAN_CTRLMODE, sizeof(ci->ci_ctrlmode),
354 &ci->ci_ctrlmode);
355
356 if (ci->ci_mask & CAN_HAS_BITTIMING)
357 NLA_PUT(msg, IFLA_CAN_BITTIMING, sizeof(ci->ci_bittiming),
358 &ci->ci_bittiming);
359
360 if (ci->ci_mask & CAN_HAS_BITTIMING_CONST)
361 NLA_PUT(msg, IFLA_CAN_BITTIMING_CONST,
362 sizeof(ci->ci_bittiming_const),
363 &ci->ci_bittiming_const);
364
365 if (ci->ci_mask & CAN_HAS_CLOCK)
366 NLA_PUT(msg, IFLA_CAN_CLOCK, sizeof(ci->ci_clock),
367 &ci->ci_clock);
368
369 if (ci->ci_mask & CAN_HAS_DATA_BITTIMING)
370 NLA_PUT(msg, IFLA_CAN_DATA_BITTIMING, sizeof(ci->ci_data_bittiming),
371 &ci->ci_data_bittiming);
372
373 if (ci->ci_mask & CAN_HAS_DATA_BITTIMING_CONST)
374 NLA_PUT(msg, IFLA_CAN_DATA_BITTIMING_CONST, sizeof(ci->ci_data_bittiming_const),
375 &ci->ci_data_bittiming_const);
376
377 nla_nest_end(msg, data);
378
379 nla_put_failure:
380
381 return 0;
382 }
383
384 static struct rtnl_link_info_ops can_info_ops = {
385 .io_name = "can",
386 .io_alloc = can_alloc,
387 .io_parse = can_parse,
388 .io_dump = {
389 [NL_DUMP_LINE] = can_dump_line,
390 [NL_DUMP_DETAILS] = can_dump_details,
391 [NL_DUMP_STATS] = can_dump_stats,
392 },
393 .io_clone = can_clone,
394 .io_put_attrs = can_put_attrs,
395 .io_free = can_free,
396 };
397
398 /** @cond SKIP */
399 #define IS_CAN_LINK_ASSERT(link) \
400 if ((link)->l_info_ops != &can_info_ops) { \
401 APPBUG("Link is not a CAN link. set type \"can\" first."); \
402 return -NLE_OPNOTSUPP; \
403 }
404 /** @endcond */
405
406 /**
407 * @name CAN Object
408 * @{
409 */
410
411 /**
412 * Check if link is a CAN link
413 * @arg link Link object
414 *
415 * @return True if link is a CAN link, otherwise false is returned.
416 */
rtnl_link_is_can(struct rtnl_link * link)417 int rtnl_link_is_can(struct rtnl_link *link)
418 {
419 return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "can");
420 }
421
422 /**
423 * Restart CAN device
424 * @arg link Link object
425 *
426 * @return 0 on success or a negative error code
427 */
rtnl_link_can_restart(struct rtnl_link * link)428 int rtnl_link_can_restart(struct rtnl_link *link)
429 {
430 struct can_info *ci = link->l_info;
431
432 IS_CAN_LINK_ASSERT(link);
433
434 ci->ci_restart = 1;
435 ci->ci_restart |= CAN_HAS_RESTART;
436
437 return 0;
438 }
439
440 /**
441 * Get CAN base frequency
442 * @arg link Link object
443 * @arg freq frequency in Hz
444 *
445 * @return 0 on success or a negative error code
446 */
rtnl_link_can_freq(struct rtnl_link * link,uint32_t * freq)447 int rtnl_link_can_freq(struct rtnl_link *link, uint32_t *freq)
448 {
449 struct can_info *ci = link->l_info;
450
451 IS_CAN_LINK_ASSERT(link);
452 if (!freq)
453 return -NLE_INVAL;
454
455 if (ci->ci_mask & CAN_HAS_CLOCK)
456 *freq = ci->ci_clock.freq;
457 else
458 return -NLE_AGAIN;
459
460 return 0;
461 }
462
463 /**
464 * Get CAN state
465 * @arg link Link object
466 * @arg state CAN bus state
467 * @return 0 on success or a negative error code
468 */
rtnl_link_can_state(struct rtnl_link * link,uint32_t * state)469 int rtnl_link_can_state(struct rtnl_link *link, uint32_t *state)
470 {
471 struct can_info *ci = link->l_info;
472
473 IS_CAN_LINK_ASSERT(link);
474 if (!state)
475 return -NLE_INVAL;
476
477 *state = ci->ci_state;
478
479 return 0;
480 }
481
482 /**
483 * Get CAN RX bus error count
484 * @arg link Link object
485 *
486 * @return RX bus error count on success or a negative error code
487 */
rtnl_link_can_berr_rx(struct rtnl_link * link)488 int rtnl_link_can_berr_rx(struct rtnl_link *link)
489 {
490 struct can_info *ci = link->l_info;
491
492 IS_CAN_LINK_ASSERT(link);
493
494 if (ci->ci_mask & CAN_HAS_BERR_COUNTER)
495 return ci->ci_berr_counter.rxerr;
496 else
497 return -NLE_AGAIN;
498 }
499
500 /**
501 * Get CAN TX bus error count
502 * @arg link Link object
503 *
504 * @return TX bus error count on success or a negative error code
505 */
rtnl_link_can_berr_tx(struct rtnl_link * link)506 int rtnl_link_can_berr_tx(struct rtnl_link *link)
507 {
508 struct can_info *ci = link->l_info;
509
510 IS_CAN_LINK_ASSERT(link);
511
512 if (ci->ci_mask & CAN_HAS_BERR_COUNTER)
513 return ci->ci_berr_counter.txerr;
514 else
515 return -NLE_AGAIN;
516 }
517
518 /**
519 * Get CAN bus error count
520 * @arg link Link object
521 * @arg berr Bus error count
522 *
523 * @return 0 on success or a negative error code
524 */
rtnl_link_can_berr(struct rtnl_link * link,struct can_berr_counter * berr)525 int rtnl_link_can_berr(struct rtnl_link *link, struct can_berr_counter *berr)
526 {
527 struct can_info *ci = link->l_info;
528
529 IS_CAN_LINK_ASSERT(link);
530 if (!berr)
531 return -NLE_INVAL;
532
533 if (ci->ci_mask & CAN_HAS_BERR_COUNTER)
534 *berr = ci->ci_berr_counter;
535 else
536 return -NLE_AGAIN;
537
538 return 0;
539 }
540
541 /**
542 * Get CAN hardware-dependent bit-timing constant
543 * @arg link Link object
544 * @arg bt_const Bit-timing constant
545 *
546 * @return 0 on success or a negative error code
547 */
rtnl_link_can_get_bt_const(struct rtnl_link * link,struct can_bittiming_const * bt_const)548 int rtnl_link_can_get_bt_const(struct rtnl_link *link,
549 struct can_bittiming_const *bt_const)
550 {
551 struct can_info *ci = link->l_info;
552
553 IS_CAN_LINK_ASSERT(link);
554 if (!bt_const)
555 return -NLE_INVAL;
556
557 if (ci->ci_mask & CAN_HAS_BITTIMING_CONST)
558 *bt_const = ci->ci_bittiming_const;
559 else
560 return -NLE_AGAIN;
561
562 return 0;
563 }
564
565 /**
566 * Get CAN device bit-timing
567 * @arg link Link object
568 * @arg bit_timing CAN bit-timing
569 *
570 * @return 0 on success or a negative error code
571 */
rtnl_link_can_get_bittiming(struct rtnl_link * link,struct can_bittiming * bit_timing)572 int rtnl_link_can_get_bittiming(struct rtnl_link *link,
573 struct can_bittiming *bit_timing)
574 {
575 struct can_info *ci = link->l_info;
576
577 IS_CAN_LINK_ASSERT(link);
578 if (!bit_timing)
579 return -NLE_INVAL;
580
581 if (ci->ci_mask & CAN_HAS_BITTIMING)
582 *bit_timing = ci->ci_bittiming;
583 else
584 return -NLE_AGAIN;
585
586 return 0;
587 }
588
589 /**
590 * Set CAN device bit-timing
591 * @arg link Link object
592 * @arg bit_timing CAN bit-timing
593 *
594 * @return 0 on success or a negative error code
595 */
rtnl_link_can_set_bittiming(struct rtnl_link * link,const struct can_bittiming * bit_timing)596 int rtnl_link_can_set_bittiming(struct rtnl_link *link,
597 const struct can_bittiming *bit_timing)
598 {
599 struct can_info *ci = link->l_info;
600
601 IS_CAN_LINK_ASSERT(link);
602 if (!bit_timing)
603 return -NLE_INVAL;
604
605 ci->ci_bittiming = *bit_timing;
606 ci->ci_mask |= CAN_HAS_BITTIMING;
607
608 return 0;
609 }
610
611 /**
612 * Get CAN device bit-timing
613 * @arg link Link object
614 * @arg bitrate CAN bitrate
615 *
616 * @return 0 on success or a negative error code
617 */
rtnl_link_can_get_bitrate(struct rtnl_link * link,uint32_t * bitrate)618 int rtnl_link_can_get_bitrate(struct rtnl_link *link, uint32_t *bitrate)
619 {
620 struct can_info *ci = link->l_info;
621
622 IS_CAN_LINK_ASSERT(link);
623 if (!bitrate)
624 return -NLE_INVAL;
625
626 if (ci->ci_mask & CAN_HAS_BITTIMING)
627 *bitrate = ci->ci_bittiming.bitrate;
628 else
629 return -NLE_AGAIN;
630
631 return 0;
632 }
633
634 /**
635 * Set CAN device bit-rate
636 * @arg link Link object
637 * @arg bitrate CAN bitrate
638 *
639 * @return 0 on success or a negative error code
640 */
rtnl_link_can_set_bitrate(struct rtnl_link * link,uint32_t bitrate)641 int rtnl_link_can_set_bitrate(struct rtnl_link *link, uint32_t bitrate)
642 {
643 struct can_info *ci = link->l_info;
644
645 IS_CAN_LINK_ASSERT(link);
646
647 ci->ci_bittiming.bitrate = bitrate;
648 ci->ci_mask |= CAN_HAS_BITTIMING;
649
650 return 0;
651 }
652
653 /**
654 * Get CAN device sample point
655 * @arg link Link object
656 * @arg sp CAN sample point
657 *
658 * @return 0 on success or a negative error code
659 */
rtnl_link_can_get_sample_point(struct rtnl_link * link,uint32_t * sp)660 int rtnl_link_can_get_sample_point(struct rtnl_link *link, uint32_t *sp)
661 {
662 struct can_info *ci = link->l_info;
663
664 IS_CAN_LINK_ASSERT(link);
665 if (!sp)
666 return -NLE_INVAL;
667
668 if (ci->ci_mask & CAN_HAS_BITTIMING)
669 *sp = ci->ci_bittiming.sample_point;
670 else
671 return -NLE_AGAIN;
672
673 return 0;
674 }
675
676 /**
677 * Set CAN device sample point
678 * @arg link Link object
679 * @arg sp CAN sample point
680 *
681 * @return 0 on success or a negative error code
682 */
rtnl_link_can_set_sample_point(struct rtnl_link * link,uint32_t sp)683 int rtnl_link_can_set_sample_point(struct rtnl_link *link, uint32_t sp)
684 {
685 struct can_info *ci = link->l_info;
686
687 IS_CAN_LINK_ASSERT(link);
688
689 ci->ci_bittiming.sample_point = sp;
690 ci->ci_mask |= CAN_HAS_BITTIMING;
691
692 return 0;
693 }
694
695 /**
696 * Get CAN device restart intervall
697 * @arg link Link object
698 * @arg interval Restart intervall in ms
699 *
700 * @return 0 on success or a negative error code
701 */
rtnl_link_can_get_restart_ms(struct rtnl_link * link,uint32_t * interval)702 int rtnl_link_can_get_restart_ms(struct rtnl_link *link, uint32_t *interval)
703 {
704 struct can_info *ci = link->l_info;
705
706 IS_CAN_LINK_ASSERT(link);
707 if (!interval)
708 return -NLE_INVAL;
709
710 if (ci->ci_mask & CAN_HAS_RESTART_MS)
711 *interval = ci->ci_restart_ms;
712 else
713 return -NLE_AGAIN;
714
715 return 0;
716 }
717
718 /**
719 * Set CAN device restart intervall
720 * @arg link Link object
721 * @arg interval Restart intervall in ms
722 *
723 * @return 0 on success or a negative error code
724 */
rtnl_link_can_set_restart_ms(struct rtnl_link * link,uint32_t interval)725 int rtnl_link_can_set_restart_ms(struct rtnl_link *link, uint32_t interval)
726 {
727 struct can_info *ci = link->l_info;
728
729 IS_CAN_LINK_ASSERT(link);
730
731 ci->ci_restart_ms = interval;
732 ci->ci_mask |= CAN_HAS_RESTART_MS;
733
734 return 0;
735 }
736
737 /**
738 * Get CAN control mode
739 * @arg link Link object
740 * @arg ctrlmode CAN control mode
741 *
742 * @return 0 on success or a negative error code
743 */
rtnl_link_can_get_ctrlmode(struct rtnl_link * link,uint32_t * ctrlmode)744 int rtnl_link_can_get_ctrlmode(struct rtnl_link *link, uint32_t *ctrlmode)
745 {
746 struct can_info *ci = link->l_info;
747
748 IS_CAN_LINK_ASSERT(link);
749 if (!ctrlmode)
750 return -NLE_INVAL;
751
752 if (ci->ci_mask & CAN_HAS_CTRLMODE)
753 *ctrlmode = ci->ci_ctrlmode.flags;
754 else
755 return -NLE_AGAIN;
756
757 return 0;
758 }
759
760 /**
761 * Set a CAN Control Mode
762 * @arg link Link object
763 * @arg ctrlmode CAN control mode
764 *
765 * @return 0 on success or a negative error code
766 */
rtnl_link_can_set_ctrlmode(struct rtnl_link * link,uint32_t ctrlmode)767 int rtnl_link_can_set_ctrlmode(struct rtnl_link *link, uint32_t ctrlmode)
768 {
769 struct can_info *ci = link->l_info;
770
771 IS_CAN_LINK_ASSERT(link);
772
773 ci->ci_ctrlmode.flags |= ctrlmode;
774 ci->ci_ctrlmode.mask |= ctrlmode;
775 ci->ci_mask |= CAN_HAS_CTRLMODE;
776
777 return 0;
778 }
779
780 /**
781 * Unset a CAN Control Mode
782 * @arg link Link object
783 * @arg ctrlmode CAN control mode
784 *
785 * @return 0 on success or a negative error code
786 */
rtnl_link_can_unset_ctrlmode(struct rtnl_link * link,uint32_t ctrlmode)787 int rtnl_link_can_unset_ctrlmode(struct rtnl_link *link, uint32_t ctrlmode)
788 {
789 struct can_info *ci = link->l_info;
790
791 IS_CAN_LINK_ASSERT(link);
792
793 ci->ci_ctrlmode.flags &= ~ctrlmode;
794 ci->ci_ctrlmode.mask |= ctrlmode;
795 ci->ci_mask |= CAN_HAS_CTRLMODE;
796
797 return 0;
798 }
799
800 /**
801 * Get CAN FD hardware-dependent data bit-timing constant
802 * @arg link Link object
803 * @arg data_bt_const CAN FD data bit-timing constant
804 *
805 * @return 0 on success or a negative error code
806 */
rtnl_link_can_get_data_bittiming_const(struct rtnl_link * link,struct can_bittiming_const * data_bt_const)807 int rtnl_link_can_get_data_bittiming_const(struct rtnl_link *link,
808 struct can_bittiming_const *data_bt_const)
809 {
810 struct can_info *ci = link->l_info;
811
812 IS_CAN_LINK_ASSERT(link);
813 if (!data_bt_const)
814 return -NLE_INVAL;
815
816 if (ci->ci_mask & CAN_HAS_DATA_BITTIMING_CONST)
817 *data_bt_const = ci->ci_data_bittiming_const;
818 else
819 return -NLE_AGAIN;
820
821 return 0;
822 }
823
824 /**
825 * Set CAN FD device data bit-timing-const
826 * @arg link Link object
827 * @arg data_bit_timing CAN FD data bit-timing
828 *
829 * @return 0 on success or a negative error code
830 */
rtnl_link_can_set_data_bittiming_const(struct rtnl_link * link,const struct can_bittiming_const * data_bt_const)831 int rtnl_link_can_set_data_bittiming_const(struct rtnl_link *link,
832 const struct can_bittiming_const *data_bt_const)
833 {
834 struct can_info *ci = link->l_info;
835
836 IS_CAN_LINK_ASSERT(link);
837 if (!data_bt_const)
838 return -NLE_INVAL;
839
840 ci->ci_data_bittiming_const = *data_bt_const;
841 ci->ci_mask |= CAN_HAS_DATA_BITTIMING_CONST;
842
843 return 0;
844 }
845
846 /**
847 * Get CAN FD device data bit-timing
848 * @arg link Link object
849 * @arg data_bit_timing CAN FD data bit-timing
850 *
851 * @return 0 on success or a negative error code
852 */
rtnl_link_can_get_data_bittiming(struct rtnl_link * link,struct can_bittiming * data_bit_timing)853 int rtnl_link_can_get_data_bittiming(struct rtnl_link *link,
854 struct can_bittiming *data_bit_timing)
855 {
856 struct can_info *ci = link->l_info;
857
858 IS_CAN_LINK_ASSERT(link);
859 if (!data_bit_timing)
860 return -NLE_INVAL;
861
862 if (ci->ci_mask & CAN_HAS_DATA_BITTIMING)
863 *data_bit_timing = ci->ci_data_bittiming;
864 else
865 return -NLE_AGAIN;
866
867 return 0;
868 }
869
870 /**
871 * Set CAN FD device data bit-timing
872 * @arg link Link object
873 * @arg data_bit_timing CAN FD data bit-timing
874 *
875 * @return 0 on success or a negative error code
876 */
rtnl_link_can_set_data_bittiming(struct rtnl_link * link,const struct can_bittiming * data_bit_timing)877 int rtnl_link_can_set_data_bittiming(struct rtnl_link *link,
878 const struct can_bittiming *data_bit_timing)
879 {
880 struct can_info *ci = link->l_info;
881
882 IS_CAN_LINK_ASSERT(link);
883 if (!data_bit_timing)
884 return -NLE_INVAL;
885
886 ci->ci_data_bittiming = *data_bit_timing;
887 ci->ci_mask |= CAN_HAS_DATA_BITTIMING;
888
889 return 0;
890 }
891
892 /**
893 * Get CAN device stats
894 * @arg link Link object
895 * @arg device_stats CAN device stats
896 *
897 * @return 0 on success or a negative error code
898 */
rtnl_link_can_get_device_stats(struct rtnl_link * link,struct can_device_stats * device_stats)899 int rtnl_link_can_get_device_stats(struct rtnl_link* link,
900 struct can_device_stats *device_stats)
901 {
902 struct can_info *ci = link->l_info;
903
904 IS_CAN_LINK_ASSERT(link);
905 if (!device_stats)
906 return -NLE_INVAL;
907
908 if (ci->ci_mask & CAN_HAS_DEVICE_STATS)
909 *device_stats = ci->ci_device_stats;
910 else
911 return -NLE_MISSING_ATTR;
912
913 return 0;
914 }
915
916 /** @} */
917
918 /**
919 * @name Control Mode Translation
920 * @{
921 */
922
923 static const struct trans_tbl can_ctrlmode[] = {
924 __ADD(CAN_CTRLMODE_LOOPBACK, loopback),
925 __ADD(CAN_CTRLMODE_LISTENONLY, listen-only),
926 __ADD(CAN_CTRLMODE_3_SAMPLES, triple-sampling),
927 __ADD(CAN_CTRLMODE_ONE_SHOT, one-shot),
928 __ADD(CAN_CTRLMODE_BERR_REPORTING, berr-reporting),
929 __ADD(CAN_CTRLMODE_FD, fd),
930 __ADD(CAN_CTRLMODE_PRESUME_ACK, presume-ack),
931 __ADD(CAN_CTRLMODE_FD_NON_ISO, fd-non-iso),
932 };
933
rtnl_link_can_ctrlmode2str(int ctrlmode,char * buf,size_t len)934 char *rtnl_link_can_ctrlmode2str(int ctrlmode, char *buf, size_t len)
935 {
936 return __flags2str(ctrlmode, buf, len, can_ctrlmode,
937 ARRAY_SIZE(can_ctrlmode));
938 }
939
rtnl_link_can_str2ctrlmode(const char * name)940 int rtnl_link_can_str2ctrlmode(const char *name)
941 {
942 return __str2flags(name, can_ctrlmode, ARRAY_SIZE(can_ctrlmode));
943 }
944
945 /** @} */
946
can_init(void)947 static void _nl_init can_init(void)
948 {
949 rtnl_link_register_info(&can_info_ops);
950 }
951
can_exit(void)952 static void _nl_exit can_exit(void)
953 {
954 rtnl_link_unregister_info(&can_info_ops);
955 }
956
957 /** @} */
958