BOROSOFTWAREAll work →
scantool/scantool_set.c 532 lines
3 findings in this fileD1L303D14L341B12L377
1/*
2 * freediag - Vehicle Diagnostic Utility
3 *
4 *
5 * Copyright (C) 2001 Richard Almeida & Ibex Ltd ([email protected])
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 *************************************************************************
22 *
23 *
24 * Mostly ODBII Compliant Scan Tool (as defined in SAE J1978)
25 *
26 * CLI routines - "set" commands
27 *
28 *
29 */
30#include <stdbool.h>
31#include <stdint.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35
36#include "diag.h"
37#include "diag_cfg.h" //for cfgi
38#include "diag_l0.h"
39#include "diag_l1.h"
40#include "diag_l2.h"
41
42#include "libcli.h"
43#include "scantool_cli.h"
44#include "utlist.h"
45
46/** Global parameters **/
47/* struct global_cfg contains all global parameters */
48struct globcfg global_cfg;
49
50/* SET sub menu */
51static enum cli_retval cmd_set_custom(int argc, char **argv);
52static enum cli_retval cmd_set_help(int argc, char **argv);
53static enum cli_retval cmd_set_show(int argc, char **argv);
54static enum cli_retval cmd_set_speed(int argc, char **argv);
55static enum cli_retval cmd_set_testerid(int argc, char **argv);
56static enum cli_retval cmd_set_destaddr(int argc, char **argv);
57static enum cli_retval cmd_set_addrtype(int argc, char **argv);
58static enum cli_retval cmd_set_l1protocol(int argc, char **argv);
59static enum cli_retval cmd_set_l2protocol(int argc, char **argv);
60static enum cli_retval cmd_set_initmode(int argc, char **argv);
61static enum cli_retval cmd_set_display(int argc, char **argv);
62static enum cli_retval cmd_set_interface(int argc, char **argv);
63
64const struct cmd_tbl_entry set_cmd_table[] = {
65 { "help", "help [command]", "Gives help for a command",
66 cmd_set_help, 0, NULL},
67 { "?", "help [command]", "Gives help for a command",
68 cmd_set_help, CLI_CMD_HIDDEN, NULL},
69
70 { "interface", "interface [NAME]", "Interface to use. Use set interface ? to get a list of names",
71 cmd_set_interface, 0, NULL},
72
73 { "display", "display [english/metric]", "English or metric display",
74 cmd_set_display, 0, NULL},
75
76 { "speed", "speed [speed]", "ECU communications speed",
77 cmd_set_speed, 0, NULL},
78 { "testerid", "testerid [testerid]", "Source ID/address",
79 cmd_set_testerid, 0, NULL},
80 { "destaddr", "destaddr [destaddr]","Destination ID/address",
81 cmd_set_destaddr, 0, NULL},
82
83 { "addrtype", "addrtype [func/phys]", "Address type, physical or functional.",
84 cmd_set_addrtype, 0, NULL},
85
86 { "l1protocol", "l1protocol [protocolname]", "Hardware (L1) protocol to use. Use 'set l1protocol ?' to show valid choices.",
87 cmd_set_l1protocol, 0, NULL},
88
89 { "l2protocol", "l2protocol [protocolname]", "Software (L2) protocol to use. Use 'set l2protocol ?' to show valid choices.",
90 cmd_set_l2protocol, 0, NULL},
91
92 { "initmode", "initmode [modename]", "Bus initialisation mode to use. Use 'set initmode ?' to show valid choices.",
93 cmd_set_initmode, 0, NULL},
94
95 { "show", "show", "Shows all settable values, including L0-specific items",
96 cmd_set_show, 0, NULL},
97
98 CLI_TBL_BUILTINS,
99
100 { "", "", "",
101 cmd_set_custom, CLI_CMD_CUSTOM | CLI_CMD_HIDDEN, NULL},
102
103 CLI_TBL_END
104};
105
106const char *const l1_names[] = { //these MUST be in the same order as they are listed in diag_l1.h !!
107 "ISO9141", "ISO14230",
108 "J1850-VPW", "J1850-PWM", "CAN", "", "", "RAW", NULL
109};
110
111//These MUST match the DIAG_L2_TYPE_* flags in diag_l2.h so that
112// l2_initmodes[DIAG_L2_TYPE_XX] == "XX" !!
113const char *const l2_initmodes[] = {
114 "5BAUD", "FAST", "CARB", NULL
115};
116
117
118/* workaround to use cmd_set_interface() properly: set up fake command args */
119static char *default_cmd = "interface";
120static char *default_iface = "DUMB";
121
122int set_init(void) {
123 /* Reset parameters to defaults. */
124
125 global_cfg.speed = 10400; /* Comms speed; ECUs will probably send at 10416 bps (96us per bit) */
126
127 global_cfg.src = 0xf1; /* Our tester ID */
128 global_cfg.addrtype = 1; /* Use functional addressing */
129 global_cfg.tgt = 0x33; /* Dest ECU address */
130
131 global_cfg.L1proto = DIAG_L1_ISO9141; /* L1 protocol type */
132
133 global_cfg.L2idx = 0;
134 global_cfg.L2proto = l2proto_list[0]->diag_l2_protocol; /* cannot guarantee 9141 was compiled... DIAG_L2_PROT_ISO9141; */
135
136 global_cfg.initmode = DIAG_L2_TYPE_FASTINIT;
137
138 global_cfg.units = 0; /* English (1), or Metric (0) */
139
140 char *garbage_args[] = {default_cmd, default_iface};
141 cmd_set_interface(2, garbage_args); /* Default H/w interface to use */
142
143 return 0;
144}
145
146void set_close(void) {
147 return;
148}
149
150// handle dynamic options (L0-specific).
151// argv[0] is the config shortname, etc.
152// if argv[0] is '?' (special case), this prints available subcommands.
153static enum cli_retval cmd_set_custom(int argc, char **argv) {
154 struct cfgi *cfgp;
155 char *setstr;
156 bool helping=0;
157 bool show_current=0;
158 int newval;
159
160 if (!global_dl0d) {
161 // no L0 selected yet
162 if (strcmp(argv[0], "?") == 0) {
163 return CMD_OK;
164 }
165 printf("No such item !\nAdditional items may be available after setting the interface type.\nUse \"set interface NAME\" to set the interface type.\n");
166 return CMD_FAILED;
167 }
168
169 if (strcmp(argv[0], "?") == 0) {
170 //list available custom commands for the current L0.
171 LL_FOREACH(diag_l0_getcfg(global_dl0d), cfgp) {
172 printf("\t%s\n", cfgp->shortname);
173 }
174 return CMD_OK;
175 }
176
177 if (argc >= 2) {
178 if (strcmp(argv[1], "?") == 0) {
179 helping = 1;
180 }
181 } else {
182 // no args: display current settings
183 show_current = 1;
184 }
185
186 /* find the config item */
187 LL_FOREACH(diag_l0_getcfg(global_dl0d), cfgp) {
188 if (strcasecmp(cfgp->shortname, argv[0]) == 0) {
189 break;
190 }
191 }
192
193 if (!cfgp) {
194 printf("No such item !\n");
195 return CMD_FAILED;
196 }
197
198 if (show_current) {
199 char *val = diag_cfg_getstr(cfgp);
200 printf("%s: %s\n", argv[0], val);
201 free(val);
202 return CMD_OK;
203 }
204
205 if (helping) {
206 printf("%s\n", cfgp->descr);
207 diag_cfg_refresh(cfgp);
208 printf("Available options:\n");
209 if (cfgp->numopts > 0) {
210 int i;
211 for (i=0; i < cfgp->numopts; i++) {
212 printf("\t\t%s\n", cfgp->opt[i]);
213 }
214 }
215 return CMD_OK;
216 }
217
218/* TODO : move this to diag_cfg.* if it works */
219 newval = htoi(argv[1]);
220 switch (cfgp->type) {
221 case CFGT_STR:
222 diag_cfg_setstr(cfgp, argv[1]);
223 break;
224 case CFGT_U8:
225 diag_cfg_setu8(cfgp, (uint8_t) newval);
226 break;
227 case CFGT_INT:
228 diag_cfg_setint(cfgp, newval);
229 break;
230 case CFGT_BOOL:
231 diag_cfg_setbool(cfgp, (bool) newval);
232 break;
233 default:
234 return CMD_FAILED;
235 }
236
237 setstr = diag_cfg_getstr(cfgp);
238 printf("%s set to: %s\n", cfgp->shortname, setstr);
239 free(setstr);
240 return CMD_OK;
241}
242
243static enum cli_retval cmd_set_show(UNUSED(int argc), UNUSED(char **argv)) {
244 /* Show stuff; calling the cmd_set_*() functions with argc=0 displays the current setting. */
245 cmd_set_interface(0,NULL);
246 cmd_set_speed(0, NULL);
247 cmd_set_display(0,NULL);
248 cmd_set_testerid(0,NULL);
249 cmd_set_addrtype(0,NULL);
250 cmd_set_destaddr(0,NULL);
251 cmd_set_l1protocol(0,NULL);
252 cmd_set_l2protocol(0,NULL);
253 cmd_set_initmode(0,NULL);
254
255 /* Parse L0-specific config items */
256 if (global_dl0d) {
257 struct cfgi *cfgp;
258 printf("L0 options:\n");
259 LL_FOREACH(diag_l0_getcfg(global_dl0d), cfgp) {
260 char *cs = diag_cfg_getstr(cfgp);
261 if (cfgp->shortname == NULL || cs == NULL) {
262 continue;
263 }
264
265 printf("\t%s=%s\n",cfgp->shortname, cs);
266 free(cs);
267 }
268 }
269
270 return CMD_OK;
271}
272
273
274static enum cli_retval cmd_set_interface(int argc, char **argv) {
275 const struct diag_l0 *iter;
276
277 if (argc <= 1 || argv == NULL) {
278 printf("interface: using %s\n",
279 global_cfg.l0name);
280 return CMD_OK;
281 }
282 if (argc > 2) {
283 printf("Too many arguments !\n");
284 return CMD_USAGE;
285 }
286
287 if (global_dl0d) {
288 if (global_dl0d->opened) {
289 printf("Error : L0 busy or connected; please disconnect first\n");
290 return CMD_FAILED;
291 }
292 }
293
294 int i, helping = 0, found = 0;
295 if (strcmp(argv[1], "?") == 0) {
296 helping = 1;
297 printf("Valid interface names (not case sensitive): \n\t");
298 }
299 for (i=0; l0dev_list[i]; i++) {
300 iter = l0dev_list[i];
301 //loop through l0 interface names, either printing or comparing to argv[1]
302 if (helping) {
303 printf("%s ", iter->shortname);
304 } else if (strcasecmp(argv[1], iter->shortname) == 0) {
305 global_cfg.l0name = iter->shortname;
306 found = 1;
307 break; // no use in continuing
308 }
309 }
310
311 if (helping) {
312 printf("\n");
313 return CMD_USAGE;
314 }
315
316 if (!found) {
317 printf("interface: invalid interface %s\n", argv[1]);
318 printf("interface: use \"set interface ?\" to see list of names\n");
319 return CMD_FAILED;
320 }
321
322 printf("interface is now %s\n", global_cfg.l0name);
323
324 /* close + free current global dl0d. */
325 if (global_dl0d) {
326 /* XXX warn before breaking a (possibly) active L0-L2 chain */
327 diag_l0_close(global_dl0d);
328 diag_l0_del(global_dl0d);
329 }
330
331 global_dl0d = diag_l0_new(global_cfg.l0name);
332 if (!global_dl0d) {
333 printf("Error loading interface %s.\n", global_cfg.l0name);
334 }
335
336 return CMD_OK;
337}
338
339static enum cli_retval cmd_set_display(int argc, char **argv) {
340 if (argc > 1) {
341 if (strcasecmp(argv[1], "english") == 0) {
342 global_cfg.units = 1;
343 } else if (strcasecmp(argv[1], "metric") == 0) {
344 global_cfg.units = 0;
345 } else {
346 return CMD_USAGE;
347 }
348 } else {
349 printf("display: %s units\n", global_cfg.units?"english":"metric");
350 }
351
352 return CMD_OK;
353}
354
355static enum cli_retval cmd_set_speed(int argc, char **argv) {
356 if (argc > 1) {
357 if (strcmp(argv[1], "?") == 0) {
358 return CMD_USAGE;
359 }
360
361 global_cfg.speed = htoi(argv[1]);
362 }
363 printf("Connect speed: %u\n", global_cfg.speed);
364
365 return CMD_OK;
366}
367
368static enum cli_retval cmd_set_testerid(int argc, char **argv) {
369 if (argc > 1) {
370 int tmp;
371 if (strncmp(argv[1], "?", 1) == 0) {
372 return CMD_USAGE;
373 }
374 tmp = htoi(argv[1]);
375 if ( (tmp < 0) || (tmp > 0xff)) {
376 printf("testerid: must be between 0 and 0xff\n");
377 return CMD_FAILED;
378 }
379 global_cfg.src = (uint8_t) tmp;
380 }
381 printf("testerid: using 0x%02X\n", (unsigned) global_cfg.src);
382
383 return CMD_OK;
384}
385
386static enum cli_retval cmd_set_destaddr(int argc, char **argv) {
387 if (argc > 1) {
388 int tmp;
389 if (strncmp(argv[1], "?", 1) == 0) {
390 return CMD_USAGE;
391 }
392 tmp = htoi(argv[1]);
393 if ( (tmp < 0) || (tmp > 0xff)) {
394 printf("destaddr: must be between 0 and 0xff\n");
395 return CMD_FAILED;
396 }
397 global_cfg.tgt = (uint8_t) tmp;
398 }
399 printf("destaddr: using 0x%02X\n",
400 (unsigned) global_cfg.tgt);
401
402 return CMD_OK;
403}
404
405static enum cli_retval cmd_set_addrtype(int argc, char **argv) {
406 if (argc > 1) {
407 if (strncmp(argv[1], "func", 4) == 0) {
408 global_cfg.addrtype = 1;
409 } else if (strncmp(argv[1], "phys", 4) == 0) {
410 global_cfg.addrtype = 0;
411 } else {
412 return CMD_USAGE;
413 }
414 } else {
415 printf("addrtype: %s addressing\n",
416 global_cfg.addrtype ? "functional" : "physical");
417 }
418
419 return CMD_OK;
420}
421
422static enum cli_retval cmd_set_l2protocol(int argc, char **argv) {
423 if (argc > 1) {
424 int i, helping = 0, found = 0;
425 if (strcmp(argv[1], "?") == 0) {
426 helping = 1;
427 printf("L2 protocol: valid names are ");
428 }
429 for (i=0; l2proto_list[i] != NULL; i++) {
430 const struct diag_l2_proto *d2p=l2proto_list[i];
431 if (helping) {
432 printf("%s ", d2p->shortname);
433 continue;
434 }
435 if (strcasecmp(argv[1], d2p->shortname) == 0) {
436 found = 1;
437 global_cfg.L2idx = i;
438 global_cfg.L2proto = d2p->diag_l2_protocol;
439 break;
440 }
441 }
442 if (helping) {
443 printf("\n");
444 return CMD_USAGE;
445 }
446 if (!found) {
447 printf("l2protocol: invalid protocol %s\n", argv[1]);
448 printf("l2protocol: use \"set l2protocol ?\" to see list of protocols\n");
449 }
450 } else {
451 printf("l2protocol: Layer 2 protocol to use %s\n",
452 l2proto_list[global_cfg.L2idx]->shortname);
453 }
454 return CMD_OK;
455}
456
457static enum cli_retval cmd_set_l1protocol(int argc, char **argv) {
458 if (argc > 1) {
459 int i, helping = 0, found = 0;
460 if (strcmp(argv[1], "?") == 0) {
461 helping = 1;
462 printf("L1 protocol: valid names are ");
463 }
464 for (i=0; l1_names[i] != NULL; i++) {
465 if (helping && *l1_names[i]) {
466 printf("%s ", l1_names[i]);
467 } else if (strcasecmp(argv[1], l1_names[i]) == 0) {
468 global_cfg.L1proto = 1 << i;
469 found = 1;
470 }
471 }
472 if (helping) {
473 printf("\n");
474 return CMD_USAGE;
475 }
476 if (!found) {
477 printf("L1protocol: invalid protocol %s\n", argv[1]);
478 printf("l1protocol: use \"set l1protocol ?\" to see list of protocols\n");
479 }
480 return CMD_OK;
481 }
482
483 int offset;
484
485 for (offset=0; offset < 8; offset++) {
486 if (global_cfg.L1proto == (1 << offset)) {
487 break;
488 }
489 }
490 printf("l1protocol: Layer 1 (H/W) protocol to use %s\n",
491 l1_names[offset]);
492
493 return CMD_OK;
494}
495
496static enum cli_retval cmd_set_initmode(int argc, char **argv) {
497 if (argc > 1) {
498 int i, helping = 0, found = 0;
499 if (strcmp(argv[1], "?") == 0) {
500 helping = 1;
501 }
502 for (i=0; l2_initmodes[i] != NULL; i++) {
503 if (helping) {
504 printf("%s ", l2_initmodes[i]);
505 } else {
506 if (strcasecmp(argv[1], l2_initmodes[i]) == 0) {
507 found = 1;
508 global_cfg.initmode = i;
509 }
510 }
511 }
512 if (helping) {
513 printf("\n");
514 return CMD_USAGE;
515 }
516 if (!found) {
517 printf("initmode: invalid mode %s\n", argv[1]);
518 printf("initmode: use \"set initmode ?\" to see list of initmodes\n");
519 }
520 return CMD_OK;
521 }
522
523 printf("initmode: Initmode to use with above protocol is %s\n",
524 l2_initmodes[global_cfg.initmode]);
525
526 return CMD_OK;
527}
528
529static enum cli_retval cmd_set_help(int argc, char **argv) {
530 return cli_help_basic(argc, argv, set_cmd_table);
531}
532