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