Logo Search packages:      
Sourcecode: obdgpslogger version File versions  Download package

enum obd_serial_status getobdbytes ( int  fd,
unsigned int  mode,
unsigned int  cmd,
int  numbytes_expected,
unsigned int *  retvals,
unsigned int  retvals_size,
int *  numbytes_returned,
int  quiet 
)

Get the raw bits returned from an OBD command.

This returns some unsigned integers. Each contains eight bits in its low byte and zeros in the rest

Parameters:
fdthe serial port opened with openserial
cmdthe obd service command
numbytes_expectedthe number of bytes we expect in the response [optimisation]. Set to zero for safe-nothing-can-go-wrong
retvals_sizenumber of retvals allocated in the retvals array
retvalsarray of retvals_size items to stuff with retvalues
numbytes_returnedtells you how many of retvals were filled.
Returns:
something from the obd_serial_status enum

Definition at line 677 of file obdserial.c.

References appendseriallog(), OBD_ERROR, OBD_NO_DATA, OBD_SUCCESS, OBD_UNABLE_TO_CONNECT, OBDCMD_NEWLINE, parseobdline(), and readserialdata().

Referenced by getnumobderrors(), getobderrorcodes(), and getobdvalue().

                                                                                           {

      char sendbuf[20]; // Command to send
      int sendbuflen; // Number of bytes in the send buffer

      char retbuf[4096]; // Buffer to store returned stuff

      int nbytes; // Number of bytes read

      if(mode == 0x03 || mode == 0x04) {
            sendbuflen = snprintf(sendbuf,sizeof(sendbuf),"%02X" OBDCMD_NEWLINE, mode);
      } else {
            if(0 == numbytes_expected) {
                  sendbuflen = snprintf(sendbuf,sizeof(sendbuf),"%02X%02X" OBDCMD_NEWLINE, mode, cmd);
            } else {
                  sendbuflen = snprintf(sendbuf,sizeof(sendbuf),"%02X%02X%01X" OBDCMD_NEWLINE, mode, cmd, numbytes_expected);
            }
      }

      appendseriallog(sendbuf, SERIAL_OUT);
      if(write(fd,sendbuf,sendbuflen) < sendbuflen) {
            return OBD_ERROR;
      }

      nbytes = readserialdata(fd, retbuf, sizeof(retbuf));
      if(0 == nbytes) {
            if(!quiet)
                  fprintf(stderr, "No data at all returned from serial port\n");
            return OBD_ERROR;
      } else if(-1 == nbytes) {
            if(!quiet)
                  fprintf(stderr, "Error reading from serial port\n");
            return OBD_ERROR;
      }

      // First some sanity checks on the data

      if(NULL != strstr(retbuf, "NO DATA")) {
            if(!quiet)
                  fprintf(stderr, "OBD reported NO DATA for %02X %02X: %s\n", mode, cmd, retbuf);
            return OBD_NO_DATA;
      }

      if(0 != strstr(retbuf, "?")) {
            if(!quiet)
                  fprintf(stderr, "OBD reported ? for %02X %02X: %s\n", mode, cmd, retbuf);
            return OBD_NO_DATA;
      }

      if(NULL != strstr(retbuf, "UNABLE TO CONNECT")) {
            if(!quiet)
                  fprintf(stderr, "OBD reported UNABLE TO CONNECT for %02X %02X: %s\n", mode, cmd, retbuf);
            return OBD_UNABLE_TO_CONNECT;
      }

      /* 
            Good grief, this is ugly.
            1) We look go through the output line by line [strtokking]
            2) For each line, if it's a regular line, parse it
            3) If it has a colon near the start, it means it's a multi-line response
            4) So go into crazy C string handling mode.
      */

      char *line = strtok(retbuf, "\r\n>");

      int values_returned = 0;
      enum obd_serial_status ret = OBD_ERROR;
      while(NULL != line) {
            char *colon;
            int joined_lines = 0; // Set if we joined some lines together
            char longline[1024] = "\0"; // Catenate other lines into this

            char *parseline = line; // The line to actually parse.

            while(NULL != line && NULL != (colon = strstr(line, ":"))) {
                  // printf("Colon line: %s\n", line);
                  strncat(longline, colon+1, sizeof(longline)-strlen(longline)-1);
                  parseline = longline;
                  joined_lines = 1;
                  line = strtok(NULL, "\r\n>");
            }
            // We gracefully handle these lines without
            //   needing to actually parse them
            if(3 >= strlen(parseline)) continue;

            // printf("parseline: %s\n", parseline);

            unsigned int local_rets[20];
            unsigned int vals_read;

            ret = parseobdline(parseline, mode, cmd,
                  local_rets, sizeof(local_rets)/sizeof(local_rets[0]), &vals_read, quiet);

            if(OBD_SUCCESS == ret) {
                  int i;
                  for(i=0; i<vals_read; i++, values_returned++) {
                        retvals[values_returned] = local_rets[i];
                  }
                  break;
            }

            if(0 == joined_lines) {
                  // If we joined some lines together, this strtok was already done
                  line = strtok(NULL, "\r\n>");
            }
      }
      *numbytes_returned = values_returned;
      if(0 == values_returned) return ret;
      return OBD_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Generated by  Doxygen 1.6.0   Back to index