xref: /aosp_15_r20/external/libnl/lib/route/link/can.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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