예제 #1
0
/**
 * \brief Find tail of packet ("\r\n") in buffer and check control sum (CRC).
 * @param buff a constant character pointer of packets buffer.
 * @param buff_sz buffer size.
 * @param res_crc a integer pointer for return CRC of packet (must be defined).
 * @return Number of bytes to packet tail.
 */
int nmea_find_tail(const char *buff, int buff_sz, int *res_crc)
{
    static const int tail_sz = 3 /* *[CRC] */ + 2 /* \r\n */;

    const char *end_buff = buff + buff_sz;  // EDIT: the end_buff can be a char instead a pointer to the last location of buffer
    int nread = 0;
    int crc = 0;

    NMEA_ASSERT(buff && res_crc);

    *res_crc = -1;

    for(;buff < end_buff; ++buff, ++nread)
    {
        if(('$' == *buff) && nread)
        {
            buff = 0;
            break;
        }
        else if('*' == *buff)
        {
            if(buff + tail_sz <= end_buff && '\r' == buff[3] && '\n' == buff[4])
            {
                *res_crc = nmea_atoi(buff + 1, 2, 16);
                nread = buff_sz - (int)(end_buff - (buff + tail_sz));
                if(*res_crc != crc)
                {
                    *res_crc = -1;
                    buff = 0;
                }
            }

            break;
        }
        else if(nread)
            crc ^= (int)*buff;
    }

    if(*res_crc < 0 && buff)
        nread = 0;

    return nread;
}
예제 #2
0
파일: parse.c 프로젝트: ElmarSieke/nmealib
/**
 * Find the tail ("\r\n") of a sentence in a string and check the checksum of the sentence.
 *
 * @param s the string
 * @param len the length of the string
 * @param checksum a pointer to the location where the checksum (as specified
 * in the sentence) should be stored (will be -1 if the checksum did not match
 * the calculated checksum or a new sentence was found in s after the start of s)
 * @return Number of bytes from the start of the string until the tail or 0
 * when no sentence was found
 */
int nmea_parse_get_sentence_length(const char *s, const int len, int *checksum) {
	static const int tail_sz = 1 + 2 + 2 /* *xx\r\n */;

	const char * s_end = s + len;
	int nread = 0;
	int cksum = 0;

	assert(s);
	assert(checksum);

	*checksum = -1;

	for (; s < s_end; s++, nread++) {
		if ((*s == '$') && nread) {
			/* found a new sentence start marker _after_ the first character of s */
			s = NULL; /* do not reset nread when exiting */
			break;
		}
		if ('*' == *s) {
			/* found a sentence checksum marker */
			if (((s + tail_sz) <= s_end) && ('\r' == s[3]) && ('\n' == s[4])) {
				*checksum = nmea_atoi(s + 1, 2, 16);
				nread = len - (int) (s_end - (s + tail_sz));
				if (*checksum != cksum) {
					*checksum = -1;
					s = NULL; /* do not reset nread when exiting */
				}
			}
			break;
		}
		if (nread) {
			cksum ^= (int) *s;
		}
	}

	if (s && (*checksum < 0))
		nread = 0;

	return nread;
}
예제 #3
0
파일: parser.c 프로젝트: RTsien/nmealib
static bool nmea_parse_sentence_character(nmeaPARSER *parser, const char * c) {
  assert(parser);

  /* always reset when we encounter a start-of-sentence character */
  if (*c == '$') {
    reset_sentence_parser(parser, READ_SENTENCE);
    parser->buffer.buffer[parser->buffer.length++] = *c;
    return false;
  }

  /* just return when we haven't encountered a start-of-sentence character yet */
  if (parser->sentence_parser.state == SKIP_UNTIL_START) {
    return false;
  }

  /* this character belongs to the sentence */

  /* check whether the sentence still fits in the buffer */
  if (parser->buffer.length >= SENTENCE_SIZE) {
    reset_sentence_parser(parser, SKIP_UNTIL_START);
    return false;
  }

  parser->buffer.buffer[parser->buffer.length++] = *c;

  switch (parser->sentence_parser.state) {
    case READ_SENTENCE:
      if (*c == '*') {
        parser->sentence_parser.state = READ_CHECKSUM;
        parser->sentence_parser.sentence_checksum_chars_count = 0;
      } else if (*c == first_eol_char) {
        parser->sentence_parser.state = READ_EOL;
        parser->sentence_parser.sentence_eol_chars_count = 1;
      } else if (isInvalidNMEACharacter(c)) {
        reset_sentence_parser(parser, SKIP_UNTIL_START);
      } else {
        parser->sentence_parser.calculated_checksum ^= (int) *c;
      }
      break;

    case READ_CHECKSUM:
      if (!isHexChar(*c)) {
        reset_sentence_parser(parser, SKIP_UNTIL_START);
      } else {
        switch (parser->sentence_parser.sentence_checksum_chars_count) {
          case 0:
            parser->sentence_parser.sentence_checksum_chars[0] = *c;
            parser->sentence_parser.sentence_checksum_chars[1] = 0;
            parser->sentence_parser.sentence_checksum_chars_count = 1;
            break;

          case 1:
            parser->sentence_parser.sentence_checksum_chars[1] = *c;
            parser->sentence_parser.sentence_checksum_chars_count = 2;
            parser->sentence_parser.sentence_checksum = nmea_atoi(parser->sentence_parser.sentence_checksum_chars, 2, 16);
            parser->sentence_parser.has_checksum = true;
            parser->sentence_parser.state = READ_EOL;
            break;

          default:
            reset_sentence_parser(parser, SKIP_UNTIL_START);
            break;
          }
      }
      break;


    case READ_EOL:
      switch (parser->sentence_parser.sentence_eol_chars_count) {
        case 0:
          if (*c != first_eol_char) {
            reset_sentence_parser(parser, SKIP_UNTIL_START);
          } else {
            parser->sentence_parser.sentence_eol_chars_count = 1;
          }
          break;

        case 1:
          if (*c != second_eol_char) {
            reset_sentence_parser(parser, SKIP_UNTIL_START);
          } else {
            parser->sentence_parser.state = SKIP_UNTIL_START;
            return (!parser->sentence_parser.sentence_checksum_chars_count
                || (parser->sentence_parser.sentence_checksum_chars_count
                    && (parser->sentence_parser.sentence_checksum == parser->sentence_parser.calculated_checksum)));
          }
          break;

        default:
          reset_sentence_parser(parser, SKIP_UNTIL_START);
          break;
      }
      break;

      /* can't occur, but keep compiler happy */
      case SKIP_UNTIL_START:
      default:
        break;

  }

  return false;
}