/* * Do wakeup on the bus * * We do this by noting a wakeup needs to be done for the next packet for * fastinit, and doing slowinit now */ static int diag_l0_muleng_initbus(struct diag_l0_device *dl0d, struct diag_l1_initbus_args *in) { int rv = 0; struct diag_l0_muleng_device *dev; dev = (struct diag_l0_muleng_device *)dl0d->l0_int; if (!dev) return diag_iseterr(DIAG_ERR_GENERAL); if (diag_l0_debug & DIAG_DEBUG_IOCTL) fprintf(stderr, FLFMT "device link %p info %p initbus type %d proto %d\n", FL, (void *)dl0d, (void *)dev, in->type, dev->protocol); diag_tty_iflush(dl0d); /* Empty the receive buffer, wait for idle bus */ if (in->type == DIAG_L1_INITBUS_5BAUD) rv = diag_l0_muleng_slowinit(dl0d, in, dev); else { /* Do wakeup on first TX */ dev->dev_wakeup = in->type; dev->dev_state = MULENG_STATE_FASTSTART; } return rv; }
/* * Open the diagnostic device, returns a file descriptor * records original state of term interface so we can restore later */ static struct diag_l0_device * diag_l0_muleng_open(const char *subinterface, int iProtocol) { int rv; struct diag_l0_device *dl0d; struct diag_l0_muleng_device *dev; struct diag_serial_settings set; if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "open subinterface %s protocol %d\n", FL, subinterface, iProtocol); } diag_l0_muleng_init(); if ((rv=diag_calloc(&dev, 1))) return diag_pseterr(rv); dev->protocol = iProtocol; dl0d = diag_l0_new(&diag_l0_me, (void *)dev); if (!dl0d) { free(dev); return diag_pseterr(rv); } /* try to open TTY */ if ((rv=diag_tty_open(dl0d, subinterface))) { diag_l0_del(dl0d); free(dev); return diag_pseterr(rv); } /* And set to 19200 baud , 8N1 */ set.speed = 19200; set.databits = diag_databits_8; set.stopbits = diag_stopbits_1; set.parflag = diag_par_n; if ((rv=diag_tty_setup(dl0d, &set))) { diag_l0_muleng_close(dl0d); return diag_pseterr(rv); } /* And set DTR high and RTS low to power the device */ if ((rv=diag_tty_control(dl0d, 1, 0))) { diag_l0_muleng_close(dl0d); return diag_pseterr(rv); } diag_tty_iflush(dl0d); /* Flush unread input */ return dl0d ; }
/* * Open the diagnostic device, returns a file descriptor * records original state of term interface so we can restore later */ static struct diag_l0_device * diag_l0_dumb_open(const char *subinterface, int iProtocol) { int rv; struct diag_l0_device *dl0d; struct diag_l0_dumb_device *dev; if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "open subinterface %s protocol %d\n", FL, subinterface, iProtocol); } diag_l0_dumb_init(); //make sure it is initted if ((rv=diag_calloc(&dev, 1))) return diag_pseterr(DIAG_ERR_NOMEM); dev->protocol = iProtocol; dl0d = diag_l0_new(&diag_l0_dumb, (void *)dev); if (!dl0d) { free(dev); return diag_pseterr(rv); } /* try to open TTY */ if ((rv=diag_tty_open(dl0d, subinterface))) { diag_l0_del(dl0d); free(dev); return diag_pseterr(rv); } /* * We set RTS to low, and DTR high, because this allows some * interfaces to work than need power from the DTR/RTS lines; * this is altered according to dumb_flags. */ if (diag_tty_control(dl0d, !(dumb_flags & CLEAR_DTR), (dumb_flags & SET_RTS)) < 0) { diag_l0_dumb_close(&dl0d); return diag_pseterr(DIAG_ERR_GENERAL); } if (dumb_flags & DUMBDEFAULTS) dumb_flags = DUMBDEFAULTS & MAN_BREAK; (void)diag_tty_iflush(dl0d); /* Flush unread input */ return dl0d; }
/* * Do wakeup on the bus * * We do this by noting a wakeup needs to be done for the next packet for * fastinit, and doing slowinit now */ static int diag_l0_br_initbus(struct diag_l0_device *dl0d, struct diag_l1_initbus_args *in) { int rv = 0; struct diag_l0_br_device *dev; dev = (struct diag_l0_br_device *)dl0d->l0_int; if (diag_l0_debug & DIAG_DEBUG_IOCTL) fprintf(stderr, FLFMT "device link %p info %p initbus type %d proto %d\n", FL, (void *)dl0d, (void *)dev, in->type, dev ? dev->protocol : -1); if (!dev) return diag_iseterr(DIAG_ERR_GENERAL); diag_tty_iflush(dl0d); /* Flush unread input */ switch (in->type) { case DIAG_L1_INITBUS_5BAUD: rv = diag_l0_br_slowinit(dl0d, in); break; case DIAG_L1_INITBUS_FAST: if ((dev->dev_features & BR_FEATURE_FASTINIT) == 0) { /* Fast init Not supported */ rv = DIAG_ERR_INIT_NOTSUPP; } else { /* Fastinit done on 1st TX */ dev->dev_state = BR_STATE_KWP_FASTINIT; rv = 0; } break; default: rv = DIAG_ERR_INIT_NOTSUPP; break; } return rv? diag_iseterr(rv):0 ; }
/* * Open the diagnostic device, return a file descriptor, * record the original state of term interface so we can restore later */ static int br_open(struct diag_l0_device *dl0d, int iProtocol) { struct br_device *dev = dl0d->l0_int; int rv; uint8_t buf[4]; /* Was MAXRBUF. We only use 1! */ struct diag_serial_settings set; br_init(); dev->protocol = iProtocol; dev->dev_rdoffset = 0; dev->dev_txlen = 0; dev->dev_framenr = 0; dev->dev_state = BR_STATE_CLOSED; dev->dev_features = BR_FEATURE_SETADDR; /* try to open TTY */ dev->tty_int = diag_tty_open(dev->port.val.str); if (dev->tty_int == NULL) { return diag_iseterr(DIAG_ERR_GENERAL); } DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V, FLFMT "features 0x%X\n", FL, dev->dev_features); /* Set serial line to 19200 baud , 8N1 */ set.speed = 19200; set.databits = diag_databits_8; set.stopbits = diag_stopbits_1; set.parflag = diag_par_n; if (diag_tty_setup(dev->tty_int, &set)) { fprintf(stderr, FLFMT "open: TTY setup failed\n", FL); br_close(dl0d); return diag_iseterr(DIAG_ERR_GENERAL); } diag_tty_iflush(dev->tty_int); /* Flush unread input data */ /* * Initialise the BR1 interface by sending the CHIP CONNECT * (0x20h) command, we should get a 0xFF back */ buf[0] = 0x20; if (br_write(dl0d, buf, 1)) { DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V, FLFMT "CHIP CONNECT write failed link %p\n", FL, (void *)dl0d); br_close(dl0d); return diag_iseterr(DIAG_ERR_BADIFADAPTER); } /* And expect 0xff as a response */ if (diag_tty_read(dev->tty_int, buf, 1, 100) != 1) { DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V, FLFMT "CHIP CONNECT read failed link %p\n", FL, (void *)dl0d); br_close(dl0d); return diag_iseterr(DIAG_ERR_BADIFADAPTER); } if (buf[0] != 0xff) { DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V, FLFMT "CHIP CONNECT rcvd 0x%X != 0xff, link %p\n", FL, buf[0], (void *)dl0d); br_close(dl0d); return diag_iseterr(DIAG_ERR_BADIFADAPTER); } /* If it's J1850, send initialisation string now */ rv = 0; switch (iProtocol) { case DIAG_L1_J1850_VPW: rv = br_initialise(dl0d, 0, 0); break; case DIAG_L1_J1850_PWM: rv = br_initialise(dl0d, 1, 0); break; case DIAG_L1_ISO9141: case DIAG_L1_ISO14230: /* This initialisation is done in the SLOWINIT code */ break; } if (rv) { br_close(dl0d); return diag_ifwderr(rv); } DIAG_DBGM(diag_l0_debug, DIAG_DEBUG_OPEN, DIAG_DBGLEVEL_V, FLFMT "open succeeded link %p features 0x%X\n", FL, (void *)dl0d, dev->dev_features); dl0d->opened = 1; return 0; }
/* * Open the diagnostic device, return a file descriptor, * record the original state of term interface so we can restore later */ static struct diag_l0_device * diag_l0_br_open(const char *subinterface, int iProtocol) { struct diag_l0_device *dl0d; struct diag_l0_br_device *dev; int rv; uint8_t buf[4]; /* Was MAXRBUF. We only use 1! */ struct diag_serial_settings set; diag_l0_br_init(); if ((rv=diag_calloc(&dev, 1))) return diag_pseterr(rv); dev->protocol = iProtocol; dev->dev_rdoffset = 0; dev->dev_txlen = 0; dev->dev_framenr = 0; dev->dev_state = BR_STATE_CLOSED; dev->dev_features = BR_FEATURE_SETADDR; /* Get an L0 link */ dl0d = diag_l0_new(&diag_l0_br, (void *)dev); if (!dl0d) { free(dev); return diag_pseterr(rv); } /* try to open TTY */ if ((rv=diag_tty_open(dl0d, subinterface))) { diag_l0_del(dl0d); free(dev); return diag_pseterr(rv); } if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "features 0x%X\n", FL, dev->dev_features); } /* Set serial line to 19200 baud , 8N1 */ set.speed = 19200; set.databits = diag_databits_8; set.stopbits = diag_stopbits_1; set.parflag = diag_par_n; if (diag_tty_setup(dl0d, &set)) { fprintf(stderr, FLFMT "open: TTY setup failed\n", FL); diag_l0_br_close(&dl0d); return diag_pseterr(rv); } diag_tty_iflush(dl0d); /* Flush unread input data */ /* * Initialise the BR1 interface by sending the CHIP CONNECT * (0x20h) command, we should get a 0xFF back */ buf[0] = 0x20; if (diag_l0_br_write(dl0d, buf, 1)) { if ((diag_l0_debug&DIAG_DEBUG_OPEN)) { fprintf(stderr, FLFMT "CHIP CONNECT write failed link %p\n", FL, (void *)dl0d); } diag_l0_br_close(&dl0d); return diag_pseterr(DIAG_ERR_BADIFADAPTER); } /* And expect 0xff as a response */ if (diag_tty_read(dl0d, buf, 1, 100) != 1) { if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "CHIP CONNECT read failed link %p\n", FL, (void *)dl0d); } diag_l0_br_close(&dl0d); return diag_pseterr(DIAG_ERR_BADIFADAPTER); } if (buf[0] != 0xff) { if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "CHIP CONNECT rcvd 0x%X != 0xff, link %p\n", FL, buf[0], (void *)dl0d); } diag_l0_br_close(&dl0d); return diag_pseterr(DIAG_ERR_BADIFADAPTER); } /* If it's J1850, send initialisation string now */ rv = 0; switch (iProtocol) { case DIAG_L1_J1850_VPW: rv = diag_l0_br_initialise(dl0d, 0, 0); break; case DIAG_L1_J1850_PWM: rv = diag_l0_br_initialise(dl0d, 1, 0); break; case DIAG_L1_ISO9141: case DIAG_L1_ISO14230: /* This initialisation is done in the SLOWINIT code */ break; } if (rv) { diag_l0_br_close(&dl0d); return diag_pseterr(rv); } if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "open succeeded link %p features 0x%X\n", FL, (void *)dl0d, dev->dev_features); } return dl0d; }
/* * Open the diagnostic device * ELM settings used : no echo (E0), headers on (H1), linefeeds off (L0), mem off (M0) */ static struct diag_l0_device * diag_l0_elm_open(const char *subinterface, int iProtocol) { int i,rv; struct diag_l0_device *dl0d; struct diag_l0_elm_device *dev; struct diag_serial_settings sset; const uint8_t *buf; uint8_t rxbuf[ELM_BUFSIZE]; const char ** elm_official; const char ** elm_clones; //point to elm323_ or elm327_ clone and official version string lists if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "open subinterface %s protocol %d\n", FL, subinterface, iProtocol); } diag_l0_elm_init(); if ((rv=diag_calloc(&dev, 1))) return diag_pseterr(rv); dev->protocol = iProtocol; dl0d = diag_l0_new(&diag_l0_elm, (void *)dev); if (!dl0d) { free(dev); return diag_pseterr(rv); } /* try to open TTY */ if ((rv=diag_tty_open(dl0d, subinterface))) { diag_l0_del(dl0d); free(dev); return diag_pseterr(rv); } //set speed to 38400;8n1. sset.speed=38400; sset.databits = diag_databits_8; sset.stopbits = diag_stopbits_1; sset.parflag = diag_par_n; dev->serial = sset; if ((rv=diag_tty_setup(dl0d, &sset))) { fprintf(stderr, FLFMT "Error setting 38400;8N1 on %s\n", FL, subinterface); diag_l0_elm_close(&dl0d); return diag_pseterr(rv); } diag_tty_iflush(dl0d); /* Flush unread input */ //At this stage, the ELM has possibly been powered up for a while; //it may have an unfinished command / garbage in its input buffer. We //need to clear that before sending the real ATZ ==> ATI is quick and safe; elm_purge does this. dev->elmflags=0; //we know nothing yet rv=elm_purge(dl0d); //if rv=0, we got a prompt so we know speed is set properly. if (rv==0) { dev->elmflags |= ELM_38400; } else { fprintf(stderr, FLFMT "sending ATI @ 38400 failed; trying @ 9600...\n", FL); sset.speed=9600; dev->serial = sset; if ((rv=diag_tty_setup(dl0d, &sset))) { fprintf(stderr, FLFMT "Error setting 9600;8N1 on %s\n", FL, subinterface); diag_l0_elm_close(&dl0d); return diag_pseterr(rv); } diag_tty_iflush(dl0d); /* Flush unread input */ rv = elm_purge(dl0d); //try ATI\r again if (rv !=0) { fprintf(stderr, FLFMT "sending ATI @ 9600 failed. Verify connection to ELM\n", FL); diag_l0_elm_close(&dl0d); return diag_pseterr(DIAG_ERR_BADIFADAPTER); } } if (diag_l0_debug&DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "elm_open : sending ATZ...\n", FL); } //the command "ATZ" causes a full reset and the ELM replies with //a string like "ELM32x vX.Xx\n>" buf=(uint8_t *)"ATZ\x0D"; rv=elm_sendcmd(dl0d, buf, 4, 2000, rxbuf); if (rv) { fprintf(stderr, FLFMT "elm_open : ATZ failed !\n", FL); diag_l0_elm_close(&dl0d); return diag_pseterr(DIAG_ERR_BADIFADAPTER); } //Correct prompt received; try to identify device. // 1) guess 323 vs 327 if (strstr((char *)rxbuf, "ELM323")!=NULL) { dev->elmflags |= ELM_323_BASIC; elm_official=elm323_official; elm_clones=elm323_clones; } else if (strstr((char *)rxbuf, "ELM327")!=NULL) { dev->elmflags |= ELM_327_BASIC; elm_official=elm327_official; elm_clones=elm327_clones; } else { fprintf(stderr, FLFMT "no valid version string !! Report this !. Got:\n%s\n", FL, rxbuf); //no point in continuing... diag_l0_elm_close(&dl0d); return diag_pseterr(DIAG_ERR_BADIFADAPTER); } // 2) identify valid VS clone devices. rv=0; // temp "device identified" flag for (i=0; elm_clones[i]; i++) { if (strstr((char *)rxbuf, elm_clones[i])) { printf("Clone ELM found, v%s\n", elm_clones[i]); dev->elmflags |= ELM_32x_CLONE; rv=1; break; } } if (rv==0) { for (i=0; elm_official[i]; i++) { if (strstr((char *)rxbuf, elm_official[i])) { printf("Official ELM found, v%s\n", elm_official[i]); rv=1; break; } } } if (rv==0) { //still not identified : assume clone. dev->elmflags |= ELM_32x_CLONE; printf("ELM version not recognized! Please report this ! Resp=%s\n", rxbuf); } if ((dev->elmflags & ELM_323_BASIC) && (dev->elmflags & ELM_32x_CLONE)) { printf("A 323 clone ? Report this !\n"); } if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "ELM reset success, elmflags=%#x\n", FL, dev->elmflags); } //now send "ATE0\n" command to disable echo. buf=(uint8_t *)"ATE0\x0D"; if (elm_sendcmd(dl0d, buf, 5, 500, NULL)) { if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "sending \"ATE0\" failed\n", FL); } diag_l0_elm_close(&dl0d); return diag_pseterr(DIAG_ERR_BADIFADAPTER); } //ATL0 : disable linefeeds buf=(uint8_t *)"ATL0\x0D"; if (elm_sendcmd(dl0d, buf, 5, 500, NULL)) { if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "sending \"ATL0\" failed\n", FL); } diag_l0_elm_close(&dl0d); return diag_pseterr(DIAG_ERR_BADIFADAPTER); } //ATH1 : always show header bytes buf=(uint8_t *)"ATH1\x0D"; if (elm_sendcmd(dl0d, buf, 5, 500, NULL)) { if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "sending \"ATH1\" failed\n", FL); } diag_l0_elm_close(&dl0d); return diag_pseterr(DIAG_ERR_BADIFADAPTER); } //for elm327 only: disable memory if (dev->elmflags & ELM_327_BASIC) { buf=(uint8_t *)"ATM0\x0D"; if (elm_sendcmd(dl0d, buf, 5, 500, NULL)) { if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "sending \"ATM0\" failed\n", FL); } diag_l0_elm_close(&dl0d); return diag_pseterr(DIAG_ERR_BADIFADAPTER); } } //check if proto is really supported (323 supports only 9141 and 14230) if ((dev->elmflags & ELM_323_BASIC) && ((iProtocol != DIAG_L1_ISO9141) && (iProtocol != DIAG_L1_ISO14230))) return diag_pseterr(DIAG_ERR_PROTO_NOTSUPP); //if 327, set proto when possible; we won't if 14230, because init type (fast vs slow) isn't decided yet // CAN is also not implemented here buf=NULL; if (dev->elmflags & ELM_327_BASIC) { switch (iProtocol) { case DIAG_L1_J1850_PWM: buf=(uint8_t *)"ATTP1\x0D"; break; case DIAG_L1_J1850_VPW: buf=(uint8_t *)"ATTP2\x0D"; break; case DIAG_L1_ISO9141: buf=(uint8_t *)"ATTP3\x0D"; break; default: buf=NULL; } } if (buf != NULL) { if (elm_sendcmd(dl0d, buf, 6, 500, NULL)) { if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "sending \"ATTPx\" failed\n", FL); } diag_l0_elm_close(&dl0d); return diag_pseterr(DIAG_ERR_BADIFADAPTER); } } //at this point : ELM is ready for further ops if (diag_l0_debug & DIAG_DEBUG_OPEN) { fprintf(stderr, FLFMT "ELM ready.\n", FL); } return dl0d; }
//Send a command to ELM device and make sure no error occured. Data is passed on directly as a string; //caller must make sure the string is \r-terminated , i.e. 0x0D-terminated. //Sending 0A after 0D will cause ELM to interrupt what it's doing to "process" 0A, resulting in a //failure. //This func should not be used for commands that elicit a data response (i.e. all data destined to the OBD bus, //hence not prefixed by "AT"). Response is dumped in *resp (0-terminated) for optional analysis by caller; *resp must be ELM_BUFSIZE long. //returns 0 if (prompt_good) && ("OK" found anywhere in the response) && (no known error message was present) || // (prompt_good && ATZ command was sent) , since response doesn't contain "OK" for ATZ. //elm_sendcmd should not be called from outside diag_l0_elm.c. static int elm_sendcmd(struct diag_l0_device *dl0d, const uint8_t *data, size_t len, unsigned int timeout, uint8_t *resp) { //note : we better not request (len == (size_t) -1) bytes ! The casts between ssize_t and size_t are // "muddy" in here //ssize_t xferd; int rv; uint8_t ebuf[ELM_BUFSIZE]; //local buffer if caller provides none. uint8_t *buf; struct diag_l0_elm_device *dev; const char *err_str; //hold a possible error message dev = (struct diag_l0_elm_device *)dl0d->l0_int; //we need access to diag_l0_elm_device to access .elmflags if (resp==NULL) buf=ebuf; //use local buffer else buf=resp; //or caller-provided buffer if (!len) return diag_iseterr(DIAG_ERR_BADLEN); if (!dev) return diag_iseterr(DIAG_ERR_BADFD); if (data[len-1] != 0x0D) { //Last byte is not a carriage return, this would die. fprintf(stderr, FLFMT "elm_sendcmd: non-terminated command : %.*s\n", FL, (int) len, (char *) data); //the %.*s is pure magic : limits the string length to len, even if the string is not null-terminated. return diag_iseterr(DIAG_ERR_GENERAL); } diag_tty_iflush(dl0d); //currently the code often "forgets" data in the input buffer, especially if the previous //transaction failed. Flushing the input increases the odds of not crashing soon if (diag_l0_debug & DIAG_DEBUG_WRITE) { fprintf(stderr, FLFMT "elm_sendcmd: %.*s\n", FL, (int) len-1, (char *)data); } rv = diag_tty_write(dl0d, data, len); if (rv != (int) len) { //XXX danger ! evil cast fprintf(stderr, FLFMT "elm_sendcmd: write error\n", FL); return diag_iseterr(DIAG_ERR_GENERAL); } //next, receive ELM response, within {ms} delay. rv=diag_tty_read(dl0d, buf, ELM_BUFSIZE-1, timeout); //rv=# bytes read if (rv<1) { //no data or error if (diag_l0_debug & DIAG_DEBUG_WRITE) { fprintf(stderr, FLFMT "ELM did not respond\n", FL); } return diag_iseterr(DIAG_ERR_GENERAL); } if (diag_l0_debug & DIAG_DEBUG_READ) { elm_parse_cr(buf, rv); //debug output is prettier with this fprintf(stderr, FLFMT "received %d bytes (%.*s\n); hex: ", FL, rv, rv, (char *)buf); if (diag_l0_debug & DIAG_DEBUG_DATA) { diag_data_dump(stderr, buf, rv); fprintf(stderr, "\n"); } } buf[rv]=0; //terminate string if (buf[rv-1] != '>') { //if last character isn't the input prompt, there is a problem fprintf(stderr, FLFMT "ELM not ready (no prompt received): %s\nhex: ", FL, buf); diag_data_dump(stderr, buf, rv); fprintf(stderr, "\n"); return diag_iseterr(DIAG_ERR_GENERAL); } //At this point we got a prompt but there may have been an error message. //There is some ambiguity in the ELM datasheets on the exact format of the replies. //1) the prompt character '>' is always alone on its line; //2) depending on some parameters, it may be preceded by 0D or 0D 0A //3) some errors ( "<DATA ERROR" and "<RX ERROR" ) can be appended after //a reply; others should be at the beginning of the response (alone on a line) //ex. of good reply : "41 00 00 \r>", bad reply :"NO DATA\r>" //let's just use strstr() to find occurences for each known error. //it'll take a while but speed isn't normally critical when sending commands err_str = elm_parse_errors(dl0d, buf); if (err_str != NULL) { fprintf(stderr, FLFMT "ELM returned error : %s\n", FL, err_str); return diag_iseterr(DIAG_ERR_GENERAL); } //check if we either 1)got a positive response "OK" //2)were sending ATZ (special case hack, it doesn't answer "OK") if ((strstr((char *)buf, "OK") != NULL) || (strstr((char *)data, "ATZ") != NULL)) { return 0; } fprintf(stderr, FLFMT "Response not recognized ! Report this ! Got: \n", FL); diag_data_dump(stderr, buf, rv); fprintf(stderr, "\n"); return diag_iseterr(DIAG_ERR_GENERAL); }
/* * Do 5 Baud initialisation * * In the case of ISO9141 we operate in the interface's "raw" mode * (VAG compatibility mode), in 14230 we do a slow init and send * a tester present message */ static int diag_l0_muleng_slowinit( struct diag_l0_device *dl0d, struct diag_l1_initbus_args *in, struct diag_l0_muleng_device *dev) { /* * Slow init * Build message into send buffer, and calculate checksum */ uint8_t txbuf[15]; uint8_t rxbuf[15]; int rv; unsigned int baud; memset(txbuf, 0, sizeof(txbuf)); txbuf[0] = INTERFACE_ADDRESS; switch (dev->protocol) { case DIAG_L1_ISO9141: txbuf[1] = 0x20; /* Raw mode 5 baud init */ txbuf[2] = in->addr; break; case DIAG_L1_ISO14230: txbuf[1] = 0x85; txbuf[2] = 0x01; /* One byte message */ txbuf[3] = DIAG_KW2K_SI_TP; /* tester present */ break; } /* * Calculate the checksum, and send the request */ (void)diag_l0_muleng_txcksum(txbuf); if ((rv = diag_l0_muleng_write(dl0d, txbuf, 15))) return diag_iseterr(rv); /* * Get answer */ switch (dev->protocol) { case DIAG_L1_ISO9141: /* * This is raw mode, we should get a single byte back * with the timing interval, then we need to change speed * to match that speed. Remember it takes 2 seconds to send * the 10 bit (1+8+1) address at 5 baud */ rv = diag_tty_read(dl0d, rxbuf, 1, 2350); if (rv != 1) return diag_iseterr(DIAG_ERR_GENERAL); if (rxbuf[0] == 0x40) { /* Problem ..., got an error message */ diag_tty_iflush(dl0d); /* Empty the receive buffer */ return diag_iseterr(DIAG_ERR_GENERAL); } baud = me_baud_table[rxbuf[0]]; if (diag_l0_debug & DIAG_DEBUG_PROTO) fprintf(stderr, FLFMT "device link %p setting baud to %u\n", FL, (void *)dl0d, baud); if (baud) { struct diag_serial_settings set; set.speed = baud; set.databits = diag_databits_8; set.stopbits = diag_stopbits_1; set.parflag = diag_par_n; /* And set the baud rate */ diag_tty_setup(dl0d, &set); } dev->dev_state = MULENG_STATE_RAW; break; case DIAG_L1_ISO14230: /* XXX * Should get an ack back, rather than an error response */ if ((rv = diag_tty_read(dl0d, rxbuf, 14, 200)) < 0) return diag_iseterr(rv); if (rxbuf[1] == 0x80) return diag_iseterr(DIAG_ERR_GENERAL); /* * Now send the "get keybyte" request, and wait for * response */ memset(txbuf, 0, sizeof(txbuf)); txbuf[0] = INTERFACE_ADDRESS; txbuf[1] = 0x86; (void)diag_l0_muleng_txcksum(txbuf); rv = diag_l0_muleng_write(dl0d, txbuf, 15); if (rv < 0) return diag_iseterr(rv); if ((rv = diag_tty_read(dl0d, rxbuf, 14, 200)) < 0) return diag_iseterr(rv); if (rxbuf[1] == 0x80) /* Error */ return diag_iseterr(rv); /* * Store the keybytes */ dev->dev_kb1 = rxbuf[2]; dev->dev_kb2 = rxbuf[3]; /* * And tell read code to report the keybytes on first read */ dev->dev_state = MULENG_STATE_KWP_SENDKB1; break; } return rv; }