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