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