| 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 - debug subcommand |
| 27 | */ |
| 28 | #include <stdio.h> |
| 29 | #include <string.h> |
| 30 | |
| 31 | #include "diag.h" |
| 32 | #include "diag_l0.h" |
| 33 | #include "diag_l1.h" |
| 34 | #include "diag_l2.h" |
| 35 | #include "diag_l3.h" |
| 36 | |
| 37 | #include "libcli.h" |
| 38 | |
| 39 | #include "scantool_cli.h" |
| 40 | |
| 41 | |
| 42 | enum debugflag_enum {OPEN=DIAG_DEBUG_OPEN, |
| 43 | CLOSE=DIAG_DEBUG_CLOSE, |
| 44 | READ=DIAG_DEBUG_READ, |
| 45 | WRITE=DIAG_DEBUG_WRITE, |
| 46 | IOCTL=DIAG_DEBUG_IOCTL, |
| 47 | PROTO=DIAG_DEBUG_PROTO, |
| 48 | INIT=DIAG_DEBUG_INIT, |
| 49 | DATA=DIAG_DEBUG_DATA, |
| 50 | TIMER=DIAG_DEBUG_TIMER, |
| 51 | NIL=0}; |
| 52 | |
| 53 | //declare an array of structs to associate debug flag masks with short description. |
| 54 | struct debugflags_descr { |
| 55 | enum debugflag_enum mask; |
| 56 | const char *descr; //associate short description for each flag. |
| 57 | const char *shortdescr; |
| 58 | }; |
| 59 | |
| 60 | static const struct debugflags_descr debugflags[] = { |
| 61 | {OPEN, "Open events","OPEN"}, |
| 62 | {CLOSE, "Close events","CLOSE"}, |
| 63 | {READ, "Read events","READ"}, |
| 64 | {WRITE, "Write events","WRITE"}, |
| 65 | {IOCTL, "Ioctl stuff (setspeed etc)","IOCTL"}, |
| 66 | {PROTO, "Protocol stuff","PROTO"}, |
| 67 | {INIT, "Init stuff","INIT"}, |
| 68 | {DATA, "Dump data if READ or WRITE","DATA"}, |
| 69 | {TIMER, "Timer stuff","TIMER"}, |
| 70 | {NIL, NULL, NULL} |
| 71 | }; |
| 72 | |
| 73 | static enum cli_retval cmd_debug_help(int argc, char **argv); |
| 74 | static enum cli_retval cmd_debug_show(int argc, char **argv); |
| 75 | |
| 76 | static enum cli_retval cmd_debug_cli(int argc, char **argv); |
| 77 | static enum cli_retval cmd_debug_l0(int argc, char **argv); |
| 78 | static enum cli_retval cmd_debug_l1(int argc, char **argv); |
| 79 | static enum cli_retval cmd_debug_l2(int argc, char **argv); |
| 80 | static enum cli_retval cmd_debug_l3(int argc, char **argv); |
| 81 | static enum cli_retval cmd_debug_all(int argc, char **argv); |
| 82 | static enum cli_retval cmd_debug_l0test(int argc, char **argv); |
| 83 | |
| 84 | const struct cmd_tbl_entry debug_cmd_table[] = { |
| 85 | { "help", "help [command]", "Gives help for a command", |
| 86 | cmd_debug_help, 0, NULL}, |
| 87 | { "?", "? [command]", "Gives help for a command", |
| 88 | cmd_debug_help, CLI_CMD_HIDDEN, NULL}, |
| 89 | |
| 90 | { "show", "show", "Shows current debug levels", |
| 91 | cmd_debug_show, 0, NULL}, |
| 92 | |
| 93 | { "l0", "l0 [val]", "Show/set Layer0 debug level", |
| 94 | cmd_debug_l0, 0, NULL}, |
| 95 | { "l1", "l1 [val]", "Show/set Layer1 debug level", |
| 96 | cmd_debug_l1, 0, NULL}, |
| 97 | { "l2", "l2 [val]", "Show/set Layer2 debug level", |
| 98 | cmd_debug_l2, 0, NULL}, |
| 99 | { "l3", "l3 [val]", "Show/set Layer3 debug level", |
| 100 | cmd_debug_l3, 0, NULL}, |
| 101 | { "cli", "cli [val]", "Show/set CLI debug level", |
| 102 | cmd_debug_cli, 0, NULL}, |
| 103 | { "all", "all [val]", "Show/set All layer debug level", |
| 104 | cmd_debug_all, 0, NULL}, |
| 105 | { "l0test", "l0test [testnum]", "Dumb interface tests. Disconnect from vehicle first !", |
| 106 | cmd_debug_l0test, 0, NULL}, |
| 107 | CLI_TBL_BUILTINS, |
| 108 | CLI_TBL_END |
| 109 | }; |
| 110 | |
| 111 | static enum cli_retval cmd_debug_help(int argc, char **argv) { |
| 112 | if (argc<2) { |
| 113 | printf("Debugging flags are set per level according to the values set in diag.h\n"); |
| 114 | printf("Setting [val] to -1 will enable all debug messages for that level.\n" |
| 115 | "Available flags:\n"); |
| 116 | int i; |
| 117 | for (i=0; debugflags[i].mask != NIL; i++) { |
| 118 | printf("\t0x%4X: %s\n", debugflags[i].mask, debugflags[i].descr); |
| 119 | } |
| 120 | } |
| 121 | return cli_help_basic(argc, argv, debug_cmd_table); |
| 122 | } |
| 123 | |
| 124 | |
| 125 | |
| 126 | static enum cli_retval cmd_debug_common( const char *txt, int *val, int argc, char **argv) { |
| 127 | int r; |
| 128 | int i; |
| 129 | |
| 130 | if ((argc ==2) && (argv[1][0]!='?')) { |
| 131 | //decode number unless it was ? |
| 132 | r = htoi(argv[1]); |
| 133 | *val = r; |
| 134 | } |
| 135 | |
| 136 | printf("%s debug is 0x%X: ", txt, *val); |
| 137 | for (i=0; debugflags[i].mask != NIL; i++) { |
| 138 | //check each flag and show what was enabled. |
| 139 | if (*val & debugflags[i].mask) { |
| 140 | printf("%s ", debugflags[i].shortdescr); |
| 141 | } |
| 142 | } |
| 143 | printf("\n"); |
| 144 | |
| 145 | return CMD_OK; |
| 146 | } |
| 147 | |
| 148 | static enum cli_retval cmd_debug_l0(int argc, char **argv) { |
| 149 | return cmd_debug_common("L0", &diag_l0_debug, argc, argv); |
| 150 | } |
| 151 | static enum cli_retval cmd_debug_l1(int argc, char **argv) { |
| 152 | return cmd_debug_common("L1", &diag_l1_debug, argc, argv); |
| 153 | } |
| 154 | static enum cli_retval cmd_debug_l2(int argc, char **argv) { |
| 155 | return cmd_debug_common("L2", &diag_l2_debug, argc, argv); |
| 156 | } |
| 157 | static enum cli_retval cmd_debug_l3(int argc, char **argv) { |
| 158 | return cmd_debug_common("L3", &diag_l3_debug, argc, argv); |
| 159 | } |
| 160 | static enum cli_retval cmd_debug_cli(int argc, char **argv) { |
| 161 | return cmd_debug_common("CLI", &diag_cli_debug, argc, argv); |
| 162 | //for now, value > 0x80 will enable all debugging info. |
| 163 | } |
| 164 | |
| 165 | static enum cli_retval cmd_debug_all(int argc, char **argv) { |
| 166 | int val; |
| 167 | |
| 168 | if (argc > 0) { |
| 169 | val = htoi(argv[1]); |
| 170 | diag_l0_debug = val; |
| 171 | diag_l1_debug = val; |
| 172 | diag_l2_debug = val; |
| 173 | diag_l3_debug = val; |
| 174 | diag_cli_debug = val; |
| 175 | } |
| 176 | return cmd_debug_show(1, NULL); |
| 177 | |
| 178 | return CMD_OK; |
| 179 | } |
| 180 | |
| 181 | |
| 182 | static enum cli_retval cmd_debug_show(UNUSED(int argc), UNUSED(char **argv)) { |
| 183 | /* int layer, val; */ |
| 184 | |
| 185 | printf("Debug values: L0 0x%X, L1 0x%X, L2 0x%X L3 0x%X CLI 0x%X\n", |
| 186 | diag_l0_debug, diag_l1_debug, diag_l2_debug, diag_l3_debug, |
| 187 | diag_cli_debug); |
| 188 | return CMD_OK; |
| 189 | } |
| 190 | |
| 191 | |
| 192 | //cmd_debug_l0test : run a variety of low-level |
| 193 | //tests, for dumb interfaces. Do not use while connected |
| 194 | //to a vehicle: this sends garbage data on the K-line which |
| 195 | //could interfere with ECUs, although very unlikely. |
| 196 | |
| 197 | static enum cli_retval cmd_debug_l0test(int argc, char **argv) { |
| 198 | #define MAX_L0TEST 14 |
| 199 | struct diag_l0_device *dl0d = global_dl0d; |
| 200 | unsigned int testnum=0; |
| 201 | |
| 202 | if ((argc <= 1) || (strcmp(argv[1], "?") == 0) || (sscanf(argv[1],"%u", &testnum) != 1)) { |
| 203 | printf("usage: %s [testnum], where testnum is a number between 1 and %d.\n", argv[0], MAX_L0TEST); |
| 204 | printf("you must have done \"set interface dumbt [port]\" and \"set dumbopts\" before proceding.\n"); |
| 205 | |
| 206 | printf("Available tests:\n" |
| 207 | "\t1 : slow pulse TXD (K) with diag_tty_break.\n" |
| 208 | "\t2 : fast pulse TXD (K) : send 0x55 @ 10400bps, 5ms interbyte (P4)\n" |
| 209 | "\t10: fast pulse TXD (K) : send 0x55 @ 15000bps, 5ms interbyte (P4)\n" |
| 210 | "\t3 : slow pulse RTS.\n" |
| 211 | "\t4 : slow pulse DTR.\n" |
| 212 | "\t5 : fast pulse TXD (K) with diag_tty_break.\n" |
| 213 | "\t6 : fast pulse TXD (K) with diag_tty_fastbreak.\n" |
| 214 | "\t13: simulate iso14230 fastinit with diag_tty_fastbreak.\n" |
| 215 | "\t7 : simple half duplex removal speed test (10400bps)\n" |
| 216 | "\t14: simple half duplex removal speed test (360bps)\n" |
| 217 | "\t8 : block half duplex removal speed test.\n" |
| 218 | "\t9 : read timeout accuracy check\n" |
| 219 | "\t11: half duplex incomplete read timeout test.\n" |
| 220 | "\t12: diag_tty_write() duration.\n"); |
| 221 | return CMD_OK; |
| 222 | } |
| 223 | if ((testnum < 1) || (testnum > MAX_L0TEST)) { |
| 224 | printf("Invalid test.\n"); |
| 225 | return CMD_USAGE; |
| 226 | } |
| 227 | |
| 228 | if (!dl0d) { |
| 229 | printf("No global L0. Please select + conf L0 first\n"); |
| 230 | return CMD_FAILED; |
| 231 | } |
| 232 | |
| 233 | if (strcmp(dl0d->dl0->shortname, "DUMBT") != 0) { |
| 234 | printf("Wrong global L0, please set to DUMBT\n"); |
| 235 | return CMD_FAILED; |
| 236 | } |
| 237 | |
| 238 | printf("Trying test %u...\n", testnum); |
| 239 | |
| 240 | // I think the easiest way to pass on "testnum" on to diag_l0_dumbtest.c is |
| 241 | // to pretend testnum is an L1protocol. Then we can use diag_l2_open to start the |
| 242 | // test. |
| 243 | |
| 244 | (void) diag_l2_open(dl0d, (int) testnum); |
| 245 | |
| 246 | //We don't need to _close anything since DUMBT is designed to "fail", i.e. |
| 247 | //return no new dl0d, etc. |
| 248 | return CMD_OK; |
| 249 | |
| 250 | |
| 251 | } |
| 252 | |