15a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger/* 25a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger * iplink_can.c CAN device support 35a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger * 45a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger * This program is free software; you can redistribute it and/or 55a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger * modify it under the terms of the GNU General Public License 65a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger * as published by the Free Software Foundation; either version 75a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger * 2 of the License, or (at your option) any later version. 85a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger * 95a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger * Authors: Wolfgang Grandegger <wg@grandegger.com> 105a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger */ 115a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 125a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger#include <stdio.h> 135a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger#include <stdlib.h> 145a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger#include <string.h> 155a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 165a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger#include <linux/can/netlink.h> 175a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 185a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger#include "rt_names.h" 195a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger#include "utils.h" 205a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger#include "ip_common.h" 215a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 225a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandeggerstatic void usage(void) 235a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger{ 245a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(stderr, 255a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "Usage: ip link set DEVICE type can\n" 265a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t[ bitrate BITRATE [ sample-point SAMPLE-POINT] ] | \n" 275a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t[ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1\n " 285a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t phase-seg2 PHASE-SEG2 [ sjw SJW ] ]\n" 295a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\n" 305a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t[ loopback { on | off } ]\n" 315a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t[ listen-only { on | off } ]\n" 325a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t[ triple-sampling { on | off } ]\n" 338a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger "\t[ one-shot { on | off } ]\n" 348a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger "\t[ berr-reporting { on | off } ]\n" 355a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\n" 365a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t[ restart-ms TIME-MS ]\n" 375a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t[ restart ]\n" 385a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\n" 395a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\tWhere: BITRATE := { 1..1000000 }\n" 405a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t SAMPLE-POINT := { 0.000..0.999 }\n" 415a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t TQ := { NUMBER }\n" 425a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t PROP-SEG := { 1..8 }\n" 435a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t PHASE-SEG1 := { 1..8 }\n" 445a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t PHASE-SEG2 := { 1..8 }\n" 455a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t SJW := { 1..4 }\n" 465a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "\t RESTART-MS := { 0 | NUMBER }\n" 475a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger ); 485a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger} 495a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 505a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandeggerstatic int get_float(float *val, const char *arg) 515a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger{ 525a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger float res; 535a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger char *ptr; 545a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 555a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (!arg || !*arg) 565a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger return -1; 575a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger res = strtof(arg, &ptr); 585a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (!ptr || ptr == arg || *ptr) 595a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger return -1; 605a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger *val = res; 615a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger return 0; 625a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger} 635a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 645a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandeggerstatic void set_ctrlmode(char* name, char *arg, 655a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger struct can_ctrlmode *cm, __u32 flags) 665a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger{ 675a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (strcmp(arg, "on") == 0) { 685a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger cm->flags |= flags; 695a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (strcmp(arg, "off") != 0) { 705a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(stderr, 715a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "Error: argument of \"%s\" must be \"on\" or \"off\"\n", 725a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger name); 735a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger exit(-1); 745a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } 755a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger cm->mask |= flags; 765a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger} 775a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 785a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandeggerstatic void print_ctrlmode(FILE *f, __u32 cm) 795a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger{ 805a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(f, "<"); 815a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger#define _PF(cmflag, cmname) \ 825a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (cm & cmflag) { \ 835a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger cm &= ~cmflag; \ 845a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(f, "%s%s", cmname, cm ? "," : ""); \ 855a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } 865a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger _PF(CAN_CTRLMODE_LOOPBACK, "LOOPBACK"); 875a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger _PF(CAN_CTRLMODE_LISTENONLY, "LISTEN-ONLY"); 885a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger _PF(CAN_CTRLMODE_3_SAMPLES, "TRIPLE-SAMPLING"); 898a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger _PF(CAN_CTRLMODE_ONE_SHOT, "ONE-SHOT"); 908a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger _PF(CAN_CTRLMODE_BERR_REPORTING, "BERR-REPORTING"); 915a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger#undef _PF 925a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (cm) 935a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(f, "%x", cm); 945a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(f, "> "); 955a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger} 965a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 975a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandeggerstatic int can_parse_opt(struct link_util *lu, int argc, char **argv, 985a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger struct nlmsghdr *n) 995a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger{ 1005a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger struct can_bittiming bt; 1015a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger struct can_ctrlmode cm = {0, 0}; 1025a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 1035a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger memset(&bt, 0, sizeof(bt)); 1045a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger while (argc > 0) { 1055a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (matches(*argv, "bitrate") == 0) { 1065a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger NEXT_ARG(); 1075a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (get_u32(&bt.bitrate, *argv, 0)) 1085a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger invarg("invalid \"bitrate\" value\n", *argv); 1095a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (matches(*argv, "sample-point") == 0) { 1105a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger float sp; 1115a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 1125a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger NEXT_ARG(); 1135a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (get_float(&sp, *argv)) 1145a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger invarg("invalid \"sample-point\" value\n", 1155a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger *argv); 1165a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger bt.sample_point = (__u32)(sp * 1000); 1175a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (matches(*argv, "tq") == 0) { 1185a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger NEXT_ARG(); 1195a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (get_u32(&bt.tq, *argv, 0)) 1205a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger invarg("invalid \"tq\" value\n", *argv); 1215a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (matches(*argv, "prop-seg") == 0) { 1225a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger NEXT_ARG(); 1235a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (get_u32(&bt.prop_seg, *argv, 0)) 1245a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger invarg("invalid \"prop-seg\" value\n", *argv); 1255a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (matches(*argv, "phase-seg1") == 0) { 1265a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger NEXT_ARG(); 1275a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (get_u32(&bt.phase_seg1, *argv, 0)) 1285a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger invarg("invalid \"phase-seg1\" value\n", *argv); 1295a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (matches(*argv, "phase-seg2") == 0) { 1305a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger NEXT_ARG(); 1315a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (get_u32(&bt.phase_seg2, *argv, 0)) 1325a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger invarg("invalid \"phase-seg2\" value\n", *argv); 1335a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (matches(*argv, "sjw") == 0) { 1345a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger NEXT_ARG(); 1355a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (get_u32(&bt.sjw, *argv, 0)) 1365a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger invarg("invalid \"sjw\" value\n", *argv); 1375a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (matches(*argv, "loopback") == 0) { 1385a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger NEXT_ARG(); 1395a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger set_ctrlmode("loopback", *argv, &cm, 1405a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger CAN_CTRLMODE_LOOPBACK); 1415a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (matches(*argv, "listen-only") == 0) { 1425a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger NEXT_ARG(); 1435a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger set_ctrlmode("listen-only", *argv, &cm, 1445a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger CAN_CTRLMODE_LISTENONLY); 1455a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (matches(*argv, "triple-sampling") == 0) { 1465a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger NEXT_ARG(); 1475a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger set_ctrlmode("triple-sampling", *argv, &cm, 1485a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger CAN_CTRLMODE_3_SAMPLES); 1498a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger } else if (matches(*argv, "one-shot") == 0) { 1508a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger NEXT_ARG(); 1518a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger set_ctrlmode("one-shot", *argv, &cm, 1528a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger CAN_CTRLMODE_ONE_SHOT); 1538a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger } else if (matches(*argv, "berr-reporting") == 0) { 1548a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger NEXT_ARG(); 1558a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger set_ctrlmode("berr-reporting", *argv, &cm, 1568a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger CAN_CTRLMODE_BERR_REPORTING); 1575a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (matches(*argv, "restart") == 0) { 1585a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger __u32 val = 1; 1595a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 1605a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger addattr32(n, 1024, IFLA_CAN_RESTART, val); 1615a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (matches(*argv, "restart-ms") == 0) { 1625a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger __u32 val; 1635a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 1645a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger NEXT_ARG(); 1655a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (get_u32(&val, *argv, 0)) 1665a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger invarg("invalid \"restart-ms\" value\n", *argv); 1675a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger addattr32(n, 1024, IFLA_CAN_RESTART_MS, val); 1685a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else if (matches(*argv, "help") == 0) { 1695a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger usage(); 1705a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger return -1; 1715a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } else { 1725a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(stderr, "can: what is \"%s\"?\n", *argv); 1735a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger usage(); 1745a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger return -1; 1755a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } 1765a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger argc--, argv++; 1775a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } 1785a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 1795a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (bt.bitrate || bt.tq) 1805a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger addattr_l(n, 1024, IFLA_CAN_BITTIMING, &bt, sizeof(bt)); 1815a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (cm.mask) 1825a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger addattr_l(n, 1024, IFLA_CAN_CTRLMODE, &cm, sizeof(cm)); 1835a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 1845a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger return 0; 1855a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger} 1865a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 1875a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandeggerstatic const char *can_state_names[] = { 1885a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger [CAN_STATE_ERROR_ACTIVE] = "ERROR-ACTIVE", 1895a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger [CAN_STATE_ERROR_WARNING] = "ERROR-WARNING", 1905a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger [CAN_STATE_ERROR_PASSIVE] = "ERROR-PASSIVE", 1915a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger [CAN_STATE_BUS_OFF] = "BUS-OFF", 1925a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger [CAN_STATE_STOPPED] = "STOPPED", 1935a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger [CAN_STATE_SLEEPING] = "SLEEPING" 1945a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger}; 1955a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 1965a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandeggerstatic void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) 1975a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger{ 1985a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (!tb) 1995a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger return; 2005a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2015a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (tb[IFLA_CAN_CTRLMODE]) { 2025a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger struct can_ctrlmode *cm = RTA_DATA(tb[IFLA_CAN_CTRLMODE]); 2035a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2045a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (cm->flags) 2055a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger print_ctrlmode(f, cm->flags); 2065a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } 2075a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2085a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (tb[IFLA_CAN_STATE]) { 2095a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger int *state = RTA_DATA(tb[IFLA_CAN_STATE]); 2105a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2115a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(f, "state %s ", *state <= CAN_STATE_MAX ? 2125a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger can_state_names[*state] : "UNKNOWN"); 2135a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } 2145a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2158a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger if (tb[IFLA_CAN_BERR_COUNTER]) { 2168a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger struct can_berr_counter *bc = 2178a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger RTA_DATA(tb[IFLA_CAN_BERR_COUNTER]); 2188a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger 2198a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger fprintf(f, "(berr-counter tx %d rx %d) ", bc->txerr, bc->rxerr); 2208a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger } 2218a5179466a142172a6f24f5d815c622541b3f61fWolfgang Grandegger 2225a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (tb[IFLA_CAN_RESTART_MS]) { 2235a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger __u32 *restart_ms = RTA_DATA(tb[IFLA_CAN_RESTART_MS]); 2245a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2255a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(f, "restart-ms %d ", *restart_ms); 2265a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } 2275a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2285a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (tb[IFLA_CAN_BITTIMING]) { 2295a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger struct can_bittiming *bt = RTA_DATA(tb[IFLA_CAN_BITTIMING]); 2305a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2315a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(f, "\n " 2325a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "bitrate %d sample-point %.3f ", 2335a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger bt->bitrate, (float)bt->sample_point / 1000.); 2345a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(f, "\n " 2355a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "tq %d prop-seg %d phase-seg1 %d phase-seg2 %d sjw %d", 2365a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger bt->tq, bt->prop_seg, bt->phase_seg1, bt->phase_seg2, 2375a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger bt->sjw); 2385a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } 2395a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2405a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (tb[IFLA_CAN_BITTIMING_CONST]) { 2415a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger struct can_bittiming_const *btc = 2425a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger RTA_DATA(tb[IFLA_CAN_BITTIMING_CONST]); 2435a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2445a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(f, "\n " 2455a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "%s: tseg1 %d..%d tseg2 %d..%d " 2465a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "sjw 1..%d brp %d..%d brp-inc %d", 2475a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger btc->name, btc->tseg1_min, btc->tseg1_max, 2485a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger btc->tseg2_min, btc->tseg2_max, btc->sjw_max, 2495a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger btc->brp_min, btc->brp_max, btc->brp_inc); 2505a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } 2515a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2525a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (tb[IFLA_CAN_CLOCK]) { 2535a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger struct can_clock *clock = RTA_DATA(tb[IFLA_CAN_CLOCK]); 2545a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2555a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(f, "\n clock %d", clock->freq); 2565a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } 2575a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2585a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger} 2595a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2605a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandeggerstatic void can_print_xstats(struct link_util *lu, 2615a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger FILE *f, struct rtattr *xstats) 2625a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger{ 2635a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger struct can_device_stats *stats; 2645a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2655a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger if (xstats && RTA_PAYLOAD(xstats) == sizeof(*stats)) { 2665a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger stats = RTA_DATA(xstats); 2675a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(f, "\n " 2685a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "re-started bus-errors arbit-lost " 2695a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger "error-warn error-pass bus-off"); 2705a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger fprintf(f, "\n %-10d %-10d %-10d %-10d %-10d %-10d", 2715a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger stats->restarts, stats->bus_error, 2725a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger stats->arbitration_lost, stats->error_warning, 2735a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger stats->error_passive, stats->bus_off); 2745a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger } 2755a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger} 2765a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger 2775a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandeggerstruct link_util can_link_util = { 2785a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger .id = "can", 2795a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger .maxattr = IFLA_CAN_MAX, 2805a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger .parse_opt = can_parse_opt, 2815a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger .print_opt = can_print_opt, 2825a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger .print_xstats = can_print_xstats, 2835a2044782b6a0eb7594d3b3e2e32bbd6a63e77f1Wolfgang Grandegger}; 284