Home | History | Annotate | Download | only in link
      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 (at) 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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 
    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 
    767 int rtnl_link_can_str2ctrlmode(const char *name)
    768 {
    769 	return __str2flags(name, can_ctrlmode, ARRAY_SIZE(can_ctrlmode));
    770 }
    771 
    772 /** @} */
    773 
    774 static void __init can_init(void)
    775 {
    776 	rtnl_link_register_info(&can_info_ops);
    777 }
    778 
    779 static void __exit can_exit(void)
    780 {
    781 	rtnl_link_unregister_info(&can_info_ops);
    782 }
    783 
    784 /** @} */
    785