Home | History | Annotate | Line # | Download | only in canconfig
      1  1.2  bouyer /*	$NetBSD: canconfig.c,v 1.2 2017/05/27 21:02:55 bouyer Exp $	*/
      2  1.2  bouyer 
      3  1.2  bouyer /*
      4  1.2  bouyer  * Copyright 2001 Wasabi Systems, Inc.
      5  1.2  bouyer  * All rights reserved.
      6  1.2  bouyer  *
      7  1.2  bouyer  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
      8  1.2  bouyer  *
      9  1.2  bouyer  * Redistribution and use in source and binary forms, with or without
     10  1.2  bouyer  * modification, are permitted provided that the following conditions
     11  1.2  bouyer  * are met:
     12  1.2  bouyer  * 1. Redistributions of source code must retain the above copyright
     13  1.2  bouyer  *    notice, this list of conditions and the following disclaimer.
     14  1.2  bouyer  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.2  bouyer  *    notice, this list of conditions and the following disclaimer in the
     16  1.2  bouyer  *    documentation and/or other materials provided with the distribution.
     17  1.2  bouyer  * 3. All advertising materials mentioning features or use of this software
     18  1.2  bouyer  *    must display the following acknowledgement:
     19  1.2  bouyer  *	This product includes software developed for the NetBSD Project by
     20  1.2  bouyer  *	Wasabi Systems, Inc.
     21  1.2  bouyer  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  1.2  bouyer  *    or promote products derived from this software without specific prior
     23  1.2  bouyer  *    written permission.
     24  1.2  bouyer  *
     25  1.2  bouyer  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  1.2  bouyer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  1.2  bouyer  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  1.2  bouyer  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  1.2  bouyer  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  1.2  bouyer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  1.2  bouyer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  1.2  bouyer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  1.2  bouyer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  1.2  bouyer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  1.2  bouyer  * POSSIBILITY OF SUCH DAMAGE.
     36  1.2  bouyer  */
     37  1.2  bouyer 
     38  1.2  bouyer #include <sys/cdefs.h>
     39  1.2  bouyer 
     40  1.2  bouyer #ifndef lint
     41  1.2  bouyer __RCSID("$NetBSD: canconfig.c,v 1.2 2017/05/27 21:02:55 bouyer Exp $");
     42  1.2  bouyer #endif
     43  1.2  bouyer 
     44  1.2  bouyer 
     45  1.2  bouyer #include <sys/param.h>
     46  1.2  bouyer #include <sys/socket.h>
     47  1.2  bouyer #include <sys/ioctl.h>
     48  1.2  bouyer 
     49  1.2  bouyer #include <net/if.h>
     50  1.2  bouyer #include <netcan/can.h>
     51  1.2  bouyer #include <netcan/can_link.h>
     52  1.2  bouyer #include <ifaddrs.h>
     53  1.2  bouyer 
     54  1.2  bouyer #include <ctype.h>
     55  1.2  bouyer #include <err.h>
     56  1.2  bouyer #include <errno.h>
     57  1.2  bouyer #include <stdio.h>
     58  1.2  bouyer #include <stdlib.h>
     59  1.2  bouyer #include <string.h>
     60  1.2  bouyer #include <unistd.h>
     61  1.2  bouyer 
     62  1.2  bouyer struct command {
     63  1.2  bouyer 	const char *cmd_keyword;
     64  1.2  bouyer 	int	cmd_argcnt;
     65  1.2  bouyer 	int	cmd_flags;
     66  1.2  bouyer 	void	(*cmd_func)(const struct command *, int, const char *,
     67  1.2  bouyer 		    char **);
     68  1.2  bouyer };
     69  1.2  bouyer 
     70  1.2  bouyer #define	CMD_INVERT	0x01	/* "invert" the sense of the command */
     71  1.2  bouyer 
     72  1.2  bouyer static void	cmd_up(const struct command *, int, const char *, char **);
     73  1.2  bouyer static void	cmd_down(const struct command *, int, const char *, char **);
     74  1.2  bouyer static void	cmd_brp(const struct command *, int, const char *, char **);
     75  1.2  bouyer static void	cmd_prop_seg(const struct command *, int, const char *, char **);
     76  1.2  bouyer static void	cmd_phase_seg1(const struct command *, int, const char *, char **);
     77  1.2  bouyer static void	cmd_phase_seg2(const struct command *, int, const char *, char **);
     78  1.2  bouyer static void	cmd_sjw(const struct command *, int, const char *, char **);
     79  1.2  bouyer static void	cmd_3samples(const struct command *, int, const char *, char **);
     80  1.2  bouyer static void	cmd_listenonly(const struct command *, int, const char *, char **);
     81  1.2  bouyer static void	cmd_loopback(const struct command *, int, const char *, char **);
     82  1.2  bouyer 
     83  1.2  bouyer static const struct command command_table[] = {
     84  1.2  bouyer 	{ "up",			0,	0,		cmd_up },
     85  1.2  bouyer 	{ "down",		0,	0,		cmd_down },
     86  1.2  bouyer 
     87  1.2  bouyer 	{ "brp",		1,	0,		cmd_brp },
     88  1.2  bouyer 	{ "prop_seg",		1,	0,		cmd_prop_seg },
     89  1.2  bouyer 	{ "phase_seg1",		1,	0,		cmd_phase_seg1 },
     90  1.2  bouyer 	{ "phase_seg2",		1,	0,		cmd_phase_seg2 },
     91  1.2  bouyer 	{ "sjw",		1,	0,		cmd_sjw },
     92  1.2  bouyer 
     93  1.2  bouyer 	{ "3samples",		0,	0,		cmd_3samples },
     94  1.2  bouyer 	{ "-3samples",		0,	CMD_INVERT,	cmd_3samples },
     95  1.2  bouyer 
     96  1.2  bouyer 	{ "listenonly",		0,	0,		cmd_listenonly },
     97  1.2  bouyer 	{ "-listenonly",	0,	CMD_INVERT,	cmd_listenonly },
     98  1.2  bouyer 
     99  1.2  bouyer 	{ "loopback",		0,	0,		cmd_loopback },
    100  1.2  bouyer 	{ "-loopback",		0,	CMD_INVERT,	cmd_loopback },
    101  1.2  bouyer 
    102  1.2  bouyer 	{ NULL,			0,	0,		NULL },
    103  1.2  bouyer };
    104  1.2  bouyer 
    105  1.2  bouyer static void	printall(int);
    106  1.2  bouyer static void	status(int, const char *);
    107  1.2  bouyer static void	show_timings(int, const char *, const char *);
    108  1.2  bouyer static int	is_can(int s, const char *);
    109  1.2  bouyer static int	get_val(const char *, u_long *);
    110  1.2  bouyer #define	do_cmd(a,b,c,d,e,f)	do_cmd2((a),(b),(c),(d),(e),NULL,(f))
    111  1.2  bouyer static int	do_cmd2(int, const char *, u_long, void *, size_t, size_t *, int);
    112  1.2  bouyer __dead static void	usage(void);
    113  1.2  bouyer 
    114  1.2  bouyer static int	aflag;
    115  1.2  bouyer static struct ifreq g_ifr;
    116  1.2  bouyer static int	g_ifr_updated = 0;
    117  1.2  bouyer 
    118  1.2  bouyer struct can_link_timecaps g_cltc;
    119  1.2  bouyer struct can_link_timings g_clt;
    120  1.2  bouyer static int	g_clt_updated = 0;
    121  1.2  bouyer 
    122  1.2  bouyer int
    123  1.2  bouyer main(int argc, char *argv[])
    124  1.2  bouyer {
    125  1.2  bouyer 	const struct command *cmd;
    126  1.2  bouyer 	char *canifname;
    127  1.2  bouyer 	int sock, ch;
    128  1.2  bouyer 
    129  1.2  bouyer 	if (argc < 2)
    130  1.2  bouyer 		usage();
    131  1.2  bouyer 
    132  1.2  bouyer 	while ((ch = getopt(argc, argv, "a")) != -1) {
    133  1.2  bouyer 		switch (ch) {
    134  1.2  bouyer 		case 'a':
    135  1.2  bouyer 			aflag = 1;
    136  1.2  bouyer 			break;
    137  1.2  bouyer 
    138  1.2  bouyer 		default:
    139  1.2  bouyer 			usage();
    140  1.2  bouyer 		}
    141  1.2  bouyer 	}
    142  1.2  bouyer 
    143  1.2  bouyer 	argc -= optind;
    144  1.2  bouyer 	argv += optind;
    145  1.2  bouyer 
    146  1.2  bouyer 	if (aflag) {
    147  1.2  bouyer 		if (argc != 0)
    148  1.2  bouyer 			usage();
    149  1.2  bouyer 		sock = socket(AF_CAN, SOCK_RAW, CAN_RAW);
    150  1.2  bouyer 		if (sock < 0)
    151  1.2  bouyer 			err(1, "socket");
    152  1.2  bouyer 
    153  1.2  bouyer 		printall(sock);
    154  1.2  bouyer 		exit(0);
    155  1.2  bouyer 	}
    156  1.2  bouyer 
    157  1.2  bouyer 	if (argc == 0)
    158  1.2  bouyer 		usage();
    159  1.2  bouyer 
    160  1.2  bouyer 	sock = socket(AF_CAN, SOCK_RAW, CAN_RAW);
    161  1.2  bouyer 	if (sock < 0)
    162  1.2  bouyer 		err(1, "socket");
    163  1.2  bouyer 
    164  1.2  bouyer 	canifname = argv[0];
    165  1.2  bouyer 
    166  1.2  bouyer 	if (is_can(sock, canifname) == 0)
    167  1.2  bouyer 		errx(1, "%s is not a can interface", canifname);
    168  1.2  bouyer 
    169  1.2  bouyer 	/* Get a copy of the interface flags. */
    170  1.2  bouyer 	strlcpy(g_ifr.ifr_name, canifname, sizeof(g_ifr.ifr_name));
    171  1.2  bouyer 	if (ioctl(sock, SIOCGIFFLAGS, &g_ifr) < 0)
    172  1.2  bouyer 		err(1, "unable to get interface flags");
    173  1.2  bouyer 
    174  1.2  bouyer 	argc--;
    175  1.2  bouyer 	argv++;
    176  1.2  bouyer 
    177  1.2  bouyer 	if (argc == 0) {
    178  1.2  bouyer 		status(sock, canifname);
    179  1.2  bouyer 		exit(0);
    180  1.2  bouyer 	}
    181  1.2  bouyer 
    182  1.2  bouyer 	if (do_cmd(sock, canifname, CANGLINKTIMECAP, &g_cltc, sizeof(g_cltc), 0)
    183  1.2  bouyer 	    < 0)
    184  1.2  bouyer 		err(1, "unable to get can link timecaps");
    185  1.2  bouyer 
    186  1.2  bouyer 	if (do_cmd(sock, canifname, CANGLINKTIMINGS, &g_clt, sizeof(g_clt), 0) < 0)
    187  1.2  bouyer 		err(1, "unable to get can link timings");
    188  1.2  bouyer 
    189  1.2  bouyer 	while (argc != 0) {
    190  1.2  bouyer 		for (cmd = command_table; cmd->cmd_keyword != NULL; cmd++) {
    191  1.2  bouyer 			if (strcmp(cmd->cmd_keyword, argv[0]) == 0)
    192  1.2  bouyer 				break;
    193  1.2  bouyer 		}
    194  1.2  bouyer 		if (cmd->cmd_keyword == NULL)
    195  1.2  bouyer 			errx(1, "unknown command: %s", argv[0]);
    196  1.2  bouyer 
    197  1.2  bouyer 		argc--;
    198  1.2  bouyer 		argv++;
    199  1.2  bouyer 
    200  1.2  bouyer 		if (argc < cmd->cmd_argcnt)
    201  1.2  bouyer 			errx(1, "command %s requires %d argument%s",
    202  1.2  bouyer 			    cmd->cmd_keyword, cmd->cmd_argcnt,
    203  1.2  bouyer 			    cmd->cmd_argcnt == 1 ? "" : "s");
    204  1.2  bouyer 
    205  1.2  bouyer 		(*cmd->cmd_func)(cmd, sock, canifname, argv);
    206  1.2  bouyer 
    207  1.2  bouyer 		argc -= cmd->cmd_argcnt;
    208  1.2  bouyer 		argv += cmd->cmd_argcnt;
    209  1.2  bouyer 	}
    210  1.2  bouyer 
    211  1.2  bouyer 	/* If the timings changed, update them. */
    212  1.2  bouyer 	if (g_clt_updated &&
    213  1.2  bouyer 	    do_cmd(sock, canifname, CANSLINKTIMINGS, &g_clt, sizeof(g_clt), 1) < 0)
    214  1.2  bouyer 		err(1, "unable to set can link timings");
    215  1.2  bouyer 
    216  1.2  bouyer 	/* If the flags changed, update them. */
    217  1.2  bouyer 	if (g_ifr_updated && ioctl(sock, SIOCSIFFLAGS, &g_ifr) < 0)
    218  1.2  bouyer 		err(1, "unable to set interface flags");
    219  1.2  bouyer 
    220  1.2  bouyer 	exit (0);
    221  1.2  bouyer }
    222  1.2  bouyer 
    223  1.2  bouyer static void
    224  1.2  bouyer usage(void)
    225  1.2  bouyer {
    226  1.2  bouyer 	static const char *usage_strings[] = {
    227  1.2  bouyer 		"-a",
    228  1.2  bouyer 		"<canif>",
    229  1.2  bouyer 		"<canif> up|down",
    230  1.2  bouyer 		"<canif> brp <value>",
    231  1.2  bouyer 		"<canif> prop_seg <value>",
    232  1.2  bouyer 		"<canif> phase_seg1 <value>",
    233  1.2  bouyer 		"<canif> phase_seg2 <value>",
    234  1.2  bouyer 		"<canif> sjw <value>",
    235  1.2  bouyer 		"<canif> 3samples | -3samples",
    236  1.2  bouyer 		"<canif> listenonly | -listenonly",
    237  1.2  bouyer 		"<canif> loopback | -loopback",
    238  1.2  bouyer 		NULL,
    239  1.2  bouyer 	};
    240  1.2  bouyer 	extern const char *__progname;
    241  1.2  bouyer 	int i;
    242  1.2  bouyer 
    243  1.2  bouyer 	for (i = 0; usage_strings[i] != NULL; i++)
    244  1.2  bouyer 		fprintf(stderr, "%s %s %s\n",
    245  1.2  bouyer 		    i == 0 ? "usage:" : "      ",
    246  1.2  bouyer 		    __progname, usage_strings[i]);
    247  1.2  bouyer 
    248  1.2  bouyer 	exit(1);
    249  1.2  bouyer }
    250  1.2  bouyer 
    251  1.2  bouyer static int
    252  1.2  bouyer is_can(int s, const char *canif)
    253  1.2  bouyer {
    254  1.2  bouyer 	uint32_t linkmode;
    255  1.2  bouyer 
    256  1.2  bouyer 	if (do_cmd(s, canif, CANGLINKMODE, &linkmode, sizeof(linkmode), 0) < 0)
    257  1.2  bouyer 		return (0);
    258  1.2  bouyer 
    259  1.2  bouyer 	return (1);
    260  1.2  bouyer }
    261  1.2  bouyer 
    262  1.2  bouyer static void
    263  1.2  bouyer printb(const char *s, u_int v, const char *bits)
    264  1.2  bouyer {
    265  1.2  bouyer 	int i, any = 0;
    266  1.2  bouyer 	char c;
    267  1.2  bouyer 
    268  1.2  bouyer 	if (bits && *bits == 8)
    269  1.2  bouyer 		printf("%s=%o", s, v);
    270  1.2  bouyer 	else
    271  1.2  bouyer 		printf("%s=%x", s, v);
    272  1.2  bouyer 	if (bits) {
    273  1.2  bouyer 		bits++;
    274  1.2  bouyer 		putchar('<');
    275  1.2  bouyer 		while ((i = *bits++) != 0) {
    276  1.2  bouyer 			if (v & (1 << (i-1))) {
    277  1.2  bouyer 				if (any)
    278  1.2  bouyer 					putchar(',');
    279  1.2  bouyer 				any = 1;
    280  1.2  bouyer 				for (; (c = *bits) > 32; bits++)
    281  1.2  bouyer 					putchar(c);
    282  1.2  bouyer 			} else
    283  1.2  bouyer 				for (; *bits > 32; bits++)
    284  1.2  bouyer 					;
    285  1.2  bouyer 		}
    286  1.2  bouyer 		putchar('>');
    287  1.2  bouyer 	}
    288  1.2  bouyer }
    289  1.2  bouyer 
    290  1.2  bouyer static void
    291  1.2  bouyer printall(int sock)
    292  1.2  bouyer {
    293  1.2  bouyer 	struct ifaddrs *ifap, *ifa;
    294  1.2  bouyer 	char *p;
    295  1.2  bouyer 
    296  1.2  bouyer 	if (getifaddrs(&ifap) != 0)
    297  1.2  bouyer 		err(1, "getifaddrs");
    298  1.2  bouyer 	p = NULL;
    299  1.2  bouyer 	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
    300  1.2  bouyer 		if (is_can(sock, ifa->ifa_name) == 0)
    301  1.2  bouyer 			continue;
    302  1.2  bouyer 		if (p != NULL && strcmp(p, ifa->ifa_name) == 0)
    303  1.2  bouyer 			continue;
    304  1.2  bouyer 		p = ifa->ifa_name;
    305  1.2  bouyer 		status(sock, ifa->ifa_name);
    306  1.2  bouyer 	}
    307  1.2  bouyer 
    308  1.2  bouyer 	freeifaddrs(ifap);
    309  1.2  bouyer }
    310  1.2  bouyer 
    311  1.2  bouyer static void
    312  1.2  bouyer status(int sock, const char *canifname)
    313  1.2  bouyer {
    314  1.2  bouyer 	struct ifreq ifr;
    315  1.2  bouyer 
    316  1.2  bouyer 	memset(&ifr, 0, sizeof(ifr));
    317  1.2  bouyer 
    318  1.2  bouyer 	strlcpy(ifr.ifr_name, canifname, sizeof(ifr.ifr_name));
    319  1.2  bouyer 	if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0)
    320  1.2  bouyer 		err(1, "unable to get flags");
    321  1.2  bouyer 
    322  1.2  bouyer 	printf("%s: ", canifname);
    323  1.2  bouyer 	printb("flags", ifr.ifr_flags, IFFBITS);
    324  1.2  bouyer 	printf("\n");
    325  1.2  bouyer 
    326  1.2  bouyer 	show_timings(sock, canifname, "\t");
    327  1.2  bouyer 
    328  1.2  bouyer }
    329  1.2  bouyer 
    330  1.2  bouyer static int
    331  1.2  bouyer valid_timings(struct can_link_timecaps *cltc, struct can_link_timings *clt)
    332  1.2  bouyer {
    333  1.2  bouyer 	if (clt->clt_brp < cltc->cltc_brp_min ||
    334  1.2  bouyer 	    clt->clt_brp > cltc->cltc_brp_max)
    335  1.2  bouyer 		return 0;
    336  1.2  bouyer 
    337  1.2  bouyer 	if (clt->clt_prop < cltc->cltc_prop_min ||
    338  1.2  bouyer 	    clt->clt_prop > cltc->cltc_prop_max)
    339  1.2  bouyer 		return 0;
    340  1.2  bouyer 
    341  1.2  bouyer 	if (clt->clt_ps1 < cltc->cltc_ps1_min ||
    342  1.2  bouyer 	    clt->clt_ps1 > cltc->cltc_ps1_max)
    343  1.2  bouyer 		return 0;
    344  1.2  bouyer 
    345  1.2  bouyer 	if (clt->clt_ps2 < cltc->cltc_ps2_min ||
    346  1.2  bouyer 	    clt->clt_ps2 > cltc->cltc_ps2_max)
    347  1.2  bouyer 		return 0;
    348  1.2  bouyer 
    349  1.2  bouyer 	return 1;
    350  1.2  bouyer }
    351  1.2  bouyer 
    352  1.2  bouyer static void
    353  1.2  bouyer show_timings(int sock, const char *canifname, const char *prefix)
    354  1.2  bouyer {
    355  1.2  bouyer 	struct can_link_timecaps cltc;
    356  1.2  bouyer 	struct can_link_timings clt;
    357  1.2  bouyer 	u_int32_t linkmode;
    358  1.2  bouyer 	char hbuf[8];
    359  1.2  bouyer 
    360  1.2  bouyer 	if (do_cmd(sock, canifname, CANGLINKTIMECAP, &cltc, sizeof(cltc), 0)
    361  1.2  bouyer 	    < 0)
    362  1.2  bouyer 		err(1, "unable to get can link timecaps");
    363  1.2  bouyer 
    364  1.2  bouyer 	if (do_cmd(sock, canifname, CANGLINKTIMINGS, &clt, sizeof(clt), 0) < 0)
    365  1.2  bouyer 		err(1, "unable to get can link timings");
    366  1.2  bouyer 
    367  1.2  bouyer 	if (do_cmd(sock, canifname, CANGLINKMODE, &linkmode, sizeof(linkmode),
    368  1.2  bouyer 	    0) < 0)
    369  1.2  bouyer 		err(1, "unable to get can link mode");
    370  1.2  bouyer 
    371  1.2  bouyer 	humanize_number(hbuf, sizeof(hbuf), cltc.cltc_clock_freq, "Hz",
    372  1.2  bouyer 	    HN_AUTOSCALE, HN_NOSPACE | HN_DIVISOR_1000);
    373  1.2  bouyer 
    374  1.2  bouyer 	printf("%stiming caps:\n", prefix);
    375  1.2  bouyer 	printf("%s  clock %s, brp [%d..%d]/%d, prop_seg [%d..%d]\n",
    376  1.2  bouyer 	    prefix, hbuf,
    377  1.2  bouyer 	    cltc.cltc_brp_min, cltc.cltc_brp_max, cltc.cltc_brp_inc,
    378  1.2  bouyer 	    cltc.cltc_prop_min, cltc.cltc_prop_max);
    379  1.2  bouyer 	printf("%s  phase_seg1 [%d..%d], phase_seg2 [%d..%d], sjw [0..%d]\n",
    380  1.2  bouyer 	    prefix,
    381  1.2  bouyer 	    cltc.cltc_ps1_min, cltc.cltc_ps1_max,
    382  1.2  bouyer 	    cltc.cltc_ps2_min, cltc.cltc_ps2_max,
    383  1.2  bouyer 	    cltc.cltc_sjw_max);
    384  1.2  bouyer 	printf("%s  ", prefix);
    385  1.2  bouyer 	printb("capabilities", cltc.cltc_linkmode_caps, CAN_IFFBITS);
    386  1.2  bouyer 	printf("\n");
    387  1.2  bouyer 	printf("%soperational timings:", prefix);
    388  1.2  bouyer 	if (valid_timings(&cltc, &clt)) {
    389  1.2  bouyer 		uint32_t tq, ntq, bps;
    390  1.2  bouyer 		tq = ((uint64_t)clt.clt_brp * (uint64_t)1000000000) /
    391  1.2  bouyer 		    cltc.cltc_clock_freq;
    392  1.2  bouyer 		ntq = 1 + clt.clt_prop + clt.clt_ps1 + clt.clt_ps2;
    393  1.2  bouyer 		printf(" %d time quanta of %dns",
    394  1.2  bouyer 		    1 + clt.clt_prop + clt.clt_ps1 + clt.clt_ps2, tq);
    395  1.2  bouyer 		bps = 1000000000 / (tq * ntq);
    396  1.2  bouyer 		humanize_number(hbuf, sizeof(hbuf), bps, "bps",
    397  1.2  bouyer 		    HN_AUTOSCALE, HN_NOSPACE | HN_DIVISOR_1000);
    398  1.2  bouyer 		printf(", %s", hbuf);
    399  1.2  bouyer 	};
    400  1.2  bouyer 	printf("\n");
    401  1.2  bouyer 
    402  1.2  bouyer 	printf("%s  brp %d, prop_seg %d, phase_seg1 %d, phase_seg2 %d, sjw %d\n",
    403  1.2  bouyer 	    prefix,
    404  1.2  bouyer 	    clt.clt_brp, clt.clt_prop, clt.clt_ps1, clt.clt_ps2, clt.clt_sjw);
    405  1.2  bouyer 	printf("%s  ", prefix);
    406  1.2  bouyer 	printb("mode", linkmode, CAN_IFFBITS);
    407  1.2  bouyer 	printf("\n");
    408  1.2  bouyer }
    409  1.2  bouyer 
    410  1.2  bouyer static int
    411  1.2  bouyer get_val(const char *cp, u_long *valp)
    412  1.2  bouyer {
    413  1.2  bouyer 	char *endptr;
    414  1.2  bouyer 	u_long val;
    415  1.2  bouyer 
    416  1.2  bouyer 	errno = 0;
    417  1.2  bouyer 	val = strtoul(cp, &endptr, 0);
    418  1.2  bouyer 	if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE)
    419  1.2  bouyer 		return (-1);
    420  1.2  bouyer 
    421  1.2  bouyer 	*valp = val;
    422  1.2  bouyer 	return (0);
    423  1.2  bouyer }
    424  1.2  bouyer 
    425  1.2  bouyer static int
    426  1.2  bouyer do_cmd2(int sock, const char *canifname, u_long op, void *arg, size_t argsize,
    427  1.2  bouyer     size_t *outsizep, int set)
    428  1.2  bouyer {
    429  1.2  bouyer 	struct ifdrv ifd;
    430  1.2  bouyer 	int error;
    431  1.2  bouyer 
    432  1.2  bouyer 	memset(&ifd, 0, sizeof(ifd));
    433  1.2  bouyer 
    434  1.2  bouyer 	strlcpy(ifd.ifd_name, canifname, sizeof(ifd.ifd_name));
    435  1.2  bouyer 	ifd.ifd_cmd = op;
    436  1.2  bouyer 	ifd.ifd_len = argsize;
    437  1.2  bouyer 	ifd.ifd_data = arg;
    438  1.2  bouyer 
    439  1.2  bouyer 	error = ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd);
    440  1.2  bouyer 
    441  1.2  bouyer 	if (outsizep)
    442  1.2  bouyer 		*outsizep = ifd.ifd_len;
    443  1.2  bouyer 
    444  1.2  bouyer 	return error;
    445  1.2  bouyer }
    446  1.2  bouyer 
    447  1.2  bouyer static void
    448  1.2  bouyer do_ifflag(int sock, const char *canifname, int flag, int set)
    449  1.2  bouyer {
    450  1.2  bouyer 
    451  1.2  bouyer 	if (set)
    452  1.2  bouyer 		g_ifr.ifr_flags |= flag;
    453  1.2  bouyer 	else
    454  1.2  bouyer 		g_ifr.ifr_flags &= ~flag;
    455  1.2  bouyer 
    456  1.2  bouyer 	g_ifr_updated = 1;
    457  1.2  bouyer }
    458  1.2  bouyer 
    459  1.2  bouyer static int
    460  1.2  bouyer do_canflag(int sock, const char *canifname, uint32_t flag, int set)
    461  1.2  bouyer {
    462  1.2  bouyer 	int cmd;
    463  1.2  bouyer 	if (set)
    464  1.2  bouyer 		cmd = CANSLINKMODE;
    465  1.2  bouyer 	else
    466  1.2  bouyer 		cmd = CANCLINKMODE;
    467  1.2  bouyer 	return do_cmd(sock, canifname, cmd, &flag, sizeof(flag), 1);
    468  1.2  bouyer }
    469  1.2  bouyer 
    470  1.2  bouyer static void
    471  1.2  bouyer cmd_up(const struct command *cmd, int sock, const char *canifname,
    472  1.2  bouyer     char **argv)
    473  1.2  bouyer {
    474  1.2  bouyer 
    475  1.2  bouyer 	do_ifflag(sock, canifname, IFF_UP, 1);
    476  1.2  bouyer }
    477  1.2  bouyer 
    478  1.2  bouyer static void
    479  1.2  bouyer cmd_down(const struct command *cmd, int sock, const char *canifname,
    480  1.2  bouyer     char **argv)
    481  1.2  bouyer {
    482  1.2  bouyer 
    483  1.2  bouyer 	do_ifflag(sock, canifname, IFF_UP, 0);
    484  1.2  bouyer }
    485  1.2  bouyer 
    486  1.2  bouyer static void
    487  1.2  bouyer cmd_brp(const struct command *cmd, int sock, const char *bridge,
    488  1.2  bouyer     char **argv)
    489  1.2  bouyer {
    490  1.2  bouyer 	u_long val;
    491  1.2  bouyer 
    492  1.2  bouyer 	if (get_val(argv[0], &val) < 0 || (val & ~0xffffffff) != 0)
    493  1.2  bouyer 		errx(1, "%s: invalid value: %s", cmd->cmd_keyword, argv[0]);
    494  1.2  bouyer 	if (val <  g_cltc.cltc_brp_min || val > g_cltc.cltc_brp_max)
    495  1.2  bouyer 		errx(1, "%s: out of range value: %s", cmd->cmd_keyword, argv[0]);
    496  1.2  bouyer 	g_clt.clt_brp = val;
    497  1.2  bouyer 	g_clt_updated=1;
    498  1.2  bouyer }
    499  1.2  bouyer 
    500  1.2  bouyer static void
    501  1.2  bouyer cmd_prop_seg(const struct command *cmd, int sock, const char *bridge,
    502  1.2  bouyer     char **argv)
    503  1.2  bouyer {
    504  1.2  bouyer 	u_long val;
    505  1.2  bouyer 
    506  1.2  bouyer 	if (get_val(argv[0], &val) < 0 || (val & ~0xffffffff) != 0)
    507  1.2  bouyer 		errx(1, "%s: invalid value: %s", cmd->cmd_keyword, argv[0]);
    508  1.2  bouyer 	if (val <  g_cltc.cltc_prop_min || val > g_cltc.cltc_prop_max)
    509  1.2  bouyer 		errx(1, "%s: out of range value: %s", cmd->cmd_keyword, argv[0]);
    510  1.2  bouyer 	g_clt.clt_prop = val;
    511  1.2  bouyer 	g_clt_updated=1;
    512  1.2  bouyer }
    513  1.2  bouyer 
    514  1.2  bouyer static void
    515  1.2  bouyer cmd_phase_seg1(const struct command *cmd, int sock, const char *bridge,
    516  1.2  bouyer     char **argv)
    517  1.2  bouyer {
    518  1.2  bouyer 	u_long val;
    519  1.2  bouyer 
    520  1.2  bouyer 	if (get_val(argv[0], &val) < 0 || (val & ~0xffffffff) != 0)
    521  1.2  bouyer 		errx(1, "%s: invalid value: %s", cmd->cmd_keyword, argv[0]);
    522  1.2  bouyer 	if (val <  g_cltc.cltc_ps1_min || val > g_cltc.cltc_ps1_max)
    523  1.2  bouyer 		errx(1, "%s: out of range value: %s", cmd->cmd_keyword, argv[0]);
    524  1.2  bouyer 	g_clt.clt_ps1 = val;
    525  1.2  bouyer 	g_clt_updated=1;
    526  1.2  bouyer }
    527  1.2  bouyer 
    528  1.2  bouyer static void
    529  1.2  bouyer cmd_phase_seg2(const struct command *cmd, int sock, const char *bridge,
    530  1.2  bouyer     char **argv)
    531  1.2  bouyer {
    532  1.2  bouyer 	u_long val;
    533  1.2  bouyer 
    534  1.2  bouyer 	if (get_val(argv[0], &val) < 0 || (val & ~0xffffffff) != 0)
    535  1.2  bouyer 		errx(1, "%s: invalid value: %s", cmd->cmd_keyword, argv[0]);
    536  1.2  bouyer 	if (val <  g_cltc.cltc_ps2_min || val > g_cltc.cltc_ps2_max)
    537  1.2  bouyer 		errx(1, "%s: out of range value: %s", cmd->cmd_keyword, argv[0]);
    538  1.2  bouyer 	g_clt.clt_ps2 = val;
    539  1.2  bouyer 	g_clt_updated=1;
    540  1.2  bouyer }
    541  1.2  bouyer 
    542  1.2  bouyer static void
    543  1.2  bouyer cmd_sjw(const struct command *cmd, int sock, const char *bridge,
    544  1.2  bouyer     char **argv)
    545  1.2  bouyer {
    546  1.2  bouyer 	u_long val;
    547  1.2  bouyer 
    548  1.2  bouyer 	if (get_val(argv[0], &val) < 0 || (val & ~0xffffffff) != 0)
    549  1.2  bouyer 		errx(1, "%s: invalid value: %s", cmd->cmd_keyword, argv[0]);
    550  1.2  bouyer 	if (val > g_cltc.cltc_sjw_max)
    551  1.2  bouyer 		errx(1, "%s: out of range value: %s", cmd->cmd_keyword, argv[0]);
    552  1.2  bouyer 	g_clt.clt_sjw = val;
    553  1.2  bouyer 	g_clt_updated=1;
    554  1.2  bouyer }
    555  1.2  bouyer static void
    556  1.2  bouyer cmd_3samples(const struct command *cmd, int sock, const char *canifname,
    557  1.2  bouyer     char **argv)
    558  1.2  bouyer {
    559  1.2  bouyer         if (do_canflag(sock, canifname, CAN_LINKMODE_3SAMPLES,
    560  1.2  bouyer 	    (cmd->cmd_flags & CMD_INVERT) ? 0 : 1) < 0)
    561  1.2  bouyer 		err(1, "%s", cmd->cmd_keyword);
    562  1.2  bouyer 
    563  1.2  bouyer }
    564  1.2  bouyer 
    565  1.2  bouyer static void
    566  1.2  bouyer cmd_listenonly(const struct command *cmd, int sock, const char *canifname,
    567  1.2  bouyer     char **argv)
    568  1.2  bouyer {
    569  1.2  bouyer         if (do_canflag(sock, canifname, CAN_LINKMODE_LISTENONLY,
    570  1.2  bouyer 	    (cmd->cmd_flags & CMD_INVERT) ? 0 : 1) < 0)
    571  1.2  bouyer 		err(1, "%s", cmd->cmd_keyword);
    572  1.2  bouyer 
    573  1.2  bouyer }
    574  1.2  bouyer 
    575  1.2  bouyer static void
    576  1.2  bouyer cmd_loopback(const struct command *cmd, int sock, const char *canifname,
    577  1.2  bouyer     char **argv)
    578  1.2  bouyer {
    579  1.2  bouyer         if (do_canflag(sock, canifname, CAN_LINKMODE_LOOPBACK,
    580  1.2  bouyer 	    (cmd->cmd_flags & CMD_INVERT) ? 0 : 1) < 0)
    581  1.2  bouyer 		err(1, "%s", cmd->cmd_keyword);
    582  1.2  bouyer 
    583  1.2  bouyer }
    584