BOROSOFTWAREAll work →
scantool/diag_l0_elm.c 1252 lines
1/*
2 * freediag - Vehicle Diagnostic Utility
3 *
4 * (c) 2011-2016 fenugrec
5 * Diag, Layer 0, interface for Scantool.net's ELM32x Interface
6 *
7 * This is meant to support ELM323 & 327 devices; clones and originals.
8 * COM speed is "autodetected" (it tries 38400, 9600 and 115200bps) but can also be
9 * manually specified.
10 *
11 * ELM interfaces are particular in that they handle the header bytes + checksum internally.
12 * Data is transferred in ASCII hex format, i.e. 0x46 0xFE is sent and received as "46FE"
13 * This could be modified by enabling the "packed data" mode but I think ELM327 devices
14 * don't support that, and clones are equally hopeless.
15 *
16 * The ELM327 has non-volatile settings; this will require special treatment. Not
17 * completely implemented at the moment.
18
19 * Note concerning non-volatile settings : it appears only these are stored to the EEPROM:
20 * -327: AT SP (set protocol)
21 * -327: PP 0C (custom baudrate)
22 * -323: these have no EEPROM so "ATZ" should really reset all to default
23 *
24 *
25 * Problems :
26 * * _recv() doesn't check if a good prompt '>' was received at the end
27 * * every time _open() is called it goes through the whole (long) init sequence
28 * * responses from multiple ECUs probably won't work
29 *
30 * Incomplete list of commands not supported by clones : {FI, SI, BD, KW}
31 */
32
33#include <assert.h>
34#include <stdio.h>
35#include <stdint.h>
36#include <stdlib.h>
37#include <string.h>
38
39#include "diag.h"
40#include "diag_cfg.h"
41#include "diag_os.h"
42#include "diag_err.h"
43#include "diag_tty.h"
44#include "diag_l0.h"
45#include "diag_l1.h"
46
47
48#define ELM_BUFSIZE 1000 //fit even max-length iso14230 frames, at 3 ASCII chars per byte.
49#define ELM_SLOWNESS 100 //Add this many ms to read timeouts, because ELMs are sloooow
50#define ELM_PURGETIME 400 //Time to wait (ms) for a response to "ATI" command
51
52struct elm_device {
53 int protocol; //current L1 protocol
54
55 int elmflags; //see defines below
56
57 struct cfgi port;
58 struct cfgi speed; //Host <-> ELM comms
59
60 struct diag_serial_settings serial;
61 ttyp *tty_int; /** handle for tty stuff */
62
63 uint8_t kb1, kb2; // key bytes from 5 baud init
64 uint8_t atsh[3]; // current header setting for ISO9141
65 struct diag_msg *wm; // custom wakeup message, if set
66};
67
68#define CFGSPEED_DESCR "Host <-> ELM comm speed (bps)"
69#define CFGSPEED_SHORTN "elmspeed"
70
71
72//flags for elmflags; set either 323_BASIC or 327_BASIC but not both;
73// _CLONE can be set in addition to the basic type
74#define ELM_323_BASIC 1 //device type is 323
75#define ELM_327_BASIC 2 //device type is 327
76#define ELM_32x_CLONE 4 //device is a clone; some commands will not be supported
77#define ELM_INITDONE 0x10 //set when "BUS INIT" has happened. This is important for clones.
78
79
80// possible error messages returned by the ELM IC
81static const char *elm323_errors[] = {"BUS BUSY", "FB ERROR", "DATA ERROR", "<DATA ERROR", "NO DATA", "?", NULL};
82
83static const char *elm327_errors[] = {"BUS BUSY", "FB ERROR", "DATA ERROR", "<DATA ERROR", "NO DATA", "?",
84 "ACT ALERT", "BUFFER FULL", "BUS ERROR", "CAN ERROR", "LP ALERT",
85 "LV RESET", "<RX ERROR", "STOPPED", "UNABLE TO CONNECT", "ERR", NULL};
86
87/* authentic VS clone identification strings.
88 * I know of no elm323 clones. 327 clones may not support some commands (atfi, atsi, atkw) and thus need fallback methods.
89 * version strings should be ordered to test the longer strings first, e.g. '1.4a' before '1.4', as long
90 * as we use strstr() to match against the response.
91 */
92static const char *elm323_official[] = {"2.0",NULL}; //authentic 323 firmware versions, possibly incomplete list
93static const char *elm323_clones[] = {NULL}; //known cloned versions
94static const char *elm327_official[] = {"1.0a", "1.0", "1.1", "1.2a", "1.2", "1.3a", "1.3", "1.4b", "2.0", NULL};
95static const char *elm327_clones[] = {"1.4a", "1.4", "1.5a", "1.5", "2.1", NULL};
96
97// baud rates for host to elm32x communication. Start with user-specified speed, then try common values
98#define ELM_CUSTOMSPEED ((unsigned) -1)
99static const unsigned elm_speeds[] = {ELM_CUSTOMSPEED, 38400, 9600, 115200, 0};
100
101
102extern const struct diag_l0 diag_l0_elm;
103
104static int elm_send(struct diag_l0_device *dl0d, const void *data, size_t len);
105
106static int elm_sendcmd(struct diag_l0_device *dl0d,
107 const uint8_t *data, size_t len, unsigned int timeout, uint8_t *resp);
108
109static int elm_purge(struct diag_l0_device *dl0d);
110
111static void elm_parse_cr(uint8_t *data, int len); //change 0x0A to 0x0D
112static void elm_close(struct diag_l0_device *dl0d);
113
114/*
115 * Init must be callable even if no physical interface is
116 * present, it's just here for the code here to initialise its
117 * variables etc
118 */
119static int elm_init(void) {
120 static int elm_initdone=0;
121
122 if (elm_initdone) {
123 return 0;
124 }
125
126 elm_initdone = 1;
127 return 0;
128}
129
130int elm_new(struct diag_l0_device *dl0d) {
131 struct elm_device *dev;
132 int rv;
133
134 assert(dl0d);
135
136 rv = diag_calloc(&dev, 1);
137 if (rv != 0) {
138 return diag_ifwderr(rv);
139 }
140
141 dl0d->l0_int = dev;
142
143 rv = diag_cfgn_tty(&dev->port);
144 if (rv != 0) {
145 free(dev);
146 return diag_ifwderr(rv);
147 }
148
149 rv = diag_cfgn_int(&dev->speed, 38400, 38400);
150 if (rv != 0) {
151 diag_cfg_clear(&dev->port);
152 free(dev);
153 return diag_ifwderr(rv);
154 }
155 dev->speed.descr = CFGSPEED_DESCR;
156 dev->speed.shortname = CFGSPEED_SHORTN;
157
158 dev->port.next = &dev->speed;
159 dev->speed.next = NULL;
160
161 return 0;
162}
163
164struct cfgi *elm_getcfg(struct diag_l0_device *dl0d) {
165 struct elm_device *dev;
166 if (dl0d == NULL) {
167 return diag_pseterr(DIAG_ERR_BADCFG);
168 }
169
170 dev = dl0d->l0_int;
171 return &dev->port;
172}
173
174void elm_del(struct diag_l0_device *dl0d) {
175 struct elm_device *dev;
176
177 assert(dl0d);
178
179 dev = dl0d->l0_int;
180 if (!dev) {
181 return;
182 }
183
184 diag_cfg_clear(&dev->port);
185 diag_cfg_clear(&dev->speed);
186 if (dev->wm != NULL) {
187 diag_freemsg(dev->wm);
188 }
189 free(dev);
190 return;
191}
192
193
194static void elm_close(struct diag_l0_device *dl0d) {
195 uint8_t buf[]="ATPC\x0D";
196 struct elm_device *dev;
197
198 assert(dl0d != NULL);
199
200 if (dl0d->opened) {
201 elm_sendcmd(dl0d, buf, 5, 500, NULL); //close protocol. So clean !
202 }
203
204 dev = (struct elm_device *)dl0d->l0_int;
205
206 /* If debugging, print to stderr */
207 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_CLOSE, DIAG_DBGLEVEL_V,
208 FLFMT "link %p closing\n", FL, (void *)dl0d);
209
210 diag_tty_close(dev->tty_int);
211 dev->tty_int = NULL;
212 dl0d->opened = 0;
213
214 return;
215}
216
217
218//elm_parse_errors : look for known error messages in the reply.
219// return any match or NULL if nothing found.
220// data[] must be \0-terminated !
221static const char *elm_parse_errors(struct diag_l0_device *dl0d, uint8_t *data) {
222 struct elm_device *dev;
223 const char **elm_errors; //just used to select between the 2 error lists
224 int i;
225
226 dev = (struct elm_device *) dl0d->l0_int;
227
228 //pick the right set of error messages. Although we could just systematically
229 //use the vaster ELM327 set of error messages...
230
231 if (dev->elmflags & ELM_323_BASIC) {
232 elm_errors=elm323_errors;
233 } else {
234 elm_errors = elm327_errors;
235 }
236
237 for (i=0; elm_errors[i]; i++) {
238 if (strstr((char *)data, elm_errors[i])) {
239 //we found an error msg, return it.
240 return elm_errors[i];
241 }
242 }
243 return NULL;
244}
245
246//Send a command to ELM device and make sure no error occured. Data is passed on directly as a string;
247//caller must make sure the string is \r-terminated , i.e. 0x0D-terminated.
248//Sending 0A after 0D will cause ELM to interrupt what it's doing to "process" 0A, resulting in a
249//failure.
250//This func should not be used for commands that elicit a data response (i.e. all data destined to the OBD bus,
251//hence not prefixed by "AT"). Response is dumped in *resp (0-terminated) for optional analysis by caller; *resp must be ELM_BUFSIZE long.
252//returns 0 if (prompt_good) && ("OK" found anywhere in the response) && (no known error message was present) ||
253// (prompt_good && ATZ or ATKW command was sent) , since response doesn't contain "OK" for ATZ or ATKW.
254//elm_sendcmd should not be called from outside diag_l0_elm.c.
255static int elm_sendcmd(struct diag_l0_device *dl0d, const uint8_t *data, size_t len, unsigned int timeout, uint8_t *resp) {
256 //note : we better not request (len == (size_t) -1) bytes ! The casts between ssize_t and size_t are
257 // "muddy" in here
258 //ssize_t xferd;
259 int rv;
260 uint8_t ebuf[ELM_BUFSIZE]; //local buffer if caller provides none.
261 uint8_t *buf;
262 struct elm_device *dev;
263 const char *err_str; //hold a possible error message
264
265 dev = (struct elm_device *)dl0d->l0_int;
266 //we need access to elm_device to access .elmflags
267
268 if (resp == NULL) {
269 buf=ebuf; //use local buffer
270 } else {
271 buf = resp; // or caller-provided buffer
272 }
273
274 if (!len) {
275 return diag_iseterr(DIAG_ERR_BADLEN);
276 }
277 if (!dev) {
278 return diag_iseterr(DIAG_ERR_BADFD);
279 }
280
281 if (data[len-1] != 0x0D) {
282 //Last byte is not a carriage return, this would die.
283 fprintf(stderr, FLFMT "elm_sendcmd: non-terminated command : %.*s\n", FL, (int) len, (char *) data);
284 //the %.*s is pure magic : limits the string length to len, even if the string is not null-terminated.
285 return diag_iseterr(DIAG_ERR_GENERAL);
286 }
287 diag_tty_iflush(dev->tty_int); //currently the code often "forgets" data in the input buffer, especially if the previous
288 //transaction failed. Flushing the input increases the odds of not crashing soon
289
290 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_WRITE, DIAG_DBGLEVEL_V,
291 FLFMT "elm_sendcmd: %.*s\n", FL, (int) len-1, (char *)data);
292
293 rv = diag_tty_write(dev->tty_int, data, len);
294 if (rv != (int) len) { //XXX danger ! evil cast
295 fprintf(stderr, FLFMT "elm_sendcmd: write error\n", FL);
296 return diag_iseterr(DIAG_ERR_GENERAL);
297 }
298
299 //next, receive ELM response, within {ms} delay.
300
301 rv=diag_tty_read(dev->tty_int, buf, ELM_BUFSIZE-1, timeout); //rv=# bytes read
302
303 if (rv<1) {
304 //no data or error
305 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_WRITE, DIAG_DBGLEVEL_V,
306 FLFMT "ELM did not respond\n", FL);
307
308 return diag_iseterr(DIAG_ERR_GENERAL);
309 }
310
311 elm_parse_cr(buf, rv); //debug output is prettier with this
312 DIAG_DBGMDATA(diag_l0_debug, DIAG_DEBUG_READ, DIAG_DBGLEVEL_V, buf, rv,
313 FLFMT "received %d bytes (%.*s\n); hex: ", FL, rv, rv, (char *)buf);
314
315 buf[rv]=0; //terminate string
316 if (buf[rv-1] != '>') {
317 //if last character isn't the input prompt, there is a problem
318 fprintf(stderr, FLFMT "ELM not ready (no prompt received): %s\nhex: ", FL, buf);
319 diag_data_dump(stderr, buf, rv);
320 fprintf(stderr, "\n");
321 return diag_iseterr(DIAG_ERR_GENERAL);
322 }
323 //At this point we got a prompt but there may have been an error message.
324 //There is some ambiguity in the ELM datasheets on the exact format of the replies.
325 //1) the prompt character '>' is always alone on its line;
326 //2) depending on some parameters, it may be preceded by 0D or 0D 0A
327 //3) some errors ( "<DATA ERROR" and "<RX ERROR" ) can be appended after
328 //a reply; others should be at the beginning of the response (alone on a line)
329
330 //ex. of good reply : "41 00 00 \r>", bad reply :"NO DATA\r>"
331 //let's just use strstr() to find occurences for each known error.
332 //it'll take a while but speed isn't normally critical when sending commands
333
334 err_str = elm_parse_errors(dl0d, buf);
335
336 if (err_str != NULL) {
337 fprintf(stderr, FLFMT "ELM returned error : %s\n", FL, err_str);
338 return diag_iseterr(DIAG_ERR_GENERAL);
339 }
340
341 //check if we either 1)got a positive response "OK"
342 //2)were sending ATZ (special case hack, it doesn't answer "OK")
343 if ((strstr((char *)buf, "OK") != NULL) ||
344 (strstr((char *)data, "ATKW") != NULL) ||
345 (strstr((char *)data, "ATZ") != NULL)) {
346 return 0;
347 }
348
349 fprintf(stderr, FLFMT "Response not recognized ! Report this ! Got: \n", FL);
350 diag_data_dump(stderr, buf, rv);
351 fprintf(stderr, "\n");
352 return diag_iseterr(DIAG_ERR_GENERAL);
353
354}
355/*
356 * Open the diagnostic device
357 * ELM settings used : no echo (E0), headers on (H1), linefeeds off (L0), mem off (M0)
358 */
359static int elm_open(struct diag_l0_device *dl0d, int iProtocol) {
360 int i,rv;
361 struct elm_device *dev;
362 struct diag_serial_settings sset;
363 const uint8_t *buf;
364 uint8_t rxbuf[ELM_BUFSIZE];
365
366 const char **elm_official;
367 const char **elm_clones; //point to elm323_ or elm327_ clone and official version string lists
368
369 assert(dl0d);
370 dev = dl0d->l0_int;
371
372 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V,
373 FLFMT "open port %s L1proto %d\n",
374 FL, dev->port.val.str, iProtocol);
375
376 elm_init();
377
378 //sending ATZ to elm will wipe out current header setting
379 dev->atsh[0]=0; dev->atsh[1]=0; dev->atsh[2]=0;
380
381 //throw away previous wakeup message setting, if any
382 if (dev->wm != NULL) {
383 diag_freemsg(dev->wm);
384 }
385 dev->wm = NULL;
386
387 /* try to open TTY */
388 dev->tty_int = diag_tty_open(dev->port.val.str);
389 if (dev->tty_int == NULL) {
390 return diag_iseterr(DIAG_ERR_GENERAL);
391 }
392 dev->protocol = iProtocol;
393
394 //try sending a command to elm327 at each possible speed until we get a response
395 sset.databits = diag_databits_8;
396 sset.stopbits = diag_stopbits_1;
397 sset.parflag = diag_par_n;
398 for (i=0; elm_speeds[i]; i++) {
399 sset.speed = elm_speeds[i];
400
401 // skip if custom speed was already tried:
402 if (sset.speed == (unsigned) dev->speed.val.i) {
403 continue;
404 }
405
406 if (sset.speed == ELM_CUSTOMSPEED) {
407 //magic flag to retrieve custom speed
408 sset.speed = (unsigned) dev->speed.val.i;
409 }
410 fprintf(stderr, FLFMT "Sending ATI to ELM32x at %u...\n", FL, sset.speed);
411
412 dev->serial = sset;
413
414 if ((rv=diag_tty_setup(dev->tty_int, &sset))) {
415 fprintf(stderr, FLFMT "Error setting %u;8N1 on %s\n",
416 FL, sset.speed, dev->port.val.str);
417 elm_close(dl0d);
418 return diag_ifwderr(rv);
419 }
420
421 diag_tty_iflush(dev->tty_int); /* Flush unread input */
422
423 //At this stage, the ELM has possibly been powered up for a while;
424 //it may have an unfinished command / garbage in its input buffer. We
425 //need to clear that before sending the real ATZ ==> ATI is quick and safe; elm_purge does this.
426
427 dev->elmflags=0; //we know nothing yet
428
429 rv=elm_purge(dl0d);
430 //if rv=0, we got a prompt so we know speed is set properly.
431 if (rv == 0) {
432 break;
433 }
434 }
435 if (elm_speeds[i]==0) {
436 fprintf(stderr, FLFMT "No response from ELM323/ELM327. Verify connection to ELM\n", FL);
437 elm_close(dl0d);
438 return diag_iseterr(DIAG_ERR_BADIFADAPTER);
439 }
440
441 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V,
442 FLFMT "elm_open : sending ATZ...\n", FL);
443
444 //the command "ATZ" causes a full reset and the ELM replies with
445 //a string like "ELM32x vX.Xx\n>"
446
447 buf=(uint8_t *)"ATZ\x0D";
448 rv=elm_sendcmd(dl0d, buf, 4, 2000, rxbuf);
449 if (rv) {
450 fprintf(stderr, FLFMT "elm_open : ATZ failed !\n", FL);
451 elm_close(dl0d);
452 return diag_iseterr(DIAG_ERR_BADIFADAPTER);
453 }
454
455 //Correct prompt received; try to identify device.
456 // 1) guess 323 vs 327
457 if (strstr((char *)rxbuf, "ELM323")!=NULL) {
458 dev->elmflags |= ELM_323_BASIC;
459 elm_official=elm323_official;
460 elm_clones=elm323_clones;
461 } else if (strstr((char *)rxbuf, "ELM327")!=NULL) {
462 dev->elmflags |= ELM_327_BASIC;
463 elm_official=elm327_official;
464 elm_clones=elm327_clones;
465 } else {
466 fprintf(stderr, FLFMT "no valid version string !! Report this !. Got:\n%s\n", FL, rxbuf);
467 //no point in continuing...
468 elm_close(dl0d);
469 return diag_iseterr(DIAG_ERR_BADIFADAPTER);
470 }
471 // 2) identify valid VS clone devices.
472 rv=0; // temp "device identified" flag
473 for (i=0; elm_official[i]; i++) {
474 if (strstr((char *)rxbuf, elm_official[i])) {
475 printf("Official ELM found, v%s\n", elm_official[i]);
476 rv=1;
477 break;
478 }
479 }
480
481 if (rv==0) {
482 for (i=0; elm_clones[i]; i++) {
483 if (strstr((char *)rxbuf, elm_clones[i])) {
484 printf("Clone ELM found, v%s. Expect inferior performance\n", elm_clones[i]);
485 dev->elmflags |= ELM_32x_CLONE;
486 rv=1;
487 break;
488 }
489 }
490 }
491
492 if (rv==0) {
493 //still not identified : assume clone.
494 dev->elmflags |= ELM_32x_CLONE;
495 printf("ELM version not recognized! Please report this ! Response was:\n%s\n", rxbuf);
496 }
497
498 if ((dev->elmflags & ELM_323_BASIC) && (dev->elmflags & ELM_32x_CLONE)) {
499 printf("A 323 clone ? Report this !\n");
500 }
501
502
503 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V,
504 FLFMT "ELM reset success, elmflags=%#x\n", FL, dev->elmflags);
505
506 dl0d->opened = 1; //TODO : use this flag to skip the clone detection next time
507
508 //now send "ATE0\n" command to disable echo.
509 buf=(uint8_t *)"ATE0\x0D";
510 if (elm_sendcmd(dl0d, buf, 5, 500, NULL)) {
511 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V,
512 FLFMT "sending \"ATE0\" failed\n", FL);
513
514 elm_close(dl0d);
515 return diag_iseterr(DIAG_ERR_BADIFADAPTER);
516 }
517
518 //ATL0 : disable linefeeds
519 buf=(uint8_t *)"ATL0\x0D";
520 if (elm_sendcmd(dl0d, buf, 5, 500, NULL)) {
521 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V,
522 FLFMT "sending \"ATL0\" failed\n", FL);
523
524 elm_close(dl0d);
525 return diag_iseterr(DIAG_ERR_BADIFADAPTER);
526 }
527
528 //ATH1 : always show header bytes
529 buf=(uint8_t *)"ATH1\x0D";
530 if (elm_sendcmd(dl0d, buf, 5, 500, NULL)) {
531 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V,
532 FLFMT "sending \"ATH1\" failed\n", FL);
533
534 elm_close(dl0d);
535 return diag_iseterr(DIAG_ERR_BADIFADAPTER);
536 }
537
538 //for elm327 only: disable memory
539 if (dev->elmflags & ELM_327_BASIC) {
540 buf=(uint8_t *)"ATM0\x0D";
541 if (elm_sendcmd(dl0d, buf, 5, 500, NULL)) {
542 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V,
543 FLFMT "sending \"ATM0\" failed\n", FL);
544
545 elm_close(dl0d);
546 return diag_iseterr(DIAG_ERR_BADIFADAPTER);
547 }
548 }
549
550 //check if proto is really supported (323 supports only 9141 and 14230)
551 if ((dev->elmflags & ELM_323_BASIC) &&
552 ((iProtocol != DIAG_L1_ISO9141) &&
553 (iProtocol != DIAG_L1_ISO14230))) {
554 return diag_iseterr(DIAG_ERR_PROTO_NOTSUPP);
555 }
556
557 //if 327, set proto when possible; we won't if 14230, because init type (fast vs slow) isn't decided yet
558 // CAN is also not implemented here
559 buf=NULL;
560 if (dev->elmflags & ELM_327_BASIC) {
561 switch (iProtocol) {
562 case DIAG_L1_J1850_PWM:
563 buf=(uint8_t *)"ATTP1\x0D";
564 break;
565 case DIAG_L1_J1850_VPW:
566 buf=(uint8_t *)"ATTP2\x0D";
567 break;
568 case DIAG_L1_ISO9141:
569 buf=(uint8_t *)"ATTP3\x0D";
570 break;
571 default:
572 buf=NULL;
573 }
574 }
575
576 if (buf != NULL) {
577 if (elm_sendcmd(dl0d, buf, 6, 500, NULL)) {
578 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V,
579 FLFMT "sending \"ATTPx\" failed\n", FL);
580
581 elm_close(dl0d);
582 return diag_iseterr(DIAG_ERR_BADIFADAPTER);
583 }
584 }
585
586
587 //at this point : ELM is ready for further ops
588 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V,
589 FLFMT "ELM ready.\n", FL);
590
591 return 0;
592}
593
594
595/*
596 * Fastinit & slowinit:
597 * ELM should manage slow/fast init automatically... Until the code from levels L1 and up can deal with
598 * this, the bus will manually be initialized.
599 * Only callable internally. Not for export !!
600 * Unsupported by some (all?) clones !! (they handle the init internally, on demand)
601 */
602static int elm_fastinit(struct diag_l0_device *dl0d) {
603 uint8_t *cmds= (uint8_t *) "ATFI\x0D";
604
605 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_PROTO, DIAG_DBGLEVEL_V,
606 FLFMT "ELM forced fastinit...\n", FL);
607
608 //send command with 1000ms timeout (guessing)
609 if (elm_sendcmd(dl0d, cmds, 5, 1000, NULL)) {
610 fprintf(stderr, FLFMT "Command ATFI failed\n", FL);
611 return diag_iseterr(DIAG_ERR_GENERAL);
612 }
613 return 0;
614}
615
616
617static int elm_slowinit(struct diag_l0_device *dl0d) {
618 uint8_t *cmds=(uint8_t *)"ATSI\x0D";
619
620 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_PROTO, DIAG_DBGLEVEL_V,
621 FLFMT "ELM forced slowinit...\n", FL);
622
623 //huge timeout of 2.8s. Not sure if this is adequate
624 if (elm_sendcmd(dl0d, cmds, 5, 2800, NULL)) {
625 fprintf(stderr, FLFMT "Command ATSI failed\n", FL);
626 return diag_iseterr(DIAG_ERR_GENERAL);
627 }
628 return 0;
629
630}
631
632//elm_bogusinit : send a 01 00 request to force ELM to init bus.
633//Only used to force clones to establish a connection... hack-grade because it assumes all ECUs support this.
634// non-OBD ECUs may not work with this. ELM clones suck...
635// TODO : add argument to allow either a 01 00 request (SID1 PID0, J1979) or 3E (iso14230 TesterPresent) request to force init.
636static int elm_bogusinit(struct diag_l0_device *dl0d, unsigned int timeout) {
637 int rv;
638 struct elm_device *dev;
639 uint8_t buf[MAXRBUF];
640 uint8_t generic_data[] = {0x01,0x00}; // J1979 request only
641 uint8_t iso9141_data[] = {0x68,0x6a,0xf1,0x01,0x00}; // with ISO9141 hdr
642 const char *err_str;
643
644 dev = dl0d->l0_int;
645 if (dev->protocol & DIAG_L1_ISO9141) {
646 rv = elm_send(dl0d, iso9141_data, 5);
647 } else {
648 rv = elm_send(dl0d, generic_data, 2);
649 }
650 if (rv) {
651 return diag_ifwderr(rv);
652 }
653
654 // receive everything; we're hoping for a prompt at the end and no error message.
655 rv=diag_tty_read(dev->tty_int, buf, MAXRBUF-5, timeout); //rv=# bytes read
656 elm_parse_cr(buf, rv);
657 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_READ, DIAG_DBGLEVEL_V,
658 FLFMT "received %d bytes: %.*s: ",
659 FL, rv, rv, buf);
660
661 if (rv<1) {
662 //no data or error
663 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_WRITE, DIAG_DBGLEVEL_V,
664 FLFMT "ELM did not respond\n", FL);
665
666 return diag_iseterr(DIAG_ERR_GENERAL);
667 }
668 buf[rv]=0; //terminate string
669 if (buf[rv-1] != '>') {
670 //if last character isn't the input prompt, there is a problem
671 fprintf(stderr, FLFMT "ELM not ready (no prompt received): %s\n", FL, buf);
672 return diag_iseterr(DIAG_ERR_GENERAL);
673 }
674
675 err_str = elm_parse_errors(dl0d, buf);
676
677 if (err_str != NULL) {
678 fprintf(stderr, FLFMT "got error while forcing init: %s\n", FL, err_str);
679 return diag_iseterr(DIAG_ERR_GENERAL);
680 }
681
682 return 0;
683
684}
685
686// set wakeup message
687static int elm_updatewm(struct diag_l0_device *dl0d) {
688 struct elm_device *dev;
689 uint8_t wm[18];
690
691 dev = (struct elm_device *)dl0d->l0_int;
692 sprintf((char *) wm, "ATWM %02X %02X %02X %02X\x0D", dev->wm->data[0], dev->wm->data[1], dev->wm->data[2], dev->wm->data[3]);
693 if (elm_sendcmd(dl0d, wm, 17, 500, NULL) < 0) {
694 fprintf(stderr, FLFMT "elm_updatewm: ATWM failed\n", FL);
695 return diag_iseterr(DIAG_ERR_GENERAL);
696 }
697 return 0;
698}
699
700/*
701 * Do manual wakeup on the bus, if supported
702 * ret 0 if ok
703 */
704static int elm_initbus(struct diag_l0_device *dl0d, struct diag_l1_initbus_args *in) {
705 const uint8_t *buf;
706 int rv = DIAG_ERR_INIT_NOTSUPP;
707 unsigned int timeout=0; //for bogus init
708
709 struct elm_device *dev;
710
711 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_WRITE, DIAG_DBGLEVEL_V,
712 FLFMT "ELM initbus type %d\n", FL, in->type);
713
714 dev = (struct elm_device *)dl0d->l0_int;
715
716 if (!dev) {
717 return diag_iseterr(rv);
718 }
719
720 if (dev->elmflags & ELM_32x_CLONE) {
721 printf("Note : explicit bus init not available on clones. Errors here are ignored.\n");
722 dev->elmflags &= ~ELM_INITDONE; //clear flag
723 }
724
725 switch (in->type) {
726 case DIAG_L1_INITBUS_FAST: {
727 uint8_t fmt, src, tgt;
728 uint8_t setproto[]="ATTP5\x0D";
729 uint8_t sethdr[15]; //format: "ATSH xx yy zz\x0D"
730
731 fmt=(in->physaddr)? 0x81:0xC1;
732 src=in->testerid;
733 tgt=in->addr;
734 if (dev->elmflags & ELM_327_BASIC) {
735 //only needed for 327s (ATTP not available on ELM323)
736 //set proto; We assume iso14230 since it's a fast init
737 rv=elm_sendcmd(dl0d, setproto, 6, 500, NULL);
738 if (rv < 0) {
739 break;
740 }
741 }
742
743 // set wakeup message if applicable
744 if (dev->wm != NULL) {
745 rv=elm_updatewm(dl0d);
746 if (rv < 0) {
747 return rv;
748 }
749 }
750
751 sprintf((char *) sethdr, "ATSH %02X %02X %02X\x0D", fmt, tgt, src);
752 rv=elm_sendcmd(dl0d, sethdr, 14, 500, NULL);
753
754 //explicit init is not supported by clones, they wait for the first OBD request...
755 if ((dev->elmflags & ELM_32x_CLONE)==0) {
756 rv = elm_fastinit(dl0d);
757 if (!rv) {
758 dev->elmflags |= ELM_INITDONE;
759 }
760 } //if explicit init failed we'll try a bogus init anyway
761 timeout=1500;
762 } //case fastinit
763 break; //case fastinit
764 case DIAG_L1_INITBUS_5BAUD:
765 //if 327 : set proto first
766 if (dev->elmflags & ELM_327_BASIC) {
767 if (dev->protocol & DIAG_L1_ISO9141) {
768 buf=(uint8_t *) "ATTP3\x0D";
769 } else if (dev->protocol & DIAG_L1_ISO14230) {
770 buf=(uint8_t *) "ATTP4\x0D";
771 } else { // illegal combination !
772 return diag_iseterr(
773 DIAG_ERR_INIT_NOTSUPP);
774 }
775
776 rv=elm_sendcmd(dl0d, buf, 6, 500, NULL);
777 if (rv < 0) {
778 break;
779 }
780 }
781
782 // set wakeup message if applicable
783 if (dev->wm != NULL) {
784 rv=elm_updatewm(dl0d);
785 if (rv < 0) {
786 return rv;
787 }
788 }
789
790 //set init address
791 if ((dev->elmflags & ELM_323_BASIC) && (in->addr != 0x33)) {
792 fprintf(stderr, FLFMT "elm_initbus: ELM323 doesn't support target address %02X", FL, in->addr);
793 return diag_iseterr(DIAG_ERR_GENERAL);
794 }
795 if (in->addr != 0x33) {
796 uint8_t iia[15];
797 sprintf((char *) iia, "ATIIA %02X\x0D", in->addr);
798 rv=elm_sendcmd(dl0d, iia, 9, 500, NULL);
799 if (rv < 0) {
800 fprintf(stderr, FLFMT "elm_initbus: ATIIA %02X failed\n", FL, in->addr);
801 return diag_iseterr(DIAG_ERR_GENERAL);
802 }
803 }
804
805 //accept nonstandard keybytes during init
806 if (dev->elmflags & ELM_327_BASIC) {
807 buf=(uint8_t *) "ATKW0\x0D";
808 rv=elm_sendcmd(dl0d, buf, 6, 500, NULL);
809 if (rv < 0) {
810 fprintf(stderr,
811 FLFMT
812 "elm_initbus: ATKW0 failed, "
813 "continuing anyway\n",
814 FL);
815 }
816 }
817
818 //explicit init is not supported by clones
819 if ((dev->elmflags & ELM_32x_CLONE)==0) {
820 rv = elm_slowinit(dl0d);
821 if (!rv) {
822 dev->elmflags |= ELM_INITDONE;
823 }
824 }
825 timeout=4200; //slow init is slow !
826
827 //query elm for keybytes
828 dev->kb1 = 0; dev->kb2 = 0;
829 if (dev->elmflags & ELM_INITDONE) {
830 uint8_t rxbuf[ELM_BUFSIZE];
831 unsigned int kb1, kb2;
832
833 buf=(uint8_t *) "ATKW\x0D";
834 rv=elm_sendcmd(dl0d, buf, 5, 500, rxbuf);
835 if (rv < 0) {
836 fprintf(stderr, FLFMT "elm_initbus: ATKW failed, continuing anyway\n", FL);
837 // TODO: for clones without ATKW, can
838 // fall back to ATBD. If ATBD response
839 // starts with 06 addr 55 xx yy aa bb
840 // and aa=yy^0xff and bb=addr^0xff then
841 // xx and yy should be key bytes
842 rv = 0;
843 } else if (sscanf((char *)rxbuf, "1:%02X 2:%02X", &kb1, &kb2) == 2) {
844 dev->kb1 = kb1;
845 dev->kb2 = kb2;
846 in->kb1 = kb1;
847 in->kb2 = kb2;
848 } else {
849 fprintf(stderr, FLFMT "elm_initbus: ATKW failed, continuing anyway\n", FL);
850 rv = 0;
851 }
852 }
853
854 // enable receipt of >7 byte messages, if possible
855 if (dev->elmflags & ELM_INITDONE) {
856 buf=(uint8_t *) "ATAL\x0D";
857 rv=elm_sendcmd(dl0d, buf, 5, 500, NULL);
858 if (rv < 0) {
859 fprintf(stderr, FLFMT "elm_initbus: ATAL failed, continuing anyway\n", FL);
860 rv = 0;
861 }
862 }
863
864 break;
865 default:
866 rv = DIAG_ERR_INIT_NOTSUPP;
867 break;
868 }
869
870 if ((dev->elmflags & ELM_INITDONE)==0) {
871 // init not done, either because it's a clone (explicit init unsupported), or another reason.
872 // two choices : A) assume comms will be OBD compliant, so request "01 00" has to be supported
873 // B) tweak _recv() to skip the "BUS INIT: " line that ELM will send at the next request.
874 // A is easier for now...
875 // Note that since we don't check for "DIAG_ERR_INIT_NOTSUPP" here, we allow the ELM to (possibly)
876 // carry out an incorrect init. I can't see when this can be a problem.
877 // Note : clones suck
878 rv=elm_bogusinit(dl0d, timeout);
879 if (rv == 0) {
880 dev->elmflags |= ELM_INITDONE;
881 }
882 }
883
884 return rv? diag_iseterr(rv):0;
885
886}
887
888//elm_purge : sends ATI command and checks for a valid prompt. This is faster than ATZ.
889//use : if the ELM received garbage before ATI, ex.: "\xFF\xFFATI\r" it will just reject
890//the invalid command but still give a valid prompt.
891//Return 0 only if a valid prompt was received.
892static int elm_purge(struct diag_l0_device *dl0d) {
893 uint8_t buf[ELM_BUFSIZE] = "ATI\x0D";
894 int rv;
895 struct elm_device *dev = dl0d->l0_int;
896
897 if (diag_tty_write(dev->tty_int, buf, 4) != 4) {
898 fprintf(stderr, FLFMT "elm_purge : write error\n", FL);
899 return diag_iseterr(DIAG_ERR_GENERAL);
900 }
901 rv = diag_tty_read(dev->tty_int, buf, sizeof(buf), ELM_PURGETIME);
902 if (rv < 1) {
903 return DIAG_ERR_GENERAL;
904 }
905
906 if (buf[rv-1] != '>') {
907 DIAG_DBGMDATA(diag_l0_debug, DIAG_DEBUG_CLOSE, DIAG_DBGLEVEL_V,
908 buf, rv, FLFMT "elm_purge: got ", FL);
909
910 return DIAG_ERR_GENERAL;
911 }
912 return 0;
913}
914
915/*
916 * Send a load of data
917 *
918 * Directly send hex-ASCII; exit without receiving response.
919 * Upper levels don't append 0x0D / 0x0A at the end, we take care of adding the required 0x0D.
920 * "AT"* commands sould not be sent with this function.
921 * Returns 0 on success
922 */
923
924static int elm_send(struct diag_l0_device *dl0d, const void *data, size_t len) {
925 uint8_t buf[ELM_BUFSIZE];
926 struct elm_device *dev = dl0d->l0_int;
927 //ssize_t xferd;
928 int rv;
929 unsigned int i;
930
931 if (len == 0) {
932 return diag_iseterr(DIAG_ERR_BADLEN);
933 }
934
935 if ((dev->protocol & DIAG_L1_ISO9141) && len <= 3) {
936 return diag_iseterr(DIAG_ERR_BADLEN);
937 }
938
939 if ((2*len)>(ELM_BUFSIZE-1)) {
940 //too much data for buffer size
941 fprintf(stderr, FLFMT "ELM: too much data for buffer (report this bug please!)\n", FL);
942 return diag_iseterr(DIAG_ERR_BADLEN);
943 }
944
945 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_WRITE, DIAG_DBGLEVEL_V,
946 FLFMT "ELM: sending %d bytes\n", FL, (int) len);
947
948 if ((dev->protocol & DIAG_L1_ISO9141) && memcmp(dev->atsh, data, 3)) {
949 sprintf((char *)buf, "ATSH %02X %02X %02X\x0D",
950 (unsigned int)((uint8_t *)data)[0],
951 (unsigned int)((uint8_t *)data)[1],
952 (unsigned int)((uint8_t *)data)[2]);
953 rv=elm_sendcmd(dl0d, buf, 14, 500, NULL);
954 if (rv < 0) {
955 fprintf(stderr, FLFMT "elm_send: ATSH failed\n",FL);
956 return diag_iseterr(DIAG_ERR_GENERAL);
957 }
958
959 // if ISO9141 protocol setting with KWP message format,
960 // adjust receive filter
961 if ((dev->atsh[0] & 0x80) &&
962 (dev->atsh[2] == (unsigned int)((uint8_t *)data)[2])) {
963 // already sent ATSR for this address
964 } else if ((unsigned int)((uint8_t *)data)[0] & 0x80) {
965 sprintf((char *)buf, "ATSR %02X\x0D",
966 (unsigned int)((uint8_t *)data)[2]);
967 rv=elm_sendcmd(dl0d, buf, 8, 500, NULL);
968 if (rv < 0) {
969 fprintf(stderr, FLFMT "elm_send: ATSR failed\n",FL);
970 return diag_iseterr(DIAG_ERR_GENERAL);
971 }
972 }
973
974 memcpy(dev->atsh, data, 3);
975 }
976
977 for (i=0; i<len; i++) {
978 //fill buffer with ascii-fied hex data
979 snprintf((char *) &buf[2*i], 3, "%02X", (unsigned int)((uint8_t *)data)[i] );
980 }
981 i=2*len;
982 buf[i]=0x0D;
983 buf[i+1]=0x00; //terminate string
984
985 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_WRITE, DIAG_DBGLEVEL_V,
986 FLFMT "ELM: (sending string %s)\n", FL, (char *) buf);
987
988 if (dev->protocol & DIAG_L1_ISO9141) {
989 i -= 6;
990 rv=diag_tty_write(dev->tty_int, buf+6, i+1); // skip header
991 } else {
992 rv=diag_tty_write(dev->tty_int, buf, i+1);
993 }
994 if (rv != (int) (i+1)) { //XXX danger ! evil cast !
995 fprintf(stderr, FLFMT "elm_send:write error\n",FL);
996 return diag_iseterr(DIAG_ERR_GENERAL);
997 }
998 return 0;
999}
1000
1001/*
1002 * Get data (blocking), returns number of bytes read, between 1 and len
1003 * ELM returns a string with format "%02X %02X %02X[...]\n" . But it's slow so we add ELM_SLOWNESS ms to the specified timeout.
1004 * We convert this received ascii string to hex before returning.
1005 * note : "len" is the number of bytes read on the OBD bus, *NOT* the number of ASCII chars received on the serial link !
1006 * TODO decode possible error strings ! Essential because ELM can reply
1007 * "FB ERROR" (FB) is a valid hex number
1008 * "ACT ALARM" (AC) is a valid hex number
1009 * technique:
1010 * -if any hexpair doesn't decode cleanly, discard message
1011 * -just before returning any data, search for an error message match
1012 * -still missing : if caller requests 1 byte, and the error is "FB ERROR", we'll still happily return 0xFB !
1013 *
1014 * TODO: improve "len" semantics for L0 interfaces that do framing, such as this. Currently this returns max 1 message, to
1015 * let L2 do another call to get further messages (typical case of multiple responses)
1016 */
1017static int elm_recv(struct diag_l0_device *dl0d, void *data, size_t len, unsigned int timeout) {
1018 int rv, xferd;
1019 struct elm_device *dev = dl0d->l0_int;
1020 uint8_t rxbuf[3*MAXRBUF +1]; //I think some hotdog code in L2/L3 calls _recv with MAXRBUF so this needs to be huge.
1021 //the +1 is to \0-terminate the buffer for elm_parse_errors() to work
1022
1023 unsigned long t0,tf; //manual timeout control
1024 int steplen; /* bytes per read */
1025 int wp, rp; /* write & read indexes in rxbuf; a type of FIFO */
1026 const char *err;
1027
1028 if ((!len) || (len > MAXRBUF)) {
1029 return diag_iseterr(DIAG_ERR_BADLEN);
1030 }
1031
1032 t0=diag_os_getms();
1033 tf=t0+timeout + ELM_SLOWNESS; //timeout when tf is reached
1034
1035 steplen=2;
1036 wp=0;
1037 rp=0;
1038 xferd=0;
1039 rxbuf[0] = 0x00; //null-terminate
1040
1041 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_READ, DIAG_DBGLEVEL_V,
1042 FLFMT "Expecting 3*%d bytes from ELM, %u ms timeout(+400)...",
1043 FL, (int)len, timeout);
1044
1045 while (1) {
1046 unsigned long tcur;
1047 /* technique : try to read hexpairs (2 bytes); split messages according to
1048 * spacing chars (">\r\n")
1049 */
1050 tcur = diag_os_getms();
1051 if (tcur >= tf) {
1052 /* timed out : */
1053 goto pre_exit;
1054 }
1055 timeout = tf - tcur;
1056
1057 rv = diag_tty_read(dev->tty_int, rxbuf+wp, steplen, timeout);
1058 if (rv == DIAG_ERR_TIMEOUT) {
1059 goto pre_exit;
1060 }
1061
1062 if (rv <= 0) {
1063 fprintf(stderr, FLFMT "elm_recv error\n", FL);
1064 return diag_iseterr(DIAG_ERR_GENERAL);
1065 }
1066
1067 wp += rv; /* position for next tty_read */
1068 rxbuf[wp]=0; // '\0'-terminate "string"
1069
1070 int skipc; /* chars to skip */
1071
1072 skipc = strspn((char *)(&rxbuf[rp]), " "); /* skip contig spaces */
1073 rp += skipc;
1074 /* line end ? */
1075 skipc=strspn((char *)(&rxbuf[rp]), "\r\n>");
1076 rp += skipc;
1077 if (skipc > 0) {
1078 /* definitely a line-end / prompt ! return data so far, if any */
1079 if (xferd > 0) {
1080 goto pre_exit;
1081 }
1082 }
1083
1084 if (strlen((char *)(&rxbuf[rp])) < 2) {
1085 /* probably incomplete hexpair. */
1086 steplen=1;
1087 continue;
1088 }
1089
1090 unsigned int rbyte;
1091 if (sscanf((char *)(&rxbuf[rp]), "%02X", &rbyte) == 1) {
1092 /* good hexpair */
1093 ((uint8_t *)data)[xferd]=(uint8_t) rbyte;
1094 xferd++;
1095 if ( (size_t)xferd==len) {
1096 goto pre_exit;
1097 }
1098 } else {
1099 /* didn't scanf properly... error message ? ex. "NO DATA\r>"
1100 * NO DATA is pretty inoffensive; skip printing that one */
1101 if (!(rxbuf[rp] == 'N' && rxbuf[rp+1] =='O')) {
1102 fprintf(stderr, FLFMT "ELM sscanf failed to eat '%s'\n", FL, rxbuf);
1103 }
1104 /* finish pulling the error message or whatever garbage */
1105 rv = diag_tty_read(dev->tty_int, rxbuf+wp, sizeof(rxbuf) - wp, ELM_SLOWNESS);
1106 if (rv >= 0) {
1107 rxbuf[wp + rv] = 0x00;
1108 }
1109 xferd = DIAG_ERR_GENERAL;
1110 goto pre_exit;
1111 }
1112 /* here, we just sscanf'd 2 bytes, so we read 1 more. */
1113 /* we can't read 2 more, in case we're in a multi-message, for instance if we just decoded 0x00 in
1114 * "48 6A 01 00\n48 6A..." , reading two bytes "\n4" would corrupt the next message !
1115 */
1116 rp += 2;
1117 steplen=1;
1118 } // while (1)
1119
1120pre_exit:
1121 err = elm_parse_errors(dl0d, rxbuf);
1122 if (err) {
1123 if (strcmp(err, "NO DATA") == 0) {
1124 return DIAG_ERR_TIMEOUT;
1125 }
1126 fprintf(stderr, FLFMT "ELM error %s\n", FL, err);
1127 return diag_iseterr(DIAG_ERR_GENERAL);
1128 }
1129 return (xferd>0)? xferd:DIAG_ERR_TIMEOUT;
1130}
1131
1132
1133/* set new wakeup message, if possible */
1134static int elm_setwm(struct diag_l0_device *dl0d, struct diag_msg *pmsg) {
1135 struct elm_device *dev;
1136
1137 dev = (struct elm_device *)dl0d->l0_int;
1138
1139 if (dev->elmflags & ELM_INITDONE) {
1140 /*
1141 * It's possible to change the wakeup message after init,
1142 * but we don't currently implement this.
1143 */
1144 fprintf(stderr, FLFMT "elm_setwm: tried to set wakeup message after init\n", FL);
1145 return diag_iseterr(DIAG_ERR_GENERAL);
1146 }
1147
1148 if (dev->elmflags & ELM_323_BASIC) {
1149 fprintf(stderr, FLFMT "elm_setwm: ELM323 doesn't support setting wakeup message\n", FL);
1150 return diag_iseterr(DIAG_ERR_IOCTL_NOTSUPP);
1151 }
1152
1153 if (pmsg->len != 4) {
1154 fprintf(stderr, FLFMT "elm_setwm: invalid message length %u\n", FL, pmsg->len);
1155 return diag_iseterr(DIAG_ERR_GENERAL);
1156 }
1157
1158 if (dev->wm != NULL) {
1159 diag_freemsg(dev->wm);
1160 }
1161 dev->wm = diag_dupsinglemsg(pmsg);
1162 if (dev->wm == NULL) {
1163 return diag_iseterr(DIAG_ERR_NOMEM);
1164 }
1165 return 0;
1166}
1167
1168
1169static uint32_t elm_getflags(struct diag_l0_device *dl0d) {
1170
1171 struct elm_device *dev;
1172 uint32_t flags=0;
1173
1174 dev = (struct elm_device *)dl0d->l0_int;
1175
1176 flags = DIAG_L1_DATAONLY | DIAG_L1_AUTOSPEED | DIAG_L1_DOESP4WAIT |
1177 DIAG_L1_DOESL2FRAME | DIAG_L1_DOESL2CKSUM | DIAG_L1_DOESFULLINIT | DIAG_L1_DOESKEEPALIVE;
1178
1179 switch (dev->protocol) {
1180 case DIAG_L1_ISO9141:
1181 flags |= DIAG_L1_SLOW;
1182 flags &= ~DIAG_L1_DATAONLY;
1183 //flags |= DIAG_L1_NOHDRS; //probably not needed since we send ATH1 on init (enable headers)
1184 break;
1185 case DIAG_L1_ISO14230:
1186 flags |= DIAG_L1_SLOW | DIAG_L1_FAST | DIAG_L1_PREFFAST;
1187 //flags |= DIAG_L1_NOHDRS;
1188 break;
1189 default:
1190 break;
1191 }
1192
1193 DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_PROTO, DIAG_DBGLEVEL_V,
1194 FLFMT "getflags link %p proto %d flags 0x%X\n",
1195 FL, (void *)dl0d, dev->protocol, flags);
1196
1197 return flags;
1198
1199}
1200
1201//elm_parse_cr : change 0x0A to 0x0D in datastream.
1202static void elm_parse_cr(uint8_t *data, int len) {
1203 int i=0;
1204 for (; i<len; i++) {
1205 if (*data == 0x0D) {
1206 *data = 0x0A;
1207 }
1208 data++;
1209 }
1210 return;
1211}
1212
1213
1214static int elm_ioctl(struct diag_l0_device *dl0d, unsigned cmd, void *data) {
1215 int rv = 0;
1216
1217 switch (cmd) {
1218 case DIAG_IOCTL_IFLUSH:
1219 //do nothing
1220 rv = 0;
1221 break;
1222 case DIAG_IOCTL_INITBUS:
1223 rv = elm_initbus(dl0d, (struct diag_l1_initbus_args *)data);
1224 break;
1225 case DIAG_IOCTL_SETWM:
1226 rv = elm_setwm(dl0d, (struct diag_msg *)data);
1227 break;
1228 default:
1229 rv = DIAG_ERR_IOCTL_NOTSUPP;
1230 break;
1231 }
1232
1233 return rv;
1234}
1235
1236
1237const struct diag_l0 diag_l0_elm = {
1238 "Scantool.net ELM32x Chipset Device",
1239 "ELM",
1240 DIAG_L1_ISO9141 | DIAG_L1_ISO14230 | DIAG_L1_J1850_PWM | DIAG_L1_J1850_VPW | DIAG_L1_CAN,
1241 elm_init,
1242 elm_new,
1243 elm_getcfg,
1244 elm_del,
1245 elm_open,
1246 elm_close,
1247 elm_getflags,
1248 elm_recv,
1249 elm_send,
1250 elm_ioctl
1251};
1252