diff options
author | Gregory Fong <gregory.fong@virginorbit.com> | 2018-07-29 17:21:24 -0700 |
---|---|---|
committer | Gary E. Miller <gem@rellim.com> | 2018-07-29 17:21:24 -0700 |
commit | f41d577b6352e80919469ee1724a0b9ad4359e67 (patch) | |
tree | 7a96d9194937855ebaecc14bb254236d3ccc5940 /packet.c | |
parent | d1f79455a50f92b3dbf68c2ad5196423d80ed78a (diff) | |
download | gpsd-f41d577b6352e80919469ee1724a0b9ad4359e67.tar.gz |
Add GREIS (Javad) GPS driver.
All functional changes inside "#ifdef GREIS_ENABLE"
Includes new regression tests. All regressions tests
pass.
Developed by Gregory Fong, with help and support from
Virgin Orbit.
Signed-off-by: Gary E. Miller <gem@rellim.com>
Diffstat (limited to 'packet.c')
-rw-r--r-- | packet.c | 153 |
1 files changed, 138 insertions, 15 deletions
@@ -38,6 +38,7 @@ PERMISSIONS #include <unistd.h> #include "bits.h" +#include "driver_greis.h" #include "gpsd.h" #include "crc24q.h" #include "strfuncs.h" @@ -196,6 +197,23 @@ static size_t oncore_payload_cksum_length(unsigned char id1, unsigned char id2) } #endif /* ONCORE_ENABLE */ +#ifdef GREIS_ENABLE + +static unsigned long greis_hex2bin(char c) +/* Convert hex char to binary form. Requires that c be a hex char. */ +{ + if ((c >= 'a') && (c <= 'f')) + c = c + 10 - 'a'; + else if ((c >= 'A') && (c <= 'F')) + c = c + 10 - 'A'; + else if ((c >= '0') && (c <= '9')) + c -= '0'; + + return c; +} + +#endif /* GREIS_ENABLE */ + static bool character_pushback(struct gps_lexer_t *lexer, unsigned int newstate) /* push back the last character grabbed, setting a specified state */ { @@ -215,6 +233,21 @@ static bool character_pushback(struct gps_lexer_t *lexer, unsigned int newstate) return false; } +static void character_discard(struct gps_lexer_t *lexer) +/* shift the input buffer to discard one character and reread data */ +{ + memmove(lexer->inbuffer, lexer->inbuffer + 1, (size_t)-- lexer->inbuflen); + lexer->inbufptr = lexer->inbuffer; + if (lexer->errout.debug >= LOG_RAW+1) { + char scratchbuf[MAX_PACKET_LENGTH*4+1]; + gpsd_log(&lexer->errout, LOG_RAW + 1, + "Character discarded, buffer %zu chars = %s\n", + lexer->inbuflen, + gpsd_packetdump(scratchbuf, sizeof(scratchbuf), + (char *)lexer->inbuffer, lexer->inbuflen)); + } +} + static bool nextstate(struct gps_lexer_t *lexer, unsigned char c) { static int n = 0; @@ -329,6 +362,17 @@ static bool nextstate(struct gps_lexer_t *lexer, unsigned char c) break; } #endif /* GEOSTAR_ENABLE */ +#ifdef GREIS_ENABLE + if (c == 'R') { + lexer->state = GREIS_REPLY_1; + break; + } + /* Not the only possibility, but it is a distinctive cycle starter. */ + if (c == '~') { + lexer->state = GREIS_ID_1; + break; + } +#endif /* GREIS_ENABLE */ #ifdef RTCM104V2_ENABLE if ((isgpsstat = rtcm2_decode(lexer, c)) == ISGPS_SYNC) { lexer->state = RTCM2_SYNC_STATE; @@ -1360,6 +1404,57 @@ static bool nextstate(struct gps_lexer_t *lexer, unsigned char c) return character_pushback(lexer, GROUND_STATE); break; #endif /* GEOSTAR_ENABLE */ +#ifdef GREIS_ENABLE + case GREIS_EXPECTED: + case GREIS_RECOGNIZED: + if (!isascii(c)) { + return character_pushback(lexer, GROUND_STATE); + } else if (c == '#') { + /* Probably a comment used by the testsuite */ + lexer->state = COMMENT_BODY; + } else if (c == '\r' || c == '\n') { + /* Arbitrary CR/LF allowed here, so continue to expect GREIS */ + lexer->state = GREIS_EXPECTED; + character_discard(lexer); + } else { + lexer->state = GREIS_ID_1; + } + break; + case GREIS_REPLY_1: + if (c != 'E') + return character_pushback(lexer, GROUND_STATE); + lexer->state = GREIS_REPLY_2; + break; + case GREIS_ID_1: + if (!isascii(c)) + return character_pushback(lexer, GROUND_STATE); + lexer->state = GREIS_ID_2; + break; + case GREIS_REPLY_2: + case GREIS_ID_2: + if (!isxdigit(c)) + return character_pushback(lexer, GROUND_STATE); + lexer->length = greis_hex2bin(c) << 8; + lexer->state = GREIS_LENGTH_1; + break; + case GREIS_LENGTH_1: + if (!isxdigit(c)) + return character_pushback(lexer, GROUND_STATE); + lexer->length += greis_hex2bin(c) << 4; + lexer->state = GREIS_LENGTH_2; + break; + case GREIS_LENGTH_2: + if (!isxdigit(c)) + return character_pushback(lexer, GROUND_STATE); + lexer->length += greis_hex2bin(c); + lexer->state = GREIS_PAYLOAD; + break; + case GREIS_PAYLOAD: + if (--lexer->length == 0) + lexer->state = GREIS_RECOGNIZED; + /* else stay in payload state */ + break; +#endif /* GREIS_ENABLE */ #ifdef TSIP_ENABLE case TSIP_LEADER: /* unused case */ @@ -1619,21 +1714,6 @@ static void packet_unstash(struct gps_lexer_t *lexer) } #endif /* STASH_ENABLE */ -static void character_discard(struct gps_lexer_t *lexer) -/* shift the input buffer to discard one character and reread data */ -{ - memmove(lexer->inbuffer, lexer->inbuffer + 1, (size_t)-- lexer->inbuflen); - lexer->inbufptr = lexer->inbuffer; - if (lexer->errout.debug >= LOG_RAW+1) { - char scratchbuf[MAX_PACKET_LENGTH*4+1]; - gpsd_log(&lexer->errout, LOG_RAW + 1, - "Character discarded, buffer %zu chars = %s\n", - lexer->inbuflen, - gpsd_packetdump(scratchbuf, sizeof(scratchbuf), - (char *)lexer->inbuffer, lexer->inbuflen)); - } -} - /* get 0-origin big-endian words relative to start of packet buffer */ #define getword(i) (short)(lexer->inbuffer[2*(i)] | (lexer->inbuffer[2*(i)+1] << 8)) @@ -2298,6 +2378,49 @@ void packet_parse(struct gps_lexer_t *lexer) break; } #endif /* GEOSTAR_ENABLE */ +#ifdef GREIS_ENABLE + else if (lexer->state == GREIS_RECOGNIZED) { + int len = lexer->inbufptr - lexer->inbuffer; + + if (lexer->inbuffer[0] == 'R' && lexer->inbuffer[1] == 'E') { + /* Replies don't have checksum */ + gpsd_log(&lexer->errout, LOG_IO, + "Accept GREIS reply packet len %d\n", len); + packet_accept(lexer, GREIS_PACKET); + } else if (lexer->inbuffer[0] == 'E' && lexer->inbuffer[1] == 'R') { + /* Error messages don't have checksum */ + gpsd_log(&lexer->errout, LOG_IO, + "Accept GREIS error packet len %d\n", len); + packet_accept(lexer, GREIS_PACKET); + } else { + unsigned char expected_cs = lexer->inbuffer[len - 1]; + unsigned char cs = greis_checksum(lexer->inbuffer, len - 1); + + if (cs == expected_cs) { + gpsd_log(&lexer->errout, LOG_IO, + "Accept GREIS packet type '%c%c' len %d\n", + lexer->inbuffer[0], lexer->inbuffer[1], len); + packet_accept(lexer, GREIS_PACKET); + } else { + /* + * Print hex instead of raw characters, since they might be + * unprintable. If \0, it will even mess up the log output. + */ + gpsd_log(&lexer->errout, LOG_IO, + "REJECT GREIS len %d." + " Bad checksum %#02x, expecting %#02x." + " Packet type in hex: 0x%02x%02x", + len, cs, expected_cs, lexer->inbuffer[0], + lexer->inbuffer[1]); + packet_accept(lexer, BAD_PACKET); + /* got this far, fair to expect we will get more GREIS */ + lexer->state = GREIS_EXPECTED; + } + } + packet_discard(lexer); + break; + } +#endif /* GREIS_ENABLE */ #ifdef RTCM104V2_ENABLE else if (lexer->state == RTCM2_RECOGNIZED) { /* |