canconfig.c revision 1.2 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