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