summaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
authorGregory Fong <gregory.fong@virginorbit.com>2018-07-29 17:21:24 -0700
committerGary E. Miller <gem@rellim.com>2018-07-29 17:21:24 -0700
commitf41d577b6352e80919469ee1724a0b9ad4359e67 (patch)
tree7a96d9194937855ebaecc14bb254236d3ccc5940 /packet.c
parentd1f79455a50f92b3dbf68c2ad5196423d80ed78a (diff)
downloadgpsd-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.c153
1 files changed, 138 insertions, 15 deletions
diff --git a/packet.c b/packet.c
index 1df0070a..4c6fcc4e 100644
--- a/packet.c
+++ b/packet.c
@@ -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) {
/*