1 /****************************************************************************
4 packet.c -- a packet-sniffing engine for reading from GPS devices
8 Initial conditions of the problem:
10 1. We have a file descriptor open for (possibly non-blocking) read. The device
11 on the other end is sending packets at us.
13 2. It may require more than one read to gather a packet. Reads may span packet
16 3. There may be leading garbage before the first packet. After the first
17 start-of-packet, the input should be well-formed.
19 The problem: how do we recognize which kind of packet we're getting?
21 No need to handle Garmin USB binary, we know that type by the fact we're
22 connected to the Garmin kernel driver. But we need to be able to tell the
23 others apart and distinguish them from baud barf.
26 This file is Copyright (c) 2010 by the GPSD project
27 BSD terms apply: see the file COPYING in the distribution root for details.
29 ***************************************************************************/
31 #include "gpsd_config.h"
32 #include <sys/types.h>
37 #endif /* S_SPLINT_S */
41 #ifdef HAVE_NETINET_IN_H
42 #include <netinet/in.h> /* for htons() */
43 #endif /* HAVE_NETNET_IN_H */
44 #ifdef HAVE_ARPA_INET_H
45 #include <arpa/inet.h> /* for htons() */
46 #endif /* HAVE_ARPA_INET_H */
47 #endif /* S_SPLINT_S */
54 * The packet-recognition state machine. This takes an incoming byte stream
55 * and tries to segment it into packets. There are three types of packets:
57 * 1) Comments. These begin with # and end with \r\n.
59 * 2) NMEA lines. These begin with $, and with \r\n, and have a checksum.
61 * 3) Binary packets. These begin with some fixed leader character(s),
62 * have a length embedded in them, and end with a checksum (and possibly)
63 * some fixed trailing bytes.
65 * 4) ISGPS packets. The input may be a bitstream containing IS-GPS-200
66 * packets. Each includes a fixed leader byte, a length, and check bits.
67 * In this case, it is not guaranted that packet starts begin on byte
68 * bounaries; the recognizer has to run a separate state machine against
69 * each byte just to achieve synchronization lock with the bitstream.
71 * Adding support for a new GPS protocol typically reqires adding state
72 * transitions to support whatever binary packet structure it has. The
73 * goal is for the lexer to be able to cope with arbitrarily mixed packet
74 * types on the input stream. This is a requirement because (1) sometimes
75 * gpsd wants to switch a device that supports both NMEA and a binary
76 * packet protocol to the latter for more detailed reporting, and (b) in
77 * the presence of device hotplugging, the type of GPS report coming
78 * in is subject to change at any time.
80 * Caller should consume a packet when it sees one of the *_RECOGNIZED
81 * states. It's good practice to follow the _RECOGNIZED transition
82 * with one that recognizes a leader of the same packet type rather
83 * than dropping back to ground state -- this for example will prevent
84 * the state machine from hopping between recognizing TSIP and
85 * EverMore packets that both start with a DLE.
87 * Error handling is brutally simple; any time we see an unexpected
88 * character, go to GROUND_STATE and reset the machine (except that a
89 * $ in an NMEA payload only resets back to NMEA_DOLLAR state). Because
90 * another good packet will usually be along in less than a second
91 * repeating the same data, Boyer-Moore-like attempts to do parallel
92 * recognition beyond the headers would make no sense in this
93 * application, they'd just add complexity.
95 * The NMEA portion of the state machine allows the following talker IDs:
96 * GP -- Global Positioning System.
97 * GL -- GLONASS, according to IEIC 61162-1
98 * GN -- Mixed GPS and GLONASS data, according to IEIC 61162-1
99 * II -- Integrated Instrumentation (Raytheon's SeaTalk system).
100 * IN -- Integrated Navigation (Garmin uses this).
106 #include "packet_states.h"
109 #define SOH (unsigned char)0x01
110 #define DLE (unsigned char)0x10
111 #define STX (unsigned char)0x02
112 #define ETX (unsigned char)0x03
114 static void character_pushback(struct gps_packet_t *lexer)
115 /* push back the last character grabbed */
117 /*@-modobserver@*//* looks like a splint bug */
120 --lexer->char_counter;
121 gpsd_report(LOG_RAW + 2, "%08ld: character pushed back\n",
122 lexer->char_counter);
125 static void nextstate(struct gps_packet_t *lexer, unsigned char c)
127 #ifdef RTCM104V2_ENABLE
128 enum isgpsstat_t isgpsstat;
129 #endif /* RTCM104V2_ENABLE */
130 #ifdef SUPERSTAR2_ENABLE
131 static unsigned char ctmp;
132 #endif /* SUPERSTAR2_ENABLE */
133 /*@ +charint -casebreak @*/
134 switch (lexer->state) {
137 lexer->state = COMMENT_BODY;
142 lexer->state = NMEA_DOLLAR;
146 lexer->state = NMEA_BANG;
149 #endif /* NMEA_ENABLE */
150 #if defined(TNT_ENABLE) || defined(GARMINTXT_ENABLE) || defined(ONCORE_ENABLE)
152 lexer->state = AT1_LEADER;
158 lexer->state = SIRF_LEADER_1;
161 #endif /* SIRF_ENABLE */
162 #ifdef SUPERSTAR2_ENABLE
164 lexer->state = SUPERSTAR2_LEADER;
167 #endif /* SUPERSTAR2_ENABLE */
168 #if defined(TSIP_ENABLE) || defined(EVERMORE_ENABLE) || defined(GARMIN_ENABLE)
170 lexer->state = DLE_LEADER;
173 #endif /* TSIP_ENABLE || EVERMORE_ENABLE || GARMIN_ENABLE */
174 #ifdef TRIPMATE_ENABLE
176 #ifdef RTCM104V2_ENABLE
177 if (rtcm2_decode(lexer, c) == ISGPS_MESSAGE) {
178 lexer->state = RTCM2_RECOGNIZED;
181 #endif /* RTCM104V2_ENABLE */
182 lexer->state = ASTRAL_1;
185 #endif /* TRIPMATE_ENABLE */
186 #ifdef EARTHMATE_ENABLE
188 #ifdef RTCM104V2_ENABLE
189 if (rtcm2_decode(lexer, c) == ISGPS_MESSAGE) {
190 lexer->state = RTCM2_RECOGNIZED;
193 #endif /* RTCM104V2_ENABLE */
194 lexer->state = EARTHA_1;
197 #endif /* EARTHMATE_ENABLE */
200 lexer->state = ZODIAC_LEADER_1;
203 #endif /* ZODIAC_ENABLE */
206 lexer->state = UBX_LEADER_1;
209 #endif /* UBX_ENABLE */
212 lexer->state = ITALK_LEADER_1;
215 #endif /* ITRAX_ENABLE */
218 lexer->state = NAVCOM_LEADER_1;
221 #endif /* NAVCOM_ENABLE */
222 #ifdef RTCM104V2_ENABLE
223 if ((isgpsstat = rtcm2_decode(lexer, c)) == ISGPS_SYNC) {
224 lexer->state = RTCM2_SYNC_STATE;
226 } else if (isgpsstat == ISGPS_MESSAGE) {
227 lexer->state = RTCM2_RECOGNIZED;
230 #endif /* RTCM104V2_ENABLE */
231 #ifdef RTCM104V3_ENABLE
233 lexer->state = RTCM3_LEADER_1;
236 #endif /* RTCM104V3_ENABLE */
240 lexer->state = COMMENT_RECOGNIZED;
241 else if (!isprint(c))
242 lexer->state = GROUND_STATE;
247 lexer->state = NMEA_PUB_LEAD;
248 else if (c == 'P') /* vendor sentence */
249 lexer->state = NMEA_VENDOR_LEAD;
250 else if (c == 'I') /* Seatalk */
251 lexer->state = SEATALK_LEAD_1;
252 else if (c == 'A') /* SiRF Ack */
253 lexer->state = SIRF_ACK_LEAD_1;
254 #ifdef OCEANSERVER_ENABLE
256 lexer->state = NMEA_LEADER_END;
257 #endif /* OCEANSERVER_ENABLE */
259 lexer->state = GROUND_STATE;
263 * $GP == GPS, $GL = GLONASS only, $GN = mixed GPS and GLONASS,
264 * according to NMEA (IEIC 61162-1) DRAFT 02/06/2009.
266 if (c == 'P' || c == 'N' || c == 'L')
267 lexer->state = NMEA_LEADER_END;
269 lexer->state = GROUND_STATE;
271 case NMEA_VENDOR_LEAD:
273 lexer->state = NMEA_PASHR_A;
275 lexer->state = NMEA_LEADER_END;
277 lexer->state = GROUND_STATE;
280 * Without the following six states, DLE in a $PASHR can fool the
281 * sniffer into thinking it sees a TSIP packet. Hilarity ensues.
285 lexer->state = NMEA_PASHR_S;
287 lexer->state = NMEA_LEADER_END;
289 lexer->state = GROUND_STATE;
293 lexer->state = NMEA_PASHR_H;
295 lexer->state = NMEA_LEADER_END;
297 lexer->state = GROUND_STATE;
301 lexer->state = NMEA_BINARY_BODY;
303 lexer->state = NMEA_LEADER_END;
305 lexer->state = GROUND_STATE;
307 case NMEA_BINARY_BODY:
309 lexer->state = NMEA_BINARY_CR;
313 lexer->state = NMEA_BINARY_NL;
315 lexer->state = NMEA_BINARY_BODY;
319 character_pushback(lexer);
320 lexer->state = NMEA_RECOGNIZED; /* CRC will reject it */
322 lexer->state = NMEA_BINARY_BODY;
326 lexer->state = AIS_LEAD_1;
328 lexer->state = GROUND_STATE;
332 lexer->state = AIS_LEAD_2;
334 lexer->state = GROUND_STATE;
338 lexer->state = NMEA_LEADER_END;
340 lexer->state = GROUND_STATE;
342 #if defined(TNT_ENABLE) || defined(GARMINTXT_ENABLE) || defined(ONCORE_ENABLE)
347 lexer->state = ONCORE_AT2;
349 #endif /* ONCORE_ENABLE */
353 * TNT has similar structure to NMEA packet, '*' before
354 * optional checksum ends the packet. Since '*' cannot be
355 * received from GARMIN working in TEXT mode, use this
356 * difference to tell that this is not GARMIN TEXT packet,
359 lexer->state = NMEA_LEADER_END;
361 #endif /* TNT_ENABLE */
362 #if defined(GARMINTXT_ENABLE)
364 /* stay in this state, next character should be '\n' */
365 /* in the theory we can stop search here and don't wait for '\n' */
366 lexer->state = AT1_LEADER;
369 /* end of packet found */
370 lexer->state = GTXT_RECOGNIZED;
372 #endif /* GARMINTXT_ENABLE */
375 lexer->state = GROUND_STATE;
378 #endif /* defined(TNT_ENABLE) || defined(GARMINTXT_ENABLE) || defined(ONCORE_ENABLE) */
379 case NMEA_LEADER_END:
381 lexer->state = NMEA_CR;
383 /* not strictly correct, but helps for interpreting logfiles */
384 lexer->state = NMEA_RECOGNIZED;
386 /* faster recovery from missing sentence trailers */
387 lexer->state = NMEA_DOLLAR;
388 else if (!isprint(c))
389 lexer->state = GROUND_STATE;
393 lexer->state = NMEA_RECOGNIZED;
395 * There's a GPS called a Jackson Labs Firefly-1a that emits \r\r\n
396 * at the end of each sentence. Don't be confused by this.
399 lexer->state = NMEA_CR;
401 lexer->state = GROUND_STATE;
403 case NMEA_RECOGNIZED:
405 lexer->state = COMMENT_BODY;
407 lexer->state = NMEA_DOLLAR;
409 lexer->state = NMEA_BANG;
411 else if (c == 0xb5) /* LEA-5H can and will output NMEA and UBX back to back */
412 lexer->state = UBX_LEADER_1;
415 lexer->state = GROUND_STATE;
418 if (c == 'I' || c == 'N') /* II or IN are accepted */
419 lexer->state = NMEA_LEADER_END;
421 lexer->state = GROUND_STATE;
423 #ifdef TRIPMATE_ENABLE
426 #ifdef RTCM104V2_ENABLE
427 if (rtcm2_decode(lexer, c) == ISGPS_MESSAGE) {
428 lexer->state = RTCM2_RECOGNIZED;
431 #endif /* RTCM104V2_ENABLE */
432 lexer->state = ASTRAL_2;
434 lexer->state = GROUND_STATE;
438 #ifdef RTCM104V2_ENABLE
439 if (rtcm2_decode(lexer, c) == ISGPS_MESSAGE) {
440 lexer->state = RTCM2_RECOGNIZED;
443 #endif /* RTCM104V2_ENABLE */
444 lexer->state = ASTRAL_3;
446 lexer->state = GROUND_STATE;
450 #ifdef RTCM104V2_ENABLE
451 if (rtcm2_decode(lexer, c) == ISGPS_MESSAGE) {
452 lexer->state = RTCM2_RECOGNIZED;
455 #endif /* RTCM104V2_ENABLE */
456 lexer->state = ASTRAL_5;
458 lexer->state = GROUND_STATE;
462 #ifdef RTCM104V2_ENABLE
463 if (rtcm2_decode(lexer, c) == ISGPS_MESSAGE) {
464 lexer->state = RTCM2_RECOGNIZED;
467 #endif /* RTCM104V2_ENABLE */
468 lexer->state = ASTRAL_2;
470 lexer->state = GROUND_STATE;
474 #ifdef RTCM104V2_ENABLE
475 if (rtcm2_decode(lexer, c) == ISGPS_MESSAGE) {
476 lexer->state = RTCM2_RECOGNIZED;
479 #endif /* RTCM104V2_ENABLE */
480 lexer->state = NMEA_RECOGNIZED;
482 lexer->state = GROUND_STATE;
484 #endif /* TRIPMATE_ENABLE */
485 #ifdef EARTHMATE_ENABLE
488 #ifdef RTCM104V2_ENABLE
489 if (rtcm2_decode(lexer, c) == ISGPS_MESSAGE) {
490 lexer->state = RTCM2_RECOGNIZED;
493 #endif /* RTCM104V2_ENABLE */
494 lexer->state = EARTHA_2;
496 lexer->state = GROUND_STATE;
500 #ifdef RTCM104V2_ENABLE
501 if (rtcm2_decode(lexer, c) == ISGPS_MESSAGE) {
502 lexer->state = RTCM2_RECOGNIZED;
505 #endif /* RTCM104V2_ENABLE */
506 lexer->state = EARTHA_3;
508 lexer->state = GROUND_STATE;
512 #ifdef RTCM104V2_ENABLE
513 if (rtcm2_decode(lexer, c) == ISGPS_MESSAGE) {
514 lexer->state = RTCM2_RECOGNIZED;
517 #endif /* RTCM104V2_ENABLE */
518 lexer->state = EARTHA_4;
520 lexer->state = GROUND_STATE;
524 #ifdef RTCM104V2_ENABLE
525 if (rtcm2_decode(lexer, c) == ISGPS_MESSAGE) {
526 lexer->state = RTCM2_RECOGNIZED;
529 #endif /* RTCM104V2_ENABLE */
530 lexer->state = EARTHA_5;
532 lexer->state = GROUND_STATE;
536 #ifdef RTCM104V2_ENABLE
537 if (rtcm2_decode(lexer, c) == ISGPS_MESSAGE) {
538 lexer->state = RTCM2_RECOGNIZED;
541 #endif /* RTCM104V2_ENABLE */
542 lexer->state = NMEA_RECOGNIZED;
544 lexer->state = GROUND_STATE;
546 #endif /* EARTHMATE_ENABLE */
547 case SIRF_ACK_LEAD_1:
549 lexer->state = SIRF_ACK_LEAD_2;
551 lexer->state = AIS_LEAD_2;
553 lexer->state = GROUND_STATE;
555 case SIRF_ACK_LEAD_2:
557 lexer->state = NMEA_LEADER_END;
559 lexer->state = GROUND_STATE;
561 #endif /* NMEA_ENABLE */
565 lexer->state = SIRF_LEADER_2;
567 lexer->state = GROUND_STATE;
570 lexer->length = (size_t) (c << 8);
571 lexer->state = SIRF_LENGTH_1;
574 lexer->length += c + 2;
575 if (lexer->length <= MAX_PACKET_LENGTH)
576 lexer->state = SIRF_PAYLOAD;
578 lexer->state = GROUND_STATE;
581 if (--lexer->length == 0)
582 lexer->state = SIRF_DELIVERED;
586 lexer->state = SIRF_TRAILER_1;
588 lexer->state = GROUND_STATE;
592 lexer->state = SIRF_RECOGNIZED;
594 lexer->state = GROUND_STATE;
596 case SIRF_RECOGNIZED:
598 lexer->state = SIRF_LEADER_1;
600 lexer->state = GROUND_STATE;
602 #endif /* SIRF_ENABLE */
603 #ifdef SUPERSTAR2_ENABLE
604 case SUPERSTAR2_LEADER:
606 lexer->state = SUPERSTAR2_ID1;
609 if ((ctmp ^ 0xff) == c)
610 lexer->state = SUPERSTAR2_ID2;
612 lexer->state = GROUND_STATE;
615 lexer->length = (size_t) c; /* how many data bytes follow this byte */
617 lexer->state = SUPERSTAR2_PAYLOAD;
619 lexer->state = SUPERSTAR2_CKSUM1; /* no data, jump to checksum */
621 case SUPERSTAR2_PAYLOAD:
622 if (--lexer->length == 0)
623 lexer->state = SUPERSTAR2_CKSUM1;
625 case SUPERSTAR2_CKSUM1:
626 lexer->state = SUPERSTAR2_CKSUM2;
628 case SUPERSTAR2_CKSUM2:
629 lexer->state = SUPERSTAR2_RECOGNIZED;
631 case SUPERSTAR2_RECOGNIZED:
633 lexer->state = SUPERSTAR2_LEADER;
635 lexer->state = GROUND_STATE;
637 #endif /* SUPERSTAR2_ENABLE */
641 lexer->length = (size_t) c;
642 lexer->state = ONCORE_ID1;
644 lexer->state = GROUND_STATE;
649 oncore_payload_cksum_length((unsigned char)lexer->length, c);
650 if (lexer->length != 0) {
651 lexer->state = ONCORE_PAYLOAD;
655 lexer->state = GROUND_STATE;
658 if (--lexer->length == 0)
659 lexer->state = ONCORE_CHECKSUM;
661 case ONCORE_CHECKSUM:
663 lexer->state = GROUND_STATE;
665 lexer->state = ONCORE_CR;
669 lexer->state = ONCORE_RECOGNIZED;
671 lexer->state = ONCORE_PAYLOAD;
673 case ONCORE_RECOGNIZED:
675 lexer->state = AT1_LEADER;
677 lexer->state = GROUND_STATE;
679 #endif /* ONCORE_ENABLE */
680 #if defined(TSIP_ENABLE) || defined(EVERMORE_ENABLE) || defined(GARMIN_ENABLE)
682 #ifdef EVERMORE_ENABLE
684 lexer->state = EVERMORE_LEADER_2;
687 #endif /* EVERMORE_ENABLE */
688 #if defined(TSIP_ENABLE) || defined(GARMIN_ENABLE) || defined(NAVCOM_ENABLE)
689 /* garmin is special case of TSIP */
690 /* check last because there's no checksum */
691 #if defined(TSIP_ENABLE)
693 lexer->state = TSIP_PAYLOAD;
696 #endif /* TSIP_ENABLE */
698 lexer->state = GROUND_STATE;
701 // FALL-THRU!!!!! no break here
702 #endif /* TSIP_ENABLE */
704 case NAVCOM_LEADER_1:
706 lexer->state = NAVCOM_LEADER_2;
708 lexer->state = GROUND_STATE;
710 case NAVCOM_LEADER_2:
712 lexer->state = NAVCOM_LEADER_3;
714 lexer->state = GROUND_STATE;
716 case NAVCOM_LEADER_3:
717 lexer->state = NAVCOM_ID;
720 lexer->length = (size_t) c - 4;
721 lexer->state = NAVCOM_LENGTH_1;
723 case NAVCOM_LENGTH_1:
724 lexer->length += (c << 8);
725 lexer->state = NAVCOM_LENGTH_2;
727 case NAVCOM_LENGTH_2:
728 if (--lexer->length == 0)
729 lexer->state = NAVCOM_PAYLOAD;
734 unsigned char csum = lexer->inbuffer[3];
736 (unsigned char *)(lexer->inbuffer + n) < lexer->inbufptr - 1;
738 csum ^= lexer->inbuffer[n];
741 "Navcom packet type 0x%hx bad checksum 0x%hx, expecting 0x%hx\n",
742 lexer->inbuffer[3], csum, c);
743 gpsd_report(LOG_RAW, "Navcom packet dump: %s\n",
744 gpsd_hexdump_wrapper(lexer->inbuffer, lexer->inbuflen,
746 lexer->state = GROUND_STATE;
750 lexer->state = NAVCOM_CSUM;
754 lexer->state = NAVCOM_RECOGNIZED;
756 lexer->state = GROUND_STATE;
758 case NAVCOM_RECOGNIZED:
760 lexer->state = NAVCOM_LEADER_1;
762 lexer->state = GROUND_STATE;
764 #endif /* NAVCOM_ENABLE */
765 #endif /* TSIP_ENABLE || EVERMORE_ENABLE || GARMIN_ENABLE */
766 #ifdef RTCM104V3_ENABLE
768 if ((c & 0xFC) == 0) {
769 lexer->length = (size_t) (c << 8);
770 lexer->state = RTCM3_LEADER_2;
773 lexer->state = GROUND_STATE;
777 lexer->length += 3; /* to get the three checksum bytes */
778 lexer->state = RTCM3_PAYLOAD;
781 if (--lexer->length == 0)
782 lexer->state = RTCM3_RECOGNIZED;
784 #endif /* RTCM104V3_ENABLE */
786 case ZODIAC_EXPECTED:
787 case ZODIAC_RECOGNIZED:
789 lexer->state = ZODIAC_LEADER_1;
791 lexer->state = GROUND_STATE;
793 case ZODIAC_LEADER_1:
795 lexer->state = ZODIAC_LEADER_2;
797 lexer->state = GROUND_STATE;
799 case ZODIAC_LEADER_2:
800 lexer->state = ZODIAC_ID_1;
803 lexer->state = ZODIAC_ID_2;
806 lexer->length = (size_t) c;
807 lexer->state = ZODIAC_LENGTH_1;
809 case ZODIAC_LENGTH_1:
810 lexer->length += (c << 8);
811 lexer->state = ZODIAC_LENGTH_2;
813 case ZODIAC_LENGTH_2:
814 lexer->state = ZODIAC_FLAGS_1;
817 lexer->state = ZODIAC_FLAGS_2;
820 lexer->state = ZODIAC_HSUM_1;
824 #define getword(i) (short)(lexer->inbuffer[2*(i)] | (lexer->inbuffer[2*(i)+1] << 8))
825 short sum = getword(0) + getword(1) + getword(2) + getword(3);
827 if (sum != getword(4)) {
829 "Zodiac Header checksum 0x%hx expecting 0x%hx\n",
831 lexer->state = GROUND_STATE;
835 gpsd_report(LOG_RAW + 1, "Zodiac header id=%hd len=%hd flags=%hx\n",
836 getword(1), getword(2), getword(3));
838 if (lexer->length == 0) {
839 lexer->state = ZODIAC_RECOGNIZED;
842 lexer->length *= 2; /* word count to byte count */
843 lexer->length += 2; /* checksum */
844 /* 10 bytes is the length of the Zodiac header */
845 if (lexer->length <= MAX_PACKET_LENGTH - 10)
846 lexer->state = ZODIAC_PAYLOAD;
848 lexer->state = GROUND_STATE;
851 if (--lexer->length == 0)
852 lexer->state = ZODIAC_RECOGNIZED;
854 #endif /* ZODIAC_ENABLE */
858 lexer->state = UBX_LEADER_2;
860 lexer->state = GROUND_STATE;
863 lexer->state = UBX_CLASS_ID;
866 lexer->state = UBX_MESSAGE_ID;
869 lexer->length = (size_t) c;
870 lexer->state = UBX_LENGTH_1;
873 lexer->length += (c << 8);
874 if (lexer->length <= MAX_PACKET_LENGTH)
875 lexer->state = UBX_LENGTH_2;
877 lexer->state = GROUND_STATE;
880 lexer->state = UBX_PAYLOAD;
883 if (--lexer->length == 0)
884 lexer->state = UBX_CHECKSUM_A;
885 /* else stay in payload state */
888 lexer->state = UBX_RECOGNIZED;
892 lexer->state = UBX_LEADER_1;
894 else if (c == '$') /* LEA-5H can and will output NMEA and UBX back to back */
895 lexer->state = NMEA_DOLLAR;
896 #endif /* NMEA_ENABLE */
898 lexer->state = GROUND_STATE;
900 #endif /* UBX_ENABLE */
901 #ifdef EVERMORE_ENABLE
902 case EVERMORE_LEADER_1:
904 lexer->state = EVERMORE_LEADER_2;
906 lexer->state = GROUND_STATE;
908 case EVERMORE_LEADER_2:
909 lexer->length = (size_t) c;
911 lexer->state = EVERMORE_PAYLOAD_DLE;
913 lexer->state = EVERMORE_PAYLOAD;
915 case EVERMORE_PAYLOAD:
917 lexer->state = EVERMORE_PAYLOAD_DLE;
918 else if (--lexer->length == 0)
919 lexer->state = GROUND_STATE;
921 case EVERMORE_PAYLOAD_DLE:
924 lexer->state = EVERMORE_PAYLOAD;
927 lexer->state = EVERMORE_RECOGNIZED;
930 lexer->state = GROUND_STATE;
933 case EVERMORE_RECOGNIZED:
935 lexer->state = EVERMORE_LEADER_1;
937 lexer->state = GROUND_STATE;
939 #endif /* EVERMORE_ENABLE */
943 lexer->state = ITALK_LEADER_2;
945 lexer->state = GROUND_STATE;
948 lexer->length = (size_t) (lexer->inbuffer[6] & 0xff);
949 lexer->state = ITALK_LENGTH;
952 lexer->length += 1; /* fix number of words in payload */
953 lexer->length *= 2; /* convert to number of bytes */
954 lexer->length += 3; /* add trailer length */
955 lexer->state = ITALK_PAYLOAD;
958 /* lookahead for "<!" because sometimes packets are short but valid */
959 if ((c == '>') && (lexer->inbufptr[0] == '<') &&
960 (lexer->inbufptr[1] == '!')) {
961 lexer->state = ITALK_RECOGNIZED;
962 gpsd_report(LOG_IO, "ITALK: trying to process runt packet\n");
964 } else if (--lexer->length == 0)
965 lexer->state = ITALK_DELIVERED;
967 case ITALK_DELIVERED:
969 lexer->state = ITALK_RECOGNIZED;
971 lexer->state = GROUND_STATE;
973 case ITALK_RECOGNIZED:
975 lexer->state = ITALK_LEADER_1;
977 lexer->state = GROUND_STATE;
979 #endif /* ITRAX_ENABLE */
984 lexer->state = TSIP_PAYLOAD;
986 lexer->state = GROUND_STATE;
990 lexer->state = TSIP_DLE;
995 lexer->state = TSIP_RECOGNIZED;
998 lexer->state = TSIP_PAYLOAD;
1001 lexer->state = GROUND_STATE;
1005 case TSIP_RECOGNIZED:
1008 * Don't go to TSIP_LEADER state -- TSIP packets aren't
1009 * checksummed, so false positives are easy. We might be
1010 * looking at another DLE-stuffed protocol like EverMore
1011 * or Garmin streaming binary.
1013 lexer->state = DLE_LEADER;
1015 lexer->state = GROUND_STATE;
1017 #endif /* TSIP_ENABLE */
1018 #ifdef RTCM104V2_ENABLE
1019 case RTCM2_SYNC_STATE:
1020 case RTCM2_SKIP_STATE:
1021 if ((isgpsstat = rtcm2_decode(lexer, c)) == ISGPS_MESSAGE) {
1022 lexer->state = RTCM2_RECOGNIZED;
1024 } else if (isgpsstat == ISGPS_NO_SYNC)
1025 lexer->state = GROUND_STATE;
1028 case RTCM2_RECOGNIZED:
1029 if (rtcm2_decode(lexer, c) == ISGPS_SYNC) {
1030 lexer->state = RTCM2_SYNC_STATE;
1033 lexer->state = GROUND_STATE;
1035 #endif /* RTCM104V2_ENABLE */
1037 /*@ -charint +casebreak @*/
1042 static void packet_accept(struct gps_packet_t *lexer, int packet_type)
1043 /* packet grab succeeded, move to output buffer */
1045 size_t packetlen = lexer->inbufptr - lexer->inbuffer;
1046 if (packetlen < sizeof(lexer->outbuffer)) {
1047 memcpy(lexer->outbuffer, lexer->inbuffer, packetlen);
1048 lexer->outbuflen = packetlen;
1049 lexer->outbuffer[packetlen] = '\0';
1050 lexer->type = packet_type;
1052 gpsd_report(LOG_RAW + 1, "Packet type %d accepted %zu = %s\n",
1053 packet_type, packetlen,
1054 gpsd_hexdump_wrapper(lexer->outbuffer, lexer->outbuflen,
1056 #endif /* STATE_DEBUG */
1058 gpsd_report(LOG_ERROR, "Rejected too long packet type %d len %zu\n",
1059 packet_type, packetlen);
1063 static void packet_discard(struct gps_packet_t *lexer)
1064 /* shift the input buffer to discard all data up to current input pointer */
1066 size_t discard = lexer->inbufptr - lexer->inbuffer;
1067 size_t remaining = lexer->inbuflen - discard;
1068 lexer->inbufptr = memmove(lexer->inbuffer, lexer->inbufptr, remaining);
1069 lexer->inbuflen = remaining;
1071 gpsd_report(LOG_RAW + 1,
1072 "Packet discard of %zu, chars remaining is %zu = %s\n",
1074 gpsd_hexdump_wrapper(lexer->inbuffer, lexer->inbuflen,
1076 #endif /* STATE_DEBUG */
1079 static void character_discard(struct gps_packet_t *lexer)
1080 /* shift the input buffer to discard one character and reread data */
1082 memmove(lexer->inbuffer, lexer->inbuffer + 1, (size_t)-- lexer->inbuflen);
1083 lexer->inbufptr = lexer->inbuffer;
1085 gpsd_report(LOG_RAW + 1, "Character discarded, buffer %zu chars = %s\n",
1087 gpsd_hexdump_wrapper(lexer->inbuffer, lexer->inbuflen,
1089 #endif /* STATE_DEBUG */
1092 /* get 0-origin big-endian words relative to start of packet buffer */
1093 #define getword(i) (short)(lexer->inbuffer[2*(i)] | (lexer->inbuffer[2*(i)+1] << 8))
1095 /* entry points begin here */
1097 void packet_init( /*@out@*/ struct gps_packet_t *lexer)
1099 lexer->char_counter = 0;
1100 lexer->retry_counter = 0;
1101 packet_reset(lexer);
1104 void packet_parse(struct gps_packet_t *lexer)
1105 /* grab a packet from the input buffer */
1107 lexer->outbuflen = 0;
1108 while (packet_buffered_input(lexer) > 0) {
1109 /*@ -modobserver @*/
1110 unsigned char c = *lexer->inbufptr++;
1111 /*@ +modobserver @*/
1112 char *state_table[] = {
1113 #include "packet_names.h"
1115 nextstate(lexer, c);
1116 gpsd_report(LOG_RAW + 2,
1117 "%08ld: character '%c' [%02x], new state: %s\n",
1118 lexer->char_counter, (isprint(c) ? c : '.'), c,
1119 state_table[lexer->state]);
1120 lexer->char_counter++;
1122 if (lexer->state == GROUND_STATE) {
1123 character_discard(lexer);
1124 } else if (lexer->state == COMMENT_RECOGNIZED) {
1125 packet_accept(lexer, COMMENT_PACKET);
1126 packet_discard(lexer);
1127 lexer->state = GROUND_STATE;
1131 else if (lexer->state == NMEA_RECOGNIZED) {
1132 bool checksum_ok = true;
1133 char csum[3] = { '0', '0', '0' };
1136 * Back up past any whitespace. Need to do this because
1137 * at least one GPS (the Firefly 1a) emits \r\r\n
1139 for (end = (char *)lexer->inbufptr - 1; isspace(*end); end--)
1141 while (strchr("0123456789ABCDEF", *end))
1144 unsigned int n, crc = 0;
1145 for (n = 1; (char *)lexer->inbuffer + n < end; n++)
1146 crc ^= lexer->inbuffer[n];
1147 (void)snprintf(csum, sizeof(csum), "%02X", crc);
1148 checksum_ok = (csum[0] == toupper(end[1])
1149 && csum[1] == toupper(end[2]));
1153 if (strncmp((char *)lexer->inbuffer, "!AIVDM", 6) == 0)
1154 packet_accept(lexer, AIVDM_PACKET);
1156 #endif /* AIVDM_ENABLE */
1157 packet_accept(lexer, NMEA_PACKET);
1159 gpsd_report(LOG_WARN,
1160 "bad checksum in NMEA packet; expected %s.\n",
1162 packet_accept(lexer, BAD_PACKET);
1163 lexer->state = GROUND_STATE;
1165 packet_discard(lexer);
1168 #endif /* NMEA_ENABLE */
1170 else if (lexer->state == SIRF_RECOGNIZED) {
1171 unsigned char *trailer = lexer->inbufptr - 4;
1172 unsigned int checksum =
1173 (unsigned)((trailer[0] << 8) | trailer[1]);
1174 unsigned int n, crc = 0;
1175 for (n = 4; n < (unsigned)(trailer - lexer->inbuffer); n++)
1176 crc += (int)lexer->inbuffer[n];
1178 if (checksum == crc)
1179 packet_accept(lexer, SIRF_PACKET);
1181 packet_accept(lexer, BAD_PACKET);
1182 lexer->state = GROUND_STATE;
1184 packet_discard(lexer);
1187 #endif /* SIRF_ENABLE */
1188 #ifdef SUPERSTAR2_ENABLE
1189 else if (lexer->state == SUPERSTAR2_RECOGNIZED) {
1192 lexer->length = 4 + (size_t) lexer->inbuffer[3] + 2;
1193 for (n = 0; n < lexer->length - 2; n++)
1194 a += (unsigned)lexer->inbuffer[n];
1195 b = (unsigned)getleuw(lexer->inbuffer, lexer->length - 2);
1196 gpsd_report(LOG_IO, "SuperStarII pkt dump: type %u len %u: %s\n",
1197 lexer->inbuffer[1], (unsigned int)lexer->length,
1198 gpsd_hexdump_wrapper(lexer->inbuffer, lexer->length,
1201 gpsd_report(LOG_IO, "REJECT SuperStarII packet type 0x%02x"
1202 "%zd bad checksum 0x%04x, expecting 0x%04x\n",
1203 lexer->inbuffer[1], lexer->length, a, b);
1204 packet_accept(lexer, BAD_PACKET);
1205 lexer->state = GROUND_STATE;
1207 packet_accept(lexer, SUPERSTAR2_PACKET);
1209 packet_discard(lexer);
1212 #endif /* SUPERSTAR2_ENABLE */
1213 #ifdef ONCORE_ENABLE
1214 else if (lexer->state == ONCORE_RECOGNIZED) {
1218 len = lexer->inbufptr - lexer->inbuffer;
1219 a = (char)(lexer->inbuffer[len - 3]);
1221 for (i = 2; i < len - 3; i++)
1222 b ^= lexer->inbuffer[i];
1224 gpsd_report(LOG_IO, "Accept OnCore packet @@%c%c len %d\n",
1225 lexer->inbuffer[2], lexer->inbuffer[3], len);
1226 packet_accept(lexer, ONCORE_PACKET);
1228 gpsd_report(LOG_IO, "REJECT OnCore packet @@%c%c len %d\n",
1229 lexer->inbuffer[2], lexer->inbuffer[3], len);
1230 packet_accept(lexer, BAD_PACKET);
1231 lexer->state = GROUND_STATE;
1233 packet_discard(lexer);
1236 #endif /* ONCORE_ENABLE */
1237 #if defined(TSIP_ENABLE) || defined(GARMIN_ENABLE)
1238 else if (lexer->state == TSIP_RECOGNIZED) {
1239 size_t packetlen = lexer->inbufptr - lexer->inbuffer;
1241 unsigned int pos, dlecnt;
1242 /* don't count stuffed DLEs in the length */
1244 for (pos = 0; pos < (unsigned int)packetlen; pos++)
1245 if (lexer->inbuffer[pos] == DLE)
1250 gpsd_report(LOG_RAW, "Unstuffed %d DLEs\n", dlecnt);
1251 packetlen -= dlecnt;
1253 #endif /* TSIP_ENABLE */
1254 if (packetlen < 5) {
1255 lexer->state = GROUND_STATE;
1257 unsigned int pkt_id, len;
1259 #ifdef GARMIN_ENABLE
1260 unsigned int ch, chksum;
1264 /* shortcut garmin */
1265 if (TSIP_PACKET == lexer->type)
1267 #endif /* TSIP_ENABLE */
1268 if (lexer->inbuffer[n++] != DLE)
1270 pkt_id = lexer->inbuffer[n++]; /* packet ID */
1271 len = lexer->inbuffer[n++];
1272 chksum = len + pkt_id;
1274 if (lexer->inbuffer[n++] != DLE)
1277 for (; len > 0; len--) {
1278 chksum += lexer->inbuffer[n];
1279 if (lexer->inbuffer[n++] == DLE) {
1280 if (lexer->inbuffer[n++] != DLE)
1284 /* check sum byte */
1285 ch = lexer->inbuffer[n++];
1288 if (lexer->inbuffer[n++] != DLE)
1291 if (lexer->inbuffer[n++] != DLE)
1293 if (lexer->inbuffer[n++] != ETX)
1299 "Garmin checksum failed: %02x!=0\n", chksum);
1303 * gpsd_report(LOG_IO, "Garmin n= %#02x\n %s\n", n,
1304 * gpsd_hexdump_wrapper(lexer->inbuffer, packetlen, LOG_IO));
1306 packet_accept(lexer, GARMIN_PACKET);
1307 packet_discard(lexer);
1310 gpsd_report(LOG_RAW + 1, "Not a Garmin packet\n");
1311 #endif /* GARMIN_ENABLE */
1313 /* check for some common TSIP packet types:
1314 * 0x13, TSIP Parsing Error Notification
1315 * 0x41, GPS time, data length 10
1316 * 0x42, Single Precision Fix, data length 16
1317 * 0x43, Velocity Fix, data length 20
1318 * 0x45, Software Version Information, data length 10
1319 * 0x46, Health of Receiver, data length 2
1320 * 0x48, GPS System Messages
1321 * 0x49, Almanac Health Page
1322 * 0x4a, LLA Position, data length 20
1323 * 0x4b, Machine Code Status, data length 3
1324 * 0x4c, Operating Parameters Report
1325 * 0x54, One Satellite Bias
1326 * 0x56, Velocity Fix (ENU), data length 20
1327 * 0x57, Last Computed Fix Report
1328 * 0x5a, Raw Measurements
1329 * 0x5b, Satellite Ephemeris Status
1330 * 0x5c, Satellite Tracking Status, data length 24
1331 * 0x5e, Additional Fix Status Report
1332 * 0x6d, All-In-View Satellite Selection, data length 16+numSV
1333 * 0x82, Differential Position Fix Mode, data length 1
1334 * 0x83, Double Precision XYZ, data length 36
1335 * 0x84, Double Precision LLA, data length 36
1336 * 0xbb, GPS Navigation Configuration
1337 * 0xbc, Receiver Port Configuration
1339 * <DLE>[pkt id] [data] <DLE><ETX>
1342 pkt_id = lexer->inbuffer[1]; /* packet ID */
1344 if (!((0x13 == pkt_id) || (0xbb == pkt_id) || (0xbc == pkt_id))
1345 && ((0x41 > pkt_id) || (0x8f < pkt_id))) {
1347 "Packet ID 0x%02x out of range for TSIP\n",
1353 if ((0x13 == pkt_id) && (0x01 <= packetlen))
1355 else if ((0x41 == pkt_id)
1356 && ((0x0e == packetlen) || (0x0f == packetlen)))
1358 else if ((0x42 == pkt_id) && (0x14 == packetlen))
1360 else if ((0x43 == pkt_id) && (0x18 == packetlen))
1362 else if ((0x45 == pkt_id) && (0x0e == packetlen))
1364 else if ((0x46 == pkt_id) && (0x06 == packetlen))
1366 else if ((0x48 == pkt_id) && (0x1a == packetlen))
1368 else if ((0x49 == pkt_id) && (0x24 == packetlen))
1370 else if ((0x4a == pkt_id) && (0x18 == packetlen))
1372 else if ((0x4b == pkt_id) && (0x07 == packetlen))
1374 else if ((0x4c == pkt_id) && (0x15 == packetlen))
1376 else if ((0x54 == pkt_id) && (0x10 == packetlen))
1378 else if ((0x55 == pkt_id) && (0x08 == packetlen))
1380 else if ((0x56 == pkt_id) && (0x18 == packetlen))
1382 else if ((0x57 == pkt_id) && (0x0c == packetlen))
1384 else if ((0x5a == pkt_id)
1385 && ((0x1d <= packetlen) && (0x1f >= packetlen)))
1387 else if ((0x5b == pkt_id) && (0x24 == packetlen))
1389 else if ((0x5c == pkt_id)
1390 && ((0x1c <= packetlen) && (0x1e >= packetlen)))
1392 else if ((0x5e == pkt_id) && (0x06 == packetlen))
1394 else if ((0x5f == pkt_id) && (70 == packetlen))
1396 else if ((0x6d == pkt_id)
1397 && ((0x14 <= packetlen) && (0x20 >= packetlen)))
1399 else if ((0x82 == pkt_id) && (0x05 == packetlen))
1401 else if ((0x84 == pkt_id)
1402 && ((0x28 <= packetlen) && (0x29 >= packetlen)))
1404 else if ((0x8e == pkt_id))
1406 else if ((0x8f == pkt_id))
1408 else if ((0xbb == pkt_id) && (0x2c == packetlen))
1412 "TSIP REJECT pkt_id = %#02x, packetlen= %zu\n",
1417 gpsd_report(LOG_RAW,
1418 "TSIP pkt_id = %#02x, packetlen= %zu\n",
1420 /*@ -charint +ifempty @*/
1421 packet_accept(lexer, TSIP_PACKET);
1422 packet_discard(lexer);
1425 gpsd_report(LOG_RAW + 1, "Not a TSIP packet\n");
1427 * More attempts to recognize ambiguous TSIP-like
1428 * packet types could go here.
1430 packet_accept(lexer, BAD_PACKET);
1431 lexer->state = GROUND_STATE;
1432 packet_discard(lexer);
1434 #endif /* TSIP_ENABLE */
1437 #endif /* TSIP_ENABLE || GARMIN_ENABLE */
1438 #ifdef RTCM104V3_ENABLE
1439 else if (lexer->state == RTCM3_RECOGNIZED) {
1440 if (crc24q_check(lexer->inbuffer,
1441 lexer->inbufptr - lexer->inbuffer)) {
1442 packet_accept(lexer, RTCM3_PACKET);
1443 packet_discard(lexer);
1445 gpsd_report(LOG_IO, "RTCM3 data checksum failure, "
1446 "%0x against %02x %02x %02x\n",
1447 crc24q_hash(lexer->inbuffer,
1448 lexer->inbufptr - lexer->inbuffer -
1449 3), lexer->inbufptr[-3],
1450 lexer->inbufptr[-2], lexer->inbufptr[-1]);
1451 packet_accept(lexer, BAD_PACKET);
1452 lexer->state = GROUND_STATE;
1453 packet_discard(lexer);
1457 #endif /* RTCM104V3_ENABLE */
1458 #ifdef ZODIAC_ENABLE
1459 else if (lexer->state == ZODIAC_RECOGNIZED) {
1462 for (n = sum = 0; n < len; n++)
1463 sum += getword(5 + n);
1465 if (len == 0 || sum == getword(5 + len)) {
1466 packet_accept(lexer, ZODIAC_PACKET);
1469 "Zodiac data checksum 0x%hx over length %hd, expecting 0x%hx\n",
1470 sum, len, getword(5 + len));
1471 packet_accept(lexer, BAD_PACKET);
1472 lexer->state = GROUND_STATE;
1474 packet_discard(lexer);
1477 #endif /* ZODIAC_ENABLE */
1479 else if (lexer->state == UBX_RECOGNIZED) {
1480 /* UBX use a TCP like checksum */
1482 unsigned char ck_a = (unsigned char)0;
1483 unsigned char ck_b = (unsigned char)0;
1484 len = lexer->inbufptr - lexer->inbuffer;
1485 gpsd_report(LOG_IO, "UBX: len %d\n", len);
1486 for (n = 2; n < (len - 2); n++) {
1487 ck_a += lexer->inbuffer[n];
1490 if (ck_a == lexer->inbuffer[len - 2] &&
1491 ck_b == lexer->inbuffer[len - 1])
1492 packet_accept(lexer, UBX_PACKET);
1495 "UBX checksum 0x%02hhx%02hhx over length %hd,"
1496 " expecting 0x%02hhx%02hhx (type 0x%02hhx%02hhx)\n",
1500 lexer->inbuffer[len - 2],
1501 lexer->inbuffer[len - 1],
1502 lexer->inbuffer[2], lexer->inbuffer[3]);
1503 packet_accept(lexer, BAD_PACKET);
1504 lexer->state = GROUND_STATE;
1506 packet_discard(lexer);
1509 #endif /* UBX_ENABLE */
1510 #ifdef EVERMORE_ENABLE
1511 else if (lexer->state == EVERMORE_RECOGNIZED) {
1512 unsigned int n, crc, checksum, len;
1515 if (lexer->inbuffer[n++] != DLE)
1517 if (lexer->inbuffer[n++] != STX)
1519 len = lexer->inbuffer[n++];
1521 if (lexer->inbuffer[n++] != DLE)
1526 for (; len > 0; len--) {
1527 crc += lexer->inbuffer[n];
1528 if (lexer->inbuffer[n++] == DLE) {
1529 if (lexer->inbuffer[n++] != DLE)
1533 checksum = lexer->inbuffer[n++];
1534 if (checksum == DLE) {
1535 if (lexer->inbuffer[n++] != DLE)
1538 if (lexer->inbuffer[n++] != DLE)
1540 if (lexer->inbuffer[n++] != ETX)
1543 if (crc != checksum) {
1545 "EverMore checksum failed: %02x != %02x\n",
1550 packet_accept(lexer, EVERMORE_PACKET);
1551 packet_discard(lexer);
1554 packet_accept(lexer, BAD_PACKET);
1555 lexer->state = GROUND_STATE;
1556 packet_discard(lexer);
1559 #endif /* EVERMORE_ENABLE */
1562 #define getib(j) ((uint8_t)lexer->inbuffer[(j)])
1563 #define getiw(i) ((uint16_t)(((uint16_t)getib((i)+1) << 8) | (uint16_t)getib((i))))
1565 else if (lexer->state == ITALK_RECOGNIZED) {
1566 volatile uint16_t len, n, csum, xsum, tmpw;
1567 volatile uint32_t tmpdw;
1569 /* number of words */
1570 len = (uint16_t) (lexer->inbuffer[6] & 0xff);
1573 /* initialize all my registers */
1574 csum = tmpw = tmpdw = 0;
1575 /* expected checksum */
1576 xsum = getiw(7 + 2 * len);
1578 for (n = 0; n < len; n++) {
1579 tmpw = getiw(7 + 2 * n);
1580 tmpdw = (csum + 1) * (tmpw + n);
1581 csum ^= (tmpdw & 0xffff) ^ ((tmpdw >> 16) & 0xffff);
1584 if (len == 0 || csum == xsum)
1585 packet_accept(lexer, ITALK_PACKET);
1588 "ITALK: checksum failed - "
1589 "type 0x%02x expected 0x%04x got 0x%04x\n",
1590 lexer->inbuffer[4], xsum, csum);
1591 packet_accept(lexer, BAD_PACKET);
1592 lexer->state = GROUND_STATE;
1594 packet_discard(lexer);
1599 #endif /* ITRAX_ENABLE */
1600 #ifdef NAVCOM_ENABLE
1601 else if (lexer->state == NAVCOM_RECOGNIZED) {
1602 /* By the time we got here we know checksum is OK */
1603 packet_accept(lexer, NAVCOM_PACKET);
1604 packet_discard(lexer);
1607 #endif /* NAVCOM_ENABLE */
1608 #ifdef RTCM104V2_ENABLE
1609 else if (lexer->state == RTCM2_RECOGNIZED) {
1611 * RTCM packets don't have checksums. The six bits of parity
1612 * per word and the preamble better be good enough.
1614 packet_accept(lexer, RTCM2_PACKET);
1615 lexer->state = RTCM2_SYNC_STATE;
1616 packet_discard(lexer);
1619 #endif /* RTCM104V2_ENABLE */
1620 #ifdef GARMINTXT_ENABLE
1621 else if (lexer->state == GTXT_RECOGNIZED) {
1622 size_t packetlen = lexer->inbufptr - lexer->inbuffer;
1623 if (57 <= packetlen) {
1624 packet_accept(lexer, GARMINTXT_PACKET);
1625 packet_discard(lexer);
1626 lexer->state = GROUND_STATE;
1629 packet_accept(lexer, BAD_PACKET);
1630 lexer->state = GROUND_STATE;
1639 ssize_t packet_get(int fd, struct gps_packet_t *lexer)
1640 /* grab a packet; return -1=>I/O error, 0=>EOF, BAD_PACKET or a length */
1644 /*@ -modobserver @*/
1646 recvd = read(fd, lexer->inbuffer + lexer->inbuflen,
1647 sizeof(lexer->inbuffer) - (lexer->inbuflen));
1648 /*@ +modobserver @*/
1650 if ((errno == EAGAIN) || (errno == EINTR)) {
1652 gpsd_report(LOG_RAW + 2, "no bytes ready\n");
1654 /* fall through, input buffer may be nonempty */
1655 #endif /* STATE_DEBUG */
1658 gpsd_report(LOG_RAW + 2, "errno: %s\n", strerror(errno));
1659 #endif /* STATE_DEBUG */
1664 gpsd_report(LOG_RAW + 1,
1665 "Read %zd chars to buffer offset %zd (total %zd): %s\n",
1666 recvd, lexer->inbuflen, lexer->inbuflen + recvd,
1667 gpsd_hexdump_wrapper(lexer->inbufptr, (size_t) recvd,
1669 #endif /* STATE_DEBUG */
1670 lexer->inbuflen += recvd;
1672 gpsd_report(LOG_SPIN, "packet_get() fd %d -> %zd (%d)\n",
1676 * Bail out, indicating no more input, only if we just received
1677 * nothing from the device and there is nothing waiting in the
1678 * packet input buffer.
1680 if (recvd <= 0 && packet_buffered_input(lexer) <= 0)
1683 /* Otherwise, consume from the packet input buffer */
1684 packet_parse(lexer);
1686 /* if input buffer is full, discard */
1687 if (sizeof(lexer->inbuffer) == (lexer->inbuflen)) {
1688 packet_discard(lexer);
1689 lexer->state = GROUND_STATE;
1693 * If we gathered a packet, return its length; it will have been
1694 * consumed out of the input buffer and moved to the output
1695 * buffer. We don't care whether the read() returned 0 or -1 and
1696 * gathered packet data was all buffered or whether ot was partly
1697 * just physically read.
1699 * Note: this choice greatly simplifies life for callers of
1700 * packet_get(), but means that they cannot tell when a nonzero
1701 * return means there was a successful physical read. They will
1702 * thus credit a data source that drops out with being alive
1703 * slightly longer than it actually was. This is unlikely to
1704 * matter as long as any policy timeouts are large compared to
1705 * the time required to consume the greatest possible amount
1706 * of buffered input, but if you hack this code you need to
1707 * be aware of the issue. It might also slightly affect
1708 * performance profiling.
1710 if (lexer->outbuflen > 0)
1711 return (ssize_t) lexer->outbuflen;
1714 * Otherwise recvd is the size of whatever packet fragment we got.
1715 * It can still be 0 or -1 at this point even if buffer data
1721 void packet_reset( /*@out@*/ struct gps_packet_t *lexer)
1722 /* return the packet machine to the ground state */
1724 lexer->type = BAD_PACKET;
1725 lexer->state = GROUND_STATE;
1726 lexer->inbuflen = 0;
1727 lexer->inbufptr = lexer->inbuffer;
1728 #ifdef BINARY_ENABLE
1730 #endif /* BINARY_ENABLE */
1735 void packet_pushback(struct gps_packet_t *lexer)
1736 /* push back the last packet grabbed */
1738 if (lexer->outbuflen + lexer->inbuflen < MAX_PACKET_LENGTH) {
1739 memmove(lexer->inbuffer + lexer->outbuflen,
1740 lexer->inbuffer, lexer->inbuflen);
1741 memmove(lexer->inbuffer, lexer->outbuffer, lexer->outbuflen);
1742 lexer->inbuflen += lexer->outbuflen;
1743 lexer->inbufptr += lexer->outbuflen;
1744 lexer->outbuflen = 0;
1747 #endif /* __UNUSED */
1749 #ifdef ONCORE_ENABLE
1750 size_t oncore_payload_cksum_length(unsigned char id1, unsigned char id2)
1754 /* For the packet sniffer to not terminate the message due to
1755 * payload data looking like a trailer, the known payload lengths
1756 * including the checksum are given. Return -1 for unknown IDs.
1759 #define ONCTYPE(id2,id3) ((((unsigned int)id2)<<8)|(id3))
1762 switch (ONCTYPE(id1,id2)) {
1763 case ONCTYPE('A','b'): l = 10; break; /* GMT offset */
1764 case ONCTYPE('A','w'): l = 8; break; /* time mode */
1765 case ONCTYPE('A','c'): l = 11; break; /* date */
1766 case ONCTYPE('A','a'): l = 10; break; /* time of day */
1767 case ONCTYPE('A','d'): l = 11; break; /* latitude */
1768 case ONCTYPE('A','e'): l = 11; break; /* longitude */
1769 case ONCTYPE('A','f'): l = 15; break; /* height */
1770 case ONCTYPE('E','a'): l = 76; break; /* position/status/data */
1771 case ONCTYPE('A','g'): l = 8; break; /* satellite mask angle */
1772 case ONCTYPE('B','b'): l = 92; break; /* visible satellites status */
1773 case ONCTYPE('B','j'): l = 8; break; /* leap seconds pending */
1774 case ONCTYPE('A','q'): l = 8; break; /* atmospheric correction mode */
1775 case ONCTYPE('A','p'): l = 25; break; /* set user datum / select datum */
1776 /* Command "Ao" gives "Ap" response (select datum) */
1777 case ONCTYPE('C','h'): l = 9; break; /* almanac input ("Cb" response) */
1778 case ONCTYPE('C','b'): l = 33; break; /* almanac output ("Be" response) */
1779 case ONCTYPE('S','z'): l = 8; break; /* system power-on failure */
1780 case ONCTYPE('C','j'): l = 294; break; /* receiver ID */
1781 case ONCTYPE('F','a'): l = 9; break; /* self-test */
1782 case ONCTYPE('C','f'): l = 7; break; /* set-to-defaults */
1783 case ONCTYPE('E','q'): l = 96; break; /* ASCII position */
1784 case ONCTYPE('A','u'): l = 12; break; /* altitide hold height */
1785 case ONCTYPE('A','v'): l = 8; break; /* altitude hold mode */
1786 case ONCTYPE('A','N'): l = 8; break; /* velocity filter */
1787 case ONCTYPE('A','O'): l = 8; break; /* RTCM report mode */
1788 case ONCTYPE('C','c'): l = 80; break; /* ephemeris data input ("Bf") */
1789 case ONCTYPE('C','k'): l = 7; break; /* pseudorng correction inp. ("Ce")*/
1790 /* Command "Ci" (switch to NMEA, GT versions only) has no response */
1791 case ONCTYPE('B','o'): l = 8; break; /* UTC offset status */
1792 case ONCTYPE('A','z'): l = 11; break; /* 1PPS cable delay */
1793 case ONCTYPE('A','y'): l = 11; break; /* 1PPS offset */
1794 case ONCTYPE('A','P'): l = 8; break; /* pulse mode */
1795 case ONCTYPE('A','s'): l = 20; break; /* position-hold position */
1796 case ONCTYPE('A','t'): l = 8; break; /* position-hold mode */
1797 case ONCTYPE('E','n'): l = 69; break; /* time RAIM setup and status */
1803 return l - 6; /* Subtract header and trailer. */
1805 #endif /* ONCORE_ENABLE */