• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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