• 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 	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